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