6931566: NetworkInterface is not working when interface name is more than 15 characters long
authordsamersoff
Wed, 23 Jun 2010 17:25:50 +0400
changeset 5969 76a4031d39bd
parent 5968 4e9dd25279c7
child 5971 7f83fb438899
child 5996 68e11696dd2c
6931566: NetworkInterface is not working when interface name is more than 15 characters long Summary: Separate Linux and Solaris code, use lifreq under Solaris Reviewed-by: chegar
jdk/src/solaris/native/java/net/NetworkInterface.c
--- a/jdk/src/solaris/native/java/net/NetworkInterface.c	Tue Jun 22 19:18:06 2010 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c	Wed Jun 23 17:25:50 2010 +0400
@@ -23,6 +23,7 @@
  * questions.
  */
 
+
 #include <errno.h>
 #include <strings.h>
 #include <netinet/in.h>
@@ -33,23 +34,23 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
+
 #ifdef __solaris__
 #include <sys/dlpi.h>
 #include <fcntl.h>
 #include <stropts.h>
+#include <sys/sockio.h>
 #endif
+
 #ifdef __linux__
 #include <sys/ioctl.h>
 #include <bits/ioctls.h>
 #include <linux/sockios.h>
 #include <sys/utsname.h>
 #include <stdio.h>
-#else
-#include <sys/sockio.h>
 #endif
 
 #ifdef __linux__
-#define ifr_index ifr_ifindex
 #define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
 #endif
 
@@ -108,20 +109,41 @@
 static jfieldID ni_ib4broadcastID;
 static jfieldID ni_ib4maskID;
 
+/** Private methods declarations **/
 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
+static int     getFlags0(JNIEnv *env, jstring  ifname);
 
-static netif *enumInterfaces(JNIEnv *env);
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs);
+static netif  *enumInterfaces(JNIEnv *env);
+static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
+
 #ifdef AF_INET6
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs);
+static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 #endif
 
-static netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index,
-                    int family, struct sockaddr *new_addrP, int new_addrlen,
-                    short prefix);
-static void freeif(netif *ifs);
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname);
-static short getSubnet(JNIEnv *env, const char *ifname);
+static netif  *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static void    freeif(netif *ifs);
+
+static int     openSocket(JNIEnv *env, int proto);
+static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
+
+
+static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
+static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
+static int     getIndex(JNIEnv *env, int sock, const char *ifname);
+
+static int     getFlags(JNIEnv *env, int sock, const char *ifname);
+static int     getMacAddress(JNIEnv *env, int sock,  const char* ifname, const struct in_addr* addr, unsigned char *buf);
+static int     getMTU(JNIEnv *env, int sock, const char *ifname);
+
+
+
+#ifdef __solaris__
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
+static int    getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
+#endif
+
+
+/******************* Java entry points *****************************/
 
 /*
  * Class:     java_net_NetworkInterface
@@ -172,7 +194,7 @@
 
     netif *ifs, *curr;
     jboolean isCopy;
-    const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+    const char* name_utf;
     jobject obj = NULL;
 
     ifs = enumInterfaces(env);
@@ -180,6 +202,8 @@
         return NULL;
     }
 
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
     /*
      * Search the list of interface based on name
      */
