jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c
changeset 43614 d8e1fecbb8f2
parent 43100 a7e3457672c7
equal deleted inserted replaced
43613:276f99eae616 43614:d8e1fecbb8f2
    36 #include <net/if.h>
    36 #include <net/if.h>
    37 #endif
    37 #endif
    38 
    38 
    39 #include "net_util.h"
    39 #include "net_util.h"
    40 
    40 
       
    41 #include "java_net_InetAddress.h"
    41 #include "java_net_Inet4AddressImpl.h"
    42 #include "java_net_Inet4AddressImpl.h"
    42 #include "java_net_Inet6AddressImpl.h"
    43 #include "java_net_Inet6AddressImpl.h"
    43 #include "java_net_InetAddress.h"
       
    44 
    44 
    45 /* the initial size of our hostent buffers */
    45 /* the initial size of our hostent buffers */
    46 #ifndef NI_MAXHOST
    46 #ifndef NI_MAXHOST
    47 #define NI_MAXHOST 1025
    47 #define NI_MAXHOST 1025
    48 #endif
    48 #endif
    49 
    49 
    50 
    50 #define SET_NONBLOCKING(fd) {       \
    51 /************************************************************************
    51     int flags = fcntl(fd, F_GETFL); \
       
    52     flags |= O_NONBLOCK;            \
       
    53     fcntl(fd, F_SETFL, flags);      \
       
    54 }
       
    55 
       
    56 /*
    52  * Inet6AddressImpl
    57  * Inet6AddressImpl
    53  */
    58  */
    54 
    59 
    55 /*
    60 /*
    56  * Class:     java_net_Inet6AddressImpl
    61  * Class:     java_net_Inet6AddressImpl
    57  * Method:    getLocalHostName
    62  * Method:    getLocalHostName
    58  * Signature: ()Ljava/lang/String;
    63  * Signature: ()Ljava/lang/String;
    59  */
    64  */
    60 JNIEXPORT jstring JNICALL
    65 JNIEXPORT jstring JNICALL
    61 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
    66 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
    62     int ret;
    67     char hostname[NI_MAXHOST + 1];
    63     char hostname[NI_MAXHOST+1];
       
    64 
    68 
    65     hostname[0] = '\0';
    69     hostname[0] = '\0';
    66     ret = gethostname(hostname, NI_MAXHOST);
    70     if (gethostname(hostname, NI_MAXHOST) != 0) {
    67     if (ret == -1) {
       
    68         /* Something went wrong, maybe networking is not setup? */
       
    69         strcpy(hostname, "localhost");
    71         strcpy(hostname, "localhost");
       
    72 #if defined(__solaris__)
    70     } else {
    73     } else {
    71         // ensure null-terminated
    74         // try to resolve hostname via nameservice
       
    75         // if it is known but getnameinfo fails, hostname will still be the
       
    76         // value from gethostname
       
    77         struct addrinfo hints, *res;
       
    78 
       
    79         // make sure string is null-terminated
    72         hostname[NI_MAXHOST] = '\0';
    80         hostname[NI_MAXHOST] = '\0';
    73     }
       
    74 
       
    75 #if defined(__solaris__)
       
    76     if (ret == 0) {
       
    77         /* Solaris doesn't want to give us a fully qualified domain name.
       
    78          * We do a reverse lookup to try and get one.  This works
       
    79          * if DNS occurs before NIS in /etc/resolv.conf, but fails
       
    80          * if NIS comes first (it still gets only a partial name).
       
    81          * We use thread-safe system calls.
       
    82          */
       
    83         struct addrinfo  hints, *res;
       
    84         int error;
       
    85 
       
    86         memset(&hints, 0, sizeof(hints));
    81         memset(&hints, 0, sizeof(hints));
    87         hints.ai_flags = AI_CANONNAME;
    82         hints.ai_flags = AI_CANONNAME;
    88         hints.ai_family = AF_UNSPEC;
    83         hints.ai_family = AF_UNSPEC;
    89 
    84 
    90         error = getaddrinfo(hostname, NULL, &hints, &res);
    85         if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
    91 
    86             getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST,
    92         if (error == 0) {
    87                         NULL, 0, NI_NAMEREQD);
    93             /* host is known to name service */
       
    94             error = getnameinfo(res->ai_addr,
       
    95                                 res->ai_addrlen,
       
    96                                 hostname,
       
    97                                 NI_MAXHOST,
       
    98                                 NULL,
       
    99                                 0,
       
   100                                 NI_NAMEREQD);
       
   101 
       
   102             /* if getnameinfo fails hostname is still the value
       
   103                from gethostname */
       
   104 
       
   105             freeaddrinfo(res);
    88             freeaddrinfo(res);
   106         }
    89         }
   107     }
    90     }
   108 #endif
    91 #else
   109 
    92     } else {
       
    93         // make sure string is null-terminated
       
    94         hostname[NI_MAXHOST] = '\0';
       
    95     }
       
    96 #endif
   110     return (*env)->NewStringUTF(env, hostname);
    97     return (*env)->NewStringUTF(env, hostname);
   111 }
    98 }
   112 
    99 
   113 #ifdef MACOSX
   100 #if defined(MACOSX)
   114 /* also called from Inet4AddressImpl.c */
   101 /* also called from Inet4AddressImpl.c */
   115 __private_extern__ jobjectArray
   102 __private_extern__ jobjectArray
   116 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
   103 lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
   117 {
   104 {
   118     jobjectArray result = NULL;
   105     jobjectArray result = NULL;
   161      * address.
   148      * address.
   162      */
   149      */
   163     struct ifaddrs *iter = ifa;
   150     struct ifaddrs *iter = ifa;
   164     while (iter) {
   151     while (iter) {
   165         int family = iter->ifa_addr->sa_family;
   152         int family = iter->ifa_addr->sa_family;
   166         if (iter->ifa_name[0] != '\0'  &&  iter->ifa_addr)
   153         if (iter->ifa_name[0] != '\0' && iter->ifa_addr)
   167         {
   154         {
   168             jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;
   155             jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;
   169             if (family == AF_INET) {
   156             if (family == AF_INET) {
   170                 addrs4++;
   157                 addrs4++;
   171                 if (isLoopback) numV4Loopbacks++;
   158                 if (isLoopback) numV4Loopbacks++;
   172             } else if (family == AF_INET6 && includeV6) {
   159             } else if (family == AF_INET6 && includeV6) {
   173                 addrs6++;
   160                 addrs6++;
   174                 if (isLoopback) numV6Loopbacks++;
   161                 if (isLoopback) numV6Loopbacks++;
   175             } else {
   162             } // else we don't care, e.g. AF_LINK
   176                 /* We don't care e.g. AF_LINK */
       
   177             }
       
   178         }
   163         }
   179         iter = iter->ifa_next;
   164         iter = iter->ifa_next;
   180     }
   165     }
   181 
   166 
   182     if (addrs4 == numV4Loopbacks && addrs6 == numV6Loopbacks) {
   167     if (addrs4 == numV4Loopbacks && addrs6 == numV6Loopbacks) {
   203     iter = ifa;
   188     iter = ifa;
   204     while (iter != NULL) {
   189     while (iter != NULL) {
   205         jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;
   190         jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;
   206         int family = iter->ifa_addr->sa_family;
   191         int family = iter->ifa_addr->sa_family;
   207 
   192 
   208         if (iter->ifa_name[0] != '\0'  &&  iter->ifa_addr
   193         if (iter->ifa_name[0] != '\0' && iter->ifa_addr &&
   209             && (family == AF_INET || (family == AF_INET6 && includeV6))
   194             (family == AF_INET || (family == AF_INET6 && includeV6)) &&
   210             && (!isLoopback || includeLoopback))
   195             (!isLoopback || includeLoopback))
   211         {
   196         {
   212             int port;
   197             int port;
   213             int index = (family == AF_INET) ? i++ : j++;
   198             int index = (family == AF_INET) ? i++ : j++;
   214             jobject o = NET_SockaddrToInetAddress(env,
   199             jobject o = NET_SockaddrToInetAddress(env,
   215                             (SOCKETADDRESS *)iter->ifa_addr, &port);
   200                             (SOCKETADDRESS *)iter->ifa_addr, &port);
   232     return result;
   217     return result;
   233 }
   218 }
   234 #endif
   219 #endif
   235 
   220 
   236 /*
   221 /*
   237  * Find an internet address for a given hostname.  Note that this
       
   238  * code only works for addresses of type INET. The translation
       
   239  * of %d.%d.%d.%d to an address (int) occurs in java now, so the
       
   240  * String "host" shouldn't *ever* be a %d.%d.%d.%d string
       
   241  *
       
   242  * Class:     java_net_Inet6AddressImpl
   222  * Class:     java_net_Inet6AddressImpl
   243  * Method:    lookupAllHostAddr
   223  * Method:    lookupAllHostAddr
   244  * Signature: (Ljava/lang/String;)[[B
   224  * Signature: (Ljava/lang/String;)[[B
   245  */
   225  */
   246 
       
   247 JNIEXPORT jobjectArray JNICALL
   226 JNIEXPORT jobjectArray JNICALL
   248 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
   227 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
   249                                                 jstring host) {
   228                                                  jstring host) {
       
   229     jobjectArray ret = NULL;
   250     const char *hostname;
   230     const char *hostname;
   251     jobjectArray ret = 0;
   231     int error = 0;
   252     int retLen = 0;
   232     struct addrinfo hints, *res = NULL, *resNew = NULL, *last = NULL,
   253 
   233         *iterator;
   254     int getaddrinfo_error=0;
       
   255     struct addrinfo hints, *res, *resNew = NULL;
       
   256 
   234 
   257     initInetAddressIDs(env);
   235     initInetAddressIDs(env);
   258     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
   236     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
   259 
   237 
   260     if (IS_NULL(host)) {
   238     if (IS_NULL(host)) {
   261         JNU_ThrowNullPointerException(env, "host is null");
   239         JNU_ThrowNullPointerException(env, "host argument is null");
   262         return 0;
   240         return NULL;
   263     }
   241     }
   264     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
   242     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
   265     CHECK_NULL_RETURN(hostname, NULL);
   243     CHECK_NULL_RETURN(hostname, NULL);
   266 
   244 
   267     /* Try once, with our static buffer. */
   245     // try once, with our static buffer
   268     memset(&hints, 0, sizeof(hints));
   246     memset(&hints, 0, sizeof(hints));
   269     hints.ai_flags = AI_CANONNAME;
   247     hints.ai_flags = AI_CANONNAME;
   270     hints.ai_family = AF_UNSPEC;
   248     hints.ai_family = AF_UNSPEC;
   271 
   249 
   272 #ifdef __solaris__
   250     error = getaddrinfo(hostname, NULL, &hints, &res);
   273     /*
   251 
   274      * Workaround for Solaris bug 4160367 - if a hostname contains a
   252     if (error) {
   275      * white space then 0.0.0.0 is returned
   253 #if defined(MACOSX)
   276      */
   254         // if getaddrinfo fails try getifaddrs
   277     if (isspace((unsigned char)hostname[0])) {
       
   278         JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
       
   279                         hostname);
       
   280         JNU_ReleaseStringPlatformChars(env, host, hostname);
       
   281         return NULL;
       
   282     }
       
   283 #endif
       
   284 
       
   285     getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res);
       
   286 
       
   287 #ifdef MACOSX
       
   288     if (getaddrinfo_error) {
       
   289         /*
       
   290          * If getaddrinfo fails looking up the local machine, attempt to get the
       
   291          * address from getifaddrs. This ensures we get an IPv6 address for the
       
   292          * local machine.
       
   293          */
       
   294         ret = lookupIfLocalhost(env, hostname, JNI_TRUE);
   255         ret = lookupIfLocalhost(env, hostname, JNI_TRUE);
   295         if (ret != NULL || (*env)->ExceptionCheck(env)) {
   256         if (ret != NULL || (*env)->ExceptionCheck(env)) {
   296             JNU_ReleaseStringPlatformChars(env, host, hostname);
   257             goto cleanupAndReturn;
   297             return ret;
   258         }
   298         }
   259 #endif
   299     }
   260         // report error
   300 #endif
   261         NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
   301 
   262         goto cleanupAndReturn;
   302     if (getaddrinfo_error) {
       
   303         /* report error */
       
   304         NET_ThrowUnknownHostExceptionWithGaiError(
       
   305             env, hostname, getaddrinfo_error);
       
   306         JNU_ReleaseStringPlatformChars(env, host, hostname);
       
   307         return NULL;
       
   308     } else {
   263     } else {
   309         int i = 0, addressPreference = -1;
   264         int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
   310         int inetCount = 0, inet6Count = 0, inetIndex = 0, inet6Index = 0, originalIndex = 0;
   265             inet6Index = 0, originalIndex = 0;
   311         struct addrinfo *itr, *last = NULL, *iterator = res;
   266         int addressPreference =
       
   267             (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);;
       
   268         iterator = res;
   312         while (iterator != NULL) {
   269         while (iterator != NULL) {
       
   270             // skip duplicates
   313             int skip = 0;
   271             int skip = 0;
   314             itr = resNew;
   272             struct addrinfo *iteratorNew = resNew;
   315             while (itr != NULL) {
   273             while (iteratorNew != NULL) {
   316                 if (iterator->ai_family == itr->ai_family &&
   274                 if (iterator->ai_family == iteratorNew->ai_family &&
   317                     iterator->ai_addrlen == itr->ai_addrlen) {
   275                     iterator->ai_addrlen == iteratorNew->ai_addrlen) {
   318                     if (itr->ai_family == AF_INET) { /* AF_INET */
   276                     if (iteratorNew->ai_family == AF_INET) { /* AF_INET */
   319                         struct sockaddr_in *addr1, *addr2;
   277                         struct sockaddr_in *addr1, *addr2;
   320                         addr1 = (struct sockaddr_in *)iterator->ai_addr;
   278                         addr1 = (struct sockaddr_in *)iterator->ai_addr;
   321                         addr2 = (struct sockaddr_in *)itr->ai_addr;
   279                         addr2 = (struct sockaddr_in *)iteratorNew->ai_addr;
   322                         if (addr1->sin_addr.s_addr ==
   280                         if (addr1->sin_addr.s_addr == addr2->sin_addr.s_addr) {
   323                             addr2->sin_addr.s_addr) {
       
   324                             skip = 1;
   281                             skip = 1;
   325                             break;
   282                             break;
   326                         }
   283                         }
   327                     } else {
   284                     } else {
   328                         int t;
   285                         int t;
   329                         struct sockaddr_in6 *addr1, *addr2;
   286                         struct sockaddr_in6 *addr1, *addr2;
   330                         addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
   287                         addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
   331                         addr2 = (struct sockaddr_in6 *)itr->ai_addr;
   288                         addr2 = (struct sockaddr_in6 *)iteratorNew->ai_addr;
   332 
   289 
   333                         for (t = 0; t < 16; t++) {
   290                         for (t = 0; t < 16; t++) {
   334                             if (addr1->sin6_addr.s6_addr[t] !=
   291                             if (addr1->sin6_addr.s6_addr[t] !=
   335                                 addr2->sin6_addr.s6_addr[t]) {
   292                                 addr2->sin6_addr.s6_addr[t]) {
   336                                 break;
   293                                 break;
   337                             }
   294                             }
   338                         }
   295                         }
   339                         if (t < 16) {
   296                         if (t < 16) {
   340                             itr = itr->ai_next;
   297                             iteratorNew = iteratorNew->ai_next;
   341                             continue;
   298                             continue;
   342                         } else {
   299                         } else {
   343                             skip = 1;
   300                             skip = 1;
   344                             break;
   301                             break;
   345                         }
   302                         }
   346                     }
   303                     }
   347                 } else if (iterator->ai_family != AF_INET &&
   304                 } else if (iterator->ai_family != AF_INET &&
   348                            iterator->ai_family != AF_INET6) {
   305                            iterator->ai_family != AF_INET6) {
   349                     /* we can't handle other family types */
   306                     // we can't handle other family types
   350                     skip = 1;
   307                     skip = 1;
   351                     break;
   308                     break;
   352                 }
   309                 }
   353                 itr = itr->ai_next;
   310                 iteratorNew = iteratorNew->ai_next;
   354             }
   311             }
   355 
   312 
   356             if (!skip) {
   313             if (!skip) {
   357                 struct addrinfo *next
   314                 struct addrinfo *next
   358                     = (struct addrinfo*) malloc(sizeof(struct addrinfo));
   315                     = (struct addrinfo *)malloc(sizeof(struct addrinfo));
   359                 if (!next) {
   316                 if (!next) {
   360                     JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
   317                     JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
   361                     ret = NULL;
   318                     ret = NULL;
   362                     goto cleanupAndReturn;
   319                     goto cleanupAndReturn;
   363                 }
   320                 }
   369                     last->ai_next = next;
   326                     last->ai_next = next;
   370                 }
   327                 }
   371                 last = next;
   328                 last = next;
   372                 i++;
   329                 i++;
   373                 if (iterator->ai_family == AF_INET) {
   330                 if (iterator->ai_family == AF_INET) {
   374                     inetCount ++;
   331                     inetCount++;
   375                 } else if (iterator->ai_family == AF_INET6) {
   332                 } else if (iterator->ai_family == AF_INET6) {
   376                     inet6Count ++;
   333                     inet6Count++;
   377                 }
   334                 }
   378             }
   335             }
   379             iterator = iterator->ai_next;
   336             iterator = iterator->ai_next;
   380         }
   337         }
   381         retLen = i;
   338 
   382         iterator = resNew;
   339         // allocate array - at this point i contains the number of addresses
   383 
   340         ret = (*env)->NewObjectArray(env, i, ia_class, NULL);
   384         ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);
       
   385 
       
   386         if (IS_NULL(ret)) {
   341         if (IS_NULL(ret)) {
   387             /* we may have memory to free at the end of this */
   342             /* we may have memory to free at the end of this */
   388             goto cleanupAndReturn;
   343             goto cleanupAndReturn;
   389         }
   344         }
   390 
   345 
   391         addressPreference = (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
       
   392 
       
   393         if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
   346         if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
   394             /* AF_INET addresses will be offset by inet6Count */
       
   395             inetIndex = inet6Count;
   347             inetIndex = inet6Count;
   396             inet6Index = 0;
   348             inet6Index = 0;
   397         } else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
   349         } else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
   398             /* AF_INET6 addresses will be offset by inetCount */
       
   399             inetIndex = 0;
   350             inetIndex = 0;
   400             inet6Index = inetCount;
   351             inet6Index = inetCount;
   401         } else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
   352         } else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
   402             inetIndex = inet6Index = originalIndex = 0;
   353             inetIndex = inet6Index = originalIndex = 0;
   403         }
   354         }
   404 
   355 
       
   356         iterator = resNew;
   405         while (iterator != NULL) {
   357         while (iterator != NULL) {
   406             jboolean ret1;
       
   407             if (iterator->ai_family == AF_INET) {
   358             if (iterator->ai_family == AF_INET) {
   408                 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
   359                 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
   409                 if (IS_NULL(iaObj)) {
   360                 if (IS_NULL(iaObj)) {
   410                     ret = NULL;
   361                     ret = NULL;
   411                     goto cleanupAndReturn;
   362                     goto cleanupAndReturn;
   414                 setInetAddress_hostName(env, iaObj, host);
   365                 setInetAddress_hostName(env, iaObj, host);
   415                 (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
   366                 (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
   416                 inetIndex++;
   367                 inetIndex++;
   417             } else if (iterator->ai_family == AF_INET6) {
   368             } else if (iterator->ai_family == AF_INET6) {
   418                 jint scope = 0;
   369                 jint scope = 0;
   419 
   370                 jboolean ret1;
   420                 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
   371                 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
   421                 if (IS_NULL(iaObj)) {
   372                 if (IS_NULL(iaObj)) {
   422                     ret = NULL;
   373                     ret = NULL;
   423                     goto cleanupAndReturn;
   374                     goto cleanupAndReturn;
   424                 }
   375                 }
   425                 ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
   376                 ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
   426                 if (ret1 == JNI_FALSE) {
   377                 if (ret1 == JNI_FALSE) {
   427                     ret = NULL;
   378                     ret = NULL;
   428                     goto cleanupAndReturn;
   379                     goto cleanupAndReturn;
   429                 }
   380                 }
   430 
   381                 scope = ((struct sockaddr_in6 *)iterator->ai_addr)->sin6_scope_id;
   431                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
   382                 if (scope != 0) { // zero is default value, no need to set
   432                 if (scope != 0) { /* zero is default value, no need to set */
       
   433                     setInet6Address_scopeid(env, iaObj, scope);
   383                     setInet6Address_scopeid(env, iaObj, scope);
   434                 }
   384                 }
   435                 setInetAddress_hostName(env, iaObj, host);
   385                 setInetAddress_hostName(env, iaObj, host);
   436                 (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
   386                 (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
   437                 inet6Index++;
   387                 inet6Index++;
   441                 inetIndex = inet6Index = 0;
   391                 inetIndex = inet6Index = 0;
   442             }
   392             }
   443             iterator = iterator->ai_next;
   393             iterator = iterator->ai_next;
   444         }
   394         }
   445     }
   395     }
   446 
   396 cleanupAndReturn:
   447  cleanupAndReturn:
   397     JNU_ReleaseStringPlatformChars(env, host, hostname);
   448     {
   398     while (resNew != NULL) {
   449       struct addrinfo *iterator, *tmp;
   399         last = resNew;
   450         iterator = resNew;
   400         resNew = resNew->ai_next;
   451         while (iterator != NULL) {
   401         free(last);
   452             tmp = iterator;
   402     }
   453             iterator = iterator->ai_next;
   403     if (res != NULL) {
   454             free(tmp);
   404         freeaddrinfo(res);
   455         }
   405     }
   456         JNU_ReleaseStringPlatformChars(env, host, hostname);
       
   457     }
       
   458 
       
   459     freeaddrinfo(res);
       
   460 
       
   461     return ret;
   406     return ret;
   462 }
   407 }
   463 
   408 
   464 /*
   409 /*
   465  * Class:     java_net_Inet6AddressImpl
   410  * Class:     java_net_Inet6AddressImpl
   466  * Method:    getHostByAddr
   411  * Method:    getHostByAddr
   467  * Signature: (I)Ljava/lang/String;
   412  * Signature: (I)Ljava/lang/String;
       
   413  *
       
   414  * Theoretically the UnknownHostException could be enriched with gai error
       
   415  * information. But as it is silently ignored anyway, there's no need for this.
       
   416  * It's only important that either a valid hostname is returned or an
       
   417  * UnknownHostException is thrown.
   468  */
   418  */
   469 JNIEXPORT jstring JNICALL
   419 JNIEXPORT jstring JNICALL
   470 Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
   420 Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
   471                                             jbyteArray addrArray) {
   421                                              jbyteArray addrArray) {
   472 
       
   473     jstring ret = NULL;
   422     jstring ret = NULL;
   474 
   423     char host[NI_MAXHOST + 1];
   475     char host[NI_MAXHOST+1];
       
   476     int error = 0;
       
   477     int len = 0;
   424     int len = 0;
   478     jbyte caddr[16];
   425     jbyte caddr[16];
   479 
   426     SOCKETADDRESS sa;
   480     struct sockaddr_in him4;
   427 
   481     struct sockaddr_in6 him6;
   428     memset((void *)&sa, 0, sizeof(SOCKETADDRESS));
   482     struct sockaddr *sa;
   429 
   483 
   430     // construct a sockaddr_in structure (AF_INET or AF_INET6)
   484     /*
       
   485      * For IPv4 addresses construct a sockaddr_in structure.
       
   486      */
       
   487     if ((*env)->GetArrayLength(env, addrArray) == 4) {
   431     if ((*env)->GetArrayLength(env, addrArray) == 4) {
   488         jint addr;
   432         jint addr;
   489         (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
   433         (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
   490         addr = ((caddr[0]<<24) & 0xff000000);
   434         addr = ((caddr[0] << 24) & 0xff000000);
   491         addr |= ((caddr[1] <<16) & 0xff0000);
   435         addr |= ((caddr[1] << 16) & 0xff0000);
   492         addr |= ((caddr[2] <<8) & 0xff00);
   436         addr |= ((caddr[2] << 8) & 0xff00);
   493         addr |= (caddr[3] & 0xff);
   437         addr |= (caddr[3] & 0xff);
   494         memset((void *) &him4, 0, sizeof(him4));
   438         sa.sa4.sin_addr.s_addr = htonl(addr);
   495         him4.sin_addr.s_addr = htonl(addr);
   439         sa.sa4.sin_family = AF_INET;
   496         him4.sin_family = AF_INET;
   440         len = sizeof(struct sockaddr_in);
   497         sa = (struct sockaddr *)&him4;
       
   498         len = sizeof(him4);
       
   499     } else {
   441     } else {
   500         /*
       
   501          * For IPv6 address construct a sockaddr_in6 structure.
       
   502          */
       
   503         (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
   442         (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
   504         memset((void *)&him6, 0, sizeof(him6));
   443         memcpy((void *)&sa.sa6.sin6_addr, caddr, sizeof(struct in6_addr));
   505         memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr));
   444         sa.sa6.sin6_family = AF_INET6;
   506         him6.sin6_family = AF_INET6;
   445         len = sizeof(struct sockaddr_in6);
   507         sa = (struct sockaddr *)&him6;
   446     }
   508         len = sizeof(him6);
   447 
   509     }
   448     if (getnameinfo(&sa.sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD)) {
   510 
   449         JNU_ThrowByName(env, "java/net/UnknownHostException", NULL);
   511     error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
   450     } else {
   512 
       
   513     if (!error) {
       
   514         ret = (*env)->NewStringUTF(env, host);
   451         ret = (*env)->NewStringUTF(env, host);
   515         CHECK_NULL_RETURN(ret, NULL);
   452         if (ret == NULL) {
   516     }
   453             JNU_ThrowByName(env, "java/net/UnknownHostException", NULL);
   517 
   454         }
   518     if (ret == NULL) {
       
   519         JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
       
   520     }
   455     }
   521 
   456 
   522     return ret;
   457     return ret;
   523 }
   458 }
   524 
   459 
   525 #define SET_NONBLOCKING(fd) {           \
   460 /**
   526         int flags = fcntl(fd, F_GETFL); \
   461  * ping implementation using tcp port 7 (echo)
   527         flags |= O_NONBLOCK;            \
   462  */
   528         fcntl(fd, F_SETFL, flags);      \
   463 static jboolean
       
   464 tcp_ping6(JNIEnv *env, SOCKETADDRESS *sa, SOCKETADDRESS *netif, jint timeout,
       
   465           jint ttl)
       
   466 {
       
   467     jint fd;
       
   468     int connect_rv = -1;
       
   469 
       
   470     // open a TCP socket
       
   471     fd = socket(AF_INET6, SOCK_STREAM, 0);
       
   472     if (fd == -1) {
       
   473         // note: if you run out of fds, you may not be able to load
       
   474         // the exception class, and get a NoClassDefFoundError instead.
       
   475         NET_ThrowNew(env, errno, "Can't create socket");
       
   476         return JNI_FALSE;
       
   477     }
       
   478 
       
   479     // set TTL
       
   480     if (ttl > 0) {
       
   481         setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
       
   482     }
       
   483 
       
   484     // A network interface was specified, so let's bind to it.
       
   485     if (netif != NULL) {
       
   486         if (bind(fd, &netif->sa, sizeof(struct sockaddr_in6)) <0) {
       
   487             NET_ThrowNew(env, errno, "Can't bind socket");
       
   488             close(fd);
       
   489             return JNI_FALSE;
       
   490         }
       
   491     }
       
   492 
       
   493     // Make the socket non blocking so we can use select/poll.
       
   494     SET_NONBLOCKING(fd);
       
   495 
       
   496     sa->sa6.sin6_port = htons(7); // echo port
       
   497     connect_rv = NET_Connect(fd, &sa->sa, sizeof(struct sockaddr_in6));
       
   498 
       
   499     // connection established or refused immediately, either way it means
       
   500     // we were able to reach the host!
       
   501     if (connect_rv == 0 || errno == ECONNREFUSED) {
       
   502         close(fd);
       
   503         return JNI_TRUE;
       
   504     }
       
   505 
       
   506     switch (errno) {
       
   507     case ENETUNREACH:   // Network Unreachable
       
   508     case EAFNOSUPPORT:  // Address Family not supported
       
   509     case EADDRNOTAVAIL: // address is not available on the remote machine
       
   510 #if defined(__linux__) || defined(_AIX)
       
   511         // On some Linux versions, when a socket is bound to the loopback
       
   512         // interface, connect will fail and errno will be set to EINVAL
       
   513         // or EHOSTUNREACH.  When that happens, don't throw an exception,
       
   514         // just return false.
       
   515     case EINVAL:
       
   516     case EHOSTUNREACH:  // No route to host
       
   517 #endif
       
   518         close(fd);
       
   519         return JNI_FALSE;
       
   520     case EINPROGRESS:   // this is expected as we'll probably have to wait
       
   521         break;
       
   522     default:
       
   523         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
       
   524                                      "connect failed");
       
   525         close(fd);
       
   526         return JNI_FALSE;
       
   527     }
       
   528 
       
   529     timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
       
   530     if (timeout >= 0) {
       
   531         // connection has been established, check for error condition
       
   532         socklen_t optlen = (socklen_t)sizeof(connect_rv);
       
   533         if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
       
   534                        &optlen) <0)
       
   535         {
       
   536             connect_rv = errno;
       
   537         }
       
   538         if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
       
   539             close(fd);
       
   540             return JNI_TRUE;
       
   541         }
       
   542     }
       
   543     close(fd);
       
   544     return JNI_FALSE;
   529 }
   545 }
   530 
   546 
       
   547 /**
       
   548  * ping implementation.
       
   549  * Send an ICMP_ECHO_REQUEST packet every second until either the timeout
       
   550  * expires or an answer is received.
       
   551  * Returns true if an ECHO_REPLY is received, false otherwise.
       
   552  */
   531 static jboolean
   553 static jboolean
   532 ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
   554 ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif,
   533       struct sockaddr_in6* netif, jint ttl) {
   555       jint timeout, jint ttl)
   534     jint size;
   556 {
   535     jint n;
   557     jint n, size = 60 * 1024, tmout2, seq = 1;
   536     socklen_t len;
   558     socklen_t len;
   537     char sendbuf[1500];
   559     unsigned char sendbuf[1500], recvbuf[1500];
   538     unsigned char recvbuf[1500];
       
   539     struct icmp6_hdr *icmp6;
   560     struct icmp6_hdr *icmp6;
   540     struct sockaddr_in6 sa_recv;
   561     struct sockaddr_in6 sa_recv;
   541     jbyte *caddr, *recv_caddr;
       
   542     jchar pid;
   562     jchar pid;
   543     jint tmout2, seq = 1;
       
   544     struct timeval tv;
   563     struct timeval tv;
   545     size_t plen;
   564     size_t plen = sizeof(struct icmp6_hdr) + sizeof(tv);
   546 
   565 
   547 #ifdef __linux__
   566 #if defined(__linux__)
   548     {
       
   549     int csum_offset;
       
   550     /**
   567     /**
   551      * For some strange reason, the linux kernel won't calculate the
   568      * For some strange reason, the linux kernel won't calculate the
   552      * checksum of ICMPv6 packets unless you set this socket option
   569      * checksum of ICMPv6 packets unless you set this socket option
   553      */
   570      */
   554     csum_offset = 2;
   571     int csum_offset = 2;
   555     setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
   572     setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
   556     }
   573 #endif
   557 #endif
   574 
   558 
   575     setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
   559     caddr = (jbyte *)&(him->sin6_addr);
   576 
   560 
   577     // sets the ttl (max number of hops)
   561     /* icmp_id is a 16 bit data type, therefore down cast the pid */
   578     if (ttl > 0) {
       
   579         setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
       
   580     }
       
   581 
       
   582     // a specific interface was specified, so let's bind the socket
       
   583     // to that interface to ensure the requests are sent only through it.
       
   584     if (netif != NULL) {
       
   585         if (bind(fd, &netif->sa, sizeof(struct sockaddr_in6)) <0) {
       
   586             NET_ThrowNew(env, errno, "Can't bind socket");
       
   587             close(fd);
       
   588             return JNI_FALSE;
       
   589         }
       
   590     }
       
   591 
       
   592     // icmp_id is a 16 bit data type, therefore down cast the pid
   562     pid = (jchar)getpid();
   593     pid = (jchar)getpid();
   563     size = 60*1024;
   594 
   564     setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
   595     // Make the socket non blocking so we can use select
   565     if (ttl > 0) {
       
   566       setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
       
   567     }
       
   568     if (netif != NULL) {
       
   569       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
       
   570         NET_ThrowNew(env, errno, "Can't bind socket");
       
   571         close(fd);
       
   572         return JNI_FALSE;
       
   573       }
       
   574     }
       
   575     SET_NONBLOCKING(fd);
   596     SET_NONBLOCKING(fd);
   576 
       
   577     do {
   597     do {
   578       icmp6 = (struct icmp6_hdr *) sendbuf;
   598         // create the ICMP request
   579       icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
   599         icmp6 = (struct icmp6_hdr *)sendbuf;
   580       icmp6->icmp6_code = 0;
   600         icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
   581       /* let's tag the ECHO packet with our pid so we can identify it */
   601         icmp6->icmp6_code = 0;
   582       icmp6->icmp6_id = htons(pid);
   602         // let's tag the ECHO packet with our pid so we can identify it
   583       icmp6->icmp6_seq = htons(seq);
   603         icmp6->icmp6_id = htons(pid);
   584       seq++;
   604         icmp6->icmp6_seq = htons(seq);
   585       icmp6->icmp6_cksum = 0;
   605         seq++;
   586       gettimeofday(&tv, NULL);
   606         gettimeofday(&tv, NULL);
   587       memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
   607         memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
   588       plen = sizeof(struct icmp6_hdr) + sizeof(tv);
   608         icmp6->icmp6_cksum = 0;
   589       n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
   609         // send it
   590       if (n < 0 && errno != EINPROGRESS) {
   610         n = sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in6));
   591 #ifdef __linux__
   611         if (n < 0 && errno != EINPROGRESS) {
   592         if (errno != EINVAL && errno != EHOSTUNREACH)
   612 #if defined(__linux__)
   593           /*
   613             /*
   594            * On some Linux versions, when a socket is  bound to the
   614              * On some Linux versions, when a socket is bound to the loopback
   595            * loopback interface, sendto will fail and errno will be
   615              * interface, sendto will fail and errno will be set to
   596            * set to EINVAL or EHOSTUNREACH.
   616              * EINVAL or EHOSTUNREACH. When that happens, don't throw an
   597            * When that happens, don't throw an exception, just return false.
   617              * exception, just return false.
   598            */
   618              */
   599 #endif /*__linux__ */
   619             if (errno != EINVAL && errno != EHOSTUNREACH) {
   600         NET_ThrowNew(env, errno, "Can't send ICMP packet");
   620                 NET_ThrowNew(env, errno, "Can't send ICMP packet");
   601         close(fd);
       
   602         return JNI_FALSE;
       
   603       }
       
   604 
       
   605       tmout2 = timeout > 1000 ? 1000 : timeout;
       
   606       do {
       
   607         tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
       
   608 
       
   609         if (tmout2 >= 0) {
       
   610           len = sizeof(sa_recv);
       
   611           n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);
       
   612           icmp6 = (struct icmp6_hdr *) (recvbuf);
       
   613           recv_caddr = (jbyte *)&(sa_recv.sin6_addr);
       
   614           /*
       
   615            * We did receive something, but is it what we were expecting?
       
   616            * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
       
   617            *       from the host that we are trying to determine is reachable.
       
   618            */
       
   619           if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
       
   620               (ntohs(icmp6->icmp6_id) == pid)) {
       
   621             if (NET_IsEqual(caddr, recv_caddr)) {
       
   622               close(fd);
       
   623               return JNI_TRUE;
       
   624             }
   621             }
   625             if (NET_IsZeroAddr(caddr)) {
   622 #else
   626               close(fd);
   623             NET_ThrowNew(env, errno, "Can't send ICMP packet");
   627               return JNI_TRUE;
   624 #endif
       
   625             close(fd);
       
   626             return JNI_FALSE;
       
   627         }
       
   628 
       
   629         tmout2 = timeout > 1000 ? 1000 : timeout;
       
   630         do {
       
   631             tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
       
   632             if (tmout2 >= 0) {
       
   633                 len = sizeof(sa_recv);
       
   634                 n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0,
       
   635                              (struct sockaddr *)&sa_recv, &len);
       
   636                 // check if we received enough data
       
   637                 if (n < (jint)sizeof(struct icmp6_hdr)) {
       
   638                     continue;
       
   639                 }
       
   640                 icmp6 = (struct icmp6_hdr *)recvbuf;
       
   641                 // We did receive something, but is it what we were expecting?
       
   642                 // I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
       
   643                 //       from the host that we are trying to determine is reachable.
       
   644                 if (icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
       
   645                     (ntohs(icmp6->icmp6_id) == pid))
       
   646                 {
       
   647                     if (NET_IsEqual((jbyte *)&sa->sa6.sin6_addr,
       
   648                                     (jbyte *)&sa_recv.sin6_addr)) {
       
   649                         close(fd);
       
   650                         return JNI_TRUE;
       
   651                     } else if (NET_IsZeroAddr((jbyte *)&sa->sa6.sin6_addr)) {
       
   652                         close(fd);
       
   653                         return JNI_TRUE;
       
   654                     }
       
   655                 }
   628             }
   656             }
   629           }
   657         } while (tmout2 > 0);
   630         }
   658         timeout -= 1000;
   631       } while (tmout2 > 0);
       
   632       timeout -= 1000;
       
   633     } while (timeout > 0);
   659     } while (timeout > 0);
   634     close(fd);
   660     close(fd);
   635     return JNI_FALSE;
   661     return JNI_FALSE;
   636 }
   662 }
   637 
   663 
   640  * Method:    isReachable0
   666  * Method:    isReachable0
   641  * Signature: ([bII[bI)Z
   667  * Signature: ([bII[bI)Z
   642  */
   668  */
   643 JNIEXPORT jboolean JNICALL
   669 JNIEXPORT jboolean JNICALL
   644 Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
   670 Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
   645                                            jbyteArray addrArray,
   671                                             jbyteArray addrArray, jint scope,
   646                                            jint scope,
   672                                             jint timeout, jbyteArray ifArray,
   647                                            jint timeout,
   673                                             jint ttl, jint if_scope)
   648                                            jbyteArray ifArray,
   674 {
   649                                            jint ttl, jint if_scope) {
       
   650     jbyte caddr[16];
   675     jbyte caddr[16];
   651     jint fd, sz;
   676     jint sz, fd;
   652     struct sockaddr_in6 him6;
   677     SOCKETADDRESS sa, inf, *netif = NULL;
   653     struct sockaddr_in6 inf6;
   678 
   654     struct sockaddr_in6* netif = NULL;
   679     // If IPv6 is not enabled, then we can't reach an IPv6 address, can we?
   655     int len = 0;
   680     // Actually, we probably shouldn't even get here.
   656     int connect_rv = -1;
       
   657 
       
   658     /*
       
   659      * If IPv6 is not enable, then we can't reach an IPv6 address, can we?
       
   660      */
       
   661     if (!ipv6_available()) {
   681     if (!ipv6_available()) {
   662       return JNI_FALSE;
   682         return JNI_FALSE;
   663     }
   683     }
   664     /*
   684 
   665      * If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
   685     // If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
   666      * therefore, let's delegate to the Inet4Address method.
   686     // therefore, let's delegate to the Inet4Address method.
   667      */
       
   668     sz = (*env)->GetArrayLength(env, addrArray);
   687     sz = (*env)->GetArrayLength(env, addrArray);
   669     if (sz == 4) {
   688     if (sz == 4) {
   670       return Java_java_net_Inet4AddressImpl_isReachable0(env, this,
   689         return Java_java_net_Inet4AddressImpl_isReachable0(env, this,
   671                                                          addrArray,
   690                                                            addrArray, timeout,
   672                                                          timeout,
   691                                                            ifArray, ttl);
   673                                                          ifArray, ttl);
   692     }
   674     }
   693 
   675 
   694     // load address to SOCKETADDRESS
   676     memset((void *) caddr, 0, 16);
   695     memset((char *)caddr, 0, 16);
   677     memset((void *) &him6, 0, sizeof(him6));
       
   678     (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
   696     (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
   679     memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
   697     memset((char *)&sa, 0, sizeof(SOCKETADDRESS));
   680     him6.sin6_family = AF_INET6;
   698     memcpy((void *)&sa.sa6.sin6_addr, caddr, sizeof(struct in6_addr));
   681 #ifdef __linux__
   699     sa.sa6.sin6_family = AF_INET6;
   682     if (scope > 0)
   700     if (scope > 0) {
   683       him6.sin6_scope_id = scope;
   701         sa.sa6.sin6_scope_id = scope;
   684     else
   702 #if defined(__linux__)
   685       him6.sin6_scope_id = getDefaultIPv6Interface( &(him6.sin6_addr));
   703     } else {
   686     len = sizeof(struct sockaddr_in6);
   704         sa.sa6.sin6_scope_id = getDefaultIPv6Interface(&sa.sa6.sin6_addr);
   687 #else
   705 #endif
   688     if (scope > 0)
   706     }
   689       him6.sin6_scope_id = scope;
   707 
   690     len = sizeof(struct sockaddr_in6);
   708     // load network interface address to SOCKETADDRESS, if specified
   691 #endif
       
   692     /*
       
   693      * If a network interface was specified, let's create the address
       
   694      * for it.
       
   695      */
       
   696     if (!(IS_NULL(ifArray))) {
   709     if (!(IS_NULL(ifArray))) {
   697       memset((void *) caddr, 0, 16);
   710         memset((char *)caddr, 0, 16);
   698       memset((void *) &inf6, 0, sizeof(inf6));
   711         (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
   699       (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
   712         memset((char *)&inf, 0, sizeof(SOCKETADDRESS));
   700       memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
   713         memcpy((void *)&inf.sa6.sin6_addr, caddr, sizeof(struct in6_addr));
   701       inf6.sin6_family = AF_INET6;
   714         inf.sa6.sin6_family = AF_INET6;
   702       inf6.sin6_scope_id = if_scope;
   715         inf.sa6.sin6_scope_id = if_scope;
   703       netif = &inf6;
   716         netif = &inf;
   704     }
   717     }
   705     /*
   718 
   706      * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
   719     // Let's try to create a RAW socket to send ICMP packets.
   707      * otherwise we'll try a tcp socket to the Echo port (7).
   720     // This usually requires "root" privileges, so it's likely to fail.
   708      * Note that this is empiric, and not connecting could mean it's blocked
       
   709      * or the echo service has been disabled.
       
   710      */
       
   711 
       
   712     fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
   721     fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
   713 
       
   714     if (fd != -1) { /* Good to go, let's do a ping */
       
   715         return ping6(env, fd, &him6, timeout, netif, ttl);
       
   716     }
       
   717 
       
   718     /* No good, let's fall back on TCP */
       
   719     fd = socket(AF_INET6, SOCK_STREAM, 0);
       
   720     if (fd == -1) {
   722     if (fd == -1) {
   721         /* note: if you run out of fds, you may not be able to load
   723         return tcp_ping6(env, &sa, netif, timeout, ttl);
   722          * the exception class, and get a NoClassDefFoundError
       
   723          * instead.
       
   724          */
       
   725         NET_ThrowNew(env, errno, "Can't create socket");
       
   726         return JNI_FALSE;
       
   727     }
       
   728     if (ttl > 0) {
       
   729       setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
       
   730     }
       
   731 
       
   732     /*
       
   733      * A network interface was specified, so let's bind to it.
       
   734      */
       
   735     if (netif != NULL) {
       
   736       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
       
   737         NET_ThrowNew(env, errno, "Can't bind socket");
       
   738         close(fd);
       
   739         return JNI_FALSE;
       
   740       }
       
   741     }
       
   742     SET_NONBLOCKING(fd);
       
   743 
       
   744     him6.sin6_port = htons((short) 7); /* Echo port */
       
   745     connect_rv = NET_Connect(fd, (struct sockaddr *)&him6, len);
       
   746 
       
   747     /**
       
   748      * connection established or refused immediately, either way it means
       
   749      * we were able to reach the host!
       
   750      */
       
   751     if (connect_rv == 0 || errno == ECONNREFUSED) {
       
   752         close(fd);
       
   753         return JNI_TRUE;
       
   754     } else {
   724     } else {
   755         socklen_t optlen = (socklen_t)sizeof(connect_rv);
   725         // It didn't fail, so we can use ICMP_ECHO requests.
   756 
   726         return ping6(env, fd, &sa, netif, timeout, ttl);
   757         switch (errno) {
       
   758         case ENETUNREACH: /* Network Unreachable */
       
   759         case EAFNOSUPPORT: /* Address Family not supported */
       
   760         case EADDRNOTAVAIL: /* address is not available on  the  remote machine */
       
   761 #if defined(__linux__) || defined(_AIX)
       
   762         case EINVAL:
       
   763         case EHOSTUNREACH: /* No route to host */
       
   764           /*
       
   765            * On some Linux versions, when  a socket is bound to the
       
   766            * loopback interface, connect will fail and errno will
       
   767            * be set to EINVAL or EHOSTUNREACH.  When that happens,
       
   768            * don't throw an exception, just return false.
       
   769            */
       
   770 #endif /* __linux__ */
       
   771           close(fd);
       
   772           return JNI_FALSE;
       
   773         }
       
   774 
       
   775         if (errno != EINPROGRESS) {
       
   776             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
       
   777                                          "connect failed");
       
   778             close(fd);
       
   779             return JNI_FALSE;
       
   780         }
       
   781 
       
   782         timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
       
   783 
       
   784         if (timeout >= 0) {
       
   785           /* has connection been established */
       
   786           if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
       
   787                          &optlen) <0) {
       
   788             connect_rv = errno;
       
   789           }
       
   790           if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
       
   791             close(fd);
       
   792             return JNI_TRUE;
       
   793           }
       
   794         }
       
   795         close(fd);
       
   796         return JNI_FALSE;
       
   797     }
   727     }
   798 }
   728 }