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