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