+#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
+