changeset 4757:81987765cb81

7112670: Inet4AddressImpl should use getaddrinfo/getnameinfo Reviewed-by: chegar, alanb, mduigou, ngmr Contributed-by: Charles Lee <littlee@linux.vnet.ibm.com>
author ngmr
date Fri, 11 Nov 2011 14:40:18 +0000
parents 2db942c7eb9c
children ee2fa62fb09f
files src/solaris/native/java/net/Inet4AddressImpl.c src/solaris/native/java/net/Inet6AddressImpl.c src/solaris/native/java/net/net_util_md.c src/solaris/native/java/net/net_util_md.h
diffstat 4 files changed, 315 insertions(+), 378 deletions(-) [+]
line wrap: on
line diff
--- a/src/solaris/native/java/net/Inet4AddressImpl.c	Mon Nov 21 12:57:36 2011 +0000
+++ b/src/solaris/native/java/net/Inet4AddressImpl.c	Fri Nov 11 14:40:18 2011 +0000
@@ -43,8 +43,9 @@
 #include "java_net_Inet4AddressImpl.h"
 
 /* the initial size of our hostent buffers */
-#define HENT_BUF_SIZE 1024
-#define BIG_HENT_BUF_SIZE 10240  /* a jumbo-sized one */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
 
 /************************************************************************
  * Inet4AddressImpl
@@ -57,60 +58,36 @@
  */
 JNIEXPORT jstring JNICALL
 Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
