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