Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/java/net/NetworkInterface.c
32287 views
/*1* Copyright (c) 2000, 2018, 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*/2425#include <stdlib.h>26#include <windows.h>27#include <winsock2.h> /* needed for htonl */28#include <iprtrmib.h>29#include <assert.h>3031#include "java_net_NetworkInterface.h"32#include "jni_util.h"3334#include "NetworkInterface.h"3536/*37* Windows implementation of the java.net.NetworkInterface native methods.38* This module provides the implementations of getAll, getByName, getByIndex,39* and getByAddress.40*41* Interfaces and addresses are enumerated using the IP helper routines42* GetIfTable, GetIfAddrTable resp. These routines are available on Windows43* 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if44* IE is upgraded to 5.x.45*46* Windows does not have any standard for device names so we are forced47* to use our own convention which is based on the normal Unix naming48* convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices,49* tr0, tr1, .. for token ring, and so on). This convention gives us50* consistency across multiple Windows editions and also consistency with51* Solaris/Linux device names. Note that we always enumerate in index52* order and this ensures consistent device number across invocations.53*/5455/* various JNI ids */5657jclass ni_class; /* NetworkInterface */5859jmethodID ni_ctor; /* NetworkInterface() */6061jfieldID ni_indexID; /* NetworkInterface.index */62jfieldID ni_addrsID; /* NetworkInterface.addrs */63jfieldID ni_bindsID; /* NetworkInterface.bindings */64jfieldID ni_nameID; /* NetworkInterface.name */65jfieldID ni_displayNameID; /* NetworkInterface.displayName */66jfieldID ni_childsID; /* NetworkInterface.childs */6768jclass ni_ibcls; /* InterfaceAddress */69jmethodID ni_ibctrID; /* InterfaceAddress() */70jfieldID ni_ibaddressID; /* InterfaceAddress.address */71jfieldID ni_ibbroadcastID; /* InterfaceAddress.broadcast */72jfieldID ni_ibmaskID; /* InterfaceAddress.maskLength */7374/*75* Support routines to free netif and netaddr lists76*/77void free_netif(netif *netifP) {78netif *curr = netifP;79while (curr != NULL) {80if (curr->name != NULL)81free(curr->name);82if (curr->displayName != NULL)83free(curr->displayName);84if (curr->addrs != NULL)85free_netaddr (curr->addrs);86netifP = netifP->next;87free(curr);88curr = netifP;89}90}9192void free_netaddr(netaddr *netaddrP) {93netaddr *curr = netaddrP;94while (curr != NULL) {95netaddrP = netaddrP->next;96free(curr);97curr = netaddrP;98}99}100101/*102* Returns the interface structure from the table with the matching index.103*/104MIB_IFROW *getIF(jint index) {105MIB_IFTABLE *tableP;106MIB_IFROW *ifrowP, *ret = NULL;107ULONG size;108DWORD i, count;109jint ifindex;110111/*112* Ask the IP Helper library to enumerate the adapters113*/114size = sizeof(MIB_IFTABLE);115tableP = (MIB_IFTABLE *)malloc(size);116if(tableP == NULL)117return NULL;118119count = GetIfTable(tableP, &size, TRUE);120if (count == ERROR_INSUFFICIENT_BUFFER || count == ERROR_BUFFER_OVERFLOW) {121MIB_IFTABLE* newTableP = (MIB_IFTABLE *)realloc(tableP, size);122if (newTableP == NULL) {123free(tableP);124return NULL;125}126tableP = newTableP;127128count = GetIfTable(tableP, &size, TRUE);129}130131if (count != NO_ERROR) {132free(tableP);133return NULL;134}135136{137ifrowP = tableP->table;138for (i=0; i<tableP->dwNumEntries; i++) {139/*140* Warning: the real index is obtained by GetFriendlyIfIndex()141*/142ifindex = GetFriendlyIfIndex(ifrowP->dwIndex);143if (ifindex == index) {144/*145* Create a copy of the entry so that we can free the table.146*/147ret = (MIB_IFROW *) malloc(sizeof(MIB_IFROW));148if (ret == NULL) {149free(tableP);150return NULL;151}152memcpy(ret, ifrowP, sizeof(MIB_IFROW));153break;154}155156/* onto the next interface */157ifrowP++;158}159free(tableP);160}161return ret;162}163164/*165* Enumerate network interfaces using IP Helper Library routine GetIfTable.166* We use GetIfTable rather than other IP helper routines because it's167* available on 98 & NT SP4+.168*169* Returns the number of interfaces found or -1 if error. If no error170* occurs then netifPP be returned as list of netif structures or NULL171* if no interfaces are found.172*/173int enumInterfaces(JNIEnv *env, netif **netifPP)174{175MIB_IFTABLE *tableP;176MIB_IFROW *ifrowP;177ULONG size;178DWORD ret;179int count;180netif *netifP;181DWORD i;182int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0, wlen=0;183184/*185* Ask the IP Helper library to enumerate the adapters186*/187size = sizeof(MIB_IFTABLE);188tableP = (MIB_IFTABLE *)malloc(size);189if (tableP == NULL) {190JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");191return -1;192}193194ret = GetIfTable(tableP, &size, TRUE);195if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {196MIB_IFTABLE * newTableP = (MIB_IFTABLE *)realloc(tableP, size);197if (newTableP == NULL) {198free(tableP);199JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");200return -1;201}202tableP = newTableP;203ret = GetIfTable(tableP, &size, TRUE);204}205206if (ret != NO_ERROR) {207free(tableP);208209JNU_ThrowByName(env, "java/lang/Error",210"IP Helper Library GetIfTable function failed");211212return -1;213}214215/*216* Iterate through the list of adapters217*/218count = 0;219netifP = NULL;220221ifrowP = tableP->table;222for (i=0; i<tableP->dwNumEntries; i++) {223char dev_name[8];224netif *curr;225226/*227* Generate a name for the device as Windows doesn't have any228* real concept of a device name.229*/230switch (ifrowP->dwType) {231case MIB_IF_TYPE_ETHERNET:232_snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++);233break;234235case MIB_IF_TYPE_TOKENRING:236_snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++);237break;238239case MIB_IF_TYPE_FDDI:240_snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++);241break;242243case MIB_IF_TYPE_LOOPBACK:244/* There should only be only IPv4 loopback address */245if (lo > 0) {246continue;247}248strncpy_s(dev_name, 8, "lo", _TRUNCATE);249lo++;250break;251252case MIB_IF_TYPE_PPP:253_snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++);254break;255256case MIB_IF_TYPE_SLIP:257_snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++);258break;259260case IF_TYPE_IEEE80211:261_snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++);262break;263264default:265_snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++);266}267268/*269* Allocate a netif structure and space for the name and270* display name (description in this case).271*/272curr = (netif *)calloc(1, sizeof(netif));273if (curr != NULL) {274wlen = MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,275ifrowP->dwDescrLen, NULL, 0);276if(wlen == 0) {277// MultiByteToWideChar should not fail278// But in rare case it fails, we allow 'char' to be displayed279curr->displayName = (char *)malloc(ifrowP->dwDescrLen + 1);280} else {281curr->displayName = (wchar_t *)malloc((wlen+1)*sizeof(wchar_t));282}283284curr->name = (char *)malloc(strlen(dev_name) + 1);285286if (curr->name == NULL || curr->displayName == NULL) {287if (curr->name) free(curr->name);288if (curr->displayName) free(curr->displayName);289free(curr);290curr = NULL;291}292}293if (curr == NULL) {294JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");295free_netif(netifP);296free(tableP);297return -1;298}299300/*301* Populate the interface. Note that we need to convert the302* index into its "friendly" value as otherwise we will expose303* 32-bit numbers as index values.304*/305strcpy(curr->name, dev_name);306if (wlen == 0) {307// display char type in case of MultiByteToWideChar failure308strncpy(curr->displayName, ifrowP->bDescr, ifrowP->dwDescrLen);309curr->displayName[ifrowP->dwDescrLen] = '\0';310} else {311// call MultiByteToWideChar again to fill curr->displayName312// it should not fail, because we have called it once before313if (MultiByteToWideChar(CP_OEMCP, 0, ifrowP->bDescr,314ifrowP->dwDescrLen, curr->displayName, wlen) == 0) {315JNU_ThrowByName(env, "java/lang/Error",316"Cannot get multibyte char for interface display name");317free_netif(netifP);318free(tableP);319free(curr->name);320free(curr->displayName);321free(curr);322return -1;323} else {324((wchar_t *)curr->displayName)[wlen] = L'\0';325curr->dNameIsUnicode = TRUE;326}327}328329curr->dwIndex = ifrowP->dwIndex;330curr->ifType = ifrowP->dwType;331curr->index = GetFriendlyIfIndex(ifrowP->dwIndex);332333/*334* Put the interface at tail of list as GetIfTable(,,TRUE) is335* returning the interfaces in index order.336*/337count++;338if (netifP == NULL) {339netifP = curr;340} else {341netif *tail = netifP;342while (tail->next != NULL) {343tail = tail->next;344}345tail->next = curr;346}347348/* onto the next interface */349ifrowP++;350}351352/*353* Free the interface table and return the interface list354*/355if (tableP) {356free(tableP);357}358*netifPP = netifP;359return count;360}361362/*363* Enumerate the IP addresses on an interface using the IP helper library364* routine GetIfAddrTable and matching based on the index name. There are365* more efficient routines but we use GetIfAddrTable because it's avaliable366* on 98 and NT.367*368* Returns the count of addresses, or -1 if error. If no error occurs then369* netaddrPP will return a list of netaddr structures with the IP addresses.370*/371int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)372{373MIB_IPADDRTABLE *tableP;374ULONG size;375DWORD ret;376DWORD i;377netaddr *netaddrP;378int count = 0;379unsigned long mask;380381/*382* Use GetIpAddrTable to enumerate the IP Addresses383*/384size = sizeof(MIB_IPADDRTABLE);385tableP = (MIB_IPADDRTABLE *)malloc(size);386if (tableP == NULL) {387JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");388return -1;389}390391ret = GetIpAddrTable(tableP, &size, FALSE);392if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) {393MIB_IPADDRTABLE * newTableP = (MIB_IPADDRTABLE *)realloc(tableP, size);394if (newTableP == NULL) {395free(tableP);396JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");397return -1;398}399tableP = newTableP;400401ret = GetIpAddrTable(tableP, &size, FALSE);402}403if (ret != NO_ERROR) {404if (tableP) {405free(tableP);406}407JNU_ThrowByName(env, "java/lang/Error",408"IP Helper Library GetIpAddrTable function failed");409return -1;410}411412/*413* Iterate through the table to find the addresses with the414* matching dwIndex. Ignore 0.0.0.0 addresses.415*/416count = 0;417netaddrP = NULL;418419i = 0;420while (i<tableP->dwNumEntries) {421if (tableP->table[i].dwIndex == netifP->dwIndex &&422tableP->table[i].dwAddr != 0) {423424netaddr *curr = (netaddr *)malloc(sizeof(netaddr));425if (curr == NULL) {426JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure");427free_netaddr(netaddrP);428free(tableP);429return -1;430}431432curr->addr.him4.sin_family = AF_INET;433curr->addr.him4.sin_addr.s_addr = tableP->table[i].dwAddr;434/*435* Get netmask / broadcast address436*/437switch (netifP->ifType) {438case MIB_IF_TYPE_ETHERNET:439case MIB_IF_TYPE_TOKENRING:440case MIB_IF_TYPE_FDDI:441case MIB_IF_TYPE_LOOPBACK:442case IF_TYPE_IEEE80211:443/**444* Contrary to what it seems to indicate, dwBCastAddr doesn't445* contain the broadcast address but 0 or 1 depending on whether446* the broadcast address should set the bits of the host part447* to 0 or 1.448* Yes, I know it's stupid, but what can I say, it's MSFTs API.449*/450curr->brdcast.him4.sin_family = AF_INET;451if (tableP->table[i].dwBCastAddr == 1)452curr->brdcast.him4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask);453else454curr->brdcast.him4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask);455mask = ntohl(tableP->table[i].dwMask);456curr->mask = 0;457while (mask) {458mask <<= 1;459curr->mask++;460}461break;462case MIB_IF_TYPE_PPP:463case MIB_IF_TYPE_SLIP:464default:465/**466* these don't have broadcast/subnet467*/468curr->mask = -1;469break;470}471472curr->next = netaddrP;473netaddrP = curr;474count++;475}476i++;477}478479*netaddrPP = netaddrP;480free(tableP);481return count;482}483484/*485* Class: java_net_NetworkInterface486* Method: init487* Signature: ()V488*/489JNIEXPORT void JNICALL490Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls)491{492/*493* Get the various JNI ids that we require494*/495ni_class = (*env)->NewGlobalRef(env, cls);496CHECK_NULL(ni_class);497ni_nameID = (*env)->GetFieldID(env, ni_class, "name", "Ljava/lang/String;");498CHECK_NULL(ni_nameID);499ni_displayNameID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");500CHECK_NULL(ni_displayNameID);501ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");502CHECK_NULL(ni_indexID);503ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");504CHECK_NULL(ni_addrsID);505ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");506CHECK_NULL(ni_bindsID);507ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");508CHECK_NULL(ni_childsID);509ni_ctor = (*env)->GetMethodID(env, ni_class, "<init>", "()V");510CHECK_NULL(ni_ctor);511ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");512CHECK_NULL(ni_ibcls);513ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);514CHECK_NULL(ni_ibcls);515ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");516CHECK_NULL(ni_ibctrID);517ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");518CHECK_NULL(ni_ibaddressID);519ni_ibbroadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");520CHECK_NULL(ni_ibbroadcastID);521ni_ibmaskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");522CHECK_NULL(ni_ibmaskID);523524initInetAddressIDs(env);525}526527/*528* Create a NetworkInterface object, populate the name and index, and529* populate the InetAddress array based on the IP addresses for this530* interface.531*/532jobject createNetworkInterface533(JNIEnv *env, netif *ifs, int netaddrCount, netaddr *netaddrP)534{535jobject netifObj;536jobject name, displayName;537jobjectArray addrArr, bindsArr, childArr;538netaddr *addrs;539jint addr_index;540jint bind_index;541542/*543* Create a NetworkInterface object and populate it544*/545netifObj = (*env)->NewObject(env, ni_class, ni_ctor);546CHECK_NULL_RETURN(netifObj, NULL);547name = (*env)->NewStringUTF(env, ifs->name);548CHECK_NULL_RETURN(name, NULL);549if (ifs->dNameIsUnicode) {550displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,551(jsize)wcslen ((PWCHAR)ifs->displayName));552} else {553displayName = (*env)->NewStringUTF(env, ifs->displayName);554}555CHECK_NULL_RETURN(displayName, NULL);556(*env)->SetObjectField(env, netifObj, ni_nameID, name);557(*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);558(*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);559560/*561* Get the IP addresses for this interface if necessary562* Note that 0 is a valid number of addresses.563*/564if (netaddrCount < 0) {565netaddrCount = enumAddresses_win(env, ifs, &netaddrP);566if (netaddrCount == -1) {567return NULL;568}569}570addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);571if (addrArr == NULL) {572free_netaddr(netaddrP);573return NULL;574}575576bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);577if (bindsArr == NULL) {578free_netaddr(netaddrP);579return NULL;580}581addrs = netaddrP;582addr_index = 0;583bind_index = 0;584while (addrs != NULL) {585jobject iaObj, ia2Obj;586jobject ibObj = NULL;587if (addrs->addr.him.sa_family == AF_INET) {588iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);589if (iaObj == NULL) {590free_netaddr(netaddrP);591return NULL;592}593/* default ctor will set family to AF_INET */594595setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));596if ((*env)->ExceptionCheck(env)) {597free_netaddr(netaddrP);598return NULL;599}600if (addrs->mask != -1) {601ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);602if (ibObj == NULL) {603free_netaddr(netaddrP);604return NULL;605}606(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);607ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);608if (ia2Obj == NULL) {609free_netaddr(netaddrP);610return NULL;611}612setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));613if ((*env)->ExceptionCheck(env)) {614free_netaddr(netaddrP);615return NULL;616}617(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);618(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);619(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);620}621} else /* AF_INET6 */ {622int scope;623iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);624if (iaObj) {625int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));626if (ret == JNI_FALSE) {627free_netaddr(netaddrP);628return NULL;629}630631scope = addrs->addr.him6.sin6_scope_id;632if (scope != 0) { /* zero is default value, no need to set */633setInet6Address_scopeid(env, iaObj, scope);634setInet6Address_scopeifname(env, iaObj, netifObj);635}636ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);637if (ibObj == NULL) {638free_netaddr(netaddrP);639return NULL;640}641(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);642(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);643(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);644}645}646(*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);647addrs = addrs->next;648addr_index++;649}650(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);651(*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);652653free_netaddr(netaddrP);654655/*656* Windows doesn't have virtual interfaces, so child array657* is always empty.658*/659childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);660if (childArr == NULL) {661return NULL;662}663(*env)->SetObjectField(env, netifObj, ni_childsID, childArr);664665/* return the NetworkInterface */666return netifObj;667}668669/*670* Class: java_net_NetworkInterface671* Method: getByName0672* Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;673*/674JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0675(JNIEnv *env, jclass cls, jstring name)676{677netif *ifList, *curr;678jboolean isCopy;679const char *name_utf;680jobject netifObj = NULL;681682// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack683if (ipv6_available()) {684return Java_java_net_NetworkInterface_getByName0_XP (env, cls, name);685}686687/* get the list of interfaces */688if (enumInterfaces(env, &ifList) < 0) {689return NULL;690}691692/* get the name as a C string */693name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);694if (name_utf != NULL) {695696/* Search by name */697curr = ifList;698while (curr != NULL) {699if (strcmp(name_utf, curr->name) == 0) {700break;701}702curr = curr->next;703}704705/* if found create a NetworkInterface */706if (curr != NULL) {;707netifObj = createNetworkInterface(env, curr, -1, NULL);708}709710/* release the UTF string */711(*env)->ReleaseStringUTFChars(env, name, name_utf);712} else {713if (!(*env)->ExceptionCheck(env))714JNU_ThrowOutOfMemoryError(env, NULL);715}716717/* release the interface list */718free_netif(ifList);719720return netifObj;721}722723/*724* Class: NetworkInterface725* Method: getByIndex0726* Signature: (I)LNetworkInterface;727*/728JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0729(JNIEnv *env, jclass cls, jint index)730{731netif *ifList, *curr;732jobject netifObj = NULL;733734// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack735if (ipv6_available()) {736return Java_java_net_NetworkInterface_getByIndex0_XP (env, cls, index);737}738739/* get the list of interfaces */740if (enumInterfaces(env, &ifList) < 0) {741return NULL;742}743744/* search by index */745curr = ifList;746while (curr != NULL) {747if (index == curr->index) {748break;749}750curr = curr->next;751}752753/* if found create a NetworkInterface */754if (curr != NULL) {755netifObj = createNetworkInterface(env, curr, -1, NULL);756}757758/* release the interface list */759free_netif(ifList);760761return netifObj;762}763764/*765* Class: java_net_NetworkInterface766* Method: getByInetAddress0767* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;768*/769JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0770(JNIEnv *env, jclass cls, jobject iaObj)771{772netif *ifList, *curr;773jobject netifObj = NULL;774jint addr = getInetAddress_addr(env, iaObj);775JNU_CHECK_EXCEPTION_RETURN(env, NULL);776777// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack778if (ipv6_available()) {779return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);780}781782/* get the list of interfaces */783if (enumInterfaces(env, &ifList) < 0) {784return NULL;785}786787/*788* Enumerate the addresses on each interface until we find a789* matching address.790*/791curr = ifList;792while (curr != NULL) {793int count;794netaddr *addrList;795netaddr *addrP;796797/* enumerate the addresses on this interface */798count = enumAddresses_win(env, curr, &addrList);799if (count < 0) {800free_netif(ifList);801return NULL;802}803804/* iterate through each address */805addrP = addrList;806807while (addrP != NULL) {808if ((unsigned long)addr == ntohl(addrP->addr.him4.sin_addr.s_addr)) {809break;810}811addrP = addrP->next;812}813814/*815* Address matched so create NetworkInterface for this interface816* and address list.817*/818if (addrP != NULL) {819/* createNetworkInterface will free addrList */820netifObj = createNetworkInterface(env, curr, count, addrList);821break;822}823824/* on next interface */825curr = curr->next;826}827828/* release the interface list */829free_netif(ifList);830831return netifObj;832}833834/*835* Class: java_net_NetworkInterface836* Method: getAll837* Signature: ()[Ljava/net/NetworkInterface;838*/839JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll840(JNIEnv *env, jclass cls)841{842int count;843netif *ifList, *curr;844jobjectArray netIFArr;845jint arr_index;846847// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack848if (ipv6_available()) {849return Java_java_net_NetworkInterface_getAll_XP (env, cls);850}851852/*853* Get list of interfaces854*/855count = enumInterfaces(env, &ifList);856if (count < 0) {857return NULL;858}859860/* allocate a NetworkInterface array */861netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);862if (netIFArr == NULL) {863free_netif(ifList);864return NULL;865}866867/*868* Iterate through the interfaces, create a NetworkInterface instance869* for each array element and populate the object.870*/871curr = ifList;872arr_index = 0;873while (curr != NULL) {874jobject netifObj;875876netifObj = createNetworkInterface(env, curr, -1, NULL);877if (netifObj == NULL) {878free_netif(ifList);879return NULL;880}881882/* put the NetworkInterface into the array */883(*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);884885curr = curr->next;886}887888/* release the interface list */889free_netif(ifList);890891return netIFArr;892}893894/*895* Class: java_net_NetworkInterface896* Method: isUp0897* Signature: (Ljava/lang/String;)Z898*/899JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0900(JNIEnv *env, jclass cls, jstring name, jint index) {901jboolean ret = JNI_FALSE;902903// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack904if (ipv6_available()) {905return Java_java_net_NetworkInterface_isUp0_XP(env, cls, name, index);906} else {907MIB_IFROW *ifRowP;908ifRowP = getIF(index);909if (ifRowP != NULL) {910ret = ifRowP->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP &&911(ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL ||912ifRowP->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED);913free(ifRowP);914}915}916return ret;917}918919/*920* Class: java_net_NetworkInterface921* Method: isP2P0922* Signature: (Ljava/lang/String;I)Z923*/924JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0925(JNIEnv *env, jclass cls, jstring name, jint index) {926MIB_IFROW *ifRowP;927jboolean ret = JNI_FALSE;928929// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack930if (ipv6_available()) {931return Java_java_net_NetworkInterface_isP2P0_XP(env, cls, name, index);932} else {933ifRowP = getIF(index);934if (ifRowP != NULL) {935switch(ifRowP->dwType) {936case MIB_IF_TYPE_PPP:937case MIB_IF_TYPE_SLIP:938ret = JNI_TRUE;939break;940}941free(ifRowP);942}943}944return ret;945}946947/*948* Class: java_net_NetworkInterface949* Method: isLoopback0950* Signature: (Ljava/lang/String;I)Z951*/952JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0953(JNIEnv *env, jclass cls, jstring name, jint index) {954MIB_IFROW *ifRowP;955jboolean ret = JNI_FALSE;956957// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack958if (ipv6_available()) {959return Java_java_net_NetworkInterface_isLoopback0_XP(env, cls, name, index);960} else {961ifRowP = getIF(index);962if (ifRowP != NULL) {963if (ifRowP->dwType == MIB_IF_TYPE_LOOPBACK)964ret = JNI_TRUE;965free(ifRowP);966}967return ret;968}969}970971/*972* Class: java_net_NetworkInterface973* Method: supportsMulticast0974* Signature: (Ljava/lang/String;I)Z975*/976JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0977(JNIEnv *env, jclass cls, jstring name, jint index) {978return Java_java_net_NetworkInterface_supportsMulticast0_XP(env, cls,979name, index);980}981982/*983* Class: java_net_NetworkInterface984* Method: getMacAddr0985* Signature: ([bLjava/lang/String;I)[b986*/987JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0988(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {989jbyteArray ret = NULL;990int len;991MIB_IFROW *ifRowP;992993// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack994if (ipv6_available()) {995return Java_java_net_NetworkInterface_getMacAddr0_XP(env, class, name, index);996} else {997ifRowP = getIF(index);998if (ifRowP != NULL) {999switch(ifRowP->dwType) {1000case MIB_IF_TYPE_ETHERNET:1001case MIB_IF_TYPE_TOKENRING:1002case MIB_IF_TYPE_FDDI:1003case IF_TYPE_IEEE80211:1004len = ifRowP->dwPhysAddrLen;1005if (len > 0) {1006ret = (*env)->NewByteArray(env, len);1007if (!IS_NULL(ret)) {1008(*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr);1009}1010}1011break;1012}1013free(ifRowP);1014}1015return ret;1016}1017}10181019/*1020* Class: java_net_NetworkInterface1021* Method: getMTU01022* Signature: ([bLjava/lang/String;I)I1023*/1024JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU01025(JNIEnv *env, jclass class, jstring name, jint index) {1026jint ret = -1;1027MIB_IFROW *ifRowP;10281029// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack1030if (ipv6_available()) {1031return Java_java_net_NetworkInterface_getMTU0_XP(env, class, name, index);1032} else {1033ifRowP = getIF(index);1034if (ifRowP != NULL) {1035ret = ifRowP->dwMtu;1036free(ifRowP);1037}1038return ret;1039}1040}104110421043