1 /*
2  * Copyright (c) 2000, 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  * Interfaces and addresses are enumerated using the IP helper routines
36  * GetIfTable, GetIfAddrTable resp. These routines are available on Windows
37  * 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if
38  * IE is upgraded to 5.x.
39  *
40  * Windows does not have any standard for device names so we are forced
41  * to use our own convention which is based on the normal Unix naming
42  * convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices,
43  * tr0, tr1, .. for token ring, and so on). This convention gives us
44  * consistency across multiple Windows editions and also consistency with
45  * Solaris/Linux device names. Note that we always enumerate in index
46  * order and this ensures consistent device number across invocations.
47  */
48 
49 /* various JNI ids */
50 
51 jclass ni_class;            /* NetworkInterface */
52 
53 jmethodID ni_ctor;          /* NetworkInterface() */
54 
55 jfieldID ni_indexID;        /* NetworkInterface.index */
56 jfieldID ni_addrsID;        /* NetworkInterface.addrs */
57 jfieldID ni_bindsID;        /* NetworkInterface.bindings */
58 jfieldID ni_nameID;         /* NetworkInterface.name */
59 jfieldID ni_displayNameID;  /* NetworkInterface.displayName */
60 jfieldID ni_childsID;       /* NetworkInterface.childs */
61 
62 jclass ni_ibcls;            /* InterfaceAddress */
63 jmethodID ni_ibctrID;       /* InterfaceAddress() */
64 jfieldID ni_ibaddressID;        /* InterfaceAddress.address */
65 jfieldID ni_ibbroadcastID;      /* InterfaceAddress.broadcast */
66 jfieldID ni_ibmaskID;           /* InterfaceAddress.maskLength */
67 
68 /*
69  * Support routines to free netif and netaddr lists
70  */
free_netif(netif * netifP)71 void free_netif(netif *netifP) {
72     netif *curr = netifP;
73     while (curr != NULL) {
74         if (curr->name != NULL)
75             free(curr->name);
76         if (curr->displayName != NULL)
77             free(curr->displayName);
78         if (curr->addrs != NULL)
79             free_netaddr (curr->addrs);
80         netifP = netifP->next;
81         free(curr);
82         curr = netifP;
83     }
84 }
85 
free_netaddr(netaddr * netaddrP)86 void free_netaddr(netaddr *netaddrP) {
87     netaddr *curr = netaddrP;
88     while (curr != NULL) {
89         netaddrP = netaddrP->next;
90         free(curr);
91         curr = netaddrP;
92     }
93 }
94 
95 /*
96  * Returns the interface structure from the table with the matching index.
97  */
getIF(jint index)98 MIB_IFROW *getIF(jint index) {
99     MIB_IFTABLE *tableP;
100     MIB_IFROW *ifrowP, *ret = NULL;
101     ULONG size;
102     DWORD i, count;
103     jint ifindex;
104 
105     /*
106      * Ask the IP Helper library to enumerate the adapters
107      */
108     size = sizeof(MIB_IFTABLE);
109     tableP = (MIB_IFTABLE *)malloc(size);
110     if(tableP == NULL)
111         return NULL;
112 
113     count = GetIfTable(tableP, &size, TRUE);
114     if (count == ERROR_INSUFFICIENT_BUFFER || count == ERROR_BUFFER_OVERFLOW) {
115         MIB_IFTABLE* newTableP =  (MIB_IFTABLE *)realloc(tableP, size);
116         if (newTableP == NULL) {
117             free(tableP);
118             return NULL;
119         }
120         tableP = newTableP;
121 
122         count = GetIfTable(tableP, &size, TRUE);
123     }
124 
125     if (count != NO_ERROR) {
126         free(tableP);
127         return NULL;
128     }
129 
130     {
131     ifrowP = tableP->table;
132     for (i=0; i<tableP->dwNumEntries; i++) {
133     /*
134      * Warning: the real index is obtained by GetFriendlyIfIndex()
135     */
136         ifindex = GetFriendlyIfIndex(ifrowP->dwIndex);
137         if (ifindex == index) {
138           /*
139            * Create a copy of the entry so that we can free the table.
140            */
141             ret = (MIB_IFROW *) malloc(sizeof(MIB_IFROW));
142             if (ret == NULL) {
143                 free(tableP);
144                 return NULL;
145             }
146             memcpy(ret, ifrowP, sizeof(MIB_IFROW));
147             break;
148         }
149 
150         /* onto the next interface */
151         ifrowP++;
152       }
153       free(tableP);
154     }
155     return ret;
156 }
157 
158 /*
159  * Enumerate network interfaces using IP Helper Library routine GetIfTable.
160  * We use GetIfTable rather than other IP helper routines because it's
161  * available on 98 & NT SP4+.
162  *
163  * Returns the number of interfaces found or -1 if error. If no error
164  * occurs then netifPP be returned as list of netif structures or NULL
165  * if no interfaces are found.
166  */
enumInterfaces(JNIEnv * env,netif ** netifPP)167 int enumInterfaces(JNIEnv *env, netif **netifPP)
168 {
169     MIB_IFTABLE *tableP;
170     MIB_IFROW *ifrowP;
171     ULONG size;
172     DWORD ret;
173     int count;
174     netif *netifP;
175     DWORD i;
176     int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0, wlen=0;
177 
178     /*
179      * Ask the IP Helper library to enumerate the adapters
180      */
181     size = sizeof(MIB_IFTABLE);
182     tableP = (MIB_IFTABLE *)malloc(size);
183     if (tableP == NULL) {
184         JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
185         return -1;
186     }
187 
188     ret = GetIfTable(tableP, &size, TRUE);
189     if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {
190         MIB_IFTABLE * newTableP = (MIB_IFTABLE *)realloc(tableP, size);
191         if (newTableP == NULL) {
192             free(tableP);
193             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
194             return -1;
195         }
196         tableP = newTableP;
197         ret = GetIfTable(tableP, &size, TRUE);
198     }
199 
200     if (ret != NO_ERROR) {
201         free(tableP);
202 
203         JNU_ThrowByName(env, "java/lang/Error",
204                 "IP Helper Library GetIfTable function failed");
205         // this different error code is to handle the case when we call
206         // GetIpAddrTable in pure IPv6 environment
207         return -2;
208     }
209 
210     /*
211      * Iterate through the list of adapters
212      */
213     count = 0;
214     netifP = NULL;
215 
216     ifrowP = tableP->table;
217     for (i=0; i<tableP->dwNumEntries; i++) {
218         char dev_name[8];
219         netif *curr;
220 
221         /*
222          * Generate a name for the device as Windows doesn't have any
223          * real concept of a device name.
224          */
225         switch (ifrowP->dwType) {
226             case MIB_IF_TYPE_ETHERNET:
227                 _snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++);
228                 break;
229 
230             case MIB_IF_TYPE_TOKENRING:
231                 _snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++);
232                 break;
233 
234             case MIB_IF_TYPE_FDDI:
235                 _snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++);
236                 break;
237 
238             case MIB_IF_TYPE_LOOPBACK:
239                 /* There should only be only IPv4 loopback address */
240                 if (lo > 0) {
241                     continue;
242                 }
243                 strncpy_s(dev_name, 8, "lo", _TRUNCATE);
244                 lo++;
245                 break;
246 
247             case MIB_IF_TYPE_PPP:
248                 _snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++);
249                 break;
250 
251             case MIB_IF_TYPE_SLIP:
252                 _snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++);
253                 break;
254 
255             case IF_TYPE_IEEE80211:
256                 _snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++);
257                 break;
258 
259             default:
260                 _snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++);
261         }
262 
263         /*
264          * Allocate a netif structure and space for the name and
265          * display name (description in this case).
266          */
267         curr = (netif *)calloc(1, sizeof(netif));
268         if (curr != NULL) {
269             wlen = MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,
270                        ifrowP->dwDescrLen, NULL, 0);
271             if(wlen == 0) {
272                 // MultiByteToWideChar should not fail
273                 // But in rare case it fails, we allow 'char' to be displayed
274                 curr->displayName = (char *)malloc(ifrowP->dwDescrLen + 1);
275             } else {
276                 curr->displayName = (wchar_t *)malloc((wlen+1)*sizeof(wchar_t));
277             }
278 
279             curr->name = (char *)malloc(strlen(dev_name) + 1);
280 
281             if (curr->name == NULL || curr->displayName == NULL) {
282                 if (curr->name) free(curr->name);
283                 if (curr->displayName) free(curr->displayName);
284                 free(curr);
285                 curr = NULL;
286             }
287         }
288         if (curr == NULL) {
289             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
290             free_netif(netifP);
291             free(tableP);
292             return -1;
293         }
294 
295         /*
296          * Populate the interface. Note that we need to convert the
297          * index into its "friendly" value as otherwise we will expose
298          * 32-bit numbers as index values.
299          */
300         strcpy(curr->name, dev_name);
301         if (wlen == 0) {
302             // display char type in case of MultiByteToWideChar failure
303             strncpy(curr->displayName, ifrowP->bDescr, ifrowP->dwDescrLen);
304             curr->displayName[ifrowP->dwDescrLen] = '\0';
305         } else {
306             // call MultiByteToWideChar again to fill curr->displayName
307             // it should not fail, because we have called it once before
308             if (MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,
309                    ifrowP->dwDescrLen, curr->displayName, wlen) == 0) {
310                 JNU_ThrowByName(env, "java/lang/Error",
311                        "Cannot get multibyte char for interface display name");
312                 free_netif(netifP);
313                 free(tableP);
314                 free(curr->name);
315                 free(curr->displayName);
316                 free(curr);
317                 return -1;
318             } else {
319                 ((wchar_t *)curr->displayName)[wlen] = L'\0';
320                 curr->dNameIsUnicode = TRUE;
321             }
322         }
323 
324         curr->dwIndex = ifrowP->dwIndex;
325         curr->ifType = ifrowP->dwType;
326         curr->index = GetFriendlyIfIndex(ifrowP->dwIndex);
327 
328         /*
329          * Put the interface at tail of list as GetIfTable(,,TRUE) is
330          * returning the interfaces in index order.
331          */
332         count++;
333         if (netifP == NULL) {
334             netifP = curr;
335         } else {
336             netif *tail = netifP;
337             while (tail->next != NULL) {
338                 tail = tail->next;
339             }
340             tail->next = curr;
341         }
342 
343         /* onto the next interface */
344         ifrowP++;
345     }
346 
347     /*
348      * Free the interface table and return the interface list
349      */
350     if (tableP) {
351         free(tableP);
352     }
353     *netifPP = netifP;
354     return count;
355 }
356 
357 /*
358  * Enumerate the IP addresses on an interface using the IP helper library
359  * routine GetIfAddrTable and matching based on the index name. There are
360  * more efficient routines but we use GetIfAddrTable because it's avaliable
361  * on 98 and NT.
362  *
363  * Returns the count of addresses, or -1 if error. If no error occurs then
364  * netaddrPP will return a list of netaddr structures with the IP addresses.
365  */
enumAddresses_win(JNIEnv * env,netif * netifP,netaddr ** netaddrPP)366 int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
367 {
368     MIB_IPADDRTABLE *tableP;
369     ULONG size;
370     DWORD ret;
371     DWORD i;
372     netaddr *netaddrP;
373     int count = 0;
374     unsigned long mask;
375 
376     /*
377      * Use GetIpAddrTable to enumerate the IP Addresses
378      */
379     size = sizeof(MIB_IPADDRTABLE);
380     tableP = (MIB_IPADDRTABLE *)malloc(size);
381     if (tableP == NULL) {
382         JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
383         return -1;
384     }
385 
386     ret = GetIpAddrTable(tableP, &size, FALSE);
387     if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {
388         MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size);
389         if (newTableP == NULL) {
390             free(tableP);
391             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
392             return -1;
393         }
394         tableP = newTableP;
395 
396         ret = GetIpAddrTable(tableP, &size, FALSE);
397     }
398     if (ret != NO_ERROR) {
399         if (tableP) {
400             free(tableP);
401         }
402         JNU_ThrowByName(env, "java/lang/Error",
403                 "IP Helper Library GetIpAddrTable function failed");
404         // this different error code is to handle the case when we call
405         // GetIpAddrTable in pure IPv6 environment
406         return -2;
407     }
408 
409     /*
410      * Iterate through the table to find the addresses with the
411      * matching dwIndex. Ignore 0.0.0.0 addresses.
412      */
413     count = 0;
414     netaddrP = NULL;
415 
416     i = 0;
417     while (i<tableP->dwNumEntries) {
418         if (tableP->table[i].dwIndex == netifP->dwIndex &&
419             tableP->table[i].dwAddr != 0) {
420 
421             netaddr *curr = (netaddr *)malloc(sizeof(netaddr));
422             if (curr == NULL) {
423                 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");
424                 free_netaddr(netaddrP);
425                 free(tableP);
426                 return -1;
427             }
428 
429             curr->addr.sa4.sin_family = AF_INET;
430             curr->addr.sa4.sin_addr.s_addr = tableP->table[i].dwAddr;
431             /*
432              * Get netmask / broadcast address
433              */
434             switch (netifP->ifType) {
435             case MIB_IF_TYPE_ETHERNET:
436             case MIB_IF_TYPE_TOKENRING:
437             case MIB_IF_TYPE_FDDI:
438             case MIB_IF_TYPE_LOOPBACK:
439             case IF_TYPE_IEEE80211:
440               /**
441                * Contrary to what it seems to indicate, dwBCastAddr doesn't
442                * contain the broadcast address but 0 or 1 depending on whether
443                * the broadcast address should set the bits of the host part
444                * to 0 or 1.
445                * Yes, I know it's stupid, but what can I say, it's MSFTs API.
446                */
447               curr->brdcast.sa4.sin_family = AF_INET;
448               if (tableP->table[i].dwBCastAddr == 1)
449                 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask);
450               else
451                 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask);
452               mask = ntohl(tableP->table[i].dwMask);
453               curr->mask = 0;
454               while (mask) {
455                 mask <<= 1;
456                 curr->mask++;
457               }
458               break;
459             case MIB_IF_TYPE_PPP:
460             case MIB_IF_TYPE_SLIP:
461             default:
462               /**
463                * these don't have broadcast/subnet
464                */
465               curr->mask = -1;
466                 break;
467             }
468 
469             curr->next = netaddrP;
470             netaddrP = curr;
471             count++;
472         }
473         i++;
474     }
475 
476     *netaddrPP = netaddrP;
477     free(tableP);
478     return count;
479 }
480 
481 /*
482  * Class:     java_net_NetworkInterface
483  * Method:    init
484  * Signature: ()V
485  */
486 JNIEXPORT void JNICALL
Java_java_net_NetworkInterface_init(JNIEnv * env,jclass cls)487 Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls)
488 {
489     /*
490      * Get the various JNI ids that we require
491      */
492     ni_class = (*env)->NewGlobalRef(env, cls);
493     CHECK_NULL(ni_class);
494     ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");
495     CHECK_NULL(ni_nameID);
496     ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
497     CHECK_NULL(ni_displayNameID);
498     ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
499     CHECK_NULL(ni_indexID);
500     ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
501     CHECK_NULL(ni_addrsID);
502     ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
503     CHECK_NULL(ni_bindsID);
504     ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
505     CHECK_NULL(ni_childsID);
506     ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
507     CHECK_NULL(ni_ctor);
508     ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
509     CHECK_NULL(ni_ibcls);
510     ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
511     CHECK_NULL(ni_ibcls);
512     ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
513     CHECK_NULL(ni_ibctrID);
514     ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
515     CHECK_NULL(ni_ibaddressID);
516     ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
517     CHECK_NULL(ni_ibbroadcastID);
518     ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
519     CHECK_NULL(ni_ibmaskID);
520 
521     initInetAddressIDs(env);
522 }
523 
524 /*
525  * Create a NetworkInterface object, populate the name and index, and
526  * populate the InetAddress array based on the IP addresses for this
527  * interface.
528  */
createNetworkInterface(JNIEnv * env,netif * ifs,int netaddrCount,netaddr * netaddrP)529 jobject createNetworkInterface
530     (JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP)
531 {
532     jobject netifObj;
533     jobject name, displayName;
534     jobjectArray addrArr, bindsArr, childArr;
535     netaddr *addrs;
536     jint addr_index;
537     jint bind_index;
538 
539     /*
540      * Create a NetworkInterface object and populate it
541      */
542     netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
543     CHECK_NULL_RETURN(netifObj, NULL);
544     name = (*env)->NewStringUTF(env, ifs->name);
545     CHECK_NULL_RETURN(name, NULL);
546     if (ifs->dNameIsUnicode) {
547         displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,
548                                        (jsize)wcslen ((PWCHAR)ifs->displayName));
549     } else {
550         displayName = (*env)->NewStringUTF(env, ifs->displayName);
551     }
552     CHECK_NULL_RETURN(displayName, NULL);
553     (*env)->SetObjectField(env, netifObj, ni_nameID, name);
554     (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);
555     (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
556 
557     /*
558      * Get the IP addresses for this interface if necessary
559      * Note that 0 is a valid number of addresses.
560      */
561     if (netaddrCount < 0) {
562         netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
563         if (netaddrCount < 0) {
564             return NULL;
565         }
566     }
567     addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);
568     if (addrArr == NULL) {
569         free_netaddr(netaddrP);
570         return NULL;
571     }
572 
573     bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);
574     if (bindsArr == NULL) {
575       free_netaddr(netaddrP);
576       return NULL;
577     }
578     addrs = netaddrP;
579     addr_index = 0;
580     bind_index = 0;
581     while (addrs != NULL) {
582         jobject iaObj, ia2Obj;
583         jobject ibObj = NULL;
584         if (addrs->addr.sa.sa_family == AF_INET) {
585             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
586             if (iaObj == NULL) {
587                 free_netaddr(netaddrP);
588                 return NULL;
589             }
590             /* default ctor will set family to AF_INET */
591 
592             setInetAddress_addr(env, iaObj, ntohl(addrs->addr.sa4.sin_addr.s_addr));
593             if ((*env)->ExceptionCheck(env)) {
594                 free_netaddr(netaddrP);
595                 return NULL;
596             }
597             if (addrs->mask != -1) {
598               ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
599               if (ibObj == NULL) {
600                 free_netaddr(netaddrP);
601                 return NULL;
602               }
603               (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
604               ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
605               if (ia2Obj == NULL) {
606                 free_netaddr(netaddrP);
607                 return NULL;
608               }
609               setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.sa4.sin_addr.s_addr));
610               if ((*env)->ExceptionCheck(env)) {
611                   free_netaddr(netaddrP);
612                   return NULL;
613               }
614               (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
615               (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
616               (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
617             }
618         } else /* AF_INET6 */ {
619             int scope;
620             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
621             if (iaObj) {
622                 jboolean ret = setInet6Address_ipaddress(env, iaObj,  (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));
623                 if (ret == JNI_FALSE) {
624                     free_netaddr(netaddrP);
625                     return NULL;
626                 }
627 
628                 scope = addrs->addr.sa6.sin6_scope_id;
629                 if (scope != 0) { /* zero is default value, no need to set */
630                     setInet6Address_scopeid(env, iaObj, scope);
631                     setInet6Address_scopeifname(env, iaObj, netifObj);
632                 }
633                 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
634                 if (ibObj == NULL) {
635                   free_netaddr(netaddrP);
636                   return NULL;
637                 }
638                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
639                 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
640                 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
641             }
642         }
643         (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);
644         addrs = addrs->next;
645         addr_index++;
646     }
647     (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
648     (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);
649 
650     free_netaddr(netaddrP);
651 
652     /*
653      * Windows doesn't have virtual interfaces, so child array
654      * is always empty.
655      */
656     childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);
657     if (childArr == NULL) {
658       return NULL;
659     }
660     (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
661 
662     /* return the NetworkInterface */
663     return netifObj;
664 }
665 
666 /*
667  * Class:     java_net_NetworkInterface
668  * Method:    getByName0
669  * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
670  */
Java_java_net_NetworkInterface_getByName0(JNIEnv * env,jclass cls,jstring name)671 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
672     (JNIEnv *env, jclass cls, jstring name)
673 {
674     netif *ifList, *curr;
675     jboolean isCopy;
676     const char *name_utf;
677     jobject netifObj = NULL;
678 
679     // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
680     if (ipv6_available()) {
681         return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name);
682     }
683 
684     /* get the list of interfaces */
685     if (enumInterfaces(env, &ifList) < 0) {
686         return NULL;
687     }
688 
689     /* get the name as a C string */
690     name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
691     if (name_utf != NULL) {
692 
693         /* Search by name */
694         curr = ifList;
695         while (curr != NULL) {
696             if (strcmp(name_utf, curr->name) == 0) {
697                 break;
698             }
699             curr = curr->next;
700         }
701 
702         /* if found create a NetworkInterface */
703         if (curr != NULL) {;
704             netifObj = createNetworkInterface(env, curr, -1, NULL);
705         }
706 
707         /* release the UTF string */
708         (*env)->ReleaseStringUTFChars(env, name, name_utf);
709     } else {
710         if (!(*env)->ExceptionCheck(env))
711             JNU_ThrowOutOfMemoryError(env, NULL);
712     }
713 
714     /* release the interface list */
715     free_netif(ifList);
716 
717     return netifObj;
718 }
719 
720 /*
721  * Class:     NetworkInterface
722  * Method:    getByIndex0
723  * Signature: (I)LNetworkInterface;
724  */
Java_java_net_NetworkInterface_getByIndex0(JNIEnv * env,jclass cls,jint index)725 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
726   (JNIEnv *env, jclass cls, jint index)
727 {
728     netif *ifList, *curr;
729     jobject netifObj = NULL;
730 
731     // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
732     if (ipv6_available()) {
733         return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index);
734     }
735 
736     /* get the list of interfaces */
737     if (enumInterfaces(env, &ifList) < 0) {
738         return NULL;
739     }
740 
741     /* search by index */
742     curr = ifList;
743     while (curr != NULL) {
744         if (index == curr->index) {
745             break;
746         }
747         curr = curr->next;
748     }
749 
750     /* if found create a NetworkInterface */
751     if (curr != NULL) {
752         netifObj = createNetworkInterface(env, curr, -1, NULL);
753     }
754 
755     /* release the interface list */
756     free_netif(ifList);
757 
758     return netifObj;
759 }
760 
761 /*
762  * Class:     java_net_NetworkInterface
763  * Method:    getByInetAddress0
764  * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
765  */
Java_java_net_NetworkInterface_getByInetAddress0(JNIEnv * env,jclass cls,jobject iaObj)766 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
767     (JNIEnv *env, jclass cls, jobject iaObj)
768 {
769     netif *ifList, *curr;
770     jobject netifObj = NULL;
771     jint addr = getInetAddress_addr(env, iaObj);
772     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
773 
774     // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
775     if (ipv6_available()) {
776         return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
777     }
778 
779     /* get the list of interfaces */
780     if (enumInterfaces(env, &ifList) < 0) {
781         return NULL;
782     }
783 
784     /*
785      * Enumerate the addresses on each interface until we find a
786      * matching address.
787      */
788     curr = ifList;
789     while (curr != NULL) {
790         int count;
791         netaddr *addrList;
792         netaddr *addrP;
793 
794         /* enumerate the addresses on this interface */
795         count = enumAddresses_win(env, curr, &addrList);
796         if (count < 0) {
797             free_netif(ifList);
798             return NULL;
799         }
800 
801         /* iterate through each address */
802         addrP = addrList;
803 
804         while (addrP != NULL) {
805             if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) {
806                 break;
807             }
808             addrP = addrP->next;
809         }
810 
811         /*
812          * Address matched so create NetworkInterface for this interface
813          * and address list.
814          */
815         if (addrP != NULL) {
816             /* createNetworkInterface will free addrList */
817             netifObj = createNetworkInterface(env, curr, count, addrList);
818             break;
819         }
820 
821         /* on next interface */
822         curr = curr->next;
823     }
824 
825     /* release the interface list */
826     free_netif(ifList);
827 
828     return netifObj;
829 }
830 
831 /*
832  * Class:     java_net_NetworkInterface
833  * Method:    getAll
834  * Signature: ()[Ljava/net/NetworkInterface;
835  */
Java_java_net_NetworkInterface_getAll(JNIEnv * env,jclass cls)836 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
837     (JNIEnv *env, jclass cls)
838 {
839     int count;
840     netif *ifList = NULL, *curr;
841     jobjectArray netIFArr;
842     jint arr_index;
843 
844     // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
845     if (ipv6_available()) {
846         return Java_java_net_NetworkInterface_getAll_XP (env, cls);
847     }
848 
849     /*
850      * Get list of interfaces
851      */
852     count = enumInterfaces(env, &ifList);
853     if (count < 0) {
854         return NULL;
855     }
856 
857     /* allocate a NetworkInterface array */
858     netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);
859     if (netIFArr == NULL) {
860         free_netif(ifList);
861         return NULL;
862     }
863 
864     /*
865      * Iterate through the interfaces, create a NetworkInterface instance
866      * for each array element and populate the object.
867      */
868     curr = ifList;
869     arr_index = 0;
870     while (curr != NULL) {
871         jobject netifObj;
872 
873         netifObj = createNetworkInterface(env, curr, -1, NULL);
874         if (netifObj == NULL) {
875             free_netif(ifList);
876             return NULL;
877         }
878 
879         /* put the NetworkInterface into the array */
880         (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
881 
882         curr = curr->next;
883     }
884 
885     /* release the interface list */
886     free_netif(ifList);
887 
888     return netIFArr;
889 }
890 
891 /*
892  * Class:     java_net_NetworkInterface
893  * Method:    isUp0
894  * Signature: (Ljava/lang/String;)Z
895  */
Java_java_net_NetworkInterface_isUp0(JNIEnv * env,jclass cls,jstring name,jint index)896 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
897     (JNIEnv *env, jclass cls, jstring name, jint index) {
898   jboolean ret = JNI_FALSE;
899 
900   // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
901   if (ipv6_available()) {
902     return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index);
903   } else {
904     MIB_IFROW *ifRowP;
905     ifRowP = getIF(index);
906     if (ifRowP != NULL) {
907       ret = ifRowP->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP &&
908             (ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL ||
909              ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED);
910       free(ifRowP);
911     }
912   }
913     return ret;
914 }
915 
916 /*
917  * Class:     java_net_NetworkInterface
918  * Method:    isP2P0
919  * Signature: (Ljava/lang/String;I)Z
920  */
Java_java_net_NetworkInterface_isP2P0(JNIEnv * env,jclass cls,jstring name,jint index)921 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
922     (JNIEnv *env, jclass cls, jstring name, jint index) {
923   MIB_IFROW *ifRowP;
924   jboolean ret = JNI_FALSE;
925 
926   // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
927   if (ipv6_available()) {
928     return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index);
929   } else {
930     ifRowP = getIF(index);
931     if (ifRowP != NULL) {
932       switch(ifRowP->dwType) {
933       case MIB_IF_TYPE_PPP:
934       case MIB_IF_TYPE_SLIP:
935         ret = JNI_TRUE;
936         break;
937       }
938       free(ifRowP);
939     }
940   }
941   return ret;
942 }
943 
944 /*
945  * Class:     java_net_NetworkInterface
946  * Method:    isLoopback0
947  * Signature: (Ljava/lang/String;I)Z
948  */
Java_java_net_NetworkInterface_isLoopback0(JNIEnv * env,jclass cls,jstring name,jint index)949 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
950     (JNIEnv *env, jclass cls, jstring name, jint index) {
951   MIB_IFROW *ifRowP;
952   jboolean ret = JNI_FALSE;
953 
954   // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
955   if (ipv6_available()) {
956     return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index);
957   } else {
958     ifRowP = getIF(index);
959     if (ifRowP != NULL) {
960       if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK)
961         ret = JNI_TRUE;
962       free(ifRowP);
963     }
964     return ret;
965   }
966 }
967 
968 /*
969  * Class:     java_net_NetworkInterface
970  * Method:    supportsMulticast0
971  * Signature: (Ljava/lang/String;I)Z
972  */
Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv * env,jclass cls,jstring name,jint index)973 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
974     (JNIEnv *env, jclass cls, jstring name, jint index) {
975     return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls,
976                                                                name, index);
977 }
978 
979 /*
980  * Class:     java_net_NetworkInterface
981  * Method:    getMacAddr0
982  * Signature: ([bLjava/lang/String;I)[b
983  */
Java_java_net_NetworkInterface_getMacAddr0(JNIEnv * env,jclass class,jbyteArray addrArray,jstring name,jint index)984 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
985     (JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
986   jbyteArray ret = NULL;
987   int len;
988   MIB_IFROW *ifRowP;
989 
990   // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
991   if (ipv6_available()) {
992     return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index);
993   } else {
994     ifRowP = getIF(index);
995     if (ifRowP != NULL) {
996       switch(ifRowP->dwType) {
997       case MIB_IF_TYPE_ETHERNET:
998       case MIB_IF_TYPE_TOKENRING:
999       case MIB_IF_TYPE_FDDI:
1000       case IF_TYPE_IEEE80211:
1001         len = ifRowP->dwPhysAddrLen;
1002         if (len > 0) {
1003             ret = (*env)->NewByteArray(env, len);
1004             if (!IS_NULL(ret)) {
1005               (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);
1006             }
1007         }
1008         break;
1009       }
1010       free(ifRowP);
1011     }
1012     return ret;
1013   }
1014 }
1015 
1016 /*
1017  * Class:       java_net_NetworkInterface
1018  * Method:      getMTU0
1019  * Signature:   ([bLjava/lang/String;I)I
1020  */
Java_java_net_NetworkInterface_getMTU0(JNIEnv * env,jclass class,jstring name,jint index)1021 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
1022     (JNIEnv *env, jclass class, jstring name, jint index) {
1023   jint ret = -1;
1024   MIB_IFROW *ifRowP;
1025 
1026   // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
1027   if (ipv6_available()) {
1028     return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index);
1029   } else {
1030     ifRowP = getIF(index);
1031     if (ifRowP != NULL) {
1032       ret = ifRowP->dwMtu;
1033       free(ifRowP);
1034     }
1035     return ret;
1036   }
1037 }
1038