1 /*
   2  * Copyright (c) 2003, 2010, 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 <stdlib.h>
  27 #include <windows.h>
  28 #include <winsock2.h>           /* needed for htonl */
  29 #include <iprtrmib.h>
  30 #include <assert.h>
  31 
  32 #include "java_net_NetworkInterface.h"
  33 #include "jni_util.h"
  34 
  35 #include "NetworkInterface.h"
  36 
  37 /*
  38  * Windows implementation of the java.net.NetworkInterface native methods.
  39  * This module provides the implementations of getAll, getByName, getByIndex,
  40  * and getByAddress.
  41  */
  42 
  43 extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
  44 int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
  45 
  46 /* IP helper library routines */
  47 int (PASCAL FAR *GetIpAddrTable_fn)();
  48 int (PASCAL FAR *GetIfTable_fn)();
  49 int (PASCAL FAR *GetFriendlyIfIndex_fn)();
  50 int (PASCAL FAR *GetAdaptersAddresses_fn)();
  51 int (PASCAL FAR *GetAdaptersInfo_fn)();
  52 int (PASCAL FAR *GetNumberOfInterfaces_fn)();
  53 
  54 #ifdef DEBUG
  55 void printnif (netif *nif) {
  56 #ifdef _WIN64
  57         printf ("nif:0x%I64x name:%s\n", nif,nif->name);
  58 #else
  59         printf ("nif:0x%x name:%s\n", nif,nif->name);
  60 #endif
  61         if (nif->dNameIsUnicode) {
  62             printf ("dName:%S index:%d ", nif->displayName,nif->index);
  63         } else {
  64             printf ("dName:%s index:%d ", nif->displayName,nif->index);
  65         }
  66         printf ("naddrs:%d\n", nif->naddrs);
  67 }
  68 
  69 void printnifs (netif *netifPP, char *str) {
  70     netif *nif;
  71     printf ("%s\n", str);
  72     for (nif=netifPP; nif!=NULL; nif=nif->next) {
  73         printnif (nif);
  74     }
  75     printf("-----------------\n");
  76 }
  77 
  78 #endif
  79 
  80 static int bufsize = 1024;
  81 
  82 /*
  83  * return an array of IP_ADAPTER_ADDRESSES containing one element
  84  * for each apdapter on the system. Returned in *adapters.
  85  * Buffer is malloc'd and must be freed (unless error returned)
  86  */
  87 static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) {
  88     DWORD ret, flags;
  89     IP_ADAPTER_ADDRESSES *adapterInfo;
  90     ULONG len;
  91     adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
  92     if (adapterInfo == 0) {
  93         return -1;
  94     }
  95     len = bufsize;
  96     flags = GAA_FLAG_SKIP_DNS_SERVER;
  97     flags |= GAA_FLAG_SKIP_MULTICAST;
  98     flags |= GAA_FLAG_INCLUDE_PREFIX;
  99     ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
 100     if (ret == ERROR_BUFFER_OVERFLOW) {
 101         adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
 102         if (adapterInfo == 0) {
 103             return -1;
 104         }
 105         bufsize = len;
 106         ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
 107     }
 108     if (ret != ERROR_SUCCESS) {
 109         free (adapterInfo);
 110         JNU_ThrowByName(env, "java/lang/Error",
 111                 "IP Helper Library GetAdaptersAddresses function failed");
 112         return -1;
 113     }
 114     *adapters = adapterInfo;
 115     return ERROR_SUCCESS;
 116 }
 117 
 118 /*
 119  * return an array of IP_ADAPTER_ADDRESSES containing one element
 120  * for each apdapter on the system. Returned in *adapters.
 121  * Buffer is malloc'd and must be freed (unless error returned)
 122  */
 123 IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env,  jint index) {
 124     DWORD flags, val;
 125     IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret;
 126     ULONG len;
 127     adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
 128     if (adapterInfo == 0) {
 129         JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
 130         return NULL;
 131     }
 132     len = bufsize;
 133     flags = GAA_FLAG_SKIP_DNS_SERVER;
 134     flags |= GAA_FLAG_SKIP_MULTICAST;
 135     flags |= GAA_FLAG_INCLUDE_PREFIX;
 136     val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
 137     if (val == ERROR_BUFFER_OVERFLOW) {
 138         adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
 139         if (adapterInfo == 0) {
 140             JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
 141             return NULL;
 142         }
 143         bufsize = len;
 144         val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
 145     }
 146     if (val != ERROR_SUCCESS) {
 147         free (adapterInfo);
 148         JNU_ThrowByName(env, "java/lang/Error",
 149                 "IP Helper Library GetAdaptersAddresses function failed");
 150         return NULL;
 151     }
 152     ptr = adapterInfo;
 153     ret = NULL;
 154     while (ptr != NULL) {
 155       // IPv4 interface
 156       if (ptr->Ipv6IfIndex == index) {
 157         ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES));
 158         memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES));
 159       }
 160       ptr=ptr->Next;
 161     }
 162     free(adapterInfo);
 163     return ret;
 164 }
 165 
 166 static int ipinflen = 2048;
 167 
 168 /*
 169  */
 170 int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
 171 {
 172     DWORD ret;
 173     IP_ADAPTER_ADDRESSES *ptr, *adapters=0;
 174     ULONG len=ipinflen, count=0;
 175     netif *nif=0, *dup_nif, *last=0, *loopif=0, *curr;
 176     int tun=0, net=0;
 177 
 178     *netifPP = 0;
 179 
 180    /*
 181     * Get the IPv4 interfaces. This information is the same
 182     * as what previous JDK versions would return.
 183     */
 184 
 185     ret = enumInterfaces_win (env, netifPP);
 186     if (ret == -1) {
 187         return -1;
 188     } else {
 189         count = ret;
 190     }
 191 
 192     /* locate the loopback (and the last) interface */
 193     for (nif=*netifPP, last=nif; nif!=0; nif=nif->next) {
 194         if (nif->ifType == MIB_IF_TYPE_LOOPBACK) {
 195             loopif = nif;
 196         }
 197         last = nif;
 198     }
 199 
 200     // Retrieve IPv4 addresses with the IP Helper API
 201     curr = *netifPP;
 202     while (curr != NULL) {
 203         netaddr *netaddrP;
 204         ret = enumAddresses_win(env, curr, &netaddrP);
 205         if ((*env)->ExceptionOccurred(env)) {
 206             free_netaddr(netaddrP);
 207             return -1;
 208         }
 209         curr->addrs = netaddrP;
 210         curr->naddrs += ret;
 211         curr = curr->next;
 212     }
 213 
 214     ret = getAdapters (env, &adapters);
 215     if (ret != ERROR_SUCCESS) {
 216         goto err;
 217     }
 218 
 219     /* Now get the IPv6 information. This includes:
 220      *  (a)  IPv6 information associated with interfaces already found
 221      *  (b)  IPv6 information for IPv6 only interfaces (probably tunnels)
 222      *
 223      * For compatibility with previous releases we use the naming
 224      * information gotten from enumInterfaces_win() for (a) entries
 225      * However, the index numbers are taken from the new API.
 226      *
 227      * The procedure is to go through the list of adapters returned
 228      * by the new API looking for entries that correspond to IPv4 interfaces
 229      * already found.
 230      */
 231 
 232     ptr = adapters;
 233     while (ptr != NULL) {
 234         int c;
 235         netif *nif0;
 236         if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) {
 237             c = getAddrsFromAdapter(ptr, &loopif->addrs);
 238             if (c == -1) {
 239                 goto err;
 240             }
 241             loopif->naddrs += c;
 242         } else {
 243             int index = ptr->IfIndex;
 244             if (index != 0) {
 245                 /* This entry is associated with an IPv4 interface */
 246                 for (nif=*netifPP; nif!=0; nif=nif->next) {
 247                     if (nif->index == index) {
 248                         /* found the interface entry
 249                          * set the index to the IPv6 index and add the
 250                          * IPv6 addresses
 251                          */
 252                         nif->index = ptr->Ipv6IfIndex;
 253                         c = getAddrsFromAdapter(ptr, &nif->addrs);
 254                         nif->naddrs += c;
 255                         break;
 256                     }
 257                 }
 258             } else {
 259                 /* This entry is IPv6 only */
 260                 char newname [128];
 261                 int c;
 262 
 263                 /* Windows allocates duplicate adapter entries
 264                  * for tunnel interfaces when there are multiple
 265                  * physical adapters. Need to check
 266                  * if this is a duplicate (ipv6Index is the same)
 267                  */
 268                 dup_nif = 0;
 269                 for (nif0=*netifPP; nif0!=0; nif0=nif0->next) {
 270                     if (nif0->hasIpv6Address &&
 271                                 ptr->Ipv6IfIndex == nif0->ipv6Index) {
 272                         dup_nif = nif0;
 273                         break;
 274                     }
 275                 }
 276                 if (dup_nif == 0) {
 277                     /* new interface */
 278                     nif = (netif *) calloc (1, sizeof(netif));
 279                     if (nif == 0) {
 280                         goto err;
 281                     }
 282                     if (ptr->IfType == IF_TYPE_TUNNEL) {
 283                         sprintf (newname, "tun%d", tun);
 284                         tun ++;
 285                     } else {
 286                         sprintf (newname, "net%d", net);
 287                         net ++;
 288                     }
 289                     nif->name = malloc (strlen(newname)+1);
 290                     nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2);
 291                     if (nif->name == 0 || nif->displayName == 0) {
 292                         goto err;
 293                     }
 294                     strcpy (nif->name, newname);
 295                     wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName);
 296                     nif->dNameIsUnicode = TRUE;
 297                     nif->index = ptr->Ipv6IfIndex;
 298                     nif->ipv6Index = ptr->Ipv6IfIndex;
 299                     nif->hasIpv6Address = TRUE;
 300 
 301                     last->next = nif;
 302                     last = nif;
 303                     count++;
 304                     c = getAddrsFromAdapter(ptr, &nif->addrs);
 305                     if (c == -1) {
 306                         goto err;
 307                     }
 308                     nif->naddrs += c;
 309                 } else {
 310                     /* add the addresses from this adapter to the
 311                      * original (dup_nif)
 312                      */
 313                     c = getAddrsFromAdapter(ptr, &dup_nif->addrs);
 314                     if (c == -1) {
 315                         goto err;
 316                     }
 317                     dup_nif->naddrs += c;
 318                 }
 319             }
 320         }
 321         ptr=ptr->Next;
 322     }
 323 
 324     free (adapters);
 325     return count;
 326 
 327 err:
 328     if (*netifPP) {
 329         free_netif (*netifPP);
 330     }
 331     if (adapters) {
 332         free (adapters);
 333     }
 334     return -1;
 335 }
 336 
 337 /* If *netaddrPP is null, then the addresses are allocated and the beginning
 338  * of the allocated chain is returned in *netaddrPP.
 339  * If *netaddrPP is not null, then the addresses allocated here are appended
 340  * to the existing chain.
 341  *
 342  * Returns count of addresses or -1 on error.
 343  */
 344 
 345 static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) {
 346     LPSOCKADDR                   sock;
 347     int                          count = 0;
 348     netaddr                     *curr, *start=0, *prev=0;
 349     PIP_ADAPTER_UNICAST_ADDRESS uni_addr;
 350     PIP_ADAPTER_ANYCAST_ADDRESS any_addr;
 351     PIP_ADAPTER_PREFIX prefix;
 352 
 353     /* If chain passed in, find end */
 354     if (*netaddrPP != NULL) {
 355         for (start=*netaddrPP; start->next!=NULL; start=start->next) {
 356         }
 357         prev=start;
 358     }
 359 
 360     prefix = ptr->FirstPrefix;
 361     /* Unicast */
 362     uni_addr = ptr->FirstUnicastAddress;
 363     while (uni_addr != NULL) {
 364         /* address is only usable if dad state is preferred or deprecated */
 365         if (uni_addr->DadState == IpDadStateDeprecated ||
 366                 uni_addr->DadState == IpDadStatePreferred) {
 367             sock = uni_addr->Address.lpSockaddr;
 368 
 369             // IPv4 addresses already retrieved with enumAddresses_win
 370             if (sock->sa_family == AF_INET) {
 371                 uni_addr = uni_addr->Next;
 372                 continue;
 373             }
 374 
 375             curr = (netaddr *)calloc (1, sizeof (netaddr));
 376             if (curr == 0) {
 377                 return -1;
 378             }
 379             if (start == NULL) {
 380                 start = curr;
 381             }
 382             if (prev != NULL) {
 383                 prev->next = curr;
 384             }
 385             prev = curr;
 386             SOCKETADDRESS_COPY (&curr->addr, sock);
 387             if (prefix != NULL) {
 388               curr->mask = (short)prefix->PrefixLength;
 389               prefix = prefix->Next;
 390             }
 391             count ++;
 392         }
 393         uni_addr = uni_addr->Next;
 394     }
 395     /* Anycast */
 396     any_addr = ptr->FirstAnycastAddress;
 397     while (any_addr != NULL) {
 398         curr = (netaddr *)calloc (1, sizeof (netaddr));
 399         if (curr == 0) {
 400             return -1;
 401         }
 402         if (start == NULL) {
 403             start = curr;
 404         }
 405         if (prev != NULL) {
 406             prev->next = curr;
 407         }
 408         prev = curr;
 409         sock = any_addr->Address.lpSockaddr;
 410         SOCKETADDRESS_COPY (&curr->addr, sock);
 411         count ++;
 412         any_addr = any_addr->Next;
 413     }
 414     if (*netaddrPP == NULL) {
 415         *netaddrPP = start;
 416     }
 417     return count;
 418 }
 419 
 420 /*
 421  * Create a NetworkInterface object, populate the name and index, and
 422  * populate the InetAddress array based on the IP addresses for this
 423  * interface.
 424  */
 425 static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
 426 {
 427     jobject netifObj;
 428     jobject name, displayName;
 429     jobjectArray addrArr, bindsArr, childArr;
 430     netaddr *addrs;
 431     jint addr_index;
 432     int netaddrCount=ifs->naddrs;
 433     netaddr *netaddrP=ifs->addrs;
 434     jint bind_index;
 435 
 436     /*
 437      * Create a NetworkInterface object and populate it
 438      */
 439     netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
 440     name = (*env)->NewStringUTF(env, ifs->name);
 441     if (ifs->dNameIsUnicode) {
 442         displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, wcslen ((PWCHAR)ifs->displayName));
 443     } else {
 444         displayName = (*env)->NewStringUTF(env, ifs->displayName);
 445     }
 446     if (netifObj == NULL || name == NULL || displayName == NULL) {
 447         return NULL;
 448     }
 449     (*env)->SetObjectField(env, netifObj, ni_nameID, name);
 450     (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);
 451     (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
 452 
 453     /*
 454      * Get the IP addresses for this interface if necessary
 455      * Note that 0 is a valid number of addresses.
 456      */
 457     if (netaddrCount < 0) {
 458         netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
 459         if ((*env)->ExceptionOccurred(env)) {
 460             free_netaddr(netaddrP);
 461             return NULL;
 462         }
 463     }
 464 
 465     addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL);
 466     if (addrArr == NULL) {
 467         return NULL;
 468     }
 469 
 470     bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);
 471     if (bindsArr == NULL) {
 472       free_netaddr(netaddrP);
 473       return NULL;
 474     }
 475 
 476     addrs = netaddrP;
 477     addr_index = 0;
 478     bind_index = 0;
 479     while (addrs != NULL) {
 480         jobject iaObj, ia2Obj;
 481         jobject ibObj = NULL;
 482         if (addrs->addr.him.sa_family == AF_INET) {
 483             iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
 484             if (iaObj == NULL) {
 485                 return NULL;
 486             }
 487             /* default ctor will set family to AF_INET */
 488 
 489             (*env)->SetIntField(env, iaObj, ni_iaAddr, ntohl(addrs->addr.him4.sin_addr.s_addr));
 490 
 491             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 492             if (ibObj == NULL) {
 493               free_netaddr(netaddrP);
 494               return NULL;
 495             }
 496             (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 497             ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
 498             if (ia2Obj == NULL) {
 499               free_netaddr(netaddrP);
 500               return NULL;
 501             }
 502             (*env)->SetIntField(env, ia2Obj, ni_iaAddr,
 503                                 ntohl(addrs->brdcast.him4.sin_addr.s_addr));
 504             (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
 505             (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
 506             (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
 507         } else /* AF_INET6 */ {
 508             int scope;
 509             iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
 510             if (iaObj) {
 511                 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
 512                 if (ipaddress == NULL) {
 513                     return NULL;
 514                 }
 515                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 516                     (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
 517                 scope = addrs->addr.him6.sin6_scope_id;
 518                 if (scope != 0) { /* zero is default value, no need to set */
 519                     (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 520                     (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 521                     (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
 522                 }
 523                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
 524                 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
 525                 if (ibObj == NULL) {
 526                   free_netaddr(netaddrP);
 527                   return NULL;
 528                 }
 529                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
 530                 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
 531                 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
 532             }
 533         }
 534         (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);
 535         addrs = addrs->next;
 536         addr_index++;
 537     }
 538     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
 539     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);
 540 
 541     /*
 542      * Windows doesn't have virtual interfaces, so child array
 543      * is always empty.
 544      */
 545     childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);
 546     if (childArr == NULL) {
 547       return NULL;
 548     }
 549     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
 550 
 551     /* return the NetworkInterface */
 552     return netifObj;
 553 }
 554 
 555 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
 556     (JNIEnv *env, jclass cls, jstring name)
 557 {
 558     netif *ifList, *curr;
 559     jboolean isCopy;
 560     const char *name_utf;
 561     jobject netifObj = NULL;
 562 
 563     if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
 564         return NULL;
 565     }
 566 
 567     /* get the name as a C string */
 568     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
 569 
 570     /* Search by name */
 571     curr = ifList;
 572     while (curr != NULL) {
 573         if (strcmp(name_utf, curr->name) == 0) {
 574             break;
 575         }
 576         curr = curr->next;
 577     }
 578 
 579     /* if found create a NetworkInterface */
 580     if (curr != NULL) {;
 581         netifObj = createNetworkInterfaceXP(env, curr);
 582     }
 583 
 584     /* release the UTF string */
 585     (*env)->ReleaseStringUTFChars(env, name, name_utf);
 586 
 587     /* release the interface list */
 588     free_netif(ifList);
 589 
 590     return netifObj;
 591 }
 592 
 593 /*
 594  * Class:     NetworkInterface
 595  * Method:    getByIndex0_XP
 596  * Signature: (I)LNetworkInterface;
 597  */
 598 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0_XP
 599   (JNIEnv *env, jclass cls, jint index)
 600 {
 601     netif *ifList, *curr;
 602     jobject netifObj = NULL;
 603 
 604     if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
 605         return NULL;
 606     }
 607 
 608     /* search by index */
 609     curr = ifList;
 610     while (curr != NULL) {
 611         if (index == curr->index) {
 612             break;
 613         }
 614         curr = curr->next;
 615     }
 616 
 617     /* if found create a NetworkInterface */
 618     if (curr != NULL) {
 619         netifObj = createNetworkInterfaceXP(env, curr);
 620     }
 621 
 622     /* release the interface list */
 623     free_netif(ifList);
 624 
 625     return netifObj;
 626 }
 627 
 628 /*
 629  * Class:     java_net_NetworkInterface
 630  * Method:    getByInetAddress0
 631  * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
 632  */
 633 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP
 634     (JNIEnv *env, jclass cls, jobject iaObj)
 635 {
 636     netif *ifList, *curr;
 637     jobject netifObj = NULL;
 638 
 639     /* get the list of interfaces */
 640     if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
 641         return NULL;
 642     }
 643 
 644     /*
 645      * Enumerate the addresses on each interface until we find a
 646      * matching address.
 647      */
 648     curr = ifList;
 649     while (curr != NULL) {
 650         netaddr *addrList = curr->addrs;
 651         netaddr *addrP;
 652 
 653         /* iterate through each address */
 654         addrP = addrList;
 655 
 656         while (addrP != NULL) {
 657             if (NET_SockaddrEqualsInetAddress(env,
 658                                 (struct sockaddr*)&addrP->addr, iaObj)) {
 659                 break;
 660             }
 661             addrP = addrP->next;
 662         }
 663 
 664         /*
 665          * Address matched so create NetworkInterface for this interface
 666          * and address list.
 667          */
 668         if (addrP != NULL) {
 669             netifObj = createNetworkInterfaceXP(env, curr);
 670             break;
 671         }
 672 
 673         /* on next interface */
 674         curr = curr->next;
 675     }
 676 
 677     /* release the interface list */
 678     free_netif(ifList);
 679 
 680     return netifObj;
 681 }
 682 
 683 /*
 684  * Class:     java_net_NetworkInterface
 685  * Method:    getAll
 686  * Signature: ()[Ljava/net/NetworkInterface;
 687  */
 688 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP
 689     (JNIEnv *env, jclass cls)
 690 {
 691     int count;
 692     netif *ifList, *curr;
 693     jobjectArray netIFArr;
 694     jint arr_index;
 695 
 696     /*
 697      * Get list of interfaces
 698      */
 699     count = getAllInterfacesAndAddresses (env, &ifList);
 700     if (count < 0) {
 701         return NULL;
 702     }
 703 
 704     /* allocate a NetworkInterface array */
 705     netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);
 706     if (netIFArr == NULL) {
 707         return NULL;
 708     }
 709 
 710     /*
 711      * Iterate through the interfaces, create a NetworkInterface instance
 712      * for each array element and populate the object.
 713      */
 714     curr = ifList;
 715     arr_index = 0;
 716     while (curr != NULL) {
 717         jobject netifObj;
 718 
 719         netifObj = createNetworkInterfaceXP(env, curr);
 720         if (netifObj == NULL) {
 721             return NULL;
 722         }
 723 
 724         /* put the NetworkInterface into the array */
 725         (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
 726         curr = curr->next;
 727     }
 728 
 729     /* release the interface list */
 730     free_netif(ifList);
 731 
 732     return netIFArr;
 733 }
 734 
 735 /*
 736  * Class:     java_net_NetworkInterface
 737  * Method:    supportsMulticast0
 738  * Signature: (Ljava/lang/String;I)Z
 739  */
 740 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP
 741     (JNIEnv *env, jclass cls, jstring name, jint index) {
 742       IP_ADAPTER_ADDRESSES *ptr;
 743       jboolean val = JNI_TRUE;
 744 
 745       ptr = getAdapter(env, index);
 746       if (ptr != NULL) {
 747         val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE;
 748         free(ptr);
 749       }
 750       return val;
 751 }
 752 
 753 /*
 754  * Class:     java_net_NetworkInterface
 755  * Method:    isUp0
 756  * Signature: (Ljava/lang/String;I)Z
 757  */
 758 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP
 759     (JNIEnv *env, jclass cls, jstring name, jint index) {
 760       IP_ADAPTER_ADDRESSES *ptr;
 761       jboolean val = JNI_FALSE;
 762 
 763       ptr = getAdapter(env, index);
 764       if (ptr != NULL) {
 765         val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE;
 766         free(ptr);
 767       }
 768       return val;
 769 }
 770 
 771 /*
 772  * Class:     java_net_NetworkInterface
 773  * Method:    getMacAddr0
 774  * Signature: (Ljava/lang/String;I)Z
 775  */
 776 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP
 777     (JNIEnv *env, jclass cls, jstring name, jint index) {
 778       IP_ADAPTER_ADDRESSES *ptr;
 779       jbyteArray ret = NULL;
 780       int len;
 781 
 782       ptr = getAdapter(env, index);
 783       if (ptr != NULL) {
 784         len = ptr->PhysicalAddressLength;
 785         ret = (*env)->NewByteArray(env, len);
 786         if (!IS_NULL(ret)) {
 787           (*env)->SetByteArrayRegion(env, ret, 0, len,
 788                                      (jbyte*) ptr->PhysicalAddress);
 789         }
 790         free(ptr);
 791       }
 792       return ret;
 793 }
 794 
 795 /*
 796  * Class:       java_net_NetworkInterface
 797  * Method:      getMTU0
 798  * Signature:   ([bLjava/lang/String;I)I
 799  */
 800 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP
 801     (JNIEnv *env, jclass cls, jstring name, jint index) {
 802       IP_ADAPTER_ADDRESSES *ptr;
 803       jint ret = -1;
 804 
 805       ptr = getAdapter(env, index);
 806       if (ptr != NULL) {
 807         ret = ptr->Mtu;
 808         free(ptr);
 809       }
 810       return ret;
 811 }
 812 
 813 /*
 814  * Class:     java_net_NetworkInterface
 815  * Method:    isLoopback0
 816  * Signature: (Ljava/lang/String;I)Z
 817  */
 818 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP
 819     (JNIEnv *env, jclass cls, jstring name, jint index) {
 820       IP_ADAPTER_ADDRESSES *ptr;
 821       jboolean val = JNI_FALSE;
 822 
 823       ptr = getAdapter(env, index);
 824       if (ptr != NULL) {
 825         val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE;
 826         free(ptr);
 827       }
 828       return val;
 829 }
 830 
 831 /*
 832  * Class:     java_net_NetworkInterface
 833  * Method:    isP2P0
 834  * Signature: (Ljava/lang/String;I)Z
 835  */
 836 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP
 837     (JNIEnv *env, jclass cls, jstring name, jint index) {
 838       IP_ADAPTER_ADDRESSES *ptr;
 839       jboolean val = JNI_FALSE;
 840 
 841       ptr = getAdapter(env, index);
 842       if (ptr != NULL) {
 843         if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP ||
 844            ptr->IfType == IF_TYPE_TUNNEL) {
 845           val = JNI_TRUE;
 846         }
 847         free(ptr);
 848       }
 849       return val;
 850 }