src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c

Print this page




  48 #include "net_util.h"
  49 
  50 #define IN_CLASSD(i)    (((long)(i) & 0xf0000000) == 0xe0000000)
  51 #define IN_MULTICAST(i) IN_CLASSD(i)
  52 
  53 /************************************************************************
  54  * TwoStacksPlainDatagramSocketImpl
  55  */
  56 
  57 static jfieldID IO_fd_fdID;
  58 static jfieldID pdsi_trafficClassID;
  59 jfieldID pdsi_fdID;
  60 jfieldID pdsi_fd1ID;
  61 jfieldID pdsi_fduseID;
  62 jfieldID pdsi_lastfdID;
  63 jfieldID pdsi_timeoutID;
  64 
  65 jfieldID pdsi_localPortID;
  66 jfieldID pdsi_connected;
  67 
  68 static jclass ia4_clazz;
  69 static jmethodID ia4_ctor;
  70 
  71 static CRITICAL_SECTION sizeCheckLock;
  72 
  73 /* Windows OS version is XP or better */
  74 static int xp_or_later = 0;
  75 /* Windows OS version is Windows 2000 or better */
  76 static int w2k_or_later = 0;
  77 
  78 /*
  79  * Notes about UDP/IPV6 on Windows (XP and 2003 server):
  80  *
  81  * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd.
  82  * Both fds are used when we bind to a wild-card address. When a specific
  83  * address is used, only one of them is used.
  84  */
  85 
  86 /*
  87  * Returns a java.lang.Integer based on 'i'
  88  */
  89 jobject createInteger(JNIEnv *env, int i) {
  90     static jclass i_class;
  91     static jmethodID i_ctrID;
  92     static jfieldID i_valueID;
  93 

  94     if (i_class == NULL) {
  95         jclass c = (*env)->FindClass(env, "java/lang/Integer");
  96         CHECK_NULL_RETURN(c, NULL);
  97         i_ctrID = (*env)->GetMethodID(env, c, "<init>", "(I)V");
  98         CHECK_NULL_RETURN(i_ctrID, NULL);


  99         i_class = (*env)->NewGlobalRef(env, c);
 100         CHECK_NULL_RETURN(i_class, NULL);
 101     }


 102 



 103     return ( (*env)->NewObject(env, i_class, i_ctrID, i) );
 104 }
 105 
 106 /*
 107  * Returns a java.lang.Boolean based on 'b'
 108  */
 109 jobject createBoolean(JNIEnv *env, int b) {
 110     static jclass b_class;
 111     static jmethodID b_ctrID;
 112     static jfieldID b_valueID;
 113 





 114     if (b_class == NULL) {
 115         jclass c = (*env)->FindClass(env, "java/lang/Boolean");
 116         CHECK_NULL_RETURN(c, NULL);
 117         b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");
 118         CHECK_NULL_RETURN(b_ctrID, NULL);


 119         b_class = (*env)->NewGlobalRef(env, c);
 120         CHECK_NULL_RETURN(b_class, NULL);
 121     }


 122 



 123     return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
 124 }
 125 





 126 
 127 static int getFD(JNIEnv *env, jobject this) {
 128     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 129 
 130     if (fdObj == NULL) {
 131         return -1;
 132     }
 133     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 134 }
 135 
 136 static int getFD1(JNIEnv *env, jobject this) {
 137     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 138 
 139     if (fdObj == NULL) {
 140         return -1;
 141     }
 142     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 143 }
 144 
 145 /*


 391     pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;");
 392     CHECK_NULL(pdsi_fd1ID);
 393     pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
 394     CHECK_NULL(pdsi_timeoutID);
 395     pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I");
 396     CHECK_NULL(pdsi_fduseID);
 397     pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
 398     CHECK_NULL(pdsi_lastfdID);
 399     pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
 400     CHECK_NULL(pdsi_trafficClassID);
 401     pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I");
 402     CHECK_NULL(pdsi_localPortID);
 403     pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z");
 404     CHECK_NULL(pdsi_connected);
 405 
 406     cls = (*env)->FindClass(env, "java/io/FileDescriptor");
 407     CHECK_NULL(cls);
 408     IO_fd_fdID = NET_GetFileDescriptorID(env);
 409     CHECK_NULL(IO_fd_fdID);
 410 
 411     ia4_clazz = (*env)->FindClass(env, "java/net/Inet4Address");
 412     CHECK_NULL(ia4_clazz);
 413     ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz);
 414     CHECK_NULL(ia4_clazz);
 415     ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V");
 416     CHECK_NULL(ia4_ctor);
 417 
 418 
 419     InitializeCriticalSection(&sizeCheckLock);
 420 }
 421 
 422 JNIEXPORT void JNICALL
 423 Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
 424                                            jint port, jobject addressObj) {
 425     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 426     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 427 
 428     int fd, fd1, family;
 429     int ipv6_supported = ipv6_available();
 430 
 431     SOCKETADDRESS lcladdr;
 432     int lcladdrlen;
 433     int address;
 434 
 435     family = (*env)->GetIntField(env, addressObj, ia_familyID);
 436     if (family == IPv6 && !ipv6_supported) {
 437         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 438                         "Protocol family not supported");


 450     }
 451     if (IS_NULL(addressObj)) {
 452         JNU_ThrowNullPointerException(env, "argument address");
 453         return;
 454     } else {
 455         address = (*env)->GetIntField(env, addressObj, ia_addressID);
 456     }
 457 
 458     if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) {
 459       return;
 460     }
 461 
 462     if (ipv6_supported) {
 463         struct ipv6bind v6bind;
 464         v6bind.addr = &lcladdr;
 465         v6bind.ipv4_fd = fd;
 466         v6bind.ipv6_fd = fd1;
 467         if (NET_BindV6(&v6bind) != -1) {
 468             /* check if the fds have changed */
 469             if (v6bind.ipv4_fd != fd) {
 470                 fd = v6bind.ipv4_fd;
 471                 if (fd == -1) {
 472                     /* socket is closed. */
 473                     (*env)->SetObjectField(env, this, pdsi_fdID, NULL);
 474                 } else {
 475                     /* socket was re-created */
 476                     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 477                 }
 478             }
 479             if (v6bind.ipv6_fd != fd1) {
 480                 fd1 = v6bind.ipv6_fd;
 481                 if (fd1 == -1) {
 482                     /* socket is closed. */
 483                     (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL);
 484                 } else {
 485                     /* socket was re-created */
 486                     (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
 487                 }
 488             }
 489         } else {
 490             NET_ThrowCurrent (env, "Cannot bind");
 491             return;
 492         }
 493     } else {
 494         if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) {
 495             if (WSAGetLastError() == WSAEACCES) {
 496                 WSASetLastError(WSAEADDRINUSE);
 497             }
 498             NET_ThrowCurrent(env, "Cannot bind");
 499             return;
 500         }


