1 /* 2 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #include <arpa/inet.h> 26 #include <errno.h> 27 #include <net/if.h> 28 #include <net/if_arp.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/ioctl.h> 32 33 #if defined(_AIX) 34 #include <netinet/in6_var.h> 35 #include <sys/ndd_var.h> 36 #include <sys/kinfo.h> 37 #include <strings.h> 38 #endif 39 40 #if defined(__solaris__) 41 #include <stropts.h> 42 #include <sys/dlpi.h> 43 #include <sys/sockio.h> 44 #endif 45 46 #if defined(_ALLBSD_SOURCE) 47 #include <net/ethernet.h> 48 #include <net/if_dl.h> 49 #include <ifaddrs.h> 50 #endif 51 52 #include "net_util.h" 53 54 #include "java_net_InetAddress.h" 55 56 #if defined(__linux__) 57 #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" 58 #elif defined(__solaris__) 59 #ifndef SIOCGLIFHWADDR 60 #define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq) 61 #endif 62 #define DEV_PREFIX "/dev/" 63 #endif 64 65 #ifdef LIFNAMSIZ 66 #define IFNAMESIZE LIFNAMSIZ 67 #else 68 #define IFNAMESIZE IFNAMSIZ 69 #endif 70 71 #define CHECKED_MALLOC3(_pointer, _type, _size) \ 72 do { \ 73 _pointer = (_type)malloc(_size); \ 74 if (_pointer == NULL) { \ 75 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \ 76 return ifs; /* return untouched list */ \ 77 } \ 78 } while(0) 79 80 typedef struct _netaddr { 81 struct sockaddr *addr; 82 struct sockaddr *brdcast; 83 short mask; 84 int family; /* to make searches simple */ 85 struct _netaddr *next; 86 } netaddr; 87 88 typedef struct _netif { 89 char *name; 90 int index; 91 char virtual; 92 netaddr *addr; 93 struct _netif *childs; 94 struct _netif *next; 95 } netif; 96 97 /************************************************************************ 98 * NetworkInterface 99 */ 100 101 #include "java_net_NetworkInterface.h" 102 103 /************************************************************************ 104 * NetworkInterface 105 */ 106 jclass ni_class; 107 jfieldID ni_nameID; 108 jfieldID ni_indexID; 109 jfieldID ni_descID; 110 jfieldID ni_addrsID; 111 jfieldID ni_bindsID; 112 jfieldID ni_virutalID; 113 jfieldID ni_childsID; 114 jfieldID ni_parentID; 115 jfieldID ni_defaultIndexID; 116 jmethodID ni_ctrID; 117 118 static jclass ni_ibcls; 119 static jmethodID ni_ibctrID; 120 static jfieldID ni_ibaddressID; 121 static jfieldID ni_ib4broadcastID; 122 static jfieldID ni_ib4maskID; 123 124 /** Private methods declarations **/ 125 static jobject createNetworkInterface(JNIEnv *env, netif *ifs); 126 static int getFlags0(JNIEnv *env, jstring ifname); 127 128 static netif *enumInterfaces(JNIEnv *env); 129 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs); 130 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs); 131 132 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs, 133 struct sockaddr *ifr_addrP, 134 struct sockaddr *ifr_broadaddrP, 135 int family, short prefix); 136 static void freeif(netif *ifs); 137 138 static int openSocket(JNIEnv *env, int proto); 139 static int openSocketWithFallback(JNIEnv *env, const char *ifname); 140 141 static short translateIPv4AddressToPrefix(struct sockaddr_in *addr); 142 static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr); 143 144 static int getIndex(int sock, const char *ifname); 145 static int getFlags(int sock, const char *ifname, int *flags); 146 static int getMacAddress(JNIEnv *env, const char *ifname, 147 const struct in_addr *addr, unsigned char *buf); 148 static int getMTU(JNIEnv *env, int sock, const char *ifname); 149 150 #if defined(__solaris__) 151 static int getMacFromDevice(JNIEnv *env, const char *ifname, 152 unsigned char *retbuf); 153 #endif 154 155 /******************* Java entry points *****************************/ 156 157 /* 158 * Class: java_net_NetworkInterface 159 * Method: init 160 * Signature: ()V 161 */ 162 JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init 163 (JNIEnv *env, jclass cls) 164 { 165 ni_class = (*env)->FindClass(env, "java/net/NetworkInterface"); 166 CHECK_NULL(ni_class); 167 ni_class = (*env)->NewGlobalRef(env, ni_class); 168 CHECK_NULL(ni_class); 169 ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;"); 170 CHECK_NULL(ni_nameID); 171 ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I"); 172 CHECK_NULL(ni_indexID); 173 ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", 174 "[Ljava/net/InetAddress;"); 175 CHECK_NULL(ni_addrsID); 176 ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", 177 "[Ljava/net/InterfaceAddress;"); 178 CHECK_NULL(ni_bindsID); 179 ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", 180 "Ljava/lang/String;"); 181 CHECK_NULL(ni_descID); 182 ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z"); 183 CHECK_NULL(ni_virutalID); 184 ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", 185 "[Ljava/net/NetworkInterface;"); 186 CHECK_NULL(ni_childsID); 187 ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", 188 "Ljava/net/NetworkInterface;"); 189 CHECK_NULL(ni_parentID); 190 ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V"); 191 CHECK_NULL(ni_ctrID); 192 ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress"); 193 CHECK_NULL(ni_ibcls); 194 ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls); 195 CHECK_NULL(ni_ibcls); 196 ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V"); 197 CHECK_NULL(ni_ibctrID); 198 ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", 199 "Ljava/net/InetAddress;"); 200 CHECK_NULL(ni_ibaddressID); 201 ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", 202 "Ljava/net/Inet4Address;"); 203 CHECK_NULL(ni_ib4broadcastID); 204 ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S"); 205 CHECK_NULL(ni_ib4maskID); 206 ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", 207 "I"); 208 CHECK_NULL(ni_defaultIndexID); 209 initInetAddressIDs(env); 210 } 211 212 /* 213 * Class: java_net_NetworkInterface 214 * Method: getByName0 215 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 216 */ 217 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 218 (JNIEnv *env, jclass cls, jstring name) 219 { 220 netif *ifs, *curr; 221 jboolean isCopy; 222 const char* name_utf; 223 char *colonP; 224 char searchName[IFNAMESIZE]; 225 jobject obj = NULL; 226 227 if (name != NULL) { 228 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 229 } else { 230 JNU_ThrowNullPointerException(env, "network interface name is NULL"); 231 return NULL; 232 } 233 234 if (name_utf == NULL) { 235 if (!(*env)->ExceptionCheck(env)) 236 JNU_ThrowOutOfMemoryError(env, NULL); 237 return NULL; 238 } 239 240 ifs = enumInterfaces(env); 241 if (ifs == NULL) { 242 (*env)->ReleaseStringUTFChars(env, name, name_utf); 243 return NULL; 244 } 245 246 // search the list of interfaces based on name, 247 // if it is virtual sub interface search with parent first. 248 strncpy(searchName, name_utf, IFNAMESIZE); 249 searchName[IFNAMESIZE - 1] = '\0'; 250 colonP = strchr(searchName, ':'); 251 if (colonP != NULL) { 252 *colonP = '\0'; 253 } 254 curr = ifs; 255 while (curr != NULL) { 256 if (strcmp(searchName, curr->name) == 0) { 257 break; 258 } 259 curr = curr->next; 260 } 261 262 // search the child list 263 if (colonP != NULL && curr != NULL) { 264 curr = curr->childs; 265 while (curr != NULL) { 266 if (strcmp(name_utf, curr->name) == 0) { 267 break; 268 } 269 curr = curr->next; 270 } 271 } 272 273 // if found create a NetworkInterface 274 if (curr != NULL) { 275 obj = createNetworkInterface(env, curr); 276 } 277 278 // release the UTF string and interface list 279 (*env)->ReleaseStringUTFChars(env, name, name_utf); 280 freeif(ifs); 281 282 return obj; 283 } 284 285 /* 286 * Class: java_net_NetworkInterface 287 * Method: getByIndex0 288 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 289 */ 290 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0 291 (JNIEnv *env, jclass cls, jint index) 292 { 293 netif *ifs, *curr; 294 jobject obj = NULL; 295 296 if (index <= 0) { 297 return NULL; 298 } 299 300 ifs = enumInterfaces(env); 301 if (ifs == NULL) { 302 return NULL; 303 } 304 305 // search the list of interfaces based on index 306 curr = ifs; 307 while (curr != NULL) { 308 if (index == curr->index) { 309 break; 310 } 311 curr = curr->next; 312 } 313 314 // if found create a NetworkInterface 315 if (curr != NULL) { 316 obj = createNetworkInterface(env, curr); 317 } 318 319 // release the interface list 320 freeif(ifs); 321 322 return obj; 323 } 324 325 // Return the interface in ifs that iaObj is bound to, if any - otherwise NULL 326 static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) { 327 netif* curr = ifs; 328 while (curr != NULL) { 329 netaddr *addrP = curr->addr; 330 331 // iterate through each address on the interface 332 while (addrP != NULL) { 333 334 if (family == addrP->family) { 335 if (family == AF_INET) { 336 int address1 = htonl( 337 ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr); 338 int address2 = getInetAddress_addr(env, iaObj); 339 if ((*env)->ExceptionCheck(env)) { 340 return NULL; 341 } 342 if (address1 == address2) { 343 return curr; 344 } 345 } else if (family == AF_INET6) { 346 jbyte *bytes = (jbyte *)&( 347 ((struct sockaddr_in6*)addrP->addr)->sin6_addr); 348 jbyte caddr[16]; 349 int i; 350 unsigned int scopeid; 351 getInet6Address_ipaddress(env, iaObj, (char *)caddr); 352 scopeid = (unsigned int)getInet6Address_scopeid(env, iaObj); 353 if (scopeid != 0 && scopeid != ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id) 354 break; 355 i = 0; 356 while (i < 16) { 357 if (caddr[i] != bytes[i]) { 358 break; 359 } 360 i++; 361 } 362 if (i >= 16) { 363 return curr; 364 } 365 } 366 } 367 368 addrP = addrP->next; 369 } 370 curr = curr->next; 371 } 372 373 return NULL; 374 } 375 376 /* 377 * Class: java_net_NetworkInterface 378 * Method: boundInetAddress0 379 * Signature: (Ljava/net/InetAddress;)boundInetAddress; 380 */ 381 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0 382 (JNIEnv *env, jclass cls, jobject iaObj) 383 { 384 netif *ifs = NULL; 385 jboolean bound = JNI_FALSE; 386 int sock; 387 388 int family = getInetAddress_family(env, iaObj); 389 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 390 391 if (family == java_net_InetAddress_IPv4) { 392 family = AF_INET; 393 } else if (family == java_net_InetAddress_IPv6) { 394 family = AF_INET6; 395 } else { 396 return JNI_FALSE; // Invalid family 397 } 398 399 if (family == AF_INET) { 400 sock = openSocket(env, AF_INET); 401 if (sock < 0 && (*env)->ExceptionOccurred(env)) { 402 return JNI_FALSE; 403 } 404 405 // enumerate IPv4 addresses 406 if (sock >= 0) { 407 ifs = enumIPv4Interfaces(env, sock, ifs); 408 close(sock); 409 410 if ((*env)->ExceptionOccurred(env)) { 411 goto cleanup; 412 } 413 } 414 if (find_bound_interface(env, ifs, iaObj, family) != NULL) 415 bound = JNI_TRUE; 416 } else if (ipv6_available()) { 417 // If IPv6 is available then enumerate IPv6 addresses. 418 // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true, 419 // so we have to call ipv6_available() 420 sock = openSocket(env, AF_INET6); 421 if (sock < 0) { 422 return JNI_FALSE; 423 } 424 425 ifs = enumIPv6Interfaces(env, sock, ifs); 426 close(sock); 427 428 if ((*env)->ExceptionOccurred(env)) { 429 goto cleanup; 430 } 431 432 if (find_bound_interface(env, ifs, iaObj, family) != NULL) 433 bound = JNI_TRUE; 434 } 435 436 cleanup: 437 freeif(ifs); 438 439 return bound; 440 } 441 442 /* 443 * Class: java_net_NetworkInterface 444 * Method: getByInetAddress0 445 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; 446 */ 447 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 448 (JNIEnv *env, jclass cls, jobject iaObj) 449 { 450 netif *ifs, *curr; 451 jobject obj = NULL; 452 int family = getInetAddress_family(env, iaObj); 453 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 454 455 if (family == java_net_InetAddress_IPv4) { 456 family = AF_INET; 457 } else if (family == java_net_InetAddress_IPv6) { 458 family = AF_INET6; 459 } else { 460 return NULL; // Invalid family 461 } 462 ifs = enumInterfaces(env); 463 if (ifs == NULL) { 464 return NULL; 465 } 466 467 curr = find_bound_interface(env, ifs, iaObj, family); 468 469 // if found create a NetworkInterface 470 if (curr != NULL) { 471 obj = createNetworkInterface(env, curr); 472 } 473 474 // release the interface list 475 freeif(ifs); 476 477 return obj; 478 } 479 480 /* 481 * Class: java_net_NetworkInterface 482 * Method: getAll 483 * Signature: ()[Ljava/net/NetworkInterface; 484 */ 485 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll 486 (JNIEnv *env, jclass cls) 487 { 488 netif *ifs, *curr; 489 jobjectArray netIFArr; 490 jint arr_index, ifCount; 491 492 ifs = enumInterfaces(env); 493 if (ifs == NULL) { 494 return NULL; 495 } 496 497 // count the interfaces 498 ifCount = 0; 499 curr = ifs; 500 while (curr != NULL) { 501 ifCount++; 502 curr = curr->next; 503 } 504 505 // allocate a NetworkInterface array 506 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL); 507 if (netIFArr == NULL) { 508 freeif(ifs); 509 return NULL; 510 } 511 512 // iterate through the interfaces, create a NetworkInterface instance 513 // for each array element and populate the object 514 curr = ifs; 515 arr_index = 0; 516 while (curr != NULL) { 517 jobject netifObj; 518 519 netifObj = createNetworkInterface(env, curr); 520 if (netifObj == NULL) { 521 freeif(ifs); 522 return NULL; 523 } 524 525 // put the NetworkInterface into the array 526 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj); 527 528 curr = curr->next; 529 } 530 531 // release the interface list 532 freeif(ifs); 533 534 return netIFArr; 535 } 536 537 /* 538 * Class: java_net_NetworkInterface 539 * Method: isUp0 540 * Signature: (Ljava/lang/String;I)Z 541 */ 542 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0 543 (JNIEnv *env, jclass cls, jstring name, jint index) 544 { 545 int ret = getFlags0(env, name); 546 return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE; 547 } 548 549 /* 550 * Class: java_net_NetworkInterface 551 * Method: isP2P0 552 * Signature: (Ljava/lang/String;I)Z 553 */ 554 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0 555 (JNIEnv *env, jclass cls, jstring name, jint index) 556 { 557 int ret = getFlags0(env, name); 558 return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE; 559 } 560 561 /* 562 * Class: java_net_NetworkInterface 563 * Method: isLoopback0 564 * Signature: (Ljava/lang/String;I)Z 565 */ 566 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0 567 (JNIEnv *env, jclass cls, jstring name, jint index) 568 { 569 int ret = getFlags0(env, name); 570 return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE; 571 } 572 573 /* 574 * Class: java_net_NetworkInterface 575 * Method: supportsMulticast0 576 * Signature: (Ljava/lang/String;I)Z 577 */ 578 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0 579 (JNIEnv *env, jclass cls, jstring name, jint index) 580 { 581 int ret = getFlags0(env, name); 582 return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE; 583 } 584 585 /* 586 * Class: java_net_NetworkInterface 587 * Method: getMacAddr0 588 * Signature: ([bLjava/lang/String;I)[b 589 */ 590 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0 591 (JNIEnv *env, jclass cls, jbyteArray addrArray, jstring name, jint index) 592 { 593 jint addr; 594 jbyte caddr[4]; 595 struct in_addr iaddr; 596 jbyteArray ret = NULL; 597 unsigned char mac[16]; 598 int len; 599 jboolean isCopy; 600 const char *name_utf; 601 602 if (name != NULL) { 603 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 604 } else { 605 JNU_ThrowNullPointerException(env, "network interface name is NULL"); 606 return NULL; 607 } 608 609 if (name_utf == NULL) { 610 if (!(*env)->ExceptionCheck(env)) 611 JNU_ThrowOutOfMemoryError(env, NULL); 612 return NULL; 613 } 614 615 if (!IS_NULL(addrArray)) { 616 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); 617 addr = ((caddr[0]<<24) & 0xff000000); 618 addr |= ((caddr[1] <<16) & 0xff0000); 619 addr |= ((caddr[2] <<8) & 0xff00); 620 addr |= (caddr[3] & 0xff); 621 iaddr.s_addr = htonl(addr); 622 len = getMacAddress(env, name_utf, &iaddr, mac); 623 } else { 624 len = getMacAddress(env, name_utf, NULL, mac); 625 } 626 627 if (len > 0) { 628 ret = (*env)->NewByteArray(env, len); 629 if (!IS_NULL(ret)) { 630 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *)(mac)); 631 } 632 } 633 634 // release the UTF string and interface list 635 (*env)->ReleaseStringUTFChars(env, name, name_utf); 636 637 return ret; 638 } 639 640 /* 641 * Class: java_net_NetworkInterface 642 * Method: getMTU0 643 * Signature: ([bLjava/lang/String;I)I 644 */ 645 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0 646 (JNIEnv *env, jclass cls, jstring name, jint index) 647 { 648 jboolean isCopy; 649 int sock, ret = -1; 650 const char* name_utf = NULL; 651 652 if (name != NULL) { 653 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 654 } else { 655 JNU_ThrowNullPointerException(env, "network interface name is NULL"); 656 return ret; 657 } 658 659 if (name_utf == NULL) { 660 if (!(*env)->ExceptionCheck(env)) 661 JNU_ThrowOutOfMemoryError(env, NULL); 662 return ret; 663 } 664 665 if ((sock = openSocketWithFallback(env, name_utf)) < 0) { 666 (*env)->ReleaseStringUTFChars(env, name, name_utf); 667 return JNI_FALSE; 668 } 669 670 ret = getMTU(env, sock, name_utf); 671 672 (*env)->ReleaseStringUTFChars(env, name, name_utf); 673 674 close(sock); 675 return ret; 676 } 677 678 /*** Private methods definitions ****/ 679 680 static int getFlags0(JNIEnv *env, jstring name) { 681 jboolean isCopy; 682 int ret, sock, flags = 0; 683 const char *name_utf; 684 685 if (name != NULL) { 686 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 687 } else { 688 JNU_ThrowNullPointerException(env, "network interface name is NULL"); 689 return -1; 690 } 691 692 if (name_utf == NULL) { 693 if (!(*env)->ExceptionCheck(env)) 694 JNU_ThrowOutOfMemoryError(env, NULL); 695 return -1; 696 } 697 if ((sock = openSocketWithFallback(env, name_utf)) < 0) { 698 (*env)->ReleaseStringUTFChars(env, name, name_utf); 699 return -1; 700 } 701 702 ret = getFlags(sock, name_utf, &flags); 703 704 close(sock); 705 (*env)->ReleaseStringUTFChars(env, name, name_utf); 706 707 if (ret < 0) { 708 JNU_ThrowByNameWithMessageAndLastError 709 (env, JNU_JAVANETPKG "SocketException", "getFlags() failed"); 710 return -1; 711 } 712 713 return flags; 714 } 715 716 /* 717 * Creates a NetworkInterface object, populates the name, the index, and 718 * populates the InetAddress array based on the IP addresses for this 719 * interface. 720 */ 721 static jobject createNetworkInterface(JNIEnv *env, netif *ifs) { 722 jobject netifObj; 723 jobject name; 724 jobjectArray addrArr; 725 jobjectArray bindArr; 726 jobjectArray childArr; 727 netaddr *addrs; 728 jint addr_index, addr_count, bind_index; 729 jint child_count, child_index; 730 netaddr *addrP; 731 netif *childP; 732 jobject tmp; 733 734 // create a NetworkInterface object and populate it 735 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID); 736 CHECK_NULL_RETURN(netifObj, NULL); 737 name = (*env)->NewStringUTF(env, ifs->name); 738 CHECK_NULL_RETURN(name, NULL); 739 (*env)->SetObjectField(env, netifObj, ni_nameID, name); 740 (*env)->SetObjectField(env, netifObj, ni_descID, name); 741 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); 742 (*env)->SetBooleanField(env, netifObj, ni_virutalID, 743 ifs->virtual ? JNI_TRUE : JNI_FALSE); 744 745 // count the number of addresses on this interface 746 addr_count = 0; 747 addrP = ifs->addr; 748 while (addrP != NULL) { 749 addr_count++; 750 addrP = addrP->next; 751 } 752 753 // create the array of InetAddresses 754 addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL); 755 if (addrArr == NULL) { 756 return NULL; 757 } 758 759 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL); 760 if (bindArr == NULL) { 761 return NULL; 762 } 763 addrP = ifs->addr; 764 addr_index = 0; 765 bind_index = 0; 766 while (addrP != NULL) { 767 jobject iaObj = NULL; 768 jobject ibObj = NULL; 769 770 if (addrP->family == AF_INET) { 771 iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 772 if (iaObj) { 773 setInetAddress_addr(env, iaObj, htonl( 774 ((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr)); 775 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 776 } else { 777 return NULL; 778 } 779 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 780 if (ibObj) { 781 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 782 if (addrP->brdcast) { 783 jobject ia2Obj = NULL; 784 ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 785 if (ia2Obj) { 786 setInetAddress_addr(env, ia2Obj, htonl( 787 ((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr)); 788 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 789 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj); 790 } else { 791 return NULL; 792 } 793 } 794 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); 795 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); 796 } else { 797 return NULL; 798 } 799 } 800 if (addrP->family == AF_INET6) { 801 int scope=0; 802 iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); 803 if (iaObj) { 804 jboolean ret = setInet6Address_ipaddress(env, iaObj, 805 (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); 806 if (ret == JNI_FALSE) { 807 return NULL; 808 } 809 810 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; 811 812 if (scope != 0) { /* zero is default value, no need to set */ 813 setInet6Address_scopeid(env, iaObj, scope); 814 setInet6Address_scopeifname(env, iaObj, netifObj); 815 } 816 } else { 817 return NULL; 818 } 819 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 820 if (ibObj) { 821 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 822 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); 823 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); 824 } else { 825 return NULL; 826 } 827 } 828 829 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj); 830 addrP = addrP->next; 831 } 832 833 // see if there is any virtual interface attached to this one. 834 child_count = 0; 835 childP = ifs->childs; 836 while (childP) { 837 child_count++; 838 childP = childP->next; 839 } 840 841 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL); 842 if (childArr == NULL) { 843 return NULL; 844 } 845 846 // create the NetworkInterface instances for the sub-interfaces as well 847 child_index = 0; 848 childP = ifs->childs; 849 while(childP) { 850 tmp = createNetworkInterface(env, childP); 851 if (tmp == NULL) { 852 return NULL; 853 } 854 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj); 855 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp); 856 childP = childP->next; 857 } 858 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); 859 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr); 860 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); 861 862 // return the NetworkInterface 863 return netifObj; 864 } 865 866 /* 867 * Enumerates all interfaces 868 */ 869 static netif *enumInterfaces(JNIEnv *env) { 870 netif *ifs = NULL; 871 int sock; 872 873 sock = openSocket(env, AF_INET); 874 if (sock < 0 && (*env)->ExceptionOccurred(env)) { 875 return NULL; 876 } 877 878 // enumerate IPv4 addresses 879 if (sock >= 0) { 880 ifs = enumIPv4Interfaces(env, sock, ifs); 881 close(sock); 882 883 if ((*env)->ExceptionOccurred(env)) { 884 freeif(ifs); 885 return NULL; 886 } 887 } 888 889 // If IPv6 is available then enumerate IPv6 addresses. 890 // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true, 891 // so we have to call ipv6_available() 892 if (ipv6_available()) { 893 sock = openSocket(env, AF_INET6); 894 if (sock < 0) { 895 freeif(ifs); 896 return NULL; 897 } 898 899 ifs = enumIPv6Interfaces(env, sock, ifs); 900 close(sock); 901 902 if ((*env)->ExceptionOccurred(env)) { 903 freeif(ifs); 904 return NULL; 905 } 906 } 907 908 return ifs; 909 } 910 911 /* 912 * Frees an interface list (including any attached addresses). 913 */ 914 static void freeif(netif *ifs) { 915 netif *currif = ifs; 916 netif *child = NULL; 917 918 while (currif != NULL) { 919 netaddr *addrP = currif->addr; 920 while (addrP != NULL) { 921 netaddr *next = addrP->next; 922 free(addrP); 923 addrP = next; 924 } 925 926 // don't forget to free the sub-interfaces 927 if (currif->childs != NULL) { 928 freeif(currif->childs); 929 } 930 931 ifs = currif->next; 932 free(currif); 933 currif = ifs; 934 } 935 } 936 937 static netif *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs, 938 struct sockaddr *ifr_addrP, 939 struct sockaddr *ifr_broadaddrP, 940 int family, short prefix) 941 { 942 netif *currif = ifs, *parent; 943 netaddr *addrP; 944 char name[IFNAMESIZE], vname[IFNAMESIZE]; 945 char *name_colonP; 946 int isVirtual = 0; 947 int addr_size; 948 949 // If the interface name is a logical interface then we remove the unit 950 // number so that we have the physical interface (eg: hme0:1 -> hme0). 951 // NetworkInterface currently doesn't have any concept of physical vs. 952 // logical interfaces. 953 strncpy(name, if_name, IFNAMESIZE); 954 name[IFNAMESIZE - 1] = '\0'; 955 *vname = 0; 956 957 // Create and populate the netaddr node. If allocation fails 958 // return an un-updated list. 959 960 // Allocate for addr and brdcast at once 961 962 addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) 963 : sizeof(struct sockaddr_in6); 964 965 CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size); 966 addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr)); 967 memcpy(addrP->addr, ifr_addrP, addr_size); 968 969 addrP->family = family; 970 addrP->mask = prefix; 971 addrP->next = 0; 972 973 // for IPv4 add broadcast address 974 if (family == AF_INET && ifr_broadaddrP != NULL) { 975 addrP->brdcast = (struct sockaddr *) 976 ((char *)addrP + sizeof(netaddr) + addr_size); 977 memcpy(addrP->brdcast, ifr_broadaddrP, addr_size); 978 } else { 979 addrP->brdcast = NULL; 980 } 981 982 // Deal with virtual interface with colon notation e.g. eth0:1 983 name_colonP = strchr(name, ':'); 984 if (name_colonP != NULL) { 985 int flags = 0; 986 // This is a virtual interface. If we are able to access the parent 987 // we need to create a new entry if it doesn't exist yet *and* update 988 // the 'parent' interface with the new records. 989 *name_colonP = 0; 990 if (getFlags(sock, name, &flags) < 0 || flags < 0) { 991 // failed to access parent interface do not create parent. 992 // We are a virtual interface with no parent. 993 isVirtual = 1; 994 *name_colonP = ':'; 995 } else { 996 // Got access to parent, so create it if necessary. 997 // Save original name to vname and truncate name by ':' 998 memcpy(vname, name, sizeof(vname)); 999 vname[name_colonP - name] = ':'; 1000 } 1001 } 1002 1003 // Check if this is a "new" interface. Use the interface name for 1004 // matching because index isn't supported on Solaris 2.6 & 7. 1005 while (currif != NULL) { 1006 if (strcmp(name, currif->name) == 0) { 1007 break; 1008 } 1009 currif = currif->next; 1010 } 1011 1012 // If "new" then create a netif structure and insert it into the list. 1013 if (currif == NULL) { 1014 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE); 1015 currif->name = (char *)currif + sizeof(netif); 1016 strncpy(currif->name, name, IFNAMESIZE); 1017 currif->name[IFNAMESIZE - 1] = '\0'; 1018 currif->index = getIndex(sock, name); 1019 currif->addr = NULL; 1020 currif->childs = NULL; 1021 currif->virtual = isVirtual; 1022 currif->next = ifs; 1023 ifs = currif; 1024 } 1025 1026 // Finally insert the address on the interface 1027 addrP->next = currif->addr; 1028 currif->addr = addrP; 1029 1030 parent = currif; 1031 1032 // Deal with the virtual interface now. 1033 if (vname[0]) { 1034 netaddr *tmpaddr; 1035 1036 currif = parent->childs; 1037 1038 while (currif != NULL) { 1039 if (strcmp(vname, currif->name) == 0) { 1040 break; 1041 } 1042 currif = currif->next; 1043 } 1044 1045 if (currif == NULL) { 1046 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + IFNAMESIZE); 1047 currif->name = (char *)currif + sizeof(netif); 1048 strncpy(currif->name, vname, IFNAMESIZE); 1049 currif->name[IFNAMESIZE - 1] = '\0'; 1050 currif->index = getIndex(sock, vname); 1051 currif->addr = NULL; // Need to duplicate the addr entry? 1052 currif->virtual = 1; 1053 currif->childs = NULL; 1054 currif->next = parent->childs; 1055 parent->childs = currif; 1056 } 1057 1058 CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr) + 2 * addr_size); 1059 memcpy(tmpaddr, addrP, sizeof(netaddr)); 1060 if (addrP->addr != NULL) { 1061 tmpaddr->addr = (struct sockaddr *) 1062 ((char*)tmpaddr + sizeof(netaddr)); 1063 memcpy(tmpaddr->addr, addrP->addr, addr_size); 1064 } 1065 1066 if (addrP->brdcast != NULL) { 1067 tmpaddr->brdcast = (struct sockaddr *) 1068 ((char *)tmpaddr + sizeof(netaddr) + addr_size); 1069 memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size); 1070 } 1071 1072 tmpaddr->next = currif->addr; 1073 currif->addr = tmpaddr; 1074 } 1075 1076 return ifs; 1077 } 1078 1079 /* 1080 * Determines the prefix value for an AF_INET subnet address. 1081 */ 1082 static short translateIPv4AddressToPrefix(struct sockaddr_in *addr) { 1083 short prefix = 0; 1084 unsigned int mask; 1085 if (addr == NULL) { 1086 return 0; 1087 } 1088 mask = ntohl(addr->sin_addr.s_addr); 1089 while (mask) { 1090 mask <<= 1; 1091 prefix++; 1092 } 1093 return prefix; 1094 } 1095 1096 /* 1097 * Determines the prefix value for an AF_INET6 subnet address. 1098 */ 1099 static short translateIPv6AddressToPrefix(struct sockaddr_in6 *addr) { 1100 short prefix = 0; 1101 u_char *addrBytes; 1102 if (addr == NULL) { 1103 return 0; 1104 } 1105 addrBytes = (u_char *)&(addr->sin6_addr); 1106 unsigned int byte, bit; 1107 1108 for (byte = 0; byte < sizeof(struct in6_addr); byte++, prefix += 8) { 1109 if (addrBytes[byte] != 0xff) { 1110 break; 1111 } 1112 } 1113 if (byte != sizeof(struct in6_addr)) { 1114 for (bit = 7; bit != 0; bit--, prefix++) { 1115 if (!(addrBytes[byte] & (1 << bit))) { 1116 break; 1117 } 1118 } 1119 for (; bit != 0; bit--) { 1120 if (addrBytes[byte] & (1 << bit)) { 1121 prefix = 0; 1122 break; 1123 } 1124 } 1125 if (prefix > 0) { 1126 byte++; 1127 for (; byte < sizeof(struct in6_addr); byte++) { 1128 if (addrBytes[byte]) { 1129 prefix = 0; 1130 } 1131 } 1132 } 1133 } 1134 1135 return prefix; 1136 } 1137 1138 /* 1139 * Opens a socket for further ioct calls. proto is one of AF_INET or AF_INET6. 1140 */ 1141 static int openSocket(JNIEnv *env, int proto) { 1142 int sock; 1143 1144 if ((sock = socket(proto, SOCK_DGRAM, 0)) < 0) { 1145 // If we lack support for this address family or protocol, 1146 // don't throw an exception. 1147 if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) { 1148 JNU_ThrowByNameWithMessageAndLastError 1149 (env, JNU_JAVANETPKG "SocketException", "Socket creation failed"); 1150 } 1151 return -1; 1152 } 1153 1154 return sock; 1155 } 1156 1157 /** Linux **/ 1158 #if defined(__linux__) 1159 1160 /* 1161 * Opens a socket for further ioctl calls. Tries AF_INET socket first and 1162 * if it fails return AF_INET6 socket. 1163 */ 1164 static int openSocketWithFallback(JNIEnv *env, const char *ifname) { 1165 int sock; 1166 1167 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1168 if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { 1169 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1170 JNU_ThrowByNameWithMessageAndLastError 1171 (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 1172 return -1; 1173 } 1174 } else { // errno is not NOSUPPORT 1175 JNU_ThrowByNameWithMessageAndLastError 1176 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); 1177 return -1; 1178 } 1179 } 1180 1181 // Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or 1182 // IPv6 socket regardless of type of address of an interface. 1183 return sock; 1184 } 1185 1186 /* 1187 * Enumerates and returns all IPv4 interfaces on Linux. 1188 */ 1189 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { 1190 struct ifconf ifc; 1191 struct ifreq *ifreqP; 1192 char *buf = NULL; 1193 unsigned i; 1194 1195 // do a dummy SIOCGIFCONF to determine the buffer size 1196 // SIOCGIFCOUNT doesn't work 1197 ifc.ifc_buf = NULL; 1198 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { 1199 JNU_ThrowByNameWithMessageAndLastError 1200 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed"); 1201 return ifs; 1202 } 1203 1204 // call SIOCGIFCONF to enumerate the interfaces 1205 CHECKED_MALLOC3(buf, char *, ifc.ifc_len); 1206 ifc.ifc_buf = buf; 1207 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { 1208 JNU_ThrowByNameWithMessageAndLastError 1209 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed"); 1210 free(buf); 1211 return ifs; 1212 } 1213 1214 // iterate through each interface 1215 ifreqP = ifc.ifc_req; 1216 for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) { 1217 struct sockaddr addr, broadaddr, *broadaddrP = NULL; 1218 short prefix = 0; 1219 1220 // ignore non IPv4 addresses 1221 if (ifreqP->ifr_addr.sa_family != AF_INET) { 1222 continue; 1223 } 1224 1225 // save socket address 1226 memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr)); 1227 1228 // determine broadcast address, if applicable 1229 if ((ioctl(sock, SIOCGIFFLAGS, ifreqP) == 0) && 1230 ifreqP->ifr_flags & IFF_BROADCAST) { 1231 1232 // restore socket address to ifreqP 1233 memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr)); 1234 1235 if (ioctl(sock, SIOCGIFBRDADDR, ifreqP) == 0) { 1236 memcpy(&broadaddr, &(ifreqP->ifr_broadaddr), 1237 sizeof(struct sockaddr)); 1238 broadaddrP = &broadaddr; 1239 } 1240 } 1241 1242 // restore socket address to ifreqP 1243 memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr)); 1244 1245 // determine netmask 1246 if (ioctl(sock, SIOCGIFNETMASK, ifreqP) == 0) { 1247 prefix = translateIPv4AddressToPrefix( 1248 (struct sockaddr_in *)&(ifreqP->ifr_netmask)); 1249 } 1250 1251 // add interface to the list 1252 ifs = addif(env, sock, ifreqP->ifr_name, ifs, 1253 &addr, broadaddrP, AF_INET, prefix); 1254 1255 // in case of exception, free interface list and buffer and return NULL 1256 if ((*env)->ExceptionOccurred(env)) { 1257 free(buf); 1258 freeif(ifs); 1259 return NULL; 1260 } 1261 } 1262 1263 // free buffer 1264 free(buf); 1265 return ifs; 1266 } 1267 1268 /* 1269 * Enumerates and returns all IPv6 interfaces on Linux. 1270 */ 1271 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { 1272 FILE *f; 1273 char devname[21], addr6p[8][5]; 1274 int prefix, scope, dad_status, if_idx; 1275 1276 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { 1277 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", 1278 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 1279 addr6p[4], addr6p[5], addr6p[6], addr6p[7], 1280 &if_idx, &prefix, &scope, &dad_status, devname) != EOF) { 1281 1282 char addr6[40]; 1283 struct sockaddr_in6 addr; 1284 1285 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", 1286 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 1287 addr6p[4], addr6p[5], addr6p[6], addr6p[7]); 1288 1289 memset(&addr, 0, sizeof(struct sockaddr_in6)); 1290 inet_pton(AF_INET6, addr6, (void*)addr.sin6_addr.s6_addr); 1291 1292 // set scope ID to interface index 1293 addr.sin6_scope_id = if_idx; 1294 1295 // add interface to the list 1296 ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, 1297 NULL, AF_INET6, (short)prefix); 1298 1299 // if an exception occurred then return the list as is 1300 if ((*env)->ExceptionOccurred(env)) { 1301 break; 1302 } 1303 } 1304 fclose(f); 1305 } 1306 return ifs; 1307 } 1308 1309 /* 1310 * Try to get the interface index. 1311 */ 1312 static int getIndex(int sock, const char *name) { 1313 struct ifreq if2; 1314 memset((char *)&if2, 0, sizeof(if2)); 1315 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1); 1316 1317 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { 1318 return -1; 1319 } 1320 1321 return if2.ifr_ifindex; 1322 } 1323 1324 /* 1325 * Gets the Hardware address (usually MAC address) for the named interface. 1326 * On return puts the data in buf, and returns the length, in byte, of the 1327 * MAC address. Returns -1 if there is no hardware address on that interface. 1328 */ 1329 static int getMacAddress 1330 (JNIEnv *env, const char *ifname, const struct in_addr *addr, 1331 unsigned char *buf) 1332 { 1333 struct ifreq ifr; 1334 int i, sock; 1335 1336 if ((sock = openSocketWithFallback(env, ifname)) < 0) { 1337 return -1; 1338 } 1339 1340 memset((char *)&ifr, 0, sizeof(ifr)); 1341 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); 1342 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { 1343 JNU_ThrowByNameWithMessageAndLastError 1344 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFHWADDR) failed"); 1345 close(sock); 1346 return -1; 1347 } 1348 1349 close(sock); 1350 memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); 1351 1352 // all bytes to 0 means no hardware address 1353 for (i = 0; i < IFHWADDRLEN; i++) { 1354 if (buf[i] != 0) 1355 return IFHWADDRLEN; 1356 } 1357 1358 return -1; 1359 } 1360 1361 static int getMTU(JNIEnv *env, int sock, const char *ifname) { 1362 struct ifreq if2; 1363 memset((char *)&if2, 0, sizeof(if2)); 1364 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 1365 1366 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) { 1367 JNU_ThrowByNameWithMessageAndLastError 1368 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed"); 1369 return -1; 1370 } 1371 1372 return if2.ifr_mtu; 1373 } 1374 1375 static int getFlags(int sock, const char *ifname, int *flags) { 1376 struct ifreq if2; 1377 memset((char *)&if2, 0, sizeof(if2)); 1378 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 1379 1380 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) { 1381 return -1; 1382 } 1383 1384 if (sizeof(if2.ifr_flags) == sizeof(short)) { 1385 *flags = (if2.ifr_flags & 0xffff); 1386 } else { 1387 *flags = if2.ifr_flags; 1388 } 1389 return 0; 1390 } 1391 1392 #endif /* __linux__ */ 1393 1394 /** AIX **/ 1395 #if defined(_AIX) 1396 1397 /* seems getkerninfo is guarded by _KERNEL in the system headers */ 1398 /* see net/proto_uipc.h */ 1399 int getkerninfo(int, char *, int *, int32long64_t); 1400 1401 /* 1402 * Opens a socket for further ioctl calls. Tries AF_INET socket first and 1403 * if it fails return AF_INET6 socket. 1404 */ 1405 static int openSocketWithFallback(JNIEnv *env, const char *ifname) { 1406 int sock; 1407 1408 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1409 if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { 1410 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1411 JNU_ThrowByNameWithMessageAndLastError 1412 (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 1413 return -1; 1414 } 1415 } else { // errno is not NOSUPPORT 1416 JNU_ThrowByNameWithMessageAndLastError 1417 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); 1418 return -1; 1419 } 1420 } 1421 1422 return sock; 1423 } 1424 1425 /* 1426 * Enumerates and returns all IPv4 interfaces on AIX. 1427 */ 1428 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { 1429 struct ifconf ifc; 1430 struct ifreq *ifreqP; 1431 char *buf = NULL; 1432 unsigned i; 1433 1434 // call SIOCGSIZIFCONF to get the size of SIOCGIFCONF buffer 1435 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) { 1436 JNU_ThrowByNameWithMessageAndLastError 1437 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed"); 1438 return ifs; 1439 } 1440 1441 // call CSIOCGIFCONF instead of SIOCGIFCONF where interface 1442 // records will always have sizeof(struct ifreq) length. 1443 // Be aware that only IPv4 data is complete this way. 1444 CHECKED_MALLOC3(buf, char *, ifc.ifc_len); 1445 ifc.ifc_buf = buf; 1446 if (ioctl(sock, CSIOCGIFCONF, (char *)&ifc) < 0) { 1447 JNU_ThrowByNameWithMessageAndLastError 1448 (env, JNU_JAVANETPKG "SocketException", "ioctl(CSIOCGIFCONF) failed"); 1449 free(buf); 1450 return ifs; 1451 } 1452 1453 // iterate through each interface 1454 ifreqP = ifc.ifc_req; 1455 for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++, ifreqP++) { 1456 struct sockaddr addr, broadaddr, *broadaddrP = NULL; 1457 short prefix = 0; 1458 1459 // ignore non IPv4 addresses 1460 if (ifreqP->ifr_addr.sa_family != AF_INET) { 1461 continue; 1462 } 1463 1464 // save socket address 1465 memcpy(&addr, &(ifreqP->ifr_addr), sizeof(struct sockaddr)); 1466 1467 // determine broadcast address, if applicable 1468 if ((ioctl(sock, SIOCGIFFLAGS, ifreqP) == 0) && 1469 ifreqP->ifr_flags & IFF_BROADCAST) { 1470 1471 // restore socket address to ifreqP 1472 memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr)); 1473 1474 if (ioctl(sock, SIOCGIFBRDADDR, ifreqP) == 0) { 1475 memcpy(&broadaddr, &(ifreqP->ifr_broadaddr), 1476 sizeof(struct sockaddr)); 1477 broadaddrP = &broadaddr; 1478 } 1479 } 1480 1481 // restore socket address to ifreqP 1482 memcpy(&(ifreqP->ifr_addr), &addr, sizeof(struct sockaddr)); 1483 1484 // determine netmask 1485 if (ioctl(sock, SIOCGIFNETMASK, ifreqP) == 0) { 1486 prefix = translateIPv4AddressToPrefix( 1487 (struct sockaddr_in *)&(ifreqP->ifr_addr)); 1488 } 1489 1490 // add interface to the list 1491 ifs = addif(env, sock, ifreqP->ifr_name, ifs, 1492 &addr, broadaddrP, AF_INET, prefix); 1493 1494 // in case of exception, free interface list and buffer and return NULL 1495 if ((*env)->ExceptionOccurred(env)) { 1496 free(buf); 1497 freeif(ifs); 1498 return NULL; 1499 } 1500 } 1501 1502 // free buffer 1503 free(buf); 1504 return ifs; 1505 } 1506 1507 /* 1508 * Enumerates and returns all IPv6 interfaces on AIX. 1509 */ 1510 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { 1511 struct ifconf ifc; 1512 struct ifreq *ifreqP; 1513 char *buf, *cp, *cplimit; 1514 1515 // call SIOCGSIZIFCONF to get size for SIOCGIFCONF buffer 1516 if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) { 1517 JNU_ThrowByNameWithMessageAndLastError 1518 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGSIZIFCONF) failed"); 1519 return ifs; 1520 } 1521 1522 // call SIOCGIFCONF to enumerate the interfaces 1523 CHECKED_MALLOC3(buf, char *, ifc.ifc_len); 1524 ifc.ifc_buf = buf; 1525 if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { 1526 JNU_ThrowByNameWithMessageAndLastError 1527 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFCONF) failed"); 1528 free(buf); 1529 return ifs; 1530 } 1531 1532 // iterate through each interface 1533 ifreqP = ifc.ifc_req; 1534 cp = (char *)ifc.ifc_req; 1535 cplimit = cp + ifc.ifc_len; 1536 1537 for (; cp < cplimit; 1538 cp += (sizeof(ifreqP->ifr_name) + 1539 MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr)))) 1540 { 1541 ifreqP = (struct ifreq *)cp; 1542 short prefix = 0; 1543 1544 // ignore non IPv6 addresses 1545 if (ifreqP->ifr_addr.sa_family != AF_INET6) { 1546 continue; 1547 } 1548 1549 // determine netmask 1550 struct in6_ifreq if6; 1551 memset((char *)&if6, 0, sizeof(if6)); 1552 strncpy(if6.ifr_name, ifreqP->ifr_name, sizeof(if6.ifr_name) - 1); 1553 memcpy(&(if6.ifr_Addr), &(ifreqP->ifr_addr), 1554 sizeof(struct sockaddr_in6)); 1555 if (ioctl(sock, SIOCGIFNETMASK6, (char *)&if6) >= 0) { 1556 prefix = translateIPv6AddressToPrefix(&(if6.ifr_Addr)); 1557 } 1558 1559 // set scope ID to interface index 1560 ((struct sockaddr_in6 *)&(ifreqP->ifr_addr))->sin6_scope_id = 1561 getIndex(sock, ifreqP->ifr_name); 1562 1563 // add interface to the list 1564 ifs = addif(env, sock, ifreqP->ifr_name, ifs, 1565 (struct sockaddr *)&(ifreqP->ifr_addr), 1566 NULL, AF_INET6, prefix); 1567 1568 // if an exception occurred then free the list 1569 if ((*env)->ExceptionOccurred(env)) { 1570 free(buf); 1571 freeif(ifs); 1572 return NULL; 1573 } 1574 } 1575 1576 // free buffer 1577 free(buf); 1578 return ifs; 1579 } 1580 1581 /* 1582 * Try to get the interface index. 1583 */ 1584 static int getIndex(int sock, const char *name) { 1585 int index = if_nametoindex(name); 1586 return (index == 0) ? -1 : index; 1587 } 1588 1589 /* 1590 * Gets the Hardware address (usually MAC address) for the named interface. 1591 * On return puts the data in buf, and returns the length, in byte, of the 1592 * MAC address. Returns -1 if there is no hardware address on that interface. 1593 */ 1594 static int getMacAddress 1595 (JNIEnv *env, const char *ifname, const struct in_addr *addr, 1596 unsigned char *buf) 1597 { 1598 int size; 1599 struct kinfo_ndd *nddp; 1600 void *end; 1601 1602 size = getkerninfo(KINFO_NDD, 0, 0, 0); 1603 if (size == 0) { 1604 return -1; 1605 } 1606 1607 if (size < 0) { 1608 perror("getkerninfo 1"); 1609 return -1; 1610 } 1611 1612 nddp = (struct kinfo_ndd *)malloc(size); 1613 1614 if (!nddp) { 1615 JNU_ThrowOutOfMemoryError(env, 1616 "Network interface getMacAddress native buffer allocation failed"); 1617 return -1; 1618 } 1619 1620 if (getkerninfo(KINFO_NDD, (char*) nddp, &size, 0) < 0) { 1621 perror("getkerninfo 2"); 1622 free(nddp); 1623 return -1; 1624 } 1625 1626 end = (void *)nddp + size; 1627 while ((void *)nddp < end) { 1628 if (!strcmp(nddp->ndd_alias, ifname) || 1629 !strcmp(nddp->ndd_name, ifname)) { 1630 bcopy(nddp->ndd_addr, buf, 6); 1631 free(nddp); 1632 return 6; 1633 } else { 1634 nddp++; 1635 } 1636 } 1637 1638 free(nddp); 1639 return -1; 1640 } 1641 1642 static int getMTU(JNIEnv *env, int sock, const char *ifname) { 1643 struct ifreq if2; 1644 memset((char *)&if2, 0, sizeof(if2)); 1645 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 1646 1647 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) { 1648 JNU_ThrowByNameWithMessageAndLastError 1649 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed"); 1650 return -1; 1651 } 1652 1653 return if2.ifr_mtu; 1654 } 1655 1656 static int getFlags(int sock, const char *ifname, int *flags) { 1657 struct ifreq if2; 1658 memset((char *)&if2, 0, sizeof(if2)); 1659 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 1660 1661 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) { 1662 return -1; 1663 } 1664 1665 if (sizeof(if2.ifr_flags) == sizeof(short)) { 1666 *flags = (if2.ifr_flags & 0xffff); 1667 } else { 1668 *flags = if2.ifr_flags; 1669 } 1670 return 0; 1671 } 1672 1673 #endif /* _AIX */ 1674 1675 /** Solaris **/ 1676 #if defined(__solaris__) 1677 1678 /* 1679 * Opens a socket for further ioctl calls. Tries AF_INET socket first and 1680 * if it fails return AF_INET6 socket. 1681 */ 1682 static int openSocketWithFallback(JNIEnv *env, const char *ifname) { 1683 int sock, alreadyV6 = 0; 1684 struct lifreq if2; 1685 1686 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1687 if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { 1688 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1689 JNU_ThrowByNameWithMessageAndLastError 1690 (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 1691 return -1; 1692 } 1693 alreadyV6 = 1; 1694 } else { // errno is not NOSUPPORT 1695 JNU_ThrowByNameWithMessageAndLastError 1696 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); 1697 return -1; 1698 } 1699 } 1700 1701 // Solaris requires that we have an IPv6 socket to query an interface 1702 // without an IPv4 address - check it here. POSIX 1 require the kernel to 1703 // return ENOTTY if the call is inappropriate for a device e.g. the NETMASK 1704 // for a device having IPv6 only address but not all devices follow the 1705 // standard so fall back on any error. It's not an ecologically friendly 1706 // gesture but more reliable. 1707 if (!alreadyV6) { 1708 memset((char *)&if2, 0, sizeof(if2)); 1709 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); 1710 if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) { 1711 close(sock); 1712 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1713 JNU_ThrowByNameWithMessageAndLastError 1714 (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 1715 return -1; 1716 } 1717 } 1718 } 1719 1720 return sock; 1721 } 1722 1723 /* 1724 * Enumerates and returns all IPv4 interfaces on Solaris. 1725 */ 1726 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { 1727 struct lifconf ifc; 1728 struct lifreq *ifreqP; 1729 struct lifnum numifs; 1730 char *buf = NULL; 1731 unsigned i; 1732 1733 // call SIOCGLIFNUM to get the interface count 1734 numifs.lifn_family = AF_INET; 1735 numifs.lifn_flags = 0; 1736 if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { 1737 JNU_ThrowByNameWithMessageAndLastError 1738 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed"); 1739 return ifs; 1740 } 1741 1742 // call SIOCGLIFCONF to enumerate the interfaces 1743 ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq); 1744 CHECKED_MALLOC3(buf, char *, ifc.lifc_len); 1745 ifc.lifc_buf = buf; 1746 ifc.lifc_family = AF_INET; 1747 ifc.lifc_flags = 0; 1748 if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { 1749 JNU_ThrowByNameWithMessageAndLastError 1750 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed"); 1751 free(buf); 1752 return ifs; 1753 } 1754 1755 // iterate through each interface 1756 ifreqP = ifc.lifc_req; 1757 for (i = 0; i < numifs.lifn_count; i++, ifreqP++) { 1758 struct sockaddr addr, *broadaddrP = NULL; 1759 1760 // ignore non IPv4 addresses 1761 if (ifreqP->lifr_addr.ss_family != AF_INET) { 1762 continue; 1763 } 1764 1765 // save socket address 1766 memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr)); 1767 1768 // determine broadcast address, if applicable 1769 if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) && 1770 ifreqP->lifr_flags & IFF_BROADCAST) { 1771 1772 // restore socket address to ifreqP 1773 memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr)); 1774 1775 // query broadcast address and set pointer to it 1776 if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) { 1777 broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr); 1778 } 1779 } 1780 1781 // add to the list 1782 ifs = addif(env, sock, ifreqP->lifr_name, ifs, 1783 &addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen); 1784 1785 // if an exception occurred we return immediately 1786 if ((*env)->ExceptionOccurred(env)) { 1787 free(buf); 1788 return ifs; 1789 } 1790 } 1791 1792 // free buffer 1793 free(buf); 1794 return ifs; 1795 } 1796 1797 /* 1798 * Enumerates and returns all IPv6 interfaces on Solaris. 1799 */ 1800 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { 1801 struct lifconf ifc; 1802 struct lifreq *ifreqP; 1803 struct lifnum numifs; 1804 char *buf = NULL; 1805 unsigned i; 1806 1807 // call SIOCGLIFNUM to get the interface count 1808 numifs.lifn_family = AF_INET6; 1809 numifs.lifn_flags = 0; 1810 if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { 1811 JNU_ThrowByNameWithMessageAndLastError 1812 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed"); 1813 return ifs; 1814 } 1815 1816 // call SIOCGLIFCONF to enumerate the interfaces 1817 ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq); 1818 CHECKED_MALLOC3(buf, char *, ifc.lifc_len); 1819 ifc.lifc_buf = buf; 1820 ifc.lifc_family = AF_INET6; 1821 ifc.lifc_flags = 0; 1822 if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { 1823 JNU_ThrowByNameWithMessageAndLastError 1824 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed"); 1825 free(buf); 1826 return ifs; 1827 } 1828 1829 // iterate through each interface 1830 ifreqP = ifc.lifc_req; 1831 for (i = 0; i < numifs.lifn_count; i++, ifreqP++) { 1832 1833 // ignore non IPv6 addresses 1834 if (ifreqP->lifr_addr.ss_family != AF_INET6) { 1835 continue; 1836 } 1837 1838 // set scope ID to interface index 1839 ((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id = 1840 getIndex(sock, ifreqP->lifr_name); 1841 1842 // add to the list 1843 ifs = addif(env, sock, ifreqP->lifr_name, ifs, 1844 (struct sockaddr *)&(ifreqP->lifr_addr), 1845 NULL, AF_INET6, (short)ifreqP->lifr_addrlen); 1846 1847 // if an exception occurred we return immediately 1848 if ((*env)->ExceptionOccurred(env)) { 1849 free(buf); 1850 return ifs; 1851 } 1852 } 1853 1854 // free buffer 1855 free(buf); 1856 return ifs; 1857 } 1858 1859 /* 1860 * Try to get the interface index. 1861 * (Not supported on Solaris 2.6 or 7) 1862 */ 1863 static int getIndex(int sock, const char *name) { 1864 struct lifreq if2; 1865 memset((char *)&if2, 0, sizeof(if2)); 1866 strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1); 1867 1868 if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) { 1869 return -1; 1870 } 1871 1872 return if2.lifr_index; 1873 } 1874 1875 /* 1876 * Solaris specific DLPI code to get hardware address from a device. 1877 * Unfortunately, at least up to Solaris X, you have to have special 1878 * privileges (i.e. be root). 1879 */ 1880 static int getMacFromDevice 1881 (JNIEnv *env, const char *ifname, unsigned char *retbuf) 1882 { 1883 char style1dev[MAXPATHLEN]; 1884 int fd; 1885 dl_phys_addr_req_t dlpareq; 1886 dl_phys_addr_ack_t *dlpaack; 1887 dl_error_ack_t *dlerack; 1888 struct strbuf msg; 1889 char buf[128]; 1890 int flags = 0; 1891 1892 // Device is in /dev. e.g.: /dev/bge0 1893 strcpy(style1dev, DEV_PREFIX); 1894 strcat(style1dev, ifname); 1895 if ((fd = open(style1dev, O_RDWR)) < 0) { 1896 // Can't open it. We probably are missing the privilege. 1897 // We'll have to try something else 1898 return 0; 1899 } 1900 1901 dlpareq.dl_primitive = DL_PHYS_ADDR_REQ; 1902 dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR; 1903 1904 msg.buf = (char *)&dlpareq; 1905 msg.len = DL_PHYS_ADDR_REQ_SIZE; 1906 1907 if (putmsg(fd, &msg, NULL, 0) < 0) { 1908 JNU_ThrowByNameWithMessageAndLastError 1909 (env, JNU_JAVANETPKG "SocketException", "putmsg() failed"); 1910 return -1; 1911 } 1912 1913 dlpaack = (dl_phys_addr_ack_t *)buf; 1914 1915 msg.buf = (char *)buf; 1916 msg.len = 0; 1917 msg.maxlen = sizeof (buf); 1918 if (getmsg(fd, &msg, NULL, &flags) < 0) { 1919 JNU_ThrowByNameWithMessageAndLastError 1920 (env, JNU_JAVANETPKG "SocketException", "getmsg() failed"); 1921 return -1; 1922 } 1923 1924 if (dlpaack->dl_primitive == DL_ERROR_ACK) { 1925 dlerack = (dl_error_ack_t *)buf; 1926 if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) { 1927 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", 1928 "Couldn't obtain physical address\n"); 1929 return -1; 1930 } 1931 if (dlerack->dl_errno == DL_UNSUPPORTED) { 1932 // fallback to lookup in the ARP table 1933 return 0; 1934 } 1935 } 1936 1937 if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) { 1938 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", 1939 "Couldn't obtain phys addr\n"); 1940 return -1; 1941 } 1942 1943 memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length); 1944 return dlpaack->dl_addr_length; 1945 } 1946 1947 /* 1948 * Gets the Hardware address (usually MAC address) for the named interface. 1949 * On return puts the data in buf, and returns the length, in byte, of the 1950 * MAC address. Returns -1 if there is no hardware address on that interface. 1951 */ 1952 static int getMacAddress 1953 (JNIEnv *env, const char *ifname, const struct in_addr *addr, 1954 unsigned char *buf) 1955 { 1956 struct lifreq if2; 1957 int len, i, sock; 1958 1959 if ((sock = openSocketWithFallback(env, ifname)) < 0) { 1960 return -1; 1961 } 1962 1963 // First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails 1964 // try the old way. 1965 memset((char *)&if2, 0, sizeof(if2)); 1966 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); 1967 1968 if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) { 1969 struct sockaddr_dl *sp; 1970 sp = (struct sockaddr_dl *)&if2.lifr_addr; 1971 memcpy(buf, &sp->sdl_data[0], sp->sdl_alen); 1972 close(sock); 1973 return sp->sdl_alen; 1974 } 1975 1976 // On Solaris we have to use DLPI, but it will only work if we have 1977 // privileged access (i.e. root). If that fails, we try a lookup 1978 // in the ARP table, which requires an IPv4 address. 1979 if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) { 1980 struct arpreq arpreq; 1981 struct sockaddr_in *sin; 1982 struct sockaddr_in ipAddr; 1983 1984 len = 6; //??? 1985 1986 sin = (struct sockaddr_in *)&arpreq.arp_pa; 1987 memset((char *)&arpreq, 0, sizeof(struct arpreq)); 1988 ipAddr.sin_port = 0; 1989 ipAddr.sin_family = AF_INET; 1990 memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr)); 1991 memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); 1992 arpreq.arp_flags= ATF_PUBL; 1993 1994 if (ioctl(sock, SIOCGARP, &arpreq) < 0) { 1995 close(sock); 1996 return -1; 1997 } 1998 1999 memcpy(buf, &arpreq.arp_ha.sa_data[0], len); 2000 } 2001 close(sock); 2002 2003 // all bytes to 0 means no hardware address 2004 for (i = 0; i < len; i++) { 2005 if (buf[i] != 0) 2006 return len; 2007 } 2008 2009 return -1; 2010 } 2011 2012 static int getMTU(JNIEnv *env, int sock, const char *ifname) { 2013 struct lifreq if2; 2014 memset((char *)&if2, 0, sizeof(if2)); 2015 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); 2016 2017 if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) { 2018 JNU_ThrowByNameWithMessageAndLastError 2019 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed"); 2020 return -1; 2021 } 2022 2023 return if2.lifr_mtu; 2024 } 2025 2026 static int getFlags(int sock, const char *ifname, int *flags) { 2027 struct lifreq if2; 2028 memset((char *)&if2, 0, sizeof(if2)); 2029 strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1); 2030 2031 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) { 2032 return -1; 2033 } 2034 2035 *flags = if2.lifr_flags; 2036 return 0; 2037 } 2038 2039 #endif /* __solaris__ */ 2040 2041 /** BSD **/ 2042 #if defined(_ALLBSD_SOURCE) 2043 2044 /* 2045 * Opens a socket for further ioctl calls. Tries AF_INET socket first and 2046 * if it fails return AF_INET6 socket. 2047 */ 2048 static int openSocketWithFallback(JNIEnv *env, const char *ifname) { 2049 int sock; 2050 2051 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 2052 if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { 2053 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 2054 JNU_ThrowByNameWithMessageAndLastError 2055 (env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 2056 return -1; 2057 } 2058 } else { // errno is not NOSUPPORT 2059 JNU_ThrowByNameWithMessageAndLastError 2060 (env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); 2061 return -1; 2062 } 2063 } 2064 2065 return sock; 2066 } 2067 2068 /* 2069 * Enumerates and returns all IPv4 interfaces on BSD. 2070 */ 2071 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { 2072 struct ifaddrs *ifa, *origifa; 2073 2074 if (getifaddrs(&origifa) != 0) { 2075 JNU_ThrowByNameWithMessageAndLastError 2076 (env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed"); 2077 return ifs; 2078 } 2079 2080 for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { 2081 struct sockaddr *broadaddrP = NULL; 2082 2083 // ignore non IPv4 addresses 2084 if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) 2085 continue; 2086 2087 // set ifa_broadaddr, if there is one 2088 if ((ifa->ifa_flags & IFF_POINTOPOINT) == 0 && 2089 ifa->ifa_flags & IFF_BROADCAST) { 2090 broadaddrP = ifa->ifa_dstaddr; 2091 } 2092 2093 // add interface to the list 2094 ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, 2095 broadaddrP, AF_INET, 2096 translateIPv4AddressToPrefix((struct sockaddr_in *) 2097 ifa->ifa_netmask)); 2098 2099 // if an exception occurred then free the list 2100 if ((*env)->ExceptionOccurred(env)) { 2101 freeifaddrs(origifa); 2102 freeif(ifs); 2103 return NULL; 2104 } 2105 } 2106 2107 // free ifaddrs buffer 2108 freeifaddrs(origifa); 2109 return ifs; 2110 } 2111 2112 /* 2113 * Enumerates and returns all IPv6 interfaces on BSD. 2114 */ 2115 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { 2116 struct ifaddrs *ifa, *origifa; 2117 2118 if (getifaddrs(&origifa) != 0) { 2119 JNU_ThrowByNameWithMessageAndLastError 2120 (env, JNU_JAVANETPKG "SocketException", "getifaddrs() failed"); 2121 return ifs; 2122 } 2123 2124 for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { 2125 // ignore non IPv6 addresses 2126 if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6) 2127 continue; 2128 2129 // set scope ID to interface index 2130 ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id = 2131 getIndex(sock, ifa->ifa_name); 2132 2133 // add interface to the list 2134 ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, NULL, 2135 AF_INET6, 2136 translateIPv6AddressToPrefix((struct sockaddr_in6 *) 2137 ifa->ifa_netmask)); 2138 2139 // if an exception occurred then free the list 2140 if ((*env)->ExceptionOccurred(env)) { 2141 freeifaddrs(origifa); 2142 freeif(ifs); 2143 return NULL; 2144 } 2145 } 2146 2147 // free ifaddrs buffer 2148 freeifaddrs(origifa); 2149 return ifs; 2150 } 2151 2152 /* 2153 * Try to get the interface index. 2154 */ 2155 static int getIndex(int sock, const char *name) { 2156 #if !defined(__FreeBSD__) 2157 int index = if_nametoindex(name); 2158 return (index == 0) ? -1 : index; 2159 #else 2160 struct ifreq if2; 2161 memset((char *)&if2, 0, sizeof(if2)); 2162 strncpy(if2.ifr_name, name, sizeof(if2.ifr_name) - 1); 2163 2164 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { 2165 return -1; 2166 } 2167 2168 return if2.ifr_index; 2169 #endif 2170 } 2171 2172 /* 2173 * Gets the Hardware address (usually MAC address) for the named interface. 2174 * On return puts the data in buf, and returns the length, in byte, of the 2175 * MAC address. Returns -1 if there is no hardware address on that interface. 2176 */ 2177 static int getMacAddress 2178 (JNIEnv *env, const char *ifname, const struct in_addr *addr, 2179 unsigned char *buf) 2180 { 2181 struct ifaddrs *ifa0, *ifa; 2182 struct sockaddr *saddr; 2183 int i; 2184 2185 // grab the interface list 2186 if (!getifaddrs(&ifa0)) { 2187 // cycle through the interfaces 2188 for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) { 2189 saddr = ifa->ifa_addr; 2190 if (saddr != NULL) { 2191 // link layer contains the MAC address 2192 if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) { 2193 struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr; 2194 // check the address has the correct length 2195 if (sadl->sdl_alen == ETHER_ADDR_LEN) { 2196 memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN); 2197 freeifaddrs(ifa0); 2198 return ETHER_ADDR_LEN; 2199 } 2200 } 2201 } 2202 } 2203 freeifaddrs(ifa0); 2204 } 2205 2206 return -1; 2207 } 2208 2209 static int getMTU(JNIEnv *env, int sock, const char *ifname) { 2210 struct ifreq if2; 2211 memset((char *)&if2, 0, sizeof(if2)); 2212 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 2213 2214 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) { 2215 JNU_ThrowByNameWithMessageAndLastError 2216 (env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGIFMTU) failed"); 2217 return -1; 2218 } 2219 2220 return if2.ifr_mtu; 2221 } 2222 2223 static int getFlags(int sock, const char *ifname, int *flags) { 2224 struct ifreq if2; 2225 memset((char *)&if2, 0, sizeof(if2)); 2226 strncpy(if2.ifr_name, ifname, sizeof(if2.ifr_name) - 1); 2227 2228 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) { 2229 return -1; 2230 } 2231 2232 if (sizeof(if2.ifr_flags) == sizeof(short)) { 2233 *flags = (if2.ifr_flags & 0xffff); 2234 } else { 2235 *flags = if2.ifr_flags; 2236 } 2237 return 0; 2238 } 2239 #endif /* _ALLBSD_SOURCE */