$OpenBSD: patch-jdk_src_solaris_native_java_net_NetworkInterface_c,v 1.3 2009/05/23 03:03:25 kurt Exp $
--- jdk/src/solaris/native/java/net/NetworkInterface.c.orig	Fri May  8 03:35:07 2009
+++ jdk/src/solaris/native/java/net/NetworkInterface.c	Mon May 18 19:36:07 2009
@@ -23,13 +23,13 @@
  * have any questions.
  */
 
+#include <sys/types.h>
+#include <sys/socket.h>
 #include <errno.h>
 #include <strings.h>
 #include <netinet/in.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
@@ -47,6 +47,21 @@
 #else
 #include <sys/sockio.h>
 #endif
+#if defined(_ALLBSD_SOURCE)
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#if defined(__FreeBSD__) || defined(__APPLE__)
+#include <net/ethernet.h>
+#include <net/if_var.h>
+#elif defined(__OpenBSD__)
+#include <netinet/if_ether.h>
+#elif defined(__NetBSD__)
+#include <net/if_ether.h>
+#endif
+#include <net/if_dl.h>
+#include <netinet/in_var.h>
+#include <ifaddrs.h>
+#endif
 
 #ifdef __linux__
 #define ifr_index ifr_ifindex
@@ -583,6 +598,7 @@ static netif *enumInterfaces(JNIEnv *env) {
 }
 
 
+#if !defined(_ALLBSD_SOURCE)
 /*
  * Enumerates and returns all IPv4 interfaces
  */
@@ -693,7 +709,177 @@ static netif *enumIPv4Interfaces(JNIEnv *env, netif *i
     return ifs;
 }
 
