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