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