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