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