Home | History | Annotate | Download | only in ch
      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 
     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      */
     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      */
     77     static boolean useExclusiveBind() {
     78         return exclusiveBind;
     79     }
     80 
     81     /**
     82      * Tells whether IPv6 sockets can join IPv4 multicast groups
     83      */
     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      */
     92     static boolean canJoin6WithIPv4Group() {
     93         return canJoin6WithIPv4Group0();
     94     }
     95 
     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 
    114     static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
    115         if (!(sa instanceof InetSocketAddress))
    116             throw new UnsupportedAddressTypeException();
    117         return (InetSocketAddress)sa;
    118     }
    119 
    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 
    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 
    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      */
    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 
    193     static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
    194         return System.getSecurityManager() == null ? addr.toString() :
    195                 getLoopbackAddress(addr.getPort()).toString();
    196     }
    197 
    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      */
    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