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