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