#include <string.h>
#ifdef __linux__
+
+#include <signal.h>
+#include <setjmp.h>
+#include <unistd.h>
+
+/* setjmp() / longjmp() stuff */
+static jmp_buf nixio__jump_alarm;
+static void nixio__handle_alarm(int sig) { longjmp(nixio__jump_alarm, 1); }
+
#include <linux/netdevice.h>
/* struct net_device_stats is buggy on amd64, redefine it */
}
/**
- * getnameinfo(address, family)
+ * getnameinfo(address, family[, timeout])
*/
static int nixio_getnameinfo(lua_State *L) {
const char *ip = luaL_checkstring(L, 1);
const char *family = luaL_optstring(L, 2, NULL);
+
+#ifdef __linux__
+ struct sigaction sa_new, sa_old;
+ int timeout = luaL_optnumber(L, 3, 0);
+ if (timeout > 0 && timeout < 1000)
+ {
+ sa_new.sa_handler = nixio__handle_alarm;
+ sa_new.sa_flags = 0;
+ sigemptyset(&sa_new.sa_mask);
+ sigaction(SIGALRM, &sa_new, &sa_old);
+
+ /* user timeout exceeded */
+ if (setjmp(nixio__jump_alarm))
+ {
+ sigaction(SIGALRM, &sa_old, NULL);
+
+ lua_pushnil(L);
+ lua_pushinteger(L, EAI_AGAIN);
+ lua_pushstring(L, gai_strerror(EAI_AGAIN));
+
+ return 3;
+ }
+
+ ualarm(timeout * 1000, 0);
+ }
+#endif
+
char host[NI_MAXHOST];
struct sockaddr_storage saddr;
int res = getnameinfo((struct sockaddr *)&saddr, sizeof(saddr),
host, sizeof(host), NULL, 0, NI_NAMEREQD);
+
+#ifdef __linux__
+ if (timeout > 0 && timeout < 1000)
+ {
+ ualarm(0, 0);
+ sigaction(SIGALRM, &sa_old, NULL);
+ }
+#endif
+
if (res) {
lua_pushnil(L);
lua_pushinteger(L, res);
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) {
+ if (!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");
lua_pushinteger(L, addr.prefix);
lua_setfield(L, -2, "hatype");
+ }
+#endif
+ }
- if (c->ifa_data) {
- lua_createtable(L, 0, 10);
- struct nixio__nds *stats = c->ifa_data;
+#ifdef __linux__
+ if (c->ifa_data && (!c->ifa_addr
+ || c->ifa_addr->sa_family == AF_PACKET)) {
+ if (!c->ifa_addr) {
+ lua_pushliteral(L, "packet");
+ lua_setfield(L, -2, "family");
+ }
- lua_pushnumber(L, stats->rx_packets);
- lua_setfield(L, -2, "rx_packets");
+ lua_createtable(L, 0, 10);
+ struct nixio__nds *stats = c->ifa_data;
- lua_pushnumber(L, stats->tx_packets);
- lua_setfield(L, -2, "tx_packets");
+ lua_pushnumber(L, stats->rx_packets);
+ lua_setfield(L, -2, "rx_packets");
- lua_pushnumber(L, stats->rx_bytes);
- lua_setfield(L, -2, "rx_bytes");
+ lua_pushnumber(L, stats->tx_packets);
+ lua_setfield(L, -2, "tx_packets");
- lua_pushnumber(L, stats->tx_bytes);
- lua_setfield(L, -2, "tx_bytes");
+ lua_pushnumber(L, stats->rx_bytes);
+ lua_setfield(L, -2, "rx_bytes");
- lua_pushnumber(L, stats->rx_errors);
- lua_setfield(L, -2, "rx_errors");
+ lua_pushnumber(L, stats->tx_bytes);
+ lua_setfield(L, -2, "tx_bytes");
- lua_pushnumber(L, stats->tx_errors);
- lua_setfield(L, -2, "tx_errors");
+ lua_pushnumber(L, stats->rx_errors);
+ lua_setfield(L, -2, "rx_errors");
- lua_pushnumber(L, stats->rx_dropped);
- lua_setfield(L, -2, "rx_dropped");
+ lua_pushnumber(L, stats->tx_errors);
+ lua_setfield(L, -2, "tx_errors");
- lua_pushnumber(L, stats->tx_dropped);
- lua_setfield(L, -2, "tx_dropped");
+ lua_pushnumber(L, stats->rx_dropped);
+ lua_setfield(L, -2, "rx_dropped");
- lua_pushnumber(L, stats->multicast);
- lua_setfield(L, -2, "multicast");
+ lua_pushnumber(L, stats->tx_dropped);
+ lua_setfield(L, -2, "tx_dropped");
- lua_pushnumber(L, stats->collisions);
- lua_setfield(L, -2, "collisions");
- } else {
- lua_newtable(L);
- }
- lua_setfield(L, -2, "data");
- }
-#endif
+ 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);