1 /*
   2  * Copyright (c) 2000, 2019, 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.FileDescriptor;
  29 import java.io.IOException;
  30 import java.net.Inet4Address;
  31 import java.net.Inet6Address;
  32 import java.net.InetAddress;
  33 import java.net.InetSocketAddress;
  34 import java.net.NetworkInterface;
  35 import java.net.ProtocolFamily;
  36 import java.net.SocketAddress;
  37 import java.net.SocketException;
  38 import java.net.SocketOption;
  39 import java.net.StandardProtocolFamily;
  40 import java.net.StandardSocketOptions;
  41 import java.net.UnixSocketAddress;
  42 import java.net.UnknownHostException;
  43 import java.nio.channels.AlreadyBoundException;
  44 import java.nio.channels.ClosedChannelException;
  45 import java.nio.channels.NotYetBoundException;
  46 import java.nio.channels.NotYetConnectedException;
  47 import java.nio.channels.UnresolvedAddressException;
  48 import java.nio.channels.UnsupportedAddressTypeException;
  49 import java.security.AccessController;
  50 import java.security.PrivilegedAction;
  51 import java.util.Enumeration;
  52 
  53 import sun.net.ext.ExtendedSocketOptions;
  54 import sun.net.util.IPAddressUtil;
  55 import sun.security.action.GetPropertyAction;
  56 
  57 public class Net {
  58 
  59     private Net() { }
  60 
  61     // unspecified protocol family
  62     static final ProtocolFamily UNSPEC = new ProtocolFamily() {
  63         public String name() {
  64             return "UNSPEC";
  65         }
  66     };
  67 
  68     // set to true if exclusive binding is on for Windows
  69     private static final boolean exclusiveBind;
  70 
  71     // set to true if the fast tcp loopback should be enabled on Windows
  72     private static final boolean fastLoopback;
  73 
  74     // -- Miscellaneous utilities --
  75 
  76     private static volatile boolean checkedIPv6;
  77     private static volatile boolean isIPv6Available;
  78     private static volatile boolean checkedReusePort;
  79     private static volatile boolean isReusePortAvailable;
  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      * Tells whether SO_REUSEPORT is supported.
  94      */
  95     static boolean isReusePortAvailable() {
  96         if (!checkedReusePort) {
  97             isReusePortAvailable = isReusePortAvailable0();
  98             checkedReusePort = true;
  99         }
 100         return isReusePortAvailable;
 101     }
 102 
 103     /**
 104      * Returns true if exclusive binding is on
 105      */
 106     static boolean useExclusiveBind() {
 107         return exclusiveBind;
 108     }
 109 
 110     /**
 111      * Tells whether IPv6 sockets can join IPv4 multicast groups
 112      */
 113     static boolean canIPv6SocketJoinIPv4Group() {
 114         return canIPv6SocketJoinIPv4Group0();
 115     }
 116 
 117     /**
 118      * Tells whether {@link #join6} can be used to join an IPv4
 119      * multicast group (IPv4 group as IPv4-mapped IPv6 address)
 120      */
 121     static boolean canJoin6WithIPv4Group() {
 122         return canJoin6WithIPv4Group0();
 123     }
 124 
 125     public static InetSocketAddress checkAddress(SocketAddress sa) {
 126         if (sa == null)
 127             throw new NullPointerException();
 128         if (!(sa instanceof InetSocketAddress))
 129             throw new UnsupportedAddressTypeException(); // ## needs arg
 130         InetSocketAddress isa = (InetSocketAddress)sa;
 131         if (isa.isUnresolved())
 132             throw new UnresolvedAddressException(); // ## needs arg
 133         InetAddress addr = isa.getAddress();
 134         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
 135             throw new IllegalArgumentException("Invalid address type");
 136         return isa;
 137     }
 138 
 139     static InetSocketAddress checkAddress(SocketAddress sa, ProtocolFamily family) {
 140         InetSocketAddress isa = checkAddress(sa);
 141         if (family == StandardProtocolFamily.INET) {
 142             InetAddress addr = isa.getAddress();
 143             if (!(addr instanceof Inet4Address))
 144                 throw new UnsupportedAddressTypeException();
 145         }
 146         return isa;
 147     }
 148 
 149     static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
 150         if (!(sa instanceof InetSocketAddress))
 151             throw new UnsupportedAddressTypeException();
 152         return (InetSocketAddress)sa;
 153     }
 154 
 155     static void translateToSocketException(Exception x)
 156         throws SocketException
 157     {
 158         if (x instanceof SocketException)
 159             throw (SocketException)x;
 160         Exception nx = x;
 161         if (x instanceof ClosedChannelException)
 162             nx = new SocketException("Socket is closed");
 163         else if (x instanceof NotYetConnectedException)
 164             nx = new SocketException("Socket is not connected");
 165         else if (x instanceof AlreadyBoundException)
 166             nx = new SocketException("Already bound");
 167         else if (x instanceof NotYetBoundException)
 168             nx = new SocketException("Socket is not bound yet");
 169         else if (x instanceof UnsupportedAddressTypeException)
 170             nx = new SocketException("Unsupported address type");
 171         else if (x instanceof UnresolvedAddressException) {
 172             nx = new SocketException("Unresolved address");
 173         }
 174         if (nx != x)
 175             nx.initCause(x);
 176 
 177         if (nx instanceof SocketException)
 178             throw (SocketException)nx;
 179         else if (nx instanceof RuntimeException)
 180             throw (RuntimeException)nx;
 181         else
 182             throw new Error("Untranslated exception", nx);
 183     }
 184 
 185     static void translateException(Exception x,
 186                                    boolean unknownHostForUnresolved)
 187         throws IOException
 188     {
 189         if (x instanceof IOException)
 190             throw (IOException)x;
 191         // Throw UnknownHostException from here since it cannot
 192         // be thrown as a SocketException
 193         if (unknownHostForUnresolved &&
 194             (x instanceof UnresolvedAddressException))
 195         {
 196              throw new UnknownHostException();
 197         }
 198         translateToSocketException(x);
 199     }
 200 
 201     static void translateException(Exception x)
 202         throws IOException
 203     {
 204         translateException(x, false);
 205     }
 206 
 207     /**
 208      * Returns the local address after performing a SecurityManager#checkConnect.
 209      */
 210     static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
 211         SecurityManager sm = System.getSecurityManager();
 212         if (addr == null || sm == null)
 213             return addr;
 214 
 215         try{
 216             sm.checkConnect(addr.getAddress().getHostAddress(), -1);
 217             // Security check passed
 218         } catch (SecurityException e) {
 219             // Return loopback address only if security check fails
 220             addr = getLoopbackAddress(addr.getPort());
 221         }
 222         return addr;
 223     }
 224 
 225     static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
 226         return System.getSecurityManager() == null ? addr.toString() :
 227                 getLoopbackAddress(addr.getPort()).toString();
 228     }
 229 
 230     private static InetSocketAddress getLoopbackAddress(int port) {
 231         return new InetSocketAddress(InetAddress.getLoopbackAddress(),
 232                                      port);
 233     }
 234 
 235     /**
 236      * Returns any IPv4 address of the given network interface, or
 237      * null if the interface does not have any IPv4 addresses.
 238      */
 239     static Inet4Address anyInet4Address(final NetworkInterface interf) {
 240         return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
 241             public Inet4Address run() {
 242                 Enumeration<InetAddress> addrs = interf.getInetAddresses();
 243                 while (addrs.hasMoreElements()) {
 244                     InetAddress addr = addrs.nextElement();
 245                     if (addr instanceof Inet4Address) {
 246                         return (Inet4Address)addr;
 247                     }
 248                 }
 249                 return null;
 250             }
 251         });
 252     }
 253 
 254     /**
 255      * Returns an IPv4 address as an int.
 256      */
 257     static int inet4AsInt(InetAddress ia) {
 258         if (ia instanceof Inet4Address) {
 259             byte[] addr = ia.getAddress();
 260             int address  = addr[3] & 0xFF;
 261             address |= ((addr[2] << 8) & 0xFF00);
 262             address |= ((addr[1] << 16) & 0xFF0000);
 263             address |= ((addr[0] << 24) & 0xFF000000);
 264             return address;
 265         }
 266         throw new AssertionError("Should not reach here");
 267     }
 268 
 269     /**
 270      * Returns an InetAddress from the given IPv4 address
 271      * represented as an int.
 272      */
 273     static InetAddress inet4FromInt(int address) {
 274         byte[] addr = new byte[4];
 275         addr[0] = (byte) ((address >>> 24) & 0xFF);
 276         addr[1] = (byte) ((address >>> 16) & 0xFF);
 277         addr[2] = (byte) ((address >>> 8) & 0xFF);
 278         addr[3] = (byte) (address & 0xFF);
 279         try {
 280             return InetAddress.getByAddress(addr);
 281         } catch (UnknownHostException uhe) {
 282             throw new AssertionError("Should not reach here");
 283         }
 284     }
 285 
 286     /**
 287      * Returns an IPv6 address as a byte array
 288      */
 289     static byte[] inet6AsByteArray(InetAddress ia) {
 290         if (ia instanceof Inet6Address) {
 291             return ia.getAddress();
 292         }
 293 
 294         // need to construct IPv4-mapped address
 295         if (ia instanceof Inet4Address) {
 296             byte[] ip4address = ia.getAddress();
 297             byte[] address = new byte[16];
 298             address[10] = (byte)0xff;
 299             address[11] = (byte)0xff;
 300             address[12] = ip4address[0];
 301             address[13] = ip4address[1];
 302             address[14] = ip4address[2];
 303             address[15] = ip4address[3];
 304             return address;
 305         }
 306 
 307         throw new AssertionError("Should not reach here");
 308     }
 309 
 310     // -- Socket options
 311 
 312     static final ExtendedSocketOptions extendedOptions =
 313             ExtendedSocketOptions.getInstance();
 314 
 315     static void setSocketOption(FileDescriptor fd, SocketOption<?> name, Object value)
 316         throws IOException
 317     {
 318         setSocketOption(fd, Net.UNSPEC, name, value);
 319     }
 320 
 321     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
 322                                 SocketOption<?> name, Object value)
 323         throws IOException
 324     {
 325         if (value == null)
 326             throw new IllegalArgumentException("Invalid option value");
 327 
 328         // only simple values supported by this method
 329         Class<?> type = name.type();
 330 
 331         if (extendedOptions.isOptionSupported(name)) {
 332             extendedOptions.setOption(fd, name, value);
 333             return;
 334         }
 335 
 336         if (type != Integer.class && type != Boolean.class)
 337             throw new AssertionError("Should not reach here");
 338 
 339         // special handling
 340         if (name == StandardSocketOptions.SO_RCVBUF ||
 341             name == StandardSocketOptions.SO_SNDBUF)
 342         {
 343             int i = ((Integer)value).intValue();
 344             if (i < 0)
 345                 throw new IllegalArgumentException("Invalid send/receive buffer size");
 346         }
 347         if (name == StandardSocketOptions.SO_LINGER) {
 348             int i = ((Integer)value).intValue();
 349             if (i < 0)
 350                 value = Integer.valueOf(-1);
 351             if (i > 65535)
 352                 value = Integer.valueOf(65535);
 353         }
 354         if (name == StandardSocketOptions.IP_TOS) {
 355             int i = ((Integer)value).intValue();
 356             if (i < 0 || i > 255)
 357                 throw new IllegalArgumentException("Invalid IP_TOS value");
 358         }
 359         if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
 360             int i = ((Integer)value).intValue();
 361             if (i < 0 || i > 255)
 362                 throw new IllegalArgumentException("Invalid TTL/hop value");
 363         }
 364 
 365         // map option name to platform level/name
 366         OptionKey key = SocketOptionRegistry.findOption(name, family);
 367         if (key == null)
 368             throw new AssertionError("Option not found");
 369 
 370         int arg;
 371         if (type == Integer.class) {
 372             arg = ((Integer)value).intValue();
 373         } else {
 374             boolean b = ((Boolean)value).booleanValue();
 375             arg = (b) ? 1 : 0;
 376         }
 377 
 378         boolean mayNeedConversion = (family == UNSPEC);
 379         boolean isIPv6 = (family == StandardProtocolFamily.INET6);
 380         setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
 381     }
 382 
 383     static Object getSocketOption(FileDescriptor fd, SocketOption<?> name)
 384         throws IOException
 385     {
 386         return getSocketOption(fd, Net.UNSPEC, name);
 387     }
 388 
 389     static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption<?> name)
 390         throws IOException
 391     {
 392         Class<?> type = name.type();
 393 
 394         if (extendedOptions.isOptionSupported(name)) {
 395             return extendedOptions.getOption(fd, name);
 396         }
 397 
 398         // only simple values supported by this method
 399         if (type != Integer.class && type != Boolean.class)
 400             throw new AssertionError("Should not reach here");
 401 
 402         // map option name to platform level/name
 403         OptionKey key = SocketOptionRegistry.findOption(name, family);
 404         if (key == null)
 405             throw new AssertionError("Option not found");
 406 
 407         boolean mayNeedConversion = (family == UNSPEC);
 408         int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
 409 
 410         if (type == Integer.class) {
 411             return Integer.valueOf(value);
 412         } else {
 413             return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
 414         }
 415     }
 416 
 417     public static boolean isFastTcpLoopbackRequested() {
 418         String loopbackProp = GetPropertyAction
 419                 .privilegedGetProperty("jdk.net.useFastTcpLoopback", "false");
 420         return loopbackProp.isEmpty() ? true : Boolean.parseBoolean(loopbackProp);
 421     }
 422 
 423     // -- Socket operations --
 424 
 425     private static native boolean isIPv6Available0();
 426 
 427     private static native boolean isReusePortAvailable0();
 428 
 429     /*
 430      * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
 431      */
 432     private static native int isExclusiveBindAvailable();
 433 
 434     private static native boolean canIPv6SocketJoinIPv4Group0();
 435 
 436     private static native boolean canJoin6WithIPv4Group0();
 437 
 438     static FileDescriptor socket(boolean stream) throws IOException {
 439         return socket(UNSPEC, stream);
 440     }
 441 
 442     static FileDescriptor socket(ProtocolFamily family, boolean stream) throws IOException {
 443         if (family == StandardProtocolFamily.UNIX) {
 444             return IOUtil.newFD(socket1(stream));
 445         } else {
 446             boolean preferIPv6 = isIPv6Available() &&
 447                 (family != StandardProtocolFamily.INET);
 448             return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
 449         }
 450     }
 451 
 452     static FileDescriptor serverSocket(boolean stream, ProtocolFamily family) {
 453         if (family == StandardProtocolFamily.UNIX) {
 454             return IOUtil.newFD(socket1(stream));
 455         } else {
 456             return serverSocket(stream);
 457         }
 458     }
 459     
 460     static FileDescriptor serverSocket(boolean stream) {
 461         return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
 462     }
 463     
 464     // Due to oddities SO_REUSEADDR on windows reuse is ignored
 465     private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse,
 466                                       boolean fastLoopback);
 467     
 468     // TODO: rename, refactor, support maybe also SOCK_SEQPACKET, support reuse (delete socket file if exists)?
 469     private static native int socket1(boolean stream);
 470 
 471     public static void bind(FileDescriptor fd, UnixSocketAddress addr)
 472         throws IOException
 473     {
 474         bind1(fd, addr.getPathBytes());
 475     }
 476     
 477     // TODO: rename, UnixSocketAddress object instead of byte array?
 478     private static native void bind1(FileDescriptor fd, byte[] addr) throws IOException;
 479     
 480     public static void bind(FileDescriptor fd, InetAddress addr, int port)
 481         throws IOException
 482     {
 483         bind(UNSPEC, fd, addr, port);
 484     }
 485 
 486     static void bind(ProtocolFamily family, FileDescriptor fd,
 487                      InetAddress addr, int port) throws IOException
 488     {
 489         boolean preferIPv6 = isIPv6Available() &&
 490             (family != StandardProtocolFamily.INET);
 491         if (addr.isLinkLocalAddress()) {
 492             addr = IPAddressUtil.toScopedAddress(addr);
 493         }
 494         bind0(fd, preferIPv6, exclusiveBind, addr, port);
 495     }
 496 
 497     private static native void bind0(FileDescriptor fd, boolean preferIPv6,
 498                                      boolean useExclBind, InetAddress addr,
 499                                      int port)
 500         throws IOException;
 501 
 502     static native void listen(FileDescriptor fd, int backlog) throws IOException;
 503 
 504     static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
 505         throws IOException
 506     {
 507         return connect(UNSPEC, fd, remote, remotePort);
 508     }
 509     
 510     static int connect(FileDescriptor fd, UnixSocketAddress remote)
 511         throws IOException
 512     {
 513         return connect1(fd, remote.getPathBytes());
 514     }
 515 
 516     static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
 517         throws IOException
 518     {
 519         if (remote.isLinkLocalAddress()) {
 520             remote = IPAddressUtil.toScopedAddress(remote);
 521         }
 522         boolean preferIPv6 = isIPv6Available() &&
 523             (family != StandardProtocolFamily.INET);
 524         return connect0(preferIPv6, fd, remote, remotePort);
 525     }
 526 
 527     private static native int connect0(boolean preferIPv6,
 528                                        FileDescriptor fd,
 529                                        InetAddress remote,
 530                                        int remotePort)
 531         throws IOException;
 532     
 533     private static native int connect1(FileDescriptor fd, byte[] remote)
 534         throws IOException;
 535 
 536     public static int accept(FileDescriptor fd,
 537                                     FileDescriptor newfd,
 538                                     InetSocketAddress[] isaa)
 539         throws IOException {
 540         
 541         SocketAddress[] array = new SocketAddress[isaa.length];
 542         int result = accept(fd, newfd, array);
 543         for (int i = 0; i < isaa.length; i++) {
 544             isaa[i] = (InetSocketAddress) array[i];
 545         }
 546         return result;
 547     }
 548     
 549     public static native int accept(FileDescriptor fd,
 550                                     FileDescriptor newfd,
 551                                     SocketAddress[] isaa)
 552         throws IOException;
 553 
 554     public static final int SHUT_RD = 0;
 555     public static final int SHUT_WR = 1;
 556     public static final int SHUT_RDWR = 2;
 557 
 558     static native void shutdown(FileDescriptor fd, int how) throws IOException;
 559 
 560     private static native int localPort(FileDescriptor fd)
 561         throws IOException;
 562 
 563     private static native InetAddress localInetAddress(FileDescriptor fd)
 564         throws IOException;
 565 
 566     public static InetSocketAddress localAddress(FileDescriptor fd)
 567         throws IOException
 568     {
 569         return new InetSocketAddress(localInetAddress(fd), localPort(fd));
 570     }
 571     
 572     public static native SocketAddress localSocketAddress(FileDescriptor fd)
 573         throws IOException;
 574     
 575     private static native int remotePort(FileDescriptor fd)
 576         throws IOException;
 577 
 578     private static native InetAddress remoteInetAddress(FileDescriptor fd)
 579         throws IOException;
 580 
 581     static InetSocketAddress remoteAddress(FileDescriptor fd)
 582         throws IOException
 583     {
 584         return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
 585     }
 586 
 587     private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
 588                                             int level, int opt)
 589         throws IOException;
 590 
 591     private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
 592                                              int level, int opt, int arg, boolean isIPv6)
 593         throws IOException;
 594 
 595     /**
 596      * Polls a file descriptor for events.
 597      * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
 598      * @return the polled events or 0 if no events are polled
 599      */
 600     static native int poll(FileDescriptor fd, int events, long timeout)
 601         throws IOException;
 602 
 603     /**
 604      * Performs a non-blocking poll of a file descriptor.
 605      * @return the polled events or 0 if no events are polled
 606      */
 607     static int pollNow(FileDescriptor fd, int events) throws IOException {
 608         return poll(fd, events, 0);
 609     }
 610 
 611     /**
 612      * Polls a connecting socket to test if the connection has been established.
 613      *
 614      * @apiNote This method is public to allow it be used by code in jdk.sctp.
 615      *
 616      * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
 617      * @return true if connected
 618      */
 619     public static native boolean pollConnect(FileDescriptor fd, long timeout)
 620         throws IOException;
 621 
 622     /**
 623      * Performs a non-blocking poll of a connecting socket to test if the
 624      * connection has been established.
 625      *
 626      * @return true if connected
 627      */
 628     static boolean pollConnectNow(FileDescriptor fd) throws IOException {
 629         return pollConnect(fd, 0);
 630     }
 631 
 632     /**
 633      * Return the number of bytes in the socket input buffer.
 634      */
 635     static native int available(FileDescriptor fd) throws IOException;
 636 
 637     /**
 638      * Send one byte of urgent data (MSG_OOB) on the socket.
 639      */
 640     static native int sendOOB(FileDescriptor fd, byte data) throws IOException;
 641 
 642 
 643     // -- Multicast support --
 644 
 645     /**
 646      * Join IPv4 multicast group
 647      */
 648     static int join4(FileDescriptor fd, int group, int interf, int source)
 649         throws IOException
 650     {
 651         return joinOrDrop4(true, fd, group, interf, source);
 652     }
 653 
 654     /**
 655      * Drop membership of IPv4 multicast group
 656      */
 657     static void drop4(FileDescriptor fd, int group, int interf, int source)
 658         throws IOException
 659     {
 660         joinOrDrop4(false, fd, group, interf, source);
 661     }
 662 
 663     private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
 664         throws IOException;
 665 
 666     /**
 667      * Block IPv4 source
 668      */
 669     static int block4(FileDescriptor fd, int group, int interf, int source)
 670         throws IOException
 671     {
 672         return blockOrUnblock4(true, fd, group, interf, source);
 673     }
 674 
 675     /**
 676      * Unblock IPv6 source
 677      */
 678     static void unblock4(FileDescriptor fd, int group, int interf, int source)
 679         throws IOException
 680     {
 681         blockOrUnblock4(false, fd, group, interf, source);
 682     }
 683 
 684     private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
 685                                               int interf, int source)
 686         throws IOException;
 687 
 688     /**
 689      * Join IPv6 multicast group
 690      */
 691     static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
 692         throws IOException
 693     {
 694         return joinOrDrop6(true, fd, group, index, source);
 695     }
 696 
 697     /**
 698      * Drop membership of IPv6 multicast group
 699      */
 700     static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
 701         throws IOException
 702     {
 703         joinOrDrop6(false, fd, group, index, source);
 704     }
 705 
 706     private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
 707         throws IOException;
 708 
 709     /**
 710      * Block IPv6 source
 711      */
 712     static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
 713         throws IOException
 714     {
 715         return blockOrUnblock6(true, fd, group, index, source);
 716     }
 717 
 718     /**
 719      * Unblock IPv6 source
 720      */
 721     static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
 722         throws IOException
 723     {
 724         blockOrUnblock6(false, fd, group, index, source);
 725     }
 726 
 727     static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
 728         throws IOException;
 729 
 730     static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
 731 
 732     static native int getInterface4(FileDescriptor fd) throws IOException;
 733 
 734     static native void setInterface6(FileDescriptor fd, int index) throws IOException;
 735 
 736     static native int getInterface6(FileDescriptor fd) throws IOException;
 737 
 738     private static native void initIDs();
 739 
 740     /**
 741      * Event masks for the various poll system calls.
 742      * They will be set platform dependent in the static initializer below.
 743      */
 744     public static final short POLLIN;
 745     public static final short POLLOUT;
 746     public static final short POLLERR;
 747     public static final short POLLHUP;
 748     public static final short POLLNVAL;
 749     public static final short POLLCONN;
 750 
 751     static native short pollinValue();
 752     static native short polloutValue();
 753     static native short pollerrValue();
 754     static native short pollhupValue();
 755     static native short pollnvalValue();
 756     static native short pollconnValue();
 757 
 758     static {
 759         IOUtil.load();
 760         initIDs();
 761 
 762         POLLIN     = pollinValue();
 763         POLLOUT    = polloutValue();
 764         POLLERR    = pollerrValue();
 765         POLLHUP    = pollhupValue();
 766         POLLNVAL   = pollnvalValue();
 767         POLLCONN   = pollconnValue();
 768     }
 769 
 770     static {
 771         int availLevel = isExclusiveBindAvailable();
 772         if (availLevel >= 0) {
 773             String exclBindProp = GetPropertyAction
 774                     .privilegedGetProperty("sun.net.useExclusiveBind");
 775             if (exclBindProp != null) {
 776                 exclusiveBind = exclBindProp.isEmpty() ?
 777                         true : Boolean.parseBoolean(exclBindProp);
 778             } else if (availLevel == 1) {
 779                 exclusiveBind = true;
 780             } else {
 781                 exclusiveBind = false;
 782             }
 783         } else {
 784             exclusiveBind = false;
 785         }
 786 
 787         fastLoopback = isFastTcpLoopbackRequested();
 788     }
 789 }