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