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