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