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