@@ -253,12 +277,13 @@
     (JNIEnv *env, jclass cls, jobject iaObj) {
 
     netif *ifs, *curr;
+
 #ifdef AF_INET6
-    int family = (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4?
-        AF_INET : AF_INET6;
+    int family = (  (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6;
 #else
-    int family = AF_INET;
+    int family =  AF_INET;
 #endif
+
     jobject obj = NULL;
     jboolean match = JNI_FALSE;
 
@@ -390,18 +415,169 @@
     return netIFArr;
 }
 
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isUp0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isP2P0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_POINTOPOINT) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isLoopback0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_LOOPBACK) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    supportsMulticast0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_MULTICAST) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    getMacAddr0
+ * Signature: ([bLjava/lang/String;I)[b
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
+    jint addr;
+    jbyte caddr[4];
+    struct in_addr iaddr;
+    jbyteArray ret = NULL;
+    unsigned char mac[16];
+    int len;
+    int sock;
+    jboolean isCopy;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+       (*env)->ReleaseStringUTFChars(env, name, name_utf);
+       return JNI_FALSE;
+    }
+
+
+    if (!IS_NULL(addrArray)) {
+       (*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);
+       iaddr.s_addr = htonl(addr);
+       len = getMacAddress(env, sock, name_utf, &iaddr, mac);
+    } else {
+       len = getMacAddress(env, sock, name_utf,NULL, mac);
+    }
+    if (len > 0) {
+       ret = (*env)->NewByteArray(env, len);
+       if (IS_NULL(ret)) {
+          /* we may have memory to free at the end of this */
+          goto fexit;
+       }
+       (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
+    }
+ fexit:
+   /* release the UTF string and interface list */
+   (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+   close(sock);
+   return ret;
+}
+
+/*
+ * Class:       java_net_NetworkInterface
+ * Method:      getMTU0
+ * Signature:   ([bLjava/lang/String;I)I
+ */
+
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
+    jboolean isCopy;
+    int ret = -1;
+    int sock;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+       (*env)->ReleaseStringUTFChars(env, name, name_utf);
+       return JNI_FALSE;
+    }
+
+    ret = getMTU(env, sock, name_utf);
+
+    (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+    close(sock);
+    return ret;
+}
+
+/*** Private methods definitions ****/
+
+static int getFlags0(JNIEnv *env, jstring name) {
+    jboolean isCopy;
+    int ret, sock;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
+        (*env)->ReleaseStringUTFChars(env, name, name_utf);
+         return -1;
+    }
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    ret = getFlags(env, sock, name_utf);
+
+    close(sock);
+    (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+    if (ret < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        return -1;
+    }
+
+    return ret;
+}
+
+
+
+
 /*
  * Create a NetworkInterface object, populate the name and index, and
  * populate the InetAddress array based on the IP addresses for this
  * interface.
  */
-jobject createNetworkInterface(JNIEnv *env, netif *ifs)
-{
+jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
     jobject netifObj;
     jobject name;
     jobjectArray addrArr;
     jobjectArray bindArr;
     jobjectArray childArr;
+    netaddr *addrs;
     jint addr_index, addr_count, bind_index;
     jint child_count, child_index;
     netaddr *addrP;
@@ -441,7 +617,7 @@
 
     bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
     if (bindArr == NULL) {
-      return NULL;
+       return NULL;
     }
     addrP = ifs->addr;
     addr_index = 0;
@@ -453,23 +629,22 @@
         if (addrP->family == AF_INET) {
             iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
             if (iaObj) {
-                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
-                     htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+                 (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
             }
             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
             if (ibObj) {
-              (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
-              if (addrP->brdcast) {
-                jobject ia2Obj = NULL;
-                ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
-                if (ia2Obj) {
-                  (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
-                                      htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
-                  (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
-                  (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
-                }
-              }
-              (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+                 if (addrP->brdcast) {
+                    jobject ia2Obj = NULL;
+                    ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+                    if (ia2Obj) {
+                       (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
+                                                               htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+                       (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
+                       (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+                    }
+                 }
+                 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
             }
         }
 
@@ -483,14 +658,10 @@
                     return NULL;
                 }
                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                    (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
-#ifdef __linux__
-                if (!kernelIsV22()) {
-                    scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
-                }
-#else
+                                                                        (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+
                 scope = ((struct sockaddr_in6*)addrP->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);
@@ -500,9 +671,9 @@
             }
             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
             if (ibObj) {
-              (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
-              (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
-              (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+                (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+                (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+                (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
             }
         }
 #endif
@@ -521,13 +692,13 @@
     child_count = 0;
     childP = ifs->childs;
     while (childP) {
-      child_count++;
-      childP = childP->next;
+        child_count++;
+        childP = childP->next;
     }
 
     childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
     if (childArr == NULL) {
-      return NULL;
+        return NULL;
     }
 
     /*
@@ -539,7 +710,7 @@
     while(childP) {
       tmp = createNetworkInterface(env, childP);
       if (tmp == NULL) {
-        return NULL;
+         return NULL;
       }
       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
@@ -558,294 +729,56 @@
  */
 static netif *enumInterfaces(JNIEnv *env) {
     netif *ifs;
+    int sock;
 
     /*
      * Enumerate IPv4 addresses
      */
-    ifs = enumIPv4Interfaces(env, NULL);
-    if (ifs == NULL) {
-        if ((*env)->ExceptionOccurred(env)) {
-            return NULL;
-        }
+
+    sock = openSocket(env, AF_INET);
+    if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+        return NULL;
     }
 
+    ifs = enumIPv4Interfaces(env, sock, NULL);
+    close(sock);
+
+    if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
+        return NULL;
+    }
+
+    /* return partial list if exception occure in the middle of process ???*/
+
     /*
      * If IPv6 is available then enumerate IPv6 addresses.
      */
 #ifdef AF_INET6
-    if (ipv6_available()) {
-        ifs = enumIPv6Interfaces(env, ifs);
+        sock =  openSocket(env, AF_INET6);
+        if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+            freeif(ifs);
+            return NULL;
+        }
+
+        ifs = enumIPv6Interfaces(env, sock, ifs);
+        close(sock);
 
         if ((*env)->ExceptionOccurred(env)) {
             freeif(ifs);
             return NULL;
         }
-    }
 #endif
 
     return ifs;
 }
 
-
-/*
- * Enumerates and returns all IPv4 interfaces
- */
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) {
-    int sock;
-    struct ifconf ifc;
-    struct ifreq *ifreqP;
-    char *buf;
-    int numifs;
-    unsigned i;
-    unsigned bufsize;
-
-    sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        /*
-         * If EPROTONOSUPPORT is returned it means we don't have
-         * IPv4 support so don't throw an exception.
-         */
-        if (errno != EPROTONOSUPPORT) {
-            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                             "Socket creation failed");
-        }
-        return ifs;
-    }
-
-#ifdef __linux__
-    /* need to do a dummy SIOCGIFCONF to determine the buffer size.
-     * SIOCGIFCOUNT doesn't work
-     */
-    ifc.ifc_buf = NULL;
-    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFCONF failed");
-        close(sock);
-        return ifs;
-    }
-    bufsize = ifc.ifc_len;
-#else
-    if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFNUM failed");
-        close(sock);
-        return ifs;
-    }
-    bufsize = numifs * sizeof (struct ifreq);
-#endif /* __linux__ */
-
-    buf = (char *)malloc(bufsize);
-    if (!buf) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        (void) close(sock);
-        return ifs;
-    }
-    ifc.ifc_len = bufsize;
-    ifc.ifc_buf = buf;
-    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFCONF failed");
-        (void) close(sock);
-        (void) free(buf);
-        return ifs;
-    }
-
-    /*
-     * Iterate through each interface
-     */
-    ifreqP = ifc.ifc_req;
-    for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
-        int index;
-        struct ifreq if2;
-
-        memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, ifreqP->ifr_name);
-
-        /*
-         * Try to get the interface index
-         * (Not supported on Solaris 2.6 or 7)
-         */
-        if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) {
-            index = if2.ifr_index;
-        } else {
-            index = -1;
-        }
-
-        /*
-         * Add to the list
-         */
-        ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET,
-                    (struct sockaddr *)&(ifreqP->ifr_addr),
-                    sizeof(struct sockaddr_in), 0);
-
-        /*
-         * If an exception occurred then free the list
-         */
-        if ((*env)->ExceptionOccurred(env)) {
-            close(sock);
-            free(buf);
-            freeif(ifs);
-            return NULL;
-        }
-    }
-
-    /*
-     * Free socket and buffer
-     */
-    close(sock);
-    free(buf);
-    return ifs;
-}
-
-
-#if defined(__solaris__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Solaris
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
-    int sock;
-    struct lifconf ifc;
-    struct lifreq *ifr;
-    int n;
-    char *buf;
-    struct lifnum numifs;
-    unsigned bufsize;
-
-    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "Failed to create IPv6 socket");
-        return ifs;
-    }
-
-    /*
-     * Get the interface count
-     */
-    numifs.lifn_family = AF_UNSPEC;
-    numifs.lifn_flags = 0;
-    if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGLIFNUM failed");
-        close(sock);
-        return ifs;
-    }
-
-    /*
-     *  Enumerate the interface configurations
-     */
-    bufsize = numifs.lifn_count * sizeof (struct lifreq);
-    buf = (char *)malloc(bufsize);
-    if (!buf) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        (void) close(sock);
-        return ifs;
-    }
-    ifc.lifc_family = AF_UNSPEC;
-    ifc.lifc_flags = 0;
-    ifc.lifc_len = bufsize;
-    ifc.lifc_buf = buf;
-    if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGLIFCONF failed");
-        close(sock);
-        free(buf);
-        return ifs;
-    }
-
-    /*
-     * Iterate through each interface
-     */
-    ifr = ifc.lifc_req;
-    for (n=0; n<numifs.lifn_count; n++, ifr++) {
-        int index = -1;
-        struct lifreq if2;
-
-        /*
-         * Ignore non-IPv6 addresses
-         */
-        if (ifr->lifr_addr.ss_family != AF_INET6) {
-            continue;
-        }
-
-        /*
-         * Get the index
-         */
-        memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.lifr_name, ifr->lifr_name);
-        if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) {
-            struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
-            index = if2.lifr_index;
-            s6->sin6_scope_id = index;
-        }
-
-        /* add to the list */
-        ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6,
-                    (struct sockaddr *)&(ifr->lifr_addr),
-                    sizeof(struct sockaddr_in6), (short) ifr->lifr_addrlen);
-
-        /*
-         * If an exception occurred we return
-         */
-        if ((*env)->ExceptionOccurred(env)) {
-            close(sock);
-            free(buf);
-            return ifs;
-        }
-
-    }
-
-    close(sock);
-    free(buf);
-    return ifs;
-
-}
-#endif
-
-
-#if defined(__linux__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
-    FILE *f;
-    char addr6[40], devname[20];
-    char addr6p[8][5];
-    int plen, scope, dad_status, if_idx;
-    uint8_t ipv6addr[16];
-
-    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
-        while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
-                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
-                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
-                  &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
-            struct sockaddr_in6 addr;
-
-            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
-                    addr6p[0], addr6p[1], addr6p[2], addr6p[3],
-                    addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
-            inet_pton(AF_INET6, addr6, ipv6addr);
-
-            memset(&addr, 0, sizeof(struct sockaddr_in6));
-            memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
-            addr.sin6_scope_id = if_idx;
-
-            ifs = addif(env, ifs, devname, if_idx, AF_INET6,
-                        (struct sockaddr *)&addr,
-                        sizeof(struct sockaddr_in6), plen);
-
-            /*
-             * If an exception occurred then return the list as is.
-             */
-            if ((*env)->ExceptionOccurred(env)) {
-                fclose(f);
-                return ifs;
-            }
-        }
-        fclose(f);
-    }
-    return ifs;
-}
-#endif
+#define CHECKED_MALLOC3(_pointer,_type,_size) \
+       do{ \
+        _pointer = (_type)malloc( _size ); \
+        if (_pointer == NULL) { \
+            JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); \
+            return ifs; /* return untouched list */ \
+        } \
+       } while(0)
 
 
 /*
@@ -853,52 +786,43 @@
  */
 void freeif(netif *ifs) {
     netif *currif = ifs;
+    netif *child = NULL;
 
     while (currif != NULL) {
         netaddr *addrP = currif->addr;
         while (addrP != NULL) {
             netaddr *next = addrP->next;
-            if (addrP->addr != NULL)
-                free(addrP->addr);
-            if (addrP->brdcast != NULL)
-                free(addrP->brdcast);
             free(addrP);
             addrP = next;
-        }
-
-        free(currif->name);
+         }
 
-        /*
-         * Don't forget to free the sub-interfaces.
-         */
-        if (currif->childs != NULL) {
-          freeif(currif->childs);
-        }
+            /*
+            * Don't forget to free the sub-interfaces.
+            */
+          if (currif->childs != NULL) {
+                freeif(currif->childs);
+          }
 
-        ifs = currif->next;
-        free(currif);
-        currif = ifs;
+          ifs = currif->next;
+          free(currif);
+          currif = ifs;
     }
 }
 
