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