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     ret = getFlags(sock, name_utf, &flags);
 570 
 571     close(sock);
 572     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 573 
 574     if (ret < 0) {
 575         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
 576         return -1;
 577     }
 578 
 579     return flags;
 580 }
 581 
 582 
 583 
 584 
 585 /*
 586  * Create a NetworkInterface object, populate the name and index, and
 587  * populate the InetAddress array based on the IP addresses for this
 588  * interface.
 589  */
 590 jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
 591     jobject netifObj;
 592     jobject name;
 593     jobjectArray addrArr;
 594     jobjectArray bindArr;
 595     jobjectArray childArr;
 596     netaddr *addrs;
 597     jint addr_index, addr_count, bind_index;
 598     jint child_count, child_index;
 599     netaddr *addrP;
 600     netif *childP;
 601     jobject tmp;
 602 
 603     /*
 604      * Create a NetworkInterface object and populate it
 605      */
 606     netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
 607     name = (*env)->NewStringUTF(env, ifs->name);
 608     if (netifObj == NULL || name == NULL) {
 609         return NULL;
 610     }
 611     (*env)->SetObjectField(env, netifObj, ni_nameID, name);
 612     (*env)->SetObjectField(env, netifObj, ni_descID, name);
 613     (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
 614     (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
 615 
 616     /*
 617      * Count the number of address on this interface
 618      */
 619     addr_count = 0;
 620     addrP = ifs->addr;
 621     while (addrP != NULL) {
 622         addr_count++;
 623         addrP = addrP->next;
 624     }
 625 
 626     /*
 627      * Create the array of InetAddresses
 628      */
 629     addrArr = (*env)->NewObjectArray(env, addr_count,  ni_iacls, NULL);
 630     if (addrArr == NULL) {
 631         return NULL;
 632     }
 633 
 634     bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
 635     if (bindArr == NULL) {
 636        return NULL;
 637     }
 638     addrP = ifs->addr;
 639     addr_index = 0;
 640     bind_index = 0;
 641     while (addrP != NULL) {
 642         jobject iaObj = NULL;
 643         jobject ibObj = NULL;
 644 
 645         if (addrP->family == AF_INET) {
 646             iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
 647             if (iaObj) {
 648                  setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
 649             }
 650             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 651             if (ibObj) {
 652                  (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 653                  if (addrP->brdcast) {
 654                     jobject ia2Obj = NULL;
 655                     ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
 656                     if (ia2Obj) {
 657                        setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
 658                        (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
 659                     }
 660                  }
 661                  (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
 662                  (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
 663             }
 664         }
 665 
 666 #ifdef AF_INET6
 667         if (addrP->family == AF_INET6) {
 668             int scope=0;
 669             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
 670             if (iaObj) {
 671                 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
 672                 if (ipaddress == NULL) {
 673                     return NULL;
 674                 }
 675                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 676                                                                         (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
 677 
 678                 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
 679 
 680                 if (scope != 0) { /* zero is default value, no need to set */
 681                     (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 682                     (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 683                     (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
 684                 }
 685                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
 686             }
 687             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 688             if (ibObj) {
 689                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 690                 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
 691                 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
 692             }
 693         }
 694 #endif
 695 
 696         if (iaObj == NULL) {
 697             return NULL;
 698         }
 699 
 700         (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
 701         addrP = addrP->next;
 702     }
 703 
 704     /*
 705      * See if there is any virtual interface attached to this one.
 706      */
 707     child_count = 0;
 708     childP = ifs->childs;
 709     while (childP) {
 710         child_count++;
 711         childP = childP->next;
 712     }
 713 
 714     childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
 715     if (childArr == NULL) {
 716         return NULL;
 717     }
 718 
 719     /*
 720      * Create the NetworkInterface instances for the sub-interfaces as
 721      * well.
 722      */
 723     child_index = 0;
 724     childP = ifs->childs;
 725     while(childP) {
 726       tmp = createNetworkInterface(env, childP);
 727       if (tmp == NULL) {
 728          return NULL;
 729       }
 730       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
 731       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
 732       childP = childP->next;
 733     }
 734     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
 735     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
 736     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 737 
 738     /* return the NetworkInterface */
 739     return netifObj;
 740 }
 741 
 742 /*
 743  * Enumerates all interfaces
 744  */
 745 static netif *enumInterfaces(JNIEnv *env) {
 746     netif *ifs;
 747     int sock;
 748 
 749     /*
 750      * Enumerate IPv4 addresses
 751      */
 752 
 753     sock = openSocket(env, AF_INET);
 754     if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 755         return NULL;
 756     }
 757 
 758     ifs = enumIPv4Interfaces(env, sock, NULL);
 759     close(sock);
 760 
 761     if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
 762         return NULL;
 763     }
 764 
 765     /* return partial list if an exception occurs in the middle of process ???*/
 766 
 767     /*
 768      * If IPv6 is available then enumerate IPv6 addresses.
 769      */
 770 #ifdef AF_INET6
 771 
 772         /* User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
 773          * so we have to call ipv6_available()
 774          */
 775         if (ipv6_available()) {
 776 
 777            sock =  openSocket(env, AF_INET6);
 778            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
 779                freeif(ifs);
 780                return NULL;
 781            }
 782 
 783            ifs = enumIPv6Interfaces(env, sock, ifs);
 784            close(sock);
 785 
 786            if ((*env)->ExceptionOccurred(env)) {
 787               freeif(ifs);
 788               return NULL;
 789            }
 790 
 791        }
 792 #endif
 793 
 794     return ifs;
 795 }
 796 
 797 #define CHECKED_MALLOC3(_pointer,_type,_size) \
 798        do{ \
 799         _pointer = (_type)malloc( _size ); \
 800         if (_pointer == NULL) { \
 801             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
 802             return ifs; /* return untouched list */ \
 803         } \
 804        } while(0)
 805 
 806 
 807 /*
 808  * Free an interface list (including any attached addresses)
 809  */
 810 void freeif(netif *ifs) {
 811     netif *currif = ifs;
 812     netif *child = NULL;
 813 
 814     while (currif != NULL) {
 815         netaddr *addrP = currif->addr;
 816         while (addrP != NULL) {
 817             netaddr *next = addrP->next;
 818             free(addrP);
 819             addrP = next;
 820          }
 821 
 822             /*
 823             * Don't forget to free the sub-interfaces.
 824             */
 825           if (currif->childs != NULL) {
 826                 freeif(currif->childs);
 827           }
 828 
 829           ifs = currif->next;
 830           free(currif);
 831           currif = ifs;
 832     }
 833 }
 834 
 835 netif *addif(JNIEnv *env, int sock, const char * if_name,
 836              netif *ifs, struct sockaddr* ifr_addrP, int family,
 837              short prefix)
 838 {
 839     netif *currif = ifs, *parent;
 840     netaddr *addrP;
 841 
 842 #ifdef LIFNAMSIZ
 843     int ifnam_size = LIFNAMSIZ;
 844     char name[LIFNAMSIZ], vname[LIFNAMSIZ];
 845 #else
 846     int ifnam_size = IFNAMSIZ;
 847     char name[IFNAMSIZ], vname[IFNAMSIZ];
 848 #endif
 849 
 850     char  *name_colonP;
 851     int mask;
 852     int isVirtual = 0;
 853     int addr_size;
 854     int flags = 0;
 855 
 856     /*
 857      * If the interface name is a logical interface then we
 858      * remove the unit number so that we have the physical
 859      * interface (eg: hme0:1 -> hme0). NetworkInterface
 860      * currently doesn't have any concept of physical vs.
 861      * logical interfaces.
 862      */
 863     strncpy(name, if_name, ifnam_size);
 864     name[ifnam_size - 1] = '\0';
 865     *vname = 0;
 866 
 867     /*
 868      * Create and populate the netaddr node. If allocation fails
 869      * return an un-updated list.
 870      */
 871     /*Allocate for addr and brdcast at once*/
 872 
 873 #ifdef AF_INET6
 874     addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
 875 #else
 876     addr_size = sizeof(struct sockaddr_in);
 877 #endif
 878 
 879     CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
 880     addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
 881     memcpy(addrP->addr, ifr_addrP, addr_size);
 882 
 883     addrP->family = family;
 884     addrP->brdcast = NULL;
 885     addrP->mask = prefix;
 886     addrP->next = 0;
 887     if (family == AF_INET) {
 888        // Deal with broadcast addr & subnet mask
 889        struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
 890        addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
 891 
 892        if ((mask = getSubnet(env, sock, name)) != -1)
 893            addrP->mask = mask;
 894      }
 895 
 896     /**
 897      * Deal with virtual interface with colon notation e.g. eth0:1
 898      */
 899     name_colonP = strchr(name, ':');
 900     if (name_colonP != NULL) {
 901       /**
 902        * This is a virtual interface. If we are able to access the parent
 903        * we need to create a new entry if it doesn't exist yet *and* update
 904        * the 'parent' interface with the new records.
 905        */
 906         *name_colonP = 0;
 907         if (getFlags(sock, name, &flags) < 0 || flags < 0) {
 908             // failed to access parent interface do not create parent.
 909             // We are a virtual interface with no parent.
 910             isVirtual = 1;
 911             *name_colonP = ':';
 912         }
 913         else{
 914            // Got access to parent, so create it if necessary.
 915            // Save original name to vname and truncate name by ':'
 916             memcpy(vname, name, sizeof(vname) );
 917             vname[name_colonP - name] = ':';
 918         }
 919     }
 920 
 921     /*
 922      * Check if this is a "new" interface. Use the interface
 923      * name for matching because index isn't supported on
 924      * Solaris 2.6 & 7.
 925      */
 926     while (currif != NULL) {
 927         if (strcmp(name, currif->name) == 0) {
 928             break;
 929         }
 930         currif = currif->next;
 931     }
 932 
 933     /*
 934      * If "new" then create an netif structure and
 935      * insert it onto the list.
 936      */
 937     if (currif == NULL) {
 938          CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
 939          currif->name = (char *) currif+sizeof(netif);
 940          strncpy(currif->name, name, ifnam_size);
 941          currif->name[ifnam_size - 1] = '\0';
 942          currif->index = getIndex(sock, name);
 943          currif->addr = NULL;
 944          currif->childs = NULL;
 945          currif->virtual = isVirtual;
 946          currif->next = ifs;
 947          ifs = currif;
 948     }
 949 
 950     /*
 951      * Finally insert the address on the interface
 952      */
 953     addrP->next = currif->addr;
 954     currif->addr = addrP;
 955 
 956     parent = currif;
 957 
 958     /**
 959      * Let's deal with the virtual interface now.
 960      */
 961     if (vname[0]) {
 962         netaddr *tmpaddr;
 963 
 964         currif = parent->childs;
 965 
 966         while (currif != NULL) {
 967             if (strcmp(vname, currif->name) == 0) {
 968                 break;
 969             }
 970             currif = currif->next;
 971         }
 972 
 973         if (currif == NULL) {
 974             CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
 975             currif->name = (char *) currif + sizeof(netif);
 976             strncpy(currif->name, vname, ifnam_size);
 977             currif->name[ifnam_size - 1] = '\0';
 978             currif->index = getIndex(sock, vname);
 979             currif->addr = NULL;
 980            /* Need to duplicate the addr entry? */
 981             currif->virtual = 1;
 982             currif->childs = NULL;
 983             currif->next = parent->childs;
 984             parent->childs = currif;
 985         }
 986 
 987         CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
 988         memcpy(tmpaddr, addrP, sizeof(netaddr));
 989         if (addrP->addr != NULL) {
 990             tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
 991             memcpy(tmpaddr->addr, addrP->addr, addr_size);
 992         }
 993 
 994         if (addrP->brdcast != NULL) {
 995             tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
 996             memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
 997         }
 998 
 999         tmpaddr->next = currif->addr;
1000         currif->addr = tmpaddr;
1001     }
1002 
1003     return ifs;
1004 }
1005 
1006 /* Open socket for further ioct calls
1007  * proto is AF_INET/AF_INET6
1008  */
1009 static int  openSocket(JNIEnv *env, int proto){
1010     int sock;
1011 
1012     if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
1013         /*
1014          * If EPROTONOSUPPORT is returned it means we don't have
1015          * support  for this proto so don't throw an exception.
1016          */
1017         if (errno != EPROTONOSUPPORT) {
1018             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
1019         }
1020         return -1;
1021     }
1022 
1023     return sock;
1024 }
1025 
1026 
1027 /** Linux **/
1028 #ifdef __linux__
1029 /* Open socket for further ioct calls, try v4 socket first and
1030  * if it falls return v6 socket
1031  */
1032 
1033 #ifdef AF_INET6
1034 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1035     int sock;
1036     struct ifreq if2;
1037 
1038      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1039          if (errno == EPROTONOSUPPORT){
1040               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1041                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1042                  return -1;
1043               }
1044          }
1045          else{ // errno is not NOSUPPORT
1046              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1047              return -1;
1048          }
1049    }
1050 
1051      /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
1052         of address of an interface */
1053 
1054        return sock;
1055 }
1056 
1057 #else
1058 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1059     return openSocket(env,AF_INET);
1060 }
1061 #endif
1062 
1063 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1064     struct ifconf ifc;
1065     struct ifreq *ifreqP;
1066     char *buf;
1067     int numifs;
1068     unsigned i;
1069 
1070 
1071     /* need to do a dummy SIOCGIFCONF to determine the buffer size.
1072      * SIOCGIFCOUNT doesn't work
1073      */
1074     ifc.ifc_buf = NULL;
1075     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1076         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1077         return ifs;
1078     }
1079 
1080     CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
1081 
1082     ifc.ifc_buf = buf;
1083     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1084         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
1085         (void) free(buf);
1086         return ifs;
1087     }
1088 
1089     /*
1090      * Iterate through each interface
1091      */
1092     ifreqP = ifc.ifc_req;
1093     for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
1094         /*
1095          * Add to the list
1096          */
1097         ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
1098 
1099         /*
1100          * If an exception occurred then free the list
1101          */
1102         if ((*env)->ExceptionOccurred(env)) {
1103             free(buf);
1104             freeif(ifs);
1105             return NULL;
1106         }
1107     }
1108 
1109     /*
1110      * Free socket and buffer
1111      */
1112     free(buf);
1113     return ifs;
1114 }
1115 
1116 
1117 /*
1118  * Enumerates and returns all IPv6 interfaces on Linux
1119  */
1120 
1121 #ifdef AF_INET6
1122 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1123     FILE *f;
1124     char addr6[40], devname[21];
1125     char addr6p[8][5];
1126     int plen, scope, dad_status, if_idx;
1127     uint8_t ipv6addr[16];
1128 
1129     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1130         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1131                          addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1132                          &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
1133 
1134             struct netif *ifs_ptr = NULL;
1135             struct netif *last_ptr = NULL;
1136             struct sockaddr_in6 addr;
1137 
1138             sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1139                            addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1140             inet_pton(AF_INET6, addr6, ipv6addr);
1141 
1142             memset(&addr, 0, sizeof(struct sockaddr_in6));
1143             memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
1144 
1145             addr.sin6_scope_id = if_idx;
1146 
1147             ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
1148 
1149 
1150             /*
1151              * If an exception occurred then return the list as is.
1152              */
1153             if ((*env)->ExceptionOccurred(env)) {
1154                 fclose(f);
1155                 return ifs;
1156             }
1157        }
1158        fclose(f);
1159     }
1160     return ifs;
1161 }
1162 #endif
1163 
1164 
1165 static int getIndex(int sock, const char *name){
1166      /*
1167       * Try to get the interface index
1168       * (Not supported on Solaris 2.6 or 7)
1169       */
1170     struct ifreq if2;
1171     strcpy(if2.ifr_name, name);
1172 
1173     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1174         return -1;
1175     }
1176 
1177     return if2.ifr_ifindex;
1178 }
1179 
1180 /**
1181  * Returns the IPv4 broadcast address of a named interface, if it exists.
1182  * Returns 0 if it doesn't have one.
1183  */
1184 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1185   struct sockaddr *ret = NULL;
1186   struct ifreq if2;
1187 
1188   memset((char *) &if2, 0, sizeof(if2));
1189   strcpy(if2.ifr_name, ifname);
1190 
1191   /* Let's make sure the interface does have a broadcast address */
1192   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
1193       NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
1194       return ret;
1195   }
1196 
1197   if (if2.ifr_flags & IFF_BROADCAST) {
1198       /* It does, let's retrieve it*/
1199       if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1200           NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
1201           return ret;
1202       }
1203 
1204       ret = brdcast_store;
1205       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1206   }
1207 
1208   return ret;
1209 }
1210 
1211 /**
1212  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1213  * interface, if it has one, otherwise return -1.
1214  */
1215 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1216     unsigned int mask;
1217     short ret;
1218     struct ifreq if2;
1219 
1220     memset((char *) &if2, 0, sizeof(if2));
1221     strcpy(if2.ifr_name, ifname);
1222 
1223     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1224         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1225         return -1;
1226     }
1227 
1228     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1229     ret = 0;
1230     while (mask) {
1231        mask <<= 1;
1232        ret++;
1233     }
1234 
1235     return ret;
1236 }
1237 
1238 /**
1239  * Get the Hardware address (usually MAC address) for the named interface.
1240  * return puts the data in buf, and returns the length, in byte, of the
1241  * MAC address. Returns -1 if there is no hardware address on that interface.
1242  */
1243 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1244     static struct ifreq ifr;
1245     int i;
1246 
1247     strcpy(ifr.ifr_name, ifname);
1248     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1249         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
1250         return -1;
1251     }
1252 
1253     memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1254 
1255    /*
1256     * All bytes to 0 means no hardware address.
1257     */
1258 
1259     for (i = 0; i < IFHWADDRLEN; i++) {
1260         if (buf[i] != 0)
1261             return IFHWADDRLEN;
1262     }
1263 
1264     return -1;
1265 }
1266 
1267 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1268     struct ifreq if2;
1269 
1270     memset((char *) &if2, 0, sizeof(if2));
1271     strcpy(if2.ifr_name, ifname);
1272 
1273     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1274         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1275         return -1;
1276     }
1277 
1278     return  if2.ifr_mtu;
1279 }
1280 
1281 static int getFlags(int sock, const char *ifname, int *flags) {
1282   struct ifreq if2;
1283 
1284   memset((char *) &if2, 0, sizeof(if2));
1285   strcpy(if2.ifr_name, ifname);
1286 
1287   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
1288       return -1;
1289   }
1290 
1291   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1292       *flags = (if2.ifr_flags & 0xffff);
1293   } else {
1294       *flags = if2.ifr_flags;
1295   }
1296   return 0;
1297 }
1298 
1299 #endif
1300 
1301 /** Solaris **/
1302 #ifdef __solaris__
1303 /* Open socket for further ioct calls, try v4 socket first and
1304  * if it falls return v6 socket
1305  */
1306 
1307 #ifdef AF_INET6
1308 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1309     int sock, alreadyV6 = 0;
1310     struct lifreq if2;
1311 
1312      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1313          if (errno == EPROTONOSUPPORT){
1314               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1315                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1316                  return -1;
1317               }
1318 
1319               alreadyV6=1;
1320          }
1321          else{ // errno is not NOSUPPORT
1322              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1323              return -1;
1324          }
1325    }
1326 
1327      /**
1328       * Solaris requires that we have an IPv6 socket to query an
1329       * interface without an IPv4 address - check it here.
1330       * POSIX 1 require the kernel to return ENOTTY if the call is
1331       * inappropriate for a device e.g. the NETMASK for a device having IPv6
1332       * only address but not all devices follow the standard so
1333       * fall back on any error. It's not an ecologically friendly gesture
1334       * but more reliable.
1335       */
1336 
1337     if (! alreadyV6 ){
1338         memset((char *) &if2, 0, sizeof(if2));
1339         strcpy(if2.lifr_name, ifname);
1340         if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1341                 close(sock);
1342                 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1343                       NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1344                       return -1;
1345                 }
1346         }
1347     }
1348 
1349     return sock;
1350 }
1351 
1352 #else
1353 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1354     return openSocket(env,AF_INET);
1355 }
1356 #endif
1357 
1358 /*
1359  * Enumerates and returns all IPv4 interfaces
1360  * (linux verision)
1361  */
1362 
1363 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1364      return enumIPvXInterfaces(env,sock, ifs, AF_INET);
1365 }
1366 
1367 #ifdef AF_INET6
1368 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1369     return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
1370 }
1371 #endif
1372 
1373 /*
1374    Enumerates and returns all interfaces on Solaris
1375    use the same code for IPv4 and IPv6
1376  */
1377 static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
1378     struct lifconf ifc;
1379     struct lifreq *ifr;
1380     int n;
1381     char *buf;
1382     struct lifnum numifs;
1383     unsigned bufsize;
1384 
1385     /*
1386      * Get the interface count
1387      */
1388     numifs.lifn_family = family;
1389     numifs.lifn_flags = 0;
1390     if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
1391         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
1392         return ifs;
1393     }
1394 
1395     /*
1396      *  Enumerate the interface configurations
1397      */
1398     bufsize = numifs.lifn_count * sizeof (struct lifreq);
1399     CHECKED_MALLOC3(buf, char *, bufsize);
1400 
1401     ifc.lifc_family = family;
1402     ifc.lifc_flags = 0;
1403     ifc.lifc_len = bufsize;
1404     ifc.lifc_buf = buf;
1405     if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
1406         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
1407         free(buf);
1408         return ifs;
1409     }
1410 
1411     /*
1412      * Iterate through each interface
1413      */
1414     ifr = ifc.lifc_req;
1415     for (n=0; n<numifs.lifn_count; n++, ifr++) {
1416         int index = -1;
1417         struct lifreq if2;
1418 
1419         /*
1420         * Ignore either IPv4 or IPv6 addresses
1421         */
1422         if (ifr->lifr_addr.ss_family != family) {
1423             continue;
1424         }
1425 
1426 #ifdef AF_INET6
1427         if (ifr->lifr_addr.ss_family == AF_INET6) {
1428             struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
1429             s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
1430         }
1431 #endif
1432 
1433         /* add to the list */
1434         ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
1435 
1436         /*
1437         * If an exception occurred we return immediately
1438         */
1439         if ((*env)->ExceptionOccurred(env)) {
1440             free(buf);
1441             return ifs;
1442         }
1443 
1444    }
1445 
1446     free(buf);
1447     return ifs;
1448 }
1449 
1450 static int getIndex(int sock, const char *name){
1451    /*
1452     * Try to get the interface index
1453     * (Not supported on Solaris 2.6 or 7)
1454     */
1455     struct lifreq if2;
1456     strcpy(if2.lifr_name, name);
1457 
1458     if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
1459         return -1;
1460     }
1461 
1462     return if2.lifr_index;
1463 }
1464 
1465 /**
1466  * Returns the IPv4 broadcast address of a named interface, if it exists.
1467  * Returns 0 if it doesn't have one.
1468  */
1469 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1470     struct sockaddr *ret = NULL;
1471     struct lifreq if2;
1472 
1473     memset((char *) &if2, 0, sizeof(if2));
1474     strcpy(if2.lifr_name, ifname);
1475 
1476     /* Let's make sure the interface does have a broadcast address */
1477     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
1478         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
1479         return ret;
1480     }
1481 
1482     if (if2.lifr_flags & IFF_BROADCAST) {
1483         /* It does, let's retrieve it*/
1484         if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
1485             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
1486             return ret;
1487         }
1488 
1489         ret = brdcast_store;
1490         memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
1491     }
1492 
1493     return ret;
1494 }
1495 
1496 /**
1497  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1498  * interface, if it has one, otherwise return -1.
1499  */
1500 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1501     unsigned int mask;
1502     short ret;
1503     struct lifreq if2;
1504 
1505     memset((char *) &if2, 0, sizeof(if2));
1506     strcpy(if2.lifr_name, ifname);
1507 
1508     if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
1509         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
1510         return -1;
1511     }
1512 
1513     mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
1514     ret = 0;
1515 
1516     while (mask) {
1517        mask <<= 1;
1518        ret++;
1519     }
1520 
1521     return ret;
1522 }
1523 
1524 
1525 
1526 #define DEV_PREFIX  "/dev/"
1527 
1528 /**
1529  * Solaris specific DLPI code to get hardware address from a device.
1530  * Unfortunately, at least up to Solaris X, you have to have special
1531  * privileges (i.e. be root).
1532  */
1533 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
1534     char style1dev[MAXPATHLEN];
1535     int fd;
1536     dl_phys_addr_req_t dlpareq;
1537     dl_phys_addr_ack_t *dlpaack;
1538     struct strbuf msg;
1539     char buf[128];
1540     int flags = 0;
1541 
1542    /**
1543     * Device is in /dev
1544     * e.g.: /dev/bge0
1545     */
1546     strcpy(style1dev, DEV_PREFIX);
1547     strcat(style1dev, ifname);
1548     if ((fd = open(style1dev, O_RDWR)) < 0) {
1549         /*
1550          * Can't open it. We probably are missing the privilege.
1551          * We'll have to try something else
1552          */
1553          return 0;
1554     }
1555 
1556     dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1557     dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1558 
1559     msg.buf = (char *)&dlpareq;
1560     msg.len = DL_PHYS_ADDR_REQ_SIZE;
1561 
1562     if (putmsg(fd, &msg, NULL, 0) < 0) {
1563         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
1564         return -1;
1565     }
1566 
1567     dlpaack = (dl_phys_addr_ack_t *)buf;
1568 
1569     msg.buf = (char *)buf;
1570     msg.len = 0;
1571     msg.maxlen = sizeof (buf);
1572     if (getmsg(fd, &msg, NULL, &flags) < 0) {
1573         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
1574         return -1;
1575     }
1576 
1577     if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1578         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
1579         return -1;
1580     }
1581 
1582     memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1583     return dlpaack->dl_addr_length;
1584 }
1585 
1586 /**
1587  * Get the Hardware address (usually MAC address) for the named interface.
1588  * return puts the data in buf, and returns the length, in byte, of the
1589  * MAC address. Returns -1 if there is no hardware address on that interface.
1590  */
1591 static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
1592     struct arpreq arpreq;
1593     struct sockaddr_in* sin;
1594     struct sockaddr_in ipAddr;
1595     int len, i;
1596     struct lifreq lif;
1597 
1598     /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
1599      * try the old way.
1600      */
1601     memset(&lif, 0, sizeof(lif));
1602     strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
1603 
1604     if (ioctl(sock, SIOCGLIFHWADDR, &lif) != -1) {
1605         struct sockaddr_dl *sp;
1606         sp = (struct sockaddr_dl *)&lif.lifr_addr;
1607         memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
1608         return sp->sdl_alen;
1609     }
1610 
1611    /**
1612     * On Solaris we have to use DLPI, but it will only work if we have
1613     * privileged access (i.e. root). If that fails, we try a lookup
1614     * in the ARP table, which requires an IPv4 address.
1615     */
1616     if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
1617         /*DLPI failed - trying to do arp lookup*/
1618 
1619         if (addr == NULL) {
1620             /**
1621              * No IPv4 address for that interface, so can't do an ARP lookup.
1622              */
1623              return -1;
1624          }
1625 
1626          len = 6; //???
1627 
1628          sin = (struct sockaddr_in *) &arpreq.arp_pa;
1629          memset((char *) &arpreq, 0, sizeof(struct arpreq));
1630          ipAddr.sin_port = 0;
1631          ipAddr.sin_family = AF_INET;
1632          memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
1633          memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
1634          arpreq.arp_flags= ATF_PUBL;
1635 
1636          if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
1637              return -1;
1638          }
1639 
1640          memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
1641     }
1642 
1643     /*
1644      * All bytes to 0 means no hardware address.
1645      */
1646 
1647     for (i = 0; i < len; i++) {
1648       if (buf[i] != 0)
1649          return len;
1650     }
1651 
1652     return -1;
1653 }
1654 
1655 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1656     struct lifreq if2;
1657 
1658     memset((char *) &if2, 0, sizeof(if2));
1659     strcpy(if2.lifr_name, ifname);
1660 
1661     if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
1662         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
1663         return -1;
1664     }
1665 
1666     return  if2.lifr_mtu;
1667 }
1668 
1669 
1670 static int getFlags(int sock, const char *ifname, int *flags) {
1671      struct   lifreq lifr;
1672      memset((caddr_t)&lifr, 0, sizeof(lifr));
1673      strcpy((caddr_t)&(lifr.lifr_name), ifname);
1674 
1675      if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1676          return -1;
1677      }
1678 
1679      *flags = lifr.lifr_flags;
1680      return 0;
1681 }
1682 
1683 
1684 #endif
1685 
1686 
1687 /** BSD **/
1688 #ifdef _ALLBSD_SOURCE
1689 /* Open socket for further ioct calls, try v4 socket first and
1690  * if it falls return v6 socket
1691  */
1692 
1693 #ifdef AF_INET6
1694 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1695     int sock;
1696     struct ifreq if2;
1697 
1698      if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1699          if (errno == EPROTONOSUPPORT){
1700               if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
1701                  NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1702                  return -1;
1703               }
1704          }
1705          else{ // errno is not NOSUPPORT
1706              NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1707              return -1;
1708          }
1709    }
1710 
1711    return sock;
1712 }
1713 
1714 #else
1715 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
1716     return openSocket(env,AF_INET);
1717 }
1718 #endif
1719 
1720 /*
1721  * Enumerates and returns all IPv4 interfaces
1722  */
1723 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1724     struct ifaddrs *ifa, *origifa;
1725 
1726     if (getifaddrs(&origifa) != 0) {
1727         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1728                          "getifaddrs() function failed");
1729         return ifs;
1730     }
1731 
1732     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1733 
1734         /*
1735          * Skip non-AF_INET entries.
1736          */
1737         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
1738             continue;
1739 
1740         /*
1741          * Add to the list.
1742          */
1743         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
1744 
1745         /*
1746          * If an exception occurred then free the list.
1747          */
1748         if ((*env)->ExceptionOccurred(env)) {
1749             freeifaddrs(origifa);
1750             freeif(ifs);
1751             return NULL;
1752         }
1753     }
1754 
1755     /*
1756      * Free socket and buffer
1757      */
1758     freeifaddrs(origifa);
1759     return ifs;
1760 }
1761 
1762 
1763 /*
1764  * Enumerates and returns all IPv6 interfaces on Linux
1765  */
1766 
1767 #ifdef AF_INET6
1768 /*
1769  * Determines the prefix on BSD for IPv6 interfaces.
1770  */
1771 static
1772 int prefix(void *val, int size) {
1773     u_char *name = (u_char *)val;
1774     int byte, bit, plen = 0;
1775 
1776     for (byte = 0; byte < size; byte++, plen += 8)
1777         if (name[byte] != 0xff)
1778             break;
1779     if (byte == size)
1780         return (plen);
1781     for (bit = 7; bit != 0; bit--, plen++)
1782         if (!(name[byte] & (1 << bit)))
1783             break;
1784     for (; bit != 0; bit--)
1785         if (name[byte] & (1 << bit))
1786             return (0);
1787     byte++;
1788     for (; byte < size; byte++)
1789         if (name[byte])
1790             return (0);
1791     return (plen);
1792 }
1793 
1794 /*
1795  * Enumerates and returns all IPv6 interfaces on BSD
1796  */
1797 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1798     struct ifaddrs *ifa, *origifa;
1799     struct sockaddr_in6 *sin6;
1800     struct in6_ifreq ifr6;
1801 
1802     if (getifaddrs(&origifa) != 0) {
1803         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1804                          "getifaddrs() function failed");
1805         return ifs;
1806     }
1807 
1808     for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1809 
1810         /*
1811          * Skip non-AF_INET6 entries.
1812          */
1813         if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
1814             continue;
1815 
1816         memset(&ifr6, 0, sizeof(ifr6));
1817         strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
1818         memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
1819 
1820         if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
1821             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
1822                              "ioctl SIOCGIFNETMASK_IN6 failed");
1823             freeifaddrs(origifa);
1824             freeif(ifs);
1825             return NULL;
1826         }
1827 
1828         /* Add to the list.  */
1829         sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
1830         ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
1831                     prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
1832 
1833         /* If an exception occurred then free the list.  */
1834         if ((*env)->ExceptionOccurred(env)) {
1835             freeifaddrs(origifa);
1836             freeif(ifs);
1837             return NULL;
1838         }
1839     }
1840 
1841     /*
1842      * Free socket and ifaddrs buffer
1843      */
1844     freeifaddrs(origifa);
1845     return ifs;
1846 }
1847 #endif
1848 
1849 static int getIndex(int sock, const char *name){
1850 #ifdef __FreeBSD__
1851      /*
1852       * Try to get the interface index
1853       * (Not supported on Solaris 2.6 or 7)
1854       */
1855     struct ifreq if2;
1856     strcpy(if2.ifr_name, name);
1857 
1858     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1859         return -1;
1860     }
1861 
1862     return if2.ifr_index;
1863 #else
1864     /*
1865      * Try to get the interface index using BSD specific if_nametoindex
1866      */
1867     int index = if_nametoindex(name);
1868     return (index == 0) ? -1 : index;
1869 #endif
1870 }
1871 
1872 /**
1873  * Returns the IPv4 broadcast address of a named interface, if it exists.
1874  * Returns 0 if it doesn't have one.
1875  */
1876 static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
1877   struct sockaddr *ret = NULL;
1878   struct ifreq if2;
1879 
1880   memset((char *) &if2, 0, sizeof(if2));
1881   strcpy(if2.ifr_name, ifname);
1882 
1883   /* Let's make sure the interface does have a broadcast address */
1884   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1885       NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
1886       return ret;
1887   }
1888 
1889   if (if2.ifr_flags & IFF_BROADCAST) {
1890       /* It does, let's retrieve it*/
1891       if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
1892           NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
1893           return ret;
1894       }
1895 
1896       ret = brdcast_store;
1897       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1898   }
1899 
1900   return ret;
1901 }
1902 
1903 /**
1904  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1905  * interface, if it has one, otherwise return -1.
1906  */
1907 static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
1908     unsigned int mask;
1909     short ret;
1910     struct ifreq if2;
1911 
1912     memset((char *) &if2, 0, sizeof(if2));
1913     strcpy(if2.ifr_name, ifname);
1914 
1915     if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
1916         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
1917         return -1;
1918     }
1919 
1920     mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1921     ret = 0;
1922     while (mask) {
1923        mask <<= 1;
1924        ret++;
1925     }
1926 
1927     return ret;
1928 }
1929 
1930 /**
1931  * Get the Hardware address (usually MAC address) for the named interface.
1932  * return puts the data in buf, and returns the length, in byte, of the
1933  * MAC address. Returns -1 if there is no hardware address on that interface.
1934  */
1935 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
1936     struct ifaddrs *ifa0, *ifa;
1937     struct sockaddr *saddr;
1938     int i;
1939 
1940     /* Grab the interface list */
1941     if (!getifaddrs(&ifa0)) {
1942         /* Cycle through the interfaces */
1943         for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
1944             saddr = ifa->ifa_addr;
1945             /* Link layer contains the MAC address */
1946             if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
1947                 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
1948                 /* Check the address is the correct length */
1949                 if (sadl->sdl_alen == ETHER_ADDR_LEN) {
1950                     memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
1951                     freeifaddrs(ifa0);
1952                     return ETHER_ADDR_LEN;
1953                 }
1954             }
1955         }
1956         freeifaddrs(ifa0);
1957     }
1958 
1959     return -1;
1960 }
1961 
1962 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
1963     struct ifreq if2;
1964 
1965     memset((char *) &if2, 0, sizeof(if2));
1966     strcpy(if2.ifr_name, ifname);
1967 
1968     if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1969         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
1970         return -1;
1971     }
1972 
1973     return  if2.ifr_mtu;
1974 }
1975 
1976 static int getFlags(int sock, const char *ifname, int *flags) {
1977   struct ifreq if2;
1978   int ret = -1;
1979 
1980   memset((char *) &if2, 0, sizeof(if2));
1981   strcpy(if2.ifr_name, ifname);
1982 
1983   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
1984       return -1;
1985   }
1986 
1987   if (sizeof(if2.ifr_flags) == sizeof(short)) {
1988     *flags = (if2.ifr_flags & 0xffff);
1989   } else {
1990     *flags = if2.ifr_flags;
1991   }
1992   return 0;
1993 }
1994 
1995 #endif