-/*
- * Add an interface to the list. If known interface just link
- * a new netaddr onto the list. If new interface create new
- * netif structure.
- */
-netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family,
-             struct sockaddr *new_addrP, int new_addrlen, short prefix) {
-  netif *currif = ifs, *parent;
+netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix) {
+    netif *currif = ifs, *parent;
     netaddr *addrP;
-#ifdef LIFNAMSIZ
-    char name[LIFNAMSIZ];
-    char vname[LIFNAMSIZ];
-#else
-    char name[IFNAMSIZ];
-    char vname[IFNAMSIZ];
-#endif
-    char *unit;
+
+    #ifdef __solaris__
+    char name[LIFNAMSIZ],  vname[LIFNAMSIZ];
+    #else
+    char name[IFNAMSIZ],  vname[IFNAMSIZ];
+    #endif
+
+    char  *name_colonP;
+    int mask;
     int isVirtual = 0;
+    int addr_size;
 
     /*
      * If the interface name is a logical interface then we
@@ -908,107 +832,63 @@
      * logical interfaces.
      */
     strcpy(name, if_name);
+    *vname = 0;
 
     /*
      * Create and populate the netaddr node. If allocation fails
      * return an un-updated list.
      */
-    addrP = (netaddr *)malloc(sizeof(netaddr));
-    if (addrP) {
-        addrP->addr = (struct sockaddr *)malloc(new_addrlen);
-        if (addrP->addr == NULL) {
-            free(addrP);
-            addrP = NULL;
-        }
-    }
-    if (addrP == NULL) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        return ifs; /* return untouched list */
-    }
-    memcpy(addrP->addr, new_addrP, new_addrlen);
+    /*Allocate for addr and brdcast at once*/
+
+#ifdef AF_INET6
+    addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+#else
+    addr_size = sizeof(struct sockaddr_in);
+#endif
+
+    CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
+    addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+    memcpy(addrP->addr, ifr_addrP, addr_size);
+
     addrP->family = family;
