Path: blob/master/src/java.base/windows/native/libnet/NetworkInterface_winXP.c
41119 views
/*1* Copyright (c) 2003, 2020, 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_NetworkInterface.h"2829/*30* Windows implementation of the java.net.NetworkInterface native methods.31* This module provides the implementations of getAll, getByName, getByIndex,32* and getByAddress.33*/3435extern int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP);36extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);37extern int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP);38int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);3940#ifdef DEBUG41void printnif (netif *nif) {42#ifdef _WIN6443printf ("nif:0x%I64x name:%s\n", (UINT_PTR)nif, nif->name);44#else45printf ("nif:0x%x name:%s\n", (UINT_PTR)nif, nif->name);46#endif47if (nif->dNameIsUnicode) {48printf ("dName:%S index:%d ", (unsigned short *)nif->displayName,49nif->index);50} else {51printf ("dName:%s index:%d ", nif->displayName, nif->index);52}53printf ("naddrs:%d\n", nif->naddrs);54}5556void printnifs (netif *netifPP, char *str) {57netif *nif;58printf ("%s\n", str);59for (nif=netifPP; nif!=NULL; nif=nif->next) {60printnif (nif);61}62printf("-----------------\n");63}6465#endif6667const ULONG BUFF_SIZE = 15360;68const int MAX_TRIES = 3;6970/*71* return an array of IP_ADAPTER_ADDRESSES containing one element72* for each adapter on the system. Returned in *adapters.73* Buffer is malloc'd and must be freed (unless error returned)74*/75int getAdapters (JNIEnv *env, int flags, IP_ADAPTER_ADDRESSES **adapters) {76DWORD ret;77IP_ADAPTER_ADDRESSES *adapterInfo;78ULONG len;79int try;8081adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);82if (adapterInfo == NULL) {83JNU_ThrowByName(env, "java/lang/OutOfMemoryError",84"Native heap allocation failure");85return -1;86}8788len = BUFF_SIZE;89ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);9091for (try = 0; ret == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {92IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;93if (len < (ULONG_MAX - BUFF_SIZE)) {94len += BUFF_SIZE;95}96newAdapterInfo =97(IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);98if (newAdapterInfo == NULL) {99free(adapterInfo);100JNU_ThrowByName(env, "java/lang/OutOfMemoryError",101"Native heap allocation failure");102return -1;103}104105adapterInfo = newAdapterInfo;106107ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);108}109110if (ret != ERROR_SUCCESS) {111free (adapterInfo);112if (ret == ERROR_INSUFFICIENT_BUFFER) {113JNU_ThrowByName(env, "java/lang/Error",114"IP Helper Library GetAdaptersAddresses function failed "115"with ERROR_INSUFFICIENT_BUFFER");116} else if (ret == ERROR_ADDRESS_NOT_ASSOCIATED ) {117JNU_ThrowByName(env, "java/lang/Error",118"IP Helper Library GetAdaptersAddresses function failed "119"with ERROR_ADDRESS_NOT_ASSOCIATED");120} else {121char error_msg_buf[100];122int _sr;123_sr = _snprintf_s(error_msg_buf, sizeof(error_msg_buf),124_TRUNCATE, "IP Helper Library GetAdaptersAddresses "125"function failed with error == %d", ret);126if (_sr != -1) {127JNU_ThrowByName(env, "java/lang/Error", error_msg_buf);128} else {129JNU_ThrowByName(env, "java/lang/Error",130"IP Helper Library GetAdaptersAddresses function failure");131}132}133return -1;134}135*adapters = adapterInfo;136return ERROR_SUCCESS;137}138139/*140* return an array of IP_ADAPTER_ADDRESSES containing one element141* for each adapter on the system. Returned in *adapters.142* Buffer is malloc'd and must be freed (unless error returned)143*/144IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {145DWORD flags, val;146IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret;147ULONG len;148int try;149adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);150if (adapterInfo == NULL) {151JNU_ThrowByName(env, "java/lang/OutOfMemoryError",152"Native heap allocation failure");153return NULL;154}155len = BUFF_SIZE;156flags = GAA_FLAG_SKIP_DNS_SERVER;157flags |= GAA_FLAG_SKIP_MULTICAST;158flags |= GAA_FLAG_INCLUDE_PREFIX;159val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);160for (try = 0; val == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {161IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;162if (len < (ULONG_MAX - BUFF_SIZE)) {163len += BUFF_SIZE;164}165newAdapterInfo =166(IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);167if (newAdapterInfo == NULL) {168free(adapterInfo);169JNU_ThrowByName(env, "java/lang/OutOfMemoryError",170"Native heap allocation failure");171return NULL;172}173174adapterInfo = newAdapterInfo;175176val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);177}178179if (val != ERROR_SUCCESS) {180free (adapterInfo);181if (val == ERROR_INSUFFICIENT_BUFFER) {182JNU_ThrowByName(env, "java/lang/Error",183"IP Helper Library GetAdaptersAddresses function failed "184"with ERROR_INSUFFICIENT_BUFFER");185} else if (val == ERROR_ADDRESS_NOT_ASSOCIATED ) {186JNU_ThrowByName(env, "java/lang/Error",187"IP Helper Library GetAdaptersAddresses function failed "188"with ERROR_ADDRESS_NOT_ASSOCIATED");189} else {190char error_msg_buf[100];191int _sr;192_sr = _snprintf_s(error_msg_buf, sizeof(error_msg_buf),193_TRUNCATE, "IP Helper Library GetAdaptersAddresses function failed "194"with error == %d", val);195if (_sr != -1) {196JNU_ThrowByName(env, "java/lang/Error", error_msg_buf);197} else {198JNU_ThrowByName(env, "java/lang/Error",199"IP Helper Library GetAdaptersAddresses function failure");200}201}202return NULL;203}204205ptr = adapterInfo;206ret = NULL;207while (ptr != NULL) {208// in theory the IPv4 index and the IPv6 index can be the same209// where an interface is enabled for v4 and v6210// IfIndex == 0 IPv4 not available on this interface211// Ipv6IfIndex == 0 IPv6 not available on this interface212if (((ptr->IfIndex != 0)&&(ptr->IfIndex == index)) ||213((ptr->Ipv6IfIndex !=0) && (ptr->Ipv6IfIndex == index))) {214ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES));215if (ret == NULL) {216free(adapterInfo);217JNU_ThrowByName(env, "java/lang/OutOfMemoryError",218"Native heap allocation failure");219return NULL;220}221222//copy the memory and break out of the while loop.223memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES));224break;225226}227ptr=ptr->Next;228}229free(adapterInfo);230return ret;231}232233static int ipinflen = 2048;234235/*236*/237int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)238{239DWORD ret, flags;240MIB_IPADDRTABLE *tableP;241IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;242ULONG len=ipinflen, count=0;243netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;244int tun=0, net=0;245246*netifPP = NULL;247/*248* Get the IPv4 interfaces. This information is the same249* as what previous JDK versions would return.250*/251252ret = enumInterfaces(env, netifPP);253if (ret == -1) {254return -1;255} else if( ret == -2){256if ((*env)->ExceptionCheck(env)) {257(*env)->ExceptionClear(env);258}259} else {260count = ret;261}262263/* locate the loopback (and the last) interface */264for (nif=*netifPP, last=nif; nif!=NULL; nif=nif->next) {265if (nif->ifType == MIB_IF_TYPE_LOOPBACK) {266loopif = nif;267}268last = nif;269}270271// Retrieve IPv4 addresses with the IP Helper API272curr = *netifPP;273ret = lookupIPAddrTable(env, &tableP);274if (ret < 0) {275return -1;276}277while (curr != NULL) {278netaddr *netaddrP;279ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP);280if (ret == -1) {281free(tableP);282return -1;283} else if (ret == -2) {284if ((*env)->ExceptionCheck(env)) {285(*env)->ExceptionClear(env);286}287break;288} else{289curr->addrs = netaddrP;290curr->naddrs += ret;291curr = curr->next;292}293}294free(tableP);295296flags = GAA_FLAG_SKIP_DNS_SERVER;297flags |= GAA_FLAG_SKIP_MULTICAST;298flags |= GAA_FLAG_INCLUDE_PREFIX;299ret = getAdapters (env, flags, &adapters);300if (ret != ERROR_SUCCESS) {301goto err;302}303304/* Now get the IPv6 information. This includes:305* (a) IPv6 information associated with interfaces already found306* (b) IPv6 information for IPv6 only interfaces (probably tunnels)307*308* For compatibility with previous releases we use the naming309* information gotten from enumInterfaces() for (a) entries310* However, the index numbers are taken from the new API.311*312* The procedure is to go through the list of adapters returned313* by the new API looking for entries that correspond to IPv4 interfaces314* already found.315*/316317ptr = adapters;318while (ptr != NULL) {319int c;320netif *nif0;321if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) {322c = getAddrsFromAdapter(ptr, &loopif->addrs);323if (c == -1) {324goto err;325}326loopif->naddrs += c;327loopif->ipv6Index = ptr->Ipv6IfIndex;328} else {329int index = ptr->IfIndex;330if (index != 0) {331/* This entry is associated with an IPv4 interface */332for (nif=*netifPP; nif!=NULL; nif=nif->next) {333if (nif->index == index) {334/* found the interface entry335* set the index to the IPv6 index and add the336* IPv6 addresses337*/338nif->ipv6Index = ptr->Ipv6IfIndex;339c = getAddrsFromAdapter(ptr, &nif->addrs);340nif->naddrs += c;341break;342}343}344} else {345/* This entry is IPv6 only */346char newname [128];347int c;348349/* Windows allocates duplicate adapter entries350* for tunnel interfaces when there are multiple351* physical adapters. Need to check352* if this is a duplicate (ipv6Index is the same)353*/354dup_nif = 0;355for (nif0=*netifPP; nif0!=NULL; nif0=nif0->next) {356if (nif0->hasIpv6Address &&357ptr->Ipv6IfIndex == nif0->ipv6Index) {358dup_nif = nif0;359break;360}361}362if (dup_nif == 0) {363/* new interface */364nif = (netif *) calloc (1, sizeof(netif));365if (nif == 0) {366goto err;367}368if (ptr->IfType == IF_TYPE_TUNNEL) {369sprintf (newname, "tun%d", tun);370tun ++;371} else {372sprintf (newname, "net%d", net);373net ++;374}375nif->name = malloc (strlen(newname)+1);376nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2);377if (nif->name == 0 || nif->displayName == 0) {378goto err;379}380strcpy (nif->name, newname);381wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName);382nif->dNameIsUnicode = TRUE;383384// the java.net.NetworkInterface abstraction only has index385// so the Ipv6IfIndex needs to map onto index386nif->index = ptr->Ipv6IfIndex;387nif->ipv6Index = ptr->Ipv6IfIndex;388nif->hasIpv6Address = TRUE;389390last->next = nif;391last = nif;392count++;393c = getAddrsFromAdapter(ptr, &nif->addrs);394if (c == -1) {395goto err;396}397nif->naddrs += c;398} else {399/* add the addresses from this adapter to the400* original (dup_nif)401*/402c = getAddrsFromAdapter(ptr, &dup_nif->addrs);403if (c == -1) {404goto err;405}406dup_nif->naddrs += c;407}408}409}410ptr=ptr->Next;411}412413free (adapters);414return count;415416err:417if (*netifPP) {418free_netif (*netifPP);419}420if (adapters) {421free (adapters);422}423return -1;424}425426/* If *netaddrPP is null, then the addresses are allocated and the beginning427* of the allocated chain is returned in *netaddrPP.428* If *netaddrPP is not null, then the addresses allocated here are appended429* to the existing chain.430*431* Returns count of addresses or -1 on error.432*/433434static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) {435LPSOCKADDR sock;436int count = 0;437netaddr *curr, *start = NULL, *prev = NULL;438PIP_ADAPTER_UNICAST_ADDRESS uni_addr;439PIP_ADAPTER_ANYCAST_ADDRESS any_addr;440PIP_ADAPTER_PREFIX prefix;441442/* If chain passed in, find end */443if (*netaddrPP != NULL) {444for (start=*netaddrPP; start->next!=NULL; start=start->next)445;446447prev=start;448}449450prefix = ptr->FirstPrefix;451/* Unicast */452uni_addr = ptr->FirstUnicastAddress;453while (uni_addr != NULL) {454/* address is only usable if dad state is preferred or deprecated */455if (uni_addr->DadState == IpDadStateDeprecated ||456uni_addr->DadState == IpDadStatePreferred) {457sock = uni_addr->Address.lpSockaddr;458459// IPv4 addresses already retrieved with enumAddresses_win460if (sock->sa_family == AF_INET) {461uni_addr = uni_addr->Next;462continue;463}464465curr = (netaddr *)calloc (1, sizeof (netaddr));466467if (curr == NULL)468goto freeAllocatedMemory;469470if (start == NULL)471start = curr;472473if (prev != NULL)474prev->next = curr;475476prev = curr;477SOCKETADDRESS_COPY (&curr->addr, sock);478if (prefix != NULL) {479curr->mask = (short)prefix->PrefixLength;480prefix = prefix->Next;481}482count ++;483}484uni_addr = uni_addr->Next;485}486/* Anycast */487any_addr = ptr->FirstAnycastAddress;488while (any_addr != NULL) {489curr = (netaddr *)calloc (1, sizeof (netaddr));490491if (curr == NULL)492goto freeAllocatedMemory;493494if (start == NULL)495start = curr;496497if (prev != NULL)498prev->next = curr;499500prev = curr;501sock = any_addr->Address.lpSockaddr;502SOCKETADDRESS_COPY (&curr->addr, sock);503count ++;504any_addr = any_addr->Next;505}506if (*netaddrPP == NULL) {507*netaddrPP = start;508}509return count;510511freeAllocatedMemory:512513if (*netaddrPP != NULL) {514//N.B. the variable "start" cannot be NULL at this point because we started with an515//existing list.516curr=start->next;517start->next = NULL;518start = curr;519}520// otherwise, "start" points to the beginning of an incomplete list that we must deallocate.521522while (start != NULL) {523curr = start->next;524free(start);525start = curr;526}527528return -1;529}530531/*532* Create a NetworkInterface object, populate the name and index, and533* populate the InetAddress array based on the IP addresses for this534* interface.535*/536static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)537{538jobject netifObj;539jobject name, displayName;540jobjectArray addrArr, bindsArr, childArr;541netaddr *addrs;542jint addr_index;543int netaddrCount = ifs->naddrs;544netaddr *netaddrP = ifs->addrs;545netaddr *netaddrPToFree = NULL;546jint bind_index;547548/*549* Create a NetworkInterface object and populate it550*/551netifObj = (*env)->NewObject(env, ni_class, ni_ctor);552if (netifObj == NULL) {553return NULL;554}555name = (*env)->NewStringUTF(env, ifs->name);556if (name == NULL) {557return NULL;558}559if (ifs->dNameIsUnicode) {560displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,561(jsize)wcslen ((PWCHAR)ifs->displayName));562} else {563displayName = (*env)->NewStringUTF(env, ifs->displayName);564}565if (displayName == NULL) {566return NULL;567}568(*env)->SetObjectField(env, netifObj, ni_nameID, name);569(*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);570(*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);571/*572* Get the IP addresses for this interface if necessary573* Note that 0 is a valid number of addresses.574*/575if (netaddrCount < 0) {576netaddrCount = enumAddresses_win(env, ifs, &netaddrPToFree);577if (netaddrCount == -1) {578return NULL;579}580if (netaddrCount == -2) {581// Clear the exception and continue.582if ((*env)->ExceptionCheck(env)) {583(*env)->ExceptionClear(env);584}585}586netaddrP = netaddrPToFree;587}588589addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);590if (addrArr == NULL) {591free_netaddr(netaddrPToFree);592return NULL;593}594595bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);596if (bindsArr == NULL) {597free_netaddr(netaddrPToFree);598return NULL;599}600601addrs = netaddrP;602addr_index = 0;603bind_index = 0;604while (addrs != NULL) {605jobject iaObj, ia2Obj;606jobject ibObj = NULL;607if (addrs->addr.sa.sa_family == AF_INET) {608iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);609if (iaObj == NULL) {610free_netaddr(netaddrPToFree);611return NULL;612}613/* default ctor will set family to AF_INET */614615setInetAddress_addr(env, iaObj, ntohl(addrs->addr.sa4.sin_addr.s_addr));616if ((*env)->ExceptionCheck(env)) {617free_netaddr(netaddrPToFree);618return NULL;619}620ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);621if (ibObj == NULL) {622free_netaddr(netaddrPToFree);623return NULL;624}625(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);626ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);627if (ia2Obj == NULL) {628free_netaddr(netaddrPToFree);629return NULL;630}631setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.sa4.sin_addr.s_addr));632if ((*env)->ExceptionCheck(env)) {633free_netaddr(netaddrPToFree);634return NULL;635}636(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);637(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);638(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);639} else /* AF_INET6 */ {640int scope;641jboolean ret;642iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);643if (iaObj == NULL) {644free_netaddr(netaddrPToFree);645return NULL;646}647ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));648if (ret == JNI_FALSE) {649free_netaddr(netaddrPToFree);650return NULL;651}652scope = addrs->addr.sa6.sin6_scope_id;653if (scope != 0) { /* zero is default value, no need to set */654setInet6Address_scopeid(env, iaObj, scope);655setInet6Address_scopeifname(env, iaObj, netifObj);656}657ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);658if (ibObj == NULL) {659free_netaddr(netaddrPToFree);660return NULL;661}662(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);663(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);664(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);665}666(*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);667addrs = addrs->next;668addr_index++;669}670(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);671(*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);672673free_netaddr(netaddrPToFree);674675/*676* Windows doesn't have virtual interfaces, so child array677* is always empty.678*/679childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);680if (childArr == NULL) {681return NULL;682}683(*env)->SetObjectField(env, netifObj, ni_childsID, childArr);684685/* return the NetworkInterface */686return netifObj;687}688689JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP690(JNIEnv *env, jclass cls, jstring name)691{692netif *ifList, *curr;693jboolean isCopy;694const char *name_utf;695jobject netifObj = NULL;696697if (getAllInterfacesAndAddresses (env, &ifList) < 0) {698return NULL;699}700701/* get the name as a C string */702name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);703704/* Search by name */705curr = ifList;706while (curr != NULL) {707if (strcmp(name_utf, curr->name) == 0) {708break;709}710curr = curr->next;711}712713/* if found create a NetworkInterface */714if (curr != NULL) {715netifObj = createNetworkInterfaceXP(env, curr);716}717718/* release the UTF string */719(*env)->ReleaseStringUTFChars(env, name, name_utf);720721/* release the interface list */722free_netif(ifList);723724return netifObj;725}726727/*728* Class: NetworkInterface729* Method: getByIndex0_XP730* Signature: (I)LNetworkInterface;731*/732JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0_XP733(JNIEnv *env, jclass cls, jint index)734{735netif *ifList, *curr;736jobject netifObj = NULL;737738if (getAllInterfacesAndAddresses (env, &ifList) < 0) {739return NULL;740}741742/* search by index */743curr = ifList;744while (curr != NULL) {745if (index == curr->index) {746break;747}748curr = curr->next;749}750751/* if found create a NetworkInterface */752if (curr != NULL) {753netifObj = createNetworkInterfaceXP(env, curr);754}755756/* release the interface list */757free_netif(ifList);758759return netifObj;760}761762/*763* Class: java_net_NetworkInterface764* Method: getByInetAddress0765* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;766*/767JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP768(JNIEnv *env, jclass cls, jobject iaObj)769{770netif *ifList, *curr;771jobject netifObj = NULL;772773/* get the list of interfaces */774if (getAllInterfacesAndAddresses (env, &ifList) < 0) {775return NULL;776}777778/*779* Enumerate the addresses on each interface until we find a780* matching address.781*/782curr = ifList;783while (curr != NULL) {784netaddr *addrList = curr->addrs;785netaddr *addrP;786787/* iterate through each address */788addrP = addrList;789790while (addrP != NULL) {791if (NET_SockaddrEqualsInetAddress(env,792(struct sockaddr*)&addrP->addr, iaObj)) {793break;794}795addrP = addrP->next;796}797798/*799* Address matched so create NetworkInterface for this interface800* and address list.801*/802if (addrP != NULL) {803netifObj = createNetworkInterfaceXP(env, curr);804break;805}806807/* on next interface */808curr = curr->next;809}810811/* release the interface list */812free_netif(ifList);813814return netifObj;815}816817/*818* Class: java_net_NetworkInterface819* Method: getAll820* Signature: ()[Ljava/net/NetworkInterface;821*/822JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP823(JNIEnv *env, jclass cls)824{825int count;826netif *ifList = NULL, *curr;827jobjectArray netIFArr;828jint arr_index;829830/*831* Get list of interfaces832*/833count = getAllInterfacesAndAddresses (env, &ifList);834if (count < 0) {835return NULL;836}837838/* allocate a NetworkInterface array */839netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);840if (netIFArr == NULL) {841free_netif(ifList);842return NULL;843}844845/*846* Iterate through the interfaces, create a NetworkInterface instance847* for each array element and populate the object.848*/849curr = ifList;850arr_index = 0;851while (curr != NULL) {852jobject netifObj;853854netifObj = createNetworkInterfaceXP(env, curr);855if (netifObj == NULL) {856free_netif(ifList);857return NULL;858}859860/* put the NetworkInterface into the array */861(*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);862curr = curr->next;863}864865/* release the interface list */866free_netif(ifList);867868return netIFArr;869}870871/*872* Class: java_net_NetworkInterface873* Method: supportsMulticast0874* Signature: (Ljava/lang/String;I)Z875*/876JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP877(JNIEnv *env, jclass cls, jstring name, jint index) {878IP_ADAPTER_ADDRESSES *ptr;879jboolean val = JNI_TRUE;880881ptr = getAdapter(env, index);882if (ptr != NULL) {883val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE;884free(ptr);885}886return val;887}888889/*890* Class: java_net_NetworkInterface891* Method: isUp0892* Signature: (Ljava/lang/String;I)Z893*/894JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP895(JNIEnv *env, jclass cls, jstring name, jint index) {896IP_ADAPTER_ADDRESSES *ptr;897jboolean val = JNI_FALSE;898899ptr = getAdapter(env, index);900if (ptr != NULL) {901val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE;902free(ptr);903}904return val;905}906907/*908* Class: java_net_NetworkInterface909* Method: getMacAddr0910* Signature: (Ljava/lang/String;I)Z911*/912JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP913(JNIEnv *env, jclass cls, jstring name, jint index) {914IP_ADAPTER_ADDRESSES *ptr;915jbyteArray ret = NULL;916int len;917918ptr = getAdapter(env, index);919if (ptr != NULL) {920len = ptr->PhysicalAddressLength;921if (len > 0) {922ret = (*env)->NewByteArray(env, len);923if (!IS_NULL(ret)) {924(*env)->SetByteArrayRegion(env, ret, 0, len,925(jbyte*) ptr->PhysicalAddress);926}927}928free(ptr);929}930return ret;931}932933/*934* Class: java_net_NetworkInterface935* Method: getMTU0936* Signature: ([bLjava/lang/String;I)I937*/938JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP939(JNIEnv *env, jclass cls, jstring name, jint index) {940IP_ADAPTER_ADDRESSES *ptr;941jint ret = -1;942943ptr = getAdapter(env, index);944if (ptr != NULL) {945ret = ptr->Mtu;946free(ptr);947}948return ret;949}950951/*952* Class: java_net_NetworkInterface953* Method: isLoopback0954* Signature: (Ljava/lang/String;I)Z955*/956JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP957(JNIEnv *env, jclass cls, jstring name, jint index) {958IP_ADAPTER_ADDRESSES *ptr;959jboolean val = JNI_FALSE;960961ptr = getAdapter(env, index);962if (ptr != NULL) {963val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE;964free(ptr);965}966return val;967}968969/*970* Class: java_net_NetworkInterface971* Method: isP2P0972* Signature: (Ljava/lang/String;I)Z973*/974JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP975(JNIEnv *env, jclass cls, jstring name, jint index) {976IP_ADAPTER_ADDRESSES *ptr;977jboolean val = JNI_FALSE;978979ptr = getAdapter(env, index);980if (ptr != NULL) {981if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP ||982ptr->IfType == IF_TYPE_TUNNEL) {983val = JNI_TRUE;984}985free(ptr);986}987return val;988}989990991