jdk/src/windows/native/sun/nio/ch/Net.c
changeset 1152 29d6145d1097
parent 2 90ce3da70b43
child 1247 b4c26443dee5
equal deleted inserted replaced
1151:4070cecdb99d 1152:29d6145d1097
    34 #include "nio_util.h"
    34 #include "nio_util.h"
    35 #include "net_util.h"
    35 #include "net_util.h"
    36 
    36 
    37 #include "sun_nio_ch_Net.h"
    37 #include "sun_nio_ch_Net.h"
    38 
    38 
    39 
    39 /**
    40 static jfieldID ia_addrID;
    40  * Definitions to allow for building with older SDK include files.
    41 static jclass ia_class;
       
    42 static jmethodID ia_ctorID;
       
    43 static jfieldID ia_famID;
       
    44 
       
    45 /**************************************************************
       
    46  * static method to store field IDs in initializers
       
    47  */
    41  */
    48 
    42 
       
    43 #ifndef MCAST_BLOCK_SOURCE
       
    44 
       
    45 #define MCAST_BLOCK_SOURCE          43
       
    46 #define MCAST_UNBLOCK_SOURCE        44
       
    47 #define MCAST_JOIN_SOURCE_GROUP     45
       
    48 #define MCAST_LEAVE_SOURCE_GROUP    46
       
    49 
       
    50 #endif  /* MCAST_BLOCK_SOURCE */
       
    51 
       
    52 typedef struct my_ip_mreq_source {
       
    53     IN_ADDR imr_multiaddr;
       
    54     IN_ADDR imr_sourceaddr;
       
    55     IN_ADDR imr_interface;
       
    56 };
       
    57 
       
    58 typedef struct my_group_source_req {
       
    59     ULONG gsr_interface;
       
    60     SOCKADDR_STORAGE gsr_group;
       
    61     SOCKADDR_STORAGE gsr_source;
       
    62 };
       
    63 
       
    64 /**
       
    65  * Copy IPv6 address as jbytearray to target
       
    66  */
       
    67 #define COPY_INET6_ADDRESS(env, source, target) \
       
    68     (*env)->GetByteArrayRegion(env, source, 0, 16, target)
       
    69 
       
    70 
       
    71 
    49 JNIEXPORT void JNICALL
    72 JNIEXPORT void JNICALL
    50 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
    73 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
    51 {
    74 {
    52     clazz = (*env)->FindClass(env, "java/net/Inet4Address");
    75     /* nothing to do */
    53     ia_class = (*env)->NewGlobalRef(env, clazz);
    76 }
    54     ia_addrID = (*env)->GetFieldID(env, clazz, "address", "I");
    77 
    55     ia_famID = (*env)->GetFieldID(env, clazz, "family", "I");
    78 JNIEXPORT jboolean JNICALL
    56     ia_ctorID = (*env)->GetMethodID(env, clazz, "<init>", "()V");
    79 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
    57 }
    80 {
    58 
    81     /*
    59 
    82      * Return true if Windows Vista or newer, and IPv6 is configured
    60 JNIEXPORT jint JNICALL
    83      */
    61 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
    84     OSVERSIONINFO ver;
    62                             jboolean reuse)
    85     ver.dwOSVersionInfoSize = sizeof(ver);
       
    86     GetVersionEx(&ver);
       
    87     if ((ver.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
       
    88         (ver.dwMajorVersion >= 6)  && ipv6_available())
       
    89     {
       
    90         return JNI_TRUE;
       
    91     }
       
    92     return JNI_FALSE;
       
    93 }
       
    94 
       
    95 JNIEXPORT jint JNICALL
       
    96 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
       
    97                             jboolean stream, jboolean reuse)
    63 {
    98 {
    64     SOCKET s;
    99     SOCKET s;
    65 
   100     int domain = (preferIPv6) ? AF_INET6 : AF_INET;
    66     s = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
   101 
       
   102     s = socket(domain, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
    67     if (s != INVALID_SOCKET) {
   103     if (s != INVALID_SOCKET) {
    68         SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
   104         SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
       
   105 
       
   106         /* IPV6_V6ONLY is true by default */
       
   107         if (domain == AF_INET6) {
       
   108             int opt = 0;
       
   109             setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
       
   110                        (const char *)&opt, sizeof(opt));
       
   111         }
    69     } else {
   112     } else {
    70         NET_ThrowNew(env, WSAGetLastError(), "socket");
   113         NET_ThrowNew(env, WSAGetLastError(), "socket");
    71     }
   114     }
       
   115 
    72     return (jint)s;
   116     return (jint)s;
    73 }
   117 }
    74 
   118 
    75 JNIEXPORT void JNICALL
   119 JNIEXPORT void JNICALL
    76 Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz,
   120 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
    77                          jobject fdo, jobject iao, jint port)
   121                           jobject fdo, jobject iao, jint port)
    78 {
   122 {
    79     SOCKETADDRESS sa;
   123     SOCKETADDRESS sa;
    80     int rv;
   124     int rv;
    81     int sa_len = sizeof(sa);
   125     int sa_len;
    82 
   126 
    83    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
   127     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
    84       return;
   128       return;
    85     }
   129     }
    86 
   130 
    87     rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   131     rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
    88     if (rv == SOCKET_ERROR)
   132     if (rv == SOCKET_ERROR)
    89         NET_ThrowNew(env, WSAGetLastError(), "bind");
   133         NET_ThrowNew(env, WSAGetLastError(), "bind");
    90 }
   134 }
    91 
   135 
    92 JNIEXPORT jint JNICALL
   136 JNIEXPORT void JNICALL
    93 Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao,
   137 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
    94                             jint port, jint trafficClass)
   138 {
       
   139     if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) {
       
   140         NET_ThrowNew(env, WSAGetLastError(), "listen");
       
   141     }
       
   142 }
       
   143 
       
   144 
       
   145 JNIEXPORT jint JNICALL
       
   146 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo,
       
   147                              jobject iao, jint port)
    95 {
   148 {
    96     SOCKETADDRESS sa;
   149     SOCKETADDRESS sa;
    97     int rv;
   150     int rv;
    98     int sa_len = sizeof(sa);
   151     int sa_len;
    99 
   152 
   100    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
   153     if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
   101       return IOS_THROWN;
   154         return IOS_THROWN;
   102     }
   155     }
   103 
   156 
   104     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   157     rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
   105     if (rv != 0) {
   158     if (rv != 0) {
   106         int err = WSAGetLastError();
   159         int err = WSAGetLastError();
   114 }
   167 }
   115 
   168 
   116 JNIEXPORT jint JNICALL
   169 JNIEXPORT jint JNICALL
   117 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
   170 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
   118 {
   171 {
   119     struct sockaddr_in sa;
   172     SOCKETADDRESS sa;
   120     int sa_len = sizeof(sa);
   173     int sa_len = sizeof(sa);
   121 
   174 
   122     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
   175     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
   123         int error = WSAGetLastError();
   176         int error = WSAGetLastError();
   124         if (error == WSAEINVAL) {
   177         if (error == WSAEINVAL) {
   125             return 0;
   178             return 0;
   126         }
   179         }
   127         NET_ThrowNew(env, error, "getsockname");
   180         NET_ThrowNew(env, error, "getsockname");
   128         return IOS_THROWN;
   181         return IOS_THROWN;
   129     }
   182     }
   130     return (jint)ntohs(sa.sin_port);
   183     return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
   131 }
   184 }
   132 
   185 
   133 JNIEXPORT jobject JNICALL
   186 JNIEXPORT jobject JNICALL
   134 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
   187 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
   135 {
   188 {
   136     struct sockaddr_in sa;
   189     SOCKETADDRESS sa;
   137     int sa_len = sizeof(sa);
   190     int sa_len = sizeof(sa);
   138     jobject iao;
   191     int port;
   139 
   192 
   140     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
   193     if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
   141         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
   194         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
   142         return NULL;
   195         return NULL;
   143     }
   196     }
   144 
   197     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
   145     iao = (*env)->NewObject(env, ia_class, ia_ctorID);
   198 }
   146     if (iao == NULL) {
   199 
   147         JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
   200 JNIEXPORT jint JNICALL
   148     } else {
   201 Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
   149         (*env)->SetIntField(env, iao, ia_addrID, ntohl(sa.sin_addr.s_addr));
   202 {
   150     }
   203     SOCKETADDRESS sa;
   151 
   204     int sa_len = sizeof(sa);
   152     return iao;
   205 
   153 }
   206     if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
   154 
   207         int error = WSAGetLastError();
   155 
   208         if (error == WSAEINVAL) {
   156 JNIEXPORT jint JNICALL
   209             return 0;
   157 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
   210         }
   158                                   jobject fdo, jint opt)
   211         NET_ThrowNew(env, error, "getsockname");
   159 {
   212         return IOS_THROWN;
   160     int klevel, kopt;
   213     }
   161     int result;
   214     return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
       
   215 }
       
   216 
       
   217 JNIEXPORT jobject JNICALL
       
   218 Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
       
   219 {
       
   220     SOCKETADDRESS sa;
       
   221     int sa_len = sizeof(sa);
       
   222     int port;
       
   223 
       
   224     if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
       
   225         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
       
   226         return NULL;
       
   227     }
       
   228     return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
       
   229 }
       
   230 
       
   231 JNIEXPORT jint JNICALL
       
   232 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
       
   233                                   jboolean mayNeedConversion, jint level, jint opt)
       
   234 {
       
   235     int result = 0;
   162     struct linger linger;
   236     struct linger linger;
   163     char *arg;
   237     char *arg;
   164     int arglen;
   238     int arglen, n;
   165 
   239 
   166     if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
   240     if (level == SOL_SOCKET && opt == SO_LINGER) {
   167         JNU_ThrowByNameWithLastError(env,
       
   168                                      JNU_JAVANETPKG "SocketException",
       
   169                                      "Unsupported socket option");
       
   170         return IOS_THROWN;
       
   171     }
       
   172 
       
   173     if (opt == java_net_SocketOptions_SO_LINGER) {
       
   174         arg = (char *)&linger;
   241         arg = (char *)&linger;
   175         arglen = sizeof(linger);
   242         arglen = sizeof(linger);
   176     } else {
   243     } else {
   177         arg = (char *)&result;
   244         arg = (char *)&result;
   178         arglen = sizeof(result);
   245         arglen = sizeof(result);
   179     }
   246     }
   180 
   247 
   181     if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
   248     /**
   182         NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
   249      * HACK: IP_TOS is deprecated on Windows and querying the option
   183         return IOS_THROWN;
   250      * returns a protocol error. NET_GetSockOpt handles this and uses
   184     }
   251      * a fallback mechanism.
   185 
   252      */
   186     if (opt == java_net_SocketOptions_SO_LINGER)
   253     if (level == IPPROTO_IP && opt == IP_TOS) {
       
   254         mayNeedConversion = JNI_TRUE;
       
   255     }
       
   256 
       
   257     if (mayNeedConversion) {
       
   258         n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
       
   259     } else {
       
   260         n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
       
   261     }
       
   262     if (n < 0) {
       
   263         handleSocketError(env, WSAGetLastError());
       
   264         return IOS_THROWN;
       
   265     }
       
   266 
       
   267     if (level == SOL_SOCKET && opt == SO_LINGER)
   187         return linger.l_onoff ? linger.l_linger : -1;
   268         return linger.l_onoff ? linger.l_linger : -1;
   188     else
   269     else
   189         return result;
   270         return result;
   190 }
   271 }
   191 
   272 
   192 JNIEXPORT void JNICALL
   273 JNIEXPORT void JNICALL
   193 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
   274 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
   194                                   jobject fdo, jint opt, jint arg)
   275                                   jboolean mayNeedConversion, jint level, jint opt, jint arg)
   195 {
   276 {
   196     int klevel, kopt;
       
   197     struct linger linger;
   277     struct linger linger;
   198     char *parg;
   278     char *parg;
   199     int arglen;
   279     int arglen, n;
   200 
   280 
   201     if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
   281     if (level == SOL_SOCKET && opt == SO_LINGER) {
   202         JNU_ThrowByNameWithLastError(env,
       
   203                                      JNU_JAVANETPKG "SocketException",
       
   204                                      "Unsupported socket option");
       
   205         return;
       
   206     }
       
   207 
       
   208     if (opt == java_net_SocketOptions_SO_LINGER) {
       
   209         parg = (char *)&linger;
   282         parg = (char *)&linger;
   210         arglen = sizeof(linger);
   283         arglen = sizeof(linger);
   211         if (arg >= 0) {
   284         if (arg >= 0) {
   212             linger.l_onoff = 1;
   285             linger.l_onoff = 1;
   213             linger.l_linger = (unsigned short)arg;
   286             linger.l_linger = (unsigned short)arg;
   218     } else {
   291     } else {
   219         parg = (char *)&arg;
   292         parg = (char *)&arg;
   220         arglen = sizeof(arg);
   293         arglen = sizeof(arg);
   221     }
   294     }
   222 
   295 
   223     if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
   296     if (mayNeedConversion) {
   224         NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
   297         n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
   225     }
   298     } else {
   226 }
   299         n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
       
   300     }
       
   301     if (n < 0)
       
   302         handleSocketError(env, WSAGetLastError());
       
   303 }
       
   304 
       
   305 JNIEXPORT jint JNICALL
       
   306 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
       
   307                                 jint group, jint interf, jint source)
       
   308 {
       
   309     struct ip_mreq mreq;
       
   310     struct my_ip_mreq_source mreq_source;
       
   311     int opt, n, optlen;
       
   312     void* optval;
       
   313 
       
   314     if (source == 0) {
       
   315         mreq.imr_multiaddr.s_addr = htonl(group);
       
   316         mreq.imr_interface.s_addr = htonl(interf);
       
   317         opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
       
   318         optval = (void*)&mreq;
       
   319         optlen = sizeof(mreq);
       
   320     } else {
       
   321         mreq_source.imr_multiaddr.s_addr = htonl(group);
       
   322         mreq_source.imr_sourceaddr.s_addr = htonl(source);
       
   323         mreq_source.imr_interface.s_addr = htonl(interf);
       
   324         opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
       
   325         optval = (void*)&mreq_source;
       
   326         optlen = sizeof(mreq_source);
       
   327     }
       
   328 
       
   329     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
       
   330     if (n < 0) {
       
   331         if (join && (WSAGetLastError() == WSAENOPROTOOPT))
       
   332             return IOS_UNAVAILABLE;
       
   333         handleSocketError(env, WSAGetLastError());
       
   334     }
       
   335     return 0;
       
   336 }
       
   337 
       
   338 JNIEXPORT jint JNICALL
       
   339 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
       
   340                                    jint group, jint interf, jint source)
       
   341 {
       
   342     struct my_ip_mreq_source mreq_source;
       
   343     int n;
       
   344     int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
       
   345 
       
   346     mreq_source.imr_multiaddr.s_addr = htonl(group);
       
   347     mreq_source.imr_sourceaddr.s_addr = htonl(source);
       
   348     mreq_source.imr_interface.s_addr = htonl(interf);
       
   349 
       
   350     n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
       
   351                    (void*)&mreq_source, sizeof(mreq_source));
       
   352     if (n < 0) {
       
   353         if (block && (WSAGetLastError() == WSAENOPROTOOPT))
       
   354             return IOS_UNAVAILABLE;
       
   355         handleSocketError(env, WSAGetLastError());
       
   356     }
       
   357     return 0;
       
   358 }
       
   359 
       
   360 /**
       
   361  * Call setsockopt with a IPPROTO_IPV6 level socket option
       
   362  * and a group_source_req structure as the option value. The
       
   363  * given IPv6 group, interface index, and IPv6 source address
       
   364  * are copied into the structure.
       
   365  */
       
   366 static int setGroupSourceReqOption(JNIEnv* env,
       
   367                                    jobject fdo,
       
   368                                    int opt,
       
   369                                    jbyteArray group,
       
   370                                    jint index,
       
   371                                    jbyteArray source)
       
   372 {
       
   373     struct my_group_source_req req;
       
   374     struct sockaddr_in6* sin6;
       
   375 
       
   376     req.gsr_interface = (ULONG)index;
       
   377 
       
   378     sin6 = (struct sockaddr_in6*)&(req.gsr_group);
       
   379     sin6->sin6_family = AF_INET6;
       
   380     COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
       
   381 
       
   382     sin6 = (struct sockaddr_in6*)&(req.gsr_source);
       
   383     sin6->sin6_family = AF_INET6;
       
   384     COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
       
   385 
       
   386     return setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req));
       
   387 }
       
   388 
       
   389 JNIEXPORT jint JNICALL
       
   390 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
       
   391                                 jbyteArray group, jint index, jbyteArray source)
       
   392 {
       
   393     struct ipv6_mreq mreq6;
       
   394     int n;
       
   395 
       
   396     if (source == NULL) {
       
   397         int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
       
   398         COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
       
   399         mreq6.ipv6mr_interface = (int)index;
       
   400         n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
       
   401                        (void*)&mreq6, sizeof(mreq6));
       
   402     } else {
       
   403         int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
       
   404         n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
       
   405     }
       
   406 
       
   407     if (n < 0) {
       
   408         handleSocketError(env, errno);
       
   409     }
       
   410     return 0;
       
   411 }
       
   412 
       
   413 JNIEXPORT jint JNICALL
       
   414 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
       
   415                                     jbyteArray group, jint index, jbyteArray source)
       
   416 {
       
   417     int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
       
   418     int n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
       
   419     if (n < 0) {
       
   420         handleSocketError(env, errno);
       
   421     }
       
   422     return 0;
       
   423 }
       
   424 
       
   425 JNIEXPORT void JNICALL
       
   426 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
       
   427 {
       
   428     struct in_addr in;
       
   429     int arglen = sizeof(struct in_addr);
       
   430     int n;
       
   431 
       
   432     in.s_addr = htonl(interf);
       
   433 
       
   434     n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
       
   435                    (void*)&(in.s_addr), arglen);
       
   436     if (n < 0) {
       
   437         handleSocketError(env, WSAGetLastError());
       
   438     }
       
   439 }
       
   440 
       
   441 JNIEXPORT jint JNICALL
       
   442 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
       
   443 {
       
   444     struct in_addr in;
       
   445     int arglen = sizeof(struct in_addr);
       
   446     int n;
       
   447 
       
   448     n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
       
   449     if (n < 0) {
       
   450         handleSocketError(env, WSAGetLastError());
       
   451         return IOS_THROWN;
       
   452     }
       
   453     return ntohl(in.s_addr);
       
   454 }
       
   455 
       
   456 JNIEXPORT void JNICALL
       
   457 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
       
   458 {
       
   459     int value = (jint)index;
       
   460     int arglen = sizeof(value);
       
   461     int n;
       
   462 
       
   463     n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
       
   464                    (void*)&(index), arglen);
       
   465     if (n < 0) {
       
   466         handleSocketError(env, errno);
       
   467     }
       
   468 }
       
   469 
       
   470 JNIEXPORT jint JNICALL
       
   471 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
       
   472 {
       
   473     int index;
       
   474     int arglen = sizeof(index);
       
   475     int n;
       
   476 
       
   477     n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
       
   478     if (n < 0) {
       
   479         handleSocketError(env, errno);
       
   480         return -1;
       
   481     }
       
   482     return (jint)index;
       
   483 }
       
   484 
       
   485 JNIEXPORT void JNICALL
       
   486 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) {
       
   487     int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SD_RECEIVE :
       
   488         (jhow == sun_nio_ch_Net_SHUT_WR) ? SD_SEND : SD_BOTH;
       
   489     if (shutdown(fdval(env, fdo), how) == SOCKET_ERROR) {
       
   490         NET_ThrowNew(env, WSAGetLastError(), "shutdown");
       
   491     }
       
   492 }