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