1 /* 2 * Copyright (c) 2000, 2011, 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 #include <linux/if_packet.h> 41 42 #include <sys/ioctl.h> 43 //#include <bits/ioctls.h> 44 #include <sys/utsname.h> 45 #include <stdio.h> 46 #include <ifaddrs.h> 47 48 #include "jvm.h" 49 #include "jni_util.h" 50 #include "net_util.h" 51 #include "JNIHelp.h" 52 53 #define NATIVE_METHOD(className, functionName, signature) \ 54 { #functionName, signature, (void*)(className ## _ ## functionName) } 55 56 typedef struct _netaddr { 57 struct sockaddr *addr; 58 struct sockaddr *brdcast; 59 short mask; 60 int family; /* to make searches simple */ 61 struct _netaddr *next; 62 } netaddr; 63 64 typedef struct _netif { 65 char *name; 66 int index; 67 char virtual; 68 69 uint8_t hwAddrLen; 70 uint8_t *hwAddr; 71 netaddr *addr; 72 struct _netif *childs; 73 struct _netif *next; 74 } netif; 75 76 /************************************************************************ 77 * NetworkInterface 78 */ 79 80 81 /************************************************************************ 82 * NetworkInterface 83 */ 84 jclass ni_class; 85 jfieldID ni_nameID; 86 jfieldID ni_indexID; 87 jfieldID ni_descID; 88 jfieldID ni_addrsID; 89 jfieldID ni_bindsID; 90 jfieldID ni_virutalID; 91 jfieldID ni_childsID; 92 jfieldID ni_parentID; 93 jfieldID ni_defaultIndexID; 94 jfieldID ni_hardwareAddrID; 95 jmethodID ni_ctrID; 96 97 static jclass ni_iacls; 98 static jclass ni_ia4cls; 99 static jclass ni_ia6cls; 100 static jclass ni_ibcls; 101 static jmethodID ni_ia4ctrID; 102 static jmethodID ni_ia6ctrID; 103 static jmethodID ni_ibctrID; 104 static jfieldID ni_ia6ipaddressID; 105 static jfieldID ni_ibaddressID; 106 static jfieldID ni_ib4broadcastID; 107 static jfieldID ni_ib4maskID; 108 109 /** Private methods declarations **/ 110 static jobject createNetworkInterface(JNIEnv *env, netif *ifs); 111 static int getFlags0(JNIEnv *env, jstring ifname); 112 113 static netif *enumInterfaces(JNIEnv *env); 114 115 static netif *addif(JNIEnv *env, int sock, struct ifaddrs *ifa, netif *ifs); 116 static void freeif(netif *ifs); 117 118 static int openSocket(JNIEnv *env, int proto); 119 static int openSocketWithFallback(JNIEnv *env, const char *ifname); 120 121 static int getIndex(int sock, const char *ifname); 122 123 static int getFlags(int sock, const char *ifname, int *flags); 124 static int getMTU(JNIEnv *env, int sock, const char *ifname); 125 126 /******************* Java entry points *****************************/ 127 128 static void NetworkInterface_init(JNIEnv *env) { 129 ni_class = (*env)->FindClass(env,"java/net/NetworkInterface"); 130 ni_class = (*env)->NewGlobalRef(env, ni_class); 131 ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;"); 132 ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I"); 133 ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;"); 134 ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;"); 135 ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;"); 136 ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z"); 137 ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;"); 138 ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;"); 139 ni_hardwareAddrID = (*env)->GetFieldID(env, ni_class, "hardwareAddr", "[B"); 140 ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V"); 141 142 ni_iacls = (*env)->FindClass(env, "java/net/InetAddress"); 143 ni_iacls = (*env)->NewGlobalRef(env, ni_iacls); 144 ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address"); 145 ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls); 146 ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address"); 147 ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); 148 ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress"); 149 ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls); 150 ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V"); 151 ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V"); 152 ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V"); 153 ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); 154 ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;"); 155 ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;"); 156 ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S"); 157 ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", "I"); 158 } 159 160 161 /* 162 * Class: java_net_NetworkInterface 163 * Method: getByName0 164 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 165 */ 166 JNIEXPORT jobject JNICALL NetworkInterface_getByName0 167 (JNIEnv *env, jclass cls, jstring name) { 168 169 netif *ifs, *curr; 170 jboolean isCopy; 171 const char* name_utf; 172 jobject obj = NULL; 173 174 ifs = enumInterfaces(env); 175 if (ifs == NULL) { 176 return NULL; 177 } 178 179 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 180 181 /* 182 * Search the list of interface based on name 183 */ 184 curr = ifs; 185 while (curr != NULL) { 186 if (strcmp(name_utf, curr->name) == 0) { 187 break; 188 } 189 curr = curr->next; 190 } 191 192 /* if found create a NetworkInterface */ 193 if (curr != NULL) {; 194 obj = createNetworkInterface(env, curr); 195 } 196 197 /* release the UTF string and interface list */ 198 (*env)->ReleaseStringUTFChars(env, name, name_utf); 199 freeif(ifs); 200 201 return obj; 202 } 203 204 205 /* 206 * Class: java_net_NetworkInterface 207 * Method: getByIndex0 208 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 209 */ 210 JNIEXPORT jobject JNICALL NetworkInterface_getByIndex0 211 (JNIEnv *env, jclass cls, jint index) { 212 213 netif *ifs, *curr; 214 jobject obj = NULL; 215 216 if (index <= 0) { 217 return NULL; 218 } 219 220 ifs = enumInterfaces(env); 221 if (ifs == NULL) { 222 return NULL; 223 } 224 225 /* 226 * Search the list of interface based on index 227 */ 228 curr = ifs; 229 while (curr != NULL) { 230 if (index == curr->index) { 231 break; 232 } 233 curr = curr->next; 234 } 235 236 /* if found create a NetworkInterface */ 237 if (curr != NULL) {; 238 obj = createNetworkInterface(env, curr); 239 } 240 241 freeif(ifs); 242 return obj; 243 } 244 245 /* 246 * Class: java_net_NetworkInterface 247 * Method: getByInetAddress0 248 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; 249 */ 250 JNIEXPORT jobject JNICALL NetworkInterface_getByInetAddress0 251 (JNIEnv *env, jclass cls, jobject iaObj) { 252 253 netif *ifs, *curr; 254 255 int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6; 256 257 jobject obj = NULL; 258 jboolean match = JNI_FALSE; 259 260 ifs = enumInterfaces(env); 261 if (ifs == NULL) { 262 return NULL; 263 } 264 265 curr = ifs; 266 while (curr != NULL) { 267 netaddr *addrP = curr->addr; 268 269 /* 270 * Iterate through each address on the interface 271 */ 272 while (addrP != NULL) { 273 274 if (family == addrP->family) { 275 if (family == AF_INET) { 276 int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr); 277 int address2 = getInetAddress_addr(env, iaObj); 278 279 if (address1 == address2) { 280 match = JNI_TRUE; 281 break; 282 } 283 } 284 285 if (family == AF_INET6) { 286 jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr); 287 jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID); 288 jbyte caddr[16]; 289 int i; 290 291 (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); 292 i = 0; 293 while (i < 16) { 294 if (caddr[i] != bytes[i]) { 295 break; 296 } 297 i++; 298 } 299 if (i >= 16) { 300 match = JNI_TRUE; 301 break; 302 } 303 } 304 } 305 306 if (match) { 307 break; 308 } 309 addrP = addrP->next; 310 } 311 312 if (match) { 313 break; 314 } 315 curr = curr->next; 316 } 317 318 /* if found create a NetworkInterface */ 319 if (match) {; 320 obj = createNetworkInterface(env, curr); 321 } 322 323 freeif(ifs); 324 return obj; 325 } 326 327 328 /* 329 * Class: java_net_NetworkInterface 330 * Method: getAll 331 * Signature: ()[Ljava/net/NetworkInterface; 332 */ 333 JNIEXPORT jobjectArray JNICALL NetworkInterface_getAll 334 (JNIEnv *env, jclass cls) { 335 336 netif *ifs, *curr; 337 jobjectArray netIFArr; 338 jint arr_index, ifCount; 339 340 ifs = enumInterfaces(env); 341 if (ifs == NULL) { 342 return NULL; 343 } 344 345 /* count the interface */ 346 ifCount = 0; 347 curr = ifs; 348 while (curr != NULL) { 349 ifCount++; 350 curr = curr->next; 351 } 352 353 /* allocate a NetworkInterface array */ 354 netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL); 355 if (netIFArr == NULL) { 356 freeif(ifs); 357 return NULL; 358 } 359 360 /* 361 * Iterate through the interfaces, create a NetworkInterface instance 362 * for each array element and populate the object. 363 */ 364 curr = ifs; 365 arr_index = 0; 366 while (curr != NULL) { 367 jobject netifObj; 368 369 netifObj = createNetworkInterface(env, curr); 370 if (netifObj == NULL) { 371 freeif(ifs); 372 return NULL; 373 } 374 375 /* put the NetworkInterface into the array */ 376 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj); 377 378 curr = curr->next; 379 } 380 381 freeif(ifs); 382 return netIFArr; 383 } 384 385 386 /* 387 * Class: java_net_NetworkInterface 388 * Method: isUp0 389 * Signature: (Ljava/lang/String;I)Z 390 */ 391 JNIEXPORT jboolean JNICALL NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) { 392 int ret = getFlags0(env, name); 393 return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE; 394 } 395 396 /* 397 * Class: java_net_NetworkInterface 398 * Method: isP2P0 399 * Signature: (Ljava/lang/String;I)Z 400 */ 401 JNIEXPORT jboolean JNICALL NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) { 402 int ret = getFlags0(env, name); 403 return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE; 404 } 405 406 /* 407 * Class: java_net_NetworkInterface 408 * Method: isLoopback0 409 * Signature: (Ljava/lang/String;I)Z 410 */ 411 JNIEXPORT jboolean JNICALL NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) { 412 int ret = getFlags0(env, name); 413 return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE; 414 } 415 416 /* 417 * Class: java_net_NetworkInterface 418 * Method: supportsMulticast0 419 * Signature: (Ljava/lang/String;I)Z 420 */ 421 JNIEXPORT jboolean JNICALL NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) { 422 int ret = getFlags0(env, name); 423 return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE; 424 } 425 426 /* 427 * Class: java_net_NetworkInterface 428 * Method: getMTU0 429 * Signature: ([bLjava/lang/String;I)I 430 */ 431 432 JNIEXPORT jint JNICALL NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) { 433 jboolean isCopy; 434 int ret = -1; 435 int sock; 436 const char* name_utf; 437 438 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 439 440 if ((sock =openSocketWithFallback(env, name_utf)) < 0) { 441 (*env)->ReleaseStringUTFChars(env, name, name_utf); 442 return JNI_FALSE; 443 } 444 445 ret = getMTU(env, sock, name_utf); 446 447 (*env)->ReleaseStringUTFChars(env, name, name_utf); 448 449 untagSocket(env, sock); 450 close(sock); 451 return ret; 452 } 453 454 /*** Private methods definitions ****/ 455 456 static int getFlags0(JNIEnv *env, jstring name) { 457 jboolean isCopy; 458 int ret, sock; 459 const char* name_utf; 460 int flags = 0; 461 462 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 463 464 if ((sock = openSocketWithFallback(env, name_utf)) < 0) { 465 (*env)->ReleaseStringUTFChars(env, name, name_utf); 466 return -1; 467 } 468 469 ret = getFlags(sock, name_utf, &flags); 470 471 untagSocket(env, sock); 472 close(sock); 473 (*env)->ReleaseStringUTFChars(env, name, name_utf); 474 475 if (ret < 0) { 476 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed"); 477 return -1; 478 } 479 480 return flags; 481 } 482 483 484 485 486 /* 487 * Create a NetworkInterface object, populate the name and index, and 488 * populate the InetAddress array based on the IP addresses for this 489 * interface. 490 */ 491 jobject createNetworkInterface(JNIEnv *env, netif *ifs) { 492 jobject netifObj; 493 jobject name; 494 jobjectArray addrArr; 495 jobjectArray bindArr; 496 jobjectArray childArr; 497 netaddr *addrs; 498 jint addr_index, addr_count, bind_index; 499 jint child_count, child_index; 500 netaddr *addrP; 501 netif *childP; 502 jobject tmp; 503 504 /* 505 * Create a NetworkInterface object and populate it 506 */ 507 netifObj = (*env)->NewObject(env, ni_class, ni_ctrID); 508 name = (*env)->NewStringUTF(env, ifs->name); 509 if (netifObj == NULL || name == NULL) { 510 return NULL; 511 } 512 (*env)->SetObjectField(env, netifObj, ni_nameID, name); 513 (*env)->SetObjectField(env, netifObj, ni_descID, name); 514 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); 515 (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE); 516 517 /* 518 * Set the hardware address 519 */ 520 if (ifs->hwAddrLen > 0 && ifs->hwAddr != NULL) { 521 jbyteArray hardwareAddr = (*env)->NewByteArray(env, ifs->hwAddrLen); 522 if (hardwareAddr == NULL) { 523 return NULL; 524 } 525 (*env)->SetByteArrayRegion(env, hardwareAddr, 0, ifs->hwAddrLen, (jbyte *)ifs->hwAddr); 526 (*env)->SetObjectField(env, netifObj, ni_hardwareAddrID, hardwareAddr); 527 } 528 529 /* 530 * Count the number of address on this interface 531 */ 532 addr_count = 0; 533 addrP = ifs->addr; 534 while (addrP != NULL) { 535 addr_count++; 536 addrP = addrP->next; 537 } 538 539 /* 540 * Create the array of InetAddresses 541 */ 542 addrArr = (*env)->NewObjectArray(env, addr_count, ni_iacls, NULL); 543 if (addrArr == NULL) { 544 return NULL; 545 } 546 547 bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL); 548 if (bindArr == NULL) { 549 return NULL; 550 } 551 addrP = ifs->addr; 552 addr_index = 0; 553 bind_index = 0; 554 while (addrP != NULL) { 555 jobject iaObj = NULL; 556 jobject ibObj = NULL; 557 558 if (addrP->family == AF_INET) { 559 iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); 560 if (iaObj) { 561 setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr)); 562 } 563 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 564 if (ibObj) { 565 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 566 if (addrP->brdcast) { 567 jobject ia2Obj = NULL; 568 ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); 569 if (ia2Obj) { 570 setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr)); 571 (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj); 572 } 573 } 574 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); 575 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); 576 } 577 } 578 579 if (addrP->family == AF_INET6) { 580 int scope=0; 581 iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); 582 if (iaObj) { 583 jbyteArray ipaddress = (*env)->NewByteArray(env, 16); 584 if (ipaddress == NULL) { 585 return NULL; 586 } 587 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, 588 (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); 589 590 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; 591 592 if (scope != 0) { /* zero is default value, no need to set */ 593 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); 594 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); 595 (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); 596 } 597 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); 598 } 599 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 600 if (ibObj) { 601 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 602 (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); 603 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); 604 } 605 } 606 607 if (iaObj == NULL) { 608 return NULL; 609 } 610 611 (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj); 612 addrP = addrP->next; 613 } 614 615 /* 616 * See if there is any virtual interface attached to this one. 617 */ 618 child_count = 0; 619 childP = ifs->childs; 620 while (childP) { 621 child_count++; 622 childP = childP->next; 623 } 624 625 childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL); 626 if (childArr == NULL) { 627 return NULL; 628 } 629 630 /* 631 * Create the NetworkInterface instances for the sub-interfaces as 632 * well. 633 */ 634 child_index = 0; 635 childP = ifs->childs; 636 while(childP) { 637 tmp = createNetworkInterface(env, childP); 638 if (tmp == NULL) { 639 return NULL; 640 } 641 (*env)->SetObjectField(env, tmp, ni_parentID, netifObj); 642 (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp); 643 childP = childP->next; 644 } 645 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); 646 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr); 647 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); 648 649 /* return the NetworkInterface */ 650 return netifObj; 651 } 652 653 /* 654 * Determines the mask length for IPV4/v6 addresses. 655 */ 656 static 657 int mask_address_to_mask_length(uint8_t *val, int size) { 658 int byte, bit, plen = 0; 659 660 for (byte = 0; byte < size && val[byte] == 0xff; byte++) { 661 plen += 8; 662 } 663 if (byte < size) { 664 for (bit = 7; bit > 0; bit--) { 665 if (val[byte] & (1 << bit)) plen++; 666 } 667 } 668 return plen; 669 } 670 671 /* 672 * Enumerates all interfaces 673 */ 674 static netif *enumInterfaces(JNIEnv *env) { 675 netif *ifs = NULL; 676 struct ifaddrs *ifa, *origifa; 677 678 int sock = openSocket(env, AF_INET); 679 if (sock < 0 && (*env)->ExceptionOccurred(env)) { 680 return NULL; 681 } 682 683 if (getifaddrs(&origifa) != 0) { 684 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", 685 "getifaddrs() function failed"); 686 return NULL; 687 } 688 689 for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) { 690 if (ifa->ifa_addr != NULL) { 691 switch (ifa->ifa_addr->sa_family) { 692 case AF_PACKET: 693 case AF_INET: 694 case AF_INET6: 695 ifs = addif(env, sock, ifa, ifs); 696 break; 697 } 698 } 699 } 700 701 freeifaddrs(origifa); 702 untagSocket(env, sock); 703 close(sock); 704 705 return ifs; 706 } 707 708 #define CHECKED_MALLOC3(_pointer,_type,_size) \ 709 do{ \ 710 _pointer = (_type)malloc( _size ); \ 711 if (_pointer == NULL) { \ 712 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \ 713 return ifs; /* return untouched list */ \ 714 } \ 715 } while(0) 716 717 718 /* 719 * Free an interface list (including any attached addresses) 720 */ 721 void freeif(netif *ifs) { 722 netif *currif = ifs; 723 netif *child = NULL; 724 725 while (currif != NULL) { 726 netaddr *addrP = currif->addr; 727 while (addrP != NULL) { 728 netaddr *next = addrP->next; 729 free(addrP); 730 addrP = next; 731 } 732 733 /* 734 * Don't forget to free the sub-interfaces. 735 */ 736 if (currif->childs != NULL) { 737 freeif(currif->childs); 738 } 739 740 /* 741 * Remove mac address 742 */ 743 if (currif->hwAddr != NULL) { 744 free(currif->hwAddr); 745 } 746 747 ifs = currif->next; 748 free(currif); 749 currif = ifs; 750 } 751 } 752 753 netif *addif(JNIEnv *env, int sock, struct ifaddrs *ifa, netif *ifs) 754 { 755 netif *currif = ifs, *parent; 756 netaddr *addrP = NULL; 757 758 char name[IFNAMSIZ], vname[IFNAMSIZ]; 759 760 char *name_colonP; 761 int mask; 762 int isVirtual = 0; 763 int addr_size; 764 int flags = 0; 765 766 /* 767 * If the interface name is a logical interface then we 768 * remove the unit number so that we have the physical 769 * interface (eg: hme0:1 -> hme0). NetworkInterface 770 * currently doesn't have any concept of physical vs. 771 * logical interfaces. 772 */ 773 strncpy(name, ifa->ifa_name, sizeof(name)); 774 name[sizeof(name) - 1] = '\0'; 775 *vname = 0; 776 777 /* 778 * Create and populate the netaddr node. If allocation fails 779 * return an un-updated list. 780 */ 781 switch(ifa->ifa_addr->sa_family) { 782 case AF_INET: 783 addr_size = sizeof(struct sockaddr_in); 784 break; 785 case AF_INET6: 786 addr_size = sizeof(struct sockaddr_in6); 787 break; 788 case AF_PACKET: 789 // Don't add an address entry, will extract data to netif struct 790 addr_size = 0; 791 break; 792 default: 793 return NULL; 794 } 795 796 if (addr_size > 0) { 797 /*Allocate for addr and brdcast at once*/ 798 CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size); 799 addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) ); 800 memcpy(addrP->addr, ifa->ifa_addr, addr_size); 801 802 addrP->family = ifa->ifa_addr->sa_family; 803 addrP->next = 0; 804 805 if (ifa->ifa_broadaddr && (ifa->ifa_flags & IFF_BROADCAST)) { 806 struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size); 807 addrP->brdcast = brdcast_to; 808 memcpy(brdcast_to, ifa->ifa_broadaddr, sizeof(struct sockaddr)); 809 } else { 810 addrP->brdcast = NULL; 811 } 812 813 if (ifa->ifa_netmask) { 814 if (ifa->ifa_netmask->sa_family == AF_INET) { 815 addrP->mask = mask_address_to_mask_length( 816 (uint8_t*)&(((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr), 817 sizeof(struct in_addr)); 818 } else if (ifa->ifa_netmask->sa_family == AF_INET6) { 819 addrP->mask = mask_address_to_mask_length( 820 (uint8_t*)&((struct sockaddr_in6*)ifa->ifa_netmask)->sin6_addr, 821 sizeof(struct in6_addr)); 822 } 823 } else { 824 addrP->mask = 0; 825 } 826 } 827 828 /** 829 * Deal with virtual interface with colon notaion e.g. eth0:1 830 */ 831 name_colonP = strchr(name, ':'); 832 if (name_colonP != NULL) { 833 /** 834 * This is a virtual interface. If we are able to access the parent 835 * we need to create a new entry if it doesn't exist yet *and* update 836 * the 'parent' interface with the new records. 837 */ 838 *name_colonP = 0; 839 if (getFlags(sock, name, &flags) < 0 || flags < 0) { 840 // failed to access parent interface do not create parent. 841 // We are a virtual interface with no parent. 842 isVirtual = 1; 843 *name_colonP = ':'; 844 } 845 else{ 846 // Got access to parent, so create it if necessary. 847 // Save original name to vname and truncate name by ':' 848 memcpy(vname, name, sizeof(vname) ); 849 vname[name_colonP - name] = ':'; 850 } 851 } 852 853 /* 854 * Check if this is a "new" interface. Use the interface 855 * name for matching because index isn't supported on 856 * Solaris 2.6 & 7. 857 */ 858 while (currif != NULL) { 859 if (strcmp(name, currif->name) == 0) { 860 break; 861 } 862 currif = currif->next; 863 } 864 865 /* 866 * If "new" then create an netif structure and 867 * insert it onto the list. 868 */ 869 if (currif == NULL) { 870 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + sizeof(name)); 871 currif->name = (char *) currif+sizeof(netif); 872 strncpy(currif->name, name, sizeof(name)); 873 currif->name[sizeof(name) - 1] = '\0'; 874 currif->index = getIndex(sock, name); 875 currif->addr = NULL; 876 currif->childs = NULL; 877 currif->virtual = isVirtual; 878 currif->hwAddrLen = 0; 879 currif->hwAddr = NULL; 880 currif->next = ifs; 881 ifs = currif; 882 } 883 884 /* 885 * Insert the mac address on the interface 886 */ 887 if (ifa->ifa_addr->sa_family == AF_PACKET) { 888 struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr; 889 890 if (s->sll_halen > 0) { 891 /* 892 * All bytes to 0 means no hardware address. 893 */ 894 int i; 895 for (i = 0;i < s->sll_halen; ++i) { 896 if (s->sll_addr[i] != 0) { 897 break; 898 } 899 } 900 if (i != s->sll_halen && currif->hwAddr == NULL) { 901 CHECKED_MALLOC3(currif->hwAddr, uint8_t *, s->sll_halen); 902 memcpy(currif->hwAddr, s->sll_addr, s->sll_halen); 903 currif->hwAddrLen = s->sll_halen; 904 } 905 } 906 } 907 908 /* 909 * Finally insert the address on the interface 910 */ 911 if (addrP != NULL) { 912 addrP->next = currif->addr; 913 currif->addr = addrP; 914 } 915 916 parent = currif; 917 918 /** 919 * Let's deal with the virtual interface now. 920 */ 921 if (vname[0]) { 922 netaddr *tmpaddr; 923 924 currif = parent->childs; 925 926 while (currif != NULL) { 927 if (strcmp(vname, currif->name) == 0) { 928 break; 929 } 930 currif = currif->next; 931 } 932 933 if (currif == NULL) { 934 CHECKED_MALLOC3(currif, netif *, sizeof(netif) + sizeof(name)); 935 currif->name = (char *) currif + sizeof(netif); 936 strncpy(currif->name, vname, sizeof(name)); 937 currif->name[sizeof(name) - 1] = '\0'; 938 currif->index = getIndex(sock, vname); 939 currif->addr = NULL; 940 /* Need to duplicate the addr entry? */ 941 currif->virtual = 1; 942 currif->childs = NULL; 943 currif->next = parent->childs; 944 parent->childs = currif; 945 } 946 947 CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size); 948 memcpy(tmpaddr, addrP, sizeof(netaddr)); 949 if (addrP->addr != NULL) { 950 tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ; 951 memcpy(tmpaddr->addr, addrP->addr, addr_size); 952 } 953 954 if (addrP->brdcast != NULL) { 955 tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size); 956 memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size); 957 } 958 959 tmpaddr->next = currif->addr; 960 currif->addr = tmpaddr; 961 } 962 963 return ifs; 964 } 965 966 /* Open socket for further ioct calls 967 * proto is AF_INET/AF_INET6 968 */ 969 static int openSocket(JNIEnv *env, int proto){ 970 int sock; 971 972 if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) { 973 /* 974 * If EPROTONOSUPPORT is returned it means we don't have 975 * support for this proto so don't throw an exception. 976 */ 977 if (errno != EPROTONOSUPPORT) { 978 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed"); 979 } 980 return -1; 981 } 982 983 tagSocket(env, sock); 984 return sock; 985 } 986 987 988 /** Linux **/ 989 990 /* Open socket for further ioct calls, try v4 socket first and 991 * if it falls return v6 socket 992 */ 993 994 static int openSocketWithFallback(JNIEnv *env, const char *ifname){ 995 int sock; 996 struct ifreq if2; 997 998 if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 999 if (errno == EPROTONOSUPPORT){ 1000 if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){ 1001 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); 1002 return -1; 1003 } 1004 } 1005 else{ // errno is not NOSUPPORT 1006 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); 1007 return -1; 1008 } 1009 } 1010 1011 /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type 1012 of address of an interface */ 1013 1014 tagSocket(env, sock); 1015 return sock; 1016 } 1017 1018 static int getIndex(int sock, const char *name){ 1019 /* 1020 * Try to get the interface index 1021 * (Not supported on Solaris 2.6 or 7) 1022 */ 1023 struct ifreq if2; 1024 strcpy(if2.ifr_name, name); 1025 1026 if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { 1027 return -1; 1028 } 1029 1030 return if2.ifr_ifindex; 1031 } 1032 1033 static int getMTU(JNIEnv *env, int sock, const char *ifname) { 1034 struct ifreq if2; 1035 1036 memset((char *) &if2, 0, sizeof(if2)); 1037 strcpy(if2.ifr_name, ifname); 1038 1039 if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) { 1040 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed"); 1041 return -1; 1042 } 1043 1044 return if2.ifr_mtu; 1045 } 1046 1047 static int getFlags(int sock, const char *ifname, int *flags) { 1048 struct ifreq if2; 1049 1050 memset((char *) &if2, 0, sizeof(if2)); 1051 strcpy(if2.ifr_name, ifname); 1052 1053 if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){ 1054 return -1; 1055 } 1056 1057 if (sizeof(if2.ifr_flags) == sizeof(short)) { 1058 *flags = (if2.ifr_flags & 0xffff); 1059 } else { 1060 *flags = if2.ifr_flags; 1061 } 1062 return 0; 1063 } 1064 1065 static JNINativeMethod gMethods[] = { 1066 NATIVE_METHOD(NetworkInterface, getMTU0, "(Ljava/lang/String;I)I"), 1067 NATIVE_METHOD(NetworkInterface, supportsMulticast0, "(Ljava/lang/String;I)Z"), 1068 NATIVE_METHOD(NetworkInterface, isLoopback0, "(Ljava/lang/String;I)Z"), 1069 NATIVE_METHOD(NetworkInterface, isP2P0, "(Ljava/lang/String;I)Z"), 1070 NATIVE_METHOD(NetworkInterface, isUp0, "(Ljava/lang/String;I)Z"), 1071 NATIVE_METHOD(NetworkInterface, getAll, "()[Ljava/net/NetworkInterface;"), 1072 NATIVE_METHOD(NetworkInterface, getByInetAddress0, "(Ljava/net/InetAddress;)Ljava/net/NetworkInterface;"), 1073 NATIVE_METHOD(NetworkInterface, getByIndex0, "(I)Ljava/net/NetworkInterface;"), 1074 NATIVE_METHOD(NetworkInterface, getByName0, "(Ljava/lang/String;)Ljava/net/NetworkInterface;"), 1075 }; 1076 1077 void register_java_net_NetworkInterface(JNIEnv* env) { 1078 jniRegisterNativeMethods(env, "java/net/NetworkInterface", gMethods, NELEM(gMethods)); 1079 NetworkInterface_init(env); 1080 } 1081