0N/A/*
3261N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <stdlib.h>
0N/A#include <windows.h>
0N/A#include <winsock2.h> /* needed for htonl */
0N/A#include <iprtrmib.h>
0N/A#include <assert.h>
0N/A
0N/A#include "java_net_NetworkInterface.h"
0N/A#include "jni_util.h"
0N/A
0N/A#include "NetworkInterface.h"
5888N/A#include "net_util.h"
0N/A
0N/A/*
0N/A * Windows implementation of the java.net.NetworkInterface native methods.
0N/A * This module provides the implementations of getAll, getByName, getByIndex,
0N/A * and getByAddress.
0N/A */
0N/A
0N/Aextern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
453N/Aint getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
0N/A
0N/A#ifdef DEBUG
0N/Avoid printnif (netif *nif) {
0N/A#ifdef _WIN64
0N/A printf ("nif:0x%I64x name:%s\n", nif,nif->name);
0N/A#else
0N/A printf ("nif:0x%x name:%s\n", nif,nif->name);
0N/A#endif
0N/A if (nif->dNameIsUnicode) {
0N/A printf ("dName:%S index:%d ", nif->displayName,nif->index);
0N/A } else {
0N/A printf ("dName:%s index:%d ", nif->displayName,nif->index);
0N/A }
0N/A printf ("naddrs:%d\n", nif->naddrs);
0N/A}
0N/A
0N/Avoid printnifs (netif *netifPP, char *str) {
0N/A netif *nif;
0N/A printf ("%s\n", str);
0N/A for (nif=netifPP; nif!=NULL; nif=nif->next) {
0N/A printnif (nif);
0N/A }
0N/A printf("-----------------\n");
0N/A}
0N/A
0N/A#endif
0N/A
0N/Astatic int bufsize = 1024;
0N/A
0N/A/*
0N/A * return an array of IP_ADAPTER_ADDRESSES containing one element
0N/A * for each apdapter on the system. Returned in *adapters.
0N/A * Buffer is malloc'd and must be freed (unless error returned)
0N/A */
0N/Astatic int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) {
0N/A DWORD ret, flags;
0N/A IP_ADAPTER_ADDRESSES *adapterInfo;
0N/A ULONG len;
0N/A adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
0N/A if (adapterInfo == 0) {
0N/A return -1;
0N/A }
0N/A len = bufsize;
0N/A flags = GAA_FLAG_SKIP_DNS_SERVER;
0N/A flags |= GAA_FLAG_SKIP_MULTICAST;
0N/A flags |= GAA_FLAG_INCLUDE_PREFIX;
3877N/A ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
0N/A if (ret == ERROR_BUFFER_OVERFLOW) {
0N/A adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
0N/A if (adapterInfo == 0) {
0N/A return -1;
0N/A }
0N/A bufsize = len;
3877N/A ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
0N/A }
0N/A if (ret != ERROR_SUCCESS) {
0N/A free (adapterInfo);
0N/A JNU_ThrowByName(env, "java/lang/Error",
0N/A "IP Helper Library GetAdaptersAddresses function failed");
0N/A return -1;
0N/A }
0N/A *adapters = adapterInfo;
0N/A return ERROR_SUCCESS;
0N/A}
0N/A
0N/A/*
0N/A * return an array of IP_ADAPTER_ADDRESSES containing one element
0N/A * for each apdapter on the system. Returned in *adapters.
0N/A * Buffer is malloc'd and must be freed (unless error returned)
0N/A */
0N/AIP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) {
0N/A DWORD flags, val;
0N/A IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret;
0N/A ULONG len;
0N/A adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize);
0N/A if (adapterInfo == 0) {
0N/A JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
0N/A return NULL;
0N/A }
0N/A len = bufsize;
0N/A flags = GAA_FLAG_SKIP_DNS_SERVER;
0N/A flags |= GAA_FLAG_SKIP_MULTICAST;
0N/A flags |= GAA_FLAG_INCLUDE_PREFIX;
3877N/A val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
0N/A if (val == ERROR_BUFFER_OVERFLOW) {
0N/A adapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len);
0N/A if (adapterInfo == 0) {
0N/A JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
0N/A return NULL;
0N/A }
0N/A bufsize = len;
3877N/A val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len);
0N/A }
0N/A if (val != ERROR_SUCCESS) {
0N/A free (adapterInfo);
0N/A JNU_ThrowByName(env, "java/lang/Error",
0N/A "IP Helper Library GetAdaptersAddresses function failed");
0N/A return NULL;
0N/A }
0N/A ptr = adapterInfo;
0N/A ret = NULL;
0N/A while (ptr != NULL) {
0N/A // IPv4 interface
0N/A if (ptr->Ipv6IfIndex == index) {
0N/A ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES));
0N/A memcpy(ret, ptr, sizeof(IP_ADAPTER_ADDRESSES));
0N/A }
0N/A ptr=ptr->Next;
0N/A }
0N/A free(adapterInfo);
0N/A return ret;
0N/A}
0N/A
0N/Astatic int ipinflen = 2048;
0N/A
0N/A/*
0N/A */
0N/Aint getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
0N/A{
453N/A DWORD ret;
453N/A IP_ADAPTER_ADDRESSES *ptr, *adapters=0;
0N/A ULONG len=ipinflen, count=0;
2109N/A netif *nif=0, *dup_nif, *last=0, *loopif=0, *curr;
0N/A int tun=0, net=0;
0N/A
0N/A *netifPP = 0;
0N/A
0N/A /*
0N/A * Get the IPv4 interfaces. This information is the same
0N/A * as what previous JDK versions would return.
0N/A */
0N/A
3877N/A ret = enumInterfaces(env, netifPP);
0N/A if (ret == -1) {
0N/A return -1;
0N/A } else {
0N/A count = ret;
0N/A }
0N/A
0N/A /* locate the loopback (and the last) interface */
0N/A for (nif=*netifPP, last=nif; nif!=0; nif=nif->next) {
0N/A if (nif->ifType == MIB_IF_TYPE_LOOPBACK) {
0N/A loopif = nif;
0N/A }
0N/A last = nif;
0N/A }
0N/A
2109N/A // Retrieve IPv4 addresses with the IP Helper API
2109N/A curr = *netifPP;
2109N/A while (curr != NULL) {
2109N/A netaddr *netaddrP;
2109N/A ret = enumAddresses_win(env, curr, &netaddrP);
5242N/A if (ret == -1) {
2109N/A return -1;
2109N/A }
2109N/A curr->addrs = netaddrP;
2109N/A curr->naddrs += ret;
2109N/A curr = curr->next;
2109N/A }
2109N/A
0N/A ret = getAdapters (env, &adapters);
0N/A if (ret != ERROR_SUCCESS) {
0N/A goto err;
0N/A }
0N/A
0N/A /* Now get the IPv6 information. This includes:
0N/A * (a) IPv6 information associated with interfaces already found
0N/A * (b) IPv6 information for IPv6 only interfaces (probably tunnels)
0N/A *
0N/A * For compatibility with previous releases we use the naming
3877N/A * information gotten from enumInterfaces() for (a) entries
0N/A * However, the index numbers are taken from the new API.
0N/A *
0N/A * The procedure is to go through the list of adapters returned
0N/A * by the new API looking for entries that correspond to IPv4 interfaces
0N/A * already found.
0N/A */
0N/A
0N/A ptr = adapters;
0N/A while (ptr != NULL) {
0N/A int c;
0N/A netif *nif0;
0N/A if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK && (loopif != NULL)) {
0N/A c = getAddrsFromAdapter(ptr, &loopif->addrs);
0N/A if (c == -1) {
0N/A goto err;
0N/A }
0N/A loopif->naddrs += c;
0N/A } else {
0N/A int index = ptr->IfIndex;
0N/A if (index != 0) {
0N/A /* This entry is associated with an IPv4 interface */
0N/A for (nif=*netifPP; nif!=0; nif=nif->next) {
0N/A if (nif->index == index) {
0N/A /* found the interface entry
0N/A * set the index to the IPv6 index and add the
0N/A * IPv6 addresses
0N/A */
0N/A nif->index = ptr->Ipv6IfIndex;
0N/A c = getAddrsFromAdapter(ptr, &nif->addrs);
0N/A nif->naddrs += c;
0N/A break;
0N/A }
0N/A }
0N/A } else {
0N/A /* This entry is IPv6 only */
0N/A char newname [128];
0N/A int c;
0N/A
0N/A /* Windows allocates duplicate adapter entries
0N/A * for tunnel interfaces when there are multiple
0N/A * physical adapters. Need to check
0N/A * if this is a duplicate (ipv6Index is the same)
0N/A */
0N/A dup_nif = 0;
0N/A for (nif0=*netifPP; nif0!=0; nif0=nif0->next) {
0N/A if (nif0->hasIpv6Address &&
0N/A ptr->Ipv6IfIndex == nif0->ipv6Index) {
0N/A dup_nif = nif0;
0N/A break;
0N/A }
0N/A }
0N/A if (dup_nif == 0) {
0N/A /* new interface */
0N/A nif = (netif *) calloc (1, sizeof(netif));
0N/A if (nif == 0) {
0N/A goto err;
0N/A }
0N/A if (ptr->IfType == IF_TYPE_TUNNEL) {
0N/A sprintf (newname, "tun%d", tun);
0N/A tun ++;
0N/A } else {
0N/A sprintf (newname, "net%d", net);
0N/A net ++;
0N/A }
0N/A nif->name = malloc (strlen(newname)+1);
0N/A nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2);
0N/A if (nif->name == 0 || nif->displayName == 0) {
0N/A goto err;
0N/A }
0N/A strcpy (nif->name, newname);
0N/A wcscpy ((PWCHAR)nif->displayName, ptr->FriendlyName);
0N/A nif->dNameIsUnicode = TRUE;
0N/A nif->index = ptr->Ipv6IfIndex;
0N/A nif->ipv6Index = ptr->Ipv6IfIndex;
0N/A nif->hasIpv6Address = TRUE;
0N/A
0N/A last->next = nif;
0N/A last = nif;
0N/A count++;
0N/A c = getAddrsFromAdapter(ptr, &nif->addrs);
0N/A if (c == -1) {
0N/A goto err;
0N/A }
0N/A nif->naddrs += c;
0N/A } else {
0N/A /* add the addresses from this adapter to the
0N/A * original (dup_nif)
0N/A */
0N/A c = getAddrsFromAdapter(ptr, &dup_nif->addrs);
0N/A if (c == -1) {
0N/A goto err;
0N/A }
0N/A dup_nif->naddrs += c;
0N/A }
0N/A }
0N/A }
0N/A ptr=ptr->Next;
0N/A }
0N/A
0N/A free (adapters);
0N/A return count;
0N/A
0N/Aerr:
0N/A if (*netifPP) {
0N/A free_netif (*netifPP);
0N/A }
0N/A if (adapters) {
0N/A free (adapters);
0N/A }
0N/A return -1;
0N/A}
0N/A
0N/A/* If *netaddrPP is null, then the addresses are allocated and the beginning
0N/A * of the allocated chain is returned in *netaddrPP.
0N/A * If *netaddrPP is not null, then the addresses allocated here are appended
0N/A * to the existing chain.
0N/A *
0N/A * Returns count of addresses or -1 on error.
0N/A */
0N/A
0N/Astatic int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP) {
0N/A LPSOCKADDR sock;
453N/A int count = 0;
0N/A netaddr *curr, *start=0, *prev=0;
0N/A PIP_ADAPTER_UNICAST_ADDRESS uni_addr;
0N/A PIP_ADAPTER_ANYCAST_ADDRESS any_addr;
0N/A PIP_ADAPTER_PREFIX prefix;
0N/A
0N/A /* If chain passed in, find end */
0N/A if (*netaddrPP != NULL) {
0N/A for (start=*netaddrPP; start->next!=NULL; start=start->next) {
0N/A }
0N/A prev=start;
0N/A }
0N/A
0N/A prefix = ptr->FirstPrefix;
0N/A /* Unicast */
0N/A uni_addr = ptr->FirstUnicastAddress;
0N/A while (uni_addr != NULL) {
0N/A /* address is only usable if dad state is preferred or deprecated */
0N/A if (uni_addr->DadState == IpDadStateDeprecated ||
0N/A uni_addr->DadState == IpDadStatePreferred) {
2109N/A sock = uni_addr->Address.lpSockaddr;
2109N/A
2109N/A // IPv4 addresses already retrieved with enumAddresses_win
2109N/A if (sock->sa_family == AF_INET) {
2109N/A uni_addr = uni_addr->Next;
2109N/A continue;
2109N/A }
2109N/A
0N/A curr = (netaddr *)calloc (1, sizeof (netaddr));
0N/A if (curr == 0) {
0N/A return -1;
0N/A }
0N/A if (start == NULL) {
0N/A start = curr;
0N/A }
0N/A if (prev != NULL) {
0N/A prev->next = curr;
0N/A }
0N/A prev = curr;
0N/A SOCKETADDRESS_COPY (&curr->addr, sock);
0N/A if (prefix != NULL) {
453N/A curr->mask = (short)prefix->PrefixLength;
0N/A prefix = prefix->Next;
0N/A }
0N/A count ++;
0N/A }
0N/A uni_addr = uni_addr->Next;
0N/A }
0N/A /* Anycast */
0N/A any_addr = ptr->FirstAnycastAddress;
0N/A while (any_addr != NULL) {
0N/A curr = (netaddr *)calloc (1, sizeof (netaddr));
0N/A if (curr == 0) {
0N/A return -1;
0N/A }
0N/A if (start == NULL) {
0N/A start = curr;
0N/A }
0N/A if (prev != NULL) {
0N/A prev->next = curr;
0N/A }
0N/A prev = curr;
0N/A sock = any_addr->Address.lpSockaddr;
0N/A SOCKETADDRESS_COPY (&curr->addr, sock);
0N/A count ++;
0N/A any_addr = any_addr->Next;
0N/A }
0N/A if (*netaddrPP == NULL) {
0N/A *netaddrPP = start;
0N/A }
0N/A return count;
0N/A}
0N/A
0N/A/*
0N/A * Create a NetworkInterface object, populate the name and index, and
0N/A * populate the InetAddress array based on the IP addresses for this
0N/A * interface.
0N/A */
0N/Astatic jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs)
0N/A{
0N/A jobject netifObj;
0N/A jobject name, displayName;
0N/A jobjectArray addrArr, bindsArr, childArr;
0N/A netaddr *addrs;
0N/A jint addr_index;
0N/A int netaddrCount=ifs->naddrs;
0N/A netaddr *netaddrP=ifs->addrs;
0N/A jint bind_index;
0N/A
0N/A /*
0N/A * Create a NetworkInterface object and populate it
0N/A */
0N/A netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
0N/A name = (*env)->NewStringUTF(env, ifs->name);
0N/A if (ifs->dNameIsUnicode) {
3877N/A displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,
3877N/A (jsize)wcslen ((PWCHAR)ifs->displayName));
0N/A } else {
0N/A displayName = (*env)->NewStringUTF(env, ifs->displayName);
0N/A }
0N/A if (netifObj == NULL || name == NULL || displayName == NULL) {
0N/A return NULL;
0N/A }
0N/A (*env)->SetObjectField(env, netifObj, ni_nameID, name);
0N/A (*env)->SetObjectField(env, netifObj, ni_displayNameID, displayName);
0N/A (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
0N/A
0N/A /*
0N/A * Get the IP addresses for this interface if necessary
0N/A * Note that 0 is a valid number of addresses.
0N/A */
0N/A if (netaddrCount < 0) {
0N/A netaddrCount = enumAddresses_win(env, ifs, &netaddrP);
5242N/A if (netaddrCount == -1) {
0N/A return NULL;
0N/A }
0N/A }
0N/A
0N/A addrArr = (*env)->NewObjectArray(env, netaddrCount, ni_iacls, NULL);
0N/A if (addrArr == NULL) {
0N/A return NULL;
0N/A }
0N/A
0N/A bindsArr = (*env)->NewObjectArray(env, netaddrCount, ni_ibcls, NULL);
0N/A if (bindsArr == NULL) {
0N/A free_netaddr(netaddrP);
0N/A return NULL;
0N/A }
0N/A
0N/A addrs = netaddrP;
0N/A addr_index = 0;
0N/A bind_index = 0;
0N/A while (addrs != NULL) {
0N/A jobject iaObj, ia2Obj;
0N/A jobject ibObj = NULL;
0N/A if (addrs->addr.him.sa_family == AF_INET) {
0N/A iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
0N/A if (iaObj == NULL) {
0N/A return NULL;
0N/A }
0N/A /* default ctor will set family to AF_INET */
0N/A
5888N/A setInetAddress_addr(env, iaObj, ntohl(addrs->addr.him4.sin_addr.s_addr));
0N/A
0N/A ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
0N/A if (ibObj == NULL) {
0N/A free_netaddr(netaddrP);
0N/A return NULL;
0N/A }
0N/A (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
0N/A ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4Ctor);
0N/A if (ia2Obj == NULL) {
0N/A free_netaddr(netaddrP);
0N/A return NULL;
0N/A }
5888N/A setInetAddress_addr(env, ia2Obj, ntohl(addrs->brdcast.him4.sin_addr.s_addr));
0N/A (*env)->SetObjectField(env, ibObj, ni_ibbroadcastID, ia2Obj);
0N/A (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
0N/A (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
0N/A } else /* AF_INET6 */ {
0N/A int scope;
0N/A iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
0N/A if (iaObj) {
0N/A jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
0N/A if (ipaddress == NULL) {
0N/A return NULL;
0N/A }
0N/A (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
0N/A (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr));
0N/A scope = addrs->addr.him6.sin6_scope_id;
0N/A if (scope != 0) { /* zero is default value, no need to set */
0N/A (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
0N/A (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
0N/A (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
0N/A }
0N/A (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
0N/A ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
0N/A if (ibObj == NULL) {
0N/A free_netaddr(netaddrP);
0N/A return NULL;
0N/A }
0N/A (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
0N/A (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
0N/A (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
0N/A }
0N/A }
0N/A (*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);
0N/A addrs = addrs->next;
0N/A addr_index++;
0N/A }
0N/A (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
0N/A (*env)->SetObjectField(env, netifObj, ni_bindsID, bindsArr);
0N/A
0N/A /*
0N/A * Windows doesn't have virtual interfaces, so child array
0N/A * is always empty.
0N/A */
0N/A childArr = (*env)->NewObjectArray(env, 0, ni_class, NULL);
0N/A if (childArr == NULL) {
0N/A return NULL;
0N/A }
0N/A (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
0N/A
0N/A /* return the NetworkInterface */
0N/A return netifObj;
0N/A}
0N/A
0N/AJNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
0N/A (JNIEnv *env, jclass cls, jstring name)
0N/A{
0N/A netif *ifList, *curr;
0N/A jboolean isCopy;
0N/A const char *name_utf;
0N/A jobject netifObj = NULL;
0N/A
0N/A if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A /* get the name as a C string */
0N/A name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
0N/A
0N/A /* Search by name */
0N/A curr = ifList;
0N/A while (curr != NULL) {
0N/A if (strcmp(name_utf, curr->name) == 0) {
0N/A break;
0N/A }
0N/A curr = curr->next;
0N/A }
0N/A
0N/A /* if found create a NetworkInterface */
0N/A if (curr != NULL) {;
0N/A netifObj = createNetworkInterfaceXP(env, curr);
0N/A }
0N/A
0N/A /* release the UTF string */
0N/A (*env)->ReleaseStringUTFChars(env, name, name_utf);
0N/A
0N/A /* release the interface list */
0N/A free_netif(ifList);
0N/A
0N/A return netifObj;
0N/A}
0N/A
0N/A/*
0N/A * Class: NetworkInterface
509N/A * Method: getByIndex0_XP
0N/A * Signature: (I)LNetworkInterface;
0N/A */
509N/AJNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0_XP
0N/A (JNIEnv *env, jclass cls, jint index)
0N/A{
0N/A netif *ifList, *curr;
0N/A jobject netifObj = NULL;
0N/A
0N/A if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A /* search by index */
0N/A curr = ifList;
0N/A while (curr != NULL) {
0N/A if (index == curr->index) {
0N/A break;
0N/A }
0N/A curr = curr->next;
0N/A }
0N/A
0N/A /* if found create a NetworkInterface */
0N/A if (curr != NULL) {
0N/A netifObj = createNetworkInterfaceXP(env, curr);
0N/A }
0N/A
0N/A /* release the interface list */
0N/A free_netif(ifList);
0N/A
0N/A return netifObj;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: getByInetAddress0
0N/A * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
0N/A */
0N/AJNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0_XP
0N/A (JNIEnv *env, jclass cls, jobject iaObj)
0N/A{
0N/A netif *ifList, *curr;
0N/A jobject netifObj = NULL;
0N/A
0N/A /* get the list of interfaces */
0N/A if (getAllInterfacesAndAddresses (env, &ifList) < 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A /*
0N/A * Enumerate the addresses on each interface until we find a
0N/A * matching address.
0N/A */
0N/A curr = ifList;
0N/A while (curr != NULL) {
0N/A netaddr *addrList = curr->addrs;
0N/A netaddr *addrP;
0N/A
0N/A /* iterate through each address */
0N/A addrP = addrList;
0N/A
0N/A while (addrP != NULL) {
0N/A if (NET_SockaddrEqualsInetAddress(env,
0N/A (struct sockaddr*)&addrP->addr, iaObj)) {
0N/A break;
0N/A }
0N/A addrP = addrP->next;
0N/A }
0N/A
0N/A /*
0N/A * Address matched so create NetworkInterface for this interface
0N/A * and address list.
0N/A */
0N/A if (addrP != NULL) {
0N/A netifObj = createNetworkInterfaceXP(env, curr);
0N/A break;
0N/A }
0N/A
0N/A /* on next interface */
0N/A curr = curr->next;
0N/A }
0N/A
0N/A /* release the interface list */
0N/A free_netif(ifList);
0N/A
0N/A return netifObj;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: getAll
0N/A * Signature: ()[Ljava/net/NetworkInterface;
0N/A */
0N/AJNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A int count;
0N/A netif *ifList, *curr;
0N/A jobjectArray netIFArr;
0N/A jint arr_index;
0N/A
0N/A /*
0N/A * Get list of interfaces
0N/A */
0N/A count = getAllInterfacesAndAddresses (env, &ifList);
0N/A if (count < 0) {
0N/A return NULL;
0N/A }
0N/A
0N/A /* allocate a NetworkInterface array */
0N/A netIFArr = (*env)->NewObjectArray(env, count, cls, NULL);
0N/A if (netIFArr == NULL) {
0N/A return NULL;
0N/A }
0N/A
0N/A /*
0N/A * Iterate through the interfaces, create a NetworkInterface instance
0N/A * for each array element and populate the object.
0N/A */
0N/A curr = ifList;
0N/A arr_index = 0;
0N/A while (curr != NULL) {
0N/A jobject netifObj;
0N/A
0N/A netifObj = createNetworkInterfaceXP(env, curr);
0N/A if (netifObj == NULL) {
0N/A return NULL;
0N/A }
0N/A
0N/A /* put the NetworkInterface into the array */
0N/A (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
0N/A curr = curr->next;
0N/A }
0N/A
0N/A /* release the interface list */
0N/A free_netif(ifList);
0N/A
0N/A return netIFArr;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: supportsMulticast0
0N/A * Signature: (Ljava/lang/String;I)Z
0N/A */
0N/AJNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jboolean val = JNI_TRUE;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A val = ptr->Flags & IP_ADAPTER_NO_MULTICAST ? JNI_FALSE : JNI_TRUE;
0N/A free(ptr);
0N/A }
0N/A return val;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: isUp0
0N/A * Signature: (Ljava/lang/String;I)Z
0N/A */
0N/AJNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jboolean val = JNI_FALSE;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A val = ptr->OperStatus == IfOperStatusUp ? JNI_TRUE : JNI_FALSE;
0N/A free(ptr);
0N/A }
0N/A return val;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: getMacAddr0
0N/A * Signature: (Ljava/lang/String;I)Z
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jbyteArray ret = NULL;
0N/A int len;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A len = ptr->PhysicalAddressLength;
0N/A ret = (*env)->NewByteArray(env, len);
0N/A if (!IS_NULL(ret)) {
0N/A (*env)->SetByteArrayRegion(env, ret, 0, len,
0N/A (jbyte*) ptr->PhysicalAddress);
0N/A }
0N/A free(ptr);
0N/A }
0N/A return ret;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: getMTU0
0N/A * Signature: ([bLjava/lang/String;I)I
0N/A */
0N/AJNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jint ret = -1;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A ret = ptr->Mtu;
0N/A free(ptr);
0N/A }
0N/A return ret;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: isLoopback0
0N/A * Signature: (Ljava/lang/String;I)Z
0N/A */
0N/AJNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jboolean val = JNI_FALSE;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A val = ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? JNI_TRUE : JNI_FALSE;
0N/A free(ptr);
0N/A }
0N/A return val;
0N/A}
0N/A
0N/A/*
0N/A * Class: java_net_NetworkInterface
0N/A * Method: isP2P0
0N/A * Signature: (Ljava/lang/String;I)Z
0N/A */
0N/AJNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0_XP
0N/A (JNIEnv *env, jclass cls, jstring name, jint index) {
0N/A IP_ADAPTER_ADDRESSES *ptr;
0N/A jboolean val = JNI_FALSE;
0N/A
0N/A ptr = getAdapter(env, index);
0N/A if (ptr != NULL) {
0N/A if (ptr->IfType == IF_TYPE_PPP || ptr->IfType == IF_TYPE_SLIP ||
0N/A ptr->IfType == IF_TYPE_TUNNEL) {
0N/A val = JNI_TRUE;
0N/A }
0N/A free(ptr);
0N/A }
0N/A return val;
0N/A}