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