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