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