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