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