Path: blob/master/src/java.base/windows/native/libnet/NetworkInterface.c
41119 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include "net_util.h"25#include "NetworkInterface.h"2627#include "java_net_InetAddress.h"28#include "java_net_NetworkInterface.h"2930/*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 routines36* GetIfTable, GetIfAddrTable resp. These routines are available on Windows37* 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if38* IE is upgraded to 5.x.39*40* Windows does not have any standard for device names so we are forced41* to use our own convention which is based on the normal Unix naming42* convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices,43* tr0, tr1, .. for token ring, and so on). This convention gives us44* consistency across multiple Windows editions and also consistency with45* Solaris/Linux device names. Note that we always enumerate in index46* order and this ensures consistent device number across invocations.47*/4849/* various JNI ids */5051jclass ni_class; /* NetworkInterface */5253jmethodID ni_ctor; /* NetworkInterface() */5455jfieldID ni_indexID; /* NetworkInterface.index */56jfieldID ni_addrsID; /* NetworkInterface.addrs */57jfieldID ni_bindsID; /* NetworkInterface.bindings */58jfieldID ni_nameID; /* NetworkInterface.name */59jfieldID ni_displayNameID; /* NetworkInterface.displayName */60jfieldID ni_childsID; /* NetworkInterface.childs */6162jclass ni_ibcls; /* InterfaceAddress */63jmethodID ni_ibctrID; /* InterfaceAddress() */64jfieldID ni_ibaddressID; /* InterfaceAddress.address */65jfieldID ni_ibbroadcastID; /* InterfaceAddress.broadcast */66jfieldID ni_ibmaskID; /* InterfaceAddress.maskLength */6768/*69* Support routines to free netif and netaddr lists70*/71void free_netif(netif *netifP) {72netif *curr = netifP;73while (curr != NULL) {74if (curr->name != NULL)75free(curr->name);76if (curr->displayName != NULL)77free(curr->displayName);78if (curr->addrs != NULL)79free_netaddr (curr->addrs);80netifP = netifP->next;81free(curr);82curr = netifP;83}84}8586void free_netaddr(netaddr *netaddrP) {87netaddr *curr = netaddrP;88while (curr != NULL) {89netaddrP = netaddrP->next;90free(curr);91curr = netaddrP;92}93}9495/*96* Returns the interface structure from the table with the matching index.97*/98MIB_IFROW *getIF(jint index) {99MIB_IFTABLE *tableP;100MIB_IFROW *ifrowP, *ret = NULL;101ULONG size;102DWORD i, count;103jint ifindex;104105/*106* Ask the IP Helper library to enumerate the adapters107*/108size = sizeof(MIB_IFTABLE);109tableP = (MIB_IFTABLE *)malloc(size);110if(tableP == NULL)111return NULL;112113count = GetIfTable(tableP, &size, TRUE);114if (count == ERROR_INSUFFICIENT_BUFFER || count == ERROR_BUFFER_OVERFLOW) {115MIB_IFTABLE* newTableP = (MIB_IFTABLE *)realloc(tableP, size);116if (newTableP == NULL) {117free(tableP);118return NULL;119}120tableP = newTableP;121122count = GetIfTable(tableP, &size, TRUE);123}124125if (count != NO_ERROR) {126free(tableP);127return NULL;128}129130{131ifrowP = tableP->table;132for (i=0; i<tableP->dwNumEntries; i++) {133/*134* Warning: the real index is obtained by GetFriendlyIfIndex()135*/136ifindex = GetFriendlyIfIndex(ifrowP->dwIndex);137if (ifindex == index) {138/*139* Create a copy of the entry so that we can free the table.140*/141ret = (MIB_IFROW *) malloc(sizeof(MIB_IFROW));142if (ret == NULL) {143free(tableP);144return NULL;145}146memcpy(ret, ifrowP, sizeof(MIB_IFROW));147break;148}149150/* onto the next interface */151ifrowP++;152}153free(tableP);154}155return ret;156}157158/*159* Enumerate network interfaces using IP Helper Library routine GetIfTable.160* We use GetIfTable rather than other IP helper routines because it's161* available on 98 & NT SP4+.162*163* Returns the number of interfaces found or -1 if error. If no error164* occurs then netifPP be returned as list of netif structures or NULL165* if no interfaces are found.166*/167int enumInterfaces(JNIEnv *env, netif **netifPP)168{169MIB_IFTABLE *tableP;170MIB_IFROW *ifrowP;171ULONG size;172DWORD ret;173int count;174netif *netifP;175DWORD i;176int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0, wlen=0;177178/*179* Ask the IP Helper library to enumerate the adapters180*/181size = sizeof(MIB_IFTABLE);182tableP = (MIB_IFTABLE *)malloc(size);183if (tableP == NULL) {184JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");185return -1;186}187188ret = GetIfTable(tableP, &size, TRUE);189if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {190MIB_IFTABLE * newTableP = (MIB_IFTABLE *)realloc(tableP, size);191if (newTableP == NULL) {192free(tableP);193JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");194return -1;195}196tableP = newTableP;197ret = GetIfTable(tableP, &size, TRUE);198}199200if (ret != NO_ERROR) {201free(tableP);202203JNU_ThrowByName(env, "java/lang/Error",204"IP Helper Library GetIfTable function failed");205// this different error code is to handle the case when we call206// GetIpAddrTable in pure IPv6 environment207return -2;208}209210/*211* Iterate through the list of adapters212*/213count = 0;214netifP = NULL;215216ifrowP = tableP->table;217for (i=0; i<tableP->dwNumEntries; i++) {218char dev_name[8];219netif *curr;220221/*222* Generate a name for the device as Windows doesn't have any223* real concept of a device name.224*/225switch (ifrowP->dwType) {226case MIB_IF_TYPE_ETHERNET:227_snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++);228break;229230case MIB_IF_TYPE_TOKENRING:231_snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++);232break;233234case MIB_IF_TYPE_FDDI:235_snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++);236break;237238case MIB_IF_TYPE_LOOPBACK:239/* There should only be only IPv4 loopback address */240if (lo > 0) {241continue;242}243strncpy_s(dev_name, 8, "lo", _TRUNCATE);244lo++;245break;246247case MIB_IF_TYPE_PPP:248_snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++);249break;250251case MIB_IF_TYPE_SLIP:252_snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++);253break;254255case IF_TYPE_IEEE80211:256_snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++);257break;258259default:260_snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++);261}262263/*264* Allocate a netif structure and space for the name and265* display name (description in this case).266*/267curr = (netif *)calloc(1, sizeof(netif));268if (curr != NULL) {269wlen = MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,270ifrowP->dwDescrLen, NULL, 0);271if(wlen == 0) {272// MultiByteToWideChar should not fail273// But in rare case it fails, we allow 'char' to be displayed274curr->displayName = (char *)malloc(ifrowP->dwDescrLen + 1);275} else {276curr->displayName = (wchar_t *)malloc((wlen+1)*sizeof(wchar_t));277}278279curr->name = (char *)malloc(strlen(dev_name) + 1);280281if (curr->name == NULL || curr->displayName == NULL) {282if (curr->name) free(curr->name);283if (curr->displayName) free(curr->displayName);284free(curr);285curr = NULL;286}287}288if (curr == NULL) {289JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");290free_netif(netifP);291free(tableP);292return -1;293}294295/*296* Populate the interface. Note that we need to convert the297* index into its "friendly" value as otherwise we will expose298* 32-bit numbers as index values.299*/300strcpy(curr->name, dev_name);301if (wlen == 0) {302// display char type in case of MultiByteToWideChar failure303strncpy(curr->displayName, ifrowP->bDescr, ifrowP->dwDescrLen);304curr->displayName[ifrowP->dwDescrLen] = '\0';305} else {306// call MultiByteToWideChar again to fill curr->displayName307// it should not fail, because we have called it once before308if (MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,309ifrowP->dwDescrLen, curr->displayName, wlen) == 0) {310JNU_ThrowByName(env, "java/lang/Error",311"Cannot get multibyte char for interface display name");312free_netif(netifP);313free(tableP);314free(curr->name);315free(curr->displayName);316free(curr);317return -1;318} else {319((wchar_t *)curr->displayName)[wlen] = L'\0';320curr->dNameIsUnicode = TRUE;321}322}323324curr->dwIndex = ifrowP->dwIndex;325curr->ifType = ifrowP->dwType;326curr->index = GetFriendlyIfIndex(ifrowP->dwIndex);327328/*329* Put the interface at tail of list as GetIfTable(,,TRUE) is330* returning the interfaces in index order.331*/332count++;333if (netifP == NULL) {334netifP = curr;335} else {336netif *tail = netifP;337while (tail->next != NULL) {338tail = tail->next;339}340tail->next = curr;341}342343/* onto the next interface */344ifrowP++;345}346347/*348* Free the interface table and return the interface list349*/350if (tableP != NULL) {351free(tableP);352}353*netifPP = netifP;354return count;355}356357/*358* Enumerate all addresses using the IP helper library359*/360int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP)361{362MIB_IPADDRTABLE *tableP;363ULONG size;364DWORD ret;365/*366* Use GetIpAddrTable to enumerate the IP Addresses367*/368size = sizeof(MIB_IPADDRTABLE);369tableP = (MIB_IPADDRTABLE *)malloc(size);370if (tableP == NULL) {371JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");372return -1;373}374375ret = GetIpAddrTable(tableP, &size, FALSE);376if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {377MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size);378if (newTableP == NULL) {379free(tableP);380JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");381return -1;382}383tableP = newTableP;384385ret = GetIpAddrTable(tableP, &size, FALSE);386}387if (ret != NO_ERROR) {388if (tableP != NULL) {389free(tableP);390}391JNU_ThrowByName(env, "java/lang/Error",392"IP Helper Library GetIpAddrTable function failed");393// this different error code is to handle the case when we call394// GetIpAddrTable in pure IPv6 environment395return -2;396}397*tablePP = tableP;398return 0;399}400401/*402* Enumerate the IP addresses on an interface, given an IP address table403* and matching based on index.404*405* Returns the count of addresses, or -1 if error. If no error occurs then406* netaddrPP will return a list of netaddr structures with the IP addresses.407*/408int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP)409{410DWORD i;411netaddr *netaddrP;412int count = 0;413unsigned long mask;414415/*416* Iterate through the table to find the addresses with the417* matching dwIndex. Ignore 0.0.0.0 addresses.418*/419if (tableP == NULL)420return 0;421count = 0;422netaddrP = NULL;423424i = 0;425while (i < tableP->dwNumEntries) {426if (tableP->table[i].dwIndex == netifP->dwIndex &&427tableP->table[i].dwAddr != 0) {428429netaddr *curr = (netaddr *)malloc(sizeof(netaddr));430if (curr == NULL) {431JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");432free_netaddr(netaddrP);433free(tableP);434return -1;435}436437curr->addr.sa4.sin_family = AF_INET;438curr->addr.sa4.sin_addr.s_addr = tableP->table[i].dwAddr;439/*440* Get netmask / broadcast address441*/442switch (netifP->ifType) {443case MIB_IF_TYPE_ETHERNET:444case MIB_IF_TYPE_TOKENRING:445case MIB_IF_TYPE_FDDI:446case MIB_IF_TYPE_LOOPBACK:447case IF_TYPE_IEEE80211:448/**449* Contrary to what it seems to indicate, dwBCastAddr doesn't450* contain the broadcast address but 0 or 1 depending on whether451* the broadcast address should set the bits of the host part452* to 0 or 1.453* Yes, I know it's stupid, but what can I say, it's MSFTs API.454*/455curr->brdcast.sa4.sin_family = AF_INET;456if (tableP->table[i].dwBCastAddr == 1)457curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask);458else459curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask);460mask = ntohl(tableP->table[i].dwMask);461curr->mask = 0;462while (mask) {463mask <<= 1;464curr->mask++;465}466break;467case MIB_IF_TYPE_PPP:468case MIB_IF_TYPE_SLIP:469default:470/**471* these don't have broadcast/subnet472*/473curr->mask = -1;474break;475}476477curr->next = netaddrP;478netaddrP = curr;479count++;480}481i++;482}483484*netaddrPP = netaddrP;485return count;486}487488489/*490* Enumerate the IP addresses on an interface, using an IP address table491* retrieved using GetIPAddrTable and matching based on index.492*493* Returns the count of addresses, or -1 if error. If no error occurs then494* netaddrPP will return a list of netaddr structures with the IP addresses.495*/496int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) {497MIB_IPADDRTABLE *tableP;498int count;499int ret = lookupIPAddrTable(env, &tableP);500if (ret < 0) {501return NULL;502}503count = enumAddresses_win_ipaddrtable(env, netifP, netaddrPP, tableP);504free(tableP);505return count;506}507508509/*510* Class: java_net_NetworkInterface511* Method: init512* Signature: ()V513*/514JNIEXPORT void JNICALL515Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls)516{517/*518* Get the various JNI ids that we require519*/520ni_class = (*env)->NewGlobalRef(env, cls);521CHECK_NULL(ni_class);522ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");523CHECK_NULL(ni_nameID);524ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");525CHECK_NULL(ni_displayNameID);526ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");527CHECK_NULL(ni_indexID);528ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");529CHECK_NULL(ni_addrsID);530ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");531CHECK_NULL(ni_bindsID);532ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");533CHECK_NULL(ni_childsID);534ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V");535CHECK_NULL(ni_ctor);536ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");537CHECK_NULL(ni_ibcls);538ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);539CHECK_NULL(ni_ibcls);540ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");541CHECK_NULL(ni_ibctrID);542ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");543CHECK_NULL(ni_ibaddressID);544ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");545CHECK_NULL(ni_ibbroadcastID);546ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");547CHECK_NULL(ni_ibmaskID);548549initInetAddressIDs(env);550}551552/*553* Create a NetworkInterface object, populate the name and index, and554* populate the InetAddress array based on the IP addresses for this555* interface.556*/557jobject createNetworkInterface558(JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP)559{560jobject netifObj;561jobject name, displayName;562jobjectArray addrArr, bindsArr, childArr;563netaddr *addrs;564jint addr_index;565jint bind_index;566567/*568* Create a NetworkInterface object and populate it569*/570netifObj = (*env)->NewObject(env, ni_class, ni_ctor);571CHECK_NULL_RETURN(netifObj, NULL);572name = (*env)->NewStringUTF(env, ifs->name);573CHECK_NULL_RETURN(name, NULL);574if (ifs->dNameIsUnicode) {575displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,576(jsize)wcslen ((PWCHAR)ifs->displayName));577} else {578displayName = (*env)->NewStringUTF(env, ifs->displayName);579}580CHECK_NULL_RETURN(displayName, NULL);581(*env)->SetObjectField(env, netifObj, ni_nameID, name);582(*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);583(*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);584585/*586* Get the IP addresses for this interface if necessary587* Note that 0 is a valid number of addresses.588*/589if (netaddrCount < 0) {590netaddrCount = enumAddresses_win(env, ifs, &netaddrP);591if (netaddrCount < 0) {592return NULL;593}594}595addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);596if (addrArr == NULL) {597free_netaddr(netaddrP);598return NULL;599}600601bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);602if (bindsArr == NULL) {603free_netaddr(netaddrP);604return NULL;605}606addrs = netaddrP;607addr_index = 0;608bind_index = 0;609while (addrs != NULL) {610jobject iaObj, ia2Obj;611jobject ibObj = NULL;612if (addrs->addr.sa.sa_family == AF_INET) {613iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);614if (iaObj == NULL) {615free_netaddr(netaddrP);616return NULL;617}618/* default ctor will set family to AF_INET */619620setInetAddress_addr(env, iaObj, ntohl(addrs->addr.sa4.sin_addr.s_addr));621if ((*env)->ExceptionCheck(env)) {622free_netaddr(netaddrP);623return NULL;624}625if (addrs->mask != -1) {626ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);627if (ibObj == NULL) {628free_netaddr(netaddrP);629return NULL;630}631(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);632ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);633if (ia2Obj == NULL) {634free_netaddr(netaddrP);635return NULL;636}637setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.sa4.sin_addr.s_addr));638if ((*env)->ExceptionCheck(env)) {639free_netaddr(netaddrP);640return NULL;641}642(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);643(*env)->DeleteLocalRef(env, ia2Obj);644(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);645(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);646(*env)->DeleteLocalRef(env, ibObj);647}648} else /* AF_INET6 */ {649int scope;650iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);651if (iaObj) {652jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));653if (ret == JNI_FALSE) {654free_netaddr(netaddrP);655return NULL;656}657658scope = addrs->addr.sa6.sin6_scope_id;659if (scope != 0) { /* zero is default value, no need to set */660setInet6Address_scopeid(env, iaObj, scope);661setInet6Address_scopeifname(env, iaObj, netifObj);662}663ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);664if (ibObj == NULL) {665free_netaddr(netaddrP);666return NULL;667}668(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);669(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);670(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);671(*env)->DeleteLocalRef(env, ibObj);672}673}674(*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);675(*env)->DeleteLocalRef(env, iaObj);676addrs = addrs->next;677addr_index++;678}679(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);680(*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);681682free_netaddr(netaddrP);683(*env)->DeleteLocalRef(env, name);684(*env)->DeleteLocalRef(env, displayName);685(*env)->DeleteLocalRef(env, addrArr);686(*env)->DeleteLocalRef(env, bindsArr);687688/*689* Windows doesn't have virtual interfaces, so child array690* is always empty.691*/692childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);693if (childArr == NULL) {694return NULL;695}696(*env)->SetObjectField(env, netifObj, ni_childsID, childArr);697(*env)->DeleteLocalRef(env, childArr);698699/* return the NetworkInterface */700return netifObj;701}702703/*704* Class: java_net_NetworkInterface705* Method: getByName0706* Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;707*/708JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0709(JNIEnv *env, jclass cls, jstring name)710{711netif *ifList, *curr;712jboolean isCopy;713const char *name_utf;714jobject netifObj = NULL;715716// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack717if (ipv6_available()) {718return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name);719}720721/* get the list of interfaces */722if (enumInterfaces(env, &ifList) < 0) {723return NULL;724}725726/* get the name as a C string */727name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);728if (name_utf != NULL) {729730/* Search by name */731curr = ifList;732while (curr != NULL) {733if (strcmp(name_utf, curr->name) == 0) {734break;735}736curr = curr->next;737}738739/* if found create a NetworkInterface */740if (curr != NULL) {;741netifObj = createNetworkInterface(env, curr, -1, NULL);742}743744/* release the UTF string */745(*env)->ReleaseStringUTFChars(env, name, name_utf);746} else {747if (!(*env)->ExceptionCheck(env))748JNU_ThrowOutOfMemoryError(env, NULL);749}750751/* release the interface list */752free_netif(ifList);753754return netifObj;755}756757/*758* Class: NetworkInterface759* Method: getByIndex0760* Signature: (I)LNetworkInterface;761*/762JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0763(JNIEnv *env, jclass cls, jint index)764{765netif *ifList, *curr;766jobject netifObj = NULL;767768// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack769if (ipv6_available()) {770return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index);771}772773/* get the list of interfaces */774if (enumInterfaces(env, &ifList) < 0) {775return NULL;776}777778/* search by index */779curr = ifList;780while (curr != NULL) {781if (index == curr->index) {782break;783}784curr = curr->next;785}786787/* if found create a NetworkInterface */788if (curr != NULL) {789netifObj = createNetworkInterface(env, curr, -1, NULL);790}791792/* release the interface list */793free_netif(ifList);794795return netifObj;796}797798799/*800* Class: java_net_NetworkInterface801* Method: boundInetAddress0802* Signature: (Ljava/net/InetAddress;)Z803*/804JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0805(JNIEnv *env, jclass cls, jobject iaObj)806{807jobject netifObj = NULL;808DWORD i;809810int family = getInetAddress_family(env, iaObj);811JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);812813if (family == java_net_InetAddress_IPv6) {814if (!ipv6_available())815return JNI_FALSE;816return Java_java_net_NetworkInterface_getByInetAddress0_XP(env, cls, iaObj) != NULL;817} else if (family == java_net_InetAddress_IPv4) {818jint addr = getInetAddress_addr(env, iaObj);819JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);820821jboolean found = JNI_FALSE;822MIB_IPADDRTABLE *tableP;823if (lookupIPAddrTable(env, &tableP) >= 0 && tableP != NULL) {824for (i = 0; i < tableP->dwNumEntries; i++) {825if (tableP->table[i].dwAddr != 0 &&826(unsigned long)addr == ntohl(tableP->table[i].dwAddr)) {827found = JNI_TRUE;828break;829}830}831}832if (tableP != NULL) {833free(tableP);834}835return found;836} else {837// Unknown address family838return JNI_FALSE;839}840}841842/*843* Class: java_net_NetworkInterface844* Method: getByInetAddress0845* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;846*/847JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0848(JNIEnv *env, jclass cls, jobject iaObj)849{850netif *ifList, *curr;851MIB_IPADDRTABLE *tableP;852jobject netifObj = NULL;853jint addr = getInetAddress_addr(env, iaObj);854JNU_CHECK_EXCEPTION_RETURN(env, NULL);855856if (ipv6_available()) {857return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);858}859860/* get the list of interfaces */861if (enumInterfaces(env, &ifList) < 0) {862return NULL;863}864865/*866* Enumerate the addresses on each interface until we find a867* matching address.868*/869tableP = NULL;870if (lookupIPAddrTable(env, &tableP) >= 0) {871curr = ifList;872while (curr != NULL) {873int count;874netaddr *addrList;875netaddr *addrP;876877/* enumerate the addresses on this interface */878count = enumAddresses_win_ipaddrtable(env, curr, &addrList, tableP);879if (count < 0) {880free_netif(ifList);881free(tableP);882return NULL;883}884885/* iterate through each address */886addrP = addrList;887888while (addrP != NULL) {889if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) {890break;891}892addrP = addrP->next;893}894895/*896* Address matched so create NetworkInterface for this interface897* and address list.898*/899if (addrP != NULL) {900/* createNetworkInterface will free addrList */901netifObj = createNetworkInterface(env, curr, count, addrList);902break;903}904905/* on next interface */906curr = curr->next;907}908}909910/* release the IP address table */911if (tableP != NULL)912free(tableP);913914/* release the interface list */915free_netif(ifList);916917return netifObj;918}919920/*921* Class: java_net_NetworkInterface922* Method: getAll923* Signature: ()[Ljava/net/NetworkInterface;924*/925JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll926(JNIEnv *env, jclass cls)927{928int count;929netif *ifList = NULL, *curr;930jobjectArray netIFArr;931jint arr_index;932933// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack934if (ipv6_available()) {935return Java_java_net_NetworkInterface_getAll_XP (env, cls);936}937938/*939* Get list of interfaces940*/941count = enumInterfaces(env, &ifList);942if (count < 0) {943return NULL;944}945946/* allocate a NetworkInterface array */947netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);948if (netIFArr == NULL) {949free_netif(ifList);950return NULL;951}952953/*954* Iterate through the interfaces, create a NetworkInterface instance955* for each array element and populate the object.956*/957curr = ifList;958arr_index = 0;959while (curr != NULL) {960jobject netifObj;961962netifObj = createNetworkInterface(env, curr, -1, NULL);963if (netifObj == NULL) {964free_netif(ifList);965return NULL;966}967968/* put the NetworkInterface into the array */969(*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);970(*env)->DeleteLocalRef(env, netifObj);971972curr = curr->next;973}974975/* release the interface list */976free_netif(ifList);977978return netIFArr;979}980981/*982* Class: java_net_NetworkInterface983* Method: isUp0984* Signature: (Ljava/lang/String;)Z985*/986JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0987(JNIEnv *env, jclass cls, jstring name, jint index) {988jboolean ret = JNI_FALSE;989990// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack991if (ipv6_available()) {992return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index);993} else {994MIB_IFROW *ifRowP;995ifRowP = getIF(index);996if (ifRowP != NULL) {997ret = ifRowP->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP &&998(ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL ||999ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED);1000free(ifRowP);1001}1002}1003return ret;1004}10051006/*1007* Class: java_net_NetworkInterface1008* Method: isP2P01009* Signature: (Ljava/lang/String;I)Z1010*/1011JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P01012(JNIEnv *env, jclass cls, jstring name, jint index) {1013MIB_IFROW *ifRowP;1014jboolean ret = JNI_FALSE;10151016// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack1017if (ipv6_available()) {1018return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index);1019} else {1020ifRowP = getIF(index);1021if (ifRowP != NULL) {1022switch(ifRowP->dwType) {1023case MIB_IF_TYPE_PPP:1024case MIB_IF_TYPE_SLIP:1025ret = JNI_TRUE;1026break;1027}1028free(ifRowP);1029}1030}1031return ret;1032}10331034/*1035* Class: java_net_NetworkInterface1036* Method: isLoopback01037* Signature: (Ljava/lang/String;I)Z1038*/1039JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback01040(JNIEnv *env, jclass cls, jstring name, jint index) {1041MIB_IFROW *ifRowP;1042jboolean ret = JNI_FALSE;10431044// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack1045if (ipv6_available()) {1046return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index);1047} else {1048ifRowP = getIF(index);1049if (ifRowP != NULL) {1050if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK)1051ret = JNI_TRUE;1052free(ifRowP);1053}1054return ret;1055}1056}10571058/*1059* Class: java_net_NetworkInterface1060* Method: supportsMulticast01061* Signature: (Ljava/lang/String;I)Z1062*/1063JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast01064(JNIEnv *env, jclass cls, jstring name, jint index) {1065return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls,1066name, index);1067}10681069/*1070* Class: java_net_NetworkInterface1071* Method: getMacAddr01072* Signature: ([bLjava/lang/String;I)[b1073*/1074JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr01075(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {1076jbyteArray ret = NULL;1077int len;1078MIB_IFROW *ifRowP;10791080// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack1081if (ipv6_available()) {1082return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index);1083} else {1084ifRowP = getIF(index);1085if (ifRowP != NULL) {1086switch(ifRowP->dwType) {1087case MIB_IF_TYPE_ETHERNET:1088case MIB_IF_TYPE_TOKENRING:1089case MIB_IF_TYPE_FDDI:1090case IF_TYPE_IEEE80211:1091len = ifRowP->dwPhysAddrLen;1092if (len > 0) {1093ret = (*env)->NewByteArray(env, len);1094if (!IS_NULL(ret)) {1095(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);1096}1097}1098break;1099}1100free(ifRowP);1101}1102return ret;1103}1104}11051106/*1107* Class: java_net_NetworkInterface1108* Method: getMTU01109* Signature: ([bLjava/lang/String;I)I1110*/1111JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU01112(JNIEnv *env, jclass class, jstring name, jint index) {1113jint ret = -1;1114MIB_IFROW *ifRowP;11151116// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack1117if (ipv6_available()) {1118return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index);1119} else {1120ifRowP = getIF(index);1121if (ifRowP != NULL) {1122ret = ifRowP->dwMtu;1123free(ifRowP);1124}1125return ret;1126}1127}112811291130