+#else /* _ALLBSD_SOURCE */
+ 
+/*
+ * Enumerates and returns all IPv4 interfaces
+ *
+ * WARNING! Make sure that it's correctly synchronized on future JDK
+ * versions imports!
+ */
+static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs)
+{
+    int sock;
+    struct ifaddrs *ifa, *origifa;
 
+    sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+	/*
+	 * If EPROTONOSUPPORT is returned it means we don't have
+	 * IPv4 support so don't throw an exception.
+	 */
+	if (errno != EPROTONOSUPPORT) {
+	    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                             "Socket creation failed");
+	}
+	return ifs;
+    }
+
+    if (getifaddrs(&origifa) != 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                         "getifaddrs() function failed");
+	close(sock);
+	return ifs;
+    }
+
+    for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
+
+	/*
+	 * Skip non-AF_INET entries.
+	 */
+	if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
+	    continue;
+
+	/*
+	 * Add to the list.
+	 *
+	 * BSDNOTE: in order to optimize code, interface index detection
+	 * logic was added directly to addif().
+	 */
+	ifs = addif(env, ifs, ifa->ifa_name, (-1), AF_INET,
+		    ifa->ifa_addr, sizeof(struct sockaddr_in), 0);
+
+	/*
+	 * If an exception occurred then free the list.
+	 */
+	if ((*env)->ExceptionOccurred(env)) {
+	    close(sock);
+	    freeifaddrs(origifa);
+	    freeif(ifs);
+	    return NULL;
+	}
+    }
+
+    /*
+     * Free socket and buffer
+     */
+    close(sock);
+    freeifaddrs(origifa);
+    return ifs;
+}
+
+#if defined(AF_INET6)
+/*
+ * Determines the prefix on BSD for IPv6 interfaces.
+ */
+static
+int prefix(void *val, int size) {
+    u_char *name = (u_char *)val;
+    int byte, bit, plen = 0;
+
+    for (byte = 0; byte < size; byte++, plen += 8)
+        if (name[byte] != 0xff)
+            break;
+    if (byte == size)
+        return (plen);
+    for (bit = 7; bit != 0; bit--, plen++)
+        if (!(name[byte] & (1 << bit)))
+            break;
+    for (; bit != 0; bit--)
+        if (name[byte] & (1 << bit))
+            return (0);
+    byte++;
+    for (; byte < size; byte++)
+        if (name[byte])
+            return (0);
+    return (plen);
+}
+
+/*
+ * Enumerates and returns all IPv6 interfaces on FreeBSD
+ *
+ * BSDNOTE: it's done in same as IPv4 enumeration and should be carefully
+ *          reviewed with each JDK update (according to Solaris/Linux version)
+ */
+static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
+
+    int sock;
+    struct ifaddrs *ifa, *origifa;
+    struct sockaddr_in6 *sin6;
+    struct in6_ifreq ifr6;
+
+    // Open IPv6 UDP socket.
+    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+    if (sock < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                     "Failed to create IPv6 socket");
+        return ifs;
+    }
+
+    if (getifaddrs(&origifa) != 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                         "getifaddrs() function failed");
+	close(sock);
+	return ifs;
+    }
+
+    for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
+
+	/*
+	 * Skip non-AF_INET6 entries.
+	 */
+	if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
+	    continue;
+
+	memset(&ifr6, 0, sizeof(ifr6));
+	strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
+	memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
+
+	if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
+	    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                             "ioctl SIOCGIFNETMASK_IN6 failed");
+	    close(sock);
+	    freeifaddrs(origifa);
+	    freeif(ifs);
+	    return NULL;
+	}
+
+	/* Add to the list.  */
+	sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
+	ifs = addif(env, ifs, ifa->ifa_name, (-1), AF_INET6,
+	            ifa->ifa_addr, sizeof(struct sockaddr_in6),
+		    prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
+
+	/* If an exception occurred then free the list.  */
+	if ((*env)->ExceptionOccurred(env)) {
+	    close(sock);
+	    freeifaddrs(origifa);
+	    freeif(ifs);
+	    return NULL;
+	}
+    }
+
+    /*
+     * Free socket and ifaddrs buffer
+     */
+    close(sock);
+    freeifaddrs(origifa);
+    return ifs;
+}
+#endif /* AF_INET6 */
+
+#endif /* !_ALLBSD_SOURCE */
+
 #if defined(__solaris__) && defined(AF_INET6)
 /*
  * Enumerates and returns all IPv6 interfaces on Solaris
@@ -1036,7 +1222,13 @@ netif *addif(JNIEnv *env, netif *ifs, char *if_name, i
             JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
             return ifs;
         }
+#if defined(_ALLBSD_SOURCE)
+	currif->index = if_nametoindex(name);
+	if (currif->index == 0)
+	    currif->index = -1;
+#else
         currif->index = index;
+#endif
         currif->addr = NULL;
         currif->childs = NULL;
         currif->virtual = isVirtual;
@@ -1347,6 +1539,31 @@ int getMacAddress(JNIEnv *env, const struct in_addr* a
    * All bytes to 0 means no hardware address.
    */
   return -1;
+#elif defined(_ALLBSD_SOURCE)
+  struct ifaddrs *ifa0, *ifa;
+  struct sockaddr *saddr;
+  int i;
+
+  /* Grab the interface list */
+  if (!getifaddrs(&ifa0)) {
+    /* Cycle through the interfaces */
+    for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
+      saddr = ifa->ifa_addr;
+      /* Link layer contains the MAC address */
+      if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
+        struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
+        /* Check the address is the correct length */
+        if (sadl->sdl_alen == ETHER_ADDR_LEN) {
+           memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
+           freeifaddrs(ifa0);
+           return ETHER_ADDR_LEN;
+        }
+      }
+    }
+    freeifaddrs(ifa0);
+  }
+
+  return -1;
 #else
   struct arpreq arpreq;
   struct sockaddr_in* sin;
@@ -1512,7 +1729,7 @@ JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_
                                  "Socket creation failed");
   } else {
 
-#ifdef __linux__
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
     memset((char *) &if2, 0, sizeof(if2));
     strcpy(if2.ifr_name, name_utf);
 
