src/solaris/native/java/net/Inet6AddressImpl.c

Print this page




  95                 error = (*getnameinfo_ptr)(res->ai_addr,
  96                                            res->ai_addrlen,
  97                                            hostname,
  98                                            NI_MAXHOST,
  99                                            NULL,
 100                                            0,
 101                                            NI_NAMEREQD);
 102 
 103                 /* if getnameinfo fails hostname is still the value
 104                    from gethostname */
 105 
 106                 (*freeaddrinfo_ptr)(res);
 107             }
 108         }
 109 #endif /* AF_INET6 */
 110 #endif /* __linux__ */
 111     }
 112     return (*env)->NewStringUTF(env, hostname);
 113 }
 114 
 115 static jclass ni_iacls;
 116 static jclass ni_ia4cls;
 117 static jclass ni_ia6cls;
 118 static jmethodID ni_ia4ctrID;
 119 static jmethodID ni_ia6ctrID;
 120 static jfieldID ni_iaaddressID;
 121 static jfieldID ni_iahostID;
 122 static jfieldID ni_iafamilyID;
 123 static jfieldID ni_ia6ipaddressID;
 124 static int initialized = 0;
 125 
 126 /*
 127  * Find an internet address for a given hostname.  Not this this
 128  * code only works for addresses of type INET. The translation
 129  * of %d.%d.%d.%d to an address (int) occurs in java now, so the
 130  * String "host" shouldn't *ever* be a %d.%d.%d.%d string
 131  *
 132  * Class:     java_net_Inet6AddressImpl
 133  * Method:    lookupAllHostAddr
 134  * Signature: (Ljava/lang/String;)[[B
 135  */
 136 
 137 JNIEXPORT jobjectArray JNICALL
 138 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
 139                                                 jstring host) {
 140     const char *hostname;
 141     jobjectArray ret = 0;
 142     int retLen = 0;
 143     jboolean preferIPv6Address;
 144 
 145     int error=0;
 146 #ifdef AF_INET6
 147     struct addrinfo hints, *res, *resNew = NULL;
 148 #endif /* AF_INET6 */
 149 
 150     if (!initialized) {
 151       ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
 152       ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
 153       ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
 154       ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
 155       ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
 156       ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
 157       ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
 158       ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
 159       ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
 160       ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
 161       ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
 162       ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
 163       initialized = 1;
 164     }
 165 
 166     if (IS_NULL(host)) {
 167         JNU_ThrowNullPointerException(env, "host is null");
 168         return 0;
 169     }
 170     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
 171     CHECK_NULL_RETURN(hostname, NULL);
 172 
 173 #ifdef AF_INET6
 174     if (NET_addrtransAvailable()) {
 175         static jfieldID ia_preferIPv6AddressID;
 176         if (ia_preferIPv6AddressID == NULL) {
 177             jclass c = (*env)->FindClass(env,"java/net/InetAddress");
 178             if (c)  {
 179                 ia_preferIPv6AddressID =
 180                     (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
 181             }
 182             if (ia_preferIPv6AddressID == NULL) {
 183                 JNU_ReleaseStringPlatformChars(env, host, hostname);
 184                 return NULL;
 185             }
 186         }
 187         /* get the address preference */
 188         preferIPv6Address
 189             = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
 190 
 191         /* Try once, with our static buffer. */
 192         bzero(&hints, sizeof(hints));
 193         hints.ai_flags = AI_CANONNAME;
 194         hints.ai_family = AF_UNSPEC;
 195 
 196 #ifdef __solaris__
 197         /*
 198          * Workaround for Solaris bug 4160367 - if a hostname contains a
 199          * white space then 0.0.0.0 is returned
 200          */
 201         if (isspace((unsigned char)hostname[0])) {
 202             JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
 203                             (char *)hostname);
 204             JNU_ReleaseStringPlatformChars(env, host, hostname);
 205             return NULL;
 206         }


 273                     memcpy(next, iterator, sizeof(struct addrinfo));
 274                     next->ai_next = NULL;
 275                     if (resNew == NULL) {
 276                         resNew = next;
 277                     } else {
 278                         last->ai_next = next;
 279                     }
 280                     last = next;
 281                     i++;
 282                     if (iterator->ai_family == AF_INET) {
 283                         inetCount ++;
 284                     } else if (iterator->ai_family == AF_INET6) {
 285                         inet6Count ++;
 286                     }
 287                 }
 288                 iterator = iterator->ai_next;
 289             }
 290             retLen = i;
 291             iterator = resNew;
 292 
 293             ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
 294 
 295             if (IS_NULL(ret)) {
 296                 /* we may have memory to free at the end of this */
 297                 goto cleanupAndReturn;
 298             }
 299 
 300             if (preferIPv6Address) {
 301                 /* AF_INET addresses will be offset by inet6Count */
 302                 inetIndex = inet6Count;
 303                 inet6Index = 0;
 304             } else {
 305                 /* AF_INET6 addresses will be offset by inetCount */
 306                 inetIndex = 0;
 307                 inet6Index = inetCount;
 308             }
 309 
 310             while (iterator != NULL) {
 311               if (iterator->ai_family == AF_INET) {
 312                 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
 313                 if (IS_NULL(iaObj)) {
 314                   ret = NULL;
 315                   goto cleanupAndReturn;
 316                 }
 317                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
 318                                     ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
 319                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
 320                 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
 321                 inetIndex++;
 322               } else if (iterator->ai_family == AF_INET6) {
 323                 jint scope = 0;
 324                 jbyteArray ipaddress;
 325 
 326                 jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
 327                 if (IS_NULL(iaObj)) {
 328                   ret = NULL;
 329                   goto cleanupAndReturn;
 330                 }
 331                 ipaddress = (*env)->NewByteArray(env, 16);
 332                 if (IS_NULL(ipaddress)) {
 333                   ret = NULL;
 334                   goto cleanupAndReturn;
 335                 }
 336                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 337                                            (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
 338 #ifdef __linux__
 339                 if (!kernelIsV22()) {
 340                   scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 341                 }
 342 #else
 343                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 344 #endif
 345                 if (scope != 0) { /* zero is default value, no need to set */
 346                   (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 347                   (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 348                 }
 349                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
 350                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
 351                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
 352                 inet6Index++;
 353               }
 354               iterator = iterator->ai_next;
 355             }
 356         }
 357     }
 358 
 359 cleanupAndReturn:
 360     {
 361         struct addrinfo *iterator, *tmp;
 362         iterator = resNew;
 363         while (iterator != NULL) {
 364             tmp = iterator;
 365             iterator = iterator->ai_next;
 366             free(tmp);
 367         }
 368         JNU_ReleaseStringPlatformChars(env, host, hostname);
 369     }
 370 




  95                 error = (*getnameinfo_ptr)(res->ai_addr,
  96                                            res->ai_addrlen,
  97                                            hostname,
  98                                            NI_MAXHOST,
  99                                            NULL,
 100                                            0,
 101                                            NI_NAMEREQD);
 102 
 103                 /* if getnameinfo fails hostname is still the value
 104                    from gethostname */
 105 
 106                 (*freeaddrinfo_ptr)(res);
 107             }
 108         }
 109 #endif /* AF_INET6 */
 110 #endif /* __linux__ */
 111     }
 112     return (*env)->NewStringUTF(env, hostname);
 113 }
 114 











 115 /*
 116  * Find an internet address for a given hostname.  Not this this
 117  * code only works for addresses of type INET. The translation
 118  * of %d.%d.%d.%d to an address (int) occurs in java now, so the
 119  * String "host" shouldn't *ever* be a %d.%d.%d.%d string
 120  *
 121  * Class:     java_net_Inet6AddressImpl
 122  * Method:    lookupAllHostAddr
 123  * Signature: (Ljava/lang/String;)[[B
 124  */
 125 
 126 JNIEXPORT jobjectArray JNICALL
 127 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
 128                                                 jstring host) {
 129     const char *hostname;
 130     jobjectArray ret = 0;
 131     int retLen = 0;
 132     jboolean preferIPv6Address;
 133 
 134     int error=0;
 135 #ifdef AF_INET6
 136     struct addrinfo hints, *res, *resNew = NULL;
 137 #endif /* AF_INET6 */
 138 
 139     init(env);














 140 
 141     if (IS_NULL(host)) {
 142         JNU_ThrowNullPointerException(env, "host is null");
 143         return 0;
 144     }
 145     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
 146     CHECK_NULL_RETURN(hostname, NULL);
 147 
 148 #ifdef AF_INET6
 149     if (NET_addrtransAvailable()) {












 150         /* get the address preference */
 151         preferIPv6Address
 152             = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
 153 
 154         /* Try once, with our static buffer. */
 155         bzero(&hints, sizeof(hints));
 156         hints.ai_flags = AI_CANONNAME;
 157         hints.ai_family = AF_UNSPEC;
 158 
 159 #ifdef __solaris__
 160         /*
 161          * Workaround for Solaris bug 4160367 - if a hostname contains a
 162          * white space then 0.0.0.0 is returned
 163          */
 164         if (isspace((unsigned char)hostname[0])) {
 165             JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
 166                             (char *)hostname);
 167             JNU_ReleaseStringPlatformChars(env, host, hostname);
 168             return NULL;
 169         }


 236                     memcpy(next, iterator, sizeof(struct addrinfo));
 237                     next->ai_next = NULL;
 238                     if (resNew == NULL) {
 239                         resNew = next;
 240                     } else {
 241                         last->ai_next = next;
 242                     }
 243                     last = next;
 244                     i++;
 245                     if (iterator->ai_family == AF_INET) {
 246                         inetCount ++;
 247                     } else if (iterator->ai_family == AF_INET6) {
 248                         inet6Count ++;
 249                     }
 250                 }
 251                 iterator = iterator->ai_next;
 252             }
 253             retLen = i;
 254             iterator = resNew;
 255 
 256             ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);
 257 
 258             if (IS_NULL(ret)) {
 259                 /* we may have memory to free at the end of this */
 260                 goto cleanupAndReturn;
 261             }
 262 
 263             if (preferIPv6Address) {
 264                 /* AF_INET addresses will be offset by inet6Count */
 265                 inetIndex = inet6Count;
 266                 inet6Index = 0;
 267             } else {
 268                 /* AF_INET6 addresses will be offset by inetCount */
 269                 inetIndex = 0;
 270                 inet6Index = inetCount;
 271             }
 272 
 273             while (iterator != NULL) {
 274               if (iterator->ai_family == AF_INET) {
 275                 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
 276                 if (IS_NULL(iaObj)) {
 277                   ret = NULL;
 278                   goto cleanupAndReturn;
 279                 }
 280                 (*env)->SetIntField(env, iaObj, ia_addressID,
 281                                     ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
 282                 (*env)->SetObjectField(env, iaObj, ia_hostNameID, host);
 283                 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
 284                 inetIndex++;
 285               } else if (iterator->ai_family == AF_INET6) {
 286                 jint scope = 0;
 287                 jbyteArray ipaddress;
 288 
 289                 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
 290                 if (IS_NULL(iaObj)) {
 291                   ret = NULL;
 292                   goto cleanupAndReturn;
 293                 }
 294                 ipaddress = (*env)->NewByteArray(env, 16);
 295                 if (IS_NULL(ipaddress)) {
 296                   ret = NULL;
 297                   goto cleanupAndReturn;
 298                 }
 299                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 300                                            (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
 301 #ifdef __linux__
 302                 if (!kernelIsV22()) {
 303                   scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 304                 }
 305 #else
 306                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 307 #endif
 308                 if (scope != 0) { /* zero is default value, no need to set */
 309                   (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 310                   (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 311                 }
 312                 (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
 313                 (*env)->SetObjectField(env, iaObj, ia_hostNameID, host);
 314                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
 315                 inet6Index++;
 316               }
 317               iterator = iterator->ai_next;
 318             }
 319         }
 320     }
 321 
 322 cleanupAndReturn:
 323     {
 324         struct addrinfo *iterator, *tmp;
 325         iterator = resNew;
 326         while (iterator != NULL) {
 327             tmp = iterator;
 328             iterator = iterator->ai_next;
 329             free(tmp);
 330         }
 331         JNU_ReleaseStringPlatformChars(env, host, hostname);
 332     }
 333