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