< prev index next >

src/java.base/unix/native/libnio/ch/Net.c

Print this page
rev 57536 : [mq]: Cleanup

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -39,88 +39,28 @@
 #include "net_util.h"
 #include "net_util_md.h"
 #include "nio_util.h"
 #include "nio.h"
 
-#ifdef _AIX
-#include <stdlib.h>
-#include <sys/utsname.h>
+/**
+ * Use MCAST_JOIN_GROUP/MCAST_BLOCK_SOURCE on platforms that support it.
+ */
+#if defined(__linux__) || defined(__solaris__)
+  #include "nio_multicast.h"
+  #define USE_MCAST_XXX  1
 #endif
 
 /**
- * IP_MULTICAST_ALL supported since 2.6.31 but may not be available at
- * build time.
+ * IP_MULTICAST_ALL supported since 2.6.31 (and glibc 2.15) but may not be
+ * available at build time.
  */
 #ifdef __linux__
   #ifndef IP_MULTICAST_ALL
     #define IP_MULTICAST_ALL    49
   #endif
 #endif
 
-/**
- * IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP may not be defined on OSX and AIX
- */
-#if defined(__APPLE__) || defined(_AIX)
-  #ifndef IPV6_ADD_MEMBERSHIP
-    #define IPV6_ADD_MEMBERSHIP     IPV6_JOIN_GROUP
-    #define IPV6_DROP_MEMBERSHIP    IPV6_LEAVE_GROUP
-  #endif
-#endif
-
-#define COPY_INET6_ADDRESS(env, source, target) \
-    (*env)->GetByteArrayRegion(env, source, 0, 16, target)
-
-/*
- * Copy IPv6 group, interface index, and IPv6 source address
- * into group_source_req structure.
- */
-static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
-                               jbyteArray source, struct group_source_req *req)
-{
-    struct sockaddr_in6* sin6;
-
-    req->gsr_interface = (uint32_t)index;
-
-    sin6 = (struct sockaddr_in6 *)&(req->gsr_group);
-    sin6->sin6_family = AF_INET6;
-    COPY_INET6_ADDRESS(env, group, (jbyte *)&(sin6->sin6_addr));
-
-    sin6 = (struct sockaddr_in6 *)&(req->gsr_source);
-    sin6->sin6_family = AF_INET6;
-    COPY_INET6_ADDRESS(env, source, (jbyte *)&(sin6->sin6_addr));
-}
-
-#ifdef _AIX
-
-/*
- * Checks whether or not "socket extensions for multicast source filters" is supported.
- * Returns JNI_TRUE if it is supported, JNI_FALSE otherwise
- */
-static jboolean isSourceFilterSupported(){
-    static jboolean alreadyChecked = JNI_FALSE;
-    static jboolean result = JNI_TRUE;
-    if (alreadyChecked != JNI_TRUE){
-        struct utsname uts;
-        memset(&uts, 0, sizeof(uts));
-        strcpy(uts.sysname, "?");
-        const int utsRes = uname(&uts);
-        int major = -1;
-        int minor = -1;
-        major = atoi(uts.version);
-        minor = atoi(uts.release);
-        if (strcmp(uts.sysname, "AIX") == 0) {
-            if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1
-                result = JNI_FALSE;
-            }
-        }
-        alreadyChecked = JNI_TRUE;
-    }
-    return result;
-}
-
-#endif  /* _AIX */
-
 static jclass isa_class;        /* java.net.InetSocketAddress */
 static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
 
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)

@@ -181,14 +121,14 @@
 
 JNIEXPORT jboolean JNICALL
 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
 {
 #if defined(__APPLE__) || defined(__solaris__)
-    /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
+    /* IPv6 sockets use IPPROTO_IPV6 level options to join IPv4 multicast groups */
     return JNI_TRUE;
 #else
-    /* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */
+    /* IPv6 sockets use IPPROTO_IP level options to join IPv4 multicast groups */
     return JNI_FALSE;
 #endif
 }
 
 JNIEXPORT jboolean JNICALL

@@ -554,153 +494,146 @@
     }
 }
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
-                                jint group, jint interf, jint source)
+                                jint group, jint index, jint infAddress, jint source)
 {
-    struct ip_mreq mreq;
-    struct ip_mreq_source mreq_source;
-    int opt, n, optlen;
-    void* optval;
-
+    int n;
+    int fd = fdval(env, fdo);
+    #ifdef USE_MCAST_XXX
     if (source == 0) {
-        mreq.imr_multiaddr.s_addr = htonl(group);
-        mreq.imr_interface.s_addr = htonl(interf);
-        opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
-        optval = (void*)&mreq;
-        optlen = sizeof(mreq);
+            int opt = (join) ? MCAST_JOIN_GROUP  : MCAST_LEAVE_GROUP;
+            struct group_req req;
+            initGroupReq4(env, &req, index, group);
+            n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&req, sizeof(req));
     } else {
-
-#ifdef _AIX
-        /* check AIX for support of source filtering */
-        if (isSourceFilterSupported() != JNI_TRUE){
-            return IOS_UNAVAILABLE;
+            int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
+            struct group_source_req req;
+            initGroupSourceReq4(env, &req, index, group, source);
+            n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&req, sizeof(req));
         }
