blob: 471215a2a34a901fe343d8d627bd136ed7293a31 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include <stdlib.h>
27#include <windows.h>
28#include <winsock2.h> /* needed for htonl */
29#include <iprtrmib.h>
30#include <assert.h>
31
32#include "java_net_NetworkInterface.h"
33#include "jni_util.h"
34
35#include "NetworkInterface.h"
36
37/*
38 * Windows implementation of the java.net.NetworkInterface native methods.
39 * This module provides the implementations of getAll, getByName, getByIndex,
40 * and getByAddress.
41 */
42
43extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
44
45/* IP helper library routines */
46int (PASCAL FAR *GetIpAddrTable_fn)();
47int (PASCAL FAR *GetIfTable_fn)();
48int (PASCAL FAR *GetFriendlyIfIndex_fn)();
49int (PASCAL FAR *GetAdaptersAddresses_fn)();
50int (PASCAL FAR *GetAdaptersInfo_fn)();
51int (PASCAL FAR *GetNumberOfInterfaces_fn)();
52
53#ifdef DEBUG
54void printnif (netif *nif) {
55#ifdef _WIN64
56 printf ("nif:0x%I64x name:%s\n", nif,nif->name);
57#else
58 printf ("nif:0x%x name:%s\n", nif,nif->name);
59#endif
60 if (nif->dNameIsUnicode) {
61 printf ("dName:%S index:%d ", nif->displayName,nif->index);
62 } else {
63 printf ("dName:%s index:%d ", nif->displayName,nif->index);
64 }
65 printf ("naddrs:%d\n", nif->naddrs);
66}
67
68void printnifs (netif *netifPP, char *str) {
69 netif *nif;
70 printf ("%s\n", str);
71 for (nif=netifPP; nif!=NULL; nif=nif->next) {
72 printnif (nif);
73 }
74 printf("-----------------\n");
75}
76
77#endif
78
79static int bufsize = 1024;
80
81/*
82 * return an array of IP_ADAPTER_ADDRESSES containing one element
83 * for each apdapter on the system. Returned in *adapters.
84 * Buffer is malloc'd and must be freed (unless error returned)
85 */
86static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) {
87 DWORD ret, flags;
88 IP_ADAPTER_ADDRESSES *adapterInfo;
89 ULONG len;
90 adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
91 if (adapterInfo == 0) {
92 return -1;
93 }
94 len = bufsize;
95 flags = GAA_FLAG_SKIP_DNS_SERVER;
96 flags |= GAA_FLAG_SKIP_MULTICAST;
97 flags |= GAA_FLAG_INCLUDE_PREFIX;
98 ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
99 if (ret == ERROR_BUFFER_OVERFLOW) {
100 adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
101 if (adapterInfo == 0) {
102 return -1;
103 }
104 bufsize = len;
105 ret = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
106 }
107 if (ret != ERROR_SUCCESS) {
108 free (adapterInfo);
109 JNU_ThrowByName(env, "java/lang/Error",
110 "IP Helper Library GetAdaptersAddresses function failed");
111 return -1;
112 }
113 *adapters = adapterInfo;
114 return ERROR_SUCCESS;
115}
116
117/*
118 * return an array of IP_ADAPTER_ADDRESSES containing one element
119 * for each apdapter on the system. Returned in *adapters.
120 * Buffer is malloc'd and must be freed (unless error returned)
121 */
122IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {
123 DWORD flags, val;
124 IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret;
125 ULONG len;
126 adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
127 if (adapterInfo == 0) {
128 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
129 return NULL;
130 }
131 len = bufsize;
132 flags = GAA_FLAG_SKIP_DNS_SERVER;
133 flags |= GAA_FLAG_SKIP_MULTICAST;
134 flags |= GAA_FLAG_INCLUDE_PREFIX;
135 val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
136 if (val == ERROR_BUFFER_OVERFLOW) {
137 adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
138 if (adapterInfo == 0) {
139 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
140 return NULL;
141 }
142 bufsize = len;
143 val = (*GetAdaptersAddresses_fn) (AF_UNSPEC, flags, NULL, adapterInfo, &len);
144 }
145 if (val != ERROR_SUCCESS) {
146 free (adapterInfo);
147 JNU_ThrowByName(env, "java/lang/Error",
148 "IP Helper Library GetAdaptersAddresses function failed");
149 return NULL;
150 }
151 ptr = adapterInfo;
152 ret = NULL;
153 while (ptr != NULL) {
154 // IPv4 interface
155 if (ptr->Ipv6IfIndex == index) {
156 ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES));
157 memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES));
158 }
159 ptr=ptr->Next;
160 }
161 free(adapterInfo);
162 return ret;
163}
164
165static int ipinflen = 2048;
166
167/*
168 */
169int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
170{
171 DWORD ret, numInterfaces;
172 IP_ADAPTER_ADDRESSES *ptr, *ptr1, *adapters=0;
173 ULONG len=ipinflen, count=0;
174 netif *nif=0, *dup_nif, *last=0, *loopif=0;
175 netaddr *addr, *addr1;
176 int tun=0, net=0;
177
178 *netifPP = 0;
179
180 /*
181 * Get the IPv4 interfaces. This information is the same
182 * as what previous JDK versions would return.
183 */
184
185 ret = enumInterfaces_win (env, netifPP);
186 if (ret == -1) {
187 return -1;
188 } else {
189 count = ret;
190 }
191
192 /* locate the loopback (and the last) interface */
193 for (nif=*netifPP, last=nif; nif!=0; nif=nif->next) {
194 if (nif->ifType == MIB_IF_TYPE_LOOPBACK) {
195 loopif = nif;
196 }
197 last = nif;
198 }
199
200 ret = getAdapters (env, &adapters);
201 if (ret != ERROR_SUCCESS) {
202 goto err;
203 }
204
205 /* Now get the IPv6 information. This includes:
206 * (a) IPv6 information associated with interfaces already found
207 * (b) IPv6 information for IPv6 only interfaces (probably tunnels)
208 *
209 * For compatibility with previous releases we use the naming
210 * information gotten from enumInterfaces_win() for (a) entries
211 * However, the index numbers are taken from the new API.
212 *
213 * The procedure is to go through the list of adapters returned
214 * by the new API looking for entries that correspond to IPv4 interfaces
215 * already found.
216 */
217
218 ptr = adapters;
219 while (ptr != NULL) {
220 int c;
221 netif *nif0;
222 if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) {
223 c = getAddrsFromAdapter(ptr, &loopif->addrs);
224 if (c == -1) {
225 goto err;
226 }
227 loopif->naddrs += c;
228 } else {
229 int index = ptr->IfIndex;
230 if (index != 0) {
231 /* This entry is associated with an IPv4 interface */
232 for (nif=*netifPP; nif!=0; nif=nif->next) {
233 if (nif->index == index) {
234 /* found the interface entry
235 * set the index to the IPv6 index and add the
236 * IPv6 addresses
237 */
238 nif->index = ptr->Ipv6IfIndex;
239 c = getAddrsFromAdapter(ptr, &nif->addrs);
240 nif->naddrs += c;
241 break;
242 }
243 }
244 } else {
245 /* This entry is IPv6 only */
246 char newname [128];
247 int c;
248
249 /* Windows allocates duplicate adapter entries
250 * for tunnel interfaces when there are multiple
251 * physical adapters. Need to check
252 * if this is a duplicate (ipv6Index is the same)
253 */
254 dup_nif = 0;
255 for (nif0=*netifPP; nif0!=0; nif0=nif0->next) {
256 if (nif0->hasIpv6Address &&
257 ptr->Ipv6IfIndex == nif0->ipv6Index) {
258 dup_nif = nif0;
259 break;
260 }
261 }
262 if (dup_nif == 0) {
263 /* new interface */
264 nif = (netif *) calloc (1, sizeof(netif));
265 if (nif == 0) {
266 goto err;
267 }
268 if (ptr->IfType == IF_TYPE_TUNNEL) {
269 sprintf (newname, "tun%d", tun);
270 tun ++;
271 } else {
272 sprintf (newname, "net%d", net);
273 net ++;
274 }
275 nif->name = malloc (strlen(newname)+1);
276 nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2);
277 if (nif->name == 0 || nif->displayName == 0) {
278 goto err;
279 }
280 strcpy (nif->name, newname);
281 wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName);
282 nif->dNameIsUnicode = TRUE;
283 nif->index = ptr->Ipv6IfIndex;
284 nif->ipv6Index = ptr->Ipv6IfIndex;
285 nif->hasIpv6Address = TRUE;
286
287 last->next = nif;
288 last = nif;
289 count++;
290 c = getAddrsFromAdapter(ptr, &nif->addrs);
291 if (c == -1) {
292 goto err;
293 }
294 nif->naddrs += c;
295 } else {
296 /* add the addresses from this adapter to the
297 * original (dup_nif)
298 */
299 c = getAddrsFromAdapter(ptr, &dup_nif->addrs);
300 if (c == -1) {
301 goto err;
302 }
303 dup_nif->naddrs += c;
304 }
305 }
306 }
307 ptr=ptr->Next;
308 }
309
310 free (adapters);
311 return count;
312
313err:
314 if (*netifPP) {
315 free_netif (*netifPP);
316 }
317 if (adapters) {
318 free (adapters);
319 }
320 return -1;
321}
322
323/* If *netaddrPP is null, then the addresses are allocated and the beginning
324 * of the allocated chain is returned in *netaddrPP.
325 * If *netaddrPP is not null, then the addresses allocated here are appended
326 * to the existing chain.
327 *
328 * Returns count of addresses or -1 on error.
329 */
330
331static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) {
332 LPSOCKADDR sock;
333 int ret, count = 0;
334 netaddr *curr, *start=0, *prev=0;
335 PIP_ADAPTER_UNICAST_ADDRESS uni_addr;
336 PIP_ADAPTER_ANYCAST_ADDRESS any_addr;
337 PIP_ADAPTER_PREFIX prefix;
338
339 /* If chain passed in, find end */
340 if (*netaddrPP != NULL) {
341 for (start=*netaddrPP; start->next!=NULL; start=start->next) {
342 }
343 prev=start;
344 }
345
346 prefix = ptr->FirstPrefix;
347 /* Unicast */
348 uni_addr = ptr->FirstUnicastAddress;
349 while (uni_addr != NULL) {
350 /* address is only usable if dad state is preferred or deprecated */
351 if (uni_addr->DadState == IpDadStateDeprecated ||
352 uni_addr->DadState == IpDadStatePreferred) {
353 curr = (netaddr *)calloc (1, sizeof (netaddr));
354 if (curr == 0) {
355 return -1;
356 }
357 if (start == NULL) {
358 start = curr;
359 }
360 if (prev != NULL) {
361 prev->next = curr;
362 }
363 prev = curr;
364 sock = uni_addr->Address.lpSockaddr;
365 SOCKETADDRESS_COPY (&curr->addr, sock);
366 if (prefix != NULL) {
367 curr->mask = prefix->PrefixLength;
368 if (sock->sa_family == AF_INET) {
369 sock = prefix->Address.lpSockaddr;
370 SOCKETADDRESS_COPY(&curr->brdcast, sock);
371 curr->brdcast.him4.sin_addr.s_addr |= htonl((0xffffffff >> curr->mask));
372 }
373 prefix = prefix->Next;
374 }
375 count ++;
376 }
377 uni_addr = uni_addr->Next;
378 }
379 /* Anycast */
380 any_addr = ptr->FirstAnycastAddress;
381 while (any_addr != NULL) {
382 curr = (netaddr *)calloc (1, sizeof (netaddr));
383 if (curr == 0) {
384 return -1;
385 }
386 if (start == NULL) {
387 start = curr;
388 }
389 if (prev != NULL) {
390 prev->next = curr;
391 }
392 prev = curr;
393 sock = any_addr->Address.lpSockaddr;
394 SOCKETADDRESS_COPY (&curr->addr, sock);
395 count ++;
396 any_addr = any_addr->Next;
397 }
398 if (*netaddrPP == NULL) {
399 *netaddrPP = start;
400 }
401 return count;
402}
403
404/*
405 * Create a NetworkInterface object, populate the name and index, and
406 * populate the InetAddress array based on the IP addresses for this
407 * interface.
408 */
409static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
410{
411 jobject netifObj;
412 jobject name, displayName;
413 jobjectArray addrArr, bindsArr, childArr;
414 netaddr *addrs;
415 jint addr_index;
416 int netaddrCount=ifs->naddrs;
417 netaddr *netaddrP=ifs->addrs;
418 jint bind_index;
419
420 /*
421 * Create a NetworkInterface object and populate it
422 */
423 netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
424 name = (*env)->NewStringUTF(env, ifs->name);
425 if (ifs->dNameIsUnicode) {
426 displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, wcslen ((PWCHAR)ifs->displayName));
427 } else {
428 displayName = (*env)->NewStringUTF(env, ifs->displayName);
429 }
430 if (netifObj == NULL || name == NULL || displayName == NULL) {
431 return NULL;
432 }
433 (*env)->SetObjectField(env, netifObj, ni_nameID, name);
434 (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);
435 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
436
437 /*
438 * Get the IP addresses for this interface if necessary
439 * Note that 0 is a valid number of addresses.
440 */
441 if (netaddrCount < 0) {
442 netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
443 if ((*env)->ExceptionOccurred(env)) {
444 free_netaddr(netaddrP);
445 return NULL;
446 }
447 }
448
449 addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL);
450 if (addrArr == NULL) {
451 return NULL;
452 }
453
454 bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);
455 if (bindsArr == NULL) {
456 free_netaddr(netaddrP);
457 return NULL;
458 }
459
460 addrs = netaddrP;
461 addr_index = 0;
462 bind_index = 0;
463 while (addrs != NULL) {
464 jobject iaObj, ia2Obj;
465 jobject ibObj = NULL;
466 if (addrs->addr.him.sa_family == AF_INET) {
467 iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
468 if (iaObj == NULL) {
469 return NULL;
470 }
471 /* default ctor will set family to AF_INET */
472
473 (*env)->SetIntField(env, iaObj, ni_iaAddr, ntohl(addrs->addr.him4.sin_addr.s_addr));
474
475 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
476 if (ibObj == NULL) {
477 free_netaddr(netaddrP);
478 return NULL;
479 }
480 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
481 ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
482 if (ia2Obj == NULL) {
483 free_netaddr(netaddrP);
484 return NULL;
485 }
486 (*env)->SetIntField(env, ia2Obj, ni_iaAddr,
487 ntohl(addrs->brdcast.him4.sin_addr.s_addr));
488 (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
489 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
490 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
491 } else /* AF_INET6 */ {
492 int scope;
493 iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
494 if (iaObj) {
495 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
496 if (ipaddress == NULL) {
497 return NULL;
498 }
499 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
500 (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
501 scope = addrs->addr.him6.sin6_scope_id;
502 if (scope != 0) { /* zero is default value, no need to set */
503 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
504 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
505 (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
506 }
507 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
508 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
509 if (ibObj == NULL) {
510 free_netaddr(netaddrP);
511 return NULL;
512 }
513 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
514 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
515 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
516 }
517 }
518 (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);
519 addrs = addrs->next;
520 addr_index++;
521 }
522 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
523 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);
524
525 /*
526 * Windows doesn't have virtual interfaces, so child array
527 * is always empty.
528 */
529 childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);
530 if (childArr == NULL) {
531 return NULL;
532 }
533 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
534
535 /* return the NetworkInterface */
536 return netifObj;
537}
538
539JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
540 (JNIEnv *env, jclass cls, jstring name)
541{
542 netif *ifList, *curr;
543 jboolean isCopy;
544 const char *name_utf;
545 jobject netifObj = NULL;
546
547 if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
548 return NULL;
549 }
550
551 /* get the name as a C string */
552 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
553
554 /* Search by name */
555 curr = ifList;
556 while (curr != NULL) {
557 if (strcmp(name_utf, curr->name) == 0) {
558 break;
559 }
560 curr = curr->next;
561 }
562
563 /* if found create a NetworkInterface */
564 if (curr != NULL) {;
565 netifObj = createNetworkInterfaceXP(env, curr);
566 }
567
568 /* release the UTF string */
569 (*env)->ReleaseStringUTFChars(env, name, name_utf);
570
571 /* release the interface list */
572 free_netif(ifList);
573
574 return netifObj;
575}
576
577/*
578 * Class: NetworkInterface
579 * Method: getByIndex
580 * Signature: (I)LNetworkInterface;
581 */
582JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex_XP
583 (JNIEnv *env, jclass cls, jint index)
584{
585 netif *ifList, *curr;
586 jobject netifObj = NULL;
587
588 if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
589 return NULL;
590 }
591
592 /* search by index */
593 curr = ifList;
594 while (curr != NULL) {
595 if (index == curr->index) {
596 break;
597 }
598 curr = curr->next;
599 }
600
601 /* if found create a NetworkInterface */
602 if (curr != NULL) {
603 netifObj = createNetworkInterfaceXP(env, curr);
604 }
605
606 /* release the interface list */
607 free_netif(ifList);
608
609 return netifObj;
610}
611
612/*
613 * Class: java_net_NetworkInterface
614 * Method: getByInetAddress0
615 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
616 */
617JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP
618 (JNIEnv *env, jclass cls, jobject iaObj)
619{
620 netif *ifList, *curr;
621 jobject netifObj = NULL;
622
623 /* get the list of interfaces */
624 if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
625 return NULL;
626 }
627
628 /*
629 * Enumerate the addresses on each interface until we find a
630 * matching address.
631 */
632 curr = ifList;
633 while (curr != NULL) {
634 netaddr *addrList = curr->addrs;
635 netaddr *addrP;
636
637 /* iterate through each address */
638 addrP = addrList;
639
640 while (addrP != NULL) {
641 if (NET_SockaddrEqualsInetAddress(env,
642 (struct sockaddr*)&addrP->addr, iaObj)) {
643 break;
644 }
645 addrP = addrP->next;
646 }
647
648 /*
649 * Address matched so create NetworkInterface for this interface
650 * and address list.
651 */
652 if (addrP != NULL) {
653 netifObj = createNetworkInterfaceXP(env, curr);
654 break;
655 }
656
657 /* on next interface */
658 curr = curr->next;
659 }
660
661 /* release the interface list */
662 free_netif(ifList);
663
664 return netifObj;
665}
666
667/*
668 * Class: java_net_NetworkInterface
669 * Method: getAll
670 * Signature: ()[Ljava/net/NetworkInterface;
671 */
672JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP
673 (JNIEnv *env, jclass cls)
674{
675 int count;
676 netif *ifList, *curr;
677 jobjectArray netIFArr;
678 jint arr_index;
679
680 /*
681 * Get list of interfaces
682 */
683 count = getAllInterfacesAndAddresses (env, &ifList);
684 if (count < 0) {
685 return NULL;
686 }
687
688 /* allocate a NetworkInterface array */
689 netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);
690 if (netIFArr == NULL) {
691 return NULL;
692 }
693
694 /*
695 * Iterate through the interfaces, create a NetworkInterface instance
696 * for each array element and populate the object.
697 */
698 curr = ifList;
699 arr_index = 0;
700 while (curr != NULL) {
701 jobject netifObj;
702
703 netifObj = createNetworkInterfaceXP(env, curr);
704 if (netifObj == NULL) {
705 return NULL;
706 }
707
708 /* put the NetworkInterface into the array */
709 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
710 curr = curr->next;
711 }
712
713 /* release the interface list */
714 free_netif(ifList);
715
716 return netIFArr;
717}
718
719/*
720 * Class: java_net_NetworkInterface
721 * Method: supportsMulticast0
722 * Signature: (Ljava/lang/String;I)Z
723 */
724JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP
725 (JNIEnv *env, jclass cls, jstring name, jint index) {
726 IP_ADAPTER_ADDRESSES *ptr;
727 jboolean val = JNI_TRUE;
728
729 ptr = getAdapter(env, index);
730 if (ptr != NULL) {
731 val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE;
732 free(ptr);
733 }
734 return val;
735}
736
737/*
738 * Class: java_net_NetworkInterface
739 * Method: isUp0
740 * Signature: (Ljava/lang/String;I)Z
741 */
742JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP
743 (JNIEnv *env, jclass cls, jstring name, jint index) {
744 IP_ADAPTER_ADDRESSES *ptr;
745 jboolean val = JNI_FALSE;
746
747 ptr = getAdapter(env, index);
748 if (ptr != NULL) {
749 val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE;
750 free(ptr);
751 }
752 return val;
753}
754
755/*
756 * Class: java_net_NetworkInterface
757 * Method: getMacAddr0
758 * Signature: (Ljava/lang/String;I)Z
759 */
760JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP
761 (JNIEnv *env, jclass cls, jstring name, jint index) {
762 IP_ADAPTER_ADDRESSES *ptr;
763 jbyteArray ret = NULL;
764 int len;
765
766 ptr = getAdapter(env, index);
767 if (ptr != NULL) {
768 len = ptr->PhysicalAddressLength;
769 ret = (*env)->NewByteArray(env, len);
770 if (!IS_NULL(ret)) {
771 (*env)->SetByteArrayRegion(env, ret, 0, len,
772 (jbyte*) ptr->PhysicalAddress);
773 }
774 free(ptr);
775 }
776 return ret;
777}
778
779/*
780 * Class: java_net_NetworkInterface
781 * Method: getMTU0
782 * Signature: ([bLjava/lang/String;I)I
783 */
784JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP
785 (JNIEnv *env, jclass cls, jstring name, jint index) {
786 IP_ADAPTER_ADDRESSES *ptr;
787 jint ret = -1;
788
789 ptr = getAdapter(env, index);
790 if (ptr != NULL) {
791 ret = ptr->Mtu;
792 free(ptr);
793 }
794 return ret;
795}
796
797/*
798 * Class: java_net_NetworkInterface
799 * Method: isLoopback0
800 * Signature: (Ljava/lang/String;I)Z
801 */
802JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP
803 (JNIEnv *env, jclass cls, jstring name, jint index) {
804 IP_ADAPTER_ADDRESSES *ptr;
805 jboolean val = JNI_FALSE;
806
807 ptr = getAdapter(env, index);
808 if (ptr != NULL) {
809 val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE;
810 free(ptr);
811 }
812 return val;
813}
814
815/*
816 * Class: java_net_NetworkInterface
817 * Method: isP2P0
818 * Signature: (Ljava/lang/String;I)Z
819 */
820JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP
821 (JNIEnv *env, jclass cls, jstring name, jint index) {
822 IP_ADAPTER_ADDRESSES *ptr;
823 jboolean val = JNI_FALSE;
824
825 ptr = getAdapter(env, index);
826 if (ptr != NULL) {
827 if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP ||
828 ptr->IfType == IF_TYPE_TUNNEL) {
829 val = JNI_TRUE;
830 }
831 free(ptr);
832 }
833 return val;
834}