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