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