Software /
code /
prosody
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 } |