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