src/solaris/native/java/net/NetworkInterface.c

Print this page
rev 8725 : 8024854: Basic changes and files to build the class library on AIX
Contributed-by: luchsh@linux.vnet.ibm.com, spoole@linux.vnet.ibm.com, thomas.stuefe@sap.com
Reviewed-by: alanb, prr, sla, chegar, michaelm, mullan

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -50,10 +50,17 @@
 #include <bits/ioctls.h>
 #include <sys/utsname.h>
 #include <stdio.h>
 #endif
 
+#if defined(_AIX)
+#include <sys/ioctl.h>
+#include <netinet/in6_var.h>
+#include <sys/ndd_var.h>
+#include <sys/kinfo.h>
+#endif
+
 #ifdef __linux__
 #define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
 #endif
 
 #if defined(_ALLBSD_SOURCE)

@@ -1039,12 +1046,12 @@
 
     return sock;
 }
 
 
-/** Linux **/
-#ifdef __linux__
+/** Linux, AIX **/
+#if defined(__linux__) || defined(_AIX)
 /* Open socket for further ioct calls, try v4 socket first and
  * if it falls return v6 socket
  */
 
 #ifdef AF_INET6

@@ -1078,38 +1085,53 @@
 #endif
 
 static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
     struct ifconf ifc;
     struct ifreq *ifreqP;
-    char *buf;
+    char *buf = NULL;
     int numifs;
     unsigned i;
+    int siocgifconfRequest = SIOCGIFCONF;
 
 
+#if defined(__linux__)
     /* need to do a dummy SIOCGIFCONF to determine the buffer size.
      * SIOCGIFCOUNT doesn't work
      */
     ifc.ifc_buf = NULL;
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
         return ifs;
     }
+#elif defined(_AIX)
+    ifc.ifc_buf = NULL;
+    if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGSIZIFCONF failed");
+        return ifs;
+    }
+#endif /* __linux__ */
 
     CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
 
     ifc.ifc_buf = buf;
-    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+#if defined(_AIX)
+    siocgifconfRequest = CSIOCGIFCONF;
+#endif
+    if (ioctl(sock, siocgifconfRequest, (char *)&ifc) < 0) {
         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
         (void) free(buf);
         return ifs;
     }
 
     /*
      * Iterate through each interface
      */
     ifreqP = ifc.ifc_req;
     for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+#if defined(_AIX)
+        if (ifreqP->ifr_addr.sa_family != AF_INET) continue;
+#endif
         /*
          * Add to the list
          */
         ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
 

@@ -1133,11 +1155,11 @@
 
 /*
  * Enumerates and returns all IPv6 interfaces on Linux
  */
 
-#ifdef AF_INET6
+#if defined(AF_INET6) && defined(__linux__)
 static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
     FILE *f;
     char addr6[40], devname[21];
     char addr6p[8][5];
     int plen, scope, dad_status, if_idx;

@@ -1177,23 +1199,116 @@
     return ifs;
 }
 #endif
 
 
+/*
+ * Enumerates and returns all IPv6 interfaces on AIX
+ */
+
+#if defined(AF_INET6) && defined(_AIX)
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    struct ifconf ifc;
+    struct ifreq *ifreqP;
+    char *buf;
+    int numifs;
+    unsigned i;
+    unsigned bufsize;
+    char *cp, *cplimit;
+
+    /* use SIOCGSIZIFCONF to get size for  SIOCGIFCONF */
+
+    ifc.ifc_buf = NULL;
+    if (ioctl(sock, SIOCGSIZIFCONF, &(ifc.ifc_len)) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                        "ioctl SIOCGSIZIFCONF failed");
+        return ifs;
+    }
+    bufsize = ifc.ifc_len;
+
+    buf = (char *)malloc(bufsize);
+    if (!buf) {
+        JNU_ThrowOutOfMemoryError(env, "Network interface native buffer allocation failed");
+        return ifs;
+    }
+    ifc.ifc_len = bufsize;
+    ifc.ifc_buf = buf;
+    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                       "ioctl CSIOCGIFCONF failed");
+        free(buf);
+        return ifs;
+    }
+
+    /*
+     * Iterate through each interface
+     */
+    ifreqP = ifc.ifc_req;
+    cp = (char *)ifc.ifc_req;
+    cplimit = cp + ifc.ifc_len;
+
+    for ( ; cp < cplimit; cp += (sizeof(ifreqP->ifr_name) + MAX((ifreqP->ifr_addr).sa_len, sizeof(ifreqP->ifr_addr)))) {
+        ifreqP = (struct ifreq *)cp;
+        struct ifreq if2;
+
+        memset((char *)&if2, 0, sizeof(if2));
+        strcpy(if2.ifr_name, ifreqP->ifr_name);
+
+        /*
+         * Skip interface that aren't UP
+         */
+        if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
+            if (!(if2.ifr_flags & IFF_UP)) {
+                continue;
+            }
+        }
+
+        if (ifreqP->ifr_addr.sa_family != AF_INET6)
+            continue;
+
+        /*
+         * Add to the list
+         */
+        ifs = addif(env, sock, ifreqP->ifr_name, ifs,
+                    (struct sockaddr *)&(ifreqP->ifr_addr),
+                     AF_INET6, 0);
+
+        /*
+         * If an exception occurred then free the list
+         */
+        if ((*env)->ExceptionOccurred(env)) {
+            free(buf);
+            freeif(ifs);
+            return NULL;
+        }
+    }
+
+    /*
+     * Free socket and buffer
+     */
+    free(buf);
+    return ifs;
+}
+#endif
+
+
 static int getIndex(int sock, const char *name){
      /*
       * Try to get the interface index
-      * (Not supported on Solaris 2.6 or 7)
       */
+#if defined(_AIX)
+    return if_nametoindex(name);
+#else
     struct ifreq if2;
     strcpy(if2.ifr_name, name);
 
     if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
         return -1;
     }
 
     return if2.ifr_ifindex;
+#endif
 }
 
 /**
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.

@@ -1256,10 +1371,50 @@
  * Get the Hardware address (usually MAC address) for the named interface.
  * return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
 static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+#if defined (_AIX)
+    int size;
+    struct kinfo_ndd *nddp;
+    void *end;
+
+    size = getkerninfo(KINFO_NDD, 0, 0, 0);
+    if (size == 0) {
+        return -1;
+    }
+
+    if (size < 0) {
+        perror("getkerninfo 1");
+        return -1;
+    }
+
+    nddp = (struct kinfo_ndd *)malloc(size);
+
+    if (!nddp) {
+        return -1;
+    }
+
+    if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
+        perror("getkerninfo 2");
+        return -1;
+    }
+
+    end = (void *)nddp + size;
+    while ((void *)nddp < end) {
+        if (!strcmp(nddp->ndd_alias, ifname) ||
+                !strcmp(nddp->ndd_name, ifname)) {
+            bcopy(nddp->ndd_addr, buf, 6);
+            return 6;
+        } else {
+            nddp++;
+        }
+    }
+
+    return -1;
+
+#elif defined(__linux__)
     static struct ifreq ifr;
     int i;
 
     strcpy(ifr.ifr_name, ifname);
     if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {

@@ -1277,10 +1432,11 @@
         if (buf[i] != 0)
             return IFHWADDRLEN;
     }
 
     return -1;
+#endif
 }
 
 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
     struct ifreq if2;