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