1 /* 2 * Copyright (c) 2000, 2018, 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 51 jclass ni_class; /* NetworkInterface */ 52 53 jmethodID ni_ctor; /* NetworkInterface() */ 54 55 jfieldID ni_indexID; /* NetworkInterface.index */ 56 jfieldID ni_addrsID; /* NetworkInterface.addrs */ 57 jfieldID ni_bindsID; /* NetworkInterface.bindings */ 58 jfieldID ni_nameID; /* NetworkInterface.name */ 59 jfieldID ni_displayNameID; /* NetworkInterface.displayName */ 60 jfieldID ni_childsID; /* NetworkInterface.childs */ 61 62 jclass ni_ibcls; /* InterfaceAddress */ 63 jmethodID ni_ibctrID; /* InterfaceAddress() */ 64 jfieldID ni_ibaddressID; /* InterfaceAddress.address */ 65 jfieldID ni_ibbroadcastID; /* InterfaceAddress.broadcast */ 66 jfieldID ni_ibmaskID; /* InterfaceAddress.maskLength */ 67 68 /* 69 * Support routines to free netif and netaddr lists 70 */ 71 void 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 86 void 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 */ 98 MIB_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 */ 167 int 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 free(curr); 284 curr = NULL; 285 } 286 } 287 if (curr == NULL) { 288 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 289 free_netif(netifP); 290 free(tableP); 291 return -1; 292 } 293 294 /* 295 * Populate the interface. Note that we need to convert the 296 * index into its "friendly" value as otherwise we will expose 297 * 32-bit numbers as index values. 298 */ 299 strcpy(curr->name, dev_name); 300 if (wlen == 0) { 301 // display char type in case of MultiByteToWideChar failure 302 strncpy(curr->displayName, ifrowP->bDescr, ifrowP->dwDescrLen); 303 curr->displayName[ifrowP->dwDescrLen] = '\0'; 304 } else { 305 // call MultiByteToWideChar again to fill curr->displayName 306 // it should not fail, because we have called it once before 307 if (MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr, 308 ifrowP->dwDescrLen, curr->displayName, wlen) == 0) { 309 JNU_ThrowByName(env, "java/lang/Error", 310 "Cannot get multibyte char for interface display name"); 311 free_netif(netifP); 312 free(tableP); 313 free(curr->name); 314 free(curr->displayName); 315 free(curr); 316 return -1; 317 } else { 318 curr->displayName[wlen*(sizeof(wchar_t))] = '\0'; 319 curr->dNameIsUnicode = TRUE; 320 } 321 } 322 323 curr->dwIndex = ifrowP->dwIndex; 324 curr->ifType = ifrowP->dwType; 325 curr->index = GetFriendlyIfIndex(ifrowP->dwIndex); 326 327 /* 328 * Put the interface at tail of list as GetIfTable(,,TRUE) is 329 * returning the interfaces in index order. 330 */ 331 count++; 332 if (netifP == NULL) { 333 netifP = curr; 334 } else { 335 netif *tail = netifP; 336 while (tail->next != NULL) { 337 tail = tail->next; 338 } 339 tail->next = curr; 340 } 341 342 /* onto the next interface */ 343 ifrowP++; 344 } 345 346 /* 347 * Free the interface table and return the interface list 348 */ 349 if (tableP) { 350 free(tableP); 351 } 352 *netifPP = netifP; 353 return count; 354 } 355 356 /* 357 * Enumerate the IP addresses on an interface using the IP helper library 358 * routine GetIfAddrTable and matching based on the index name. There are 359 * more efficient routines but we use GetIfAddrTable because it's avaliable 360 * on 98 and NT. 361 * 362 * Returns the count of addresses, or -1 if error. If no error occurs then 363 * netaddrPP will return a list of netaddr structures with the IP addresses. 364 */ 365 int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) 366 { 367 MIB_IPADDRTABLE *tableP; 368 ULONG size; 369 DWORD ret; 370 DWORD i; 371 netaddr *netaddrP; 372 int count = 0; 373 unsigned long mask; 374 375 /* 376 * Use GetIpAddrTable to enumerate the IP Addresses 377 */ 378 size = sizeof(MIB_IPADDRTABLE); 379 tableP = (MIB_IPADDRTABLE *)malloc(size); 380 if (tableP == NULL) { 381 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 382 return -1; 383 } 384 385 ret = GetIpAddrTable(tableP, &size, FALSE); 386 if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) { 387 MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size); 388 if (newTableP == NULL) { 389 free(tableP); 390 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 391 return -1; 392 } 393 tableP = newTableP; 394 395 ret = GetIpAddrTable(tableP, &size, FALSE); 396 } 397 if (ret != NO_ERROR) { 398 if (tableP) { 399 free(tableP); 400 } 401 JNU_ThrowByName(env, "java/lang/Error", 402 "IP Helper Library GetIpAddrTable function failed"); 403 return -1; 404 } 405 406 /* 407 * Iterate through the table to find the addresses with the 408 * matching dwIndex. Ignore 0.0.0.0 addresses. 409 */ 410 count = 0; 411 netaddrP = NULL; 412 413 i = 0; 414 while (i<tableP->dwNumEntries) { 415 if (tableP->table[i].dwIndex == netifP->dwIndex && 416 tableP->table[i].dwAddr != 0) { 417 418 netaddr *curr = (netaddr *)malloc(sizeof(netaddr)); 419 if (curr == NULL) { 420 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); 421 free_netaddr(netaddrP); 422 free(tableP); 423 return -1; 424 } 425 426 curr->addr.sa4.sin_family = AF_INET; 427 curr->addr.sa4.sin_addr.s_addr = tableP->table[i].dwAddr; 428 /* 429 * Get netmask / broadcast address 430 */ 431 switch (netifP->ifType) { 432 case MIB_IF_TYPE_ETHERNET: 433 case MIB_IF_TYPE_TOKENRING: 434 case MIB_IF_TYPE_FDDI: 435 case MIB_IF_TYPE_LOOPBACK: 436 case IF_TYPE_IEEE80211: 437 /** 438 * Contrary to what it seems to indicate, dwBCastAddr doesn't 439 * contain the broadcast address but 0 or 1 depending on whether 440 * the broadcast address should set the bits of the host part 441 * to 0 or 1. 442 * Yes, I know it's stupid, but what can I say, it's MSFTs API. 443 */ 444 curr->brdcast.sa4.sin_family = AF_INET; 445 if (tableP->table[i].dwBCastAddr == 1) 446 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask); 447 else 448 curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask); 449 mask = ntohl(tableP->table[i].dwMask); 450 curr->mask = 0; 451 while (mask) { 452 mask <<= 1; 453 curr->mask++; 454 } 455 break; 456 case MIB_IF_TYPE_PPP: 457 case MIB_IF_TYPE_SLIP: 458 default: 459 /** 460 * these don't have broadcast/subnet 461 */ 462 curr->mask = -1; 463 break; 464 } 465 466 curr->next = netaddrP; 467 netaddrP = curr; 468 count++; 469 } 470 i++; 471 } 472 473 *netaddrPP = netaddrP; 474 free(tableP); 475 return count; 476 } 477 478 /* 479 * Class: java_net_NetworkInterface 480 * Method: init 481 * Signature: ()V 482 */ 483 JNIEXPORT void JNICALL 484 Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) 485 { 486 /* 487 * Get the various JNI ids that we require 488 */ 489 ni_class = (*env)->NewGlobalRef(env, cls); 490 CHECK_NULL(ni_class); 491 ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;"); 492 CHECK_NULL(ni_nameID); 493 ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;"); 494 CHECK_NULL(ni_displayNameID); 495 ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I"); 496 CHECK_NULL(ni_indexID); 497 ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;"); 498 CHECK_NULL(ni_addrsID); 499 ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;"); 500 CHECK_NULL(ni_bindsID); 501 ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;"); 502 CHECK_NULL(ni_childsID); 503 ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V"); 504 CHECK_NULL(ni_ctor); 505 ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress"); 506 CHECK_NULL(ni_ibcls); 507 ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls); 508 CHECK_NULL(ni_ibcls); 509 ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V"); 510 CHECK_NULL(ni_ibctrID); 511 ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;"); 512 CHECK_NULL(ni_ibaddressID); 513 ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;"); 514 CHECK_NULL(ni_ibbroadcastID); 515 ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S"); 516 CHECK_NULL(ni_ibmaskID); 517 518 initInetAddressIDs(env); 519 } 520 521 /* 522 * Create a NetworkInterface object, populate the name and index, and 523 * populate the InetAddress array based on the IP addresses for this 524 * interface. 525 */ 526 jobject createNetworkInterface 527 (JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP) 528 { 529 jobject netifObj; 530 jobject name, displayName; 531 jobjectArray addrArr, bindsArr, childArr; 532 netaddr *addrs; 533 jint addr_index; 534 jint bind_index; 535 536 /* 537 * Create a NetworkInterface object and populate it 538 */ 539 netifObj = (*env)->NewObject(env, ni_class, ni_ctor); 540 CHECK_NULL_RETURN(netifObj, NULL); 541 name = (*env)->NewStringUTF(env, ifs->name); 542 CHECK_NULL_RETURN(name, NULL); 543 if (ifs->dNameIsUnicode) { 544 displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName, 545 (jsize)wcslen ((PWCHAR)ifs->displayName)); 546 } else { 547 displayName = (*env)->NewStringUTF(env, ifs->displayName); 548 } 549 CHECK_NULL_RETURN(displayName, NULL); 550 (*env)->SetObjectField(env, netifObj, ni_nameID, name); 551 (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName); 552 (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index); 553 554 /* 555 * Get the IP addresses for this interface if necessary 556 * Note that 0 is a valid number of addresses. 557 */ 558 if (netaddrCount < 0) { 559 netaddrCount = enumAddresses_win(env, ifs, &netaddrP); 560 if (netaddrCount == -1) { 561 return NULL; 562 } 563 } 564 addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL); 565 if (addrArr == NULL) { 566 free_netaddr(netaddrP); 567 return NULL; 568 } 569 570 bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL); 571 if (bindsArr == NULL) { 572 free_netaddr(netaddrP); 573 return NULL; 574 } 575 addrs = netaddrP; 576 addr_index = 0; 577 bind_index = 0; 578 while (addrs != NULL) { 579 jobject iaObj, ia2Obj; 580 jobject ibObj = NULL; 581 if (addrs->addr.sa.sa_family == AF_INET) { 582 iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 583 if (iaObj == NULL) { 584 free_netaddr(netaddrP); 585 return NULL; 586 } 587 /* default ctor will set family to AF_INET */ 588 589 setInetAddress_addr(env, iaObj, ntohl(addrs->addr.sa4.sin_addr.s_addr)); 590 if ((*env)->ExceptionCheck(env)) { 591 free_netaddr(netaddrP); 592 return NULL; 593 } 594 if (addrs->mask != -1) { 595 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 596 if (ibObj == NULL) { 597 free_netaddr(netaddrP); 598 return NULL; 599 } 600 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 601 ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 602 if (ia2Obj == NULL) { 603 free_netaddr(netaddrP); 604 return NULL; 605 } 606 setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.sa4.sin_addr.s_addr)); 607 if ((*env)->ExceptionCheck(env)) { 608 free_netaddr(netaddrP); 609 return NULL; 610 } 611 (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj); 612 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 613 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 614 } 615 } else /* AF_INET6 */ { 616 int scope; 617 iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); 618 if (iaObj) { 619 jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr)); 620 if (ret == JNI_FALSE) { 621 free_netaddr(netaddrP); 622 return NULL; 623 } 624 625 scope = addrs->addr.sa6.sin6_scope_id; 626 if (scope != 0) { /* zero is default value, no need to set */ 627 setInet6Address_scopeid(env, iaObj, scope); 628 setInet6Address_scopeifname(env, iaObj, netifObj); 629 } 630 ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); 631 if (ibObj == NULL) { 632 free_netaddr(netaddrP); 633 return NULL; 634 } 635 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); 636 (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask); 637 (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj); 638 } 639 } 640 (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj); 641 addrs = addrs->next; 642 addr_index++; 643 } 644 (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr); 645 (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr); 646 647 free_netaddr(netaddrP); 648 649 /* 650 * Windows doesn't have virtual interfaces, so child array 651 * is always empty. 652 */ 653 childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL); 654 if (childArr == NULL) { 655 return NULL; 656 } 657 (*env)->SetObjectField(env, netifObj, ni_childsID, childArr); 658 659 /* return the NetworkInterface */ 660 return netifObj; 661 } 662 663 /* 664 * Class: java_net_NetworkInterface 665 * Method: getByName0 666 * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface; 667 */ 668 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 669 (JNIEnv *env, jclass cls, jstring name) 670 { 671 netif *ifList, *curr; 672 jboolean isCopy; 673 const char *name_utf; 674 jobject netifObj = NULL; 675 676 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 677 if (ipv6_available()) { 678 return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name); 679 } 680 681 /* get the list of interfaces */ 682 if (enumInterfaces(env, &ifList) < 0) { 683 return NULL; 684 } 685 686 /* get the name as a C string */ 687 name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); 688 if (name_utf != NULL) { 689 690 /* Search by name */ 691 curr = ifList; 692 while (curr != NULL) { 693 if (strcmp(name_utf, curr->name) == 0) { 694 break; 695 } 696 curr = curr->next; 697 } 698 699 /* if found create a NetworkInterface */ 700 if (curr != NULL) {; 701 netifObj = createNetworkInterface(env, curr, -1, NULL); 702 } 703 704 /* release the UTF string */ 705 (*env)->ReleaseStringUTFChars(env, name, name_utf); 706 } else { 707 if (!(*env)->ExceptionCheck(env)) 708 JNU_ThrowOutOfMemoryError(env, NULL); 709 } 710 711 /* release the interface list */ 712 free_netif(ifList); 713 714 return netifObj; 715 } 716 717 /* 718 * Class: NetworkInterface 719 * Method: getByIndex0 720 * Signature: (I)LNetworkInterface; 721 */ 722 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0 723 (JNIEnv *env, jclass cls, jint index) 724 { 725 netif *ifList, *curr; 726 jobject netifObj = NULL; 727 728 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 729 if (ipv6_available()) { 730 return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index); 731 } 732 733 /* get the list of interfaces */ 734 if (enumInterfaces(env, &ifList) < 0) { 735 return NULL; 736 } 737 738 /* search by index */ 739 curr = ifList; 740 while (curr != NULL) { 741 if (index == curr->index) { 742 break; 743 } 744 curr = curr->next; 745 } 746 747 /* if found create a NetworkInterface */ 748 if (curr != NULL) { 749 netifObj = createNetworkInterface(env, curr, -1, NULL); 750 } 751 752 /* release the interface list */ 753 free_netif(ifList); 754 755 return netifObj; 756 } 757 758 /* 759 * Class: java_net_NetworkInterface 760 * Method: getByInetAddress0 761 * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface; 762 */ 763 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 764 (JNIEnv *env, jclass cls, jobject iaObj) 765 { 766 netif *ifList, *curr; 767 jobject netifObj = NULL; 768 jint addr = getInetAddress_addr(env, iaObj); 769 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 770 771 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 772 if (ipv6_available()) { 773 return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj); 774 } 775 776 /* get the list of interfaces */ 777 if (enumInterfaces(env, &ifList) < 0) { 778 return NULL; 779 } 780 781 /* 782 * Enumerate the addresses on each interface until we find a 783 * matching address. 784 */ 785 curr = ifList; 786 while (curr != NULL) { 787 int count; 788 netaddr *addrList; 789 netaddr *addrP; 790 791 /* enumerate the addresses on this interface */ 792 count = enumAddresses_win(env, curr, &addrList); 793 if (count < 0) { 794 free_netif(ifList); 795 return NULL; 796 } 797 798 /* iterate through each address */ 799 addrP = addrList; 800 801 while (addrP != NULL) { 802 if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) { 803 break; 804 } 805 addrP = addrP->next; 806 } 807 808 /* 809 * Address matched so create NetworkInterface for this interface 810 * and address list. 811 */ 812 if (addrP != NULL) { 813 /* createNetworkInterface will free addrList */ 814 netifObj = createNetworkInterface(env, curr, count, addrList); 815 break; 816 } 817 818 /* on next interface */ 819 curr = curr->next; 820 } 821 822 /* release the interface list */ 823 free_netif(ifList); 824 825 return netifObj; 826 } 827 828 /* 829 * Class: java_net_NetworkInterface 830 * Method: getAll 831 * Signature: ()[Ljava/net/NetworkInterface; 832 */ 833 JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll 834 (JNIEnv *env, jclass cls) 835 { 836 int count; 837 netif *ifList = NULL, *curr; 838 jobjectArray netIFArr; 839 jint arr_index; 840 841 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 842 if (ipv6_available()) { 843 return Java_java_net_NetworkInterface_getAll_XP (env, cls); 844 } 845 846 /* 847 * Get list of interfaces 848 */ 849 count = enumInterfaces(env, &ifList); 850 if (count < 0) { 851 return NULL; 852 } 853 854 /* allocate a NetworkInterface array */ 855 netIFArr = (*env)->NewObjectArray(env, count, cls, NULL); 856 if (netIFArr == NULL) { 857 free_netif(ifList); 858 return NULL; 859 } 860 861 /* 862 * Iterate through the interfaces, create a NetworkInterface instance 863 * for each array element and populate the object. 864 */ 865 curr = ifList; 866 arr_index = 0; 867 while (curr != NULL) { 868 jobject netifObj; 869 870 netifObj = createNetworkInterface(env, curr, -1, NULL); 871 if (netifObj == NULL) { 872 free_netif(ifList); 873 return NULL; 874 } 875 876 /* put the NetworkInterface into the array */ 877 (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj); 878 879 curr = curr->next; 880 } 881 882 /* release the interface list */ 883 free_netif(ifList); 884 885 return netIFArr; 886 } 887 888 /* 889 * Class: java_net_NetworkInterface 890 * Method: isUp0 891 * Signature: (Ljava/lang/String;)Z 892 */ 893 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0 894 (JNIEnv *env, jclass cls, jstring name, jint index) { 895 jboolean ret = JNI_FALSE; 896 897 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 898 if (ipv6_available()) { 899 return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index); 900 } else { 901 MIB_IFROW *ifRowP; 902 ifRowP = getIF(index); 903 if (ifRowP != NULL) { 904 ret = ifRowP->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP && 905 (ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL || 906 ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED); 907 free(ifRowP); 908 } 909 } 910 return ret; 911 } 912 913 /* 914 * Class: java_net_NetworkInterface 915 * Method: isP2P0 916 * Signature: (Ljava/lang/String;I)Z 917 */ 918 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0 919 (JNIEnv *env, jclass cls, jstring name, jint index) { 920 MIB_IFROW *ifRowP; 921 jboolean ret = JNI_FALSE; 922 923 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 924 if (ipv6_available()) { 925 return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index); 926 } else { 927 ifRowP = getIF(index); 928 if (ifRowP != NULL) { 929 switch(ifRowP->dwType) { 930 case MIB_IF_TYPE_PPP: 931 case MIB_IF_TYPE_SLIP: 932 ret = JNI_TRUE; 933 break; 934 } 935 free(ifRowP); 936 } 937 } 938 return ret; 939 } 940 941 /* 942 * Class: java_net_NetworkInterface 943 * Method: isLoopback0 944 * Signature: (Ljava/lang/String;I)Z 945 */ 946 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0 947 (JNIEnv *env, jclass cls, jstring name, jint index) { 948 MIB_IFROW *ifRowP; 949 jboolean ret = JNI_FALSE; 950 951 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 952 if (ipv6_available()) { 953 return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index); 954 } else { 955 ifRowP = getIF(index); 956 if (ifRowP != NULL) { 957 if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK) 958 ret = JNI_TRUE; 959 free(ifRowP); 960 } 961 return ret; 962 } 963 } 964 965 /* 966 * Class: java_net_NetworkInterface 967 * Method: supportsMulticast0 968 * Signature: (Ljava/lang/String;I)Z 969 */ 970 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0 971 (JNIEnv *env, jclass cls, jstring name, jint index) { 972 return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls, 973 name, index); 974 } 975 976 /* 977 * Class: java_net_NetworkInterface 978 * Method: getMacAddr0 979 * Signature: ([bLjava/lang/String;I)[b 980 */ 981 JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0 982 (JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) { 983 jbyteArray ret = NULL; 984 int len; 985 MIB_IFROW *ifRowP; 986 987 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 988 if (ipv6_available()) { 989 return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index); 990 } else { 991 ifRowP = getIF(index); 992 if (ifRowP != NULL) { 993 switch(ifRowP->dwType) { 994 case MIB_IF_TYPE_ETHERNET: 995 case MIB_IF_TYPE_TOKENRING: 996 case MIB_IF_TYPE_FDDI: 997 case IF_TYPE_IEEE80211: 998 len = ifRowP->dwPhysAddrLen; 999 if (len > 0) { 1000 ret = (*env)->NewByteArray(env, len); 1001 if (!IS_NULL(ret)) { 1002 (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); 1003 } 1004 } 1005 break; 1006 } 1007 free(ifRowP); 1008 } 1009 return ret; 1010 } 1011 } 1012 1013 /* 1014 * Class: java_net_NetworkInterface 1015 * Method: getMTU0 1016 * Signature: ([bLjava/lang/String;I)I 1017 */ 1018 JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0 1019 (JNIEnv *env, jclass class, jstring name, jint index) { 1020 jint ret = -1; 1021 MIB_IFROW *ifRowP; 1022 1023 // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack 1024 if (ipv6_available()) { 1025 return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index); 1026 } else { 1027 ifRowP = getIF(index); 1028 if (ifRowP != NULL) { 1029 ret = ifRowP->dwMtu; 1030 free(ifRowP); 1031 } 1032 return ret; 1033 } 1034 }