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