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     ni_class = (*env)->NewGlobalRef(env, ni_class);

 174     ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");

 175     ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");

 176     ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");

 177     ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");

 178     ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");

 179     ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");

 180     ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");

 181     ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");

 182     ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");

 183 
 184     ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");

 185     ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);

 186     ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");

 187     ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);

 188     ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");

 189     ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);

 190     ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");

 191     ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);

 192     ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");

 193     ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");

 194     ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");

 195     ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");

 196     ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");

 197     ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");

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