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