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