Here's a revised patch that uses getifaddrs. Works on Darwin with jamvm,
I have not yet tested Linux.
This still contains the same fix for jcl.c. I'll try to come up with a
better solution that fixes the issue, but for now, if you want to try it
on JamVM, you'll need this fix.
? native/jni/java-net/netif.c
? native/jni/java-net/netif.h
Index: configure.ac
===================================================================
RCS file: /cvsroot/classpath/classpath/configure.ac,v
retrieving revision 1.181
diff -u -r1.181 configure.ac
--- configure.ac 31 Aug 2006 19:56:03 -0000 1.181
+++ configure.ac 9 Sep 2006 19:01:13 -0000
@@ -373,12 +373,19 @@
fcntl \
mmap munmap mincore msync madvise getpagesize sysconf \
lstat readlink \
- ])
+ getifaddrs])
LIBMAGIC=
AC_CHECK_LIB(magic, magic_open, LIBMAGIC=-lmagic)
AC_SUBST(LIBMAGIC)
+ AC_MSG_CHECKING([whether struct sockaddr_in6 is in netinet/in.h])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <netinet/in.h>]], [[struct
sockaddr_in6 addr6;]])],
+ [AC_DEFINE(HAVE_INET6, 1,
+ [Define if inet6 structures are defined in netinet/in.h.])
+ AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)])
+
AC_HEADER_TIME
AC_STRUCT_TM
AC_STRUCT_TIMEZONE
Index: include/java_net_VMNetworkInterface.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/java_net_VMNetworkInterface.h,v
retrieving revision 1.1
diff -u -r1.1 java_net_VMNetworkInterface.h
--- include/java_net_VMNetworkInterface.h 11 Apr 2005 18:58:38 -0000
1.1
+++ include/java_net_VMNetworkInterface.h 9 Sep 2006 19:01:13 -0000
@@ -1,19 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __java_net_VMNetworkInterface__
-#define __java_net_VMNetworkInterface__
-
#include <jni.h>
+/* Header for class java_net_VMNetworkInterface */
+#ifndef _Included_java_net_VMNetworkInterface
+#define _Included_java_net_VMNetworkInterface
#ifdef __cplusplus
-extern "C"
-{
+extern "C" {
#endif
-
-JNIEXPORT jobject JNICALL Java_java_net_VMNetworkInterface_getInterfaces
(JNIEnv *env, jclass);
+/*
+ * Class: java_net_VMNetworkInterface
+ * Method: initIds
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_VMNetworkInterface_initIds
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_net_VMNetworkInterface
+ * Method: getVMInterfaces
+ * Signature: ()[Ljava/net/VMNetworkInterface;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_net_VMNetworkInterface_getVMInterfaces
+ (JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
-
-#endif /* __java_net_VMNetworkInterface__ */
+#endif
Index: java/net/NetworkInterface.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/net/NetworkInterface.java,v
retrieving revision 1.18
diff -u -r1.18 NetworkInterface.java
--- java/net/NetworkInterface.java 29 Aug 2006 08:25:15 -0000 1.18
+++ java/net/NetworkInterface.java 9 Sep 2006 19:01:14 -0000
@@ -38,6 +38,8 @@
package java.net;
+import gnu.classpath.SystemProperties;
+
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
@@ -58,25 +60,13 @@
*/
public final class NetworkInterface
{
- private String name;
- private Vector inetAddresses;
-
- NetworkInterface(String name, InetAddress address)
- {
- this.name = name;
- this.inetAddresses = new Vector(1, 1);
- this.inetAddresses.add(address);
- }
+ private final VMNetworkInterface netif;
- NetworkInterface(String name, InetAddress[] addresses)
+ private NetworkInterface(VMNetworkInterface netif)
{
- this.name = name;
- this.inetAddresses = new Vector(addresses.length, 1);
-
- for (int i = 0; i < addresses.length; i++)
- this.inetAddresses.add(addresses[i]);
+ this.netif = netif;
}
-
+
/**
* Returns the name of the network interface
*
@@ -84,7 +74,7 @@
*/
public String getName()
{
- return name;
+ return netif.name;
}
/**
@@ -100,6 +90,7 @@
public Enumeration getInetAddresses()
{
SecurityManager s = System.getSecurityManager();
+ Vector inetAddresses = new Vector(netif.addresses);
if (s == null)
return inetAddresses.elements();
@@ -131,7 +122,7 @@
*/
public String getDisplayName()
{
- return name;
+ return netif.name;
}
/**
@@ -148,15 +139,14 @@
public static NetworkInterface getByName(String name)
throws SocketException
{
- for (Enumeration e = getNetworkInterfaces(); e.hasMoreElements();)
+ if (name == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
{
- NetworkInterface tmp = (NetworkInterface) e.nextElement();
-
- if (name.equals(tmp.getName()))
- return tmp;
+ if (netifs[i].name.equals(name))
+ return new NetworkInterface(netifs[i]);
}
-
- // No interface with the given name found.
return null;
}
@@ -173,55 +163,15 @@
public static NetworkInterface getByInetAddress(InetAddress addr)
throws SocketException
{
- for (Enumeration interfaces = getNetworkInterfaces();
- interfaces.hasMoreElements();)
+ if (addr == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
{
- NetworkInterface tmp = (NetworkInterface) interfaces.nextElement();
-
- for (Enumeration addresses = tmp.inetAddresses.elements();
- addresses.hasMoreElements();)
- {
- if (addr.equals((InetAddress) addresses.nextElement()))
- return tmp;
- }
+ if (netifs[i].addresses.contains(addr))
+ return new NetworkInterface(netifs[i]);
}
-
- throw new SocketException("no network interface is bound to such an IP
address");
- }
-
- static private Collection condense(Collection interfaces)
- {
- final Map condensed = new HashMap();
-
- final Iterator interfs = interfaces.iterator();
- while (interfs.hasNext()) {
-
- final NetworkInterface face = (NetworkInterface) interfs.next();
- final String name = face.getName();
-
- if (condensed.containsKey(name))
- {
- final NetworkInterface conface = (NetworkInterface)
condensed.get(name);
- if (!conface.inetAddresses.containsAll(face.inetAddresses))
- {
- final Iterator faceAddresses = face.inetAddresses.iterator();
- while (faceAddresses.hasNext())
- {
- final InetAddress faceAddress = (InetAddress)
faceAddresses.next();
- if (!conface.inetAddresses.contains(faceAddress))
- {
- conface.inetAddresses.add(faceAddress);
- }
- }
- }
- }
- else
- {
- condensed.put(name, face);
- }
- }
-
- return condensed.values();
+ return null;
}
/**
@@ -233,14 +183,14 @@
*/
public static Enumeration getNetworkInterfaces() throws SocketException
{
- Vector networkInterfaces = VMNetworkInterface.getInterfaces();
-
- if (networkInterfaces.isEmpty())
- return null;
-
- Collection condensed = condense(networkInterfaces);
-
- return Collections.enumeration(condensed);
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ Vector networkInterfaces = new Vector(netifs.length);
+ for (int i = 0; i < netifs.length; i++)
+ {
+ if (!netifs[i].addresses.isEmpty())
+ networkInterfaces.add(new NetworkInterface(netifs[i]));
+ }
+ return networkInterfaces.elements();
}
/**
@@ -257,7 +207,8 @@
NetworkInterface tmp = (NetworkInterface) obj;
- return (name.equals(tmp.name) && inetAddresses.equals(tmp.inetAddresses));
+ return (netif.name.equals(tmp.netif.name)
+ && (netif.addresses.equals(tmp.netif.addresses)));
}
/**
@@ -268,7 +219,7 @@
public int hashCode()
{
// FIXME: hash correctly
- return name.hashCode() + inetAddresses.hashCode();
+ return netif.name.hashCode() + netif.addresses.hashCode();
}
/**
@@ -279,19 +230,22 @@
public String toString()
{
// FIXME: check if this is correct
- String result;
- String separator = System.getProperty("line.separator");
+ StringBuffer result;
+ String separator = SystemProperties.getProperty("line.separator");
- result =
- "name: " + getDisplayName() + " (" + getName() + ") addresses:"
- + separator;
+ result = new StringBuffer();
+
+ result.append("name: ");
+ result.append(getDisplayName());
+ result.append(" (").append(getName()).append(") addresses:");
+ result.append(separator);
- for (Enumeration e = inetAddresses.elements(); e.hasMoreElements();)
+ for (Iterator it = netif.addresses.iterator(); it.hasNext(); )
{
- InetAddress address = (InetAddress) e.nextElement();
- result += address.toString() + ";" + separator;
+ InetAddress address = (InetAddress) it.next();
+ result.append(address.toString()).append(";").append(separator);
}
- return result;
+ return result.toString();
}
}
Index: vm/reference/java/net/VMNetworkInterface.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/vm/reference/java/net/VMNetworkInterface.java,v
retrieving revision 1.4
diff -u -r1.4 VMNetworkInterface.java
--- vm/reference/java/net/VMNetworkInterface.java 2 Mar 2006 00:36:44
-0000 1.4
+++ vm/reference/java/net/VMNetworkInterface.java 9 Sep 2006 19:01:14
-0000
@@ -40,6 +40,9 @@
import gnu.classpath.Configuration;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.Set;
import java.util.Vector;
/**
@@ -54,22 +57,50 @@
*/
final class VMNetworkInterface
{
+ String name;
+ Set addresses;
+
+ VMNetworkInterface(String name)
+ {
+ this.name = name;
+ addresses = new HashSet();
+ }
+
static
- {
- if (Configuration.INIT_LOAD_LIBRARY)
- System.loadLibrary("javanet");
- }
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ System.loadLibrary("javanet");
+
+ initIds();
+ }
+
+ private static native void initIds();
/**
- * Returns a Vector of InetAddresses. The returned value will be
- * 'condensed', meaning that all elements with the same interface
- * name will be collapesed into one InetAddress for that name
- * containing all addresses before the returning the result to the
- * user. This means the native method can be implemented in a naive
- * way mapping each address/interface to a name even if that means
- * that the Vector contains multiple InetAddresses with the same
- * interface name.
+ * Return a list of VM network interface objects.
+ *
+ * @return The list of network interfaces.
+ * @throws SocketException
*/
- public static native Vector getInterfaces()
+ public static native VMNetworkInterface[] getVMInterfaces()
throws SocketException;
+
+ private void addAddress(ByteBuffer addr)
+ throws SocketException, UnknownHostException
+ {
+ if (addr.remaining() == 4)
+ {
+ byte[] ipv4 = new byte[4];
+ addr.get(ipv4);
+ addresses.add(Inet4Address.getByAddress(ipv4));
+ }
+ else if (addr.remaining() == 16)
+ {
+ byte[] ipv6 = new byte[16];
+ addr.get(ipv6);
+ addresses.add(Inet6Address.getByAddress(ipv6));
+ }
+ else
+ throw new SocketException("invalid interface address");
+ }
}
Index: native/jni/classpath/jcl.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/classpath/jcl.c,v
retrieving revision 1.23
diff -u -r1.23 jcl.c
--- native/jni/classpath/jcl.c 3 Apr 2006 14:03:12 -0000 1.23
+++ native/jni/classpath/jcl.c 9 Sep 2006 19:01:14 -0000
@@ -186,90 +186,113 @@
* Build a Pointer object. The function caches the class type
*/
-static jclass rawDataClass;
-static jfieldID rawData_fid;
-static jmethodID rawData_mid;
+/* Note, caching these values doesn't work. On jamvm, for example,
+ this fails if you use the JNI call NewDirectBuffer, because it
+ doesn't use JCL_NewRawDataObject, and thus these ID classes may not
+ have been filled in. This code is also not thread-safe. */
+
+/* static jclass rawDataClass; */
+/* static jfieldID rawData_fid; */
+/* static jmethodID rawData_mid; */
JNIEXPORT jobject JNICALL
JCL_NewRawDataObject (JNIEnv * env, void *data)
{
+ jclass rawDataClass;
+ jmethodID rawData_mid;
+ jobject ret;
+
+#if SIZEOF_VOID_P == 8
+ rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
if (rawDataClass == NULL)
{
- jclass tmp;
-#if SIZEOF_VOID_P == 8
- rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
- if (rawDataClass == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal class");
- return NULL;
- }
-
- rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(J)V");
- if (rawData_mid == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal constructor");
- return NULL;
- }
-
- rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "J");
- if (rawData_fid == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal field");
- return NULL;
- }
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal class");
+ return NULL;
+ }
+
+ rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(J)V");
+ if (rawData_mid == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal constructor");
+ return NULL;
+ }
#else
- rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer32");
- if (rawDataClass == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal class");
- return NULL;
- }
-
- rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(I)V");
- if (rawData_mid == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal constructor");
- return NULL;
- }
-
- rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "I");
- if (rawData_fid == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to find internal field");
- return NULL;
- }
+ rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer32");
+ if (rawDataClass == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal class");
+ return NULL;
+ }
-#endif
- tmp = (*env)->NewGlobalRef (env, rawDataClass);
- if (tmp == NULL)
- {
- JCL_ThrowException (env, "java/lang/InternalError",
- "unable to create an internal global ref");
- return NULL;
- }
- (*env)->DeleteLocalRef(env, rawDataClass);
- rawDataClass = tmp;
+ rawData_mid = (*env)->GetMethodID (env, rawDataClass, "<init>", "(I)V");
+ if (rawData_mid == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal constructor");
+ return NULL;
}
+#endif
#if SIZEOF_VOID_P == 8
- return (*env)->NewObject (env, rawDataClass, rawData_mid, (jlong) data);
+ ret = (*env)->NewObject (env, rawDataClass, rawData_mid, (jlong) data);
#else
- return (*env)->NewObject (env, rawDataClass, rawData_mid, (jint) data);
+ ret = (*env)->NewObject (env, rawDataClass, rawData_mid, (jint) data);
#endif
+
+ (*env)->DeleteLocalRef (env, rawDataClass);
+ return ret;
}
JNIEXPORT void * JNICALL
JCL_GetRawData (JNIEnv * env, jobject rawdata)
{
+ jclass rawDataClass;
+ jfieldID rawData_fid;
+ jobject ret;
+
#if SIZEOF_VOID_P == 8
- return (void *) (*env)->GetLongField (env, rawdata, rawData_fid);
+ rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
+ if (rawDataClass == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal class");
+ return NULL;
+ }
+
+ rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "J");
+ if (rawData_fid == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal field");
+ return NULL;
+ }
+#else
+ rawDataClass = (*env)->FindClass (env, "gnu/classpath/Pointer32");
+ if (rawDataClass == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal class");
+ return NULL;
+ }
+
+ rawData_fid = (*env)->GetFieldID (env, rawDataClass, "data", "I");
+ if (rawData_fid == NULL)
+ {
+ JCL_ThrowException (env, "java/lang/InternalError",
+ "unable to find internal field");
+ return NULL;
+ }
+#endif
+
+#if SIZEOF_VOID_P == 8
+ ret = (void *) (*env)->GetLongField (env, rawdata, rawData_fid);
#else
- return (void *) (*env)->GetIntField (env, rawdata, rawData_fid);
-#endif
+ ret = (void *) (*env)->GetIntField (env, rawdata, rawData_fid);
+#endif
+
+ (*env)->DeleteLocalRef (env, rawDataClass);
+ return ret;
}
Index: native/jni/java-net/java_net_VMNetworkInterface.c
===================================================================
RCS file:
/cvsroot/classpath/classpath/native/jni/java-net/java_net_VMNetworkInterface.c,v
retrieving revision 1.3
diff -u -r1.3 java_net_VMNetworkInterface.c
--- native/jni/java-net/java_net_VMNetworkInterface.c 12 Jan 2006 09:37:31
-0000 1.3
+++ native/jni/java-net/java_net_VMNetworkInterface.c 9 Sep 2006 19:01:14
-0000
@@ -35,9 +35,15 @@
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-/* do not move; needed here because of some macro definitions */
+#ifdef HAVE_CONFIG_H
#include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -47,19 +53,197 @@
#include "java_net_VMNetworkInterface.h"
-#include "javanet.h"
+
+static jmethodID java_net_VMNetworkInterface_init;
+static jmethodID java_net_VMNetworkInterface_addAddress;
+
+/*
+ * Initialize our static method ID's.
+ *
+ * Class: java_net_VMNetworkInterface
+ * Method: initIds
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_VMNetworkInterface_initIds (JNIEnv *env, jclass clazz)
+{
+ java_net_VMNetworkInterface_init =
+ (*env)->GetMethodID (env, clazz, "<init>", "(Ljava/lang/String;)V");
+ if (java_net_VMNetworkInterface_init == NULL)
+ {
+ if (!(*env)->ExceptionCheck (env))
+ JCL_ThrowException (env, "java/lang/NoSuchMethodError",
+ "VMNetworkinterface.addAddress");
+ return;
+ }
+ java_net_VMNetworkInterface_addAddress =
+ (*env)->GetMethodID (env, clazz, "addAddress", "(Ljava/nio/ByteBuffer;)V");
+ if (java_net_VMNetworkInterface_addAddress == NULL)
+ {
+ if (!(*env)->ExceptionCheck (env))
+ JCL_ThrowException (env, "java/lang/NoSuchMethodError",
+ "VMNetworkinterface.addAddress");
+ }
+}
+
+struct netif_entry
+{
+ char *name;
+ jobject netif;
+ int numaddrs;
+ struct netif_entry *next;
+};
+
+static void
+free_netif_list (JNIEnv *env, struct netif_entry *list)
+{
+ while (list != NULL)
+ {
+ struct netif_entry *e = list->next;
+ JCL_free (env, list);
+ list = e;
+ }
+}
/*
- * Returns all local network interfaces as vector
+ * Returns all local network interfaces as an array.
*/
-JNIEXPORT jobject JNICALL
-Java_java_net_VMNetworkInterface_getInterfaces (JNIEnv * env,
- jclass class
- __attribute__ ((__unused__)))
+JNIEXPORT jobjectArray JNICALL
+Java_java_net_VMNetworkInterface_getVMInterfaces (JNIEnv * env, jclass clazz)
{
- JCL_ThrowException (env, IO_EXCEPTION,
- "java.net.VMNetworkInterface.getInterfaces(): not
implemented");
- return 0;
+#ifdef HAVE_GETIFADDRS
+ struct ifaddrs *ifaddrs, *i;
+ struct netif_entry *iflist = NULL, *e;
+ jobjectArray netifs;
+ int numifs = 0;
+ int k;
+
+ if (getifaddrs (&ifaddrs) == -1)
+ {
+ JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
+ return NULL;
+ }
+
+ for (i = ifaddrs; i != NULL; i = i->ifa_next)
+ {
+ if (iflist == NULL)
+ {
+ iflist = JCL_malloc (env, sizeof (struct netif_entry));
+ if (iflist == NULL)
+ {
+ freeifaddrs (ifaddrs);
+ return NULL;
+ }
+ iflist->name = i->ifa_name;
+ iflist->numaddrs = 0;
+ iflist->next = NULL;
+ iflist->netif = (*env)->NewObject (env, clazz,
java_net_VMNetworkInterface_init,
+ (*env)->NewStringUTF (env,
i->ifa_name));
+ if (iflist->netif == NULL)
+ {
+ freeifaddrs (ifaddrs);
+ JCL_free (env, iflist);
+ return NULL;
+ }
+ e = iflist;
+ }
+ else
+ {
+ struct netif_entry *p = NULL;
+ for (e = iflist; e != NULL; e = e->next)
+ {
+ if (strcmp (e->name, i->ifa_name) == 0)
+ break;
+ p = e;
+ }
+
+ if (e == NULL)
+ {
+ p->next = (struct netif_entry *) JCL_malloc (env, sizeof (struct
netif_entry));
+ if (p->next == NULL)
+ {
+ free_netif_list (env, iflist);
+ freeifaddrs (ifaddrs);
+ return NULL;
+ }
+ e = p->next;
+ e->name = i->ifa_name;
+ e->numaddrs = 0;
+ e->next = NULL;
+ e->netif = (*env)->NewObject (env, clazz,
java_net_VMNetworkInterface_init,
+ (*env)->NewStringUTF (env,
i->ifa_name));
+ if (e->netif == NULL)
+ {
+ free_netif_list (env, iflist);
+ freeifaddrs (ifaddrs);
+ return NULL;
+ }
+ }
+ }
+
+ if (i->ifa_addr == NULL)
+ continue;
+
+ if (i->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *) i->ifa_addr;
+ jobject buffer = (*env)->NewDirectByteBuffer (env,
&(sin->sin_addr.s_addr), 4);
+ (*env)->CallVoidMethod (env, e->netif,
java_net_VMNetworkInterface_addAddress,
+ buffer);
+ if ((*env)->ExceptionCheck (env))
+ {
+ free_netif_list (env, iflist);
+ freeifaddrs (ifaddrs);
+ return NULL;
+ }
+ (*env)->DeleteLocalRef (env, buffer);
+ e->numaddrs++;
+ }
+#ifdef HAVE_INET6
+ else if (i->ifa_addr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) i->ifa_addr;
+ jobject buffer = (*env)->NewDirectByteBuffer (env,
&(sin->sin6_addr.s6_addr), 16);
+ (*env)->CallVoidMethod (env, e->netif,
java_net_VMNetworkInterface_addAddress,
+ buffer);
+ if ((*env)->ExceptionCheck (env))
+ {
+ free_netif_list (env, iflist);
+ freeifaddrs (ifaddrs);
+ return NULL;
+ }
+ (*env)->DeleteLocalRef (env, buffer);
+ e->numaddrs++;
+ }
+#endif /* HAVE_INET6 */
+ }
+
+ /* Count how many interfaces we have that have addresses. */
+ for (e = iflist; e != NULL; e = e->next)
+ {
+ if (e->numaddrs != 0)
+ numifs++;
+ }
+
+ netifs = (*env)->NewObjectArray (env, numifs, clazz, NULL);
+ k = 0;
+ for (e = iflist; e != NULL && k < numifs; e = e->next)
+ {
+ if (e->numaddrs != 0)
+ {
+ (*env)->SetObjectArrayElement (env, netifs, k, e->netif);
+ (*env)->DeleteLocalRef (env, e->netif);
+ k++;
+ }
+ }
+
+ free_netif_list (env, iflist);
+ freeifaddrs (ifaddrs);
+ return netifs;
+#else
+ JCL_ThrowException (env, "java/net/SocketException", "getifaddrs not
supported");
+ return NULL;
+#endif /* HAVE_GETIFADDRS */
}
/* end of file */