Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libnet/NetworkInterface.c
41119 views
1
/*
2
* Copyright (c) 2000, 2020, 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 <arpa/inet.h>
26
#include <errno.h>
27
#include <net/if.h>
28
#ifndef TARGET_IOS
29
#include <net/if_arp.h>
30
#endif
31
#include <stdlib.h>
32
#include <string.h>
33
#include <sys/ioctl.h>
34
35
#if defined(_AIX)
36
#include <netinet/in6_var.h>
37
#include <sys/ndd_var.h>
38
#include <sys/kinfo.h>
39
#include <strings.h>
40
#endif
41
42
#if defined(_ALLBSD_SOURCE)
43
#include <net/ethernet.h>
44
#include <net/if_dl.h>
45
#include <ifaddrs.h>
46
#endif
47
48
#include "net_util.h"
49
50
#include "java_net_InetAddress.h"
51
52
#if defined(__linux__)
53
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
54
#endif
55
56
#ifdef LIFNAMSIZ
57
#define IFNAMESIZE LIFNAMSIZ
58
#else
59
#define IFNAMESIZE IFNAMSIZ
60
#endif
61
62
#define CHECKED_MALLOC3(_pointer, _type, _size) \
63
do { \
64
_pointer = (_type)malloc(_size); \
65
if (_pointer == NULL) { \
66
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
67
return ifs; /* return untouched list */ \
68
} \
69
} while(0)
70
71
typedef struct _netaddr {
72
struct sockaddr *addr;
73
struct sockaddr *brdcast;
74
short mask;
75
int family; /* to make searches simple */
76
struct _netaddr *next;
77
} netaddr;
78
79
typedef struct _netif {
80
char *name;
81
int index;
82
char virtual;
83
netaddr *addr;
84
struct _netif *childs;
85
struct _netif *next;
86
} netif;
87
88
/************************************************************************
89
* NetworkInterface
90
*/
91
92
#include "java_net_NetworkInterface.h"
93
94
/************************************************************************
95
* NetworkInterface
96
*/
97
jclass ni_class;
98
jfieldID ni_nameID;
99
jfieldID ni_indexID;
100
jfieldID ni_descID;
101
jfieldID ni_addrsID;
102
jfieldID ni_bindsID;
103
jfieldID ni_virutalID;
104
jfieldID ni_childsID;
105
jfieldID ni_parentID;
106
jfieldID ni_defaultIndexID;
107
jmethodID ni_ctrID;
108
109
static jclass ni_ibcls;
110
static jmethodID ni_ibctrID;
111
static jfieldID ni_ibaddressID;
112
static jfieldID ni_ib4broadcastID;
113
static jfieldID ni_ib4maskID;
114
115
/** Private methods declarations **/
116
static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
117
static int getFlags0(JNIEnv *env, jstring ifname);
118
119
static netif *enumInterfaces(JNIEnv *env);
120
static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
121
static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
122
123
static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
124
struct sockaddr *ifr_addrP,
125
struct sockaddr *ifr_broadaddrP,
126
int family, short prefix);
127
static void freeif(netif *ifs);
128
129
static int openSocket(JNIEnv *env, int proto);
130
static int openSocketWithFallback(JNIEnv *env, const char *ifname);
131
132
static short translateIPv4AddressToPrefix(struct sockaddr_in *addr);
133
static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr);
134
135
static int getIndex(int sock, const char *ifname);
136
static int getFlags(int sock, const char *ifname, int *flags);
137
static int getMacAddress(JNIEnv *env, const char *ifname,
138
const struct in_addr *addr, unsigned char *buf);
139
static int getMTU(JNIEnv *env, int sock, const char *ifname);
140
141
/******************* Java entry points *****************************/
142
143
/*
144
* Class: java_net_NetworkInterface
145
* Method: init
146
* Signature: ()V
147
*/
148
JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init
149
(JNIEnv *env, jclass cls)
150
{
151
ni_class = (*env)->FindClass(env, "java/net/NetworkInterface");
152
CHECK_NULL(ni_class);
153
ni_class = (*env)->NewGlobalRef(env, ni_class);
154
CHECK_NULL(ni_class);
155
ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");
156
CHECK_NULL(ni_nameID);
157
ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
158
CHECK_NULL(ni_indexID);
159
ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs",
160
"[Ljava/net/InetAddress;");
161
CHECK_NULL(ni_addrsID);
162
ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings",
163
"[Ljava/net/InterfaceAddress;");
164
CHECK_NULL(ni_bindsID);
165
ni_descID = (*env)->GetFieldID(env, ni_class, "displayName",
166
"Ljava/lang/String;");
167
CHECK_NULL(ni_descID);
168
ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
169
CHECK_NULL(ni_virutalID);
170
ni_childsID = (*env)->GetFieldID(env, ni_class, "childs",
171
"[Ljava/net/NetworkInterface;");
172
CHECK_NULL(ni_childsID);
173
ni_parentID = (*env)->GetFieldID(env, ni_class, "parent",
174
"Ljava/net/NetworkInterface;");
175
CHECK_NULL(ni_parentID);
176
ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
177
CHECK_NULL(ni_ctrID);
178
ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
179
CHECK_NULL(ni_ibcls);
180
ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
181
CHECK_NULL(ni_ibcls);
182
ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
183
CHECK_NULL(ni_ibctrID);
184
ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address",
185
"Ljava/net/InetAddress;");
186
CHECK_NULL(ni_ibaddressID);
187
ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast",
188
"Ljava/net/Inet4Address;");
189
CHECK_NULL(ni_ib4broadcastID);
190
ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
191
CHECK_NULL(ni_ib4maskID);
192
ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex",
193
"I");
194
CHECK_NULL(ni_defaultIndexID);
195
initInetAddressIDs(env);
196
}
197
198
/*
199
* Class: java_net_NetworkInterface
200
* Method: getByName0
201
* Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
202
*/
203
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
204
(JNIEnv *env, jclass cls, jstring name)
205
{
206
netif *ifs, *curr;
207
jboolean isCopy;
208
const char* name_utf;
209
char *colonP;
210
jobject obj = NULL;
211
212
if (name != NULL) {
213
name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
214
} else {
215
JNU_ThrowNullPointerException(env, "network interface name is NULL");
216
return NULL;
217
}
218
219
if (name_utf == NULL) {
220
if (!(*env)->ExceptionCheck(env))
221
JNU_ThrowOutOfMemoryError(env, NULL);
222
return NULL;
223
}
224
225
ifs = enumInterfaces(env);
226
if (ifs == NULL) {
227
(*env)->ReleaseStringUTFChars(env, name, name_utf);
228
return NULL;
229
}
230
231
// search the list of interfaces based on name,
232
// if it is virtual sub interface search with parent first.
233
colonP = strchr(name_utf, ':');
234
size_t limit = colonP != NULL ? (size_t)(colonP - name_utf) : strlen(name_utf);
235
curr = ifs;
236
while (curr != NULL) {
237
if (strlen(curr->name) == limit && memcmp(name_utf, curr->name, limit) == 0) {
238
break;
239
}
240
curr = curr->next;
241
}
242
243
// search the child list
244
if (colonP != NULL && curr != NULL) {
245
curr = curr->childs;
246
while (curr != NULL) {
247
if (strcmp(name_utf, curr->name) == 0) {
248
break;
249
}
250
curr = curr->next;
251
}
252
}
253
254
// if found create a NetworkInterface
255
if (curr != NULL) {
256
obj = createNetworkInterface(env, curr);
257
}
258
259
// release the UTF string and interface list
260
(*env)->ReleaseStringUTFChars(env, name, name_utf);
261
freeif(ifs);
262
263
return obj;
264
}
265
266
/*
267
* Class: java_net_NetworkInterface
268
* Method: getByIndex0
269
* Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
270
*/
271
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
272
(JNIEnv *env, jclass cls, jint index)
273
{
274
netif *ifs, *curr;
275
jobject obj = NULL;
276
277
if (index <= 0) {
278
return NULL;
279
}
280
281
ifs = enumInterfaces(env);
282
if (ifs == NULL) {
283
return NULL;
284
}
285
286
// search the list of interfaces based on index
287
curr = ifs;
288
while (curr != NULL) {
289
if (index == curr->index) {
290
break;
291
}
292
curr = curr->next;
293
}
294
295
// if found create a NetworkInterface
296
if (curr != NULL) {
297
obj = createNetworkInterface(env, curr);
298
}
299
300
// release the interface list
301
freeif(ifs);
302
303
return obj;
304
}
305
306
// Return the interface in ifs that iaObj is bound to, if any - otherwise NULL
307
static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) {
308
netif* curr = ifs;
309
while (curr != NULL) {
310
netaddr *addrP = curr->addr;
311
312
// iterate through each address on the interface
313
while (addrP != NULL) {
314
315
if (family == addrP->family) {
316
if (family == AF_INET) {
317
int address1 = htonl(
318
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
319
int address2 = getInetAddress_addr(env, iaObj);
320
if ((*env)->ExceptionCheck(env)) {
321
return NULL;
322
}
323
if (address1 == address2) {
324
return curr;
325
}
326
} else if (family == AF_INET6) {
327
jbyte *bytes = (jbyte *)&(
328
((struct sockaddr_in6*)addrP->addr)->sin6_addr);
329
jbyte caddr[16];
330
int i;
331
unsigned int scopeid;
332
getInet6Address_ipaddress(env, iaObj, (char *)caddr);
333
scopeid = (unsigned int)getInet6Address_scopeid(env, iaObj);
334
if (scopeid != 0 && scopeid != ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id)
335
break;
336
i = 0;
337
while (i < 16) {
338
if (caddr[i] != bytes[i]) {
339
break;
340
}
341
i++;
342
}
343
if (i >= 16) {
344
return curr;
345
}
346
}
347
}
348
349
addrP = addrP->next;
350
}
351
curr = curr->next;
352
}
353
354
return NULL;
355
}
356
357
/*
358
* Class: java_net_NetworkInterface
359
* Method: boundInetAddress0
360
* Signature: (Ljava/net/InetAddress;)boundInetAddress;
361
*/
362
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0
363
(JNIEnv *env, jclass cls, jobject iaObj)
364
{
365
netif *ifs = NULL;
366
jboolean bound = JNI_FALSE;
367
int sock;
368
369
int family = getInetAddress_family(env, iaObj);
370
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
371
372
if (family == java_net_InetAddress_IPv4) {
373
family = AF_INET;
374
} else if (family == java_net_InetAddress_IPv6) {
375
family = AF_INET6;
376
} else {
377
return JNI_FALSE; // Invalid family
378
}
379
380
if (family == AF_INET) {
381
sock = openSocket(env, AF_INET);
382
if (sock < 0 && (*env)->ExceptionOccurred(env)) {
383
return JNI_FALSE;
384
}
385
386
// enumerate IPv4 addresses
387
if (sock >= 0) {
388
ifs = enumIPv4Interfaces(env, sock, ifs);
389
close(sock);
390
391
if ((*env)->ExceptionOccurred(env)) {
392
goto cleanup;
393
}
394
}
395
if (find_bound_interface(env, ifs, iaObj, family) != NULL)
396
bound = JNI_TRUE;
397
} else if (ipv6_available()) {
398
// If IPv6 is available then enumerate IPv6 addresses.
399
// User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
400
// so we have to call ipv6_available()
401
sock = openSocket(env, AF_INET6);
402
if (sock < 0) {
403
return JNI_FALSE;
404
}
405
406
ifs = enumIPv6Interfaces(env, sock, ifs);
407
close(sock);
408
409
if ((*env)->ExceptionOccurred(env)) {
410
goto cleanup;
411
}
412
413
if (find_bound_interface(env, ifs, iaObj, family) != NULL)
414
bound = JNI_TRUE;
415
}
416
417
cleanup:
418
freeif(ifs);
419
420
return bound;
421
}
422
423
/*
424
* Class: java_net_NetworkInterface
425
* Method: getByInetAddress0
426
* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
427
*/
428
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
429
(JNIEnv *env, jclass cls, jobject iaObj)
430
{
431
netif *ifs, *curr;
432
jobject obj = NULL;
433
int family = getInetAddress_family(env, iaObj);
434
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
435
436
if (family == java_net_InetAddress_IPv4) {
437
family = AF_INET;
438
} else if (family == java_net_InetAddress_IPv6) {
439
family = AF_INET6;
440
} else {
441
return NULL; // Invalid family
442
}
443
ifs = enumInterfaces(env);
444
if (ifs == NULL) {
445
return NULL;
446
}
447
448
curr = find_bound_interface(env, ifs, iaObj, family);
449
450
// if found create a NetworkInterface
451
if (curr != NULL) {
452
obj = createNetworkInterface(env, curr);
453
}
454
455
// release the interface list
456
freeif(ifs);
457
458
return obj;
459
}
460
461
/*
462
* Class: java_net_NetworkInterface
463
* Method: getAll
464
* Signature: ()[Ljava/net/NetworkInterface;
465
*/
466
JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
467
(JNIEnv *env, jclass cls)
468
{
469
netif *ifs, *curr;
470
jobjectArray netIFArr;
471
jint arr_index, ifCount;
472
473
ifs = enumInterfaces(env);
474
if (ifs == NULL) {
475
return NULL;
476
}
477
478
// count the interfaces
479
ifCount = 0;
480
curr = ifs;
481
while (curr != NULL) {
482
ifCount++;
483
curr = curr->next;
484
}
485
486
// allocate a NetworkInterface array
487
netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
488
if (netIFArr == NULL) {
489
freeif(ifs);
490
return NULL;
491
}
492
493
// iterate through the interfaces, create a NetworkInterface instance
494
// for each array element and populate the object
495
curr = ifs;
496
arr_index = 0;
497
while (curr != NULL) {
498
jobject netifObj;
499
500
netifObj = createNetworkInterface(env, curr);
501
if (netifObj == NULL) {
502
freeif(ifs);
503
return NULL;
504
}
505
506
// put the NetworkInterface into the array
507
(*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
508
(*env)->DeleteLocalRef(env, netifObj);
509
510
curr = curr->next;
511
}
512
513
// release the interface list
514
freeif(ifs);
515
516
return netIFArr;
517
}
518
519
/*
520
* Class: java_net_NetworkInterface
521
* Method: isUp0
522
* Signature: (Ljava/lang/String;I)Z
523
*/
524
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
525
(JNIEnv *env, jclass cls, jstring name, jint index)
526
{
527
int ret = getFlags0(env, name);
528
return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
529
}
530
531
/*
532
* Class: java_net_NetworkInterface
533
* Method: isP2P0
534
* Signature: (Ljava/lang/String;I)Z
535
*/
536
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
537
(JNIEnv *env, jclass cls, jstring name, jint index)
538
{
539
int ret = getFlags0(env, name);
540
return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE;
541
}
542
543
/*
544
* Class: java_net_NetworkInterface
545
* Method: isLoopback0
546
* Signature: (Ljava/lang/String;I)Z
547
*/
548
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
549
(JNIEnv *env, jclass cls, jstring name, jint index)
550
{
551
int ret = getFlags0(env, name);
552
return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE;
553
}
554
555
/*
556
* Class: java_net_NetworkInterface
557
* Method: supportsMulticast0
558
* Signature: (Ljava/lang/String;I)Z
559
*/
560
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
561
(JNIEnv *env, jclass cls, jstring name, jint index)
562
{
563
int ret = getFlags0(env, name);
564
return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
565
}
566
567
/*
568
* Class: java_net_NetworkInterface
569
* Method: getMacAddr0
570
* Signature: ([bLjava/lang/String;I)[b
571
*/
572
JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
573
(JNIEnv *env, jclass cls, jbyteArray addrArray, jstring name, jint index)
574
{
575
jint addr;
576
jbyte caddr[4];
577
struct in_addr iaddr;
578
jbyteArray ret = NULL;
579
unsigned char mac[16];
580
int len;
581
jboolean isCopy;
582
const char *name_utf;
583
584
if (name != NULL) {
585
name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
586
} else {
587
JNU_ThrowNullPointerException(env, "network interface name is NULL");
588
return NULL;
589
}
590
591
if (name_utf == NULL) {
592
if (!(*env)->ExceptionCheck(env))
593
JNU_ThrowOutOfMemoryError(env, NULL);
594
return NULL;
595
}
596
597
if (!IS_NULL(addrArray)) {
598
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
599
addr = ((caddr[0]<<24) & 0xff000000);
600
addr |= ((caddr[1] <<16) & 0xff0000);
601
addr |= ((caddr[2] <<8) & 0xff00);
602
addr |= (caddr[3] & 0xff);
603
iaddr.s_addr = htonl(addr);
604
len = getMacAddress(env, name_utf, &iaddr, mac);
605
} else {
606
len = getMacAddress(env, name_utf, NULL, mac);
607
}
608
609
if (len > 0) {
610
ret = (*env)->NewByteArray(env, len);
611
if (!IS_NULL(ret)) {
612
(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *)(mac));
613
}
614
}
615
616
// release the UTF string and interface list
617
(*env)->ReleaseStringUTFChars(env, name, name_utf);
618
619
return ret;
620
}
621
622
/*
623
* Class: java_net_NetworkInterface
624
* Method: getMTU0
625
* Signature: ([bLjava/lang/String;I)I
626
*/
627
JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
628
(JNIEnv *env, jclass cls, jstring name, jint index)
629
{
630
jboolean isCopy;
631
int sock, ret = -1;
632
const char* name_utf = NULL;
633
634
if (name != NULL) {
635
name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
636
} else {
637
JNU_ThrowNullPointerException(env, "network interface name is NULL");
638
return ret;
639
}
640
641
if (name_utf == NULL) {
642
if (!(*env)->ExceptionCheck(env))
643
JNU_ThrowOutOfMemoryError(env, NULL);
644
return ret;
645
}
646
647
if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
648
(*env)->ReleaseStringUTFChars(env, name, name_utf);
649
return JNI_FALSE;
650
}
651
652
ret = getMTU(env, sock, name_utf);
653
654
(*env)->ReleaseStringUTFChars(env, name, name_utf);
655
656
close(sock);
657
return ret;
658
}
659
660
/*** Private methods definitions ****/
661
662
static int getFlags0(JNIEnv *env, jstring name) {
663
jboolean isCopy;
664
int ret, sock, flags = 0;
665
const char *name_utf;
666
667
if (name != NULL) {
668
name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
669
} else {
670
JNU_ThrowNullPointerException(env, "network interface name is NULL");
671
return -1;
672
}
673
674
if (name_utf == NULL) {
675
if (!(*env)->ExceptionCheck(env))
676
JNU_ThrowOutOfMemoryError(env, NULL);
677
return -1;
678
}
679
if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
680
(*env)->ReleaseStringUTFChars(env, name, name_utf);
681
return -1;
682
}
683
684
ret = getFlags(sock, name_utf, &flags);
685
686
close(sock);
687
(*env)->ReleaseStringUTFChars(env, name, name_utf);
688
689
if (ret < 0) {
690
JNU_ThrowByNameWithMessageAndLastError
691
(env, JNU_JAVANETPKG "SocketException", "getFlags() failed");
692
return -1;
693
}
694
695
return flags;
696
}
697
698
/*
699
* Creates a NetworkInterface object, populates the name, the index, and
700
* populates the InetAddress array based on the IP addresses for this
701
* interface.
702
*/
703
static jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
704
jobject netifObj;
705
jobject name;
706
jobjectArray addrArr;
707
jobjectArray bindArr;
708
jobjectArray childArr;
709
netaddr *addrs;
710
jint addr_index, addr_count, bind_index;
711
jint child_count, child_index;
712
netaddr *addrP;
713
netif *childP;
714
jobject tmp;
715
716
// create a NetworkInterface object and populate it
717
netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
718
CHECK_NULL_RETURN(netifObj, NULL);
719
name = (*env)->NewStringUTF(env, ifs->name);
720
CHECK_NULL_RETURN(name, NULL);
721
(*env)->SetObjectField(env, netifObj, ni_nameID, name);
722
(*env)->SetObjectField(env, netifObj, ni_descID, name);
723
(*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
724
(*env)->SetBooleanField(env, netifObj, ni_virutalID,
725
ifs->virtual ? JNI_TRUE : JNI_FALSE);
726
727
// count the number of addresses on this interface
728
addr_count = 0;
729
addrP = ifs->addr;
730
while (addrP != NULL) {
731
addr_count++;
732
addrP = addrP->next;
733
}
734
735
// create the array of InetAddresses
736
addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL);
737
if (addrArr == NULL) {
738
return NULL;
739
}
740
741
bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
742
if (bindArr == NULL) {
743
return NULL;
744
}
745
addrP = ifs->addr;
746
addr_index = 0;
747
bind_index = 0;
748
while (addrP != NULL) {
749
jobject iaObj = NULL;
750
jobject ibObj = NULL;
751
752
if (addrP->family == AF_INET) {
753
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
754
if (iaObj) {
755
setInetAddress_addr(env, iaObj, htonl(
756
((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
757
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
758
} else {
759
return NULL;
760
}
761
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
762
if (ibObj) {
763
(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
764
if (addrP->brdcast) {
765
jobject ia2Obj = NULL;
766
ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
767
if (ia2Obj) {
768
setInetAddress_addr(env, ia2Obj, htonl(
769
((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
770
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
771
(*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
772
(*env)->DeleteLocalRef(env, ia2Obj);
773
} else {
774
return NULL;
775
}
776
}
777
(*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
778
(*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
779
(*env)->DeleteLocalRef(env, ibObj);
780
} else {
781
return NULL;
782
}
783
}
784
if (addrP->family == AF_INET6) {
785
int scope=0;
786
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
787
if (iaObj) {
788
jboolean ret = setInet6Address_ipaddress(env, iaObj,
789
(char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
790
if (ret == JNI_FALSE) {
791
return NULL;
792
}
793
794
scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
795
796
if (scope != 0) { /* zero is default value, no need to set */
797
setInet6Address_scopeid(env, iaObj, scope);
798
setInet6Address_scopeifname(env, iaObj, netifObj);
799
}
800
} else {
801
return NULL;
802
}
803
ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
804
if (ibObj) {
805
(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
806
(*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
807
(*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
808
(*env)->DeleteLocalRef(env, ibObj);
809
} else {
810
return NULL;
811
}
812
}
813
814
(*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
815
(*env)->DeleteLocalRef(env, iaObj);
816
addrP = addrP->next;
817
}
818
819
// see if there is any virtual interface attached to this one.
820
child_count = 0;
821
childP = ifs->childs;
822
while (childP) {
823
child_count++;
824
childP = childP->next;
825
}
826
827
childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
828
if (childArr == NULL) {
829
return NULL;
830
}
831
832
// create the NetworkInterface instances for the sub-interfaces as well
833
child_index = 0;
834
childP = ifs->childs;
835
while(childP) {
836
tmp = createNetworkInterface(env, childP);
837
if (tmp == NULL) {
838
return NULL;
839
}
840
(*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
841
(*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
842
childP = childP->next;
843
}
844
(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
845
(*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
846
(*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
847
848
(*env)->DeleteLocalRef(env, name);
849
(*env)->DeleteLocalRef(env, addrArr);
850
(*env)->DeleteLocalRef(env, bindArr);
851
(*env)->DeleteLocalRef(env, childArr);
852
853
// return the NetworkInterface
854
return netifObj;
855
}
856
857
/*
858
* Enumerates all interfaces
859
*/
860
static netif *enumInterfaces(JNIEnv *env) {
861
netif *ifs = NULL;
862
int sock;
863
864
sock = openSocket(env, AF_INET);
865
if (sock < 0 && (*env)->ExceptionOccurred(env)) {
866
return NULL;
867
}
868
869
// enumerate IPv4 addresses
870
if (sock >= 0) {
871
ifs = enumIPv4Interfaces(env, sock, ifs);
872
close(sock);
873
874
if ((*env)->ExceptionOccurred(env)) {
875
freeif(ifs);
876
return NULL;
877
}
878
}
879
880
// If IPv6 is available then enumerate IPv6 addresses.
881
// User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
882
// so we have to call ipv6_available()
883
if (ipv6_available()) {
884
sock = openSocket(env, AF_INET6);
885
if (sock < 0) {
886
freeif(ifs);
887
return NULL;
888
}
889
890
ifs = enumIPv6Interfaces(env, sock, ifs);
891
close(sock);
892
893
if ((*env)->ExceptionOccurred(env)) {
894
freeif(ifs);
895
return NULL;
896
}
897
}
898
899
return ifs;
900
}
901
902
/*
903
* Frees an interface list (including any attached addresses).
904
*/
905
static void freeif(netif *ifs) {
906
netif *currif = ifs;
907
netif *child = NULL;
908
909
while (currif != NULL) {
910
netaddr *addrP = currif->addr;
911
while (addrP != NULL) {
912
netaddr *next = addrP->next;
913
free(addrP);
914
addrP = next;
915
}
916
917
// don't forget to free the sub-interfaces
918
if (currif->childs != NULL) {
919
freeif(currif->childs);
920
}
921
922
ifs = currif->next;
923
free(currif);
924
currif = ifs;
925
}
926
}
927
928
static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
929
struct sockaddr *ifr_addrP,
930
struct sockaddr *ifr_broadaddrP,
931
int family, short prefix)
932
{
933
netif *currif = ifs, *parent;
934
netaddr *addrP;
935
char name[IFNAMESIZE], vname[IFNAMESIZE];
936
char *name_colonP;
937
int isVirtual = 0;
938
int addr_size;
939
940
// If the interface name is a logical interface then we remove the unit
941
// number so that we have the physical interface (eg: hme0:1 -> hme0).
942
// NetworkInterface currently doesn't have any concept of physical vs.
943
// logical interfaces.
944
strncpy(name, if_name, IFNAMESIZE);
945
name[IFNAMESIZE - 1] = '\0';
946
*vname = 0;
947
948
// Create and populate the netaddr node. If allocation fails
949
// return an un-updated list.
950
951
// Allocate for addr and brdcast at once
952
953
addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
954
: sizeof(struct sockaddr_in6);
955
956
CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
957
addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
958
memcpy(addrP->addr, ifr_addrP, addr_size);
959
960
addrP->family = family;
961
addrP->mask = prefix;
962
addrP->next = 0;
963
964
// for IPv4 add broadcast address
965
if (family == AF_INET && ifr_broadaddrP != NULL) {
966
addrP->brdcast = (struct sockaddr *)
967
((char *)addrP + sizeof(netaddr) + addr_size);
968
memcpy(addrP->brdcast, ifr_broadaddrP, addr_size);
969
} else {
970
addrP->brdcast = NULL;
971
}
972
973
// Deal with virtual interface with colon notation e.g. eth0:1
974
name_colonP = strchr(name, ':');
975
if (name_colonP != NULL) {
976
int flags = 0;
977
// This is a virtual interface. If we are able to access the parent
978
// we need to create a new entry if it doesn't exist yet *and* update
979
// the 'parent' interface with the new records.
980
*name_colonP = 0;
981
if (getFlags(sock, name, &flags) < 0 || flags < 0) {
982
// failed to access parent interface do not create parent.
983
// We are a virtual interface with no parent.
984
isVirtual = 1;
985
*name_colonP = ':';
986
} else {
987
// Got access to parent, so create it if necessary.
988
// Save original name to vname and truncate name by ':'
989
memcpy(vname, name, sizeof(vname));
990
vname[name_colonP - name] = ':';
991
}
992
}
993
994
// Check if this is a "new" interface. Use the interface name for
995
// matching because index isn't supported on Solaris 2.6 & 7.
996
while (currif != NULL) {
997
if (strcmp(name, currif->name) == 0) {
998
break;
999
}
1000
currif = currif->next;
1001
}
1002
1003
// If "new" then create a netif structure and insert it into the list.
1004
if (currif == NULL) {
1005
CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE);
1006
currif->name = (char *)currif + sizeof(netif);
1007
strncpy(currif->name, name, IFNAMESIZE);
1008
currif->name[IFNAMESIZE - 1] = '\0';
1009
currif->index = getIndex(sock, name);
1010
currif->addr = NULL;
1011
currif->childs = NULL;
1012
currif->virtual = isVirtual;
1013
currif->next = ifs;
1014
ifs = currif;
1015
}
1016
1017
// Finally insert the address on the interface
1018
addrP->next = currif->addr;
1019
currif->addr = addrP;
1020
1021
parent = currif;
1022
1023
// Deal with the virtual interface now.
1024
if (vname[0]) {
1025
netaddr *tmpaddr;
1026
1027
currif = parent->childs;
1028
1029
while (currif != NULL) {
1030
if (strcmp(vname, currif->name) == 0) {
1031
break;
1032
}
1033
currif = currif->next;
1034
}
1035
1036
if (currif == NULL) {
1037
CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE);
1038
currif->name = (char *)currif + sizeof(netif);
1039
strncpy(currif->name, vname, IFNAMESIZE);
1040
currif->name[IFNAMESIZE - 1] = '\0';
1041
currif->index = getIndex(sock, vname);
1042
currif->addr = NULL; // Need to duplicate the addr entry?
1043
currif->virtual = 1;
1044
currif->childs = NULL;
1045
currif->next = parent->childs;
1046
parent->childs = currif;
1047
}
1048
1049
CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr) + 2 * addr_size);
1050
memcpy(tmpaddr, addrP, sizeof(netaddr));
1051
if (addrP->addr != NULL) {
1052
tmpaddr->addr = (struct sockaddr *)
1053
((char*)tmpaddr + sizeof(netaddr));
1054
memcpy(tmpaddr->addr, addrP->addr, addr_size);
1055
}
1056
1057
if (addrP->brdcast != NULL) {
1058
tmpaddr->brdcast = (struct sockaddr *)
1059
((char *)tmpaddr + sizeof(netaddr) + addr_size);
1060
memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
1061
}
1062
1063
tmpaddr->next = currif->addr;
1064
currif->addr = tmpaddr;
1065
}
1066
1067
return ifs;
1068
}
1069
1070
/*
1071
* Determines the prefix value for an AF_INET subnet address.
1072
*/
1073
static short translateIPv4AddressToPrefix(struct sockaddr_in *addr) {
1074
short prefix = 0;
1075
unsigned int mask;
1076
if (addr == NULL) {
1077
return 0;
1078
}
1079
mask = ntohl(addr->sin_addr.s_addr);
1080
while (mask) {
1081
mask <<= 1;
1082
prefix++;
1083
}
1084
return prefix;
1085
}
1086
1087
/*
1088
* Determines the prefix value for an AF_INET6 subnet address.
1089
*/
1090
static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr) {
1091
short prefix = 0;
1092
u_char *addrBytes;
1093
if (addr == NULL) {
1094
return 0;
1095
}
1096
addrBytes = (u_char *)&(addr->sin6_addr);
1097
unsigned int byte, bit;
1098
1099
for (byte = 0; byte < sizeof(struct in6_addr); byte++, prefix += 8) {
1100
if (addrBytes[byte] != 0xff) {
1101
break;
1102
}
1103
}
1104
if (byte != sizeof(struct in6_addr)) {
1105
for (bit = 7; bit != 0; bit--, prefix++) {
1106
if (!(addrBytes[byte] & (1 << bit))) {
1107
break;
1108
}
1109
}
1110
for (; bit != 0; bit--) {
1111
if (addrBytes[byte] & (1 << bit)) {
1112
prefix = 0;
1113
break;
1114
}
1115
}
1116
if (prefix > 0) {
1117
byte++;
1118
for (; byte < sizeof(struct in6_addr); byte++) {
1119
if (addrBytes[byte]) {
1120
prefix = 0;
1121
}
1122
}
1123
}
1124
}
1125
1126
return prefix;
1127
}
1128
1129
/*
1130
* Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6.
1131
*/
1132
static int openSocket(JNIEnv *env, int proto) {
1133
int sock;
1134
1135
if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) {
1136
// If we lack support for this address family or protocol,
1137
// don't throw an exception.
1138
if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) {
1139
JNU_ThrowByNameWithMessageAndLastError
1140
(env, JNU_JAVANETPKG "SocketException", "Socket creation failed");
1141
}
1142
return -1;
1143
}
1144
1145
return sock;
1146
}
1147
1148
/** Linux **/
1149
#if defined(__linux__)
1150
1151
/*
1152
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
1153
* if it fails return AF_INET6 socket.
1154
*/
1155
static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1156
int sock;
1157
1158
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1159
if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
1160
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1161
JNU_ThrowByNameWithMessageAndLastError
1162
(env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1163
return -1;
1164
}
1165
} else { // errno is not NOSUPPORT
1166
JNU_ThrowByNameWithMessageAndLastError
1167
(env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1168
return -1;
1169
}
1170
}
1171
1172
// Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or
1173
// IPv6 socket regardless of type of address of an interface.
1174
return sock;
1175
}
1176
1177
/*
1178
* Enumerates and returns all IPv4 interfaces on Linux.
1179
*/
1180
static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1181
struct ifconf ifc;
1182
struct ifreq *ifreqP;
1183
char *buf = NULL;
1184
unsigned i;
1185
1186
// do a dummy SIOCGIFCONF to determine the buffer size
1187
// SIOCGIFCOUNT doesn't work
1188
ifc.ifc_buf = NULL;
1189
if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1190
JNU_ThrowByNameWithMessageAndLastError
1191
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
1192
return ifs;
1193
}
1194
1195
// call SIOCGIFCONF to enumerate the interfaces
1196
CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
1197
ifc.ifc_buf = buf;
1198
if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1199
JNU_ThrowByNameWithMessageAndLastError
1200
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
1201
free(buf);
1202
return ifs;
1203
}
1204
1205
// iterate through each interface
1206
ifreqP = ifc.ifc_req;
1207
for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) {
1208
struct sockaddr addr, broadaddr, *broadaddrP = NULL;
1209
short prefix = 0;
1210
1211
// ignore non IPv4 addresses
1212
if (ifreqP->ifr_addr.sa_family != AF_INET) {
1213
continue;
1214
}
1215
1216
// save socket address
1217
memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr));
1218
1219
// determine broadcast address, if applicable
1220
if ((ioctl(sock, SIOCGIFFLAGS, ifreqP) == 0) &&
1221
ifreqP->ifr_flags & IFF_BROADCAST) {
1222
1223
// restore socket address to ifreqP
1224
memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr));
1225
1226
if (ioctl(sock, SIOCGIFBRDADDR, ifreqP) == 0) {
1227
memcpy(&broadaddr, &(ifreqP->ifr_broadaddr),
1228
sizeof(struct sockaddr));
1229
broadaddrP = &broadaddr;
1230
}
1231
}
1232
1233
// restore socket address to ifreqP
1234
memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr));
1235
1236
// determine netmask
1237
if (ioctl(sock, SIOCGIFNETMASK, ifreqP) == 0) {
1238
prefix = translateIPv4AddressToPrefix(
1239
(struct sockaddr_in *)&(ifreqP->ifr_netmask));
1240
}
1241
1242
// add interface to the list
1243
ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1244
&addr, broadaddrP, AF_INET, prefix);
1245
1246
// in case of exception, free interface list and buffer and return NULL
1247
if ((*env)->ExceptionOccurred(env)) {
1248
free(buf);
1249
freeif(ifs);
1250
return NULL;
1251
}
1252
}
1253
1254
// free buffer
1255
free(buf);
1256
return ifs;
1257
}
1258
1259
/*
1260
* Enumerates and returns all IPv6 interfaces on Linux.
1261
*/
1262
static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1263
FILE *f;
1264
char devname[21], addr6p[8][5];
1265
int prefix, scope, dad_status, if_idx;
1266
1267
if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1268
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1269
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1270
addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1271
&if_idx, &prefix, &scope, &dad_status, devname) != EOF) {
1272
1273
char addr6[40];
1274
struct sockaddr_in6 addr;
1275
1276
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1277
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1278
addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1279
1280
memset(&addr, 0, sizeof(struct sockaddr_in6));
1281
inet_pton(AF_INET6, addr6, (void*)addr.sin6_addr.s6_addr);
1282
1283
// set scope ID to interface index
1284
addr.sin6_scope_id = if_idx;
1285
1286
// add interface to the list
1287
ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr,
1288
NULL, AF_INET6, (short)prefix);
1289
1290
// if an exception occurred then return the list as is
1291
if ((*env)->ExceptionOccurred(env)) {
1292
break;
1293
}
1294
}
1295
fclose(f);
1296
}
1297
return ifs;
1298
}
1299
1300
/*
1301
* Try to get the interface index.
1302
*/
1303
static int getIndex(int sock, const char *name) {
1304
struct ifreq if2;
1305
memset((char *)&if2, 0, sizeof(if2));
1306
strncpy(if2.ifr_name, name, sizeof(if2.ifr_name));
1307
if2.ifr_name[sizeof(if2.ifr_name) - 1] = 0;
1308
1309
if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1310
return -1;
1311
}
1312
1313
return if2.ifr_ifindex;
1314
}
1315
1316
/*
1317
* Gets the Hardware address (usually MAC address) for the named interface.
1318
* On return puts the data in buf, and returns the length, in byte, of the
1319
* MAC address. Returns -1 if there is no hardware address on that interface.
1320
*/
1321
static int getMacAddress
1322
(JNIEnv *env, const char *ifname, const struct in_addr *addr,
1323
unsigned char *buf)
1324
{
1325
struct ifreq ifr;
1326
int i, sock;
1327
1328
if ((sock = openSocketWithFallback(env, ifname)) < 0) {
1329
return -1;
1330
}
1331
1332
memset((char *)&ifr, 0, sizeof(ifr));
1333
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1334
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1335
JNU_ThrowByNameWithMessageAndLastError
1336
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed");
1337
close(sock);
1338
return -1;
1339
}
1340
1341
close(sock);
1342
memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1343
1344
// all bytes to 0 means no hardware address
1345
for (i = 0; i < IFHWADDRLEN; i++) {
1346
if (buf[i] != 0)
1347
return IFHWADDRLEN;
1348
}
1349
1350
return -1;
1351
}
1352
1353
static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1354
struct ifreq if2;
1355
memset((char *)&if2, 0, sizeof(if2));
1356
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1357
1358
if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1359
JNU_ThrowByNameWithMessageAndLastError
1360
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1361
return -1;
1362
}
1363
1364
return if2.ifr_mtu;
1365
}
1366
1367
static int getFlags(int sock, const char *ifname, int *flags) {
1368
struct ifreq if2;
1369
memset((char *)&if2, 0, sizeof(if2));
1370
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name));
1371
if2.ifr_name[sizeof(if2.ifr_name) - 1] = 0;
1372
1373
if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1374
return -1;
1375
}
1376
1377
if (sizeof(if2.ifr_flags) == sizeof(short)) {
1378
*flags = (if2.ifr_flags & 0xffff);
1379
} else {
1380
*flags = if2.ifr_flags;
1381
}
1382
return 0;
1383
}
1384
1385
#endif /* __linux__ */
1386
1387
/** AIX **/
1388
#if defined(_AIX)
1389
1390
/* seems getkerninfo is guarded by _KERNEL in the system headers */
1391
/* see net/proto_uipc.h */
1392
int getkerninfo(int, char *, int *, int32long64_t);
1393
1394
/*
1395
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
1396
* if it fails return AF_INET6 socket.
1397
*/
1398
static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1399
int sock;
1400
1401
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1402
if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
1403
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1404
JNU_ThrowByNameWithMessageAndLastError
1405
(env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1406
return -1;
1407
}
1408
} else { // errno is not NOSUPPORT
1409
JNU_ThrowByNameWithMessageAndLastError
1410
(env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1411
return -1;
1412
}
1413
}
1414
1415
return sock;
1416
}
1417
1418
/*
1419
* Enumerates and returns all IPv4 interfaces on AIX.
1420
*/
1421
static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1422
struct ifconf ifc;
1423
struct ifreq *ifreqP;
1424
char *buf = NULL;
1425
unsigned i;
1426
1427
// call SIOCGSIZIFCONF to get the size of SIOCGIFCONF buffer
1428
if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1429
JNU_ThrowByNameWithMessageAndLastError
1430
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed");
1431
return ifs;
1432
}
1433
1434
// call CSIOCGIFCONF instead of SIOCGIFCONF where interface
1435
// records will always have sizeof(struct ifreq) length.
1436
// Be aware that only IPv4 data is complete this way.
1437
CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
1438
ifc.ifc_buf = buf;
1439
if (ioctl(sock, CSIOCGIFCONF, (char *)&ifc) < 0) {
1440
JNU_ThrowByNameWithMessageAndLastError
1441
(env, JNU_JAVANETPKG "SocketException", "ioctl(CSIOCGIFCONF) failed");
1442
free(buf);
1443
return ifs;
1444
}
1445
1446
// iterate through each interface
1447
ifreqP = ifc.ifc_req;
1448
for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) {
1449
struct sockaddr addr, broadaddr, *broadaddrP = NULL;
1450
short prefix = 0;
1451
1452
// ignore non IPv4 addresses
1453
if (ifreqP->ifr_addr.sa_family != AF_INET) {
1454
continue;
1455
}
1456
1457
// save socket address
1458
memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr));
1459
1460
// determine broadcast address, if applicable
1461
if ((ioctl(sock, SIOCGIFFLAGS, ifreqP) == 0) &&
1462
ifreqP->ifr_flags & IFF_BROADCAST) {
1463
1464
// restore socket address to ifreqP
1465
memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr));
1466
1467
if (ioctl(sock, SIOCGIFBRDADDR, ifreqP) == 0) {
1468
memcpy(&broadaddr, &(ifreqP->ifr_broadaddr),
1469
sizeof(struct sockaddr));
1470
broadaddrP = &broadaddr;
1471
}
1472
}
1473
1474
// restore socket address to ifreqP
1475
memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr));
1476
1477
// determine netmask
1478
if (ioctl(sock, SIOCGIFNETMASK, ifreqP) == 0) {
1479
prefix = translateIPv4AddressToPrefix(
1480
(struct sockaddr_in *)&(ifreqP->ifr_addr));
1481
}
1482
1483
// add interface to the list
1484
ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1485
&addr, broadaddrP, AF_INET, prefix);
1486
1487
// in case of exception, free interface list and buffer and return NULL
1488
if ((*env)->ExceptionOccurred(env)) {
1489
free(buf);
1490
freeif(ifs);
1491
return NULL;
1492
}
1493
}
1494
1495
// free buffer
1496
free(buf);
1497
return ifs;
1498
}
1499
1500
/*
1501
* Enumerates and returns all IPv6 interfaces on AIX.
1502
*/
1503
static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1504
struct ifconf ifc;
1505
struct ifreq *ifreqP;
1506
char *buf, *cp, *cplimit;
1507
1508
// call SIOCGSIZIFCONF to get size for SIOCGIFCONF buffer
1509
if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
1510
JNU_ThrowByNameWithMessageAndLastError
1511
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed");
1512
return ifs;
1513
}
1514
1515
// call SIOCGIFCONF to enumerate the interfaces
1516
CHECKED_MALLOC3(buf, char *, ifc.ifc_len);
1517
ifc.ifc_buf = buf;
1518
if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
1519
JNU_ThrowByNameWithMessageAndLastError
1520
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed");
1521
free(buf);
1522
return ifs;
1523
}
1524
1525
// iterate through each interface
1526
ifreqP = ifc.ifc_req;
1527
cp = (char *)ifc.ifc_req;
1528
cplimit = cp + ifc.ifc_len;
1529
1530
for (; cp < cplimit;
1531
cp += (sizeof(ifreqP->ifr_name) +
1532
MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr))))
1533
{
1534
ifreqP = (struct ifreq *)cp;
1535
short prefix = 0;
1536
1537
// ignore non IPv6 addresses
1538
if (ifreqP->ifr_addr.sa_family != AF_INET6) {
1539
continue;
1540
}
1541
1542
// determine netmask
1543
struct in6_ifreq if6;
1544
memset((char *)&if6, 0, sizeof(if6));
1545
strncpy(if6.ifr_name, ifreqP->ifr_name, sizeof(if6.ifr_name) - 1);
1546
memcpy(&(if6.ifr_Addr), &(ifreqP->ifr_addr),
1547
sizeof(struct sockaddr_in6));
1548
if (ioctl(sock, SIOCGIFNETMASK6, (char *)&if6) >= 0) {
1549
prefix = translateIPv6AddressToPrefix(&(if6.ifr_Addr));
1550
}
1551
1552
// set scope ID to interface index
1553
((struct sockaddr_in6 *)&(ifreqP->ifr_addr))->sin6_scope_id =
1554
getIndex(sock, ifreqP->ifr_name);
1555
1556
// add interface to the list
1557
ifs = addif(env, sock, ifreqP->ifr_name, ifs,
1558
(struct sockaddr *)&(ifreqP->ifr_addr),
1559
NULL, AF_INET6, prefix);
1560
1561
// if an exception occurred then free the list
1562
if ((*env)->ExceptionOccurred(env)) {
1563
free(buf);
1564
freeif(ifs);
1565
return NULL;
1566
}
1567
}
1568
1569
// free buffer
1570
free(buf);
1571
return ifs;
1572
}
1573
1574
/*
1575
* Try to get the interface index.
1576
*/
1577
static int getIndex(int sock, const char *name) {
1578
int index = if_nametoindex(name);
1579
return (index == 0) ? -1 : index;
1580
}
1581
1582
/*
1583
* Gets the Hardware address (usually MAC address) for the named interface.
1584
* On return puts the data in buf, and returns the length, in byte, of the
1585
* MAC address. Returns -1 if there is no hardware address on that interface.
1586
*/
1587
static int getMacAddress
1588
(JNIEnv *env, const char *ifname, const struct in_addr *addr,
1589
unsigned char *buf)
1590
{
1591
int size;
1592
struct kinfo_ndd *nddp;
1593
void *end;
1594
1595
size = getkerninfo(KINFO_NDD, 0, 0, 0);
1596
if (size == 0) {
1597
return -1;
1598
}
1599
1600
if (size < 0) {
1601
perror("getkerninfo 1");
1602
return -1;
1603
}
1604
1605
nddp = (struct kinfo_ndd *)malloc(size);
1606
1607
if (!nddp) {
1608
JNU_ThrowOutOfMemoryError(env,
1609
"Network interface getMacAddress native buffer allocation failed");
1610
return -1;
1611
}
1612
1613
if (getkerninfo(KINFO_NDD, (char*) nddp, &size, 0) < 0) {
1614
perror("getkerninfo 2");
1615
free(nddp);
1616
return -1;
1617
}
1618
1619
end = (void *)nddp + size;
1620
while ((void *)nddp < end) {
1621
if (!strcmp(nddp->ndd_alias, ifname) ||
1622
!strcmp(nddp->ndd_name, ifname)) {
1623
bcopy(nddp->ndd_addr, buf, 6);
1624
free(nddp);
1625
return 6;
1626
} else {
1627
nddp++;
1628
}
1629
}
1630
1631
free(nddp);
1632
return -1;
1633
}
1634
1635
static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1636
struct ifreq if2;
1637
memset((char *)&if2, 0, sizeof(if2));
1638
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1639
1640
if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1641
JNU_ThrowByNameWithMessageAndLastError
1642
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1643
return -1;
1644
}
1645
1646
return if2.ifr_mtu;
1647
}
1648
1649
static int getFlags(int sock, const char *ifname, int *flags) {
1650
struct ifreq if2;
1651
memset((char *)&if2, 0, sizeof(if2));
1652
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1653
1654
if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1655
return -1;
1656
}
1657
1658
if (sizeof(if2.ifr_flags) == sizeof(short)) {
1659
*flags = (if2.ifr_flags & 0xffff);
1660
} else {
1661
*flags = if2.ifr_flags;
1662
}
1663
return 0;
1664
}
1665
1666
#endif /* _AIX */
1667
1668
/** BSD **/
1669
#if defined(_ALLBSD_SOURCE)
1670
1671
/*
1672
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
1673
* if it fails return AF_INET6 socket.
1674
*/
1675
static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
1676
int sock;
1677
1678
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1679
if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
1680
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1681
JNU_ThrowByNameWithMessageAndLastError
1682
(env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
1683
return -1;
1684
}
1685
} else { // errno is not NOSUPPORT
1686
JNU_ThrowByNameWithMessageAndLastError
1687
(env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
1688
return -1;
1689
}
1690
}
1691
1692
return sock;
1693
}
1694
1695
/*
1696
* Enumerates and returns all IPv4 interfaces on BSD.
1697
*/
1698
static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
1699
struct ifaddrs *ifa, *origifa;
1700
1701
if (getifaddrs(&origifa) != 0) {
1702
JNU_ThrowByNameWithMessageAndLastError
1703
(env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed");
1704
return ifs;
1705
}
1706
1707
for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1708
struct sockaddr *broadaddrP = NULL;
1709
1710
// ignore non IPv4 addresses
1711
if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
1712
continue;
1713
1714
// set ifa_broadaddr, if there is one
1715
if ((ifa->ifa_flags & IFF_POINTOPOINT) == 0 &&
1716
ifa->ifa_flags & IFF_BROADCAST) {
1717
broadaddrP = ifa->ifa_dstaddr;
1718
}
1719
1720
// add interface to the list
1721
ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr,
1722
broadaddrP, AF_INET,
1723
translateIPv4AddressToPrefix((struct sockaddr_in *)
1724
ifa->ifa_netmask));
1725
1726
// if an exception occurred then free the list
1727
if ((*env)->ExceptionOccurred(env)) {
1728
freeifaddrs(origifa);
1729
freeif(ifs);
1730
return NULL;
1731
}
1732
}
1733
1734
// free ifaddrs buffer
1735
freeifaddrs(origifa);
1736
return ifs;
1737
}
1738
1739
/*
1740
* Enumerates and returns all IPv6 interfaces on BSD.
1741
*/
1742
static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
1743
struct ifaddrs *ifa, *origifa;
1744
1745
if (getifaddrs(&origifa) != 0) {
1746
JNU_ThrowByNameWithMessageAndLastError
1747
(env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed");
1748
return ifs;
1749
}
1750
1751
for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
1752
// ignore non IPv6 addresses
1753
if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
1754
continue;
1755
1756
// set scope ID to interface index
1757
((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id =
1758
getIndex(sock, ifa->ifa_name);
1759
1760
// add interface to the list
1761
ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, NULL,
1762
AF_INET6,
1763
translateIPv6AddressToPrefix((struct sockaddr_in6 *)
1764
ifa->ifa_netmask));
1765
1766
// if an exception occurred then free the list
1767
if ((*env)->ExceptionOccurred(env)) {
1768
freeifaddrs(origifa);
1769
freeif(ifs);
1770
return NULL;
1771
}
1772
}
1773
1774
// free ifaddrs buffer
1775
freeifaddrs(origifa);
1776
return ifs;
1777
}
1778
1779
/*
1780
* Try to get the interface index.
1781
*/
1782
static int getIndex(int sock, const char *name) {
1783
#if !defined(__FreeBSD__)
1784
int index = if_nametoindex(name);
1785
return (index == 0) ? -1 : index;
1786
#else
1787
struct ifreq if2;
1788
memset((char *)&if2, 0, sizeof(if2));
1789
strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1);
1790
1791
if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
1792
return -1;
1793
}
1794
1795
return if2.ifr_index;
1796
#endif
1797
}
1798
1799
/*
1800
* Gets the Hardware address (usually MAC address) for the named interface.
1801
* On return puts the data in buf, and returns the length, in byte, of the
1802
* MAC address. Returns -1 if there is no hardware address on that interface.
1803
*/
1804
static int getMacAddress
1805
(JNIEnv *env, const char *ifname, const struct in_addr *addr,
1806
unsigned char *buf)
1807
{
1808
struct ifaddrs *ifa0, *ifa;
1809
struct sockaddr *saddr;
1810
int i;
1811
1812
// grab the interface list
1813
if (!getifaddrs(&ifa0)) {
1814
// cycle through the interfaces
1815
for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
1816
saddr = ifa->ifa_addr;
1817
if (saddr != NULL) {
1818
// link layer contains the MAC address
1819
if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
1820
struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
1821
// check the address has the correct length
1822
if (sadl->sdl_alen == ETHER_ADDR_LEN) {
1823
memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
1824
freeifaddrs(ifa0);
1825
return ETHER_ADDR_LEN;
1826
}
1827
}
1828
}
1829
}
1830
freeifaddrs(ifa0);
1831
}
1832
1833
return -1;
1834
}
1835
1836
static int getMTU(JNIEnv *env, int sock, const char *ifname) {
1837
struct ifreq if2;
1838
memset((char *)&if2, 0, sizeof(if2));
1839
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1840
1841
if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
1842
JNU_ThrowByNameWithMessageAndLastError
1843
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed");
1844
return -1;
1845
}
1846
1847
return if2.ifr_mtu;
1848
}
1849
1850
static int getFlags(int sock, const char *ifname, int *flags) {
1851
struct ifreq if2;
1852
memset((char *)&if2, 0, sizeof(if2));
1853
strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1);
1854
1855
if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
1856
return -1;
1857
}
1858
1859
if (sizeof(if2.ifr_flags) == sizeof(short)) {
1860
*flags = (if2.ifr_flags & 0xffff);
1861
} else {
1862
*flags = if2.ifr_flags;
1863
}
1864
return 0;
1865
}
1866
#endif /* _ALLBSD_SOURCE */
1867
1868