-
     addrP->brdcast = NULL;
     addrP->mask = prefix;
+    addrP->next = 0;
     if (family == AF_INET) {
       /*
        * Deal with brodcast addr & subnet mask
        */
-      addrP->brdcast = getBroadcast(env, name);
-      if (addrP->brdcast) {
-        addrP->mask = getSubnet(env, name);
-      }
-    }
+       struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
+       addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
 
-    vname[0] = 0;
-    unit = strchr(name, ':');
-    if (unit != NULL) {
+       if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
+           addrP->mask = mask;
+       }
+     }
+
+    /**
+     * Deal with virtual interface with colon notaion e.g. eth0:1
+     */
+    name_colonP = strchr(name, ':');
+    if (name_colonP != NULL) {
       /**
        * This is a virtual interface. If we are able to access the parent
        * we need to create a new entry if it doesn't exist yet *and* update
        * the 'parent' interface with the new records.
        */
-      struct ifreq if2;
-      int sock;
-      int len;
-
-      sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-      if (sock < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Socket creation failed");
-        return ifs; /* return untouched list */
-      }
-
-      len = unit - name;
-      if (len > 0) {
-        // temporarily use vname to hold the parent name of the interface
-        // instead of creating another buffer.
-        memcpy(&vname, name, len);
-        vname[len] = '\0';
-
-        memset((char *) &if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, vname);
-
-        if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-           // Got access to parent, so create it if necessary.
-           strcpy(vname, name);
-           *unit = '\0';
-        } else {
-#if defined(__solaris__) && defined(AF_INET6)
-          struct   lifreq lifr;
-          memset((char *) &lifr, 0, sizeof(lifr));
-          strcpy(lifr.lifr_name, vname);
-
-          /* Try with an IPv6 socket in case the interface has only IPv6
-           * addresses assigned to it */
-          close(sock);
-          sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-
-          if (sock < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "Socket creation failed");
-            return ifs; /* return untouched list */
-          }
-
-          if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
-            // Got access to parent, so create it if necessary.
-            strcpy(vname, name);
-            *unit = '\0';
-          } else {
+        *name_colonP = 0;
+        if (getFlags(env,sock,name) < 0) {
             // failed to access parent interface do not create parent.
             // We are a virtual interface with no parent.
             isVirtual = 1;
-            vname[0] = 0;
-          }
-#else
-          // failed to access parent interface do not create parent.
-          // We are a virtual interface with no parent.
-          isVirtual = 1;
-          vname[0] = 0;
-#endif
+            *name_colonP = ':';
         }
