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