-#endif
-
+    #else
+        if (source == 0) {
+            int opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
+            struct ip_mreq mreq;
+            mreq.imr_multiaddr.s_addr = htonl(group);
+            mreq.imr_interface.s_addr = htonl(infAddress);
+            n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&mreq, sizeof(mreq));
+        } else {
+            int opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
+            struct ip_mreq_source mreq_source;
         mreq_source.imr_multiaddr.s_addr = htonl(group);
+            mreq_source.imr_interface.s_addr = htonl(infAddress);
         mreq_source.imr_sourceaddr.s_addr = htonl(source);
-        mreq_source.imr_interface.s_addr = htonl(interf);
-        opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
-        optval = (void*)&mreq_source;
-        optlen = sizeof(mreq_source);
+            n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&mreq_source, sizeof(mreq_source));
     }
-
-    n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
-    if (n < 0) {
-        if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
-            return IOS_UNAVAILABLE;
+    #endif
+    if (n == -1) {
         handleSocketError(env, errno);
     }
     return 0;
 }
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
-                                    jint group, jint interf, jint source)
+                                    jint group, jint index, jint infAddress, jint source)
 {
-#ifdef __APPLE__
-    /* no IPv4 exclude-mode filtering for now */
+    #if defined(__APPLE__)
+        /* no IPv4 exclude-mode filtering on this platform */
     return IOS_UNAVAILABLE;
-#else
-    struct ip_mreq_source mreq_source;
+    #else
     int n;
+        int fd = fdval(env, fdo);
+        #if USE_MCAST_XXX
+            int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
+            struct group_source_req req;
+            initGroupSourceReq4(env, &req, index, group, source);
+            n = setsockopt(fd, IPPROTO_IP, opt, (const char*)&req, sizeof(req));
+        #else
     int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
-
-#ifdef _AIX
-    /* check AIX for support of source filtering */
-    if (isSourceFilterSupported() != JNI_TRUE){
-        return IOS_UNAVAILABLE;
-    }
-#endif
-
+            struct ip_mreq_source mreq_source;
     mreq_source.imr_multiaddr.s_addr = htonl(group);
+            mreq_source.imr_interface.s_addr = htonl(infAddress);
     mreq_source.imr_sourceaddr.s_addr = htonl(source);
-    mreq_source.imr_interface.s_addr = htonl(interf);
-
-    n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
-                   (void*)&mreq_source, sizeof(mreq_source));
-    if (n < 0) {
-        if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
-            return IOS_UNAVAILABLE;
+            n = setsockopt(fd, IPPROTO_IP, opt, (void*)&mreq_source, sizeof(mreq_source));
+        #endif
+        if (n == -1) {
         handleSocketError(env, errno);
     }
     return 0;
-#endif
+    #endif
 }
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
                                 jbyteArray group, jint index, jbyteArray source)
 {
-    struct ipv6_mreq mreq6;
+    int n;
+    int fd = fdval(env, fdo);
+    #ifdef USE_MCAST_XXX
+        if (source == NULL) {
+            int opt = (join) ? MCAST_JOIN_GROUP  : MCAST_LEAVE_GROUP;
+            struct group_req req;
+            initGroupReq6(env, &req, index, group);
+            n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&req, sizeof(req));
+        } else {
+            int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
     struct group_source_req req;
-    int opt, n, optlen;
-    void* optval;
-
+            initGroupSourceReq6(env, &req, index, group, source);
+            n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&req, sizeof(req));
+        }
+    #else
+        #ifndef IPV6_ADD_MEMBERSHIP
+            #define IPV6_ADD_MEMBERSHIP     IPV6_JOIN_GROUP
+            #define IPV6_DROP_MEMBERSHIP    IPV6_LEAVE_GROUP
+        #endif
     if (source == NULL) {
-        COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
+            int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
+            struct ipv6_mreq mreq6;
         mreq6.ipv6mr_interface = (int)index;
-        opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
-        optval = (void*)&mreq6;
-        optlen = sizeof(mreq6);
+            (*env)->GetByteArrayRegion(env, group, 0, 16, (jbyte*)&(mreq6.ipv6mr_multiaddr));
+            n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&mreq6, sizeof(mreq6));
     } else {
-#ifdef __APPLE__
-        /* no IPv6 include-mode filtering for now */
+            /* no IPv6 include-mode filtering */
         return IOS_UNAVAILABLE;
-#else
-        initGroupSourceReq(env, group, index, source, &req);
-        opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
-        optval = (void*)&req;
-        optlen = sizeof(req);
-#endif
     }
-
-    n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
-    if (n < 0) {
-        if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
-            return IOS_UNAVAILABLE;
+    #endif
+    if (n == -1) {
         handleSocketError(env, errno);
     }
     return 0;
 }
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
                                     jbyteArray group, jint index, jbyteArray source)
 {
-#ifdef __APPLE__
-    /* no IPv6 exclude-mode filtering for now */
-    return IOS_UNAVAILABLE;
-#else
-    struct group_source_req req;
+    #ifdef USE_MCAST_XXX
     int n;
     int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
-
-    initGroupSourceReq(env, group, index, source, &req);
-
-    n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
-        (void*)&req, sizeof(req));
-    if (n < 0) {
-        if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
-            return IOS_UNAVAILABLE;
+        struct group_source_req req;
+        initGroupSourceReq6(env, &req, index, group, source);
+        n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req));
+        if (n == -1) {
         handleSocketError(env, errno);
     }
     return 0;
-#endif
+    #else
+        /* no IPv6 exclude-mode filtering */
+        return IOS_UNAVAILABLE;
+    #endif
 }
 
 JNIEXPORT void JNICALL
-Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
+Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint infAddress)
 {
     struct in_addr in;
     socklen_t arglen = sizeof(struct in_addr);
     int n;
 
-    in.s_addr = htonl(interf);
-
+    in.s_addr = htonl(infAddress);
     n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
                    (void*)&(in.s_addr), arglen);
     if (n < 0) {
         handleSocketError(env, errno);
     }
< prev index next >