-      }
-      close(sock);
+        else{
+           // Got access to parent, so create it if necessary.
+           // Save original name to vname and truncate name by ':'
+            memcpy(vname, name, sizeof(vname) );
+            vname[name_colonP - name] = ':';
+        }
     }
 
     /*
@@ -1028,24 +908,15 @@
      * insert it onto the list.
      */
     if (currif == NULL) {
-        currif = (netif *)malloc(sizeof(netif));
-        if (currif) {
-            currif->name = strdup(name);
-            if (currif->name == NULL) {
-                free(currif);
-                currif = NULL;
-            }
-        }
-        if (currif == NULL) {
-            JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-            return ifs;
-        }
-        currif->index = index;
-        currif->addr = NULL;
-        currif->childs = NULL;
-        currif->virtual = isVirtual;
-        currif->next = ifs;
-        ifs = currif;
+         CHECKED_MALLOC3(currif, netif *, sizeof(netif)+IFNAMSIZ );
+         currif->name = (char *) currif+sizeof(netif);
+         strcpy(currif->name, name);
+         currif->index = getIndex(env,sock,name);
+         currif->addr = NULL;
+         currif->childs = NULL;
+         currif->virtual = isVirtual;
+         currif->next = ifs;
+         ifs = currif;
     }
 
     /*
@@ -1060,161 +931,251 @@
      * Let's deal with the virtual interface now.
      */
     if (vname[0]) {
-      netaddr *tmpaddr;
+        netaddr *tmpaddr;
 
-      currif = parent->childs;
+        currif = parent->childs;
 
-      while (currif != NULL) {
-        if (strcmp(vname, currif->name) == 0) {
-          break;
-        }
-        currif = currif->next;
-      }
-      if (currif == NULL) {
-        currif = (netif *)malloc(sizeof(netif));
-        if (currif) {
-          currif->name = strdup(vname);
-          if (currif->name == NULL) {
-            free(currif);
-            currif = NULL;
-          }
-        }
-        if (currif == NULL) {
-          JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-          return ifs;
+        while (currif != NULL) {
+            if (strcmp(vname, currif->name) == 0) {
+                break;
+            }
+            currif = currif->next;
         }
-        currif->index = index;
-        currif->addr = NULL;
-        /* Need to duplicate the addr entry? */
-        currif->virtual = 1;
-        currif->childs = NULL;
-        currif->next = parent->childs;
-        parent->childs = currif;
-      }
+
+        if (currif == NULL) {
+            CHECKED_MALLOC3(currif, netif *, sizeof(netif)+ IFNAMSIZ );
+            currif->name = (char *) currif + sizeof(netif);
+            strcpy(currif->name, vname);
+            currif->index = getIndex(env,sock,vname);
+            currif->addr = NULL;
+           /* Need to duplicate the addr entry? */
+            currif->virtual = 1;
+            currif->childs = NULL;
+            currif->next = parent->childs;
+            parent->childs = currif;
+        }
 
-      tmpaddr = (netaddr *) malloc(sizeof(netaddr));
-      if (tmpaddr == NULL) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        return ifs;
-      }
-      memcpy(tmpaddr, addrP, sizeof(netaddr));
-      /**
-       * Let's duplicate the address and broadcast address structures
-       * if there are any.
-       */
-      if (addrP->addr != NULL) {
-        tmpaddr->addr = malloc(new_addrlen);
-        if (tmpaddr->addr != NULL)
-          memcpy(tmpaddr->addr, addrP->addr, new_addrlen);
-      }
-      if (addrP->brdcast != NULL) {
-        tmpaddr->brdcast = malloc(new_addrlen);
-        if (tmpaddr->brdcast != NULL)
-          memcpy(tmpaddr->brdcast, addrP->brdcast, new_addrlen);
-      }
-      tmpaddr->next = currif->addr;
-      currif->addr = tmpaddr;
+        CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
+        memcpy(tmpaddr, addrP, sizeof(netaddr));
+        if (addrP->addr != NULL) {
+            tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
+            memcpy(tmpaddr->addr, addrP->addr, addr_size);
+        }
+
+        if (addrP->brdcast != NULL) {
+            tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
+            memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
+        }
+
+        tmpaddr->next = currif->addr;
+        currif->addr = tmpaddr;
     }
 
     return ifs;
 }
 
-/**
- * Get flags from a NetworkInterface.
+/* Open socket for further ioct calls
+ * proto is AF_INET/AF_INET6
  */
-static short getFlags(JNIEnv *env, jstring name) {
-  int sock;
-  struct ifreq if2;
-  jboolean isCopy;
-  const char* name_utf;
-  short ret = -1;
+static int  openSocket(JNIEnv *env, int proto){
+    int sock;
+
+    if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
+        /*
+         * If EPROTONOSUPPORT is returned it means we don't have
+         * support  for this proto so don't throw an exception.
+         */
+        if (errno != EPROTONOSUPPORT) {
+            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
+        }
+        return -1;
+    }
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
-  }
+    return sock;
+}
+
+
+/** Linux **/
+#ifdef __linux__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    int sock;
+    struct ifreq if2;
 
-  name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, name_utf);
+     if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+         if (errno == EPROTONOSUPPORT){
+              if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                 return -1;
+              }
+         }
+         else{ // errno is not NOSUPPORT
+             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+             return -1;
+         }
+   }
+
+     /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
+        of address of an interface */
+
+       return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    return openSocket(env,AF_INET);
+}
+#endif
 
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-    ret = if2.ifr_flags;
-  } else {
-#if defined(__solaris__) && defined(AF_INET6)
-    /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
-    struct lifreq lifr;
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    struct ifconf ifc;
+    struct ifreq *ifreqP;
+    char *buf;
+    int numifs;
+    unsigned i;
+
 
-    close(sock);
-    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+    /* need to do a dummy SIOCGIFCONF to determine the buffer size.
+     * SIOCGIFCOUNT doesn't work
+     */
+    ifc.ifc_buf = NULL;
+    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+        return ifs;
+    }
 
-    if (sock < 0) {
-      (*env)->ReleaseStringUTFChars(env, name, name_utf);
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                  "Socket creation failed");
-      return -1;
+    CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
+
+    ifc.ifc_buf = buf;
+    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+        (void) free(buf);
+        return ifs;
     }
 
-    memset((caddr_t)&lifr, 0, sizeof(lifr));
-    strcpy((caddr_t)&(lifr.lifr_name), name_utf);
+    /*
+     * Iterate through each interface
+     */
+    ifreqP = ifc.ifc_req;
+    for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+        /*
+         * Add to the list
+         */
+        ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
 
-    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
-      ret = lifr.lifr_flags;
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "IOCTL failed");
+        /*
+         * If an exception occurred then free the list
+         */
+        if ((*env)->ExceptionOccurred(env)) {
+            free(buf);
+            freeif(ifs);
+            return NULL;
+        }
     }
-#else
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
+
+    /*
+     * Free socket and buffer
+     */
+    free(buf);
+    return ifs;
+}
+
+
+/*
+ * Enumerates and returns all IPv6 interfaces on Linux
+ */
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    FILE *f;
+    char addr6[40], devname[20];
+    char addr6p[8][5];
+    int plen, scope, dad_status, if_idx;
+    uint8_t ipv6addr[16];
+
+    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
+        while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+                         addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+                         &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
+
+            struct netif *ifs_ptr = NULL;
+            struct netif *last_ptr = NULL;
+            struct sockaddr_in6 addr;
+
+            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+                           addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+            inet_pton(AF_INET6, addr6, ipv6addr);
+
+            memset(&addr, 0, sizeof(struct sockaddr_in6));
+            memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
+
+            addr.sin6_scope_id = if_idx;
+
+            ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
+
+
+            /*
+             * If an exception occurred then return the list as is.
+             */
+            if ((*env)->ExceptionOccurred(env)) {
+                fclose(f);
+                return ifs;
+            }
+       }
+       fclose(f);
+    }
+    return ifs;
+}
 #endif
