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