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