-  }
-  close(sock);
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
 
-  return ret;
+static int getIndex(JNIEnv *env, int sock, const char *name){
+     /*
+      * Try to get the interface index
+      * (Not supported on Solaris 2.6 or 7)
+      */
+    struct ifreq if2;
+    strcpy(if2.ifr_name, name);
+
+    if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
+        return -1;
+    }
+
+    return if2.ifr_ifindex;
 }
 
 /**
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.
  */
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname) {
-  int sock;
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
   struct sockaddr *ret = NULL;
   struct ifreq if2;
-  short flag = 0;
-
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return ret;
-  }
 
   memset((char *) &if2, 0, sizeof(if2));
   strcpy(if2.ifr_name, ifname);
+
   /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-    flag = if2.ifr_flags;
-  } else {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
+  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
+      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
+      return ret;
   }
-  if (flag & IFF_BROADCAST) {
-    /* It does, let's retrieve it*/
-    if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) >= 0) {
-      ret = (struct sockaddr*) malloc(sizeof(struct sockaddr));
+
+  if (if2.ifr_flags & IFF_BROADCAST) {
+      /* It does, let's retrieve it*/
+      if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+          NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
+          return ret;
+      }
+
+      ret = brdcast_store;
       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "IOCTL failed");
-    }
   }
-  close(sock);
+
   return ret;
 }
 
@@ -1222,39 +1183,307 @@
  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
  * interface, if it has one, otherwise return -1.
  */
-static short getSubnet(JNIEnv *env, const char *ifname) {
-  int sock;
-  unsigned int mask;
-  short ret;
-  struct ifreq if2;
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+    unsigned int mask;
+    short ret;
+    struct ifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.ifr_name, ifname);
+
+    if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+        return -1;
+    }
+
+    mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
+    ret = 0;
+    while (mask) {
+       mask <<= 1;
+       ret++;
+    }
+
+    return ret;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+    static struct ifreq ifr;
+    int i;
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
+    strcpy(ifr.ifr_name, ifname);
+    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
+        return -1;
+    }
+
+    memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+   /*
+    * All bytes to 0 means no hardware address.
+    */
+
+    for (i = 0; i < IFHWADDRLEN; i++) {
+        if (buf[i] != 0)
+            return IFHWADDRLEN;
+    }
+
     return -1;
-  }
+}
+
+static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
+    struct ifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.ifr_name, ifname);
+
+    if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+        return -1;
+    }
+
+    return  if2.ifr_mtu;
+}
+
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+  struct ifreq if2;
+  int ret = -1;
 
   memset((char *) &if2, 0, sizeof(if2));
   strcpy(if2.ifr_name, ifname);
-  if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) >= 0) {
-    mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
-    ret = 0;
-    while (mask) {
-      mask <<= 1;
-      ret++;
+
+  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+      return -1;
+  }
+
+  return if2.ifr_flags;
+}
+
+#endif
+
+/** Solaris **/
+#ifdef __solaris__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    int sock, alreadyV6 = 0;
+    struct lifreq if2;
+
+     if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+         if (errno == EPROTONOSUPPORT){
+              if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                 return -1;
+              }
+
+              alreadyV6=1;
+         }
+         else{ // errno is not NOSUPPORT
+             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+             return -1;
+         }
+   }
+
+     /**
+      * Solaris requires that we have IPv6 socket to query an
+      * interface without IPv4 address - check it here
+      * POSIX 1 require the kernell to return ENOTTY if the call is
+      * unappropriate for device e.g. NETMASK for device having IPv6
+      * only address but not all devices follows the standart so
+      * fallback on any error.  It's not an ecology friendly but more
+      * reliable.
+      */
+
+    if (! alreadyV6 ){
+        memset((char *) &if2, 0, sizeof(if2));
+        strcpy(if2.lifr_name, ifname);
+        if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+                close(sock);
+                if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                      return -1;
+                }
+        }
     }
-    close(sock);
-    return ret;
-  }
-  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "IOCTL failed");
-  close(sock);
-  return -1;
+
+    return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    return openSocket(env,AF_INET);
+}
+#endif
+
+/*
+ * Enumerates and returns all IPv4 interfaces
+ * (linux verison)
+ */
+
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+     return enumIPvXInterfaces(env,sock, ifs, AF_INET);
 }
 
