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