Comparison

util-src/net.c @ 5699:e9f5384f5ff1

util.net: Add util.net, containing local_addresses() (removed from LuaSocket 3.0)
author Matthew Wild <mwild1@gmail.com>
date Tue, 18 Jun 2013 09:04:44 +0100
child 5750:fbff8ecb6662
comparison
equal deleted inserted replaced
5693:ef490e9276df 5699:e9f5384f5ff1
1 /* Prosody IM
2 --
3 -- This project is MIT/X11 licensed. Please see the
4 -- COPYING file in the source package for more information.
5 --
6 -- Copyright (C) 2012 Paul Aurich
7 -- Copyright (C) 2013 Matthew Wild
8 -- Copyright (C) 2013 Florian Zeitz
9 --
10 */
11
12 #include <stddef.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #ifndef _WIN32
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <net/if.h>
21 #include <ifaddrs.h>
22 #include <arpa/inet.h>
23 #endif
24
25 #include <lua.h>
26 #include <lauxlib.h>
27
28 /* Enumerate all locally configured IP addresses */
29
30 const char * const type_strings[] = {
31 "both",
32 "ipv4",
33 "ipv6",
34 NULL
35 };
36
37 static int lc_local_addresses(lua_State *L)
38 {
39 /* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */
40 const long ip4_linklocal = htonl(0xa9fe0000); /* 169.254.0.0 */
41 const long ip4_mask = htonl(0xffff0000);
42 #ifndef _WIN32
43 struct ifaddrs *addr = NULL, *a;
44 int n = 1;
45 #endif
46 int type = luaL_checkoption(L, 1, "both", type_strings);
47 const char link_local = lua_toboolean(L, 2); /* defaults to 0 (false) */
48 const char ipv4 = (type == 0 || type == 1);
49 const char ipv6 = (type == 0 || type == 2);
50
51 #ifndef _WIN32
52 if (getifaddrs(&addr) < 0) {
53 lua_pushnil(L);
54 lua_pushfstring(L, "getifaddrs failed (%d): %s", errno,
55 strerror(errno));
56 return 2;
57 }
58
59 lua_newtable(L);
60
61 for (a = addr; a; a = a->ifa_next) {
62 int family;
63 char ipaddr[INET6_ADDRSTRLEN];
64 const char *tmp = NULL;
65
66 if (a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK)
67 continue;
68
69 family = a->ifa_addr->sa_family;
70
71 if (ipv4 && family == AF_INET) {
72 struct sockaddr_in *sa = (struct sockaddr_in *)a->ifa_addr;
73 if (!link_local &&((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal))
74 continue;
75 tmp = inet_ntop(family, &sa->sin_addr, ipaddr, sizeof(ipaddr));
76 } else if (ipv6 && family == AF_INET6) {
77 struct sockaddr_in6 *sa = (struct sockaddr_in6 *)a->ifa_addr;
78 if (!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
79 continue;
80 if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr))
81 continue;
82 tmp = inet_ntop(family, &sa->sin6_addr, ipaddr, sizeof(ipaddr));
83 }
84
85 if (tmp != NULL) {
86 lua_pushstring(L, tmp);
87 lua_rawseti(L, -2, n++);
88 }
89 /* TODO: Error reporting? */
90 }
91
92 freeifaddrs(addr);
93
94 return 1;
95 #endif
96 }
97
98 int luaopen_util_net(lua_State* L)
99 {
100 luaL_Reg exports[] = {
101 { "local_addresses", lc_local_addresses },
102 { NULL, NULL }
103 };
104
105 luaL_register(L, "net", exports);
106 return 1;
107 }