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

Print this page




 318     }
 319     return portUnreachableSupported;
 320 }
 321 
 322 /*
 323  * This function "purges" all outstanding ICMP port unreachable packets
 324  * outstanding on a socket and returns JNI_TRUE if any ICMP messages
 325  * have been purged. The rational for purging is to emulate normal BSD
 326  * behaviour whereby receiving a "connection reset" status resets the
 327  * socket.
 328  */
 329 static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd)
 330 {
 331     jboolean got_icmp = JNI_FALSE;
 332     char buf[1];
 333     fd_set tbl;
 334     struct timeval t = { 0, 0 };
 335     struct sockaddr_in rmtaddr;
 336     int addrlen = sizeof(rmtaddr);
 337 


 338     /*
 339      * A no-op if this OS doesn't support it.
 340      */
 341     if (!supportPortUnreachable()) {
 342         return JNI_FALSE;
 343     }
 344 
 345     /*
 346      * Peek at the queue to see if there is an ICMP port unreachable. If there
 347      * is then receive it.
 348      */
 349     FD_ZERO(&tbl);
 350     FD_SET(fd, &tbl);
 351     while(1) {
 352         if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
 353             break;
 354         }
 355         if (recvfrom(fd, buf, 1, MSG_PEEK,
 356                          (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) {
 357             break;


 414     ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz);
 415     CHECK_NULL(ia4_clazz);
 416     ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V");
 417     CHECK_NULL(ia4_ctor);
 418 
 419 
 420     InitializeCriticalSection(&sizeCheckLock);
 421 }
 422 
 423 JNIEXPORT void JNICALL
 424 Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
 425                                            jint port, jobject addressObj,
 426                                            jboolean exclBind) {
 427     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 428     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 429 
 430     int fd, fd1, family;
 431     int ipv6_supported = ipv6_available();
 432 
 433     SOCKETADDRESS lcladdr;
 434     int lcladdrlen;
 435     int address;
 436 


 437     family = getInetAddress_family(env, addressObj);
 438     if (family == IPv6 && !ipv6_supported) {
 439         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 440                         "Protocol family not supported");
 441         return;
 442     }
 443 
 444     if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
 445         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
 446         return;
 447     } else {
 448         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 449         if (ipv6_supported) {
 450             fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
 451         }
 452     }
 453     if (IS_NULL(addressObj)) {
 454         JNU_ThrowNullPointerException(env, "argument address");
 455         return;
 456     } else {


 600     /* The object's field */
 601     jobject fdObj;
 602     /* The fdObj'fd */
 603     jint fd, len;
 604     SOCKETADDRESS addr;
 605 
 606     if (family == IPv4) {
 607         fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 608         len = sizeof (struct sockaddr_in);
 609     } else {
 610         fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 611         len = sizeof (struct SOCKADDR_IN6);
 612     }
 613 
 614     if (IS_NULL(fdObj)) {
 615         /* disconnect doesn't throw any exceptions */
 616         return;
 617     }
 618     fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 619 
 620     memset(&addr, 0, len);
 621     connect(fd, (struct sockaddr *)&addr, len);
 622 
 623     /*
 624      * use SIO_UDP_CONNRESET
 625      * to disable ICMP port unreachable handling here.
 626      */
 627     if (xp_or_later) {
 628         DWORD x1, x2; /* ignored result codes */
 629         int t = FALSE;
 630         WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
 631     }
 632 }
 633 
 634 /*
 635  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
 636  * Method:    send
 637  * Signature: (Ljava/net/DatagramPacket;)V
 638  */
 639 JNIEXPORT void JNICALL
 640 Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
 641                                            jobject packet) {
 642 
 643     char BUF[MAX_BUFFER_LEN];
 644     char *fullPacket;
 645     jobject fdObj;
 646     jint fd;
 647 
 648     jobject iaObj;
 649     jint address;
 650     jint family;
 651 
 652     jint packetBufferOffset, packetBufferLen, packetPort;
 653     jbyteArray packetBuffer;
 654     jboolean connected;
 655 
 656     SOCKETADDRESS rmtaddr;
 657     SOCKETADDRESS *addrp = &rmtaddr;
 658     int addrlen;
 659 

 660 
 661     if (IS_NULL(packet)) {
 662         JNU_ThrowNullPointerException(env, "null packet");
 663         return;
 664     }
 665 
 666     iaObj = (*env)->GetObjectField(env, packet, dp_addressID);
 667 
 668     packetPort = (*env)->GetIntField(env, packet, dp_portID);
 669     packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
 670     packetBuffer = (jbyteArray)(*env)->GetObjectField(env, packet, dp_bufID);
 671     connected = (*env)->GetBooleanField(env, this, pdsi_connected);
 672 
 673     if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) {
 674         JNU_ThrowNullPointerException(env, "null address || null buffer");
 675         return;
 676     }
 677 
 678     family = getInetAddress_family(env, iaObj);
 679     if (family == IPv4) {


1427         /* check to see if it's because the buffer was too small */
1428         if (errorCode == WSAEMSGSIZE) {
1429             /* it is because the buffer is too small. It's UDP, it's
1430              * unreliable, it's all good. discard the rest of the
1431              * data..
1432              */
1433             n = packetBufferLen;
1434         } else {
1435             /* failure */
1436             (*env)->SetIntField(env, packet, dp_lengthID, 0);
1437         }
1438     }
1439     if (n == -1) {
1440         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
1441     } else if (n == -2) {
1442         JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
1443                         "operation interrupted");
1444     } else if (n < 0) {
1445         NET_ThrowCurrent(env, "Datagram receive failed");
1446     } else {
1447         int port;
1448         jobject packetAddress;
1449 
1450         /*
1451          * Check if there is an InetAddress already associated with this
1452          * packet. If so we check if it is the same source address. We
1453          * can't update any existing InetAddress because it is immutable
1454          */
1455         packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
1456 
1457         if (packetAddress != NULL) {
1458             if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) {
1459                 /* force a new InetAddress to be created */
1460                 packetAddress = NULL;
1461             }
1462         }
1463         if (packetAddress == NULL) {
1464             packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
1465             /* stuff the new Inetaddress in the packet */
1466             (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
1467         } else {


1805             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1806                                (const char*)&in, sizeof(in)) < 0) {
1807                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1808                                "Error setting socket option");
1809             }
1810             return;
1811         }
1812     }
1813 }
1814 
1815 /*
1816  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1817  * Method:    socketNativeSetOption
1818  * Signature: (ILjava/lang/Object;)V
1819  */
1820 JNIEXPORT void JNICALL
1821 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
1822                                                       jint opt,jobject value) {
1823 
1824     int fd=-1, fd1=-1;
1825     int levelv4, levelv6, optnamev4, optnamev6, optlen;
1826     union {
1827         int i;
1828         char c;
1829     } optval;
1830     int ipv6_supported = ipv6_available();
1831     fd = getFD(env, this);
1832 
1833     if (ipv6_supported) {
1834         fd1 = getFD1(env, this);
1835     }
1836     if (fd < 0 && fd1 < 0) {
1837         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
1838         return;
1839     }
1840 
1841     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
1842         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
1843 
1844         setMulticastInterface(env, this, fd, fd1, opt, value);
1845         return;
1846     }
1847 
1848     /*
1849      * Map the Java level socket option to the platform specific


2176     }
2177     return NULL;
2178 }
2179 
2180 
2181 /*
2182  * Returns relevant info as a jint.
2183  *
2184  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
2185  * Method:    socketGetOption
2186  * Signature: (I)Ljava/lang/Object;
2187  */
2188 JNIEXPORT jobject JNICALL
2189 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
2190                                                       jint opt) {
2191 
2192     int fd=-1, fd1=-1;
2193     int level, optname, optlen;
2194     union {
2195         int i;
2196     } optval;
2197     int ipv6_supported = ipv6_available();
2198 
2199     fd = getFD(env, this);
2200     if (ipv6_supported) {
2201         fd1 = getFD1(env, this);
2202     }
2203 
2204     if (fd < 0 && fd1 < 0) {
2205         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2206                         "Socket closed");
2207         return NULL;
2208     }
2209 
2210     /*
2211      * Handle IP_MULTICAST_IF separately
2212      */
2213     if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
2214         opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
2215         return getMulticastInterface(env, this, fd, fd1, opt);
2216     }


