3 -- This project is MIT/X11 licensed. Please see the
4 -- COPYING file in the source package for more information.
6 -- Copyright (C) 2012 Paul Aurich
7 -- Copyright (C) 2013 Matthew Wild
8 -- Copyright (C) 2013 Florian Zeitz
18 #include <sys/ioctl.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
23 #include <arpa/inet.h>
24 #include <netinet/in.h>
30 #if (LUA_VERSION_NUM == 501)
31 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
34 /* Enumerate all locally configured IP addresses */
36 const char *const type_strings
[] = {
43 static int lc_local_addresses(lua_State
*L
) {
45 /* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */
46 const long ip4_linklocal
= htonl(0xa9fe0000); /* 169.254.0.0 */
47 const long ip4_mask
= htonl(0xffff0000);
48 struct ifaddrs
*addr
= NULL
, *a
;
51 int type
= luaL_checkoption(L
, 1, "both", type_strings
);
52 const char link_local
= lua_toboolean(L
, 2); /* defaults to 0 (false) */
53 const char ipv4
= (type
== 0 || type
== 1);
54 const char ipv6
= (type
== 0 || type
== 2);
58 if(getifaddrs(&addr
) < 0) {
60 lua_pushfstring(L
, "getifaddrs failed (%d): %s", errno
,
70 for(a
= addr
; a
; a
= a
->ifa_next
) {
72 char ipaddr
[INET6_ADDRSTRLEN
];
73 const char *tmp
= NULL
;
75 if(a
->ifa_addr
== NULL
|| a
->ifa_flags
& IFF_LOOPBACK
) {
79 family
= a
->ifa_addr
->sa_family
;
81 if(ipv4
&& family
== AF_INET
) {
82 struct sockaddr_in
*sa
= (struct sockaddr_in
*)a
->ifa_addr
;
84 if(!link_local
&& ((sa
->sin_addr
.s_addr
& ip4_mask
) == ip4_linklocal
)) {
88 tmp
= inet_ntop(family
, &sa
->sin_addr
, ipaddr
, sizeof(ipaddr
));
89 } else if(ipv6
&& family
== AF_INET6
) {
90 struct sockaddr_in6
*sa
= (struct sockaddr_in6
*)a
->ifa_addr
;
92 if(!link_local
&& IN6_IS_ADDR_LINKLOCAL(&sa
->sin6_addr
)) {
96 if(IN6_IS_ADDR_V4MAPPED(&sa
->sin6_addr
) || IN6_IS_ADDR_V4COMPAT(&sa
->sin6_addr
)) {
100 tmp
= inet_ntop(family
, &sa
->sin6_addr
, ipaddr
, sizeof(ipaddr
));
104 lua_pushstring(L
, tmp
);
105 lua_rawseti(L
, -2, n
++);
108 /* TODO: Error reporting? */
115 lua_pushstring(L
, "0.0.0.0");
116 lua_rawseti(L
, -2, n
++);
120 lua_pushstring(L
, "::");
121 lua_rawseti(L
, -2, n
++);
128 int luaopen_util_net(lua_State
*L
) {
129 #if (LUA_VERSION_NUM > 501)
130 luaL_checkversion(L
);
132 luaL_Reg exports
[] = {
133 { "local_addresses", lc_local_addresses
},
137 lua_createtable(L
, 0, 1);
138 luaL_setfuncs(L
, exports
, 0);