jdk/src/solaris/native/sun/nio/ch/Net.c
changeset 1152 29d6145d1097
parent 895 67f1dc69ad10
child 1247 b4c26443dee5
equal deleted inserted replaced
1151:4070cecdb99d 1152:29d6145d1097
    35 #include "jlong.h"
    35 #include "jlong.h"
    36 #include "sun_nio_ch_Net.h"
    36 #include "sun_nio_ch_Net.h"
    37 #include "net_util.h"
    37 #include "net_util.h"
    38 #include "net_util_md.h"
    38 #include "net_util_md.h"
    39 #include "nio_util.h"
    39 #include "nio_util.h"
    40 #include "java_net_SocketOptions.h"
       
    41 #include "nio.h"
    40 #include "nio.h"
    42 
    41 
       
    42 /**
       
    43  * Definitions for source-specific multicast to allow for building
       
    44  * with older header files.
       
    45  */
       
    46 
       
    47 #ifdef __solaris__
       
    48 
       
    49 #ifndef IP_BLOCK_SOURCE
       
    50 
       
    51 #define IP_BLOCK_SOURCE                 0x15
       
    52 #define IP_UNBLOCK_SOURCE               0x16
       
    53 #define IP_ADD_SOURCE_MEMBERSHIP        0x17
       
    54 #define IP_DROP_SOURCE_MEMBERSHIP       0x18
       
    55 
       
    56 #define MCAST_BLOCK_SOURCE              0x2b
       
    57 #define MCAST_UNBLOCK_SOURCE            0x2c
       
    58 #define MCAST_JOIN_SOURCE_GROUP         0x2d
       
    59 #define MCAST_LEAVE_SOURCE_GROUP        0x2e
       
    60 
       
    61 #endif  /* IP_BLOCK_SOURCE */
       
    62 
       
    63 struct my_ip_mreq_source {
       
    64         struct in_addr  imr_multiaddr;
       
    65         struct in_addr  imr_sourceaddr;
       
    66         struct in_addr  imr_interface;
       
    67 };
       
    68 
       
    69 /*
       
    70  * Use #pragma pack() construct to force 32-bit alignment on amd64.
       
    71  */
       
    72 #if defined(amd64)
       
    73 #pragma pack(4)
       
    74 #endif
       
    75 
       
    76 struct my_group_source_req {
       
    77         uint32_t                gsr_interface;  /* interface index */
       
    78         struct sockaddr_storage gsr_group;      /* group address */
       
    79         struct sockaddr_storage gsr_source;     /* source address */
       
    80 };
       
    81 
       
    82 #if defined(amd64)
       
    83 #pragma pack()
       
    84 #endif
       
    85 
       
    86 #endif  /* __solaris__ */
       
    87 
       
    88 
    43 #ifdef __linux__
    89 #ifdef __linux__
    44 #include <sys/utsname.h>
    90 
    45 
    91 #ifndef IP_BLOCK_SOURCE
    46 #define IPV6_MULTICAST_IF 17
    92 
    47 #ifndef SO_BSDCOMPAT
    93 #define IP_BLOCK_SOURCE                 38
    48 #define SO_BSDCOMPAT  14
    94 #define IP_UNBLOCK_SOURCE               37
    49 #endif
    95 #define IP_ADD_SOURCE_MEMBERSHIP        39
    50 #endif
    96 #define IP_DROP_SOURCE_MEMBERSHIP       40
       
    97 
       
    98 #define MCAST_BLOCK_SOURCE              43
       
    99 #define MCAST_UNBLOCK_SOURCE            44
       
   100 #define MCAST_JOIN_SOURCE_GROUP         42
       
   101 #define MCAST_LEAVE_SOURCE_GROUP        45
       
   102 
       
   103 #endif  /* IP_BLOCK_SOURCE */
       
   104 
       
   105 struct my_ip_mreq_source {
       
   106         struct in_addr  imr_multiaddr;
       
   107         struct in_addr  imr_interface;
       
   108         struct in_addr  imr_sourceaddr;
       
   109 };
       
   110 
       
   111 struct my_group_source_req {
       
   112         uint32_t                gsr_interface;  /* interface index */
       
   113         struct sockaddr_storage gsr_group;      /* group address */
       
   114         struct sockaddr_storage gsr_source;     /* source address */
       
   115 };
       
   116 
       
   117 #endif   /* __linux__ */
       
   118 
       
   119 
       
   120 #define COPY_INET6_ADDRESS(env, source, target) \
       
   121     (*env)->GetByteArrayRegion(env, source, 0, 16, target)
       
   122 
       
   123 /*
       
   124  * Copy IPv6 group, interface index, and IPv6 source address
       
   125  * into group_source_req structure.
       
   126  */
       
   127 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
       
   128                                jbyteArray source, struct my_group_source_req* req)
       
   129 {
       
   130     struct sockaddr_in6* sin6;
       
   131 
       
   132     req->gsr_interface = (uint32_t)index;
       
   133 
       
   134     sin6 = (struct sockaddr_in6*)&(req->gsr_group);
       
   135     sin6->sin6_family = AF_INET6;
       
   136     COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
       
   137 
       
   138     sin6 = (struct sockaddr_in6*)&(req->gsr_source);
       
   139     sin6->sin6_family = AF_INET6;
       
   140     COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
       
   141 }
       
   142 
    51 
   143 
    52 JNIEXPORT void JNICALL
   144 JNIEXPORT void JNICALL
    53 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
   145 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
    54 {
   146 {
    55     /* Here because Windows native code does need to init IDs */
   147     /* Here because Windows native code does need to init IDs */
    56 }
   148 }
    57 
   149 
       
   150 JNIEXPORT jboolean JNICALL
       
   151 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
       
   152 {
       
   153     return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
       
   154 }
       
   155 
    58 JNIEXPORT int JNICALL
   156 JNIEXPORT int JNICALL
    59 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
   157 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
    60                             jboolean reuse)
   158                             jboolean stream, jboolean reuse)
    61 {
   159 {
    62     int fd;
   160     int fd;
    63 
   161     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
    64 #ifdef AF_INET6
   162     int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
    65     if (ipv6_available())
   163 
    66         fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
   164     fd = socket(domain, type, 0);
    67     else
       
    68 #endif /* AF_INET6 */
       
    69         fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
       
    70 
       
    71     if (fd < 0) {
   165     if (fd < 0) {
    72         return handleSocketError(env, errno);
   166         return handleSocketError(env, errno);
    73     }
   167     }
    74     if (reuse) {
   168     if (reuse) {
    75         int arg = 1;
   169         int arg = 1;
    76         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
   170         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
    77                            sizeof(arg)) < 0) {
   171                        sizeof(arg)) < 0) {
    78             JNU_ThrowByNameWithLastError(env,
   172             JNU_ThrowByNameWithLastError(env,
    79                                          JNU_JAVANETPKG "SocketException",
   173                                          JNU_JAVANETPKG "SocketException",
    80                                          "sun.nio.ch.Net.setIntOption");
   174                                          "sun.nio.ch.Net.setIntOption");
       
   175             close(fd);
       
   176             return -1;
    81         }
   177         }
    82     }
   178     }
       
   179 #ifdef __linux__
       
   180     /* By default, Linux uses the route default */
       
   181     if (domain == AF_INET6 && type == SOCK_DGRAM) {
       
   182         int arg = 1;
       
   183         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
       
   184                        sizeof(arg)) < 0) {
       
   185             JNU_ThrowByNameWithLastError(env,
       
   186                                          JNU_JAVANETPKG "SocketException",
       
   187                                          "sun.nio.ch.Net.setIntOption");
       
   188             close(fd);
       
   189             return -1;
       
   190         }
       
   191     }
       
   192 #endif
    83     return fd;
   193     return fd;
    84 }
   194 }
    85 
   195 
    86 JNIEXPORT void JNICALL
   196 JNIEXPORT void JNICALL
    87 Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
   197 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
    88                          jobject fdo, jobject ia, int port)
   198                           jobject fdo, jobject iao, int port)
    89 {
   199 {
    90     SOCKADDR sa;
   200     SOCKADDR sa;
    91     int sa_len = SOCKADDR_LEN;
   201     int sa_len = SOCKADDR_LEN;
    92     int rv = 0;
   202     int rv = 0;
    93 
   203 
    94     if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) {
   204     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
    95       return;
   205       return;
    96     }
   206     }
    97 
   207 
    98     rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   208     rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
    99     if (rv != 0) {
   209     if (rv != 0) {
   100         handleSocketError(env, errno);
   210         handleSocketError(env, errno);
   101     }
   211     }
   102 }
   212 }
   103 
   213 
   104 JNIEXPORT jint JNICALL
   214 JNIEXPORT void JNICALL
   105 Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz,
   215 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
   106                                 jobject fdo, jobject iao, jint port,
   216 {
   107                                 jint trafficClass)
   217     if (listen(fdval(env, fdo), backlog) < 0)
       
   218         handleSocketError(env, errno);
       
   219 }
       
   220 
       
   221 JNIEXPORT jint JNICALL
       
   222 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
       
   223                              jobject fdo, jobject iao, jint port)
   108 {
   224 {
   109     SOCKADDR sa;
   225     SOCKADDR sa;
   110     int sa_len = SOCKADDR_LEN;
   226     int sa_len = SOCKADDR_LEN;
   111     int rv;
   227     int rv;
   112 
   228 
   113     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, JNI_TRUE) != 0) {
   229     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
       
   230                                   &sa_len, preferIPv6) != 0)
       
   231     {
   114       return IOS_THROWN;
   232       return IOS_THROWN;
   115     }
   233     }
   116 
       
   117 #ifdef AF_INET6
       
   118 #if 0
       
   119     if (trafficClass != 0 && ipv6_available()) { /* ## FIX */
       
   120         NET_SetTrafficClass((struct sockaddr *)&sa, trafficClass);
       
   121     }
       
   122 #endif
       
   123 #endif
       
   124 
   234 
   125     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   235     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   126     if (rv != 0) {
   236     if (rv != 0) {
   127         if (errno == EINPROGRESS) {
   237         if (errno == EINPROGRESS) {
   128             return IOS_UNAVAILABLE;
   238             return IOS_UNAVAILABLE;
   157         return NULL;
   267         return NULL;
   158     }
   268     }
   159     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
   269     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
   160 }
   270 }
   161 
   271 
   162 
   272 JNIEXPORT jint JNICALL
   163 #ifdef NEEDED
   273 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
   164 
   274                                   jboolean mayNeedConversion, jint level, jint opt)
   165 /* ## This is gross.  We should generate platform-specific constant
   275 {
   166  * ## definitions into a .java file and use those directly.
       
   167  */
       
   168 
       
   169 static int
       
   170 mapOption(JNIEnv *env, int opt, int *klevel, int *kopt)
       
   171 {
       
   172 
       
   173     switch (opt) {
       
   174 
       
   175     case java_net_SocketOptions_IP_TOS:
       
   176         *klevel = IPPROTO_IP;
       
   177         *kopt = IP_TOS;
       
   178         break;
       
   179 
       
   180     case java_net_SocketOptions_SO_BROADCAST:
       
   181     case java_net_SocketOptions_SO_KEEPALIVE:
       
   182     case java_net_SocketOptions_SO_LINGER:
       
   183     case java_net_SocketOptions_SO_OOBINLINE:
       
   184     case java_net_SocketOptions_SO_RCVBUF:
       
   185     case java_net_SocketOptions_SO_REUSEADDR:
       
   186     case java_net_SocketOptions_SO_SNDBUF:
       
   187         *klevel = SOL_SOCKET;
       
   188         break;
       
   189 
       
   190     case java_net_SocketOptions_TCP_NODELAY:
       
   191         *klevel = IPPROTO_IP;
       
   192         *kopt = TCP_NODELAY;
       
   193         return 0;
       
   194 
       
   195     default:
       
   196         JNU_ThrowByName(env, "java/lang/IllegalArgumentException", NULL);
       
   197         return -1;
       
   198     }
       
   199 
       
   200     switch (opt) {
       
   201 
       
   202     case java_net_SocketOptions_SO_BROADCAST:   *kopt = SO_BROADCAST;  break;
       
   203     case java_net_SocketOptions_SO_KEEPALIVE:   *kopt = SO_KEEPALIVE;  break;
       
   204     case java_net_SocketOptions_SO_LINGER:      *kopt = SO_LINGER;  break;
       
   205     case java_net_SocketOptions_SO_OOBINLINE:   *kopt = SO_OOBINLINE;  break;
       
   206     case java_net_SocketOptions_SO_RCVBUF:      *kopt = SO_RCVBUF;  break;
       
   207     case java_net_SocketOptions_SO_REUSEADDR:   *kopt = SO_REUSEADDR;  break;
       
   208     case java_net_SocketOptions_SO_SNDBUF:      *kopt = SO_SNDBUF;  break;
       
   209 
       
   210     default:
       
   211         return -1;
       
   212     }
       
   213 
       
   214     return 0;
       
   215 }
       
   216 #endif
       
   217 
       
   218 
       
   219 JNIEXPORT jint JNICALL
       
   220 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
       
   221                                   jobject fdo, jint opt)
       
   222 {
       
   223     int klevel, kopt;
       
   224     int result;
   276     int result;
   225     struct linger linger;
   277     struct linger linger;
       
   278     u_char carg;
   226     void *arg;
   279     void *arg;
   227     int arglen;
   280     int arglen, n;
   228 
   281 
   229     if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
   282     /* Option value is an int except for a few specific cases */
   230         JNU_ThrowByNameWithLastError(env,
   283 
   231                                      JNU_JAVANETPKG "SocketException",
   284     arg = (void *)&result;
   232                                      "Unsupported socket option");
   285     arglen = sizeof(result);
   233         return -1;
   286 
   234     }
   287     if (level == IPPROTO_IP &&
   235 
   288         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
   236     if (opt == java_net_SocketOptions_SO_LINGER) {
   289         arg = (void*)&carg;
       
   290         arglen = sizeof(carg);
       
   291     }
       
   292 
       
   293     if (level == SOL_SOCKET && opt == SO_LINGER) {
   237         arg = (void *)&linger;
   294         arg = (void *)&linger;
   238         arglen = sizeof(linger);
   295         arglen = sizeof(linger);
       
   296     }
       
   297 
       
   298     if (mayNeedConversion) {
       
   299         n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
   239     } else {
   300     } else {
   240         arg = (void *)&result;
   301         n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
   241         arglen = sizeof(result);
   302     }
   242     }
   303     if (n < 0) {
   243 
       
   244     if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
       
   245         JNU_ThrowByNameWithLastError(env,
   304         JNU_ThrowByNameWithLastError(env,
   246                                      JNU_JAVANETPKG "SocketException",
   305                                      JNU_JAVANETPKG "SocketException",
   247                                      "sun.nio.ch.Net.getIntOption");
   306                                      "sun.nio.ch.Net.getIntOption");
   248         return -1;
   307         return -1;
   249     }
   308     }
   250 
   309 
   251     if (opt == java_net_SocketOptions_SO_LINGER)
   310     if (level == IPPROTO_IP &&
   252         return linger.l_onoff ? linger.l_linger : -1;
   311         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
   253     else
   312     {
   254         return result;
   313         return (jint)carg;
   255 }
   314     }
   256 
   315 
   257 JNIEXPORT void JNICALL
   316     if (level == SOL_SOCKET && opt == SO_LINGER)
   258 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
   317         return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
   259                                   jobject fdo, jint opt, jint arg)
   318 
   260 {
   319     return (jint)result;
   261     int klevel, kopt;
   320 }
       
   321 
       
   322 JNIEXPORT void JNICALL
       
   323 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
       
   324                                   jboolean mayNeedConversion, jint level, jint opt, jint arg)
       
   325 {
   262     int result;
   326     int result;
   263     struct linger linger;
   327     struct linger linger;
       
   328     u_char carg;
   264     void *parg;
   329     void *parg;
   265     int arglen;
   330     int arglen, n;
   266 
   331 
   267     if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
   332     /* Option value is an int except for a few specific cases */
   268         JNU_ThrowByNameWithLastError(env,
   333 
   269                                      JNU_JAVANETPKG "SocketException",
   334     parg = (void*)&arg;
   270                                      "Unsupported socket option");
   335     arglen = sizeof(arg);
   271         return;
   336 
   272     }
   337     if (level == IPPROTO_IP &&
   273 
   338         (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
   274     if (opt == java_net_SocketOptions_SO_LINGER) {
   339         parg = (void*)&carg;
       
   340         arglen = sizeof(carg);
       
   341         carg = (u_char)arg;
       
   342     }
       
   343 
       
   344     if (level == SOL_SOCKET && opt == SO_LINGER) {
   275         parg = (void *)&linger;
   345         parg = (void *)&linger;
   276         arglen = sizeof(linger);
   346         arglen = sizeof(linger);
   277         if (arg >= 0) {
   347         if (arg >= 0) {
   278             linger.l_onoff = 1;
   348             linger.l_onoff = 1;
   279             linger.l_linger = arg;
   349             linger.l_linger = arg;
   280         } else {
   350         } else {
   281             linger.l_onoff = 0;
   351             linger.l_onoff = 0;
   282             linger.l_linger = 0;
   352             linger.l_linger = 0;
   283         }
   353         }
       
   354     }
       
   355 
       
   356     if (mayNeedConversion) {
       
   357         n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
   284     } else {
   358     } else {
   285         parg = (void *)&arg;
   359         n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
   286         arglen = sizeof(arg);
   360     }
   287     }
   361     if (n < 0) {
   288 
       
   289     if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
       
   290         JNU_ThrowByNameWithLastError(env,
   362         JNU_ThrowByNameWithLastError(env,
   291                                      JNU_JAVANETPKG "SocketException",
   363                                      JNU_JAVANETPKG "SocketException",
   292                                      "sun.nio.ch.Net.setIntOption");
   364                                      "sun.nio.ch.Net.setIntOption");
   293     }
   365     }
   294 }
   366 }
   295 
   367 
   296 
   368 JNIEXPORT jint JNICALL
       
   369 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
       
   370                                 jint group, jint interf, jint source)
       
   371 {
       
   372     struct ip_mreq mreq;
       
   373     struct my_ip_mreq_source mreq_source;
       
   374     int opt, n, optlen;
       
   375     void* optval;
       
   376 
       
   377     if (source == 0) {
       
   378         mreq.imr_multiaddr.s_addr = htonl(group);
       
   379         mreq.imr_interface.s_addr = htonl(interf);
       
   380         opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
       
   381         optval = (void*)&mreq;
       
   382         optlen = sizeof(mreq);
       
   383     } else {
       
   384         mreq_source.imr_multiaddr.s_addr = htonl(group);
       
   385         mreq_source.imr_sourceaddr.s_addr = htonl(source);
       
   386         mreq_source.imr_interface.s_addr = htonl(interf);
       
   387         opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
       
   388         optval = (void*)&mreq_source;
       
   389         optlen = sizeof(mreq_source);
       
   390     }
       
   391 
       
   392     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
       
   393     if (n < 0) {
       
   394         if (join && (errno == ENOPROTOOPT))
       
   395             return IOS_UNAVAILABLE;
       
   396         handleSocketError(env, errno);
       
   397     }
       
   398     return 0;
       
   399 }
       
   400 
       
   401 JNIEXPORT jint JNICALL
       
   402 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
       
   403                                     jint group, jint interf, jint source)
       
   404 {
       
   405     struct my_ip_mreq_source mreq_source;
       
   406     int n;
       
   407     int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
       
   408 
       
   409     mreq_source.imr_multiaddr.s_addr = htonl(group);
       
   410     mreq_source.imr_sourceaddr.s_addr = htonl(source);
       
   411     mreq_source.imr_interface.s_addr = htonl(interf);
       
   412 
       
   413     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
       
   414                    (void*)&mreq_source, sizeof(mreq_source));
       
   415     if (n < 0) {
       
   416         if (block && (errno == ENOPROTOOPT))
       
   417             return IOS_UNAVAILABLE;
       
   418         handleSocketError(env, errno);
       
   419     }
       
   420     return 0;
       
   421 }
       
   422 
       
   423 JNIEXPORT jint JNICALL
       
   424 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
       
   425                                 jbyteArray group, jint index, jbyteArray source)
       
   426 {
       
   427     struct ipv6_mreq mreq6;
       
   428     struct my_group_source_req req;
       
   429     int opt, n, optlen;
       
   430     void* optval;
       
   431 
       
   432     if (source == NULL) {
       
   433         COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
       
   434         mreq6.ipv6mr_interface = (int)index;
       
   435         opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
       
   436         optval = (void*)&mreq6;
       
   437         optlen = sizeof(mreq6);
       
   438     } else {
       
   439 #ifdef __linux__
       
   440         /* Include-mode filtering broken on Linux at least to 2.6.24 */
       
   441         return IOS_UNAVAILABLE;
       
   442 #else
       
   443         initGroupSourceReq(env, group, index, source, &req);
       
   444         opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
       
   445         optval = (void*)&req;
       
   446         optlen = sizeof(req);
       
   447 #endif
       
   448     }
       
   449 
       
   450     n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
       
   451     if (n < 0) {
       
   452         if (join && (errno == ENOPROTOOPT))
       
   453             return IOS_UNAVAILABLE;
       
   454         handleSocketError(env, errno);
       
   455     }
       
   456     return 0;
       
   457 }
       
   458 
       
   459 JNIEXPORT jint JNICALL
       
   460 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
       
   461                                     jbyteArray group, jint index, jbyteArray source)
       
   462 {
       
   463     struct my_group_source_req req;
       
   464     int n;
       
   465     int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
       
   466 
       
   467     initGroupSourceReq(env, group, index, source, &req);
       
   468 
       
   469     n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
       
   470         (void*)&req, sizeof(req));
       
   471     if (n < 0) {
       
   472         if (block && (errno == ENOPROTOOPT))
       
   473             return IOS_UNAVAILABLE;
       
   474         handleSocketError(env, errno);
       
   475     }
       
   476     return 0;
       
   477 }
       
   478 
       
   479 JNIEXPORT void JNICALL
       
   480 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
       
   481 {
       
   482     struct in_addr in;
       
   483     int arglen = sizeof(struct in_addr);
       
   484     int n;
       
   485 
       
   486     in.s_addr = htonl(interf);
       
   487 
       
   488     n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
       
   489                    (void*)&(in.s_addr), arglen);
       
   490     if (n < 0) {
       
   491         handleSocketError(env, errno);
       
   492     }
       
   493 }
       
   494 
       
   495 JNIEXPORT jint JNICALL
       
   496 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
       
   497 {
       
   498     struct in_addr in;
       
   499     int arglen = sizeof(struct in_addr);
       
   500     int n;
       
   501 
       
   502     n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
       
   503     if (n < 0) {
       
   504         handleSocketError(env, errno);
       
   505         return -1;
       
   506     }
       
   507     return ntohl(in.s_addr);
       
   508 }
       
   509 
       
   510 JNIEXPORT void JNICALL
       
   511 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
       
   512 {
       
   513     int value = (jint)index;
       
   514     int arglen = sizeof(value);
       
   515     int n;
       
   516 
       
   517     n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
       
   518                    (void*)&(index), arglen);
       
   519     if (n < 0) {
       
   520         handleSocketError(env, errno);
       
   521     }
       
   522 }
       
   523 
       
   524 JNIEXPORT jint JNICALL
       
   525 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
       
   526 {
       
   527     int index;
       
   528     int arglen = sizeof(index);
       
   529     int n;
       
   530 
       
   531     n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
       
   532     if (n < 0) {
       
   533         handleSocketError(env, errno);
       
   534         return -1;
       
   535     }
       
   536     return (jint)index;
       
   537 }
       
   538 
       
   539 JNIEXPORT void JNICALL
       
   540 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
       
   541 {
       
   542     int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
       
   543         (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
       
   544     if (shutdown(fdval(env, fdo), how) < 0)
       
   545         handleSocketError(env, errno);
       
   546 }
   297 
   547 
   298 /* Declared in nio_util.h */
   548 /* Declared in nio_util.h */
   299 
   549 
   300 jint
   550 jint
   301 handleSocketError(JNIEnv *env, jint errorValue)
   551 handleSocketError(JNIEnv *env, jint errorValue)