Author: mladen.turk(a)jboss.com
Date: 2007-09-12 11:15:56 -0400 (Wed, 12 Sep 2007)
New Revision: 1021
Modified:
trunk/sight/native/include/sight_types.h
trunk/sight/native/os/linux/netadapter.c
Log:
Implement Linux NetworkAdapter - stage 2
Modified: trunk/sight/native/include/sight_types.h
===================================================================
--- trunk/sight/native/include/sight_types.h 2007-09-11 17:18:14 UTC (rev 1020)
+++ trunk/sight/native/include/sight_types.h 2007-09-12 15:15:56 UTC (rev 1021)
@@ -216,7 +216,10 @@
#define SIGHT_TCP_TIME_WAIT 11
#define SIGHT_TCP_DELETE_TCB 12
+#define SIGHT_IFO_UP 1
+#define SIGHT_IFO_DOWN 2
+
#ifdef __cplusplus
}
#endif
Modified: trunk/sight/native/os/linux/netadapter.c
===================================================================
--- trunk/sight/native/os/linux/netadapter.c 2007-09-11 17:18:14 UTC (rev 1020)
+++ trunk/sight/native/os/linux/netadapter.c 2007-09-12 15:15:56 UTC (rev 1021)
@@ -143,9 +143,17 @@
}
#define PROC_INET6_FILE "/proc/net/if_inet6"
+#define PROC_NET_DEV "/proc/net/dev"
typedef struct net_ifc_data_t {
int type;
+ int index;
+ int flags;
+ char ip4a[128];
+ char ip6a[128];
+ char maca[64];
+ char mask[64];
+ char badr[64];
} net_ifc_data_t;
typedef struct net_adapter_enum_t {
@@ -159,19 +167,48 @@
{
net_ifc_data_t *d = (net_ifc_data_t *)data;
if (d) {
-
free(d);
}
}
+static char *hex_base = "0123456789abcdefx";
+
+static void make_mac(void *data, char *dest)
+{
+ int i, j = 0;
+ unsigned char buf[IFHWADDRLEN];
+ char *sp = dest;
+
+ memcpy(buf, data, IFHWADDRLEN);
+ *dest = '\0';
+ for (i = 0; i < IFHWADDRLEN; i++) {
+ if (buf[i]) {
+ j = 1;
+ break;
+ }
+ }
+ if (!j)
+ return;
+ for (i = 0; i < IFHWADDRLEN - 1; i++) {
+ *sp++ = hex_base[buf[i] >> 4];
+ *sp++ = hex_base[buf[i] & 0x0f];
+ *sp++ = ':';
+ }
+ *sp++ = hex_base[buf[i] >> 4];
+ *sp++ = hex_base[buf[i] & 0x0f];
+ *sp++ = '\0';
+}
+
SIGHT_EXPORT_DECLARE(jlong, NetworkAdapter, enum0)(SIGHT_STDARGS,
jlong pool)
{
net_adapter_enum_t *e;
- int i;
+ int i, j;
struct ifconf ifc;
struct ifreq *ifr;
sight_arr_t *i6a;
+ sight_arr_t *i4a;
+ net_ifc_data_t *id;
UNREFERENCED_O;
UNREFERENCED(pool);
@@ -190,6 +227,7 @@
throwAprException(_E, apr_get_os_error());
goto cleanup;
}
+
ifc.ifc_buf = NULL;
if (ioctl(e->sd, SIOCGIFCONF, (char *)&ifc) < 0) {
throwAprException(_E, apr_get_os_error());
@@ -207,47 +245,154 @@
ifr = ifc.ifc_req;
for (i = 0; i < ifc.ifc_len; i += sizeof(struct ifreq), ifr++) {
cache_entry_t *ce;
+ char las[128] = "";
+ struct sockaddr_in *sa;
+ printf("IPV4: %10s\n", ifr->ifr_name);
+
+ sa = (struct sockaddr_in *)&ifr->ifr_addr;
+ inet_ntop(AF_INET, &sa->sin_addr, las, 64);
ce = cache_add(e->ifc, ifr->ifr_name);
- if (!ce->data) {
- net_ifc_data_t *id;
+ if (!(id = (net_ifc_data_t *)ce->data)) {
+ struct ifreq ifi;
if (!(id = (net_ifc_data_t *)sight_calloc(_E,
sizeof(net_ifc_data_t),
THROW_FMARK))) {
free(ifc.ifc_buf);
goto cleanup;
}
+ memset(&ifi, 0, sizeof(struct ifreq));
+ strcpy(ifi.ifr_name, ifr->ifr_name);
+
+ if (ioctl(e->sd, SIOCGIFINDEX, (char *)&ifi) < 0) {
+ throwAprException(_E, apr_get_os_error());
+ free(ifc.ifc_buf);
+ free(id);
+ goto cleanup;
+ }
+ id->index = ifi.ifr_ifindex;
+
+ if (ioctl(e->sd, SIOCGIFFLAGS, (char *)&ifi) < 0) {
+ throwAprException(_E, apr_get_os_error());
+ free(ifc.ifc_buf);
+ free(id);
+ goto cleanup;
+ }
+ id->flags = ifi.ifr_flags;
+ strcpy(id->ip4a, las);
+
+ if (ioctl(e->sd, SIOCGIFHWADDR, (char *)&ifi) >= 0) {
+ /* Can we have IPV4 without MAC address ? */
+ make_mac(ifi.ifr_hwaddr.sa_data, id->maca);
+ }
+
+ if (ioctl(e->sd, SIOCGIFNETMASK, (char *)&ifi) >= 0) {
+ sa = (struct sockaddr_in *)&ifi.ifr_netmask;
+ inet_ntop(AF_INET, &sa->sin_addr, id->mask, 64);
+ }
+
+ if ((id->flags & IFF_BROADCAST) &&
+ ioctl(e->sd, SIOCGIFBRDADDR, (char *)&ifi) >= 0) {
+ sa = (struct sockaddr_in *)&ifi.ifr_broadaddr;
+ inet_ntop(AF_INET, &sa->sin_addr, id->badr, 64);
+ }
id->type = AF_INET;
ce->data = id;
}
+ else {
+ strcpy(id->ip4a, las);
+ }
+
}
free(ifc.ifc_buf);
+ /* Add missing interfaces from /proc/net/dev */
+ if ((i4a = sight_arr_rload(PROC_NET_DEV)) != NULL) {
+ for (i = 2; i < i4a->siz; i++) {
+ cache_entry_t *ce;
+ char *pname;
+ if (!(pname = strchr(i4a->arr.ca[i], ':')))
+ continue;
+ *pname = '\0';
+ ce = cache_add(e->ifc, i4a->arr.ca[i]);
+ if (!(id = (net_ifc_data_t *)ce->data)) {
+ struct ifreq ifi;
+ struct sockaddr_in *sa;
+
+ if (!(id = (net_ifc_data_t *)sight_calloc(_E,
+ sizeof(net_ifc_data_t),
+ THROW_FMARK))) {
+ sight_arr_free(i4a);
+ goto cleanup;
+ }
+ strcpy(ifi.ifr_name, i4a->arr.ca[i]);
+ id->type = AF_INET;
+ if (ioctl(e->sd, SIOCGIFINDEX, (char *)&ifi) >= 0)
+ id->index = ifi.ifr_ifindex;
+ else
+ id->index = -1;
+ if (ioctl(e->sd, SIOCGIFFLAGS, (char *)&ifi) >= 0)
+ id->flags = ifi.ifr_flags;
+
+ if (ioctl(e->sd, SIOCGIFHWADDR, (char *)&ifi) >= 0) {
+ /* Can we have IPV4 without MAC address ? */
+ make_mac(ifi.ifr_hwaddr.sa_data, id->maca);
+ }
+
+ if (ioctl(e->sd, SIOCGIFNETMASK, (char *)&ifi) >= 0) {
+ sa = (struct sockaddr_in *)&ifi.ifr_netmask;
+ inet_ntop(AF_INET, &sa->sin_addr, id->mask, 64);
+ }
+
+ if ((id->flags & IFF_BROADCAST) &&
+ ioctl(e->sd, SIOCGIFBRDADDR, (char *)&ifi) >= 0) {
+ sa = (struct sockaddr_in *)&ifi.ifr_broadaddr;
+ inet_ntop(AF_INET, &sa->sin_addr, id->badr, 64);
+ }
+ ce->data = id;
+ }
+ }
+ sight_arr_free(i4a);
+ }
/* Now add IPV6 entries */
if ((i6a = sight_arr_rload(PROC_INET6_FILE)) != NULL) {
for (i = 0; i < i6a->siz; i++) {
cache_entry_t *ce;
+ struct ifreq ifi;
int al, plen, scope, dads, ifidx;
- char name[20];
+ char ias[64];
+ char las[128] = "";
struct in6_addr in6;
-
al = sscanf(i6a->arr.ca[i],
- "%08X%08X%08X%08X %02x %02x %02x %02x %20s",
- &in6.s6_addr32[0], &in6.s6_addr32[1],
- &in6.s6_addr32[2], &in6.s6_addr32[3],
- &ifidx, &plen, &scope, &dads, &name);
-
- ce = cache_add(e->ifc, name);
- if (!ce->data) {
- net_ifc_data_t *id;
+ "%32s %02x %02x %02x %02x %16s",
+ ias, &ifidx, &plen, &scope, &dads,
ifi.ifr_name);
+ sight_hex2bin(ias, in6.s6_addr, 16);
+ sight_inet_ntop6(in6.s6_addr, las, 64);
+ ce = cache_add(e->ifc, ifi.ifr_name);
+ if (plen) {
+ char buf[32];
+ sprintf(buf, "/%d", plen);
+ strcat(las, buf);
+ }
+ if (!(id = (net_ifc_data_t *)ce->data)) {
if (!(id = (net_ifc_data_t *)sight_calloc(_E,
sizeof(net_ifc_data_t),
THROW_FMARK))) {
sight_arr_free(i6a);
goto cleanup;
}
- id->type = AF_INET6;
- ce->data = id;
- }
+ strcpy(id->ip6a, las);
+ if (ioctl(e->sd, SIOCGIFHWADDR, (char *)&ifi) >= 0) {
+ make_mac(ifi.ifr_hwaddr.sa_data, las);
+ strcpy(id->maca, las);
+ }
+ id->type = AF_INET6;
+ id->index = ifidx;
+ id->flags = IFF_UP;
+ ce->data = id;
+ }
+ else {
+ strcpy(id->ip6a, las);
+ }
}
sight_arr_free(i6a);
}
@@ -279,6 +424,9 @@
{
net_adapter_enum_t *e = J2P(handle, net_adapter_enum_t *);
net_ifc_data_t *id;
+ jobject addr;
+ jobjectArray aarr;
+ jint len, idx;
UNREFERENCED_O;
if (!e || e->idx > e->ifc->siz)
@@ -287,6 +435,69 @@
SET_IFIELD_S(0000, thiz, e->ifc->list[e->idx]->key);
/* TODO: Figure out the Description */
SET_IFIELD_S(0002, thiz, e->ifc->list[e->idx]->key);
+
+ if (id->maca[0]) {
+ addr = sight_new_netaddr_class(_E, _O);
+ if (!addr || (*_E)->ExceptionCheck(_E))
+ return;
+ sight_netaddr_set_addr(_E, addr, id->maca);
+ sight_netaddr_set_family(_E, addr, AF_HARDWARE);
+ SET_IFIELD_O(0003, thiz, addr);
+ (*_E)->DeleteLocalRef(_E, addr);
+ }
+ /* Set adapter type */
+ if (id->flags & IFF_LOOPBACK) {
+ CALL_METHOD1(0000, thiz, IF_TYPE_SOFTWARE_LOOPBACK);
+ }
+ else if (id->flags & IFF_POINTOPOINT) {
+ CALL_METHOD1(0000, thiz, IF_TYPE_PPP);
+ }
+ else {
+ CALL_METHOD1(0000, thiz, IF_TYPE_ETHERNET_CSMACD);
+ }
+ /* Set adapter status */
+ if (id->flags & IFF_UP) {
+ CALL_METHOD1(0001, thiz, SIGHT_IFO_UP);
+ }
+ else {
+ CALL_METHOD1(0001, thiz, SIGHT_IFO_DOWN);
+ }
+ /* Set IP addresses */
+ len = 0;
+ if (id->ip4a[0])
+ len++;
+ if (id->ip6a[0])
+ len++;
+ if (len) {
+ idx = 0;
+ aarr = sight_new_netaddr_array(_E, _O, len);
+ if (!aarr || (*_E)->ExceptionCheck(_E))
+ goto cleanup;
+ if (id->ip4a[0]) {
+ addr = sight_new_netaddr_class(_E, _O);
+ if (!addr || (*_E)->ExceptionCheck(_E))
+ return;
+ sight_netaddr_set_addr(_E, addr, id->ip4a);
+ sight_netaddr_set_family(_E, addr, AF_INET);
+ if (id->mask[0])
+ sight_netaddr_set_mask(_E, addr, id->mask);
+ (*_E)->SetObjectArrayElement(_E, aarr, idx++, addr);
+ (*_E)->DeleteLocalRef(_E, addr);
+ }
+ if (id->ip6a[0]) {
+ addr = sight_new_netaddr_class(_E, _O);
+ if (!addr || (*_E)->ExceptionCheck(_E))
+ return;
+ sight_netaddr_set_addr(_E, addr, id->ip6a);
+ sight_netaddr_set_family(_E, addr, AF_INET6);
+ (*_E)->SetObjectArrayElement(_E, aarr, idx++, addr);
+ (*_E)->DeleteLocalRef(_E, addr);
+ }
+ SET_IFIELD_O(0006, thiz, aarr);
+ (*_E)->DeleteLocalRef(_E, aarr);
+ }
+
+cleanup:
e->idx++;
}