-    char hostname[MAXHOSTNAMELEN+1];
+    char hostname[NI_MAXHOST+1];
 
     hostname[0] = '\0';
     if (JVM_GetHostName(hostname, sizeof(hostname))) {
         /* Something went wrong, maybe networking is not setup? */
         strcpy(hostname, "localhost");
     } else {
-#ifdef __linux__
-        /* On Linux gethostname() says "host.domain.sun.com".  On
-         * Solaris gethostname() says "host", so extra work is needed.
-         */
-#else
-        /* Solaris doesn't want to give us a fully qualified domain name.
-         * We do a reverse lookup to try and get one.  This works
-         * if DNS occurs before NIS in /etc/resolv.conf, but fails
-         * if NIS comes first (it still gets only a partial name).
-         * We use thread-safe system calls.
-         */
-#endif /* __linux__ */
-        struct hostent res, res2, *hp;
-        // these buffers must be pointer-aligned so they are declared
-        // with pointer type
-        char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-        char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
-        int h_error=0;
+        hostname[NI_MAXHOST] = '\0';
+        struct addrinfo  hints, *res;
+        int error;
 
-        // ensure null-terminated
-        hostname[MAXHOSTNAMELEN] = '\0';
+        bzero(&hints, sizeof(hints));
+        hints.ai_flags = AI_CANONNAME;
+        hints.ai_family = AF_INET;
 
-#ifdef __GLIBC__
-        gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-        hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
-#endif
-        if (hp) {
-#ifdef __GLIBC__
-            gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
-                            &res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
-#else
-            hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
-                                 &res2, (char*)buf2, sizeof(buf2), &h_error);
-#endif
-            if (hp) {
-                /*
-                 * If gethostbyaddr_r() found a fully qualified host name,
-                 * returns that name. Otherwise, returns the hostname
-                 * found by gethostname().
-                 */
-                char *p = hp->h_name;
-                if ((strlen(hp->h_name) > strlen(hostname))
-                    && (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
-                    && (*(p + strlen(hostname)) == '.'))
-                    strcpy(hostname, hp->h_name);
-            }
+        error = getaddrinfo(hostname, NULL, &hints, &res);
+
+        if (error == 0) {/* host is known to name service */
+            getnameinfo(res->ai_addr,
+                        res->ai_addrlen,
+                        hostname,
+                        MAXHOSTNAMELEN,
+                        NULL,
+                        0,
+                        NI_NAMEREQD);
+
+            /* if getnameinfo fails hostname is still the value
+               from gethostname */
+
+            freeaddrinfo(res);
         }
     }
     return (*env)->NewStringUTF(env, hostname);
@@ -140,14 +117,9 @@
                                                 jstring host) {
     const char *hostname;
     jobjectArray ret = 0;
-    struct hostent res, *hp = 0;
-    // this buffer must be pointer-aligned so is declared
-    // with pointer type
-    char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-
-    /* temporary buffer, on the off chance we need to expand */
-    char *tmp = NULL;
-    int h_error=0;
+    int retLen = 0;
+    int error = 0;
+    struct addrinfo hints, *res, *resNew = NULL;
 
     if (!initialized) {
       ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
@@ -168,6 +140,11 @@
     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
     CHECK_NULL_RETURN(hostname, NULL);
 
+    /* Try once, with our static buffer. */
+    bzero(&hints, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_family = AF_INET;
+
 #ifdef __solaris__
     /*
      * Workaround for Solaris bug 4160367 - if a hostname contains a
@@ -181,69 +158,93 @@
     }
 #endif
 
-    /* Try once, with our static buffer. */
-#ifdef __GLIBC__
-    gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-    hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
-#endif
+    error = getaddrinfo(hostname, NULL, &hints, &res);
 
-    /* With the re-entrant system calls, it's possible that the buffer
-     * we pass to it is not large enough to hold an exceptionally
-     * large DNS entry.  This is signaled by errno->ERANGE.  We try once
-     * more, with a very big size.
-     */
-    if (hp == NULL && errno == ERANGE) {
-        if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
-#ifdef __GLIBC__
-            gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
-                            &hp, &h_error);
-#else
-            hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
-                                 &h_error);
-#endif
-        }
-    }
-    if (hp != NULL) {
-        struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
+    if (error) {
+        /* report error */
+        ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    } else {
         int i = 0;
+        struct addrinfo *itr, *last = NULL, *iterator = res;
 
-        while (*addrp != (struct in_addr *) 0) {
-            i++;
-            addrp++;
+        while (iterator != NULL) {
+            // remove the duplicate one
+            int skip = 0;
+            itr = resNew;
+            while (itr != NULL) {
+                struct sockaddr_in *addr1, *addr2;
+                addr1 = (struct sockaddr_in *)iterator->ai_addr;
+                addr2 = (struct sockaddr_in *)itr->ai_addr;
+                if (addr1->sin_addr.s_addr ==
+                    addr2->sin_addr.s_addr) {
+                    skip = 1;
+                    break;
+                }
+                itr = itr->ai_next;
+            }
+
+            if (!skip) {
+                struct addrinfo *next
+                    = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+                if (!next) {
+                    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+                    ret = NULL;
+                    goto cleanupAndReturn;
+                }
+                memcpy(next, iterator, sizeof(struct addrinfo));
+                next->ai_next = NULL;
+                if (resNew == NULL) {
+                    resNew = next;
+                } else {
+                    last->ai_next = next;
+                }
+                last = next;
+                i++;
+            }
+            iterator = iterator->ai_next;
         }
 
-        ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
+        retLen = i;
+        iterator = resNew;
+
+        ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+
         if (IS_NULL(ret)) {
             /* we may have memory to free at the end of this */
             goto cleanupAndReturn;
         }
-        addrp = (struct in_addr **) hp->h_addr_list;
+
         i = 0;
-        while (*addrp) {
-          jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
-          if (IS_NULL(iaObj)) {
-            ret = NULL;
-            goto cleanupAndReturn;
-          }
-          (*env)->SetIntField(env, iaObj, ni_iaaddressID,
-                              ntohl((*addrp)->s_addr));
-          (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
-          (*env)->SetObjectArrayElement(env, ret, i, iaObj);
-          addrp++;
-          i++;
+        while (iterator != NULL) {
+            jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+            if (IS_NULL(iaObj)) {
+                ret = NULL;
+                goto cleanupAndReturn;
+            }
+            (*env)->SetIntField(env, iaObj, ni_iaaddressID,
+                                ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+            (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
+            (*env)->SetObjectArrayElement(env, ret, i++, iaObj);
+            iterator = iterator->ai_next;
         }
-    } else {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                        (char *)hostname);
-        ret = NULL;
     }
 
-cleanupAndReturn:
-    JNU_ReleaseStringPlatformChars(env, host, hostname);
-    if (tmp != NULL) {
-        free(tmp);
+ cleanupAndReturn:
+    {
+        struct addrinfo *iterator, *tmp;
+        iterator = resNew;
+        while (iterator != NULL) {
+            tmp = iterator;
+            iterator = iterator->ai_next;
+            free(tmp);
+        }
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
     }
+
+    freeaddrinfo(res);
+
     return ret;
 }
 
@@ -256,63 +257,39 @@
 Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
                                             jbyteArray addrArray) {
     jstring ret = NULL;
+
+    char host[NI_MAXHOST+1];
+    int error = 0;
+    int len = 0;
+    jbyte caddr[16];
+
+    struct sockaddr_in him4;
+    struct sockaddr_in6 him6;
+    struct sockaddr *sa;
+
     jint addr;
-    struct hostent hent, *hp = 0;
-    // this buffer must be pointer-aligned so is declared
-    // with pointer type
-    char *buf[HENT_BUF_SIZE/(sizeof (char *))];
-    int h_error = 0;
-    char *tmp = NULL;
-
-    /*
-     * We are careful here to use the reentrant version of
-     * gethostbyname because at the Java level this routine is not
-     * protected by any synchronization.
-     *
-     * Still keeping the reentrant platform dependent calls temporarily
-     * We should probably conform to one interface later.
-     *
-     */
-    jbyte caddr[4];
     (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
     addr = ((caddr[0]<<24) & 0xff000000);
     addr |= ((caddr[1] <<16) & 0xff0000);
     addr |= ((caddr[2] <<8) & 0xff00);
     addr |= (caddr[3] & 0xff);
-    addr = htonl(addr);
-#ifdef __GLIBC__
-    gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
-                    (char*)buf, sizeof(buf), &hp, &h_error);
-#else
-    hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
-                         (char*)buf, sizeof(buf), &h_error);
-#endif
-    /* With the re-entrant system calls, it's possible that the buffer
-     * we pass to it is not large enough to hold an exceptionally
-     * large DNS entry.  This is signaled by errno->ERANGE.  We try once
-     * more, with a very big size.
-     */
-    if (hp == NULL && errno == ERANGE) {
-        if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
-#ifdef __GLIBC__
-            gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
-                            &hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
-#else
-            hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
-                                 &hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
-#endif
-        } else {
-            JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
-        }
+    memset((void *) &him4, 0, sizeof(him4));
+    him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+    him4.sin_family = AF_INET;
+    sa = (struct sockaddr *) &him4;
+    len = sizeof(him4);
+
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+                        NI_NAMEREQD);
+
+    if (!error) {
+        ret = (*env)->NewStringUTF(env, host);
     }
-    if (hp == NULL) {
+
+    if (ret == NULL) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
-    } else {
-        ret = (*env)->NewStringUTF(env, hp->h_name);
     }
-    if (tmp) {
-        free(tmp);
-    }
+
     return ret;
 }
 
--- a/src/solaris/native/java/net/Inet6AddressImpl.c	Mon Nov 21 12:57:36 2011 +0000
+++ b/src/solaris/native/java/net/Inet6AddressImpl.c	Fri Nov 11 14:40:18 2011 +0000
@@ -82,31 +82,29 @@
          * We use thread-safe system calls.
          */
 #ifdef AF_INET6
-        if (NET_addrtransAvailable()) {
-            struct addrinfo  hints, *res;
-            int error;
+        struct addrinfo  hints, *res;
+        int error;
 
-            bzero(&hints, sizeof(hints));
-            hints.ai_flags = AI_CANONNAME;
-            hints.ai_family = AF_UNSPEC;
+        bzero(&hints, sizeof(hints));
+        hints.ai_flags = AI_CANONNAME;
+        hints.ai_family = AF_UNSPEC;
 
-            error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+        error = getaddrinfo(hostname, NULL, &hints, &res);
 
-            if (error == 0) {
-                /* host is known to name service */
-                error = (*getnameinfo_ptr)(res->ai_addr,
-                                           res->ai_addrlen,
-                                           hostname,
-                                           NI_MAXHOST,
-                                           NULL,
-                                           0,
-                                           NI_NAMEREQD);
+        if (error == 0) {
+            /* host is known to name service */
+            error = getnameinfo(res->ai_addr,
+                                res->ai_addrlen,
+                                hostname,
+                                NI_MAXHOST,
+                                NULL,
+                                0,
+                                NI_NAMEREQD);
 
-                /* if getnameinfo fails hostname is still the value
-                   from gethostname */
+            /* if getnameinfo fails hostname is still the value
+               from gethostname */
 
-                (*freeaddrinfo_ptr)(res);
-            }
+            freeaddrinfo(res);
         }
 #endif /* AF_INET6 */
 #endif /* __linux__ */
@@ -173,193 +171,191 @@
     CHECK_NULL_RETURN(hostname, NULL);
 
 #ifdef AF_INET6
-    if (NET_addrtransAvailable()) {
-        static jfieldID ia_preferIPv6AddressID;
+    static jfieldID ia_preferIPv6AddressID;
+    if (ia_preferIPv6AddressID == NULL) {
+        jclass c = (*env)->FindClass(env,"java/net/InetAddress");
+        if (c)  {
+            ia_preferIPv6AddressID =
+                (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
+        }
         if (ia_preferIPv6AddressID == NULL) {
-            jclass c = (*env)->FindClass(env,"java/net/InetAddress");
-            if (c)  {
-                ia_preferIPv6AddressID =
-                    (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
-            }
-            if (ia_preferIPv6AddressID == NULL) {
-                JNU_ReleaseStringPlatformChars(env, host, hostname);
-                return NULL;
-            }
-        }
-        /* get the address preference */
-        preferIPv6Address
-            = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
-
-        /* Try once, with our static buffer. */
-        bzero(&hints, sizeof(hints));
-        hints.ai_flags = AI_CANONNAME;
-        hints.ai_family = AF_UNSPEC;
-
-#ifdef __solaris__
-        /*
-         * Workaround for Solaris bug 4160367 - if a hostname contains a
-         * white space then 0.0.0.0 is returned
-         */
-        if (isspace((unsigned char)hostname[0])) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                            hostname);
             JNU_ReleaseStringPlatformChars(env, host, hostname);
             return NULL;
         }
+    }
+    /* get the address preference */
+    preferIPv6Address
+        = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
+
+    /* Try once, with our static buffer. */
+    bzero(&hints, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_family = AF_UNSPEC;
+
+#ifdef __solaris__
+    /*
+     * Workaround for Solaris bug 4160367 - if a hostname contains a
+     * white space then 0.0.0.0 is returned
+     */
+    if (isspace((unsigned char)hostname[0])) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+                        hostname);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    }
 #endif
 
-        error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+    error = getaddrinfo(hostname, NULL, &hints, &res);
 
-        if (error) {
-            /* report error */
-            ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
-            JNU_ReleaseStringPlatformChars(env, host, hostname);
-            return NULL;
-        } else {
-            int i = 0;
-            int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
-            struct addrinfo *itr, *last = NULL, *iterator = res;
-            while (iterator != NULL) {
-                int skip = 0;
-                itr = resNew;
-                while (itr != NULL) {
-                    if (iterator->ai_family == itr->ai_family &&
-                        iterator->ai_addrlen == itr->ai_addrlen) {
-                        if (itr->ai_family == AF_INET) { /* AF_INET */
-                            struct sockaddr_in *addr1, *addr2;
-                            addr1 = (struct sockaddr_in *)iterator->ai_addr;
-                            addr2 = (struct sockaddr_in *)itr->ai_addr;
-                            if (addr1->sin_addr.s_addr ==
-                                addr2->sin_addr.s_addr) {
-                                skip = 1;
-                                break;
-                            }
-                        } else {
-                            int t;
-                            struct sockaddr_in6 *addr1, *addr2;
-                            addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
-                            addr2 = (struct sockaddr_in6 *)itr->ai_addr;
+    if (error) {
+        /* report error */
+        ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
+        JNU_ReleaseStringPlatformChars(env, host, hostname);
+        return NULL;
+    } else {
+        int i = 0;
+        int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
+        struct addrinfo *itr, *last = NULL, *iterator = res;
+        while (iterator != NULL) {
+            int skip = 0;
+            itr = resNew;
+            while (itr != NULL) {
+                if (iterator->ai_family == itr->ai_family &&
+                    iterator->ai_addrlen == itr->ai_addrlen) {
+                    if (itr->ai_family == AF_INET) { /* AF_INET */
+                        struct sockaddr_in *addr1, *addr2;
+                        addr1 = (struct sockaddr_in *)iterator->ai_addr;
+                        addr2 = (struct sockaddr_in *)itr->ai_addr;
+                        if (addr1->sin_addr.s_addr ==
+                            addr2->sin_addr.s_addr) {
+                            skip = 1;
+                            break;
+                        }
+                    } else {
+                        int t;
+                        struct sockaddr_in6 *addr1, *addr2;
+                        addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
+                        addr2 = (struct sockaddr_in6 *)itr->ai_addr;
 
-                            for (t = 0; t < 16; t++) {
-                                if (addr1->sin6_addr.s6_addr[t] !=
-                                    addr2->sin6_addr.s6_addr[t]) {
-                                    break;
-                                }
-                            }
-                            if (t < 16) {
-                                itr = itr->ai_next;
-                                continue;
-                            } else {
-                                skip = 1;
+                        for (t = 0; t < 16; t++) {
+                            if (addr1->sin6_addr.s6_addr[t] !=
+                                addr2->sin6_addr.s6_addr[t]) {
                                 break;
                             }
                         }
-                    } else if (iterator->ai_family != AF_INET &&
-                               iterator->ai_family != AF_INET6) {
-                        /* we can't handle other family types */
-                        skip = 1;
-                        break;
+                        if (t < 16) {
+                            itr = itr->ai_next;
+                            continue;
+                        } else {
+                            skip = 1;
+                            break;
+                        }
                     }
-                    itr = itr->ai_next;
+                } else if (iterator->ai_family != AF_INET &&
+                           iterator->ai_family != AF_INET6) {
+                    /* we can't handle other family types */
+                    skip = 1;
+                    break;
                 }
-
-                if (!skip) {
-                    struct addrinfo *next
-                        = (struct addrinfo*) malloc(sizeof(struct addrinfo));
-                    if (!next) {
-                        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-                        ret = NULL;
-                        goto cleanupAndReturn;
-                    }
-                    memcpy(next, iterator, sizeof(struct addrinfo));
-                    next->ai_next = NULL;
-                    if (resNew == NULL) {
-                        resNew = next;
-                    } else {
-                        last->ai_next = next;
-                    }
-                    last = next;
-                    i++;
-                    if (iterator->ai_family == AF_INET) {
-                        inetCount ++;
-                    } else if (iterator->ai_family == AF_INET6) {
-                        inet6Count ++;
-                    }
-                }
-                iterator = iterator->ai_next;
-            }
-            retLen = i;
-            iterator = resNew;
-
-            ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
-
-            if (IS_NULL(ret)) {
-                /* we may have memory to free at the end of this */
-                goto cleanupAndReturn;
+                itr = itr->ai_next;
             }
 
-            if (preferIPv6Address) {
-                /* AF_INET addresses will be offset by inet6Count */
-                inetIndex = inet6Count;
-                inet6Index = 0;
-            } else {
-                /* AF_INET6 addresses will be offset by inetCount */
-                inetIndex = 0;
-                inet6Index = inetCount;
+            if (!skip) {
+                struct addrinfo *next
+                    = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+                if (!next) {
+                    JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+                    ret = NULL;
+                    goto cleanupAndReturn;
+                }
+                memcpy(next, iterator, sizeof(struct addrinfo));
+                next->ai_next = NULL;
+                if (resNew == NULL) {
+                    resNew = next;
+                } else {
+                    last->ai_next = next;
+                }
+                last = next;
+                i++;
+                if (iterator->ai_family == AF_INET) {
+                    inetCount ++;
+                } else if (iterator->ai_family == AF_INET6) {
+                    inet6Count ++;
+                }
             }
+            iterator = iterator->ai_next;
+        }
+        retLen = i;
+        iterator = resNew;
 
-            while (iterator != NULL) {
-              if (iterator->ai_family == AF_INET) {
+        ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+
+        if (IS_NULL(ret)) {
+            /* we may have memory to free at the end of this */
+            goto cleanupAndReturn;
+        }
+
+        if (preferIPv6Address) {
+            /* AF_INET addresses will be offset by inet6Count */
+            inetIndex = inet6Count;
+            inet6Index = 0;
+        } else {
+            /* AF_INET6 addresses will be offset by inetCount */
+            inetIndex = 0;
+            inet6Index = inetCount;
+        }
+
+        while (iterator != NULL) {
+            if (iterator->ai_family == AF_INET) {
                 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
                 if (IS_NULL(iaObj)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                                     ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
                 inetIndex++;
-              } else if (iterator->ai_family == AF_INET6) {
+            } else if (iterator->ai_family == AF_INET6) {
                 jint scope = 0;
                 jbyteArray ipaddress;
 
                 jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
                 if (IS_NULL(iaObj)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 ipaddress = (*env)->NewByteArray(env, 16);
                 if (IS_NULL(ipaddress)) {
-                  ret = NULL;
-                  goto cleanupAndReturn;
+                    ret = NULL;
+                    goto cleanupAndReturn;
                 }
                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
                                            (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
 #ifdef __linux__
                 if (!kernelIsV22()) {
-                  scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
+                    scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
                 }
 #else
                 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
 #endif
                 if (scope != 0) { /* zero is default value, no need to set */
-                  (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
-                  (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+                    (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
+                    (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
                 }
                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
                 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
                 inet6Index++;
-              }
-              iterator = iterator->ai_next;
             }
+            iterator = iterator->ai_next;
         }
     }
 
-cleanupAndReturn:
+ cleanupAndReturn:
     {
-        struct addrinfo *iterator, *tmp;
+      struct addrinfo *iterator, *tmp;
         iterator = resNew;
         while (iterator != NULL) {
             tmp = iterator;
@@ -369,8 +365,7 @@
         JNU_ReleaseStringPlatformChars(env, host, hostname);
     }
 
-    if (NET_addrtransAvailable())
-        (*freeaddrinfo_ptr)(res);
+    freeaddrinfo(res);
 #endif /* AF_INET6 */
 
     return ret;
@@ -393,44 +388,42 @@
     int len = 0;
     jbyte caddr[16];
 
-    if (NET_addrtransAvailable()) {
-        struct sockaddr_in him4;
-        struct sockaddr_in6 him6;
-        struct sockaddr *sa;
+    struct sockaddr_in him4;
+    struct sockaddr_in6 him6;
+    struct sockaddr *sa;
 
+    /*
+     * For IPv4 addresses construct a sockaddr_in structure.
+     */
+    if ((*env)->GetArrayLength(env, addrArray) == 4) {
+        jint addr;
+        (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+        addr = ((caddr[0]<<24) & 0xff000000);
+        addr |= ((caddr[1] <<16) & 0xff0000);
+        addr |= ((caddr[2] <<8) & 0xff00);
+        addr |= (caddr[3] & 0xff);
+        memset((void *) &him4, 0, sizeof(him4));
+        him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+        him4.sin_family = AF_INET;
+        sa = (struct sockaddr *) &him4;
+        len = sizeof(him4);
+    } else {
         /*
-         * For IPv4 addresses construct a sockaddr_in structure.
+         * For IPv6 address construct a sockaddr_in6 structure.
          */
-        if ((*env)->GetArrayLength(env, addrArray) == 4) {
-            jint addr;
-            (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-            addr = ((caddr[0]<<24) & 0xff000000);
-            addr |= ((caddr[1] <<16) & 0xff0000);
-            addr |= ((caddr[2] <<8) & 0xff00);
-            addr |= (caddr[3] & 0xff);
-            memset((void *) &him4, 0, sizeof(him4));
-            him4.sin_addr.s_addr = (uint32_t) htonl(addr);
-            him4.sin_family = AF_INET;
-            sa = (struct sockaddr *) &him4;
-            len = sizeof(him4);
-        } else {
-            /*
-             * For IPv6 address construct a sockaddr_in6 structure.
-             */
-            (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
-            memset((void *) &him6, 0, sizeof(him6));
-            memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
-            him6.sin6_family = AF_INET6;
-            sa = (struct sockaddr *) &him6 ;
-            len = sizeof(him6) ;
-        }
+        (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
+        memset((void *) &him6, 0, sizeof(him6));
+        memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+        him6.sin6_family = AF_INET6;
+        sa = (struct sockaddr *) &him6 ;
+        len = sizeof(him6) ;
+    }
 
-        error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
-                                   NI_NAMEREQD);
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+                        NI_NAMEREQD);
 
-        if (!error) {
-            ret = (*env)->NewStringUTF(env, host);
-        }
+    if (!error) {
+        ret = (*env)->NewStringUTF(env, host);
     }
 #endif /* AF_INET6 */
 
--- a/src/solaris/native/java/net/net_util_md.c	Mon Nov 21 12:57:36 2011 +0000
+++ b/src/solaris/native/java/net/net_util_md.c	Fri Nov 11 14:40:18 2011 +0000
@@ -377,37 +377,12 @@
      *  we should also check if the APIs are available.
      */
     ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
+    close(fd);
     if (ipv6_fn == NULL ) {
-        close(fd);
         return JNI_FALSE;
+    } else {
+        return JNI_TRUE;
     }
-
-    /*
-     * We've got the library, let's get the pointers to some
-     * IPV6 specific functions. We have to do that because, at least
-     * on Solaris we may build on a system without IPV6 networking
-     * libraries, therefore we can't have a hard link to these
-     * functions.
-     */
-    getaddrinfo_ptr = (getaddrinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
-
-    freeaddrinfo_ptr = (freeaddrinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
-
-    gai_strerror_ptr = (gai_strerror_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
-
-    getnameinfo_ptr = (getnameinfo_f)
-        JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
-
-    if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
-        /* We need all 3 of them */
-        getaddrinfo_ptr = NULL;
-    }
-
-    close(fd);
-    return JNI_TRUE;
 #endif /* AF_INET6 */
 }
 
@@ -920,10 +895,6 @@
     return 1;
 }
 
-jboolean NET_addrtransAvailable() {
-    return (jboolean)(getaddrinfo_ptr != NULL);
-}
-
 /*
  * Map the Java level socket option to the platform specific
  * level and option name.
--- a/src/solaris/native/java/net/net_util_md.h	Mon Nov 21 12:57:36 2011 +0000
+++ b/src/solaris/native/java/net/net_util_md.h	Fri Nov 11 14:40:18 2011 +0000
@@ -102,10 +102,6 @@
                                            const char* hostname,
                                            int gai_error);
 
-/* do we have address translation support */
-
-extern jboolean NET_addrtransAvailable();
-
 #define NET_WAIT_READ   0x01
 #define NET_WAIT_WRITE  0x02
 #define NET_WAIT_CONNECT        0x04