2427 
2428     return (jbyte)result;
2429 }
2430 
2431 /* join/leave the named group on the named interface, or if no interface specified
2432  * then the interface set with setInterfac(), or the default interface otherwise */
2433 
2434 static void mcast_join_leave(JNIEnv *env, jobject this,
2435                              jobject iaObj, jobject niObj,
2436                              jboolean join)
2437 {
2438     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
2439     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
2440     jint fd = -1, fd1 = -1;
2441 
2442     SOCKETADDRESS name;
2443     struct ip_mreq mname;
2444     struct ipv6_mreq mname6;
2445 
2446     struct in_addr in;
2447     DWORD ifindex;
2448 
2449     int len, family;
2450     int ipv6_supported = ipv6_available();
2451     int cmd ;
2452 



2453     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
2454         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2455                         "Socket closed");
2456         return;
2457     }
2458     if (!IS_NULL(fdObj)) {
2459         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
2460     }
2461     if (ipv6_supported && !IS_NULL(fd1Obj)) {
2462         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
2463     }
2464 
2465     if (IS_NULL(iaObj)) {
2466         JNU_ThrowNullPointerException(env, "address");
2467         return;
2468     }
2469 
2470     if (NET_InetAddressToSockaddr(env, iaObj, 0, (struct sockaddr *)&name, &len, JNI_FALSE) != 0) {
2471       return;
2472     }




 318     }
 319     return portUnreachableSupported;
 320 }
 321 
 322 /*
 323  * This function "purges" all outstanding ICMP port unreachable packets
 324  * outstanding on a socket and returns JNI_TRUE if any ICMP messages
 325  * have been purged. The rational for purging is to emulate normal BSD
 326  * behaviour whereby receiving a "connection reset" status resets the
 327  * socket.
 328  */
 329 static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd)
 330 {
 331     jboolean got_icmp = JNI_FALSE;
 332     char buf[1];
 333     fd_set tbl;
 334     struct timeval t = { 0, 0 };
 335     struct sockaddr_in rmtaddr;
 336     int addrlen = sizeof(rmtaddr);
 337 
 338     memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
 339 
 340     /*
 341      * A no-op if this OS doesn't support it.
 342      */
 343     if (!supportPortUnreachable()) {
 344         return JNI_FALSE;
 345     }
 346 
 347     /*
 348      * Peek at the queue to see if there is an ICMP port unreachable. If there
 349      * is then receive it.
 350      */
 351     FD_ZERO(&tbl);
 352     FD_SET(fd, &tbl);
 353     while(1) {
 354         if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
 355             break;
 356         }
 357         if (recvfrom(fd, buf, 1, MSG_PEEK,
 358                          (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) {
 359             break;


 416     ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz);
 417     CHECK_NULL(ia4_clazz);
 418     ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V");
 419     CHECK_NULL(ia4_ctor);
 420 
 421 
 422     InitializeCriticalSection(&sizeCheckLock);
 423 }
 424 
 425 JNIEXPORT void JNICALL
 426 Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
 427                                            jint port, jobject addressObj,
 428                                            jboolean exclBind) {
 429     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 430     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 431 
 432     int fd, fd1, family;
 433     int ipv6_supported = ipv6_available();
 434 
 435     SOCKETADDRESS lcladdr;
 436     int lcladdrlen = sizeof(lcladdr);
 437     int address;
 438 
 439     memset((char *)&lcladdr, 0, sizeof(lcladdr));
 440 
 441     family = getInetAddress_family(env, addressObj);
 442     if (family == IPv6 && !ipv6_supported) {
 443         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 444                         "Protocol family not supported");
 445         return;
 446     }
 447 
 448     if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
 449         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
 450         return;
 451     } else {
 452         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 453         if (ipv6_supported) {
 454             fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
 455         }
 456     }
 457     if (IS_NULL(addressObj)) {
 458         JNU_ThrowNullPointerException(env, "argument address");
 459         return;
 460     } else {


 604     /* The object's field */
 605     jobject fdObj;
 606     /* The fdObj'fd */
 607     jint fd, len;
 608     SOCKETADDRESS addr;
 609 
 610     if (family == IPv4) {
 611         fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
 612         len = sizeof (struct sockaddr_in);
 613     } else {
 614         fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 615         len = sizeof (struct SOCKADDR_IN6);
 616     }
 617 
 618     if (IS_NULL(fdObj)) {
 619         /* disconnect doesn't throw any exceptions */
 620         return;
 621     }
 622     fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 623 
 624     memset((char *)&addr, 0, len);
 625     connect(fd, (struct sockaddr *)&addr, len);
 626 
 627     /*
 628      * use SIO_UDP_CONNRESET
 629      * to disable ICMP port unreachable handling here.
 630      */
 631     if (xp_or_later) {
 632         DWORD x1 = 0, x2 = 0; /* ignored result codes */
 633         int t = FALSE;
 634         WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
 635     }
 636 }
 637 
 638 /*
 639  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
 640  * Method:    send
 641  * Signature: (Ljava/net/DatagramPacket;)V
 642  */
 643 JNIEXPORT void JNICALL
 644 Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
 645                                            jobject packet) {
 646 
 647     char BUF[MAX_BUFFER_LEN];
 648     char *fullPacket;
 649     jobject fdObj;
 650     jint fd;
 651 
 652     jobject iaObj;
 653     jint address;
 654     jint family;
 655 
 656     jint packetBufferOffset, packetBufferLen, packetPort;
 657     jbyteArray packetBuffer;
 658     jboolean connected;
 659 
 660     SOCKETADDRESS rmtaddr;
 661     SOCKETADDRESS *addrp = &rmtaddr;
 662     int addrlen = 0;
 663 
 664     memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
 665 
 666     if (IS_NULL(packet)) {
 667         JNU_ThrowNullPointerException(env, "null packet");
 668         return;
 669     }
 670 
 671     iaObj = (*env)->GetObjectField(env, packet, dp_addressID);
 672 
 673     packetPort = (*env)->GetIntField(env, packet, dp_portID);
 674     packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
 675     packetBuffer = (jbyteArray)(*env)->GetObjectField(env, packet, dp_bufID);
 676     connected = (*env)->GetBooleanField(env, this, pdsi_connected);
 677 
 678     if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) {
 679         JNU_ThrowNullPointerException(env, "null address || null buffer");
 680         return;
 681     }
 682 
 683     family = getInetAddress_family(env, iaObj);
 684     if (family == IPv4) {


1432         /* check to see if it's because the buffer was too small */
1433         if (errorCode == WSAEMSGSIZE) {
1434             /* it is because the buffer is too small. It's UDP, it's
1435              * unreliable, it's all good. discard the rest of the
1436              * data..
1437              */
1438             n = packetBufferLen;
1439         } else {
1440             /* failure */
1441             (*env)->SetIntField(env, packet, dp_lengthID, 0);
1442         }
1443     }
1444     if (n == -1) {
1445         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
1446     } else if (n == -2) {
1447         JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
1448                         "operation interrupted");
1449     } else if (n < 0) {
1450         NET_ThrowCurrent(env, "Datagram receive failed");
1451     } else {
1452         int port = 0;
1453         jobject packetAddress;
1454 
1455         /*
1456          * Check if there is an InetAddress already associated with this
1457          * packet. If so we check if it is the same source address. We
1458          * can't update any existing InetAddress because it is immutable
1459          */
1460         packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
1461 
1462         if (packetAddress != NULL) {
1463             if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) {
1464                 /* force a new InetAddress to be created */
1465                 packetAddress = NULL;
1466             }
1467         }
1468         if (packetAddress == NULL) {
1469             packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
1470             /* stuff the new Inetaddress in the packet */
1471             (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
1472         } else {


1810             if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
1811                                (const char*)&in, sizeof(in)) < 0) {
1812                 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1813                                "Error setting socket option");
1814             }
1815             return;
1816         }
1817     }
1818 }
1819 
1820 /*
1821  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
1822  * Method:    socketNativeSetOption
1823  * Signature: (ILjava/lang/Object;)V
1824  */
1825 JNIEXPORT void JNICALL
1826 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
1827                                                       jint opt,jobject value) {
1828 
1829     int fd=-1, fd1=-1;
1830     int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
1831     union {
1832         int i;
1833         char c;
1834     } optval = { 0 };
1835     int ipv6_supported = ipv6_available();
1836     fd = getFD(env, this);
1837 
1838     if (ipv6_supported) {
1839         fd1 = getFD1(env, this);
1840     }
1841     if (fd < 0 && fd1 < 0) {
1842         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
1843         return;
1844     }
1845 
1846     if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
1847         (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
1848 
1849         setMulticastInterface(env, this, fd, fd1, opt, value);
1850         return;
1851     }
1852 
1853     /*
1854      * Map the Java level socket option to the platform specific


2181     }
2182     return NULL;
2183 }
2184 
2185 
2186 /*
2187  * Returns relevant info as a jint.
2188  *
2189  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
2190  * Method:    socketGetOption
2191  * Signature: (I)Ljava/lang/Object;
2192  */
2193 JNIEXPORT jobject JNICALL
2194 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
2195                                                       jint opt) {
2196 
2197     int fd=-1, fd1=-1;
2198     int level, optname, optlen;
2199     union {
2200         int i;
2201     } optval = {0};
2202     int ipv6_supported = ipv6_available();
2203 
2204     fd = getFD(env, this);
2205     if (ipv6_supported) {
2206         fd1 = getFD1(env, this);
2207     }
2208 
2209     if (fd < 0 && fd1 < 0) {
2210         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2211                         "Socket closed");
2212         return NULL;
2213     }
2214 
2215     /*
2216      * Handle IP_MULTICAST_IF separately
2217      */
2218     if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
2219         opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
2220         return getMulticastInterface(env, this, fd, fd1, opt);
2221     }


