Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/solaris/native/java/net/NetworkInterface.c
+++ new/src/solaris/native/java/net/NetworkInterface.c
1 1 /*
2 2 * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Sun designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Sun in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 23 * have any questions.
24 24 */
25 25
26 26 #include <errno.h>
27 27 #include <strings.h>
28 28 #include <netinet/in.h>
29 29 #include <stdlib.h>
30 30 #include <string.h>
31 31 #include <sys/types.h>
32 32 #include <sys/socket.h>
33 33 #include <arpa/inet.h>
34 34 #include <net/if.h>
35 35 #include <net/if_arp.h>
36 36 #ifdef __solaris__
37 37 #include <sys/dlpi.h>
38 38 #include <fcntl.h>
39 39 #include <stropts.h>
40 40 #endif
41 41 #ifdef __linux__
42 42 #include <sys/ioctl.h>
43 43 #include <bits/ioctls.h>
44 44 #include <linux/sockios.h>
45 45 #include <sys/utsname.h>
46 46 #include <stdio.h>
47 47 #else
48 48 #include <sys/sockio.h>
49 49 #endif
50 50
51 51 #ifdef __linux__
52 52 #define ifr_index ifr_ifindex
53 53 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
54 54 #endif
55 55
56 56 #include "jvm.h"
57 57 #include "jni_util.h"
58 58 #include "net_util.h"
59 59
60 60 typedef struct _netaddr {
61 61 struct sockaddr *addr;
62 62 struct sockaddr *brdcast;
63 63 short mask;
64 64 int family; /* to make searches simple */
65 65 struct _netaddr *next;
66 66 } netaddr;
67 67
68 68 typedef struct _netif {
69 69 char *name;
70 70 int index;
71 71 char virtual;
72 72 netaddr *addr;
73 73 struct _netif *childs;
74 74 struct _netif *next;
75 75 } netif;
76 76
77 77 /************************************************************************
78 78 * NetworkInterface
79 79 */
80 80
81 81 #include "java_net_NetworkInterface.h"
82 82
83 83 /************************************************************************
84 84 * NetworkInterface
85 85 */
86 86 jclass ni_class;
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
87 87 jfieldID ni_nameID;
88 88 jfieldID ni_indexID;
89 89 jfieldID ni_descID;
90 90 jfieldID ni_addrsID;
91 91 jfieldID ni_bindsID;
92 92 jfieldID ni_virutalID;
93 93 jfieldID ni_childsID;
94 94 jfieldID ni_parentID;
95 95 jmethodID ni_ctrID;
96 96
97 -static jclass ni_iacls;
98 -static jclass ni_ia4cls;
99 -static jclass ni_ia6cls;
100 97 static jclass ni_ibcls;
101 -static jmethodID ni_ia4ctrID;
102 -static jmethodID ni_ia6ctrID;
103 98 static jmethodID ni_ibctrID;
104 -static jfieldID ni_iaaddressID;
105 -static jfieldID ni_iafamilyID;
106 -static jfieldID ni_ia6ipaddressID;
107 99 static jfieldID ni_ibaddressID;
108 100 static jfieldID ni_ib4broadcastID;
109 101 static jfieldID ni_ib4maskID;
110 102
111 103 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
112 104
113 105 static netif *enumInterfaces(JNIEnv *env);
114 106 static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs);
115 107 #ifdef AF_INET6
116 108 static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs);
117 109 #endif
118 110
119 111 static netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index,
120 112 int family, struct sockaddr *new_addrP, int new_addrlen,
121 113 short prefix);
122 114 static void freeif(netif *ifs);
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
123 115 static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname);
124 116 static short getSubnet(JNIEnv *env, const char *ifname);
125 117
126 118 /*
127 119 * Class: java_net_NetworkInterface
128 120 * Method: init
129 121 * Signature: ()V
130 122 */
131 123 JNIEXPORT void JNICALL
132 124 Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
133 - ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
134 - ni_class = (*env)->NewGlobalRef(env, ni_class);
135 - ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
136 - ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
137 - ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
138 - ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
139 - ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
140 - ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
141 - ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
142 - ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
143 - ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
125 + if (ni_ib4maskID == NULL) {
126 + ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
127 + ni_class = (*env)->NewGlobalRef(env, ni_class);
128 + ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
129 + ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
130 + ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
131 + ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
132 + ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
133 + ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
134 + ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
135 + ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
136 + ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
144 137
145 - ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
146 - ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
147 - ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
148 - ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
149 - ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
150 - ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
151 - ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
152 - ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
153 - ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
154 - ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
155 - ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
156 - ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
157 - ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
158 - ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
159 - ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
160 - ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
161 - ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
138 + ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
139 + ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
140 + ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
141 + ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
142 + ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
143 + ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
144 + }
145 +
146 + init(env);
162 147 }
163 148
164 149
165 150 /*
166 151 * Class: java_net_NetworkInterface
167 152 * Method: getByName0
168 153 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
169 154 */
170 155 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
171 156 (JNIEnv *env, jclass cls, jstring name) {
172 157
173 158 netif *ifs, *curr;
174 159 jboolean isCopy;
175 160 const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
176 161 jobject obj = NULL;
177 162
178 163 ifs = enumInterfaces(env);
179 164 if (ifs == NULL) {
180 165 return NULL;
181 166 }
182 167
183 168 /*
184 169 * Search the list of interface based on name
185 170 */
186 171 curr = ifs;
187 172 while (curr != NULL) {
188 173 if (strcmp(name_utf, curr->name) == 0) {
189 174 break;
190 175 }
191 176 curr = curr->next;
192 177 }
193 178
194 179 /* if found create a NetworkInterface */
195 180 if (curr != NULL) {;
196 181 obj = createNetworkInterface(env, curr);
197 182 }
198 183
199 184 /* release the UTF string and interface list */
200 185 (*env)->ReleaseStringUTFChars(env, name, name_utf);
201 186 freeif(ifs);
202 187
203 188 return obj;
204 189 }
205 190
206 191
207 192 /*
208 193 * Class: java_net_NetworkInterface
209 194 * Method: getByIndex0
210 195 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
211 196 */
212 197 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
213 198 (JNIEnv *env, jclass cls, jint index) {
214 199
215 200 netif *ifs, *curr;
216 201 jobject obj = NULL;
217 202
218 203 if (index <= 0) {
219 204 return NULL;
220 205 }
221 206
222 207 ifs = enumInterfaces(env);
223 208 if (ifs == NULL) {
224 209 return NULL;
225 210 }
226 211
227 212 /*
228 213 * Search the list of interface based on index
229 214 */
230 215 curr = ifs;
231 216 while (curr != NULL) {
232 217 if (index == curr->index) {
233 218 break;
234 219 }
235 220 curr = curr->next;
236 221 }
237 222
238 223 /* if found create a NetworkInterface */
239 224 if (curr != NULL) {;
240 225 obj = createNetworkInterface(env, curr);
241 226 }
242 227
243 228 freeif(ifs);
244 229 return obj;
245 230 }
246 231
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
247 232 /*
248 233 * Class: java_net_NetworkInterface
249 234 * Method: getByInetAddress0
250 235 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
251 236 */
252 237 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
253 238 (JNIEnv *env, jclass cls, jobject iaObj) {
254 239
255 240 netif *ifs, *curr;
256 241 #ifdef AF_INET6
257 - int family = (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4?
242 + int family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?
258 243 AF_INET : AF_INET6;
259 244 #else
260 245 int family = AF_INET;
261 246 #endif
262 247 jobject obj = NULL;
263 248 jboolean match = JNI_FALSE;
264 249
265 250 ifs = enumInterfaces(env);
266 251 if (ifs == NULL) {
267 252 return NULL;
268 253 }
269 254
270 255 curr = ifs;
271 256 while (curr != NULL) {
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
272 257 netaddr *addrP = curr->addr;
273 258
274 259 /*
275 260 * Iterate through each address on the interface
276 261 */
277 262 while (addrP != NULL) {
278 263
279 264 if (family == addrP->family) {
280 265 if (family == AF_INET) {
281 266 int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
282 - int address2 = (*env)->GetIntField(env, iaObj, ni_iaaddressID);
267 + int address2 = (*env)->GetIntField(env, iaObj, ia_addressID);
283 268
284 269 if (address1 == address2) {
285 270 match = JNI_TRUE;
286 271 break;
287 272 }
288 273 }
289 274
290 275 #ifdef AF_INET6
291 276 if (family == AF_INET6) {
292 277 jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
293 - jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
278 + jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
294 279 jbyte caddr[16];
295 280 int i;
296 281
297 282 (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
298 283 i = 0;
299 284 while (i < 16) {
300 285 if (caddr[i] != bytes[i]) {
301 286 break;
302 287 }
303 288 i++;
304 289 }
305 290 if (i >= 16) {
306 291 match = JNI_TRUE;
307 292 break;
308 293 }
309 294 }
310 295 #endif
311 296
312 297 }
313 298
314 299 if (match) {
315 300 break;
316 301 }
317 302 addrP = addrP->next;
318 303 }
319 304
320 305 if (match) {
321 306 break;
322 307 }
323 308 curr = curr->next;
324 309 }
325 310
326 311 /* if found create a NetworkInterface */
327 312 if (match) {;
328 313 obj = createNetworkInterface(env, curr);
329 314 }
330 315
331 316 freeif(ifs);
332 317 return obj;
333 318 }
334 319
335 320
336 321 /*
337 322 * Class: java_net_NetworkInterface
338 323 * Method: getAll
339 324 * Signature: ()[Ljava/net/NetworkInterface;
340 325 */
341 326 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
342 327 (JNIEnv *env, jclass cls) {
343 328
344 329 netif *ifs, *curr;
345 330 jobjectArray netIFArr;
346 331 jint arr_index, ifCount;
347 332
348 333 ifs = enumInterfaces(env);
349 334 if (ifs == NULL) {
350 335 return NULL;
351 336 }
352 337
353 338 /* count the interface */
354 339 ifCount = 0;
355 340 curr = ifs;
356 341 while (curr != NULL) {
357 342 ifCount++;
358 343 curr = curr->next;
359 344 }
360 345
361 346 /* allocate a NetworkInterface array */
362 347 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
363 348 if (netIFArr == NULL) {
364 349 freeif(ifs);
365 350 return NULL;
366 351 }
367 352
368 353 /*
369 354 * Iterate through the interfaces, create a NetworkInterface instance
370 355 * for each array element and populate the object.
371 356 */
372 357 curr = ifs;
373 358 arr_index = 0;
374 359 while (curr != NULL) {
375 360 jobject netifObj;
376 361
377 362 netifObj = createNetworkInterface(env, curr);
378 363 if (netifObj == NULL) {
379 364 freeif(ifs);
380 365 return NULL;
381 366 }
382 367
383 368 /* put the NetworkInterface into the array */
384 369 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
385 370
386 371 curr = curr->next;
387 372 }
388 373
389 374 freeif(ifs);
390 375 return netIFArr;
391 376 }
392 377
393 378 /*
394 379 * Create a NetworkInterface object, populate the name and index, and
395 380 * populate the InetAddress array based on the IP addresses for this
396 381 * interface.
397 382 */
398 383 jobject createNetworkInterface(JNIEnv *env, netif *ifs)
399 384 {
400 385 jobject netifObj;
401 386 jobject name;
402 387 jobjectArray addrArr;
403 388 jobjectArray bindArr;
404 389 jobjectArray childArr;
405 390 jint addr_index, addr_count, bind_index;
406 391 jint child_count, child_index;
407 392 netaddr *addrP;
408 393 netif *childP;
409 394 jobject tmp;
410 395
411 396 /*
412 397 * Create a NetworkInterface object and populate it
413 398 */
414 399 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
415 400 name = (*env)->NewStringUTF(env, ifs->name);
416 401 if (netifObj == NULL || name == NULL) {
417 402 return NULL;
418 403 }
419 404 (*env)->SetObjectField(env, netifObj, ni_nameID, name);
420 405 (*env)->SetObjectField(env, netifObj, ni_descID, name);
421 406 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
422 407 (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
423 408
424 409 /*
425 410 * Count the number of address on this interface
426 411 */
↓ open down ↓ |
123 lines elided |
↑ open up ↑ |
427 412 addr_count = 0;
428 413 addrP = ifs->addr;
429 414 while (addrP != NULL) {
430 415 addr_count++;
431 416 addrP = addrP->next;
432 417 }
433 418
434 419 /*
435 420 * Create the array of InetAddresses
436 421 */
437 - addrArr = (*env)->NewObjectArray(env, addr_count, ni_iacls, NULL);
422 + addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL);
438 423 if (addrArr == NULL) {
439 424 return NULL;
440 425 }
441 426
442 427 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
443 428 if (bindArr == NULL) {
444 429 return NULL;
445 430 }
446 431 addrP = ifs->addr;
447 432 addr_index = 0;
448 433 bind_index = 0;
449 434 while (addrP != NULL) {
450 435 jobject iaObj = NULL;
451 436 jobject ibObj = NULL;
452 437
453 438 if (addrP->family == AF_INET) {
454 - iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
439 + iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
455 440 if (iaObj) {
456 - (*env)->SetIntField(env, iaObj, ni_iaaddressID,
441 + (*env)->SetIntField(env, iaObj, ia_addressID,
457 442 htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
458 443 }
459 444 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
460 445 if (ibObj) {
461 446 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
462 447 if (addrP->brdcast) {
463 448 jobject ia2Obj = NULL;
464 - ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
449 + ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
465 450 if (ia2Obj) {
466 - (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
451 + (*env)->SetIntField(env, ia2Obj, ia_addressID,
467 452 htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
468 453 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
469 454 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
470 455 }
471 456 }
472 457 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
473 458 }
474 459 }
475 460
476 461 #ifdef AF_INET6
477 462 if (addrP->family == AF_INET6) {
478 463 int scope=0;
479 - iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
464 + iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
480 465 if (iaObj) {
481 466 jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
482 467 if (ipaddress == NULL) {
483 468 return NULL;
484 469 }
485 470 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
486 471 (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
487 472 #ifdef __linux__
488 473 if (!kernelIsV22()) {
489 474 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
490 475 }
491 476 #else
492 477 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
493 478 #endif
494 479 if (scope != 0) { /* zero is default value, no need to set */
495 480 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
496 481 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
497 482 (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
498 483 }
499 - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
484 + (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
500 485 }
501 486 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
502 487 if (ibObj) {
503 488 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
504 489 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
505 490 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
506 491 }
507 492 }
508 493 #endif
509 494
510 495 if (iaObj == NULL) {
511 496 return NULL;
512 497 }
513 498
514 499 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
515 500 addrP = addrP->next;
516 501 }
517 502
518 503 /*
519 504 * See if there is any virtual interface attached to this one.
520 505 */
521 506 child_count = 0;
522 507 childP = ifs->childs;
523 508 while (childP) {
524 509 child_count++;
525 510 childP = childP->next;
526 511 }
527 512
528 513 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
529 514 if (childArr == NULL) {
530 515 return NULL;
531 516 }
532 517
533 518 /*
534 519 * Create the NetworkInterface instances for the sub-interfaces as
535 520 * well.
536 521 */
537 522 child_index = 0;
538 523 childP = ifs->childs;
539 524 while(childP) {
540 525 tmp = createNetworkInterface(env, childP);
541 526 if (tmp == NULL) {
542 527 return NULL;
543 528 }
544 529 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
545 530 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
546 531 childP = childP->next;
547 532 }
548 533 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
549 534 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
550 535 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
551 536
552 537 /* return the NetworkInterface */
553 538 return netifObj;
554 539 }
555 540
556 541 /*
557 542 * Enumerates all interfaces
558 543 */
559 544 static netif *enumInterfaces(JNIEnv *env) {
560 545 netif *ifs;
561 546
562 547 /*
563 548 * Enumerate IPv4 addresses
564 549 */
565 550 ifs = enumIPv4Interfaces(env, NULL);
566 551 if (ifs == NULL) {
567 552 if ((*env)->ExceptionOccurred(env)) {
568 553 return NULL;
569 554 }
570 555 }
571 556
572 557 /*
573 558 * If IPv6 is available then enumerate IPv6 addresses.
574 559 */
575 560 #ifdef AF_INET6
576 561 if (ipv6_available()) {
577 562 ifs = enumIPv6Interfaces(env, ifs);
578 563
579 564 if ((*env)->ExceptionOccurred(env)) {
580 565 freeif(ifs);
581 566 return NULL;
582 567 }
583 568 }
584 569 #endif
585 570
586 571 return ifs;
587 572 }
588 573
589 574
590 575 /*
591 576 * Enumerates and returns all IPv4 interfaces
592 577 */
593 578 static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) {
594 579 int sock;
595 580 struct ifconf ifc;
596 581 struct ifreq *ifreqP;
597 582 char *buf;
598 583 int numifs;
599 584 unsigned i;
600 585 unsigned bufsize;
601 586
602 587 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
603 588 if (sock < 0) {
604 589 /*
605 590 * If EPROTONOSUPPORT is returned it means we don't have
606 591 * IPv4 support so don't throw an exception.
607 592 */
608 593 if (errno != EPROTONOSUPPORT) {
609 594 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
610 595 "Socket creation failed");
611 596 }
612 597 return ifs;
613 598 }
614 599
615 600 #ifdef __linux__
616 601 /* need to do a dummy SIOCGIFCONF to determine the buffer size.
617 602 * SIOCGIFCOUNT doesn't work
618 603 */
619 604 ifc.ifc_buf = NULL;
620 605 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
621 606 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
622 607 "ioctl SIOCGIFCONF failed");
623 608 close(sock);
624 609 return ifs;
625 610 }
626 611 bufsize = ifc.ifc_len;
627 612 #else
628 613 if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
629 614 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
630 615 "ioctl SIOCGIFNUM failed");
631 616 close(sock);
632 617 return ifs;
633 618 }
634 619 bufsize = numifs * sizeof (struct ifreq);
635 620 #endif /* __linux__ */
636 621
637 622 buf = (char *)malloc(bufsize);
638 623 if (!buf) {
639 624 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
640 625 (void) close(sock);
641 626 return ifs;
642 627 }
643 628 ifc.ifc_len = bufsize;
644 629 ifc.ifc_buf = buf;
645 630 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
646 631 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
647 632 "ioctl SIOCGIFCONF failed");
648 633 (void) close(sock);
649 634 (void) free(buf);
650 635 return ifs;
651 636 }
652 637
653 638 /*
654 639 * Iterate through each interface
655 640 */
656 641 ifreqP = ifc.ifc_req;
657 642 for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
658 643 int index;
659 644 struct ifreq if2;
660 645
661 646 memset((char *)&if2, 0, sizeof(if2));
662 647 strcpy(if2.ifr_name, ifreqP->ifr_name);
663 648
664 649 /*
665 650 * Try to get the interface index
666 651 * (Not supported on Solaris 2.6 or 7)
667 652 */
668 653 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) {
669 654 index = if2.ifr_index;
670 655 } else {
671 656 index = -1;
672 657 }
673 658
674 659 /*
675 660 * Add to the list
676 661 */
677 662 ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET,
678 663 (struct sockaddr *)&(ifreqP->ifr_addr),
679 664 sizeof(struct sockaddr_in), 0);
680 665
681 666 /*
682 667 * If an exception occurred then free the list
683 668 */
684 669 if ((*env)->ExceptionOccurred(env)) {
685 670 close(sock);
686 671 free(buf);
687 672 freeif(ifs);
688 673 return NULL;
689 674 }
690 675 }
691 676
692 677 /*
693 678 * Free socket and buffer
694 679 */
695 680 close(sock);
696 681 free(buf);
697 682 return ifs;
698 683 }
699 684
700 685
701 686 #if defined(__solaris__) && defined(AF_INET6)
702 687 /*
703 688 * Enumerates and returns all IPv6 interfaces on Solaris
704 689 */
705 690 static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
706 691 int sock;
707 692 struct lifconf ifc;
708 693 struct lifreq *ifr;
709 694 int n;
710 695 char *buf;
711 696 struct lifnum numifs;
712 697 unsigned bufsize;
713 698
714 699 sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
715 700 if (sock < 0) {
716 701 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
717 702 "Failed to create IPv6 socket");
718 703 return ifs;
719 704 }
720 705
721 706 /*
722 707 * Get the interface count
723 708 */
724 709 numifs.lifn_family = AF_UNSPEC;
725 710 numifs.lifn_flags = 0;
726 711 if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
727 712 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
728 713 "ioctl SIOCGLIFNUM failed");
729 714 close(sock);
730 715 return ifs;
731 716 }
732 717
733 718 /*
734 719 * Enumerate the interface configurations
735 720 */
736 721 bufsize = numifs.lifn_count * sizeof (struct lifreq);
737 722 buf = (char *)malloc(bufsize);
738 723 if (!buf) {
739 724 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
740 725 (void) close(sock);
741 726 return ifs;
742 727 }
743 728 ifc.lifc_family = AF_UNSPEC;
744 729 ifc.lifc_flags = 0;
745 730 ifc.lifc_len = bufsize;
746 731 ifc.lifc_buf = buf;
747 732 if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
748 733 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
749 734 "ioctl SIOCGLIFCONF failed");
750 735 close(sock);
751 736 free(buf);
752 737 return ifs;
753 738 }
754 739
755 740 /*
756 741 * Iterate through each interface
757 742 */
758 743 ifr = ifc.lifc_req;
759 744 for (n=0; n<numifs.lifn_count; n++, ifr++) {
760 745 int index = -1;
761 746 struct lifreq if2;
762 747
763 748 /*
764 749 * Ignore non-IPv6 addresses
765 750 */
766 751 if (ifr->lifr_addr.ss_family != AF_INET6) {
767 752 continue;
768 753 }
769 754
770 755 /*
771 756 * Get the index
772 757 */
773 758 memset((char *)&if2, 0, sizeof(if2));
774 759 strcpy(if2.lifr_name, ifr->lifr_name);
775 760 if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) {
776 761 struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
777 762 index = if2.lifr_index;
778 763 s6->sin6_scope_id = index;
779 764 }
780 765
781 766 /* add to the list */
782 767 ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6,
783 768 (struct sockaddr *)&(ifr->lifr_addr),
784 769 sizeof(struct sockaddr_in6), (short) ifr->lifr_addrlen);
785 770
786 771 /*
787 772 * If an exception occurred we return
788 773 */
789 774 if ((*env)->ExceptionOccurred(env)) {
790 775 close(sock);
791 776 free(buf);
792 777 return ifs;
793 778 }
794 779
795 780 }
796 781
797 782 close(sock);
798 783 free(buf);
799 784 return ifs;
800 785
801 786 }
802 787 #endif
803 788
804 789
805 790 #if defined(__linux__) && defined(AF_INET6)
806 791 /*
807 792 * Enumerates and returns all IPv6 interfaces on Linux
808 793 */
809 794 static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
810 795 FILE *f;
811 796 char addr6[40], devname[20];
812 797 char addr6p[8][5];
813 798 int plen, scope, dad_status, if_idx;
814 799 uint8_t ipv6addr[16];
815 800
816 801 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
817 802 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
818 803 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
819 804 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
820 805 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
821 806 struct sockaddr_in6 addr;
822 807
823 808 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
824 809 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
825 810 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
826 811 inet_pton(AF_INET6, addr6, ipv6addr);
827 812
828 813 memset(&addr, 0, sizeof(struct sockaddr_in6));
829 814 memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
830 815 addr.sin6_scope_id = if_idx;
831 816
832 817 ifs = addif(env, ifs, devname, if_idx, AF_INET6,
833 818 (struct sockaddr *)&addr,
834 819 sizeof(struct sockaddr_in6), plen);
835 820
836 821 /*
837 822 * If an exception occurred then return the list as is.
838 823 */
839 824 if ((*env)->ExceptionOccurred(env)) {
840 825 fclose(f);
841 826 return ifs;
842 827 }
843 828 }
844 829 fclose(f);
845 830 }
846 831 return ifs;
847 832 }
848 833 #endif
849 834
850 835
851 836 /*
852 837 * Free an interface list (including any attached addresses)
853 838 */
854 839 void freeif(netif *ifs) {
855 840 netif *currif = ifs;
856 841
857 842 while (currif != NULL) {
858 843 netaddr *addrP = currif->addr;
859 844 while (addrP != NULL) {
860 845 netaddr *next = addrP->next;
861 846 if (addrP->addr != NULL)
862 847 free(addrP->addr);
863 848 if (addrP->brdcast != NULL)
864 849 free(addrP->brdcast);
865 850 free(addrP);
866 851 addrP = next;
867 852 }
868 853
869 854 free(currif->name);
870 855
871 856 /*
872 857 * Don't forget to free the sub-interfaces.
873 858 */
874 859 if (currif->childs != NULL) {
875 860 freeif(currif->childs);
876 861 }
877 862
878 863 ifs = currif->next;
879 864 free(currif);
880 865 currif = ifs;
881 866 }
882 867 }
883 868
884 869 /*
885 870 * Add an interface to the list. If known interface just link
886 871 * a new netaddr onto the list. If new interface create new
887 872 * netif structure.
888 873 */
889 874 netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family,
890 875 struct sockaddr *new_addrP, int new_addrlen, short prefix) {
891 876 netif *currif = ifs, *parent;
892 877 netaddr *addrP;
893 878 #ifdef LIFNAMSIZ
894 879 char name[LIFNAMSIZ];
895 880 char vname[LIFNAMSIZ];
896 881 #else
897 882 char name[IFNAMSIZ];
898 883 char vname[IFNAMSIZ];
899 884 #endif
900 885 char *unit;
901 886 int isVirtual = 0;
902 887
903 888 /*
904 889 * If the interface name is a logical interface then we
905 890 * remove the unit number so that we have the physical
906 891 * interface (eg: hme0:1 -> hme0). NetworkInterface
907 892 * currently doesn't have any concept of physical vs.
908 893 * logical interfaces.
909 894 */
910 895 strcpy(name, if_name);
911 896
912 897 /*
913 898 * Create and populate the netaddr node. If allocation fails
914 899 * return an un-updated list.
915 900 */
916 901 addrP = (netaddr *)malloc(sizeof(netaddr));
917 902 if (addrP) {
918 903 addrP->addr = (struct sockaddr *)malloc(new_addrlen);
919 904 if (addrP->addr == NULL) {
920 905 free(addrP);
921 906 addrP = NULL;
922 907 }
923 908 }
924 909 if (addrP == NULL) {
925 910 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
926 911 return ifs; /* return untouched list */
927 912 }
928 913 memcpy(addrP->addr, new_addrP, new_addrlen);
929 914 addrP->family = family;
930 915
931 916 addrP->brdcast = NULL;
932 917 addrP->mask = prefix;
933 918 if (family == AF_INET) {
934 919 /*
935 920 * Deal with brodcast addr & subnet mask
936 921 */
937 922 addrP->brdcast = getBroadcast(env, name);
938 923 if (addrP->brdcast) {
939 924 addrP->mask = getSubnet(env, name);
940 925 }
941 926 }
942 927
943 928 vname[0] = 0;
944 929 unit = strchr(name, ':');
945 930 if (unit != NULL) {
946 931 /**
947 932 * This is a virtual interface. If we are able to access the parent
948 933 * we need to create a new entry if it doesn't exist yet *and* update
949 934 * the 'parent' interface with the new records.
950 935 */
951 936 struct ifreq if2;
952 937 int sock;
953 938 int len;
954 939
955 940 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
956 941 if (sock < 0) {
957 942 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
958 943 "Socket creation failed");
959 944 return ifs; /* return untouched list */
960 945 }
961 946
962 947 len = unit - name;
963 948 if (len > 0) {
964 949 // temporarily use vname to hold the parent name of the interface
965 950 // instead of creating another buffer.
966 951 memcpy(&vname, name, len);
967 952 vname[len] = '\0';
968 953
969 954 memset((char *) &if2, 0, sizeof(if2));
970 955 strcpy(if2.ifr_name, vname);
971 956
972 957 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
973 958 // Got access to parent, so create it if necessary.
974 959 strcpy(vname, name);
975 960 *unit = '\0';
976 961 } else {
977 962 #if defined(__solaris__) && defined(AF_INET6)
978 963 struct lifreq lifr;
979 964 memset((char *) &lifr, 0, sizeof(lifr));
980 965 strcpy(lifr.lifr_name, vname);
981 966
982 967 /* Try with an IPv6 socket in case the interface has only IPv6
983 968 * addresses assigned to it */
984 969 close(sock);
985 970 sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
986 971
987 972 if (sock < 0) {
988 973 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
989 974 "Socket creation failed");
990 975 return ifs; /* return untouched list */
991 976 }
992 977
993 978 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
994 979 // Got access to parent, so create it if necessary.
995 980 strcpy(vname, name);
996 981 *unit = '\0';
997 982 } else {
998 983 // failed to access parent interface do not create parent.
999 984 // We are a virtual interface with no parent.
1000 985 isVirtual = 1;
1001 986 vname[0] = 0;
1002 987 }
1003 988 #else
1004 989 // failed to access parent interface do not create parent.
1005 990 // We are a virtual interface with no parent.
1006 991 isVirtual = 1;
1007 992 vname[0] = 0;
1008 993 #endif
1009 994 }
1010 995 }
1011 996 close(sock);
1012 997 }
1013 998
1014 999 /*
1015 1000 * Check if this is a "new" interface. Use the interface
1016 1001 * name for matching because index isn't supported on
1017 1002 * Solaris 2.6 & 7.
1018 1003 */
1019 1004 while (currif != NULL) {
1020 1005 if (strcmp(name, currif->name) == 0) {
1021 1006 break;
1022 1007 }
1023 1008 currif = currif->next;
1024 1009 }
1025 1010
1026 1011 /*
1027 1012 * If "new" then create an netif structure and
1028 1013 * insert it onto the list.
1029 1014 */
1030 1015 if (currif == NULL) {
1031 1016 currif = (netif *)malloc(sizeof(netif));
1032 1017 if (currif) {
1033 1018 currif->name = strdup(name);
1034 1019 if (currif->name == NULL) {
1035 1020 free(currif);
1036 1021 currif = NULL;
1037 1022 }
1038 1023 }
1039 1024 if (currif == NULL) {
1040 1025 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
1041 1026 return ifs;
1042 1027 }
1043 1028 currif->index = index;
1044 1029 currif->addr = NULL;
1045 1030 currif->childs = NULL;
1046 1031 currif->virtual = isVirtual;
1047 1032 currif->next = ifs;
1048 1033 ifs = currif;
1049 1034 }
1050 1035
1051 1036 /*
1052 1037 * Finally insert the address on the interface
1053 1038 */
1054 1039 addrP->next = currif->addr;
1055 1040 currif->addr = addrP;
1056 1041
1057 1042 parent = currif;
1058 1043
1059 1044 /**
1060 1045 * Let's deal with the virtual interface now.
1061 1046 */
1062 1047 if (vname[0]) {
1063 1048 netaddr *tmpaddr;
1064 1049
1065 1050 currif = parent->childs;
1066 1051
1067 1052 while (currif != NULL) {
1068 1053 if (strcmp(vname, currif->name) == 0) {
1069 1054 break;
1070 1055 }
1071 1056 currif = currif->next;
1072 1057 }
1073 1058 if (currif == NULL) {
1074 1059 currif = (netif *)malloc(sizeof(netif));
1075 1060 if (currif) {
1076 1061 currif->name = strdup(vname);
1077 1062 if (currif->name == NULL) {
1078 1063 free(currif);
1079 1064 currif = NULL;
1080 1065 }
1081 1066 }
1082 1067 if (currif == NULL) {
1083 1068 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
1084 1069 return ifs;
1085 1070 }
1086 1071 currif->index = index;
1087 1072 currif->addr = NULL;
1088 1073 /* Need to duplicate the addr entry? */
1089 1074 currif->virtual = 1;
1090 1075 currif->childs = NULL;
1091 1076 currif->next = parent->childs;
1092 1077 parent->childs = currif;
1093 1078 }
1094 1079
1095 1080 tmpaddr = (netaddr *) malloc(sizeof(netaddr));
1096 1081 if (tmpaddr == NULL) {
1097 1082 JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
1098 1083 return ifs;
1099 1084 }
1100 1085 memcpy(tmpaddr, addrP, sizeof(netaddr));
1101 1086 /**
1102 1087 * Let's duplicate the address and broadcast address structures
1103 1088 * if there are any.
1104 1089 */
1105 1090 if (addrP->addr != NULL) {
1106 1091 tmpaddr->addr = malloc(new_addrlen);
1107 1092 if (tmpaddr->addr != NULL)
1108 1093 memcpy(tmpaddr->addr, addrP->addr, new_addrlen);
1109 1094 }
1110 1095 if (addrP->brdcast != NULL) {
1111 1096 tmpaddr->brdcast = malloc(new_addrlen);
1112 1097 if (tmpaddr->brdcast != NULL)
1113 1098 memcpy(tmpaddr->brdcast, addrP->brdcast, new_addrlen);
1114 1099 }
1115 1100 tmpaddr->next = currif->addr;
1116 1101 currif->addr = tmpaddr;
1117 1102 }
1118 1103
1119 1104 return ifs;
1120 1105 }
1121 1106
1122 1107 /**
1123 1108 * Get flags from a NetworkInterface.
1124 1109 */
1125 1110 static short getFlags(JNIEnv *env, jstring name) {
1126 1111 int sock;
1127 1112 struct ifreq if2;
1128 1113 jboolean isCopy;
1129 1114 const char* name_utf;
1130 1115 short ret = -1;
1131 1116
1132 1117 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1133 1118 if (sock < 0) {
1134 1119 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1135 1120 "Socket creation failed");
1136 1121 return -1;
1137 1122 }
1138 1123
1139 1124 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
1140 1125 memset((char *) &if2, 0, sizeof(if2));
1141 1126 strcpy(if2.ifr_name, name_utf);
1142 1127
1143 1128 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
1144 1129 ret = if2.ifr_flags;
1145 1130 } else {
1146 1131 #if defined(__solaris__) && defined(AF_INET6)
1147 1132 /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
1148 1133 struct lifreq lifr;
1149 1134
1150 1135 close(sock);
1151 1136 sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
1152 1137
1153 1138 if (sock < 0) {
1154 1139 (*env)->ReleaseStringUTFChars(env, name, name_utf);
1155 1140 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1156 1141 "Socket creation failed");
1157 1142 return -1;
1158 1143 }
1159 1144
1160 1145 memset((caddr_t)&lifr, 0, sizeof(lifr));
1161 1146 strcpy((caddr_t)&(lifr.lifr_name), name_utf);
1162 1147
1163 1148 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
1164 1149 ret = lifr.lifr_flags;
1165 1150 } else {
1166 1151 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1167 1152 "IOCTL failed");
1168 1153 }
1169 1154 #else
1170 1155 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1171 1156 "IOCTL failed");
1172 1157 #endif
1173 1158 }
1174 1159 close(sock);
1175 1160 /* release the UTF string and interface list */
1176 1161 (*env)->ReleaseStringUTFChars(env, name, name_utf);
1177 1162
1178 1163 return ret;
1179 1164 }
1180 1165
1181 1166 /**
1182 1167 * Returns the IPv4 broadcast address of a named interface, if it exists.
1183 1168 * Returns 0 if it doesn't have one.
1184 1169 */
1185 1170 static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname) {
1186 1171 int sock;
1187 1172 struct sockaddr *ret = NULL;
1188 1173 struct ifreq if2;
1189 1174 short flag = 0;
1190 1175
1191 1176 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1192 1177 if (sock < 0) {
1193 1178 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1194 1179 "Socket creation failed");
1195 1180 return ret;
1196 1181 }
1197 1182
1198 1183 memset((char *) &if2, 0, sizeof(if2));
1199 1184 strcpy(if2.ifr_name, ifname);
1200 1185 /* Let's make sure the interface does have a broadcast address */
1201 1186 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
1202 1187 flag = if2.ifr_flags;
1203 1188 } else {
1204 1189 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1205 1190 "IOCTL failed");
1206 1191 }
1207 1192 if (flag & IFF_BROADCAST) {
1208 1193 /* It does, let's retrieve it*/
1209 1194 if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) >= 0) {
1210 1195 ret = (struct sockaddr*) malloc(sizeof(struct sockaddr));
1211 1196 memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
1212 1197 } else {
1213 1198 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1214 1199 "IOCTL failed");
1215 1200 }
1216 1201 }
1217 1202 close(sock);
1218 1203 return ret;
1219 1204 }
1220 1205
1221 1206 /**
1222 1207 * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
1223 1208 * interface, if it has one, otherwise return -1.
1224 1209 */
1225 1210 static short getSubnet(JNIEnv *env, const char *ifname) {
1226 1211 int sock;
1227 1212 unsigned int mask;
1228 1213 short ret;
1229 1214 struct ifreq if2;
1230 1215
1231 1216 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1232 1217 if (sock < 0) {
1233 1218 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1234 1219 "Socket creation failed");
1235 1220 return -1;
1236 1221 }
1237 1222
1238 1223 memset((char *) &if2, 0, sizeof(if2));
1239 1224 strcpy(if2.ifr_name, ifname);
1240 1225 if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) >= 0) {
1241 1226 mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
1242 1227 ret = 0;
1243 1228 while (mask) {
1244 1229 mask <<= 1;
1245 1230 ret++;
1246 1231 }
1247 1232 close(sock);
1248 1233 return ret;
1249 1234 }
1250 1235 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1251 1236 "IOCTL failed");
1252 1237 close(sock);
1253 1238 return -1;
1254 1239 }
1255 1240
1256 1241 #ifdef __solaris__
1257 1242 #define DEV_PREFIX "/dev/"
1258 1243
1259 1244 /**
1260 1245 * Solaris specific DLPI code to get hardware address from a device.
1261 1246 * Unfortunately, at least up to Solaris X, you have to have special
1262 1247 * privileges (i.e. be root).
1263 1248 */
1264 1249 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
1265 1250 char style1dev[MAXPATHLEN];
1266 1251 int fd;
1267 1252 dl_phys_addr_req_t dlpareq;
1268 1253 dl_phys_addr_ack_t *dlpaack;
1269 1254 struct strbuf msg;
1270 1255 char buf[128];
1271 1256 int flags = 0;
1272 1257
1273 1258 /**
1274 1259 * Device is in /dev
1275 1260 * e.g.: /dev/bge0
1276 1261 */
1277 1262 strcpy(style1dev, DEV_PREFIX);
1278 1263 strcat(style1dev, ifname);
1279 1264 if ((fd = open(style1dev, O_RDWR)) == -1) {
1280 1265 /*
1281 1266 * Can't open it. We probably are missing the privilege.
1282 1267 * We'll have to try something else
1283 1268 */
1284 1269 return 0;
1285 1270 }
1286 1271 dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
1287 1272 dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
1288 1273 msg.buf = (char *)&dlpareq;
1289 1274 msg.len = DL_PHYS_ADDR_REQ_SIZE;
1290 1275 if (putmsg(fd, &msg, NULL, 0) < 0) {
1291 1276 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1292 1277 "putmsg failed");
1293 1278 return -1;
1294 1279 }
1295 1280 dlpaack = (dl_phys_addr_ack_t *)buf;
1296 1281 msg.buf = (char *)buf;
1297 1282 msg.len = 0;
1298 1283 msg.maxlen = sizeof (buf);
1299 1284 if (getmsg(fd, &msg, NULL, &flags) < 0) {
1300 1285 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1301 1286 "getmsg failed");
1302 1287 return -1;
1303 1288 }
1304 1289 if (msg.len < DL_PHYS_ADDR_ACK_SIZE ||
1305 1290 dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
1306 1291 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
1307 1292 "Couldn't obtain phys addr\n");
1308 1293 return -1;
1309 1294 }
1310 1295
1311 1296 memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
1312 1297 return dlpaack->dl_addr_length;
1313 1298 }
1314 1299 #endif
1315 1300
1316 1301 /**
1317 1302 * Get the Hardware address (usually MAC address) for the named interface.
1318 1303 * return puts the data in buf, and returns the length, in byte, of the
1319 1304 * MAC address. Returns -1 if there is no hardware address on that interface.
1320 1305 */
1321 1306 int getMacAddress(JNIEnv *env, const struct in_addr* addr, const char* ifname,
1322 1307 unsigned char *buf) {
1323 1308 int sock;
1324 1309 #ifdef __linux__
1325 1310 static struct ifreq ifr;
1326 1311 int i;
1327 1312
1328 1313 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1329 1314
1330 1315 if (sock < 0) {
1331 1316 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1332 1317 "Socket creation failed");
1333 1318 return -1;
1334 1319 }
1335 1320
1336 1321 strcpy(ifr.ifr_name, ifname);
1337 1322
1338 1323 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
1339 1324 fprintf(stderr, "SIOCIFHWADDR: %s\n",
1340 1325 strerror(errno));
1341 1326 close(sock);
1342 1327 return -1;
1343 1328 }
1344 1329 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1345 1330 close(sock);
1346 1331 for (i = 0; i < IFHWADDRLEN; i++) {
1347 1332 if (buf[i] != 0)
1348 1333 return IFHWADDRLEN;
1349 1334 }
1350 1335 /*
1351 1336 * All bytes to 0 means no hardware address.
1352 1337 */
1353 1338 return -1;
1354 1339 #else
1355 1340 struct arpreq arpreq;
1356 1341 struct sockaddr_in* sin;
1357 1342 struct sockaddr_in ipAddr;
1358 1343 int len;
1359 1344
1360 1345 /**
1361 1346 * On Solaris we have to use DLPI, but it will only work if we have
1362 1347 * privileged access (i.e. root). If that fails, we try a lookup
1363 1348 * in the ARP table, which requires an IPv4 address.
1364 1349 */
1365 1350 if ((len = getMacFromDevice(env, ifname, buf)) > 0) {
1366 1351 return len;
1367 1352 }
1368 1353 if (addr == NULL) {
1369 1354 /**
1370 1355 * No IPv4 address for that interface, so can't do an ARP lookup.
1371 1356 */
1372 1357 return -1;
1373 1358 }
1374 1359 sin = (struct sockaddr_in *) &arpreq.arp_pa;
1375 1360 memset((char *) &arpreq, 0, sizeof(struct arpreq));
1376 1361 ipAddr.sin_port = 0;
1377 1362 ipAddr.sin_family = AF_INET;
1378 1363 memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
1379 1364 memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
1380 1365 arpreq.arp_flags= ATF_PUBL;
1381 1366 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1382 1367
1383 1368 if (sock < 0) {
1384 1369 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1385 1370 "Socket creation failed");
1386 1371 return -1;
1387 1372 }
1388 1373
1389 1374 if (ioctl(sock, SIOCGARP, &arpreq) >= 0) {
1390 1375 close(sock);
1391 1376 memcpy(buf, &arpreq.arp_ha.sa_data[0], 6);
1392 1377 return 6;
1393 1378 }
1394 1379
1395 1380 if (errno != ENXIO) {
1396 1381 // "No such device or address" means no hardware address, so it's
1397 1382 // normal don't throw an exception
1398 1383 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1399 1384 "IOCTL failed");
1400 1385 }
1401 1386 close(sock);
1402 1387 #endif
1403 1388 return -1;
1404 1389 }
1405 1390
1406 1391 /*
1407 1392 * Class: java_net_NetworkInterface
1408 1393 * Method: isUp0
1409 1394 * Signature: (Ljava/lang/String;I)Z
1410 1395 */
1411 1396 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
1412 1397 (JNIEnv *env, jclass cls, jstring name, jint index) {
1413 1398 short val;
1414 1399
1415 1400 val = getFlags(env, name);
1416 1401 if ( (val & IFF_UP) && (val & IFF_RUNNING))
1417 1402 return JNI_TRUE;
1418 1403 return JNI_FALSE;
1419 1404 }
1420 1405
1421 1406 /*
1422 1407 * Class: java_net_NetworkInterface
1423 1408 * Method: isP2P0
1424 1409 * Signature: (Ljava/lang/String;I)Z
1425 1410 */
1426 1411 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
1427 1412 (JNIEnv *env, jclass cls, jstring name, jint index) {
1428 1413 if (getFlags(env, name) & IFF_POINTOPOINT)
1429 1414 return JNI_TRUE;
1430 1415 return JNI_FALSE;
1431 1416 }
1432 1417
1433 1418 /*
1434 1419 * Class: java_net_NetworkInterface
1435 1420 * Method: isLoopback0
1436 1421 * Signature: (Ljava/lang/String;I)Z
1437 1422 */
1438 1423 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
1439 1424 (JNIEnv *env, jclass cls, jstring name, jint index) {
1440 1425 if (getFlags(env, name) & IFF_LOOPBACK)
1441 1426 return JNI_TRUE;
1442 1427 return JNI_FALSE;
1443 1428 }
1444 1429
1445 1430 /*
1446 1431 * Class: java_net_NetworkInterface
1447 1432 * Method: supportsMulticast0
1448 1433 * Signature: (Ljava/lang/String;I)Z
1449 1434 */
1450 1435 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
1451 1436 (JNIEnv *env, jclass cls, jstring name, jint index) {
1452 1437 short val;
1453 1438
1454 1439 val = getFlags(env, name);
1455 1440 if (val & IFF_MULTICAST)
1456 1441 return JNI_TRUE;
1457 1442 return JNI_FALSE;
1458 1443 }
1459 1444
1460 1445 /*
1461 1446 * Class: java_net_NetworkInterface
1462 1447 * Method: getMacAddr0
1463 1448 * Signature: ([bLjava/lang/String;I)[b
1464 1449 */
1465 1450 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
1466 1451 jint addr;
1467 1452 jbyte caddr[4];
1468 1453 struct in_addr iaddr;
1469 1454 jbyteArray ret = NULL;
1470 1455 unsigned char mac[16];
1471 1456 int len;
1472 1457 jboolean isCopy;
1473 1458 const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
1474 1459
1475 1460 if (!IS_NULL(addrArray)) {
1476 1461 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
1477 1462 addr = ((caddr[0]<<24) & 0xff000000);
1478 1463 addr |= ((caddr[1] <<16) & 0xff0000);
1479 1464 addr |= ((caddr[2] <<8) & 0xff00);
1480 1465 addr |= (caddr[3] & 0xff);
1481 1466 iaddr.s_addr = htonl(addr);
1482 1467 len = getMacAddress(env, &iaddr, name_utf, mac);
1483 1468 } else {
1484 1469 len = getMacAddress(env, NULL, name_utf, mac);
1485 1470 }
1486 1471 if (len > 0) {
1487 1472 ret = (*env)->NewByteArray(env, len);
1488 1473 if (IS_NULL(ret)) {
1489 1474 /* we may have memory to free at the end of this */
1490 1475 goto fexit;
1491 1476 }
1492 1477 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
1493 1478 }
1494 1479 fexit:
1495 1480 /* release the UTF string and interface list */
1496 1481 (*env)->ReleaseStringUTFChars(env, name, name_utf);
1497 1482 return ret;
1498 1483 }
1499 1484
1500 1485 /*
1501 1486 * Class: java_net_NetworkInterface
1502 1487 * Method: getMTU0
1503 1488 * Signature: ([bLjava/lang/String;I)I
1504 1489 */
1505 1490
1506 1491 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
1507 1492 jboolean isCopy;
1508 1493 int sock;
1509 1494 struct ifreq if2;
1510 1495 int ret = -1;
1511 1496 const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
1512 1497
1513 1498 sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
1514 1499 if (sock < 0) {
1515 1500 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1516 1501 "Socket creation failed");
1517 1502 } else {
1518 1503
1519 1504 #ifdef __linux__
1520 1505 memset((char *) &if2, 0, sizeof(if2));
1521 1506 strcpy(if2.ifr_name, name_utf);
1522 1507
1523 1508 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) >= 0) {
1524 1509 ret= if2.ifr_mtu;
1525 1510 } else {
1526 1511 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1527 1512 "IOCTL failed");
1528 1513 }
1529 1514 #else /* Solaris */
1530 1515 struct lifreq lifr;
1531 1516 memset((caddr_t)&lifr, 0, sizeof(lifr));
1532 1517 strcpy((caddr_t)&(lifr.lifr_name), name_utf);
1533 1518 if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
1534 1519 ret = lifr.lifr_mtu;
1535 1520 #ifdef AF_INET6
1536 1521 } else {
1537 1522 /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
1538 1523 close(sock);
1539 1524 sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
1540 1525
1541 1526 if (sock < 0) {
1542 1527 (*env)->ReleaseStringUTFChars(env, name, name_utf);
1543 1528 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1544 1529 "Socket creation failed");
1545 1530 return -1;
1546 1531 }
1547 1532
1548 1533 if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
1549 1534 ret = lifr.lifr_mtu;
1550 1535 } else {
1551 1536 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1552 1537 "IOCTL failed");
1553 1538 }
1554 1539 }
1555 1540 #else
1556 1541 } else {
1557 1542 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1558 1543 "IOCTL failed");
1559 1544 }
1560 1545 #endif
1561 1546 #endif
1562 1547 close(sock);
1563 1548 }
1564 1549 /* release the UTF string and interface list */
1565 1550 (*env)->ReleaseStringUTFChars(env, name, name_utf);
1566 1551 return ret;
1567 1552 }
↓ open down ↓ |
1058 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX