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