1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.io.*; 29 import java.net.*; 30 import java.nio.channels.*; 31 import java.util.*; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import java.security.PrivilegedExceptionAction; 35 36 37 public class Net { 38 39 private Net() { } 40 41 // unspecified protocol family 42 static final ProtocolFamily UNSPEC = new ProtocolFamily() { 43 public String name() { 44 return "UNSPEC"; 45 } 46 }; 47 48 // set to true if exclusive binding is on for Windows 49 private static final boolean exclusiveBind; 50 51 static { 52 int availLevel = isExclusiveBindAvailable(); 53 if (availLevel >= 0) { 54 String exclBindProp = 55 java.security.AccessController.doPrivileged( 56 new PrivilegedAction<String>() { 57 @Override 58 public String run() { 59 return System.getProperty( 60 "sun.net.useExclusiveBind"); 61 } 62 }); 63 if (exclBindProp != null) { 64 exclusiveBind = exclBindProp.length() == 0 ? 65 true : Boolean.parseBoolean(exclBindProp); 66 } else if (availLevel == 1) { 67 exclusiveBind = true; 68 } else { 69 exclusiveBind = false; 70 } 71 } else { 72 exclusiveBind = false; 73 } 74 } 75 76 // -- Miscellaneous utilities -- 77 78 private static volatile boolean checkedIPv6 = false; 79 private static volatile boolean isIPv6Available; 80 81 /** 82 * Tells whether dual-IPv4/IPv6 sockets should be used. 83 */ 84 static boolean isIPv6Available() { 85 if (!checkedIPv6) { 86 isIPv6Available = isIPv6Available0(); 87 checkedIPv6 = true; 88 } 89 return isIPv6Available; 90 } 91 92 /** 93 * Returns true if exclusive binding is on 94 */ 95 static boolean useExclusiveBind() { 96 return exclusiveBind; 97 } 98 99 /** 100 * Tells whether IPv6 sockets can join IPv4 multicast groups 101 */ 102 static boolean canIPv6SocketJoinIPv4Group() { 103 return canIPv6SocketJoinIPv4Group0(); 104 } 105 106 /** 107 * Tells whether {@link #join6} can be used to join an IPv4 108 * multicast group (IPv4 group as IPv4-mapped IPv6 address) 109 */ 110 static boolean canJoin6WithIPv4Group() { 111 return canJoin6WithIPv4Group0(); 112 } 113 114 public static InetSocketAddress checkAddress(SocketAddress sa) { 115 if (sa == null) 116 throw new NullPointerException(); 117 if (!(sa instanceof InetSocketAddress)) 118 throw new UnsupportedAddressTypeException(); // ## needs arg 119 InetSocketAddress isa = (InetSocketAddress)sa; 120 if (isa.isUnresolved()) 121 throw new UnresolvedAddressException(); // ## needs arg 122 InetAddress addr = isa.getAddress(); 123 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) 124 throw new IllegalArgumentException("Invalid address type"); 125 return isa; 126 } 127 128 static InetSocketAddress asInetSocketAddress(SocketAddress sa) { 129 if (!(sa instanceof InetSocketAddress)) 130 throw new UnsupportedAddressTypeException(); 131 return (InetSocketAddress)sa; 132 } 133 134 static void translateToSocketException(Exception x) 135 throws SocketException 136 { 137 if (x instanceof SocketException) 138 throw (SocketException)x; 139 Exception nx = x; 140 if (x instanceof ClosedChannelException) 141 nx = new SocketException("Socket is closed"); 142 else if (x instanceof NotYetConnectedException) 143 nx = new SocketException("Socket is not connected"); 144 else if (x instanceof AlreadyBoundException) 145 nx = new SocketException("Already bound"); 146 else if (x instanceof NotYetBoundException) 147 nx = new SocketException("Socket is not bound yet"); 148 else if (x instanceof UnsupportedAddressTypeException) 149 nx = new SocketException("Unsupported address type"); 150 else if (x instanceof UnresolvedAddressException) { 151 nx = new SocketException("Unresolved address"); 152 } 153 if (nx != x) 154 nx.initCause(x); 155 156 if (nx instanceof SocketException) 157 throw (SocketException)nx; 158 else if (nx instanceof RuntimeException) 159 throw (RuntimeException)nx; 160 else 161 throw new Error("Untranslated exception", nx); 162 } 163 164 static void translateException(Exception x, 165 boolean unknownHostForUnresolved) 166 throws IOException 167 { 168 if (x instanceof IOException) 169 throw (IOException)x; 170 // Throw UnknownHostException from here since it cannot 171 // be thrown as a SocketException 172 if (unknownHostForUnresolved && 173 (x instanceof UnresolvedAddressException)) 174 { 175 throw new UnknownHostException(); 176 } 177 translateToSocketException(x); 178 } 179 180 static void translateException(Exception x) 181 throws IOException 182 { 183 translateException(x, false); 184 } 185 186 /** 187 * Returns the local address after performing a SecurityManager#checkConnect. 188 */ 189 static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) { 190 SecurityManager sm = System.getSecurityManager(); 191 if (addr == null || sm == null) 192 return addr; 193 194 try{ 195 sm.checkConnect(addr.getAddress().getHostAddress(), -1); 196 // Security check passed 197 } catch (SecurityException e) { 198 // Return loopback address only if security check fails 199 addr = getLoopbackAddress(addr.getPort()); 200 } 201 return addr; 202 } 203 204 static String getRevealedLocalAddressAsString(InetSocketAddress addr) { 205 return System.getSecurityManager() == null ? addr.toString() : 206 getLoopbackAddress(addr.getPort()).toString(); 207 } 208 209 private static InetSocketAddress getLoopbackAddress(int port) { 210 return new InetSocketAddress(InetAddress.getLoopbackAddress(), 211 port); 212 } 213 214 /** 215 * Returns any IPv4 address of the given network interface, or 216 * null if the interface does not have any IPv4 addresses. 217 */ 218 static Inet4Address anyInet4Address(final NetworkInterface interf) { 219 return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() { 220 public Inet4Address run() { 221 Enumeration<InetAddress> addrs = interf.getInetAddresses(); 222 while (addrs.hasMoreElements()) { 223 InetAddress addr = addrs.nextElement(); 224 if (addr instanceof Inet4Address) { 225 return (Inet4Address)addr; 226 } 227 } 228 return null; 229 } 230 }); 231 } 232 233 /** 234 * Returns an IPv4 address as an int. 235 */ 236 static int inet4AsInt(InetAddress ia) { 237 if (ia instanceof Inet4Address) { 238 byte[] addr = ia.getAddress(); 239 int address = addr[3] & 0xFF; 240 address |= ((addr[2] << 8) & 0xFF00); 241 address |= ((addr[1] << 16) & 0xFF0000); 242 address |= ((addr[0] << 24) & 0xFF000000); 243 return address; 244 } 245 throw new AssertionError("Should not reach here"); 246 } 247 248 /** 249 * Returns an InetAddress from the given IPv4 address 250 * represented as an int. 251 */ 252 static InetAddress inet4FromInt(int address) { 253 byte[] addr = new byte[4]; 254 addr[0] = (byte) ((address >>> 24) & 0xFF); 255 addr[1] = (byte) ((address >>> 16) & 0xFF); 256 addr[2] = (byte) ((address >>> 8) & 0xFF); 257 addr[3] = (byte) (address & 0xFF); 258 try { 259 return InetAddress.getByAddress(addr); 260 } catch (UnknownHostException uhe) { 261 throw new AssertionError("Should not reach here"); 262 } 263 } 264 265 /** 266 * Returns an IPv6 address as a byte array 267 */ 268 static byte[] inet6AsByteArray(InetAddress ia) { 269 if (ia instanceof Inet6Address) { 270 return ia.getAddress(); 271 } 272 273 // need to construct IPv4-mapped address 274 if (ia instanceof Inet4Address) { 275 byte[] ip4address = ia.getAddress(); 276 byte[] address = new byte[16]; 277 address[10] = (byte)0xff; 278 address[11] = (byte)0xff; 279 address[12] = ip4address[0]; 280 address[13] = ip4address[1]; 281 address[14] = ip4address[2]; 282 address[15] = ip4address[3]; 283 return address; 284 } 285 286 throw new AssertionError("Should not reach here"); 287 } 288 289 // -- Socket options 290 291 static void setSocketOption(FileDescriptor fd, ProtocolFamily family, 292 SocketOption<?> name, Object value) 293 throws IOException 294 { 295 if (value == null) 296 throw new IllegalArgumentException("Invalid option value"); 297 298 // only simple values supported by this method 299 Class<?> type = name.type(); 300 if (type != Integer.class && type != Boolean.class) 301 throw new AssertionError("Should not reach here"); 302 303 // special handling 304 if (name == StandardSocketOptions.SO_RCVBUF || 305 name == StandardSocketOptions.SO_SNDBUF) 306 { 307 int i = ((Integer)value).intValue(); 308 if (i < 0) 309 throw new IllegalArgumentException("Invalid send/receive buffer size"); 310 } 311 if (name == StandardSocketOptions.SO_LINGER) { 312 int i = ((Integer)value).intValue(); 313 if (i < 0) 314 value = Integer.valueOf(-1); 315 if (i > 65535) 316 value = Integer.valueOf(65535); 317 } 318 if (name == StandardSocketOptions.IP_TOS) { 319 int i = ((Integer)value).intValue(); 320 if (i < 0 || i > 255) 321 throw new IllegalArgumentException("Invalid IP_TOS value"); 322 } 323 if (name == StandardSocketOptions.IP_MULTICAST_TTL) { 324 int i = ((Integer)value).intValue(); 325 if (i < 0 || i > 255) 326 throw new IllegalArgumentException("Invalid TTL/hop value"); 327 } 328 329 // map option name to platform level/name 330 OptionKey key = SocketOptionRegistry.findOption(name, family); 331 if (key == null) 332 throw new AssertionError("Option not found"); 333 334 int arg; 335 if (type == Integer.class) { 336 arg = ((Integer)value).intValue(); 337 } else { 338 boolean b = ((Boolean)value).booleanValue(); 339 arg = (b) ? 1 : 0; 340 } 341 342 boolean mayNeedConversion = (family == UNSPEC); 343 setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg); 344 } 345 346 static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, 347 SocketOption<?> name) 348 throws IOException 349 { 350 Class<?> type = name.type(); 351 352 // only simple values supported by this method 353 if (type != Integer.class && type != Boolean.class) 354 throw new AssertionError("Should not reach here"); 355 356 // map option name to platform level/name 357 OptionKey key = SocketOptionRegistry.findOption(name, family); 358 if (key == null) 359 throw new AssertionError("Option not found"); 360 361 boolean mayNeedConversion = (family == UNSPEC); 362 int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); 363 364 if (type == Integer.class) { 365 return Integer.valueOf(value); 366 } else { 367 return (value == 0) ? Boolean.FALSE : Boolean.TRUE; 368 } 369 } 370 371 // -- Socket operations -- 372 373 private static native boolean isIPv6Available0(); 374 375 /* 376 * Returns 1 for Windows versions that support exclusive binding by default, 0 377 * for those that do not, and -1 for Solaris/Linux/Mac OS 378 */ 379 private static native int isExclusiveBindAvailable(); 380 381 private static native boolean canIPv6SocketJoinIPv4Group0(); 382 383 private static native boolean canJoin6WithIPv4Group0(); 384 385 static FileDescriptor socket(boolean stream) throws IOException { 386 return socket(UNSPEC, stream); 387 } 388 389 static FileDescriptor socket(ProtocolFamily family, boolean stream) 390 throws IOException { 391 boolean preferIPv6 = isIPv6Available() && 392 (family != StandardProtocolFamily.INET); 393 return IOUtil.newFD(socket0(preferIPv6, stream, false)); 394 } 395 396 static FileDescriptor serverSocket(boolean stream) { 397 return IOUtil.newFD(socket0(isIPv6Available(), stream, true)); 398 } 399 400 // Due to oddities SO_REUSEADDR on windows reuse is ignored 401 private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse); 402 403 public static void bind(FileDescriptor fd, InetAddress addr, int port) 404 throws IOException 405 { 406 bind(UNSPEC, fd, addr, port); 407 } 408 409 static void bind(ProtocolFamily family, FileDescriptor fd, 410 InetAddress addr, int port) throws IOException 411 { 412 boolean preferIPv6 = isIPv6Available() && 413 (family != StandardProtocolFamily.INET); 414 bind0(fd, preferIPv6, exclusiveBind, addr, port); 415 } 416 417 private static native void bind0(FileDescriptor fd, boolean preferIPv6, 418 boolean useExclBind, InetAddress addr, 419 int port) 420 throws IOException; 421 422 static native void listen(FileDescriptor fd, int backlog) throws IOException; 423 424 static int connect(FileDescriptor fd, InetAddress remote, int remotePort) 425 throws IOException 426 { 427 return connect(UNSPEC, fd, remote, remotePort); 428 } 429 430 static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) 431 throws IOException 432 { 433 boolean preferIPv6 = isIPv6Available() && 434 (family != StandardProtocolFamily.INET); 435 return connect0(preferIPv6, fd, remote, remotePort); 436 } 437 438 private static native int connect0(boolean preferIPv6, 439 FileDescriptor fd, 440 InetAddress remote, 441 int remotePort) 442 throws IOException; 443 444 445 public final static int SHUT_RD = 0; 446 public final static int SHUT_WR = 1; 447 public final static int SHUT_RDWR = 2; 448 449 static native void shutdown(FileDescriptor fd, int how) throws IOException; 450 451 private static native int localPort(FileDescriptor fd) 452 throws IOException; 453 454 private static native InetAddress localInetAddress(FileDescriptor fd) 455 throws IOException; 456 457 public static InetSocketAddress localAddress(FileDescriptor fd) 458 throws IOException 459 { 460 return new InetSocketAddress(localInetAddress(fd), localPort(fd)); 461 } 462 463 private static native int remotePort(FileDescriptor fd) 464 throws IOException; 465 466 private static native InetAddress remoteInetAddress(FileDescriptor fd) 467 throws IOException; 468 469 static InetSocketAddress remoteAddress(FileDescriptor fd) 470 throws IOException 471 { 472 return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd)); 473 } 474 475 private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, 476 int level, int opt) 477 throws IOException; 478 479 private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, 480 int level, int opt, int arg) 481 throws IOException; 482 483 static native int poll(FileDescriptor fd, int events, long timeout) 484 throws IOException; 485 486 // -- Multicast support -- 487 488 489 /** 490 * Join IPv4 multicast group 491 */ 492 static int join4(FileDescriptor fd, int group, int interf, int source) 493 throws IOException 494 { 495 return joinOrDrop4(true, fd, group, interf, source); 496 } 497 498 /** 499 * Drop membership of IPv4 multicast group 500 */ 501 static void drop4(FileDescriptor fd, int group, int interf, int source) 502 throws IOException 503 { 504 joinOrDrop4(false, fd, group, interf, source); 505 } 506 507 private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source) 508 throws IOException; 509 510 /** 511 * Block IPv4 source 512 */ 513 static int block4(FileDescriptor fd, int group, int interf, int source) 514 throws IOException 515 { 516 return blockOrUnblock4(true, fd, group, interf, source); 517 } 518 519 /** 520 * Unblock IPv6 source 521 */ 522 static void unblock4(FileDescriptor fd, int group, int interf, int source) 523 throws IOException 524 { 525 blockOrUnblock4(false, fd, group, interf, source); 526 } 527 528 private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group, 529 int interf, int source) 530 throws IOException; 531 532 /** 533 * Join IPv6 multicast group 534 */ 535 static int join6(FileDescriptor fd, byte[] group, int index, byte[] source) 536 throws IOException 537 { 538 return joinOrDrop6(true, fd, group, index, source); 539 } 540 541 /** 542 * Drop membership of IPv6 multicast group 543 */ 544 static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source) 545 throws IOException 546 { 547 joinOrDrop6(false, fd, group, index, source); 548 } 549 550 private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source) 551 throws IOException; 552 553 /** 554 * Block IPv6 source 555 */ 556 static int block6(FileDescriptor fd, byte[] group, int index, byte[] source) 557 throws IOException 558 { 559 return blockOrUnblock6(true, fd, group, index, source); 560 } 561 562 /** 563 * Unblock IPv6 source 564 */ 565 static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source) 566 throws IOException 567 { 568 blockOrUnblock6(false, fd, group, index, source); 569 } 570 571 static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source) 572 throws IOException; 573 574 static native void setInterface4(FileDescriptor fd, int interf) throws IOException; 575 576 static native int getInterface4(FileDescriptor fd) throws IOException; 577 578 static native void setInterface6(FileDescriptor fd, int index) throws IOException; 579 580 static native int getInterface6(FileDescriptor fd) throws IOException; 581 582 private static native void initIDs(); 583 584 /** 585 * Event masks for the various poll system calls. 586 * They will be set platform dependant in the static initializer below. 587 */ 588 public static final short POLLIN; 589 public static final short POLLOUT; 590 public static final short POLLERR; 591 public static final short POLLHUP; 592 public static final short POLLNVAL; 593 public static final short POLLCONN; 594 595 static native short pollinValue(); 596 static native short polloutValue(); 597 static native short pollerrValue(); 598 static native short pollhupValue(); 599 static native short pollnvalValue(); 600 static native short pollconnValue(); 601 602 static { 603 IOUtil.load(); 604 initIDs(); 605 606 POLLIN = pollinValue(); 607 POLLOUT = polloutValue(); 608 POLLERR = pollerrValue(); 609 POLLHUP = pollhupValue(); 610 POLLNVAL = pollnvalValue(); 611 POLLCONN = pollconnValue(); 612 } 613 614 }