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