1/* 2 * Copyright (c) 2000, 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 * Interfaces and addresses are enumerated using the IP helper routines 36 * GetIfTable, GetIfAddrTable resp. These routines are available on Windows 37 * 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if 38 * IE is upgraded to 5.x. 39 * 40 * Windows does not have any standard for device names so we are forced 41 * to use our own convention which is based on the normal Unix naming 42 * convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices, 43 * tr0, tr1, .. for token ring, and so on). This convention gives us 44 * consistency across multiple Windows editions and also consistency with 45 * Solaris/Linux device names. Note that we always enumerate in index 46 * order and this ensures consistent device number across invocations. 47 */ 48 49/* various JNI ids */ 50 51jclass ni_class; /* NetworkInterface */ 52 53jmethodID ni_ctor; /* NetworkInterface() */ 54 55jfieldID ni_indexID; /* NetworkInterface.index */ 56jfieldID ni_addrsID; /* NetworkInterface.addrs */ 57jfieldID ni_bindsID; /* NetworkInterface.bindings */ 58jfieldID ni_nameID; /* NetworkInterface.name */ 59jfieldID ni_displayNameID; /* NetworkInterface.displayName */ 60jfieldID ni_childsID; /* NetworkInterface.childs */ 61 62jclass ni_ibcls; /* InterfaceAddress */ 63jmethodID ni_ibctrID; /* InterfaceAddress() */ 64jfieldID ni_ibaddressID; /* InterfaceAddress.address */ 65jfieldID ni_ibbroadcastID; /* InterfaceAddress.broadcast */ 66jfieldID ni_ibmaskID; /* InterfaceAddress.maskLength */ 67 68/* 69 * Support routines to free netif and netaddr lists 70 */ 71void free_netif(netif *netifP) { 72 netif *curr = netifP; 73 while (curr != NULL) { 74 if (curr->name != NULL) 75 free(curr->name); 76 if (curr->displayName != NULL) 77 free(curr->displayName); 78 if (curr->addrs != NULL) 79 free_netaddr (curr->addrs); 80 netifP = netifP->next; 81 free(curr); 82 curr = netifP; 83 } 84} 85 86void free_netaddr(netaddr *netaddrP) { 87 netaddr *curr = netaddrP; 88 while (curr != NULL) { 89 netaddrP = netaddrP->next; 90 free(curr); 91 curr = netaddrP; 92 } 93} 94 95/* 96 * Returns the interface structure from the table with the matching index. 97 */ 98MIB_IFROW *getIF(jint index) { 99 MIB_IFTABLE *tableP; 100 MIB_IFROW *ifrowP, *ret = NULL; 101 ULONG size; 102 DWORD i, count; 103 jint ifindex; 104 105 /* 106 * Ask the IP Helper library to enumerate the adapters 107 */ 108 size = sizeof(MIB_IFTABLE); 109 tableP = (MIB_IFTABLE *)malloc(size); 110 if(tableP == NULL) 111 return NULL; 112 113 count = GetIfTable(tableP, &size, TRUE); 114 if (count == ERROR_INSUFFICIENT_BUFFER || count == ERROR_BUFFER_OVERFLOW) { 115 MIB_IFTABLE* newTableP = (MIB_IFTABLE *)realloc(tableP, size); 116 if (newTableP == NULL) { 117 free(tableP); 118 return NULL; 119 } 120 tableP = newTableP; 121 122 count = GetIfTable(tableP, &size, TRUE); 123 } 124 125 if (count != NO_ERROR) { 126 free(tableP); 127 return NULL; 128 } 129 130 { 131 ifrowP = tableP->table; 132 for (i=0; i<tableP->dwNumEntries; i++) { 133 /* 134 * Warning: the real index is obtained by GetFriendlyIfIndex() 135 */ 136 ifindex = GetFriendlyIfIndex(ifrowP->dwIndex); 137 if (ifindex == index) { 138 /* 139 * Create a copy of the entry so that we can free the table. 140 */ 141 ret = (MIB_IFROW *) malloc(sizeof(MIB_IFROW)); 142 if (ret == NULL) { 143 free(tableP); 144 return NULL; 145 } 146 memcpy(ret, ifrowP, sizeof(MIB_IFROW)); 147 break; 148 } 149 150 /* onto the next interface */ 151 ifrowP++; 152 } 153 free(tableP); 154 } 155 return ret; 156} 157 158/* 159 * Enumerate network interfaces using IP Helper Library routine GetIfTable. 160 * We use GetIfTable rather than other IP helper routines because it's 161 * available on 98 & NT SP4+. 162 * 163 * Returns the number of interfaces found or -1 if error. If no error 164 * occurs then netifPP be returned as list of netif structures or NULL 165 * if no interfaces are found. 166 */ 167int enumInterfaces(JNIEnv *env, netif **netifPP) 168{ 169 MIB_IFTABLE *tableP; 170 MIB_IFROW *ifrowP; 171 ULONG size; 172 DWORD ret; 173 int count; 174 netif *netifP; 175 DWORD i; 176 int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0, wlen=0; 177 178 /* 179 * Ask the IP Helper library to enumerate the adapters 180 */ 181 size = sizeof(MIB_IFTABLE); 182 tableP = (MIB_IFTABLE *)malloc(size); 183 if (tableP == NULL) { 184 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 185 return -1; 186 } 187 188 ret = GetIfTable(tableP, &size, TRUE); 189 if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) { 190 MIB_IFTABLE * newTableP = (MIB_IFTABLE *)realloc(tableP, size); 191 if (newTableP == NULL) { 192 free(tableP); 193 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 194 return -1; 195 } 196 tableP = newTableP; 197 ret = GetIfTable(tableP, &size, TRUE); 198 } 199 200 if (ret != NO_ERROR) { 201 free(tableP); 202 203 JNU_ThrowByName(env, "java/lang/Error", 204 "IP Helper Library GetIfTable function failed"); 205 206 return -1; 207 } 208 209 /* 210 * Iterate through the list of adapters 211 */ 212 count = 0; 213 netifP = NULL; 214 215 ifrowP = tableP->table; 216 for (i=0; i<tableP->dwNumEntries; i++) { 217 char dev_name[8]; 218 netif *curr; 219 220 /* 221 * Generate a name for the device as Windows doesn't have any 222 * real concept of a device name. 223 */ 224 switch (ifrowP->dwType) { 225 case MIB_IF_TYPE_ETHERNET: 226 _snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++); 227 break; 228 229 case MIB_IF_TYPE_TOKENRING: 230 _snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++); 231 break; 232 233 case MIB_IF_TYPE_FDDI: 234 _snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++); 235 break; 236 237 case MIB_IF_TYPE_LOOPBACK: 238 /* There should only be only IPv4 loopback address */ 239 if (lo > 0) { 240 continue; 241 } 242 strncpy_s(dev_name, 8, "lo", _TRUNCATE); 243 lo++; 244 break; 245 246 case MIB_IF_TYPE_PPP: 247 _snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++); 248 break; 249 250 case MIB_IF_TYPE_SLIP: 251 _snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++); 252 break; 253 254 case IF_TYPE_IEEE80211: 255 _snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++); 256 break; 257 258 default: 259 _snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++); 260 } 261 262 /* 263 * Allocate a netif structure and space for the name and 264 * display name (description in this case). 265 */ 266 curr = (netif *)calloc(1, sizeof(netif)); 267 if (curr != NULL) { 268 wlen = MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr, 269 ifrowP->dwDescrLen, NULL, 0); 270 if(wlen == 0) { 271 // MultiByteToWideChar should not fail 272 // But in rare case it fails, we allow 'char' to be displayed 273 curr->displayName = (char *)malloc(ifrowP->dwDescrLen + 1); 274 } else { 275 curr->displayName = (wchar_t *)malloc(wlen*(sizeof(wchar_t))+1); 276 } 277 278 curr->name = (char *)malloc(strlen(dev_name) + 1); 279 280 if (curr->name == NULL || curr->displayName == NULL) { 281 if (curr->name) free(curr->name); 282 if (curr->displayName) free(curr->displayName); 283 curr = NULL; 284 } 285 } 286 if (curr == NULL) { 287 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 288 free_netif(netifP); 289 free(tableP); 290 return -1; 291 } 292 293 /* 294 * Populate the interface. Note that we need to convert the 295 * index into its "friendly" value as otherwise we will expose 296 * 32-bit numbers as index values. 297 */ 298 strcpy(curr->name, dev_name); 299 if (wlen == 0) { 300 // display char type in case of MultiByteToWideChar failure 301 strncpy(curr->displayName, ifrowP->bDescr, ifrowP->dwDescrLen); 302 curr->displayName[ifrowP->dwDescrLen] = '\0'; 303 } else { 304 // call MultiByteToWideChar again to fill curr->displayName 305 // it should not fail, because we have called it once before 306 if (MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr, 307 ifrowP->dwDescrLen, curr->displayName, wlen) == 0) { 308 JNU_ThrowByName(env, "java/lang/Error", 309 "Cannot get multibyte char for interface display name"); 310 free_netif(netifP); 311 free(tableP); 312 free(curr->name); 313 free(curr->displayName); 314 free(curr); 315 return -1; 316 } else { 317 curr->displayName[wlen*(sizeof(wchar_t))] = '\0'; 318 curr->dNameIsUnicode = TRUE; 319 } 320 } 321 322 curr->dwIndex = ifrowP->dwIndex; 323 curr->ifType = ifrowP->dwType; 324 curr->index = GetFriendlyIfIndex(ifrowP->dwIndex); 325 326 /* 327 * Put the interface at tail of list as GetIfTable(,,TRUE) is 328 * returning the interfaces in index order. 329 */ 330 count++; 331 if (netifP == NULL) { 332 netifP = curr; 333 } else { 334 netif *tail = netifP; 335 while (tail->next != NULL) { 336 tail = tail->next; 337 } 338 tail->next = curr; 339 } 340 341 /* onto the next interface */ 342 ifrowP++; 343 } 344 345 /* 346 * Free the interface table and return the interface list 347 */ 348 if (tableP) { 349 free(tableP); 350 } 351 *netifPP = netifP; 352 return count; 353} 354 355/* 356 * Enumerate the IP addresses on an interface using the IP helper library 357 * routine GetIfAddrTable and matching based on the index name. There are 358 * more efficient routines but we use GetIfAddrTable because it's avaliable 359 * on 98 and NT. 360 * 361 * Returns the count of addresses, or -1 if error. If no error occurs then 362 * netaddrPP will return a list of netaddr structures with the IP addresses. 363 */ 364int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) 365{ 366 MIB_IPADDRTABLE *tableP; 367 ULONG size; 368 DWORD ret; 369 DWORD i; 370 netaddr *netaddrP; 371 int count = 0; 372 unsigned long mask; 373 374 /* 375 * Use GetIpAddrTable to enumerate the IP Addresses 376 */ 377 size = sizeof(MIB_IPADDRTABLE); 378 tableP = (MIB_IPADDRTABLE *)malloc(size); 379 if (tableP == NULL) { 380 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 381 return -1; 382 } 383 384 ret = GetIpAddrTable(tableP, &size, FALSE); 385 if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) { 386 MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size); 387 if (newTableP == NULL) { 388 free(tableP); 389 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 390 return -1; 391 } 392 tableP = newTableP; 393 394 ret = GetIpAddrTable(tableP, &size, FALSE); 395 } 396 if (ret != NO_ERROR) { 397 if (tableP) { 398 free(tableP); 399 } 400 JNU_ThrowByName(env, "java/lang/Error", 401 "IP Helper Library GetIpAddrTable function failed"); 402 return -1; 403 } 404 405 /* 406 * Iterate through the table to find the addresses with the 407 * matching dwIndex. Ignore 0.0.0.0 addresses. 408 */ 409 count = 0; 410 netaddrP = NULL; 411 412 i = 0; 413 while (i<tableP->dwNumEntries) { 414 if (tableP->table[i].dwIndex == netifP->dwIndex && 415 tableP->table[i].dwAddr != 0) { 416 417 netaddr *curr = (netaddr *)malloc(sizeof(netaddr)); 418 if (curr == NULL) { 419 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 420 free_netaddr(netaddrP); 421 free(tableP); 422 return -1; 423 } 424 425 curr->addr.sa4.sin_family = AF_INET; 426 curr->addr.sa4.sin_addr.s_addr = tableP->table[i].dwAddr; 427 /* 428 * Get netmask / broadcast address 429 */ 430 switch (netifP->ifType) { 431 case MIB_IF_TYPE_ETHERNET: 432 case MIB_IF_TYPE_TOKENRING: 433 case MIB_IF_TYPE_FDDI: 434 case MIB_IF_TYPE_LOOPBACK: 435 case IF_TYPE_IEEE80211: 436 /** 437 * Contrary to what it seems to indicate, dwBCastAddr doesn't 438 * contain the broadcast address but 0 or 1 depending on whether 439 * the broadcast address should set the bits of the host part 440 * to 0 or 1. 441 * Yes, I know it's stupid, but what can I say, it's MSFTs API. 442 */ 443 curr->brdcast.sa4.sin_family = AF_INET; 444 if (tableP->table[i].dwBCastAddr == 1) 445 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask); 446 else 447 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask); 448 mask = ntohl(tableP->table[i].dwMask); 449 curr->mask = 0; 450 while (mask) { 451 mask <<= 1; 452 curr->mask++; 453 } 454 break; 455 case MIB_IF_TYPE_PPP: 456 case MIB_IF_TYPE_SLIP: 457 default: 458 /** 459 * these don't have broadcast/subnet 460 */ 461 curr->mask = -1; 462 break; 463 } 464 465 curr->next = netaddrP; 466 netaddrP = curr; 467 count++; 468 } 469 i++; 470 } 471 472 *netaddrPP = netaddrP; 473 free(tableP); 474 return count; 475} 476 477/* 478 * Class: java_net_NetworkInterface 479 * Method: init 480 * Signature: ()V 481 */ 482JNIEXPORT void JNICALL 483Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) 484{ 485 /* 486 * Get the various JNI ids that we require 487 */ 488 ni_class = (*env)->NewGlobalRef(env, cls); 489 CHECK_NULL(ni_class); 490 ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;"); 491 CHECK_NULL(ni_nameID); 492 ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;"); 493 CHECK_NULL(ni_displayNameID); 494 ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I"); 495 CHECK_NULL(ni_indexID); 496 ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;"); 497 CHECK_NULL(ni_addrsID); 498 ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;"); 499 CHECK_NULL(ni_bindsID); 500 ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;"); 501 CHECK_NULL(ni_childsID); 502 ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V"); 503 CHECK_NULL(ni_ctor); 504 ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress"); 505 CHECK_NULL(ni_ibcls); 506 ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls); 507 CHECK_NULL(ni_ibcls); 508 ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V"); 509 CHECK_NULL(ni_ibctrID); 510 ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;"); 511 CHECK_NULL(ni_ibaddressID); 512 ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;"); 513 CHECK_NULL(ni_ibbroadcastID); 514 ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S"); 515 CHECK_NULL(ni_ibmaskID); 516 517 initInetAddressIDs(env); 518} 519 520/* 521 * Create a NetworkInterface object, populate the name and index, and 522 * populate the InetAddress array based on the IP addresses for this 523 * interface. 524 */ 525jobject createNetworkInterface 526 (JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP) 527{ 528 jobject netifObj; 529 jobject name, displayName; 530 jobjectArray addrArr, bindsArr, childArr; 531 netaddr *addrs; 532 jint addr_index; 533 jint bind_index; 534 535 /* 536 * Create a NetworkInterface object and populate it 537 */ 538 netifObj = (*env)->NewObject(env, ni_class, ni_ctor); 539 CHECK_NULL_RETURN(netifObj, NULL); 540 name = (*env)->NewStringUTF(env, ifs->name); 541 CHECK_NULL_RETURN(name, NULL); 542 if (ifs->dNameIsUnicode) { 543 displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, 544 (jsize)wcslen ((PWCHAR)ifs->displayName)); 545 } else { 546 displayName = (*env)->NewStringUTF(env, ifs->displayName); 547 } 548 CHECK_NULL_RETURN(displayName, NULL); 549 (*env)->SetObjectField(env, netifObj, ni_nameID, name); 550 (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName); 551 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); 552 553 /* 554 * Get the IP addresses for this interface if necessary 555 * Note that 0 is a valid number of addresses. 556 */ 557 if (netaddrCount < 0) { 558 netaddrCount = enumAddresses_win(env, ifs, &netaddrP); 559 if (netaddrCount == -1) { 560 return NULL; 561 } 562 } 563 addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL); 564 if (addrArr == NULL) { 565 free_netaddr(netaddrP); 566 return NULL; 567 } 568 569 bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); 570 if (bindsArr == NULL) { 571 free_netaddr(netaddrP); 572 return NULL; 573 } 574 addrs = netaddrP; 575 addr_index = 0; 576 bind_index = 0; 577 while (addrs != NULL) { 578 jobject iaObj, ia2Obj; 579 jobject ibObj = NULL; 580 if (addrs->addr.sa.sa_family == AF_INET) { 581 iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 582 if (iaObj == NULL) { 583 free_netaddr(netaddrP); 584 return NULL; 585 } 586 /* default ctor will set family to AF_INET */ 587 588 setInetAddress_addr(env, iaObj, ntohl(addrs->addr.sa4.sin_addr.s_addr)); 589 if (addrs->mask != -1) { 590 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 591 if (ibObj == NULL) { 592 free_netaddr(netaddrP); 593 return NULL; 594 } 595 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 596 ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 597 if (ia2Obj == NULL) { 598 free_netaddr(netaddrP); 599 return NULL; 600 } 601 setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.sa4.sin_addr.s_addr)); 602 (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); 603 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 604 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 605 } 606 } else /* AF_INET6 */ { 607 int scope; 608 iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); 609 if (iaObj) { 610 jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr)); 611 if (ret == JNI_FALSE) { 612 return NULL; 613 } 614 615 scope = addrs->addr.sa6.sin6_scope_id; 616 if (scope != 0) { /* zero is default value, no need to set */ 617 setInet6Address_scopeid(env, iaObj, scope); 618 setInet6Address_scopeifname(env, iaObj, netifObj); 619 } 620 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 621 if (ibObj == NULL) { 622 free_netaddr(netaddrP); 623 return NULL; 624 } 625 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 626 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 627 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 628 } 629 } 630 (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); 631 addrs = addrs->next; 632 addr_index++; 633 } 634 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); 635 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); 636 637 free_netaddr(netaddrP); 638 639 /* 640 * Windows doesn't have virtual interfaces, so child array 641 * is always empty. 642 */ 643 childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL); 644 if (childArr == NULL) { 645 return NULL; 646 } 647 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); 648 649 /* return the NetworkInterface */ 650 return netifObj; 651} 652 653/* 654 * Class: java_net_NetworkInterface 655 * Method: getByName0 656 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 657 */ 658JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 659 (JNIEnv *env, jclass cls, jstring name) 660{ 661 netif *ifList, *curr; 662 jboolean isCopy; 663 const char *name_utf; 664 jobject netifObj = NULL; 665 666 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 667 if (ipv6_available()) { 668 return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name); 669 } 670 671 /* get the list of interfaces */ 672 if (enumInterfaces(env, &ifList) < 0) { 673 return NULL; 674 } 675 676 /* get the name as a C string */ 677 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 678 if (name_utf != NULL) { 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 = createNetworkInterface(env, curr, -1, NULL); 692 } 693 694 /* release the UTF string */ 695 (*env)->ReleaseStringUTFChars(env, name, name_utf); 696 } else { 697 if (!(*env)->ExceptionCheck(env)) 698 JNU_ThrowOutOfMemoryError(env, NULL); 699 } 700 701 /* release the interface list */ 702 free_netif(ifList); 703 704 return netifObj; 705} 706 707/* 708 * Class: NetworkInterface 709 * Method: getByIndex0 710 * Signature: (I)LNetworkInterface; 711 */ 712JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0 713 (JNIEnv *env, jclass cls, jint index) 714{ 715 netif *ifList, *curr; 716 jobject netifObj = NULL; 717 718 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 719 if (ipv6_available()) { 720 return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index); 721 } 722 723 /* get the list of interfaces */ 724 if (enumInterfaces(env, &ifList) < 0) { 725 return NULL; 726 } 727 728 /* search by index */ 729 curr = ifList; 730 while (curr != NULL) { 731 if (index == curr->index) { 732 break; 733 } 734 curr = curr->next; 735 } 736 737 /* if found create a NetworkInterface */ 738 if (curr != NULL) { 739 netifObj = createNetworkInterface(env, curr, -1, NULL); 740 } 741 742 /* release the interface list */ 743 free_netif(ifList); 744 745 return netifObj; 746} 747 748/* 749 * Class: java_net_NetworkInterface 750 * Method: getByInetAddress0 751 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; 752 */ 753JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 754 (JNIEnv *env, jclass cls, jobject iaObj) 755{ 756 netif *ifList, *curr; 757 jint addr = getInetAddress_addr(env, iaObj); 758 jobject netifObj = NULL; 759 760 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 761 if (ipv6_available()) { 762 return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj); 763 } 764 765 /* get the list of interfaces */ 766 if (enumInterfaces(env, &ifList) < 0) { 767 return NULL; 768 } 769 770 /* 771 * Enumerate the addresses on each interface until we find a 772 * matching address. 773 */ 774 curr = ifList; 775 while (curr != NULL) { 776 int count; 777 netaddr *addrList; 778 netaddr *addrP; 779 780 /* enumerate the addresses on this interface */ 781 count = enumAddresses_win(env, curr, &addrList); 782 if (count < 0) { 783 free_netif(ifList); 784 return NULL; 785 } 786 787 /* iterate through each address */ 788 addrP = addrList; 789 790 while (addrP != NULL) { 791 if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) { 792 break; 793 } 794 addrP = addrP->next; 795 } 796 797 /* 798 * Address matched so create NetworkInterface for this interface 799 * and address list. 800 */ 801 if (addrP != NULL) { 802 /* createNetworkInterface will free addrList */ 803 netifObj = createNetworkInterface(env, curr, count, addrList); 804 break; 805 } 806 807 /* on next interface */ 808 curr = curr->next; 809 } 810 811 /* release the interface list */ 812 free_netif(ifList); 813 814 return netifObj; 815} 816 817/* 818 * Class: java_net_NetworkInterface 819 * Method: getAll 820 * Signature: ()[Ljava/net/NetworkInterface; 821 */ 822JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll 823 (JNIEnv *env, jclass cls) 824{ 825 int count; 826 netif *ifList, *curr; 827 jobjectArray netIFArr; 828 jint arr_index; 829 830 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 831 if (ipv6_available()) { 832 return Java_java_net_NetworkInterface_getAll_XP (env, cls); 833 } 834 835 /* 836 * Get list of interfaces 837 */ 838 count = enumInterfaces(env, &ifList); 839 if (count < 0) { 840 return NULL; 841 } 842 843 /* allocate a NetworkInterface array */ 844 netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); 845 if (netIFArr == NULL) { 846 return NULL; 847 } 848 849 /* 850 * Iterate through the interfaces, create a NetworkInterface instance 851 * for each array element and populate the object. 852 */ 853 curr = ifList; 854 arr_index = 0; 855 while (curr != NULL) { 856 jobject netifObj; 857 858 netifObj = createNetworkInterface(env, curr, -1, NULL); 859 if (netifObj == NULL) { 860 return NULL; 861 } 862 863 /* put the NetworkInterface into the array */ 864 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj); 865 866 curr = curr->next; 867 } 868 869 /* release the interface list */ 870 free_netif(ifList); 871 872 return netIFArr; 873} 874 875/* 876 * Class: java_net_NetworkInterface 877 * Method: isUp0 878 * Signature: (Ljava/lang/String;)Z 879 */ 880JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0 881 (JNIEnv *env, jclass cls, jstring name, jint index) { 882 jboolean ret = JNI_FALSE; 883 884 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 885 if (ipv6_available()) { 886 return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index); 887 } else { 888 MIB_IFROW *ifRowP; 889 ifRowP = getIF(index); 890 if (ifRowP != NULL) { 891 ret = ifRowP->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP && 892 (ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL || 893 ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED); 894 free(ifRowP); 895 } 896 } 897 return ret; 898} 899 900/* 901 * Class: java_net_NetworkInterface 902 * Method: isP2P0 903 * Signature: (Ljava/lang/String;I)Z 904 */ 905JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0 906 (JNIEnv *env, jclass cls, jstring name, jint index) { 907 MIB_IFROW *ifRowP; 908 jboolean ret = JNI_FALSE; 909 910 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 911 if (ipv6_available()) { 912 return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index); 913 } else { 914 ifRowP = getIF(index); 915 if (ifRowP != NULL) { 916 switch(ifRowP->dwType) { 917 case MIB_IF_TYPE_PPP: 918 case MIB_IF_TYPE_SLIP: 919 ret = JNI_TRUE; 920 break; 921 } 922 free(ifRowP); 923 } 924 } 925 return ret; 926} 927 928/* 929 * Class: java_net_NetworkInterface 930 * Method: isLoopback0 931 * Signature: (Ljava/lang/String;I)Z 932 */ 933JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0 934 (JNIEnv *env, jclass cls, jstring name, jint index) { 935 MIB_IFROW *ifRowP; 936 jboolean ret = JNI_FALSE; 937 938 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 939 if (ipv6_available()) { 940 return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index); 941 } else { 942 ifRowP = getIF(index); 943 if (ifRowP != NULL) { 944 if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK) 945 ret = JNI_TRUE; 946 free(ifRowP); 947 } 948 return ret; 949 } 950} 951 952/* 953 * Class: java_net_NetworkInterface 954 * Method: supportsMulticast0 955 * Signature: (Ljava/lang/String;I)Z 956 */ 957JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0 958 (JNIEnv *env, jclass cls, jstring name, jint index) { 959 return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls, 960 name, index); 961} 962 963/* 964 * Class: java_net_NetworkInterface 965 * Method: getMacAddr0 966 * Signature: ([bLjava/lang/String;I)[b 967 */ 968JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0 969 (JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) { 970 jbyteArray ret = NULL; 971 int len; 972 MIB_IFROW *ifRowP; 973 974 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 975 if (ipv6_available()) { 976 return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index); 977 } else { 978 ifRowP = getIF(index); 979 if (ifRowP != NULL) { 980 switch(ifRowP->dwType) { 981 case MIB_IF_TYPE_ETHERNET: 982 case MIB_IF_TYPE_TOKENRING: 983 case MIB_IF_TYPE_FDDI: 984 case IF_TYPE_IEEE80211: 985 len = ifRowP->dwPhysAddrLen; 986 if (len > 0) { 987 ret = (*env)->NewByteArray(env, len); 988 if (!IS_NULL(ret)) { 989 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); 990 } 991 } 992 break; 993 } 994 free(ifRowP); 995 } 996 return ret; 997 } 998} 999 1000/* 1001 * Class: java_net_NetworkInterface 1002 * Method: getMTU0 1003 * Signature: ([bLjava/lang/String;I)I 1004 */ 1005JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0 1006 (JNIEnv *env, jclass class, jstring name, jint index) { 1007 jint ret = -1; 1008 MIB_IFROW *ifRowP; 1009 1010 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 1011 if (ipv6_available()) { 1012 return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index); 1013 } else { 1014 ifRowP = getIF(index); 1015 if (ifRowP != NULL) { 1016 ret = ifRowP->dwMtu; 1017 free(ifRowP); 1018 } 1019 return ret; 1020 } 1021} 1022