Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/java/net/NetworkInterface_winXP.c
32287 views
/*1* Copyright (c) 2003, 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>30#include <limits.h>3132#include "java_net_NetworkInterface.h"33#include "jni_util.h"3435#include "NetworkInterface.h"36#include "net_util.h"3738/*39* Windows implementation of the java.net.NetworkInterface native methods.40* This module provides the implementations of getAll, getByName, getByIndex,41* and getByAddress.42*/4344extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);45int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);4647#ifdef DEBUG48void printnif (netif *nif) {49#ifdef _WIN6450printf ("nif:0x%I64x name:%s\n", nif,nif->name);51#else52printf ("nif:0x%x name:%s\n", nif,nif->name);53#endif54if (nif->dNameIsUnicode) {55printf ("dName:%S index:%d ", nif->displayName,nif->index);56} else {57printf ("dName:%s index:%d ", nif->displayName,nif->index);58}59printf ("naddrs:%d\n", nif->naddrs);60}6162void printnifs (netif *netifPP, char *str) {63netif *nif;64printf ("%s\n", str);65for (nif=netifPP; nif!=NULL; nif=nif->next) {66printnif (nif);67}68printf("-----------------\n");69}7071#endif7273const ULONG BUFF_SIZE = 15360;74const int MAX_TRIES = 3;7576/*77* return an array of IP_ADAPTER_ADDRESSES containing one element78* for each adapter on the system. Returned in *adapters.79* Buffer is malloc'd and must be freed (unless error returned)80*/81static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) {82DWORD ret, flags;83IP_ADAPTER_ADDRESSES *adapterInfo;84ULONG len;85int try;868788adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);89if (adapterInfo == NULL) {90JNU_ThrowByName(env, "java/lang/OutOfMemoryError",91"Native heap allocation failure");92return -1;93}9495len = BUFF_SIZE;96flags = GAA_FLAG_SKIP_DNS_SERVER;97flags |= GAA_FLAG_SKIP_MULTICAST;98flags |= GAA_FLAG_INCLUDE_PREFIX;99ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);100101for (try = 0; ret == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {102IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;103if (len < (ULONG_MAX - BUFF_SIZE)) {104len += BUFF_SIZE;105}106newAdapterInfo =107(IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);108if (newAdapterInfo == NULL) {109free(adapterInfo);110JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure");111return -1;112}113114adapterInfo = newAdapterInfo;115116ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);117}118119if (ret != ERROR_SUCCESS) {120free (adapterInfo);121JNU_ThrowByName(env, "java/lang/Error",122"IP Helper Library GetAdaptersAddresses function failed");123return -1;124}125*adapters = adapterInfo;126return ERROR_SUCCESS;127}128129/*130* return an array of IP_ADAPTER_ADDRESSES containing one element131* for each adapter on the system. Returned in *adapters.132* Buffer is malloc'd and must be freed (unless error returned)133*/134IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {135DWORD flags, val;136IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret;137ULONG len;138int try;139adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE);140if (adapterInfo == NULL) {141JNU_ThrowByName(env, "java/lang/OutOfMemoryError",142"Native heap allocation failure");143return NULL;144}145len = BUFF_SIZE;146flags = GAA_FLAG_SKIP_DNS_SERVER;147flags |= GAA_FLAG_SKIP_MULTICAST;148flags |= GAA_FLAG_INCLUDE_PREFIX;149val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);150for (try = 0; val == ERROR_BUFFER_OVERFLOW && try < MAX_TRIES; ++try) {151IP_ADAPTER_ADDRESSES * newAdapterInfo = NULL;152if (len < (ULONG_MAX - BUFF_SIZE)) {153len += BUFF_SIZE;154}155newAdapterInfo =156(IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);157if (newAdapterInfo == NULL) {158free(adapterInfo);159JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure");160return NULL;161}162163adapterInfo = newAdapterInfo;164165val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);166}167168if (val != ERROR_SUCCESS) {169free (adapterInfo);170JNU_ThrowByName(env, "java/lang/Error",171"IP Helper Library GetAdaptersAddresses function failed");172return NULL;173}174ptr = adapterInfo;175ret = NULL;176while (ptr != NULL) {177// in theory the IPv4 index and the IPv6 index can be the same178// where an interface is enabled for v4 and v6179// IfIndex == 0 IPv4 not available on this interface180// Ipv6IfIndex == 0 IPv6 not available on this interface181if (((ptr->IfIndex != 0)&&(ptr->IfIndex == index)) ||182((ptr->Ipv6IfIndex !=0) && (ptr->Ipv6IfIndex == index))) {183ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES));184if (ret == NULL) {185free(adapterInfo);186JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure");187return NULL;188}189190//copy the memory and break out of the while loop.191memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES));192break;193194}195ptr=ptr->Next;196}197free(adapterInfo);198return ret;199}200201static int ipinflen = 2048;202203/*204*/205int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)206{207DWORD ret;208IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;209ULONG len=ipinflen, count=0;210netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;211int tun=0, net=0;212213*netifPP = NULL;214/*215* Get the IPv4 interfaces. This information is the same216* as what previous JDK versions would return.217*/218219ret = enumInterfaces(env, netifPP);220if (ret == -1) {221return -1;222} else {223count = ret;224}225226/* locate the loopback (and the last) interface */227for (nif=*netifPP, last=nif; nif!=NULL; nif=nif->next) {228if (nif->ifType == MIB_IF_TYPE_LOOPBACK) {229loopif = nif;230}231last = nif;232}233234// Retrieve IPv4 addresses with the IP Helper API235curr = *netifPP;236while (curr != NULL) {237netaddr *netaddrP;238ret = enumAddresses_win(env, curr, &netaddrP);239if (ret == -1) {240return -1;241}242curr->addrs = netaddrP;243curr->naddrs += ret;244curr = curr->next;245}246247ret = getAdapters (env, &adapters);248if (ret != ERROR_SUCCESS) {249goto err;250}251252/* Now get the IPv6 information. This includes:253* (a) IPv6 information associated with interfaces already found254* (b) IPv6 information for IPv6 only interfaces (probably tunnels)255*256* For compatibility with previous releases we use the naming257* information gotten from enumInterfaces() for (a) entries258* However, the index numbers are taken from the new API.259*260* The procedure is to go through the list of adapters returned261* by the new API looking for entries that correspond to IPv4 interfaces262* already found.263*/264265ptr = adapters;266while (ptr != NULL) {267int c;268netif *nif0;269if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) {270c = getAddrsFromAdapter(ptr, &loopif->addrs);271if (c == -1) {272goto err;273}274loopif->naddrs += c;275} else {276int index = ptr->IfIndex;277if (index != 0) {278/* This entry is associated with an IPv4 interface */279for (nif=*netifPP; nif!=NULL; nif=nif->next) {280if (nif->index == index) {281/* found the interface entry282* set the index to the IPv6 index and add the283* IPv6 addresses284*/285nif->ipv6Index = ptr->Ipv6IfIndex;286c = getAddrsFromAdapter(ptr, &nif->addrs);287nif->naddrs += c;288break;289}290}291} else {292/* This entry is IPv6 only */293char newname [128];294int c;295296/* Windows allocates duplicate adapter entries297* for tunnel interfaces when there are multiple298* physical adapters. Need to check299* if this is a duplicate (ipv6Index is the same)300*/301dup_nif = 0;302for (nif0=*netifPP; nif0!=NULL; nif0=nif0->next) {303if (nif0->hasIpv6Address &&304ptr->Ipv6IfIndex == nif0->ipv6Index) {305dup_nif = nif0;306break;307}308}309if (dup_nif == 0) {310/* new interface */311nif = (netif *) calloc (1, sizeof(netif));312if (nif == 0) {313goto err;314}315if (ptr->IfType == IF_TYPE_TUNNEL) {316sprintf (newname, "tun%d", tun);317tun ++;318} else {319sprintf (newname, "net%d", net);320net ++;321}322nif->name = malloc (strlen(newname)+1);323nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2);324if (nif->name == 0 || nif->displayName == 0) {325goto err;326}327strcpy (nif->name, newname);328wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName);329nif->dNameIsUnicode = TRUE;330331// the java.net.NetworkInterface abstraction only has index332// so the Ipv6IfIndex needs to map onto index333nif->index = ptr->Ipv6IfIndex;334nif->ipv6Index = ptr->Ipv6IfIndex;335nif->hasIpv6Address = TRUE;336337last->next = nif;338last = nif;339count++;340c = getAddrsFromAdapter(ptr, &nif->addrs);341if (c == -1) {342goto err;343}344nif->naddrs += c;345} else {346/* add the addresses from this adapter to the347* original (dup_nif)348*/349c = getAddrsFromAdapter(ptr, &dup_nif->addrs);350if (c == -1) {351goto err;352}353dup_nif->naddrs += c;354}355}356}357ptr=ptr->Next;358}359360free (adapters);361return count;362363err:364if (*netifPP) {365free_netif (*netifPP);366}367if (adapters) {368free (adapters);369}370return -1;371}372373/* If *netaddrPP is null, then the addresses are allocated and the beginning374* of the allocated chain is returned in *netaddrPP.375* If *netaddrPP is not null, then the addresses allocated here are appended376* to the existing chain.377*378* Returns count of addresses or -1 on error.379*/380381static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) {382LPSOCKADDR sock;383int count = 0;384netaddr *curr, *start = NULL, *prev = NULL;385PIP_ADAPTER_UNICAST_ADDRESS uni_addr;386PIP_ADAPTER_ANYCAST_ADDRESS any_addr;387PIP_ADAPTER_PREFIX prefix;388389/* If chain passed in, find end */390if (*netaddrPP != NULL) {391for (start=*netaddrPP; start->next!=NULL; start=start->next)392;393394prev=start;395}396397prefix = ptr->FirstPrefix;398/* Unicast */399uni_addr = ptr->FirstUnicastAddress;400while (uni_addr != NULL) {401/* address is only usable if dad state is preferred or deprecated */402if (uni_addr->DadState == IpDadStateDeprecated ||403uni_addr->DadState == IpDadStatePreferred) {404sock = uni_addr->Address.lpSockaddr;405406// IPv4 addresses already retrieved with enumAddresses_win407if (sock->sa_family == AF_INET) {408uni_addr = uni_addr->Next;409continue;410}411412curr = (netaddr *)calloc (1, sizeof (netaddr));413414if (curr == NULL)415goto freeAllocatedMemory;416417if (start == NULL)418start = curr;419420if (prev != NULL)421prev->next = curr;422423prev = curr;424SOCKETADDRESS_COPY (&curr->addr, sock);425if (prefix != NULL) {426curr->mask = (short)prefix->PrefixLength;427prefix = prefix->Next;428}429count ++;430}431uni_addr = uni_addr->Next;432}433/* Anycast */434any_addr = ptr->FirstAnycastAddress;435while (any_addr != NULL) {436curr = (netaddr *)calloc (1, sizeof (netaddr));437438if (curr == NULL)439goto freeAllocatedMemory;440441if (start == NULL)442start = curr;443444if (prev != NULL)445prev->next = curr;446447prev = curr;448sock = any_addr->Address.lpSockaddr;449SOCKETADDRESS_COPY (&curr->addr, sock);450count ++;451any_addr = any_addr->Next;452}453if (*netaddrPP == NULL) {454*netaddrPP = start;455}456return count;457458freeAllocatedMemory:459460if (*netaddrPP != NULL) {461//N.B. the variable "start" cannot be NULL at this point because we started with an462//existing list.463curr=start->next;464start->next = NULL;465start = curr;466}467// otherwise, "start" points to the beginning of an incomplete list that we must deallocate.468469while (start != NULL) {470curr = start->next;471free(start);472start = curr;473}474475return -1;476}477478/*479* Create a NetworkInterface object, populate the name and index, and480* populate the InetAddress array based on the IP addresses for this481* interface.482*/483static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)484{485jobject netifObj;486jobject name, displayName;487jobjectArray addrArr, bindsArr, childArr;488netaddr *addrs;489jint addr_index;490int netaddrCount = ifs->naddrs;491netaddr *netaddrP = ifs->addrs;492netaddr *netaddrPToFree = NULL;493jint bind_index;494495/*496* Create a NetworkInterface object and populate it497*/498netifObj = (*env)->NewObject(env, ni_class, ni_ctor);499if (netifObj == NULL) {500return NULL;501}502name = (*env)->NewStringUTF(env, ifs->name);503if (name == NULL) {504return NULL;505}506if (ifs->dNameIsUnicode) {507displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,508(jsize)wcslen ((PWCHAR)ifs->displayName));509} else {510displayName = (*env)->NewStringUTF(env, ifs->displayName);511}512if (displayName == NULL) {513return NULL;514}515(*env)->SetObjectField(env, netifObj, ni_nameID, name);516(*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);517(*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);518/*519* Get the IP addresses for this interface if necessary520* Note that 0 is a valid number of addresses.521*/522if (netaddrCount < 0) {523netaddrCount = enumAddresses_win(env, ifs, &netaddrPToFree);524if (netaddrCount == -1) {525return NULL;526}527netaddrP = netaddrPToFree;528}529530addrArr = (*env)->NewObjectArray(env, netaddrCount, ia_class, NULL);531if (addrArr == NULL) {532free_netaddr(netaddrPToFree);533return NULL;534}535536bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);537if (bindsArr == NULL) {538free_netaddr(netaddrPToFree);539return NULL;540}541542addrs = netaddrP;543addr_index = 0;544bind_index = 0;545while (addrs != NULL) {546jobject iaObj, ia2Obj;547jobject ibObj = NULL;548if (addrs->addr.him.sa_family == AF_INET) {549iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);550if (iaObj == NULL) {551free_netaddr(netaddrPToFree);552return NULL;553}554/* default ctor will set family to AF_INET */555556setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));557if ((*env)->ExceptionCheck(env)) {558free_netaddr(netaddrPToFree);559return NULL;560}561ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);562if (ibObj == NULL) {563free_netaddr(netaddrPToFree);564return NULL;565}566(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);567ia2Obj = (*env)->NewObject(env, ia4_class, ia4_ctrID);568if (ia2Obj == NULL) {569free_netaddr(netaddrPToFree);570return NULL;571}572setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));573if ((*env)->ExceptionCheck(env)) {574free_netaddr(netaddrPToFree);575return NULL;576}577(*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);578(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);579(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);580} else /* AF_INET6 */ {581int scope;582int ret;583iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);584if (iaObj == NULL) {585free_netaddr(netaddrPToFree);586return NULL;587}588ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));589if (ret == JNI_FALSE) {590free_netaddr(netaddrPToFree);591return NULL;592}593scope = addrs->addr.him6.sin6_scope_id;594if (scope != 0) { /* zero is default value, no need to set */595setInet6Address_scopeid(env, iaObj, scope);596setInet6Address_scopeifname(env, iaObj, netifObj);597}598ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);599if (ibObj == NULL) {600free_netaddr(netaddrPToFree);601return NULL;602}603(*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);604(*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);605(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);606}607(*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);608addrs = addrs->next;609addr_index++;610}611(*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);612(*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);613614free_netaddr(netaddrPToFree);615616/*617* Windows doesn't have virtual interfaces, so child array618* is always empty.619*/620childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);621if (childArr == NULL) {622return NULL;623}624(*env)->SetObjectField(env, netifObj, ni_childsID, childArr);625626/* return the NetworkInterface */627return netifObj;628}629630JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP631(JNIEnv *env, jclass cls, jstring name)632{633netif *ifList, *curr;634jboolean isCopy;635const char *name_utf;636jobject netifObj = NULL;637638if (getAllInterfacesAndAddresses (env, &ifList) < 0) {639return NULL;640}641642/* get the name as a C string */643name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);644645/* Search by name */646curr = ifList;647while (curr != NULL) {648if (strcmp(name_utf, curr->name) == 0) {649break;650}651curr = curr->next;652}653654/* if found create a NetworkInterface */655if (curr != NULL) {656netifObj = createNetworkInterfaceXP(env, curr);657}658659/* release the UTF string */660(*env)->ReleaseStringUTFChars(env, name, name_utf);661662/* release the interface list */663free_netif(ifList);664665return netifObj;666}667668/*669* Class: NetworkInterface670* Method: getByIndex0_XP671* Signature: (I)LNetworkInterface;672*/673JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0_XP674(JNIEnv *env, jclass cls, jint index)675{676netif *ifList, *curr;677jobject netifObj = NULL;678679if (getAllInterfacesAndAddresses (env, &ifList) < 0) {680return NULL;681}682683/* search by index */684curr = ifList;685while (curr != NULL) {686if (index == curr->index) {687break;688}689curr = curr->next;690}691692/* if found create a NetworkInterface */693if (curr != NULL) {694netifObj = createNetworkInterfaceXP(env, curr);695}696697/* release the interface list */698free_netif(ifList);699700return netifObj;701}702703/*704* Class: java_net_NetworkInterface705* Method: getByInetAddress0706* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;707*/708JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP709(JNIEnv *env, jclass cls, jobject iaObj)710{711netif *ifList, *curr;712jobject netifObj = NULL;713714/* get the list of interfaces */715if (getAllInterfacesAndAddresses (env, &ifList) < 0) {716return NULL;717}718719/*720* Enumerate the addresses on each interface until we find a721* matching address.722*/723curr = ifList;724while (curr != NULL) {725netaddr *addrList = curr->addrs;726netaddr *addrP;727728/* iterate through each address */729addrP = addrList;730731while (addrP != NULL) {732if (NET_SockaddrEqualsInetAddress(env,733(struct sockaddr*)&addrP->addr, iaObj)) {734break;735}736addrP = addrP->next;737}738739/*740* Address matched so create NetworkInterface for this interface741* and address list.742*/743if (addrP != NULL) {744netifObj = createNetworkInterfaceXP(env, curr);745break;746}747748/* on next interface */749curr = curr->next;750}751752/* release the interface list */753free_netif(ifList);754755return netifObj;756}757758/*759* Class: java_net_NetworkInterface760* Method: getAll761* Signature: ()[Ljava/net/NetworkInterface;762*/763JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP764(JNIEnv *env, jclass cls)765{766int count;767netif *ifList, *curr;768jobjectArray netIFArr;769jint arr_index;770771/*772* Get list of interfaces773*/774count = getAllInterfacesAndAddresses (env, &ifList);775if (count < 0) {776return NULL;777}778779/* allocate a NetworkInterface array */780netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);781if (netIFArr == NULL) {782free_netif(ifList);783return NULL;784}785786/*787* Iterate through the interfaces, create a NetworkInterface instance788* for each array element and populate the object.789*/790curr = ifList;791arr_index = 0;792while (curr != NULL) {793jobject netifObj;794795netifObj = createNetworkInterfaceXP(env, curr);796if (netifObj == NULL) {797free_netif(ifList);798return NULL;799}800801/* put the NetworkInterface into the array */802(*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);803curr = curr->next;804}805806/* release the interface list */807free_netif(ifList);808809return netIFArr;810}811812/*813* Class: java_net_NetworkInterface814* Method: supportsMulticast0815* Signature: (Ljava/lang/String;I)Z816*/817JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP818(JNIEnv *env, jclass cls, jstring name, jint index) {819IP_ADAPTER_ADDRESSES *ptr;820jboolean val = JNI_TRUE;821822ptr = getAdapter(env, index);823if (ptr != NULL) {824val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE;825free(ptr);826}827return val;828}829830/*831* Class: java_net_NetworkInterface832* Method: isUp0833* Signature: (Ljava/lang/String;I)Z834*/835JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP836(JNIEnv *env, jclass cls, jstring name, jint index) {837IP_ADAPTER_ADDRESSES *ptr;838jboolean val = JNI_FALSE;839840ptr = getAdapter(env, index);841if (ptr != NULL) {842val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE;843free(ptr);844}845return val;846}847848/*849* Class: java_net_NetworkInterface850* Method: getMacAddr0851* Signature: (Ljava/lang/String;I)Z852*/853JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP854(JNIEnv *env, jclass cls, jstring name, jint index) {855IP_ADAPTER_ADDRESSES *ptr;856jbyteArray ret = NULL;857int len;858859ptr = getAdapter(env, index);860if (ptr != NULL) {861len = ptr->PhysicalAddressLength;862if (len > 0) {863ret = (*env)->NewByteArray(env, len);864if (!IS_NULL(ret)) {865(*env)->SetByteArrayRegion(env, ret, 0, len,866(jbyte*) ptr->PhysicalAddress);867}868}869free(ptr);870}871return ret;872}873874/*875* Class: java_net_NetworkInterface876* Method: getMTU0877* Signature: ([bLjava/lang/String;I)I878*/879JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP880(JNIEnv *env, jclass cls, jstring name, jint index) {881IP_ADAPTER_ADDRESSES *ptr;882jint ret = -1;883884ptr = getAdapter(env, index);885if (ptr != NULL) {886ret = ptr->Mtu;887free(ptr);888}889return ret;890}891892/*893* Class: java_net_NetworkInterface894* Method: isLoopback0895* Signature: (Ljava/lang/String;I)Z896*/897JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP898(JNIEnv *env, jclass cls, jstring name, jint index) {899IP_ADAPTER_ADDRESSES *ptr;900jboolean val = JNI_FALSE;901902ptr = getAdapter(env, index);903if (ptr != NULL) {904val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE;905free(ptr);906}907return val;908}909910/*911* Class: java_net_NetworkInterface912* Method: isP2P0913* Signature: (Ljava/lang/String;I)Z914*/915JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP916(JNIEnv *env, jclass cls, jstring name, jint index) {917IP_ADAPTER_ADDRESSES *ptr;918jboolean val = JNI_FALSE;919920ptr = getAdapter(env, index);921if (ptr != NULL) {922if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP ||923ptr->IfType == IF_TYPE_TUNNEL) {924val = JNI_TRUE;925}926free(ptr);927}928return val;929}930931932