summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2009-04-26 19:10:36 +0000
committerSteven Barth <steven@midlink.org>2009-04-26 19:10:36 +0000
commitd81b3548a92a7a9db95d2587d6d15aebdc9b8652 (patch)
tree0ce5776c20b7864c8275fe582e738552cc8ae8e2
parenta8da3a09a3fb34327cf02306726dad640e309f20 (diff)
nixio:
Added binding for getifaddrs(): List network interfaces, their flags, addresses and statistics Cleanups
-rw-r--r--libs/nixio/docsrc/nixio.lua17
-rw-r--r--libs/nixio/src/address.c218
-rw-r--r--libs/nixio/src/binary.c2
-rw-r--r--libs/nixio/src/nixio.c2
-rw-r--r--libs/nixio/src/nixio.h4
-rw-r--r--libs/nixio/src/sockopt.c4
-rw-r--r--libs/nixio/src/tls-crypto.c4
7 files changed, 244 insertions, 7 deletions
diff --git a/libs/nixio/docsrc/nixio.lua b/libs/nixio/docsrc/nixio.lua
index 7efeab8ef..2d0056f17 100644
--- a/libs/nixio/docsrc/nixio.lua
+++ b/libs/nixio/docsrc/nixio.lua
@@ -20,6 +20,23 @@ module "nixio"
-- @param ipaddr IPv4 or IPv6-Address
-- @return FQDN
+--- (Linux, BSD) Get a list of available network interfaces and their addresses.
+-- @class function
+-- @name nixio.getifaddrs
+-- @return Table containing one or more tables containing: <ul>
+-- <li>name = Interface Name</li>
+-- <li>family = ["inet", "inet6", "packet"]</li>
+-- <li>addr = Interface Address (IPv4, IPv6, MAC, ...)</li>
+-- <li>broadaddr = Broadcast Address</li>
+-- <li>dstaddr = Destination Address (Point-to-Point)</li>
+-- <li>netmask = Netmask (if available)</li>
+-- <li>prefix = Prefix (if available)</li>
+-- <li>flags = Table of interface flags (up, multicast, loopback, ...)</li>
+-- <li>data = Statistics (Linux, "packet"-family)</li>
+-- <li>hatype = Hardware Type Identifier (Linix, "packet"-family)</li>
+-- <li>ifindex = Interface Index (Linux, "packet"-family)</li>
+-- </ul>
+
--- Create a new socket and bind it to a network address.
-- This function is a shortcut for calling nixio.socket and then bind()
-- on the socket object.
diff --git a/libs/nixio/src/address.c b/libs/nixio/src/address.c
index 835a8a2f9..3547f19be 100644
--- a/libs/nixio/src/address.c
+++ b/libs/nixio/src/address.c
@@ -21,6 +21,40 @@
#include <errno.h>
#include <string.h>
+#ifdef __linux__
+#include <linux/netdevice.h>
+
+/* struct net_device_stats is buggy on amd64, redefine it */
+struct nixio__nds {
+ uint32_t rx_packets;
+ uint32_t tx_packets;
+ uint32_t rx_bytes;
+ uint32_t tx_bytes;
+ uint32_t rx_errors;
+ uint32_t tx_errors;
+ uint32_t rx_dropped;
+ uint32_t tx_dropped;
+ uint32_t multicast;
+ uint32_t collisions;
+
+ uint32_t rx_length_errors;
+ uint32_t rx_over_errors;
+ uint32_t rx_crc_errors;
+ uint32_t rx_frame_errors;
+ uint32_t rx_fifo_errors;
+ uint32_t rx_missed_errors;
+
+ uint32_t tx_aborted_errors;
+ uint32_t tx_carrier_errors;
+ uint32_t tx_fifo_errors;
+ uint32_t tx_heartbeat_errors;
+ uint32_t tx_window_errors;
+
+ uint32_t rx_compressed;
+ uint32_t tx_compressed;
+};
+#endif
+
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
@@ -40,6 +74,20 @@ int nixio__addr_parse(nixio_addr *addr, struct sockaddr *saddr) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6*)saddr;
addr->port = ntohs(inet6addr->sin6_port);
baddr = &inet6addr->sin6_addr;
+#ifdef AF_PACKET
+ } else if (saddr->sa_family == AF_PACKET) {
+ struct sockaddr_ll *etheradddr = (struct sockaddr_ll*)saddr;
+ addr->prefix = etheradddr->sll_hatype;
+ addr->port = etheradddr->sll_ifindex;
+ char *c = addr->host;
+ for (size_t i = 0; i < etheradddr->sll_halen; i++) {
+ *c++ = nixio__bin2hex[(etheradddr->sll_addr[i] & 0xf0) >> 4];
+ *c++ = nixio__bin2hex[(etheradddr->sll_addr[i] & 0x0f)];
+ *c++ = ':';
+ }
+ *(c-1) = 0;
+ return 0;
+#endif
} else {
errno = EAFNOSUPPORT;
return -1;
@@ -91,6 +139,39 @@ int nixio__addr_write(nixio_addr *addr, struct sockaddr *saddr) {
}
}
+/**
+ * netmask to prefix helper
+ */
+int nixio__addr_prefix(struct sockaddr *saddr) {
+ int prefix = 0;
+ size_t len;
+ uint8_t *addr;
+
+ if (saddr->sa_family == AF_INET) {
+ addr = (uint8_t*)(&((struct sockaddr_in*)saddr)->sin_addr);
+ len = 4;
+ } else if (saddr->sa_family == AF_INET6) {
+ addr = (uint8_t*)(&((struct sockaddr_in6*)saddr)->sin6_addr);
+ len = 16;
+ } else {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ if (addr[i] == 0xff) {
+ prefix += 8;
+ } else if (addr[i] == 0x00) {
+ break;
+ } else {
+ for (uint8_t c = addr[i]; c; c <<= 1) {
+ prefix++;
+ }
+ }
+ }
+
+ return prefix;
+}
/**
* getaddrinfo(host, family, port)
@@ -264,9 +345,146 @@ static int nixio_sock_getpeername(lua_State *L) {
return 2;
}
+#if defined(__linux__) || defined(BSD)
+#include <ifaddrs.h>
+
+static int nixio_getifaddrs(lua_State *L) {
+ nixio_addr addr;
+ struct ifaddrs *ifaddr, *c;
+ if (getifaddrs(&ifaddr) == -1) {
+ return nixio__perror(L);
+ }
+
+ lua_newtable(L);
+ unsigned int i = 1;
+
+ for (c = ifaddr; c; c = c->ifa_next) {
+ lua_newtable(L);
+
+ lua_pushstring(L, c->ifa_name);
+ lua_setfield(L, -2, "name");
+
+ lua_createtable(L, 0, 7);
+ lua_pushboolean(L, c->ifa_flags & IFF_UP);
+ lua_setfield(L, -2, "up");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_BROADCAST);
+ lua_setfield(L, -2, "broadcast");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_LOOPBACK);
+ lua_setfield(L, -2, "loopback");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_POINTOPOINT);
+ lua_setfield(L, -2, "pointtopoint");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_NOARP);
+ lua_setfield(L, -2, "noarp");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_PROMISC);
+ lua_setfield(L, -2, "promisc");
+
+ lua_pushboolean(L, c->ifa_flags & IFF_MULTICAST);
+ lua_setfield(L, -2, "multicast");
+ lua_setfield(L, -2, "flags");
+
+ if (c->ifa_addr && !nixio__addr_parse(&addr, c->ifa_addr)) {
+ lua_pushstring(L, addr.host);
+ lua_setfield(L, -2, "addr");
+
+ if (c->ifa_addr->sa_family == AF_INET) {
+ lua_pushliteral(L, "inet");
+ } else if (c->ifa_addr->sa_family == AF_INET6) {
+ lua_pushliteral(L, "inet6");
+#ifdef AF_PACKET
+ } else if (c->ifa_addr->sa_family == AF_PACKET) {
+ lua_pushliteral(L, "packet");
+#endif
+ } else {
+ lua_pushliteral(L, "unknown");
+ }
+ lua_setfield(L, -2, "family");
+
+#ifdef __linux__
+ if (c->ifa_addr->sa_family == AF_PACKET) {
+ lua_pushinteger(L, addr.port);
+ lua_setfield(L, -2, "ifindex");
+
+ lua_pushinteger(L, addr.prefix);
+ lua_setfield(L, -2, "hatype");
+
+ if (c->ifa_data) {
+ lua_createtable(L, 0, 10);
+ struct nixio__nds *stats = c->ifa_data;
+
+ lua_pushnumber(L, stats->rx_packets);
+ lua_setfield(L, -2, "rx_packets");
+
+ lua_pushnumber(L, stats->tx_packets);
+ lua_setfield(L, -2, "tx_packets");
+
+ lua_pushnumber(L, stats->rx_bytes);
+ lua_setfield(L, -2, "rx_bytes");
+
+ lua_pushnumber(L, stats->tx_bytes);
+ lua_setfield(L, -2, "tx_bytes");
+
+ lua_pushnumber(L, stats->rx_errors);
+ lua_setfield(L, -2, "rx_errors");
+
+ lua_pushnumber(L, stats->tx_errors);
+ lua_setfield(L, -2, "tx_errors");
+
+ lua_pushnumber(L, stats->rx_dropped);
+ lua_setfield(L, -2, "rx_dropped");
+
+ lua_pushnumber(L, stats->tx_dropped);
+ lua_setfield(L, -2, "tx_dropped");
+
+ lua_pushnumber(L, stats->multicast);
+ lua_setfield(L, -2, "multicast");
+
+ lua_pushnumber(L, stats->collisions);
+ lua_setfield(L, -2, "collisions");
+ } else {
+ lua_newtable(L);
+ }
+ lua_setfield(L, -2, "data");
+ }
+#endif
+ }
+
+ if (c->ifa_netmask && !nixio__addr_parse(&addr, c->ifa_netmask)) {
+ lua_pushstring(L, addr.host);
+ lua_setfield(L, -2, "netmask");
+
+ lua_pushinteger(L, nixio__addr_prefix(c->ifa_netmask));
+ lua_setfield(L, -2, "prefix");
+ }
+
+ if (c->ifa_broadaddr && !nixio__addr_parse(&addr, c->ifa_broadaddr)) {
+ lua_pushstring(L, addr.host);
+ lua_setfield(L, -2, "broadaddr");
+ }
+
+ if (c->ifa_dstaddr && !nixio__addr_parse(&addr, c->ifa_dstaddr)) {
+ lua_pushstring(L, addr.host);
+ lua_setfield(L, -2, "dstaddr");
+ }
+
+ lua_rawseti(L, -2, i++);
+ }
+
+ freeifaddrs(ifaddr);
+ return 1;
+}
+#endif
+
/* module table */
static const luaL_reg R[] = {
+#if defined(__linux__) || defined(BSD)
+ {"getifaddrs", nixio_getifaddrs},
+#endif
{"getaddrinfo", nixio_getaddrinfo},
{"getnameinfo", nixio_getnameinfo},
{NULL, NULL}
diff --git a/libs/nixio/src/binary.c b/libs/nixio/src/binary.c
index 72425b113..2466f9891 100644
--- a/libs/nixio/src/binary.c
+++ b/libs/nixio/src/binary.c
@@ -19,7 +19,7 @@
#include "nixio.h"
#include <stdlib.h>
-static char nixio__bin2hex[] = {
+const char nixio__bin2hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
diff --git a/libs/nixio/src/nixio.c b/libs/nixio/src/nixio.c
index 457bbd1f2..5749b3bfb 100644
--- a/libs/nixio/src/nixio.c
+++ b/libs/nixio/src/nixio.c
@@ -22,7 +22,7 @@
#include <errno.h>
#include <signal.h>
-#define VERSION 0.2
+#define VERSION 0.3
/* pushes nil, error number and errstring on the stack */
diff --git a/libs/nixio/src/nixio.h b/libs/nixio/src/nixio.h
index 8caa5b969..0c43cfe8a 100644
--- a/libs/nixio/src/nixio.h
+++ b/libs/nixio/src/nixio.h
@@ -33,6 +33,7 @@ typedef struct nixio_address {
int family;
char host[128];
int port;
+ int prefix;
} nixio_addr;
int nixio__perror(lua_State *L);
@@ -47,7 +48,6 @@ int nixio__pstatus(lua_State *L, int condition);
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
-#include <net/if.h>
#include <sys/un.h>
#include <netdb.h>
#include <poll.h>
@@ -90,6 +90,8 @@ int nixio__mode_write(int mode, char *modestr);
int nixio__push_stat(lua_State *L, nixio_stat_t *buf);
+const char nixio__bin2hex[16];
+
/* Module functions */
void nixio_open_file(lua_State *L);
void nixio_open_socket(lua_State *L);
diff --git a/libs/nixio/src/sockopt.c b/libs/nixio/src/sockopt.c
index 7e063e4a3..c7fe9c297 100644
--- a/libs/nixio/src/sockopt.c
+++ b/libs/nixio/src/sockopt.c
@@ -18,6 +18,10 @@
#include "nixio.h"
+#ifndef __WINNT__
+#include <net/if.h>
+#endif
+
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
diff --git a/libs/nixio/src/tls-crypto.c b/libs/nixio/src/tls-crypto.c
index c93b1aa18..62ade2265 100644
--- a/libs/nixio/src/tls-crypto.c
+++ b/libs/nixio/src/tls-crypto.c
@@ -22,10 +22,6 @@
#include <fcntl.h>
#include <unistd.h>
-static char nixio__bin2hex[] = {
-'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-};
-
static int nixio_crypto_hash__init(lua_State *L, int hmac) {
const char *type = luaL_checkstring(L, 1);
nixio_hash *hash = lua_newuserdata(L, sizeof(nixio_hash));