1 /*
   2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 #include <errno.h>
  28 #include <strings.h>
  29 #if defined(_ALLBSD_SOURCE) && defined(__OpenBSD__)
  30 #include <sys/types.h>
  31 #endif
  32 #include <netinet/in.h>
  33 #include <stdlib.h>
  34 #include <string.h>
  35 #include <sys/types.h>
  36 #include <sys/socket.h>
  37 #include <arpa/inet.h>
  38 #include <net/if.h>
  39 #include <net/if_arp.h>
  40 
  41 #ifdef __solaris__
  42 #include <sys/dlpi.h>
  43 #include <fcntl.h>
  44 #include <stropts.h>
  45 #include <sys/sockio.h>
  46 #endif
  47 
  48 #ifdef __linux__
  49 #include <sys/ioctl.h>
  50 #include <bits/ioctls.h>
  51 #include <sys/utsname.h>
  52 #include <stdio.h>
  53 #endif
  54 
  55 #ifdef __linux__
  56 #define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
  57 #endif
  58 
  59 #if defined(_ALLBSD_SOURCE)
  60 #include <sys/param.h>
  61 #include <sys/ioctl.h>
  62 #include <sys/sockio.h>
  63 #if defined(__APPLE__)
  64 #include <net/ethernet.h>
  65 #include <net/if_var.h>
  66 #include <net/if_dl.h>
  67 #include <netinet/in_var.h>
  68 #include <ifaddrs.h>
  69 #endif
  70 #endif
  71 
  72 #include "jvm.h"
  73 #include "jni_util.h"
  74 #include "net_util.h"
  75 
  76 typedef struct _netaddr  {
  77     struct sockaddr *addr;
  78     struct sockaddr *brdcast;
  79     short mask;
  80     int family; /* to make searches simple */
  81     struct _netaddr *next;
  82 } netaddr;
  83 
  84 typedef struct _netif {
  85     char *name;
  86     int index;
  87     char virtual;
  88     netaddr *addr;
  89     struct _netif *childs;
  90     struct _netif *next;
  91 } netif;
  92 
  93 /************************************************************************
  94  * NetworkInterface
  95  */
  96 
  97 #include "java_net_NetworkInterface.h"
  98 
  99 /************************************************************************
 100  * NetworkInterface
 101  */
 102 jclass ni_class;
 103 jfieldID ni_nameID;
 104 jfieldID ni_indexID;
 105 jfieldID ni_descID;
 106 jfieldID ni_addrsID;
 107 jfieldID ni_bindsID;
 108 jfieldID ni_virutalID;
 109 jfieldID ni_childsID;
 110 jfieldID ni_parentID;
 111 jfieldID ni_defaultIndexID;
 112 jmethodID ni_ctrID;
 113 
 114 static jclass ni_iacls;
 115 static jclass ni_ia4cls;
 116 static jclass ni_ia6cls;
 117 static jclass ni_ibcls;
 118 static jmethodID ni_ia4ctrID;
 119 static jmethodID ni_ia6ctrID;
 120 static jmethodID ni_ibctrID;
 121 static jfieldID ni_ia6ipaddressID;
 122 static jfieldID ni_ibaddressID;
 123 static jfieldID ni_ib4broadcastID;
 124 static jfieldID ni_ib4maskID;
 125 
 126 /** Private methods declarations **/
 127 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
 128 static int     getFlags0(JNIEnv *env, jstring  ifname);
 129 
 130 static netif  *enumInterfaces(JNIEnv *env);
 131 static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
 132 
 133 #ifdef AF_INET6
 134 static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 135 #endif
 136 
 137 static netif  *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
 138 static void    freeif(netif *ifs);
 139 
 140 static int     openSocket(JNIEnv *env, int proto);
 141 static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
 142 
 143 
 144 static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
 145 static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
 146 static int     getIndex(int sock, const char *ifname);
 147 
 148 static int     getFlags(int sock, const char *ifname, int *flags);
 149 static int     getMacAddress(JNIEnv *env, int sock,  const char* ifname, const struct in_addr* addr, unsigned char *buf);
 150 static int     getMTU(JNIEnv *env, int sock, const char *ifname);
 151 
 152 
 153 
 154 #ifdef __solaris__
 155 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
 156 static int    getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
 157 
 158 #ifndef SIOCGLIFHWADDR
 159 #define SIOCGLIFHWADDR  _IOWR('i', 192, struct lifreq)
 160 #endif
 161 
 162 #endif
 163 
 164 /******************* Java entry points *****************************/
 165 
 166 /*
 167  * Class:     java_net_NetworkInterface
 168  * Method:    init
 169  * Signature: ()V
 170  */
 171 JNIEXPORT void JNICALL
 172 Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
 173     ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
 174     ni_class = (*env)->NewGlobalRef(env, ni_class);
 175     ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
 176     ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
 177     ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
 178     ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
 179     ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
 180     ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
 181     ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
 182     ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
 183     ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
 184 
 185     ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
 186     ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
 187     ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
 188     ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
 189     ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
 190     ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
 191     ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
 192     ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
 193     ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
 194     ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
 195     ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
 196     ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
 197     ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
 198     ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
 199     ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
 200     ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", "I");
 201 }
 202 
 203 
 204 /*
 205  * Class:     java_net_NetworkInterface
 206  * Method:    getByName0
 207  * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
 208  */
 209 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
 210     (JNIEnv *env, jclass cls, jstring name) {
 211 
 212     netif *ifs, *curr;
 213     jboolean isCopy;
 214     const char* name_utf;
 215     jobject obj = NULL;
 216 
 217     ifs = enumInterfaces(env);
 218     if (ifs == NULL) {
 219         return NULL;
 220     }
 221 
 222     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 223 
 224     /*
 225      * Search the list of interface based on name
 226      */
 227     curr = ifs;
 228     while (curr != NULL) {
 229         if (strcmp(name_utf, curr->name) == 0) {
 230             break;
 231         }
 232         curr = curr->next;
 233     }
 234 
 235     /* if found create a NetworkInterface */
 236     if (curr != NULL) {;
 237         obj = createNetworkInterface(env, curr);
 238     }
 239 
 240     /* release the UTF string and interface list */
 241     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 242     freeif(ifs);
 243 
 244     return obj;
 245 }
 246 
 247 
 248 /*
 249  * Class:     java_net_NetworkInterface
 250  * Method:    getByIndex0
 251  * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
 252  */
 253 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
 254     (JNIEnv *env, jclass cls, jint index) {
 255 
 256     netif *ifs, *curr;
 257     jobject obj = NULL;
 258 
 259     if (index <= 0) {
 260         return NULL;
 261     }
 262 
 263     ifs = enumInterfaces(env);
 264     if (ifs == NULL) {
 265         return NULL;
 266     }
 267 
 268     /*
 269      * Search the list of interface based on index
 270      */
 271     curr = ifs;
 272     while (curr != NULL) {
 273         if (index == curr->index) {
 274             break;
 275         }
 276         curr = curr->next;
 277     }
 278 
 279     /* if found create a NetworkInterface */
 280     if (curr != NULL) {;
 281         obj = createNetworkInterface(env, curr);
 282     }
 283 
 284     freeif(ifs);
 285     return obj;
 286 }
 287 
 288 /*
 289  * Class:     java_net_NetworkInterface
 290  * Method:    getByInetAddress0
 291  * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
 292  */
 293 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
 294     (JNIEnv *env, jclass cls, jobject iaObj) {
 295 
 296     netif *ifs, *curr;
 297 
 298 #ifdef AF_INET6
 299     int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
 300 #else
 301     int family =  AF_INET;
 302 #endif
 303 
 304     jobject obj = NULL;
 305     jboolean match = JNI_FALSE;
 306 
 307     ifs = enumInterfaces(env);
 308     if (ifs == NULL) {
 309         return NULL;
 310     }
 311 
 312     curr = ifs;
 313     while (curr != NULL) {
 314         netaddr *addrP = curr->addr;
 315 
 316         /*
 317          * Iterate through each address on the interface
 318          */
 319         while (addrP != NULL) {
 320 
 321             if (family == addrP->family) {
 322                 if (family == AF_INET) {
 323                     int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
 324                     int address2 = getInetAddress_addr(env, iaObj);
 325 
 326                     if (address1 == address2) {
 327                         match = JNI_TRUE;
 328                         break;
 329                     }
 330                 }
 331 
 332 #ifdef AF_INET6
 333                 if (family == AF_INET6) {
 334                     jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
 335                     jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
 336                     jbyte caddr[16];
 337                     int i;
 338 
 339                     (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
 340                     i = 0;
 341                     while (i < 16) {
 342                         if (caddr[i] != bytes[i]) {
 343                             break;
 344                         }
 345                         i++;
 346                     }
 347                     if (i >= 16) {
 348                         match = JNI_TRUE;
 349                         break;
 350                     }
 351                 }
 352 #endif
 353 
 354             }
 355 
 356             if (match) {
 357                 break;
 358             }
 359             addrP = addrP->next;
 360         }
 361 
 362         if (match) {
 363             break;
 364         }
 365         curr = curr->next;
 366     }
 367 
 368     /* if found create a NetworkInterface */
 369     if (match) {;
 370         obj = createNetworkInterface(env, curr);
 371     }
 372 
 373     freeif(ifs);
 374     return obj;
 375 }
 376 
 377 
 378 /*
 379  * Class:     java_net_NetworkInterface
 380  * Method:    getAll
 381  * Signature: ()[Ljava/net/NetworkInterface;
 382  */
 383 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
 384     (JNIEnv *env, jclass cls) {
 385 
 386     netif *ifs, *curr;
 387     jobjectArray netIFArr;
 388     jint arr_index, ifCount;
 389 
 390     ifs = enumInterfaces(env);
 391     if (ifs == NULL) {
 392         return NULL;
 393     }
 394 
 395     /* count the interface */
 396     ifCount = 0;
 397     curr = ifs;
 398     while (curr != NULL) {
 399         ifCount++;
 400         curr = curr->next;
 401     }
 402 
 403     /* allocate a NetworkInterface array */
 404     netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
 405     if (netIFArr == NULL) {
 406         freeif(ifs);
 407         return NULL;
 408     }
 409 
 410     /*
 411      * Iterate through the interfaces, create a NetworkInterface instance
 412      * for each array element and populate the object.
 413      */
 414     curr = ifs;
 415     arr_index = 0;
 416     while (curr != NULL) {
 417         jobject netifObj;
 418 
 419         netifObj = createNetworkInterface(env, curr);
 420         if (netifObj == NULL) {
 421             freeif(ifs);
 422             return NULL;
 423         }
 424 
 425         /* put the NetworkInterface into the array */
 426         (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
 427 
 428         curr = curr->next;
 429     }
 430 
 431     freeif(ifs);
 432     return netIFArr;
 433 }
 434 
 435 
 436 /*
 437  * Class:     java_net_NetworkInterface
 438  * Method:    isUp0
 439  * Signature: (Ljava/lang/String;I)Z
 440  */
 441 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
 442     int ret = getFlags0(env, name);
 443     return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE :  JNI_FALSE;
 444 }
 445 
 446 /*
 447  * Class:     java_net_NetworkInterface
 448  * Method:    isP2P0
 449  * Signature: (Ljava/lang/String;I)Z
 450  */
 451 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
 452     int ret = getFlags0(env, name);
 453     return (ret & IFF_POINTOPOINT) ? JNI_TRUE :  JNI_FALSE;
 454 }
 455 
 456 /*
 457  * Class:     java_net_NetworkInterface
 458  * Method:    isLoopback0
 459  * Signature: (Ljava/lang/String;I)Z
 460  */
 461 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
 462     int ret = getFlags0(env, name);
 463     return (ret & IFF_LOOPBACK) ? JNI_TRUE :  JNI_FALSE;
 464 }
 465 
 466 /*
 467  * Class:     java_net_NetworkInterface
 468  * Method:    supportsMulticast0
 469  * Signature: (Ljava/lang/String;I)Z
 470  */
 471 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
 472     int ret = getFlags0(env, name);
 473     return (ret & IFF_MULTICAST) ? JNI_TRUE :  JNI_FALSE;
 474 }
 475 
 476 /*
 477  * Class:     java_net_NetworkInterface
 478  * Method:    getMacAddr0
 479  * Signature: ([bLjava/lang/String;I)[b
 480  */
 481 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
 482     jint addr;
 483     jbyte caddr[4];
 484     struct in_addr iaddr;
 485     jbyteArray ret = NULL;
 486     unsigned char mac[16];
 487     int len;
 488     int sock;
 489     jboolean isCopy;
 490     const char* name_utf;
 491 
 492     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 493 
 494     if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
 495        (*env)->ReleaseStringUTFChars(env, name, name_utf);
 496        return JNI_FALSE;
 497     }
 498 
 499 
 500     if (!IS_NULL(addrArray)) {
 501        (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
 502        addr = ((caddr[0]<<24) & 0xff000000);
 503        addr |= ((caddr[1] <<16) & 0xff0000);
 504        addr |= ((caddr[2] <<8) & 0xff00);
 505        addr |= (caddr[3] & 0xff);
 506        iaddr.s_addr = htonl(addr);
 507        len = getMacAddress(env, sock, name_utf, &iaddr, mac);
 508     } else {
 509        len = getMacAddress(env, sock, name_utf,NULL, mac);
 510     }
 511     if (len > 0) {
 512        ret = (*env)->NewByteArray(env, len);
 513        if (IS_NULL(ret)) {
 514           /* we may have memory to free at the end of this */
 515           goto fexit;
 516        }
 517        (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
 518     }
 519  fexit:
 520    /* release the UTF string and interface list */
 521    (*env)->ReleaseStringUTFChars(env, name, name_utf);
 522 
 523    close(sock);
 524    return ret;
 525 }
 526 
 527 /*
 528  * Class:       java_net_NetworkInterface
 529  * Method:      getMTU0
 530  * Signature:   ([bLjava/lang/String;I)I
 531  */
 532 
 533 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
 534     jboolean isCopy;
 535     int ret = -1;
 536     int sock;
 537     const char* name_utf;
 538 
 539     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 540 
 541     if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
 542        (*env)->ReleaseStringUTFChars(env, name, name_utf);
 543        return JNI_FALSE;
 544     }
 545 
 546     ret = getMTU(env, sock, name_utf);
 547 
 548     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 549 
 550     close(sock);
 551     return ret;
 552 }
 553 
 554 /*** Private methods definitions ****/
 555 
 556 static int getFlags0(JNIEnv *env, jstring name) {
 557     jboolean isCopy;
 558     int ret, sock;
 559     const char* name_utf;
 560     int flags = 0;
 561 
 562     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 563 
 564     if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
 565         (*env)->ReleaseStringUTFChars(env, name, name_utf);
 566          return -1;
 567     }
 568 
 569     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 570 
 571     ret = getFlags(sock, name_utf, &flags);
 572 
 573     close(sock);
 574     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 575 
 576     if (ret < 0) {
 577         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
 578         return -1;
 579     }
 580 
 581     return flags;
 582 }
 583 
 584 
 585 
 586 
 587 /*
 588  * Create a NetworkInterface object, populate the name and index, and
 589  * populate the InetAddress array based on the IP addresses for this
 590  * interface.
 591  */
 592 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
 593     jobject netifObj;
 594     jobject name;
 595     jobjectArray addrArr;
 596     jobjectArray bindArr;
 597     jobjectArray childArr;
 598     netaddr *addrs;
 599     jint addr_index, addr_count, bind_index;
 600     jint child_count, child_index;
 601     netaddr *addrP;
 602     netif *childP;
 603     jobject tmp;
 604 
 605     /*
 606      * Create a NetworkInterface object and populate it
 607      */
 608     netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
 609     name = (*env)->NewStringUTF(env, ifs->name);
 610     if (netifObj == NULL || name == NULL) {
 611         return NULL;
 612     }
 613     (*env)->SetObjectField(env, netifObj, ni_nameID, name);
 614     (*env)->SetObjectField(env, netifObj, ni_descID, name);
 615     (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
 616     (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
 617 
 618     /*
 619      * Count the number of address on this interface
 620      */
 621     addr_count = 0;
 622     addrP = ifs->addr;
 623     while (addrP != NULL) {
 624         addr_count++;
 625         addrP = addrP->next;
 626     }
 627 
 628     /*
 629      * Create the array of InetAddresses
 630      */
 631     addrArr = (*env)->NewObjectArray(env, addr_count,  ni_iacls, NULL);
 632     if (addrArr == NULL) {
 633         return NULL;
 634     }
 635 
 636     bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
 637     if (bindArr == NULL) {
 638        return NULL;
 639     }
 640     addrP = ifs->addr;
 641     addr_index = 0;
 642     bind_index = 0;
 643     while (addrP != NULL) {
 644         jobject iaObj = NULL;
 645         jobject ibObj = NULL;
 646 
 647         if (addrP->family == AF_INET) {
 648             iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
 649             if (iaObj) {
 650                  setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
 651             }
 652             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 653             if (ibObj) {
 654                  (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 655                  if (addrP->brdcast) {
 656                     jobject ia2Obj = NULL;
 657                     ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
 658                     if (ia2Obj) {
 659                        setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
 660                        (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
 661                     }
 662                  }
 663                  (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
 664                  (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
 665             }
 666         }
 667 
 668 #ifdef AF_INET6
 669         if (addrP->family == AF_INET6) {
 670             int scope=0;
 671             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
 672             if (iaObj) {
 673                 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
 674                 if (ipaddress == NULL) {
 675                     return NULL;
 676                 }
 677                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 678                                                                         (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
 679 
 680                 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
 681 
 682                 if (scope != 0) { /* zero is default value, no need to set */
 683                     (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 684                     (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 685                     (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
 686                 }
 687                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
 688             }
 689             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 690             if (ibObj) {
 691                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 692                 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
 693                 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
 694             }
 695         }
 696 #endif
 697 
 698         if (iaObj == NULL) {
 699             return NULL;
 700         }
 701 
 702         (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
 703         addrP = addrP->next;
 704     }
 705 
 706     /*
 707      * See if there is any virtual interface attached to this one.
 708      */
 709     child_count = 0;
 710     childP = ifs->childs;
 711     while (childP) {
 712         child_count++;
 713         childP = childP->next;
 714     }
 715 
 716     childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
 717     if (childArr == NULL) {
 718         return NULL;
 719     }
 720 
 721     /*
 722      * Create the NetworkInterface instances for the sub-interfaces as
 723      * well.
 724      */
 725     child_index = 0;
 726     childP = ifs->childs;
 727     while(childP) {
 728       tmp = createNetworkInterface(env, childP);
 729       if (tmp == NULL) {
 730          return NULL;
 731       }
 732       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
 733       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
 734       childP = childP->next;
 735     }
 736     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
 737     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
 738     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 739 
 740     /* return the NetworkInterface */
 741     return netifObj;
 742 }
 743 
 744 /*
 745  * Enumerates all interfaces
 746  */
 747 static netif *enumInterfaces(JNIEnv *env) {
 748     netif *ifs;
 749     int sock;
 750 
 751     /*
 752      * Enumerate IPv4 addresses
 753      */
 754 
 755     sock = openSocket(env, AF_INET);
 756     if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 757         return NULL;
 758     }
 759 
 760     ifs = enumIPv4Interfaces(env, sock, NULL);
 761     close(sock);
 762 
 763     if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
 764         return NULL;
 765     }
 766 
 767     /* return partial list if an exception occurs in the middle of process ???*/
 768 
 769     /*
 770      * If IPv6 is available then enumerate IPv6 addresses.
 771      */
 772 #ifdef AF_INET6
 773 
 774         /* User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
 775          * so we have to call ipv6_available()
 776          */
 777         if (ipv6_available()) {
 778 
 779            sock =  openSocket(env, AF_INET6);
 780            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 781                freeif(ifs);
 782                return NULL;
 783            }
 784 
 785            ifs = enumIPv6Interfaces(env, sock, ifs);
 786            close(sock);
 787 
 788            if ((*env)->ExceptionOccurred(env)) {
 789               freeif(ifs);
 790               return NULL;
 791            }
 792 
 793        }
 794 #endif
 795 
 796     return ifs;
 797 }
 798 
 799 #define CHECKED_MALLOC3(_pointer,_type,_size) \
 800        do{ \
 801         _pointer = (_type)malloc( _size ); \
 802         if (_pointer == NULL) { \
 803             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
 804             return ifs; /* return untouched list */ \
 805         } \
 806        } while(0)
 807 
 808 
 809 /*
 810  * Free an interface list (including any attached addresses)
 811  */
 812 void freeif(netif *ifs) {
 813     netif *currif = ifs;
 814     netif *child = NULL;
 815 
 816     while (currif != NULL) {
 817         netaddr *addrP = currif->addr;
 818         while (addrP != NULL) {
 819             netaddr *next = addrP->next;
 820             free(addrP);
 821             addrP = next;
 822          }
 823 
 824             /*
 825             * Don't forget to free the sub-interfaces.
 826             */
 827           if (currif->childs != NULL) {
 828                 freeif(currif->childs);
 829           }
 830 
 831           ifs = currif->next;
 832           free(currif);
 833           currif = ifs;
 834     }
 835 }
 836 
 837 netif *addif(JNIEnv *env, int sock, const char * if_name,
 838              netif *ifs, struct sockaddr* ifr_addrP, int family,
 839              short prefix)
 840 {
 841     netif *currif = ifs, *parent;
 842     netaddr *addrP;
 843 
 844 #ifdef LIFNAMSIZ
 845     int ifnam_size = LIFNAMSIZ;
 846     char name[LIFNAMSIZ], vname[LIFNAMSIZ];
 847 #else
 848     int ifnam_size = IFNAMSIZ;
 849     char name[IFNAMSIZ], vname[IFNAMSIZ];
 850 #endif
 851 
 852     char  *name_colonP;
 853     int mask;
 854     int isVirtual = 0;
 855     int addr_size;
 856     int flags = 0;
 857 
 858     /*
 859      * If the interface name is a logical interface then we
 860      * remove the unit number so that we have the physical
 861      * interface (eg: hme0:1 -> hme0). NetworkInterface
 862      * currently doesn't have any concept of physical vs.
 863      * logical interfaces.
 864      */
 865     strncpy(name, if_name, ifnam_size);
 866     name[ifnam_size - 1] = '\0';
 867     *vname = 0;
 868 
 869     /*
 870      * Create and populate the netaddr node. If allocation fails
 871      * return an un-updated list.
 872      */
 873     /*Allocate for addr and brdcast at once*/
 874 
 875 #ifdef AF_INET6
 876     addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
 877 #else
 878     addr_size = sizeof(struct sockaddr_in);
 879 #endif
 880 
 881     CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
 882     addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
 883     memcpy(addrP->addr, ifr_addrP, addr_size);
 884 
 885     addrP->family = family;
 886     addrP->brdcast = NULL;
 887     addrP->mask = prefix;
 888     addrP->next = 0;
 889     if (family == AF_INET) {
 890        // Deal with broadcast addr & subnet mask
 891        struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
 892        addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
 893 
 894        if ((mask = getSubnet(env, sock, name)) != -1)
 895            addrP->mask = mask;
 896      }
 897 
 898     /**
 899      * Deal with virtual interface with colon notation e.g. eth0:1
 900      */
 901     name_colonP = strchr(name, ':');
 902     if (name_colonP != NULL) {
 903       /**
 904        * This is a virtual interface. If we are able to access the parent
 905        * we need to create a new entry if it doesn't exist yet *and* update
 906        * the 'parent' interface with the new records.
 907        */
 908         *name_colonP = 0;
 909         if (getFlags(sock, name, &flags) < 0 || flags < 0) {
 910             // failed to access parent interface do not create parent.
 911             // We are a virtual interface with no parent.
 912             isVirtual = 1;
 913             *name_colonP = ':';
 914         }
 915         else{
 916            // Got access to parent, so create it if necessary.
 917            // Save original name to vname and truncate name by ':'
 918             memcpy(vname, name, sizeof(vname) );
 919             vname[name_colonP - name] = ':';
 920         }
 921     }
 922 
 923     /*
 924      * Check if this is a "new" interface. Use the interface
 925      * name for matching because index isn't supported on
 926      * Solaris 2.6 & 7.
 927      */
 928     while (currif != NULL) {
 929         if (strcmp(name, currif->name) == 0) {
 930             break;
 931         }
 932         currif = currif->next;
 933     }
 934 
 935     /*
 936      * If "new" then create an netif structure and
 937      * insert it onto the list.
 938      */
 939     if (currif == NULL) {
 940          CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
 941          currif->name = (char *) currif+sizeof(netif);
 942          strncpy(currif->name, name, ifnam_size);
 943          currif->name[ifnam_size - 1] = '\0';
 944          currif->index = getIndex(sock, name);
 945          currif->addr = NULL;
 946          currif->childs = NULL;
 947          currif->virtual = isVirtual;
 948          currif->next = ifs;
 949          ifs = currif;
 950     }
 951 
 952     /*
 953      * Finally insert the address on the interface
 954      */
 955     addrP->next = currif->addr;
 956     currif->addr = addrP;
 957 
 958     parent = currif;
 959 
 960     /**
 961      * Let's deal with the virtual interface now.
 962      */
 963     if (vname[0]) {
 964         netaddr *tmpaddr;
 965 
 966         currif = parent->childs;
 967 
 968         while (currif != NULL) {
 969             if (strcmp(vname, currif->name) == 0) {
 970                 break;
 971             }
 972             currif = currif->next;
 973         }
 974 
 975         if (currif == NULL) {
 976             CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
 977             currif->name = (char *) currif + sizeof(netif);
 978             strncpy(currif->name, vname, ifnam_size);
 979             currif->name[ifnam_size - 1] = '\0';
 980             currif->index = getIndex(sock, vname);
 981             currif->addr = NULL;
 982            /* Need to duplicate the addr entry? */
 983             currif->virtual = 1;
 984             currif->childs = NULL;
 985             currif->next = parent->childs;
 986             parent->childs = currif;
 987         }
 988 
 989         CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
 990         memcpy(tmpaddr, addrP, sizeof(netaddr));
 991         if (addrP->addr != NULL) {
 992             tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
 993             memcpy(tmpaddr->addr, addrP->addr, addr_size);
 994         }
 995 
 996         if (addrP->brdcast != NULL) {
 997             tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
 998             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
 999         }
1000 
1001         tmpaddr->next = currif->addr;
1002         currif->addr = tmpaddr;
1003     }
1004 
1005     return ifs;
1006 }
1007 
1008 /* Open socket for further ioct calls
1009  * proto is AF_INET/AF_INET6
1010  */
1011 static int  openSocket(JNIEnv *env, int proto){
1012     int sock;
1013 
1014     if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
1015         /*
1016          * If EPROTONOSUPPORT is returned it means we don't have
1017          * support  for this proto so don't throw an exception.
1018          */
1019         if (errno != EPROTONOSUPPORT) {
1020             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
1021         }
1022         return -1;
1023     }
1024 
1025     return sock;
1026 }
1027 
1028 
1029 /** Linux **/
1030 #ifdef __linux__
1031 /* Open socket for further ioct calls, try v4 socket first and
1032  * if it falls return v6 socket
1033  */
1034 
1035 #ifdef AF_INET6
1036 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1037     int sock;
1038     struct ifreq if2;
1039 
1040      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1041          if (errno == EPROTONOSUPPORT){
1042               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1043                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1044                  return -1;
1045               }
1046          }
1047          else{ // errno is not NOSUPPORT
1048              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1049              return -1;
1050          }
1051    }
1052 
1053      /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
1054         of address of an interface */
1055 
1056        return sock;
1057 }
1058 
1059 #else
1060 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1061     return openSocket(env,AF_INET);
1062 }
1063 #endif
1064 
1065 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1066     struct ifconf ifc;
1067     struct ifreq *ifreqP;
1068     char *buf;
1069     int numifs;
1070     unsigned i;
1071 
1072 
1073     /* need to do a dummy SIOCGIFCONF to determine the buffer size.
1074      * SIOCGIFCOUNT doesn't work
1075      */
1076     ifc.ifc_buf = NULL;
1077     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1078         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1079         return ifs;
1080     }
1081 
1082     CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
1083 
1084     ifc.ifc_buf = buf;
1085     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1086         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1087         (void) free(buf);
1088         return ifs;
1089     }
1090 
1091     /*
1092      * Iterate through each interface
1093      */
1094     ifreqP = ifc.ifc_req;
1095     for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
1096         /*
1097          * Add to the list
1098          */
1099         ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
1100 
1101         /*
1102          * If an exception occurred then free the list
1103          */
1104         if ((*env)->ExceptionOccurred(env)) {
1105             free(buf);
1106             freeif(ifs);
1107             return NULL;
1108         }
1109     }
1110 
1111     /*
1112      * Free socket and buffer
1113      */
1114     free(buf);
1115     return ifs;
1116 }
1117 
1118 
1119 /*
1120  * Enumerates and returns all IPv6 interfaces on Linux
1121  */
1122 
1123 #ifdef AF_INET6
1124 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1125     FILE *f;
1126     char addr6[40], devname[21];
1127     char addr6p[8][5];
1128     int plen, scope, dad_status, if_idx;
1129     uint8_t ipv6addr[16];
1130 
1131     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1132         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1133                          addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1134                          &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
1135 
1136             struct netif *ifs_ptr = NULL;
1137             struct netif *last_ptr = NULL;
1138             struct sockaddr_in6 addr;
1139 
1140             sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1141                            addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1142             inet_pton(AF_INET6, addr6, ipv6addr);
1143 
1144             memset(&addr, 0, sizeof(struct sockaddr_in6));
1145             memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
1146 
1147             addr.sin6_scope_id = if_idx;
1148 
1149             ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
1150 
1151 
1152             /*
1153              * If an exception occurred then return the list as is.
1154              */
1155             if ((*env)->ExceptionOccurred(env)) {
1156                 fclose(f);
1157                 return ifs;
1158             }
1159        }
1160        fclose(f);
1161     }
1162     return ifs;
1163 }
1164 #endif
1165 
1166 
1167 static int getIndex(int sock, const char *name){
1168      /*
1169       * Try to get the interface index
1170       * (Not supported on Solaris 2.6 or 7)
1171       */
1172     struct ifreq if2;
1173     strcpy(if2.ifr_name, name);
1174 
1175     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1176         return -1;
1177     }
1178 
1179     return if2.ifr_ifindex;
1180 }
1181 
1182 /**
1183  * Returns the IPv4 broadcast address of a named interface, if it exists.
1184  * Returns 0 if it doesn't have one.
1185  */
1186 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1187   struct sockaddr *ret = NULL;
1188   struct ifreq if2;
1189 
1190   memset((char *) &if2, 0, sizeof(if2));
1191   strcpy(if2.ifr_name, ifname);
1192 
1193   /* Let's make sure the interface does have a broadcast address */
1194   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
1195       NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
1196       return ret;
1197   }
1198 
1199   if (if2.ifr_flags & IFF_BROADCAST) {
1200       /* It does, let's retrieve it*/
1201       if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1202           NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
1203           return ret;
1204       }
1205 
1206       ret = brdcast_store;
1207       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1208   }
1209 
1210   return ret;
1211 }
1212 
1213 /**
1214  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1215  * interface, if it has one, otherwise return -1.
1216  */
1217 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1218     unsigned int mask;
1219     short ret;
1220     struct ifreq if2;
1221 
1222     memset((char *) &if2, 0, sizeof(if2));
1223     strcpy(if2.ifr_name, ifname);
1224 
1225     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1226         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1227         return -1;
1228     }
1229 
1230     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1231     ret = 0;
1232     while (mask) {
1233        mask <<= 1;
1234        ret++;
1235     }
1236 
1237     return ret;
1238 }
1239 
1240 /**
1241  * Get the Hardware address (usually MAC address) for the named interface.
1242  * return puts the data in buf, and returns the length, in byte, of the
1243  * MAC address. Returns -1 if there is no hardware address on that interface.
1244  */
1245 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1246     static struct ifreq ifr;
1247     int i;
1248 
1249     strcpy(ifr.ifr_name, ifname);
1250     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1251         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
1252         return -1;
1253     }
1254 
1255     memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1256 
1257    /*
1258     * All bytes to 0 means no hardware address.
1259     */
1260 
1261     for (i = 0; i < IFHWADDRLEN; i++) {
1262         if (buf[i] != 0)
1263             return IFHWADDRLEN;
1264     }
1265 
1266     return -1;
1267 }
1268 
1269 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1270     struct ifreq if2;
1271 
1272     memset((char *) &if2, 0, sizeof(if2));
1273     strcpy(if2.ifr_name, ifname);
1274 
1275     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1276         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1277         return -1;
1278     }
1279 
1280     return  if2.ifr_mtu;
1281 }
1282 
1283 static int getFlags(int sock, const char *ifname, int *flags) {
1284   struct ifreq if2;
1285 
1286   memset((char *) &if2, 0, sizeof(if2));
1287   strcpy(if2.ifr_name, ifname);
1288 
1289   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
1290       return -1;
1291   }
1292 
1293   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1294       *flags = (if2.ifr_flags & 0xffff);
1295   } else {
1296       *flags = if2.ifr_flags;
1297   }
1298   return 0;
1299 }
1300 
1301 #endif
1302 
1303 /** Solaris **/
1304 #ifdef __solaris__
1305 /* Open socket for further ioct calls, try v4 socket first and
1306  * if it falls return v6 socket
1307  */
1308 
1309 #ifdef AF_INET6
1310 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1311     int sock, alreadyV6 = 0;
1312     struct lifreq if2;
1313 
1314      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1315          if (errno == EPROTONOSUPPORT){
1316               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1317                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1318                  return -1;
1319               }
1320 
1321               alreadyV6=1;
1322          }
1323          else{ // errno is not NOSUPPORT
1324              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1325              return -1;
1326          }
1327    }
1328 
1329      /**
1330       * Solaris requires that we have an IPv6 socket to query an
1331       * interface without an IPv4 address - check it here.
1332       * POSIX 1 require the kernel to return ENOTTY if the call is
1333       * inappropriate for a device e.g. the NETMASK for a device having IPv6
1334       * only address but not all devices follow the standard so
1335       * fall back on any error. It's not an ecologically friendly gesture
1336       * but more reliable.
1337       */
1338 
1339     if (! alreadyV6 ){
1340         memset((char *) &if2, 0, sizeof(if2));
1341         strcpy(if2.lifr_name, ifname);
1342         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1343                 close(sock);
1344                 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1345                       NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1346                       return -1;
1347                 }
1348         }
1349     }
1350 
1351     return sock;
1352 }
1353 
1354 #else
1355 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1356     return openSocket(env,AF_INET);
1357 }
1358 #endif
1359 
1360 /*
1361  * Enumerates and returns all IPv4 interfaces
1362  * (linux verision)
1363  */
1364 
1365 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1366      return enumIPvXInterfaces(env,sock, ifs, AF_INET);
1367 }
1368 
1369 #ifdef AF_INET6
1370 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1371     return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
1372 }
1373 #endif
1374 
1375 /*
1376    Enumerates and returns all interfaces on Solaris
1377    use the same code for IPv4 and IPv6
1378  */
1379 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
1380     struct lifconf ifc;
1381     struct lifreq *ifr;
1382     int n;
1383     char *buf;
1384     struct lifnum numifs;
1385     unsigned bufsize;
1386 
1387     /*
1388      * Get the interface count
1389      */
1390     numifs.lifn_family = family;
1391     numifs.lifn_flags = 0;
1392     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
1393         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
1394         return ifs;
1395     }
1396 
1397     /*
1398      *  Enumerate the interface configurations
1399      */
1400     bufsize = numifs.lifn_count * sizeof (struct lifreq);
1401     CHECKED_MALLOC3(buf, char *, bufsize);
1402 
1403     ifc.lifc_family = family;
1404     ifc.lifc_flags = 0;
1405     ifc.lifc_len = bufsize;
1406     ifc.lifc_buf = buf;
1407     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
1408         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
1409         free(buf);
1410         return ifs;
1411     }
1412 
1413     /*
1414      * Iterate through each interface
1415      */
1416     ifr = ifc.lifc_req;
1417     for (n=0; n<numifs.lifn_count; n++, ifr++) {
1418         int index = -1;
1419         struct lifreq if2;
1420 
1421         /*
1422         * Ignore either IPv4 or IPv6 addresses
1423         */
1424         if (ifr->lifr_addr.ss_family != family) {
1425             continue;
1426         }
1427 
1428 #ifdef AF_INET6
1429         if (ifr->lifr_addr.ss_family == AF_INET6) {
1430             struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
1431             s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
1432         }
1433 #endif
1434 
1435         /* add to the list */
1436         ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
1437 
1438         /*
1439         * If an exception occurred we return immediately
1440         */
1441         if ((*env)->ExceptionOccurred(env)) {
1442             free(buf);
1443             return ifs;
1444         }
1445 
1446    }
1447 
1448     free(buf);
1449     return ifs;
1450 }
1451 
1452 static int getIndex(int sock, const char *name){
1453    /*
1454     * Try to get the interface index
1455     * (Not supported on Solaris 2.6 or 7)
1456     */
1457     struct lifreq if2;
1458     strcpy(if2.lifr_name, name);
1459 
1460     if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
1461         return -1;
1462     }
1463 
1464     return if2.lifr_index;
1465 }
1466 
1467 /**
1468  * Returns the IPv4 broadcast address of a named interface, if it exists.
1469  * Returns 0 if it doesn't have one.
1470  */
1471 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1472     struct sockaddr *ret = NULL;
1473     struct lifreq if2;
1474 
1475     memset((char *) &if2, 0, sizeof(if2));
1476     strcpy(if2.lifr_name, ifname);
1477 
1478     /* Let's make sure the interface does have a broadcast address */
1479     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
1480         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
1481         return ret;
1482     }
1483 
1484     if (if2.lifr_flags & IFF_BROADCAST) {
1485         /* It does, let's retrieve it*/
1486         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
1487             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
1488             return ret;
1489         }
1490 
1491         ret = brdcast_store;
1492         memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
1493     }
1494 
1495     return ret;
1496 }
1497 
1498 /**
1499  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1500  * interface, if it has one, otherwise return -1.
1501  */
1502 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1503     unsigned int mask;
1504     short ret;
1505     struct lifreq if2;
1506 
1507     memset((char *) &if2, 0, sizeof(if2));
1508     strcpy(if2.lifr_name, ifname);
1509 
1510     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1511         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
1512         return -1;
1513     }
1514 
1515     mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
1516     ret = 0;
1517 
1518     while (mask) {
1519        mask <<= 1;
1520        ret++;
1521     }
1522 
1523     return ret;
1524 }
1525 
1526 
1527 
1528 #define DEV_PREFIX  "/dev/"
1529 
1530 /**
1531  * Solaris specific DLPI code to get hardware address from a device.
1532  * Unfortunately, at least up to Solaris X, you have to have special
1533  * privileges (i.e. be root).
1534  */
1535 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
1536     char style1dev[MAXPATHLEN];
1537     int fd;
1538     dl_phys_addr_req_t dlpareq;
1539     dl_phys_addr_ack_t *dlpaack;
1540     struct strbuf msg;
1541     char buf[128];
1542     int flags = 0;
1543 
1544    /**
1545     * Device is in /dev
1546     * e.g.: /dev/bge0
1547     */
1548     strcpy(style1dev, DEV_PREFIX);
1549     strcat(style1dev, ifname);
1550     if ((fd = open(style1dev, O_RDWR)) < 0) {
1551         /*
1552          * Can't open it. We probably are missing the privilege.
1553          * We'll have to try something else
1554          */
1555          return 0;
1556     }
1557 
1558     dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1559     dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1560 
1561     msg.buf = (char *)&dlpareq;
1562     msg.len = DL_PHYS_ADDR_REQ_SIZE;
1563 
1564     if (putmsg(fd, &msg, NULL, 0) < 0) {
1565         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
1566         return -1;
1567     }
1568 
1569     dlpaack = (dl_phys_addr_ack_t *)buf;
1570 
1571     msg.buf = (char *)buf;
1572     msg.len = 0;
1573     msg.maxlen = sizeof (buf);
1574     if (getmsg(fd, &msg, NULL, &flags) < 0) {
1575         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
1576         return -1;
1577     }
1578 
1579     if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1580         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
1581         return -1;
1582     }
1583 
1584     memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1585     return dlpaack->dl_addr_length;
1586 }
1587 
1588 /**
1589  * Get the Hardware address (usually MAC address) for the named interface.
1590  * return puts the data in buf, and returns the length, in byte, of the
1591  * MAC address. Returns -1 if there is no hardware address on that interface.
1592  */
1593 static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
1594     struct arpreq arpreq;
1595     struct sockaddr_in* sin;
1596     struct sockaddr_in ipAddr;
1597     int len, i;
1598     struct lifreq lif;
1599 
1600     /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
1601      * try the old way.
1602      */
1603     memset(&lif, 0, sizeof(lif));
1604     strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
1605 
1606     if (ioctl(sock, SIOCGLIFHWADDR, &lif) != -1) {
1607         struct sockaddr_dl *sp;
1608         sp = (struct sockaddr_dl *)&lif.lifr_addr;
1609         memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
1610         return sp->sdl_alen;
1611     }
1612 
1613    /**
1614     * On Solaris we have to use DLPI, but it will only work if we have
1615     * privileged access (i.e. root). If that fails, we try a lookup
1616     * in the ARP table, which requires an IPv4 address.
1617     */
1618     if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
1619         /*DLPI failed - trying to do arp lookup*/
1620 
1621         if (addr == NULL) {
1622             /**
1623              * No IPv4 address for that interface, so can't do an ARP lookup.
1624              */
1625              return -1;
1626          }
1627 
1628          len = 6; //???
1629 
1630          sin = (struct sockaddr_in *) &arpreq.arp_pa;
1631          memset((char *) &arpreq, 0, sizeof(struct arpreq));
1632          ipAddr.sin_port = 0;
1633          ipAddr.sin_family = AF_INET;
1634          memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
1635          memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
1636          arpreq.arp_flags= ATF_PUBL;
1637 
1638          if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
1639              return -1;
1640          }
1641 
1642          memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
1643     }
1644 
1645     /*
1646      * All bytes to 0 means no hardware address.
1647      */
1648 
1649     for (i = 0; i < len; i++) {
1650       if (buf[i] != 0)
1651          return len;
1652     }
1653 
1654     return -1;
1655 }
1656 
1657 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1658     struct lifreq if2;
1659 
1660     memset((char *) &if2, 0, sizeof(if2));
1661     strcpy(if2.lifr_name, ifname);
1662 
1663     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1664         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
1665         return -1;
1666     }
1667 
1668     return  if2.lifr_mtu;
1669 }
1670 
1671 
1672 static int getFlags(int sock, const char *ifname, int *flags) {
1673      struct   lifreq lifr;
1674      memset((caddr_t)&lifr, 0, sizeof(lifr));
1675      strcpy((caddr_t)&(lifr.lifr_name), ifname);
1676 
1677      if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1678          return -1;
1679      }
1680 
1681      *flags = lifr.lifr_flags;
1682      return 0;
1683 }
1684 
1685 
1686 #endif
1687 
1688 
1689 /** BSD **/
1690 #ifdef _ALLBSD_SOURCE
1691 /* Open socket for further ioct calls, try v4 socket first and
1692  * if it falls return v6 socket
1693  */
1694 
1695 #ifdef AF_INET6
1696 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1697     int sock;
1698     struct ifreq if2;
1699 
1700      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1701          if (errno == EPROTONOSUPPORT){
1702               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1703                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1704                  return -1;
1705               }
1706          }
1707          else{ // errno is not NOSUPPORT
1708              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1709              return -1;
1710          }
1711    }
1712 
1713    return sock;
1714 }
1715 
1716 #else
1717 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1718     return openSocket(env,AF_INET);
1719 }
1720 #endif
1721 
1722 /*
1723  * Enumerates and returns all IPv4 interfaces
1724  */
1725 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1726     struct ifaddrs *ifa, *origifa;
1727 
1728     if (getifaddrs(&origifa) != 0) {
1729         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1730                          "getifaddrs() function failed");
1731         return ifs;
1732     }
1733 
1734     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1735 
1736         /*
1737          * Skip non-AF_INET entries.
1738          */
1739         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
1740             continue;
1741 
1742         /*
1743          * Add to the list.
1744          */
1745         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
1746 
1747         /*
1748          * If an exception occurred then free the list.
1749          */
1750         if ((*env)->ExceptionOccurred(env)) {
1751             freeifaddrs(origifa);
1752             freeif(ifs);
1753             return NULL;
1754         }
1755     }
1756 
1757     /*
1758      * Free socket and buffer
1759      */
1760     freeifaddrs(origifa);
1761     return ifs;
1762 }
1763 
1764 
1765 /*
1766  * Enumerates and returns all IPv6 interfaces on Linux
1767  */
1768 
1769 #ifdef AF_INET6
1770 /*
1771  * Determines the prefix on BSD for IPv6 interfaces.
1772  */
1773 static
1774 int prefix(void *val, int size) {
1775     u_char *name = (u_char *)val;
1776     int byte, bit, plen = 0;
1777 
1778     for (byte = 0; byte < size; byte++, plen += 8)
1779         if (name[byte] != 0xff)
1780             break;
1781     if (byte == size)
1782         return (plen);
1783     for (bit = 7; bit != 0; bit--, plen++)
1784         if (!(name[byte] & (1 << bit)))
1785             break;
1786     for (; bit != 0; bit--)
1787         if (name[byte] & (1 << bit))
1788             return (0);
1789     byte++;
1790     for (; byte < size; byte++)
1791         if (name[byte])
1792             return (0);
1793     return (plen);
1794 }
1795 
1796 /*
1797  * Enumerates and returns all IPv6 interfaces on BSD
1798  */
1799 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1800     struct ifaddrs *ifa, *origifa;
1801     struct sockaddr_in6 *sin6;
1802     struct in6_ifreq ifr6;
1803 
1804     if (getifaddrs(&origifa) != 0) {
1805         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1806                          "getifaddrs() function failed");
1807         return ifs;
1808     }
1809 
1810     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1811 
1812         /*
1813          * Skip non-AF_INET6 entries.
1814          */
1815         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
1816             continue;
1817 
1818         memset(&ifr6, 0, sizeof(ifr6));
1819         strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
1820         memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
1821 
1822         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
1823             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1824                              "ioctl SIOCGIFNETMASK_IN6 failed");
1825             freeifaddrs(origifa);
1826             freeif(ifs);
1827             return NULL;
1828         }
1829 
1830         /* Add to the list.  */
1831         sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
1832         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
1833                     prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
1834 
1835         /* If an exception occurred then free the list.  */
1836         if ((*env)->ExceptionOccurred(env)) {
1837             freeifaddrs(origifa);
1838             freeif(ifs);
1839             return NULL;
1840         }
1841     }
1842 
1843     /*
1844      * Free socket and ifaddrs buffer
1845      */
1846     freeifaddrs(origifa);
1847     return ifs;
1848 }
1849 #endif
1850 
1851 static int getIndex(int sock, const char *name){
1852 #ifdef __FreeBSD__
1853      /*
1854       * Try to get the interface index
1855       * (Not supported on Solaris 2.6 or 7)
1856       */
1857     struct ifreq if2;
1858     strcpy(if2.ifr_name, name);
1859 
1860     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1861         return -1;
1862     }
1863 
1864     return if2.ifr_index;
1865 #else
1866     /*
1867      * Try to get the interface index using BSD specific if_nametoindex
1868      */
1869     int index = if_nametoindex(name);
1870     return (index == 0) ? -1 : index;
1871 #endif
1872 }
1873 
1874 /**
1875  * Returns the IPv4 broadcast address of a named interface, if it exists.
1876  * Returns 0 if it doesn't have one.
1877  */
1878 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1879   struct sockaddr *ret = NULL;
1880   struct ifreq if2;
1881 
1882   memset((char *) &if2, 0, sizeof(if2));
1883   strcpy(if2.ifr_name, ifname);
1884 
1885   /* Let's make sure the interface does have a broadcast address */
1886   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1887       NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
1888       return ret;
1889   }
1890 
1891   if (if2.ifr_flags & IFF_BROADCAST) {
1892       /* It does, let's retrieve it*/
1893       if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1894           NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
1895           return ret;
1896       }
1897 
1898       ret = brdcast_store;
1899       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1900   }
1901 
1902   return ret;
1903 }
1904 
1905 /**
1906  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1907  * interface, if it has one, otherwise return -1.
1908  */
1909 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1910     unsigned int mask;
1911     short ret;
1912     struct ifreq if2;
1913 
1914     memset((char *) &if2, 0, sizeof(if2));
1915     strcpy(if2.ifr_name, ifname);
1916 
1917     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1918         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1919         return -1;
1920     }
1921 
1922     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1923     ret = 0;
1924     while (mask) {
1925        mask <<= 1;
1926        ret++;
1927     }
1928 
1929     return ret;
1930 }
1931 
1932 /**
1933  * Get the Hardware address (usually MAC address) for the named interface.
1934  * return puts the data in buf, and returns the length, in byte, of the
1935  * MAC address. Returns -1 if there is no hardware address on that interface.
1936  */
1937 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1938     struct ifaddrs *ifa0, *ifa;
1939     struct sockaddr *saddr;
1940     int i;
1941 
1942     /* Grab the interface list */
1943     if (!getifaddrs(&ifa0)) {
1944         /* Cycle through the interfaces */
1945         for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
1946             saddr = ifa->ifa_addr;
1947             /* Link layer contains the MAC address */
1948             if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
1949                 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
1950                 /* Check the address is the correct length */
1951                 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
1952                     memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
1953                     freeifaddrs(ifa0);
1954                     return ETHER_ADDR_LEN;
1955                 }
1956             }
1957         }
1958         freeifaddrs(ifa0);
1959     }
1960 
1961     return -1;
1962 }
1963 
1964 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1965     struct ifreq if2;
1966 
1967     memset((char *) &if2, 0, sizeof(if2));
1968     strcpy(if2.ifr_name, ifname);
1969 
1970     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1971         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1972         return -1;
1973     }
1974 
1975     return  if2.ifr_mtu;
1976 }
1977 
1978 static int getFlags(int sock, const char *ifname, int *flags) {
1979   struct ifreq if2;
1980   int ret = -1;
1981 
1982   memset((char *) &if2, 0, sizeof(if2));
1983   strcpy(if2.ifr_name, ifname);
1984 
1985   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
1986       return -1;
1987   }
1988 
1989   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1990     *flags = (if2.ifr_flags & 0xffff);
1991   } else {
1992     *flags = if2.ifr_flags;
1993   }
1994   return 0;
1995 }
1996 
1997 #endif