1 /* 2 * Copyright (c) 2003, 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 #include <stdlib.h> 27 #include <windows.h> 28 #include <winsock2.h> /* needed for htonl */ 29 #include <iprtrmib.h> 30 #include <assert.h> 31 32 #include "java_net_NetworkInterface.h" 33 #include "jni_util.h" 34 35 #include "NetworkInterface.h" 36 #include "net_util.h" 37 38 /* 39 * Windows implementation of the java.net.NetworkInterface native methods. 40 * This module provides the implementations of getAll, getByName, getByIndex, 41 * and getByAddress. 42 */ 43 44 extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP); 45 int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP); 46 47 #ifdef DEBUG 48 void printnif (netif *nif) { 49 #ifdef _WIN64 50 printf ("nif:0x%I64x name:%s\n", nif,nif->name); 51 #else 52 printf ("nif:0x%x name:%s\n", nif,nif->name); 53 #endif 54 if (nif->dNameIsUnicode) { 55 printf ("dName:%S index:%d ", nif->displayName,nif->index); 56 } else { 57 printf ("dName:%s index:%d ", nif->displayName,nif->index); 58 } 59 printf ("naddrs:%d\n", nif->naddrs); 60 } 61 62 void printnifs (netif *netifPP, char *str) { 63 netif *nif; 64 printf ("%s\n", str); 65 for (nif=netifPP; nif!=NULL; nif=nif->next) { 66 printnif (nif); 67 } 68 printf("-----------------\n"); 69 } 70 71 #endif 72 73 static int bufsize = 1024; 74 75 /* 76 * return an array of IP_ADAPTER_ADDRESSES containing one element 77 * for each adapter on the system. Returned in *adapters. 78 * Buffer is malloc'd and must be freed (unless error returned) 79 */ 80 static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) { 81 DWORD ret, flags; 82 IP_ADAPTER_ADDRESSES *adapterInfo; 83 ULONG len; 84 adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize); 85 86 if (adapterInfo == NULL) { 87 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); 88 return -1; 89 } 90 91 len = bufsize; 92 flags = GAA_FLAG_SKIP_DNS_SERVER; 93 flags |= GAA_FLAG_SKIP_MULTICAST; 94 flags |= GAA_FLAG_INCLUDE_PREFIX; 95 ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); 96 97 if (ret == ERROR_BUFFER_OVERFLOW) { 98 IP_ADAPTER_ADDRESSES * newAdapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); 99 if (newAdapterInfo == NULL) { 100 free(adapterInfo); 101 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); 102 return -1; 103 } 104 105 adapterInfo = newAdapterInfo; 106 107 bufsize = len; 108 ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); 109 } 110 111 if (ret != ERROR_SUCCESS) { 112 free (adapterInfo); 113 JNU_ThrowByName(env, "java/lang/Error", 114 "IP Helper Library GetAdaptersAddresses function failed"); 115 return -1; 116 } 117 *adapters = adapterInfo; 118 return ERROR_SUCCESS; 119 } 120 121 /* 122 * return an array of IP_ADAPTER_ADDRESSES containing one element 123 * for each adapter on the system. Returned in *adapters. 124 * Buffer is malloc'd and must be freed (unless error returned) 125 */ 126 IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { 127 DWORD flags, val; 128 IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret; 129 ULONG len; 130 adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize); 131 if (adapterInfo == NULL) { 132 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); 133 return NULL; 134 } 135 len = bufsize; 136 flags = GAA_FLAG_SKIP_DNS_SERVER; 137 flags |= GAA_FLAG_SKIP_MULTICAST; 138 flags |= GAA_FLAG_INCLUDE_PREFIX; 139 val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); 140 if (val == ERROR_BUFFER_OVERFLOW) { 141 IP_ADAPTER_ADDRESSES * newAdapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); 142 if (newAdapterInfo == NULL) { 143 free(adapterInfo); 144 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); 145 return NULL; 146 } 147 148 adapterInfo = newAdapterInfo; 149 150 bufsize = len; 151 val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); 152 } 153 154 if (val != ERROR_SUCCESS) { 155 free (adapterInfo); 156 JNU_ThrowByName(env, "java/lang/Error", 157 "IP Helper Library GetAdaptersAddresses function failed"); 158 return NULL; 159 } 160 ptr = adapterInfo; 161 ret = NULL; 162 while (ptr != NULL) { 163 // IPv4 interface 164 if (ptr->Ipv6IfIndex == index) { 165 ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES)); 166 if (ret == NULL) { 167 free(adapterInfo); 168 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); 169 return NULL; 170 } 171 172 //copy the memory and break out of the while loop. 173 memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES)); 174 break; 175 } 176 ptr=ptr->Next; 177 } 178 free(adapterInfo); 179 return ret; 180 } 181 182 static int ipinflen = 2048; 183 184 /* 185 */ 186 int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) 187 { 188 DWORD ret; 189 IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL; 190 ULONG len=ipinflen, count=0; 191 netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr; 192 int tun=0, net=0; 193 194 *netifPP = NULL; 195 196 /* 197 * Get the IPv4 interfaces. This information is the same 198 * as what previous JDK versions would return. 199 */ 200 201 ret = enumInterfaces(env, netifPP); 202 if (ret == -1) { 203 return -1; 204 } else { 205 count = ret; 206 } 207 208 /* locate the loopback (and the last) interface */ 209 for (nif=*netifPP, last=nif; nif!=NULL; nif=nif->next) { 210 if (nif->ifType == MIB_IF_TYPE_LOOPBACK) { 211 loopif = nif; 212 } 213 last = nif; 214 } 215 216 // Retrieve IPv4 addresses with the IP Helper API 217 curr = *netifPP; 218 while (curr != NULL) { 219 netaddr *netaddrP; 220 ret = enumAddresses_win(env, curr, &netaddrP); 221 if (ret == -1) { 222 return -1; 223 } 224 curr->addrs = netaddrP; 225 curr->naddrs += ret; 226 curr = curr->next; 227 } 228 229 ret = getAdapters (env, &adapters); 230 if (ret != ERROR_SUCCESS) { 231 goto err; 232 } 233 234 /* Now get the IPv6 information. This includes: 235 * (a) IPv6 information associated with interfaces already found 236 * (b) IPv6 information for IPv6 only interfaces (probably tunnels) 237 * 238 * For compatibility with previous releases we use the naming 239 * information gotten from enumInterfaces() for (a) entries 240 * However, the index numbers are taken from the new API. 241 * 242 * The procedure is to go through the list of adapters returned 243 * by the new API looking for entries that correspond to IPv4 interfaces 244 * already found. 245 */ 246 247 ptr = adapters; 248 while (ptr != NULL) { 249 int c; 250 netif *nif0; 251 if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) { 252 c = getAddrsFromAdapter(ptr, &loopif->addrs); 253 if (c == -1) { 254 goto err; 255 } 256 loopif->naddrs += c; 257 } else { 258 int index = ptr->IfIndex; 259 if (index != 0) { 260 /* This entry is associated with an IPv4 interface */ 261 for (nif=*netifPP; nif!=NULL; nif=nif->next) { 262 if (nif->index == index) { 263 /* found the interface entry 264 * set the index to the IPv6 index and add the 265 * IPv6 addresses 266 */ 267 nif->index = ptr->Ipv6IfIndex; 268 c = getAddrsFromAdapter(ptr, &nif->addrs); 269 nif->naddrs += c; 270 break; 271 } 272 } 273 } else { 274 /* This entry is IPv6 only */ 275 char newname [128]; 276 int c; 277 278 /* Windows allocates duplicate adapter entries 279 * for tunnel interfaces when there are multiple 280 * physical adapters. Need to check 281 * if this is a duplicate (ipv6Index is the same) 282 */ 283 dup_nif = 0; 284 for (nif0=*netifPP; nif0!=NULL; nif0=nif0->next) { 285 if (nif0->hasIpv6Address && 286 ptr->Ipv6IfIndex == nif0->ipv6Index) { 287 dup_nif = nif0; 288 break; 289 } 290 } 291 if (dup_nif == 0) { 292 /* new interface */ 293 nif = (netif *) calloc (1, sizeof(netif)); 294 if (nif == 0) { 295 goto err; 296 } 297 if (ptr->IfType == IF_TYPE_TUNNEL) { 298 sprintf (newname, "tun%d", tun); 299 tun ++; 300 } else { 301 sprintf (newname, "net%d", net); 302 net ++; 303 } 304 nif->name = malloc (strlen(newname)+1); 305 nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2); 306 if (nif->name == 0 || nif->displayName == 0) { 307 goto err; 308 } 309 strcpy (nif->name, newname); 310 wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName); 311 nif->dNameIsUnicode = TRUE; 312 nif->index = ptr->Ipv6IfIndex; 313 nif->ipv6Index = ptr->Ipv6IfIndex; 314 nif->hasIpv6Address = TRUE; 315 316 last->next = nif; 317 last = nif; 318 count++; 319 c = getAddrsFromAdapter(ptr, &nif->addrs); 320 if (c == -1) { 321 goto err; 322 } 323 nif->naddrs += c; 324 } else { 325 /* add the addresses from this adapter to the 326 * original (dup_nif) 327 */ 328 c = getAddrsFromAdapter(ptr, &dup_nif->addrs); 329 if (c == -1) { 330 goto err; 331 } 332 dup_nif->naddrs += c; 333 } 334 } 335 } 336 ptr=ptr->Next; 337 } 338 339 free (adapters); 340 return count; 341 342 err: 343 if (*netifPP) { 344 free_netif (*netifPP); 345 } 346 if (adapters) { 347 free (adapters); 348 } 349 return -1; 350 } 351 352 /* If *netaddrPP is null, then the addresses are allocated and the beginning 353 * of the allocated chain is returned in *netaddrPP. 354 * If *netaddrPP is not null, then the addresses allocated here are appended 355 * to the existing chain. 356 * 357 * Returns count of addresses or -1 on error. 358 */ 359 360 static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) { 361 LPSOCKADDR sock; 362 int count = 0; 363 netaddr *curr, *start = NULL, *prev = NULL; 364 PIP_ADAPTER_UNICAST_ADDRESS uni_addr; 365 PIP_ADAPTER_ANYCAST_ADDRESS any_addr; 366 PIP_ADAPTER_PREFIX prefix; 367 368 /* If chain passed in, find end */ 369 if (*netaddrPP != NULL) { 370 for (start=*netaddrPP; start->next!=NULL; start=start->next) 371 ; 372 373 prev=start; 374 } 375 376 prefix = ptr->FirstPrefix; 377 /* Unicast */ 378 uni_addr = ptr->FirstUnicastAddress; 379 while (uni_addr != NULL) { 380 /* address is only usable if dad state is preferred or deprecated */ 381 if (uni_addr->DadState == IpDadStateDeprecated || 382 uni_addr->DadState == IpDadStatePreferred) { 383 sock = uni_addr->Address.lpSockaddr; 384 385 // IPv4 addresses already retrieved with enumAddresses_win 386 if (sock->sa_family == AF_INET) { 387 uni_addr = uni_addr->Next; 388 continue; 389 } 390 391 curr = (netaddr *)calloc (1, sizeof (netaddr)); 392 393 if (curr == NULL) 394 goto freeAllocatedMemory; 395 396 if (start == NULL) 397 start = curr; 398 399 if (prev != NULL) 400 prev->next = curr; 401 402 prev = curr; 403 SOCKETADDRESS_COPY (&curr->addr, sock); 404 if (prefix != NULL) { 405 curr->mask = (short)prefix->PrefixLength; 406 prefix = prefix->Next; 407 } 408 count ++; 409 } 410 uni_addr = uni_addr->Next; 411 } 412 /* Anycast */ 413 any_addr = ptr->FirstAnycastAddress; 414 while (any_addr != NULL) { 415 curr = (netaddr *)calloc (1, sizeof (netaddr)); 416 417 if (curr == NULL) 418 goto freeAllocatedMemory; 419 420 if (start == NULL) 421 start = curr; 422 423 if (prev != NULL) 424 prev->next = curr; 425 426 prev = curr; 427 sock = any_addr->Address.lpSockaddr; 428 SOCKETADDRESS_COPY (&curr->addr, sock); 429 count ++; 430 any_addr = any_addr->Next; 431 } 432 if (*netaddrPP == NULL) { 433 *netaddrPP = start; 434 } 435 return count; 436 437 freeAllocatedMemory: 438 439 if (*netaddrPP != NULL) { 440 //N.B. the variable "start" cannot be NULL at this point because we started with an 441 //existing list. 442 curr=start->next; 443 start->next = NULL; 444 start = curr; 445 } 446 // otherwise, "start" points to the beginning of an incomplete list that we must deallocate. 447 448 while (start != NULL) { 449 curr = start->next; 450 free(start); 451 start = curr; 452 } 453 454 return -1; 455 } 456 457 /* 458 * Create a NetworkInterface object, populate the name and index, and 459 * populate the InetAddress array based on the IP addresses for this 460 * interface. 461 */ 462 static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) 463 { 464 jobject netifObj; 465 jobject name, displayName; 466 jobjectArray addrArr, bindsArr, childArr; 467 netaddr *addrs; 468 jint addr_index; 469 int netaddrCount=ifs->naddrs; 470 netaddr *netaddrP=ifs->addrs; 471 jint bind_index; 472 473 /* 474 * Create a NetworkInterface object and populate it 475 */ 476 netifObj = (*env)->NewObject(env, ni_class, ni_ctor); 477 name = (*env)->NewStringUTF(env, ifs->name); 478 if (ifs->dNameIsUnicode) { 479 displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, 480 (jsize)wcslen ((PWCHAR)ifs->displayName)); 481 } else { 482 displayName = (*env)->NewStringUTF(env, ifs->displayName); 483 } 484 if (netifObj == NULL || name == NULL || displayName == NULL) { 485 return NULL; 486 } 487 (*env)->SetObjectField(env, netifObj, ni_nameID, name); 488 (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName); 489 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); 490 491 /* 492 * Get the IP addresses for this interface if necessary 493 * Note that 0 is a valid number of addresses. 494 */ 495 if (netaddrCount < 0) { 496 netaddrCount = enumAddresses_win(env, ifs, &netaddrP); 497 if (netaddrCount == -1) { 498 return NULL; 499 } 500 } 501 502 addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL); 503 if (addrArr == NULL) { 504 return NULL; 505 } 506 507 bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); 508 if (bindsArr == NULL) { 509 free_netaddr(netaddrP); 510 return NULL; 511 } 512 513 addrs = netaddrP; 514 addr_index = 0; 515 bind_index = 0; 516 while (addrs != NULL) { 517 jobject iaObj, ia2Obj; 518 jobject ibObj = NULL; 519 if (addrs->addr.him.sa_family == AF_INET) { 520 iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); 521 if (iaObj == NULL) { 522 return NULL; 523 } 524 /* default ctor will set family to AF_INET */ 525 526 setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr)); 527 528 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 529 if (ibObj == NULL) { 530 free_netaddr(netaddrP); 531 return NULL; 532 } 533 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 534 ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor); 535 if (ia2Obj == NULL) { 536 free_netaddr(netaddrP); 537 return NULL; 538 } 539 setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr)); 540 (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); 541 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 542 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 543 } else /* AF_INET6 */ { 544 int scope; 545 iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); 546 if (iaObj) { 547 jbyteArray ipaddress = (*env)->NewByteArray(env, 16); 548 if (ipaddress == NULL) { 549 return NULL; 550 } 551 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, 552 (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); 553 scope = addrs->addr.him6.sin6_scope_id; 554 if (scope != 0) { /* zero is default value, no need to set */ 555 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); 556 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); 557 (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); 558 } 559 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); 560 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 561 if (ibObj == NULL) { 562 free_netaddr(netaddrP); 563 return NULL; 564 } 565 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 566 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 567 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 568 } 569 } 570 (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); 571 addrs = addrs->next; 572 addr_index++; 573 } 574 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); 575 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); 576 577 /* 578 * Windows doesn't have virtual interfaces, so child array 579 * is always empty. 580 */ 581 childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL); 582 if (childArr == NULL) { 583 return NULL; 584 } 585 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); 586 587 /* return the NetworkInterface */ 588 return netifObj; 589 } 590 591 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP 592 (JNIEnv *env, jclass cls, jstring name) 593 { 594 netif *ifList, *curr; 595 jboolean isCopy; 596 const char *name_utf; 597 jobject netifObj = NULL; 598 599 if (getAllInterfacesAndAddresses (env, &ifList) < 0) { 600 return NULL; 601 } 602 603 /* get the name as a C string */ 604 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 605 606 /* Search by name */ 607 curr = ifList; 608 while (curr != NULL) { 609 if (strcmp(name_utf, curr->name) == 0) { 610 break; 611 } 612 curr = curr->next; 613 } 614 615 /* if found create a NetworkInterface */ 616 if (curr != NULL) {; 617 netifObj = createNetworkInterfaceXP(env, curr); 618 } 619 620 /* release the UTF string */ 621 (*env)->ReleaseStringUTFChars(env, name, name_utf); 622 623 /* release the interface list */ 624 free_netif(ifList); 625 626 return netifObj; 627 } 628 629 /* 630 * Class: NetworkInterface 631 * Method: getByIndex0_XP 632 * Signature: (I)LNetworkInterface; 633 */ 634 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0_XP 635 (JNIEnv *env, jclass cls, jint index) 636 { 637 netif *ifList, *curr; 638 jobject netifObj = NULL; 639 640 if (getAllInterfacesAndAddresses (env, &ifList) < 0) { 641 return NULL; 642 } 643 644 /* search by index */ 645 curr = ifList; 646 while (curr != NULL) { 647 if (index == curr->index) { 648 break; 649 } 650 curr = curr->next; 651 } 652 653 /* if found create a NetworkInterface */ 654 if (curr != NULL) { 655 netifObj = createNetworkInterfaceXP(env, curr); 656 } 657 658 /* release the interface list */ 659 free_netif(ifList); 660 661 return netifObj; 662 } 663 664 /* 665 * Class: java_net_NetworkInterface 666 * Method: getByInetAddress0 667 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; 668 */ 669 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP 670 (JNIEnv *env, jclass cls, jobject iaObj) 671 { 672 netif *ifList, *curr; 673 jobject netifObj = NULL; 674 675 /* get the list of interfaces */ 676 if (getAllInterfacesAndAddresses (env, &ifList) < 0) { 677 return NULL; 678 } 679 680 /* 681 * Enumerate the addresses on each interface until we find a 682 * matching address. 683 */ 684 curr = ifList; 685 while (curr != NULL) { 686 netaddr *addrList = curr->addrs; 687 netaddr *addrP; 688 689 /* iterate through each address */ 690 addrP = addrList; 691 692 while (addrP != NULL) { 693 if (NET_SockaddrEqualsInetAddress(env, 694 (struct sockaddr*)&addrP->addr, iaObj)) { 695 break; 696 } 697 addrP = addrP->next; 698 } 699 700 /* 701 * Address matched so create NetworkInterface for this interface 702 * and address list. 703 */ 704 if (addrP != NULL) { 705 netifObj = createNetworkInterfaceXP(env, curr); 706 break; 707 } 708 709 /* on next interface */ 710 curr = curr->next; 711 } 712 713 /* release the interface list */ 714 free_netif(ifList); 715 716 return netifObj; 717 } 718 719 /* 720 * Class: java_net_NetworkInterface 721 * Method: getAll 722 * Signature: ()[Ljava/net/NetworkInterface; 723 */ 724 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP 725 (JNIEnv *env, jclass cls) 726 { 727 int count; 728 netif *ifList, *curr; 729 jobjectArray netIFArr; 730 jint arr_index; 731 732 /* 733 * Get list of interfaces 734 */ 735 count = getAllInterfacesAndAddresses (env, &ifList); 736 if (count < 0) { 737 return NULL; 738 } 739 740 /* allocate a NetworkInterface array */ 741 netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); 742 if (netIFArr == NULL) { 743 return NULL; 744 } 745 746 /* 747 * Iterate through the interfaces, create a NetworkInterface instance 748 * for each array element and populate the object. 749 */ 750 curr = ifList; 751 arr_index = 0; 752 while (curr != NULL) { 753 jobject netifObj; 754 755 netifObj = createNetworkInterfaceXP(env, curr); 756 if (netifObj == NULL) { 757 return NULL; 758 } 759 760 /* put the NetworkInterface into the array */ 761 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj); 762 curr = curr->next; 763 } 764 765 /* release the interface list */ 766 free_netif(ifList); 767 768 return netIFArr; 769 } 770 771 /* 772 * Class: java_net_NetworkInterface 773 * Method: supportsMulticast0 774 * Signature: (Ljava/lang/String;I)Z 775 */ 776 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP 777 (JNIEnv *env, jclass cls, jstring name, jint index) { 778 IP_ADAPTER_ADDRESSES *ptr; 779 jboolean val = JNI_TRUE; 780 781 ptr = getAdapter(env, index); 782 if (ptr != NULL) { 783 val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE; 784 free(ptr); 785 } 786 return val; 787 } 788 789 /* 790 * Class: java_net_NetworkInterface 791 * Method: isUp0 792 * Signature: (Ljava/lang/String;I)Z 793 */ 794 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP 795 (JNIEnv *env, jclass cls, jstring name, jint index) { 796 IP_ADAPTER_ADDRESSES *ptr; 797 jboolean val = JNI_FALSE; 798 799 ptr = getAdapter(env, index); 800 if (ptr != NULL) { 801 val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE; 802 free(ptr); 803 } 804 return val; 805 } 806 807 /* 808 * Class: java_net_NetworkInterface 809 * Method: getMacAddr0 810 * Signature: (Ljava/lang/String;I)Z 811 */ 812 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP 813 (JNIEnv *env, jclass cls, jstring name, jint index) { 814 IP_ADAPTER_ADDRESSES *ptr; 815 jbyteArray ret = NULL; 816 int len; 817 818 ptr = getAdapter(env, index); 819 if (ptr != NULL) { 820 len = ptr->PhysicalAddressLength; 821 if (len > 0) { 822 ret = (*env)->NewByteArray(env, len); 823 if (!IS_NULL(ret)) { 824 (*env)->SetByteArrayRegion(env, ret, 0, len, 825 (jbyte*) ptr->PhysicalAddress); 826 } 827 } 828 free(ptr); 829 } 830 return ret; 831 } 832 833 /* 834 * Class: java_net_NetworkInterface 835 * Method: getMTU0 836 * Signature: ([bLjava/lang/String;I)I 837 */ 838 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP 839 (JNIEnv *env, jclass cls, jstring name, jint index) { 840 IP_ADAPTER_ADDRESSES *ptr; 841 jint ret = -1; 842 843 ptr = getAdapter(env, index); 844 if (ptr != NULL) { 845 ret = ptr->Mtu; 846 free(ptr); 847 } 848 return ret; 849 } 850 851 /* 852 * Class: java_net_NetworkInterface 853 * Method: isLoopback0 854 * Signature: (Ljava/lang/String;I)Z 855 */ 856 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP 857 (JNIEnv *env, jclass cls, jstring name, jint index) { 858 IP_ADAPTER_ADDRESSES *ptr; 859 jboolean val = JNI_FALSE; 860 861 ptr = getAdapter(env, index); 862 if (ptr != NULL) { 863 val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE; 864 free(ptr); 865 } 866 return val; 867 } 868 869 /* 870 * Class: java_net_NetworkInterface 871 * Method: isP2P0 872 * Signature: (Ljava/lang/String;I)Z 873 */ 874 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP 875 (JNIEnv *env, jclass cls, jstring name, jint index) { 876 IP_ADAPTER_ADDRESSES *ptr; 877 jboolean val = JNI_FALSE; 878 879 ptr = getAdapter(env, index); 880 if (ptr != NULL) { 881 if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP || 882 ptr->IfType == IF_TYPE_TUNNEL) { 883 val = JNI_TRUE; 884 } 885 free(ptr); 886 } 887 return val; 888 }