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