2432 
2433     return (jbyte)result;
2434 }
2435 
2436 /* join/leave the named group on the named interface, or if no interface specified
2437  * then the interface set with setInterfac(), or the default interface otherwise */
2438 
2439 static void mcast_join_leave(JNIEnv *env, jobject this,
2440                              jobject iaObj, jobject niObj,
2441                              jboolean join)
2442 {
2443     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
2444     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
2445     jint fd = -1, fd1 = -1;
2446 
2447     SOCKETADDRESS name;
2448     struct ip_mreq mname;
2449     struct ipv6_mreq mname6;
2450 
2451     struct in_addr in;
2452     DWORD ifindex = 0;
2453 
2454     int len, family;
2455     int ipv6_supported = ipv6_available();
2456     int cmd ;
2457 
2458     memset((char *)&in, 0, sizeof(in));
2459     memset((char *)&name, 0, sizeof(name));
2460 
2461     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
2462         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
2463                         "Socket closed");
2464         return;
2465     }
2466     if (!IS_NULL(fdObj)) {
2467         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
2468     }
2469     if (ipv6_supported && !IS_NULL(fd1Obj)) {
2470         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
2471     }
2472 
2473     if (IS_NULL(iaObj)) {
2474         JNU_ThrowNullPointerException(env, "address");
2475         return;
2476     }
2477 
2478     if (NET_InetAddressToSockaddr(env, iaObj, 0, (struct sockaddr *)&name, &len, JNI_FALSE) != 0) {
2479       return;
2480     }