1493     } else {
1494         fd =  (int) socket (AF_INET, SOCK_DGRAM, 0);
1495     }
1496     if (fd == JVM_IO_ERR) {
1497         NET_ThrowCurrent(env, "Socket creation failed");
1498         return;
1499     }
1500     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
1501     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
1502     NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
1503 
1504     if (ipv6_supported) {
1505         /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
1506          * returns connection reset errors un connected UDP sockets (as well
1507          * as connected sockets. The solution is to only enable this feature
1508          * when the socket is connected
1509          */
1510         t = FALSE;
1511         WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
1512         t = TRUE;
1513         fd1 = socket (AF_INET6, SOCK_DGRAM, 0);
1514         if (fd1 == JVM_IO_ERR) {
1515             NET_ThrowCurrent(env, "Socket creation failed");
1516             return;
1517         }
1518         NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
1519         t = FALSE;
1520         WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
1521         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
1522         SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE);
1523     } else {
1524         /* drop the second fd */
1525         (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL);
1526     }
1527 }
1528 
1529 /*
1530  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1531  * Method:    datagramSocketClose
1532  * Signature: ()V
1533  */


1556 
1557     if (ipv6_supported && fd1Obj != NULL) {
1558         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
1559         if (fd1 == -1) {
1560             return;
1561         }
1562         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
1563         NET_SocketClose(fd1);
1564     }
1565 }
1566 
1567 /*
1568  * check the addresses attached to the NetworkInterface object
1569  * and return the first one (of the requested family Ipv4 or Ipv6)
1570  * in *iaddr
1571  */
1572 
1573 static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iaddr)
1574 {
1575     jobjectArray addrArray;
1576     static jfieldID ni_addrsID=0;
1577     static jfieldID ia_familyID=0;
1578     jsize len;
1579     jobject addr;
1580     int i;
1581 
1582     if (ni_addrsID == NULL) {
1583         jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1584         CHECK_NULL_RETURN (c, -1);
1585         ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
1586                                         "[Ljava/net/InetAddress;");
1587         CHECK_NULL_RETURN (ni_addrsID, -1);
1588         c = (*env)->FindClass(env,"java/net/InetAddress");
1589         CHECK_NULL_RETURN (c, -1);
1590         ia_familyID = (*env)->GetFieldID(env, c, "family", "I");
1591         CHECK_NULL_RETURN (ia_familyID, -1);
1592     }
1593 
1594     addrArray = (*env)->GetObjectField(env, nif, ni_addrsID);
1595     len = (*env)->GetArrayLength(env, addrArray);
1596 
1597     /*
1598      * Check that there is at least one address bound to this
1599      * interface.
1600      */
1601     if (len < 1) {
1602         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1603             "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
1604         return -1;
1605     }
1606     for (i=0; i<len; i++) {
1607         int fam;
1608         addr = (*env)->GetObjectArrayElement(env, addrArray, i);
1609         fam = (*env)->GetIntField(env, addr, ia_familyID);
1610         if (fam == family) {
1611             *iaddr = addr;
1612             return 0;
1613         }
1614     }
1615     return -1;
1616 }
1617 
1618 static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr)
1619 {
1620     jobject addr;
1621     static jfieldID ia_addressID;
1622 
1623     int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
1624     if (ret == -1) {
1625         return -1;
1626     }
1627 
1628     if (ia_addressID == 0) {
1629         jclass c = (*env)->FindClass(env,"java/net/InetAddress");
1630         CHECK_NULL_RETURN (c, -1);
1631         ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
1632         CHECK_NULL_RETURN (ia_addressID, -1);
1633     }
1634     iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
1635     return 0;
1636 }
1637 
1638 /* Get the multicasting index from the interface */
1639 
1640 static int getIndexFromIf (JNIEnv *env, jobject nif) {
1641     static jfieldID ni_indexID;
1642 
1643     if (ni_indexID == NULL) {
1644         jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1645         CHECK_NULL_RETURN(c, -1);
1646         ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
1647         CHECK_NULL_RETURN(ni_indexID, -1);
1648     }
1649 
1650     return (*env)->GetIntField(env, nif, ni_indexID);
1651 }
1652 
1653 /*
1654  * Sets the multicast interface.
1655  *
1656  * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :-
1657  *      IPv4:   set outgoing multicast interface using
1658  *              IPPROTO_IP/IP_MULTICAST_IF
1659  *
1660  *      IPv6:   Get the interface to which the
1661  *              InetAddress is bound
1662  *              and do same as SockOptions.IF_MULTICAST_IF2
1663  *
1664  * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :-
1665  *      For each stack:
1666  *      IPv4:   Obtain IP address bound to network interface
1667  *              (NetworkInterface.addres[0])
1668  *              set outgoing multicast interface using
1669  *              IPPROTO_IP/IP_MULTICAST_IF
1670  *
1671  *      IPv6:   Obtain NetworkInterface.index
1672  *              Set outgoing multicast interface using
1673  *              IPPROTO_IPV6/IPV6_MULTICAST_IF
1674  *
1675  */
1676 static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1,
1677                                   jint opt, jobject value)
1678 {
1679     int ipv6_supported = ipv6_available();
1680 
1681     if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
1682         /*
1683          * value is an InetAddress.
1684          * On IPv4 system use IP_MULTICAST_IF socket option
1685          * On IPv6 system get the NetworkInterface that this IP
1686          * address is bound to and use the IPV6_MULTICAST_IF
1687          * option instead of IP_MULTICAST_IF
1688          */
1689         if (ipv6_supported) {
1690             static jclass ni_class;
1691             if (ni_class == NULL) {
1692                 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1693                 CHECK_NULL(c);
1694                 ni_class = (*env)->NewGlobalRef(env, c);
1695                 CHECK_NULL(ni_class);
1696             }
1697 
1698             value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value);
1699             if (value == NULL) {
1700                 if (!(*env)->ExceptionOccurred(env)) {
1701                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1702                          "bad argument for IP_MULTICAST_IF"
1703                          ": address not bound to any interface");
1704                 }
1705                 return;
1706             }
1707             opt = java_net_SocketOptions_IP_MULTICAST_IF2;
1708         } else {
1709             static jfieldID ia_addressID;
1710             struct in_addr in;
1711 
1712             if (ia_addressID == NULL) {
1713                         jclass c = (*env)->FindClass(env,"java/net/InetAddress");
1714                 CHECK_NULL(c);
1715                 ia_addressID = (*env)->GetFieldID(env, c, "address", "I");
1716                 CHECK_NULL(ia_addressID);
1717             }
1718 
1719             in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID));
1720 
1721             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1722                                (const char*)&in, sizeof(in)) < 0) {
1723                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1724                                  "Error setting socket option");
1725             }
1726             return;
1727         }
1728     }
1729 
1730     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
1731         /*
1732          * value is a NetworkInterface.
1733          * On IPv6 system get the index of the interface and use the
1734          * IPV6_MULTICAST_IF socket option
1735          * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF
1736          * option. For IPv6 both must be done.
1737          */
1738         if (ipv6_supported) {
1739             static jfieldID ni_indexID;
1740             struct in_addr in;
1741             int index;
1742 
1743             if (ni_indexID == NULL) {
1744                 jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
1745                 CHECK_NULL(c);
1746                 ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
1747                 CHECK_NULL(ni_indexID);
1748             }
1749             index = (*env)->GetIntField(env, value, ni_indexID);
1750 
1751             if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1752                                (const char*)&index, sizeof(index)) < 0) {
1753                 if (errno == EINVAL && index > 0) {
1754                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1755                         "IPV6_MULTICAST_IF failed (interface has IPv4 "
1756                         "address only?)");
1757                 } else {
1758                     NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1759                                    "Error setting socket option");
1760                 }
1761                 return;
1762             }
1763 
1764             /* If there are any IPv4 addresses on this interface then
1765              * repeat the operation on the IPv4 fd */
1766 
1767             if (getInet4AddrFromIf (env, value, &in) < 0) {
1768                 return;


1834      * level(s) and option name(s).
1835      */
1836     if (fd1 != -1) {
1837         if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) {
1838             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1839             return;
1840         }
1841     }
1842     if (fd != -1) {
1843         if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) {
1844             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1845             return;
1846         }
1847     }
1848 
1849     switch (opt) {
1850         case java_net_SocketOptions_SO_SNDBUF :
1851         case java_net_SocketOptions_SO_RCVBUF :
1852         case java_net_SocketOptions_IP_TOS :
1853             {
1854                 jclass cls;
1855                 jfieldID fid;
1856 
1857                 cls = (*env)->FindClass(env, "java/lang/Integer");
1858                 CHECK_NULL(cls);
1859                 fid =  (*env)->GetFieldID(env, cls, "value", "I");
1860                 CHECK_NULL(fid);
1861 
1862                 optval.i = (*env)->GetIntField(env, value, fid);
1863                 optlen = sizeof(optval.i);
1864             }
1865             break;
1866 
1867         case java_net_SocketOptions_SO_REUSEADDR:
1868         case java_net_SocketOptions_SO_BROADCAST:
1869         case java_net_SocketOptions_IP_MULTICAST_LOOP:
1870             {
1871                 jclass cls;
1872                 jfieldID fid;
1873                 jboolean on;
1874 
1875                 cls = (*env)->FindClass(env, "java/lang/Boolean");
1876                 CHECK_NULL(cls);
1877                 fid =  (*env)->GetFieldID(env, cls, "value", "Z");
1878                 CHECK_NULL(fid);
1879 
1880                 on = (*env)->GetBooleanField(env, value, fid);
1881                 optval.i = (on ? 1 : 0);
1882                 /*
1883                  * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather
1884                  * than enabling it.
1885                  */
1886                 if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) {
1887                     optval.i = !optval.i;
1888                 }
1889                 optlen = sizeof(optval.i);
1890             }
1891             break;
1892 
1893         default :
1894             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1895                 "Socket option not supported by PlainDatagramSocketImp");
1896             break;
1897 
1898     }
1899 
1900     if (fd1 != -1) {


1926  *              If index > 0 query NetworkInterface by index
1927  *              and returns addrs[0]
1928  *
1929  * SocketOptions.IP_MULTICAST_IF2
1930  *      IPv4:   Query IPPROTO_IP/IP_MULTICAST_IF
1931  *              Query NetworkInterface by IP address and
1932  *              return the NetworkInterface that the address
1933  *              is bound too.
1934  *      IPv6:   Query IPPROTO_IPV6 / IPV6_MULTICAST_IF
1935  *              (except Linux .2 kernel)
1936  *              Query NetworkInterface by index and
1937  *              return NetworkInterface.
1938  */
1939 jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint opt) {
1940     jboolean isIPV4 = !ipv6_available() || fd1 == -1;
1941 
1942     /*
1943      * IPv4 implementation
1944      */
1945     if (isIPV4) {
1946         static jclass inet4_class;
1947         static jmethodID inet4_ctrID;
1948         static jfieldID inet4_addrID;
1949 
1950         static jclass ni_class;
1951         static jmethodID ni_ctrID;
1952         static jfieldID ni_indexID;
1953         static jfieldID ni_addrsID;
1954 
1955         jobjectArray addrArray;
1956         jobject addr;
1957         jobject ni;
1958 
1959         struct in_addr in;
1960         struct in_addr *inP = &in;
1961         int len = sizeof(struct in_addr);
1962 
1963         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1964                            (char *)inP, &len) < 0) {
1965             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1966                              "Error getting socket option");
1967             return NULL;
1968         }
1969 
1970         /*
1971          * Construct and populate an Inet4Address
1972          */
1973         if (inet4_class == NULL) {
1974             jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
1975             CHECK_NULL_RETURN(c, NULL);
1976             inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
1977             CHECK_NULL_RETURN(inet4_ctrID, NULL);
1978             inet4_addrID = (*env)->GetFieldID(env, c, "address", "I");
1979             CHECK_NULL_RETURN(inet4_addrID, NULL);
1980             inet4_class = (*env)->NewGlobalRef(env, c);
1981             CHECK_NULL_RETURN(inet4_class, NULL);
1982         }
1983         addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
1984         CHECK_NULL_RETURN(addr, NULL);
1985 
1986         (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr));
1987 
1988         /*
1989          * For IP_MULTICAST_IF return InetAddress
1990          */
1991         if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
1992             return addr;
1993         }
1994 
1995         /*
1996          * For IP_MULTICAST_IF2 we get the NetworkInterface for
1997          * this address and return it
1998          */
1999         if (ni_class == NULL) {
2000             jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
2001             CHECK_NULL_RETURN(c, NULL);
2002             ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
2003             CHECK_NULL_RETURN(ni_ctrID, NULL);
2004             ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
2005             CHECK_NULL_RETURN(ni_indexID, NULL);
2006             ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
2007                                             "[Ljava/net/InetAddress;");
2008             CHECK_NULL_RETURN(ni_addrsID, NULL);
2009             ni_class = (*env)->NewGlobalRef(env, c);
2010             CHECK_NULL_RETURN(ni_class, NULL);
2011         }
2012         ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
2013         if (ni) {
2014             return ni;
2015         }
2016 
2017         /*
2018          * The address doesn't appear to be bound at any known
2019          * NetworkInterface. Therefore we construct a NetworkInterface
2020          * with this address.
2021          */
2022         ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
2023         CHECK_NULL_RETURN(ni, NULL);
2024 
2025         (*env)->SetIntField(env, ni, ni_indexID, -1);
2026         addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL);
2027         CHECK_NULL_RETURN(addrArray, NULL);
2028         (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
2029         (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
2030         return ni;
2031     }
2032 
2033 
2034     /*
2035      * IPv6 implementation
2036      */
2037     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
2038         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
2039 
2040         static jclass ni_class;
2041         static jmethodID ni_ctrID;
2042         static jfieldID ni_indexID;
2043         static jfieldID ni_addrsID;
2044         static jclass ia_class;
2045         static jmethodID ia_anyLocalAddressID;
2046 
2047         int index;
2048         int len = sizeof(index);
2049 
2050         jobjectArray addrArray;
2051         jobject addr;
2052         jobject ni;
2053 
2054         {
2055             if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
2056                                (char*)&index, &len) < 0) {
2057                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
2058                                "Error getting socket option");
2059                 return NULL;
2060             }
2061         }
2062 
2063         if (ni_class == NULL) {
2064             jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
2065             CHECK_NULL_RETURN(c, NULL);
2066             ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
2067             CHECK_NULL_RETURN(ni_ctrID, NULL);
2068             ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
2069             CHECK_NULL_RETURN(ni_indexID, NULL);
2070             ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
2071                                             "[Ljava/net/InetAddress;");
2072             CHECK_NULL_RETURN(ni_addrsID, NULL);
2073 
2074             ia_class = (*env)->FindClass(env, "java/net/InetAddress");
2075             CHECK_NULL_RETURN(ia_class, NULL);
2076             ia_class = (*env)->NewGlobalRef(env, ia_class);
2077             CHECK_NULL_RETURN(ia_class, NULL);
2078             ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,
2079                                                              ia_class,
2080                                                              "anyLocalAddress",
2081                                                              "()Ljava/net/InetAddress;");
2082             CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL);
2083             ni_class = (*env)->NewGlobalRef(env, c);
2084             CHECK_NULL_RETURN(ni_class, NULL);
2085         }
2086 
2087         /*
2088          * If multicast to a specific interface then return the
2089          * interface (for IF2) or the any address on that interface
2090          * (for IF).
2091          */
2092         if (index > 0) {
2093             ni = Java_java_net_NetworkInterface_getByIndex0(env, ni_class,
2094                                                                    index);
2095             if (ni == NULL) {
2096                 char errmsg[255];
2097                 sprintf(errmsg,
2098                         "IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
2099                         index);
2100                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
2101                 return NULL;
2102             }
2103 
2104             /*




  48 #include "net_util.h"
  49 
  50 #define IN_CLASSD(i)    (((long)(i) & 0xf0000000) == 0xe0000000)
  51 #define IN_MULTICAST(i) IN_CLASSD(i)
  52 
  53 /************************************************************************
  54  * TwoStacksPlainDatagramSocketImpl
  55  */
  56 
  57 static jfieldID IO_fd_fdID;
  58 static jfieldID pdsi_trafficClassID;
  59 jfieldID pdsi_fdID;
  60 jfieldID pdsi_fd1ID;
  61 jfieldID pdsi_fduseID;
  62 jfieldID pdsi_lastfdID;
  63 jfieldID pdsi_timeoutID;
  64 
  65 jfieldID pdsi_localPortID;
  66 jfieldID pdsi_connected;
  67 



  68 static CRITICAL_SECTION sizeCheckLock;
  69 
  70 /* Windows OS version is XP or better */
  71 static int xp_or_later = 0;
  72 /* Windows OS version is Windows 2000 or better */
  73 static int w2k_or_later = 0;
  74 
  75 /*
  76  * Notes about UDP/IPV6 on Windows (XP and 2003 server):
  77  *
  78  * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd.
  79  * Both fds are used when we bind to a wild-card address. When a specific
  80  * address is used, only one of them is used.
  81  */
  82 
  83 static jclass i_class;
  84 static jmethodID i_ctrID;
  85 static jfieldID i_valueID;




  86 
  87 int initIntegerIDs(JNIEnv* env) {
  88     if (i_class == NULL) {
  89         jclass c = (*env)->FindClass(env, "java/lang/Integer");
  90         CHECK_NULL_RETURN(c, NULL);
  91         i_ctrID = (*env)->GetMethodID(env, c, "<init>", "(I)V");
  92         CHECK_NULL_RETURN(i_ctrID, NULL);
  93         i_valueID = (*env)->GetFieldID(env, c, "value", "I");
  94         CHECK_NULL_RETURN(i_valueID, NULL);
  95         i_class = (*env)->NewGlobalRef(env, c);
  96         CHECK_NULL_RETURN(i_class, NULL);
  97     }
  98     return 1;
  99 }
 100 
 101 /* Returns a java.lang.Integer based on 'i' */
 102 static jobject createInteger(JNIEnv *env, int i) {
 103     CHECK_NULL_RETURN(initIntegerIDs(env), NULL);
 104     return ( (*env)->NewObject(env, i_class, i_ctrID, i) );
 105 }
 106 
 107 /* Returns a jint based on the given java.lang.Integer */
 108 static jint retrieveInteger(JNIEnv *env, jobject i) {
 109     CHECK_NULL_RETURN(initIntegerIDs(env), NULL);
 110     return (*env)->GetIntField(env, i, i_valueID);
 111 }


 112 
 113 static jclass b_class;
 114 static jmethodID b_ctrID;
 115 static jfieldID b_valueID;
 116 
 117 int initBooleanIDs(JNIEnv* env) {
 118     if (b_class == NULL) {
 119         jclass c = (*env)->FindClass(env, "java/lang/Boolean");
 120         CHECK_NULL_RETURN(c, NULL);
 121         b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");
 122         CHECK_NULL_RETURN(b_ctrID, NULL);
 123         b_valueID = (*env)->GetFieldID(env, c, "value", "Z");
 124         CHECK_NULL_RETURN(b_valueID, NULL);
 125         b_class = (*env)->NewGlobalRef(env, c);
 126         CHECK_NULL_RETURN(b_class, NULL);
 127     }
 128     return 1;
 129 }
 130 
 131 /* Returns a java.lang.Boolean based on 'b' */
 132 static jobject createBoolean(JNIEnv *env, int b) {
 133     CHECK_NULL_RETURN(initBooleanIDs(env), NULL);
 134     return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
 135 }
 136 
 137 /* Returns a jboolean based on the given java.lang.Boolean */
 138 static jboolean retrieveBoolean(JNIEnv *env, jobject b) {
 139     CHECK_NULL_RETURN(initBooleanIDs(env), NULL);
 140     return (*env)->GetBooleanField(env, b, b_valueID);
 141 }
 142 
 143 static int getFD(JNIEnv *env, jobject this) {
 144     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 145 
 146     if (fdObj == NULL) {
 147         return -1;
 148     }
 149     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 150 }
 151 
 152 static int getFD1(JNIEnv *env, jobject this) {
 153     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 154 
 155     if (fdObj == NULL) {
 156         return -1;
 157     }
 158     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 159 }
 160 
 161 /*


 407     pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;");
 408     CHECK_NULL(pdsi_fd1ID);
 409     pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
 410     CHECK_NULL(pdsi_timeoutID);
 411     pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I");
 412     CHECK_NULL(pdsi_fduseID);
 413     pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
 414     CHECK_NULL(pdsi_lastfdID);
 415     pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
 416     CHECK_NULL(pdsi_trafficClassID);
 417     pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I");
 418     CHECK_NULL(pdsi_localPortID);
 419     pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z");
 420     CHECK_NULL(pdsi_connected);
 421 
 422     cls = (*env)->FindClass(env, "java/io/FileDescriptor");
 423     CHECK_NULL(cls);
 424     IO_fd_fdID = NET_GetFileDescriptorID(env);
 425     CHECK_NULL(IO_fd_fdID);
 426 
 427     // Load static data (jclass, methodIDs, fieldID ) from InetAddress,
 428     // Inet4Address, Inet6Address and NetorkInterface.
 429     init(env);
 430     (*env)->FindClass(env, "java/net/NetworkInterface");


 431 

 432    InitializeCriticalSection(&sizeCheckLock);
 433 }
 434 
 435 JNIEXPORT void JNICALL
 436 Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
 437                                            jint port, jobject addressObj) {
 438     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 439     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 440 
 441     int fd, fd1, family;
 442     int ipv6_supported = ipv6_available();
 443 
 444     SOCKETADDRESS lcladdr;
 445     int lcladdrlen;
 446     int address;
 447 
 448     family = (*env)->GetIntField(env, addressObj, ia_familyID);
 449     if (family == IPv6 && !ipv6_supported) {
 450         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 451                         "Protocol family not supported");


 463     }
 464     if (IS_NULL(addressObj)) {
 465         JNU_ThrowNullPointerException(env, "argument address");
 466         return;
 467     } else {
 468         address = (*env)->GetIntField(env, addressObj, ia_addressID);
 469     }
 470 
 471     if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) {
 472       return;
 473     }
 474 
 475     if (ipv6_supported) {
 476         struct ipv6bind v6bind;
 477         v6bind.addr = &lcladdr;
 478         v6bind.ipv4_fd = fd;
 479         v6bind.ipv6_fd = fd1;
 480         if (NET_BindV6(&v6bind) != -1) {
 481             /* check if the fds have changed */
 482             if (v6bind.ipv4_fd != fd) {
 483                 fd = (int)v6bind.ipv4_fd;
 484                 if (fd == -1) {
 485                     /* socket is closed. */
 486                     (*env)->SetObjectField(env, this, pdsi_fdID, NULL);
 487                 } else {
 488                     /* socket was re-created */
 489                     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 490                 }
 491             }
 492             if (v6bind.ipv6_fd != fd1) {
 493                 fd1 = (int)v6bind.ipv6_fd;
 494                 if (fd1 == -1) {
 495                     /* socket is closed. */
 496                     (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL);
 497                 } else {
 498                     /* socket was re-created */
 499                     (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
 500                 }
 501             }
 502         } else {
 503             NET_ThrowCurrent (env, "Cannot bind");
 504             return;
 505         }
 506     } else {
 507         if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) {
 508             if (WSAGetLastError() == WSAEACCES) {
 509                 WSASetLastError(WSAEADDRINUSE);
 510             }
 511             NET_ThrowCurrent(env, "Cannot bind");
 512             return;
 513         }


