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;