-#ifdef __solaris__
-#define DEV_PREFIX      "/dev/"
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
+}
+#endif
+
+/*
+   Enumerates and returns all interfaces on Solaris
+   use the same code for IPv4 and IPv6
+ */
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
+    struct lifconf ifc;
+    struct lifreq *ifr;
+    int n;
+    char *buf;
+    struct lifnum numifs;
+    unsigned bufsize;
+
+    /*
+     * Get the interface count
+     */
+    numifs.lifn_family = family;
+    numifs.lifn_flags = 0;
+    if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
+        return ifs;
+    }
+
+    /*
+     *  Enumerate the interface configurations
+     */
+    bufsize = numifs.lifn_count * sizeof (struct lifreq);
+    CHECKED_MALLOC3(buf, char *, bufsize);
+
+    ifc.lifc_family = family;
+    ifc.lifc_flags = 0;
+    ifc.lifc_len = bufsize;
+    ifc.lifc_buf = buf;
+    if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
+        free(buf);
+        return ifs;
+    }
+
+    /*
+     * Iterate through each interface
+     */
+    ifr = ifc.lifc_req;
+    for (n=0; n<numifs.lifn_count; n++, ifr++) {
+        int index = -1;
+        struct lifreq if2;
+
+        /*
+        * Ignore either IPv4 or IPv6 addresses
+        */
+        if (ifr->lifr_addr.ss_family != family) {
+            continue;
+        }
+
+        /* add to the list */
+        ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
+
+        /*
+        * If an exception occurred we return immediately
+        */
+        if ((*env)->ExceptionOccurred(env)) {
+            free(buf);
+            return ifs;
+        }
+
+   }
+
+    free(buf);
+    return ifs;
+}
+
+static int getIndex(JNIEnv *env, int sock, const char *name){
+   /*
+    * Try to get the interface index
+    * (Not supported on Solaris 2.6 or 7)
+    */
+    struct lifreq if2;
+    strcpy(if2.lifr_name, name);
+
+    if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
+        return -1;
+    }
+
+    return if2.lifr_index;
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+    struct sockaddr *ret = NULL;
+    struct lifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
+
+    /* Let's make sure the interface does have a broadcast address */
+    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        return ret;
+    }
+
+    if (if2.lifr_flags & IFF_BROADCAST) {
+        /* It does, let's retrieve it*/
+        if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
+            return ret;
+        }
+
+        ret = brdcast_store;
+        memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
+    }
+
+    return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+    unsigned int mask;
+    short ret;
+    struct lifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
+
+    if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
+        return -1;
+    }
+
+    mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
+    ret = 0;
+
+    while (mask) {
+       mask <<= 1;
+       ret++;
+    }
+
+    return ret;
+}
+
+
+
+#define DEV_PREFIX  "/dev/"
 
 /**
  * Solaris specific DLPI code to get hardware address from a device.
@@ -1262,306 +1491,147 @@
  * privileges (i.e. be root).
  */
 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
-  char style1dev[MAXPATHLEN];
-  int fd;
-  dl_phys_addr_req_t dlpareq;
-  dl_phys_addr_ack_t *dlpaack;
-  struct strbuf msg;
-  char buf[128];
-  int flags = 0;
+    char style1dev[MAXPATHLEN];
+    int fd;
+    dl_phys_addr_req_t dlpareq;
+    dl_phys_addr_ack_t *dlpaack;
+    struct strbuf msg;
+    char buf[128];
+    int flags = 0;
+
+   /**
+    * Device is in /dev
+    * e.g.: /dev/bge0
+    */
+    strcpy(style1dev, DEV_PREFIX);
+    strcat(style1dev, ifname);
+    if ((fd = open(style1dev, O_RDWR)) < 0) {
+        /*
+         * Can't open it. We probably are missing the privilege.
+         * We'll have to try something else
+         */
+         return 0;
+    }
+
+    dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
+    dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
 
-  /**
-   * Device is in /dev
-   * e.g.: /dev/bge0
-   */
-  strcpy(style1dev, DEV_PREFIX);
-  strcat(style1dev, ifname);
-  if ((fd = open(style1dev, O_RDWR)) == -1) {
-    /*
-     * Can't open it. We probably are missing the privilege.
-     * We'll have to try something else
-     */
-    return 0;
-  }
-  dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
-  dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
-  msg.buf = (char *)&dlpareq;
-  msg.len = DL_PHYS_ADDR_REQ_SIZE;
-  if (putmsg(fd, &msg, NULL, 0) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "putmsg failed");
-    return -1;
-  }
-  dlpaack = (dl_phys_addr_ack_t *)buf;
-  msg.buf = (char *)buf;
-  msg.len = 0;
-  msg.maxlen = sizeof (buf);
-  if (getmsg(fd, &msg, NULL, &flags) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "getmsg failed");
-    return -1;
-  }
-  if (msg.len < DL_PHYS_ADDR_ACK_SIZE ||
-      dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
-    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                    "Couldn't obtain phys addr\n");
-    return -1;
-  }
+    msg.buf = (char *)&dlpareq;
+    msg.len = DL_PHYS_ADDR_REQ_SIZE;
+
+    if (putmsg(fd, &msg, NULL, 0) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
+        return -1;
+    }
+
+    dlpaack = (dl_phys_addr_ack_t *)buf;
 
-  memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
-  return dlpaack->dl_addr_length;
+    msg.buf = (char *)buf;
+    msg.len = 0;
+    msg.maxlen = sizeof (buf);
+    if (getmsg(fd, &msg, NULL, &flags) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
+        return -1;
+    }
+
+    if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
+        return -1;
+    }
+
+    memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
+    return dlpaack->dl_addr_length;
 }
-#endif
 
 /**
  * Get the Hardware address (usually MAC address) for the named interface.
  * return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
-int getMacAddress(JNIEnv *env, const struct in_addr* addr, const char* ifname,
-                  unsigned char *buf) {
-  int sock;
-#ifdef __linux__
-  static struct ifreq ifr;
-  int i;
+static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
+    struct arpreq arpreq;
+    struct sockaddr_in* sin;
+    struct sockaddr_in ipAddr;
+    int len, i;
+
+   /**
+    * On Solaris we have to use DLPI, but it will only work if we have
+    * privileged access (i.e. root). If that fails, we try a lookup
+    * in the ARP table, which requires an IPv4 address.
+    */
+    if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
+        /*DLPI failed - trying to do arp lookup*/
+
+       if (addr == NULL) {
+          /**
+           * No IPv4 address for that interface, so can't do an ARP lookup.
+           */
+           return -1;
+      }
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
+      len = 6; //???
+
+      sin = (struct sockaddr_in *) &arpreq.arp_pa;
+      memset((char *) &arpreq, 0, sizeof(struct arpreq));
+      ipAddr.sin_port = 0;
+      ipAddr.sin_family = AF_INET;
+      memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
+      memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
+      arpreq.arp_flags= ATF_PUBL;
 
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
+      if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
+          if (errno != ENXIO) {
+              // "No such device or address" means no hardware address, so it's
+              // normal don't throw an exception
+              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL failed");
+              return -1;
+          }
+     }
+
+     memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
   }
 