1506     } else {
1507         fd =  (int) socket (AF_INET, SOCK_DGRAM, 0);
1508     }
1509     if (fd == JVM_IO_ERR) {
1510         NET_ThrowCurrent(env, "Socket creation failed");
1511         return;
1512     }
1513     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
1514     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
1515     NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
1516 
1517     if (ipv6_supported) {
1518         /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
1519          * returns connection reset errors un connected UDP sockets (as well
1520          * as connected sockets. The solution is to only enable this feature
1521          * when the socket is connected
1522          */
1523         t = FALSE;
1524         WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
1525         t = TRUE;
1526         fd1 = (int)socket (AF_INET6, SOCK_DGRAM, 0);
1527         if (fd1 == JVM_IO_ERR) {
1528             NET_ThrowCurrent(env, "Socket creation failed");
1529             return;
1530         }
1531         NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
1532         t = FALSE;
1533         WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
1534         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
1535         SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE);
1536     } else {
1537         /* drop the second fd */
1538         (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL);
1539     }
1540 }
1541 
1542 /*
1543  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1544  * Method:    datagramSocketClose
1545  * Signature: ()V
1546  */


1569 
1570     if (ipv6_supported && fd1Obj != NULL) {
1571         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
1572         if (fd1 == -1) {
1573             return;
1574         }
1575         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
1576         NET_SocketClose(fd1);
1577     }
1578 }
1579 
1580 /*
1581  * check the addresses attached to the NetworkInterface object
1582  * and return the first one (of the requested family Ipv4 or Ipv6)
1583  * in *iaddr
1584  */
1585 
1586 static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iaddr)
1587 {
1588     jobjectArray addrArray;


1589     jsize len;
1590     jobject addr;
1591     int i;
1592 












1593     addrArray = (*env)->GetObjectField(env, nif, ni_addrsID);
1594     len = (*env)->GetArrayLength(env, addrArray);
1595 
1596     /*
1597      * Check that there is at least one address bound to this
1598      * interface.
1599      */
1600     if (len < 1) {
1601         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1602             "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
1603         return -1;
1604     }
1605     for (i=0; i<len; i++) {
1606         int fam;
1607         addr = (*env)->GetObjectArrayElement(env, addrArray, i);
1608         fam = (*env)->GetIntField(env, addr, ia_familyID);
1609         if (fam == family) {
1610             *iaddr = addr;
1611             return 0;
1612         }
1613     }
1614     return -1;
1615 }
1616 
1617 static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr)
1618 {
1619     jobject addr;

1620 
1621     int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
1622     if (ret == -1) {
1623         return -1;
1624     }
1625 






1626     iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID));
1627     return 0;
1628 }
1629 
1630 /* Get the multicasting index from the interface */
1631 
1632 static int getIndexFromIf (JNIEnv *env, jobject nif) {









1633     return (*env)->GetIntField(env, nif, ni_indexID);
1634 }
1635 
1636 /*
1637  * Sets the multicast interface.
1638  *
1639  * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :-
1640  *      IPv4:   set outgoing multicast interface using
1641  *              IPPROTO_IP/IP_MULTICAST_IF
1642  *
1643  *      IPv6:   Get the interface to which the
1644  *              InetAddress is bound
1645  *              and do same as SockOptions.IF_MULTICAST_IF2
1646  *
1647  * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :-
1648  *      For each stack:
1649  *      IPv4:   Obtain IP address bound to network interface
1650  *              (NetworkInterface.addres[0])
1651  *              set outgoing multicast interface using
1652  *              IPPROTO_IP/IP_MULTICAST_IF
1653  *
1654  *      IPv6:   Obtain NetworkInterface.index
1655  *              Set outgoing multicast interface using
1656  *              IPPROTO_IPV6/IPV6_MULTICAST_IF
1657  *
1658  */
1659 static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1,
1660                                   jint opt, jobject value)
1661 {
1662     int ipv6_supported = ipv6_available();
1663 
1664     if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
1665         /*
1666          * value is an InetAddress.
1667          * On IPv4 system use IP_MULTICAST_IF socket option
1668          * On IPv6 system get the NetworkInterface that this IP
1669          * address is bound to and use the IPV6_MULTICAST_IF
1670          * option instead of IP_MULTICAST_IF
1671          */
1672         if (ipv6_supported) {








1673             value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value);
1674             if (value == NULL) {
1675                 if (!(*env)->ExceptionOccurred(env)) {
1676                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1677                          "bad argument for IP_MULTICAST_IF"
1678                          ": address not bound to any interface");
1679                 }
1680                 return;
1681             }
1682             opt = java_net_SocketOptions_IP_MULTICAST_IF2;
1683         } else {

1684             struct in_addr in;
1685 







1686             in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID));
1687 
1688             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1689                                (const char*)&in, sizeof(in)) < 0) {
1690                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1691                                  "Error setting socket option");
1692             }
1693             return;
1694         }
1695     }
1696 
1697     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
1698         /*
1699          * value is a NetworkInterface.
1700          * On IPv6 system get the index of the interface and use the
1701          * IPV6_MULTICAST_IF socket option
1702          * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF
1703          * option. For IPv6 both must be done.
1704          */
1705         if (ipv6_supported) {

1706             struct in_addr in;
1707             int index;
1708 






1709             index = (*env)->GetIntField(env, value, ni_indexID);
1710 
1711             if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1712                                (const char*)&index, sizeof(index)) < 0) {
1713                 if (errno == EINVAL && index > 0) {
1714                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1715                         "IPV6_MULTICAST_IF failed (interface has IPv4 "
1716                         "address only?)");
1717                 } else {
1718                     NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1719                                    "Error setting socket option");
1720                 }
1721                 return;
1722             }
1723 
1724             /* If there are any IPv4 addresses on this interface then
1725              * repeat the operation on the IPv4 fd */
1726 
1727             if (getInet4AddrFromIf (env, value, &in) < 0) {
1728                 return;


1794      * level(s) and option name(s).
1795      */
1796     if (fd1 != -1) {
1797         if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) {
1798             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1799             return;
1800         }
1801     }
1802     if (fd != -1) {
1803         if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) {
1804             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1805             return;
1806         }
1807     }
1808 
1809     switch (opt) {
1810         case java_net_SocketOptions_SO_SNDBUF :
1811         case java_net_SocketOptions_SO_RCVBUF :
1812         case java_net_SocketOptions_IP_TOS :
1813             {
1814                 optval.i = retrieveInteger(env, value);








1815                 optlen = sizeof(optval.i);
1816             }
1817             break;
1818 
1819         case java_net_SocketOptions_SO_REUSEADDR:
1820         case java_net_SocketOptions_SO_BROADCAST:
1821         case java_net_SocketOptions_IP_MULTICAST_LOOP:
1822             {
1823                 jboolean on = retrieveBoolean(env, value);









1824                 optval.i = (on ? 1 : 0);
1825                 /*
1826                  * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather
1827                  * than enabling it.
1828                  */
1829                 if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) {
1830                     optval.i = !optval.i;
1831                 }
1832                 optlen = sizeof(optval.i);
1833             }
1834             break;
1835 
1836         default :
1837             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1838                 "Socket option not supported by PlainDatagramSocketImp");
1839             break;
1840 
1841     }
1842 
1843     if (fd1 != -1) {


1869  *              If index > 0 query NetworkInterface by index
1870  *              and returns addrs[0]
1871  *
1872  * SocketOptions.IP_MULTICAST_IF2
1873  *      IPv4:   Query IPPROTO_IP/IP_MULTICAST_IF
1874  *              Query NetworkInterface by IP address and
1875  *              return the NetworkInterface that the address
1876  *              is bound too.
1877  *      IPv6:   Query IPPROTO_IPV6 / IPV6_MULTICAST_IF
1878  *              (except Linux .2 kernel)
1879  *              Query NetworkInterface by index and
1880  *              return NetworkInterface.
1881  */
1882 jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint opt) {
1883     jboolean isIPV4 = !ipv6_available() || fd1 == -1;
1884 
1885     /*
1886      * IPv4 implementation
1887      */
1888     if (isIPV4) {









1889         jobjectArray addrArray;
1890         jobject addr;
1891         jobject ni;
1892 
1893         struct in_addr in;
1894         struct in_addr *inP = &in;
1895         int len = sizeof(struct in_addr);
1896 
1897         if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1898                            (char *)inP, &len) < 0) {
1899             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1900                              "Error getting socket option");
1901             return NULL;
1902         }
1903 
1904         /*
1905          * Construct and populate an Inet4Address
1906          */
1907         addr = (*env)->NewObject(env, ia4_class, ia4_ctrID, 0);










