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 }