-  strcpy(ifr.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
-    fprintf(stderr, "SIOCIFHWADDR: %s\n",
-            strerror(errno));
-    close(sock);
-    return -1;
-  }
-  memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
-  close(sock);
-  for (i = 0; i < IFHWADDRLEN; i++) {
-    if (buf[i] != 0)
-      return IFHWADDRLEN;
-  }
-  /*
-   * All bytes to 0 means no hardware address.
-   */
-  return -1;
-#else
-  struct arpreq arpreq;
-  struct sockaddr_in* sin;
-  struct sockaddr_in ipAddr;
-  int len;
-
-  /**
-   * On Solaris we have to use DLPI, but it will only work if we have
-   * privileged access (i.e. root). If that fails, we try a lookup
-   * in the ARP table, which requires an IPv4 address.
-   */
-  if ((len = getMacFromDevice(env, ifname, buf)) > 0) {
-    return len;
-  }
-  if (addr == NULL) {
-    /**
-     * No IPv4 address for that interface, so can't do an ARP lookup.
+    /*
+     * All bytes to 0 means no hardware address.
      */
-    return -1;
-  }
-  sin = (struct sockaddr_in *) &arpreq.arp_pa;
-  memset((char *) &arpreq, 0, sizeof(struct arpreq));
-  ipAddr.sin_port = 0;
-  ipAddr.sin_family = AF_INET;
-  memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
-  memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
-  arpreq.arp_flags= ATF_PUBL;
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
-  }
 
-  if (ioctl(sock, SIOCGARP, &arpreq) >= 0) {
-    close(sock);
-    memcpy(buf, &arpreq.arp_ha.sa_data[0], 6);
-    return 6;
-  }
-
-  if (errno != ENXIO) {
-    // "No such device or address" means no hardware address, so it's
-    // normal don't throw an exception
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
-  }
-  close(sock);
-#endif
-  return -1;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isUp0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    short val;
+    for (i = 0; i < len; i++) {
+      if (buf[i] != 0)
+         return len;
+    }
 
-    val = getFlags(env, name);
-    if ( (val & IFF_UP) && (val &  IFF_RUNNING))
-      return JNI_TRUE;
-    return JNI_FALSE;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isP2P0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    if (getFlags(env, name) & IFF_POINTOPOINT)
-      return JNI_TRUE;
-    return JNI_FALSE;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isLoopback0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    if (getFlags(env, name) & IFF_LOOPBACK)
-      return JNI_TRUE;
-    return JNI_FALSE;
+    return -1;
 }
 
-/*
- * Class:     java_net_NetworkInterface
- * Method:    supportsMulticast0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
-(JNIEnv *env, jclass cls, jstring name, jint index) {
-  short val;
+static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
+    struct lifreq if2;
 
-  val = getFlags(env, name);
-  if (val & IFF_MULTICAST)
-    return JNI_TRUE;
-  return JNI_FALSE;
-}
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
 
-/*
- * Class:     java_net_NetworkInterface
- * Method:    getMacAddr0
- * Signature: ([bLjava/lang/String;I)[b
- */
-JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
-  jint addr;
-  jbyte caddr[4];
-  struct in_addr iaddr;
-  jbyteArray ret = NULL;
-  unsigned char mac[16];
-  int len;
-  jboolean isCopy;
-  const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+    if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
+        return -1;
+    }
 
-  if (!IS_NULL(addrArray)) {
-    (*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);
-    iaddr.s_addr = htonl(addr);
-    len = getMacAddress(env, &iaddr, name_utf, mac);
-  } else {
-    len = getMacAddress(env, NULL, name_utf, mac);
-  }
-  if (len > 0) {
-    ret = (*env)->NewByteArray(env, len);
-    if (IS_NULL(ret)) {
-      /* we may have memory to free at the end of this */
-      goto fexit;
-    }
-    (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
-  }
- fexit:
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
-  return ret;
+    return  if2.lifr_mtu;
 }
 
-/*
- * Class:       java_net_NetworkInterface
- * Method:      getMTU0
- * Signature:   ([bLjava/lang/String;I)I
- */
 
-JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
-  jboolean isCopy;
-  int sock;
-  struct ifreq if2;
-  int ret = -1;
-  const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-  } else {
-
-#ifdef __linux__
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.ifr_name, name_utf);
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+     struct   lifreq lifr;
+     memset((caddr_t)&lifr, 0, sizeof(lifr));
+     strcpy((caddr_t)&(lifr.lifr_name), ifname);
 
-    if (ioctl(sock, SIOCGIFMTU, (char *)&if2) >= 0) {
-      ret= if2.ifr_mtu;
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "IOCTL failed");
-    }
-#else /* Solaris */
-    struct   lifreq lifr;
-    memset((caddr_t)&lifr, 0, sizeof(lifr));
-    strcpy((caddr_t)&(lifr.lifr_name), name_utf);
-    if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
-      ret = lifr.lifr_mtu;
-#ifdef AF_INET6
-    } else {
-      /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
-      close(sock);
-      sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
+         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+         return -1;
+     }
 
-      if (sock < 0) {
-        (*env)->ReleaseStringUTFChars(env, name, name_utf);
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Socket creation failed");
-        return -1;
-      }
+     return  lifr.lifr_flags;
+}
+
 
-      if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
-        ret = lifr.lifr_mtu;
-      } else {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "IOCTL failed");
-      }
-    }
-#else
-    } else {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "IOCTL failed");
-    }
 #endif
-#endif
-    close(sock);
-  }
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
-  return ret;
-}
+
+