1908         CHECK_NULL_RETURN(addr, NULL);
1909 
1910         (*env)->SetIntField(env, addr, ia_addressID, ntohl(in.s_addr));
1911 
1912         /*
1913          * For IP_MULTICAST_IF return InetAddress
1914          */
1915         if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
1916             return addr;
1917         }
1918 
1919         /*
1920          * For IP_MULTICAST_IF2 we get the NetworkInterface for
1921          * this address and return it
1922          */













1923         ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
1924         if (ni) {
1925             return ni;
1926         }
1927 
1928         /*
1929          * The address doesn't appear to be bound at any known
1930          * NetworkInterface. Therefore we construct a NetworkInterface
1931          * with this address.
1932          */
1933         ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
1934         CHECK_NULL_RETURN(ni, NULL);
1935 
1936         (*env)->SetIntField(env, ni, ni_indexID, -1);
1937         addrArray = (*env)->NewObjectArray(env, 1, ia4_class, NULL);
1938         CHECK_NULL_RETURN(addrArray, NULL);
1939         (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
1940         (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
1941         return ni;
1942     }
1943 
1944 
1945     /*
1946      * IPv6 implementation
1947      */
1948     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
1949         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
1950 





1951         static jmethodID ia_anyLocalAddressID;
1952 
1953         int index;
1954         int len = sizeof(index);
1955 
1956         jobjectArray addrArray;
1957         jobject addr;
1958         jobject ni;
1959 
1960         {
1961             if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1962                                (char*)&index, &len) < 0) {
1963                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1964                                "Error getting socket option");
1965                 return NULL;
1966             }
1967         }
1968 
1969         if (ia_anyLocalAddressID == NULL) {














1970             ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,
1971                                                              ia_class,
1972                                                              "anyLocalAddress",
1973                                                              "()Ljava/net/InetAddress;");
1974             CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL);


1975         }
1976 
1977         /*
1978          * If multicast to a specific interface then return the
1979          * interface (for IF2) or the any address on that interface
1980          * (for IF).
1981          */
1982         if (index > 0) {
1983             ni = Java_java_net_NetworkInterface_getByIndex0(env, ni_class,
1984                                                                    index);
1985             if (ni == NULL) {
1986                 char errmsg[255];
1987                 sprintf(errmsg,
1988                         "IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
1989                         index);
1990                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
1991                 return NULL;
1992             }
1993 
1994             /*