Add local_addresses() to enumerate the local host's interface addresses (tested on all supported platforms except Windows)
This commit is contained in:
parent
d548a78e55
commit
5124888add
1 changed files with 101 additions and 2 deletions
103
src/inet.c
103
src/inet.c
|
@ -5,11 +5,27 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
|
||||||
#include "inet.h"
|
#include "inet.h"
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct sockaddr_storage sas;
|
||||||
|
struct sockaddr sa;
|
||||||
|
struct sockaddr_in sa4;
|
||||||
|
struct sockaddr_in6 sa6;
|
||||||
|
} SA_union;
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
* Internal function prototypes.
|
* Internal function prototypes.
|
||||||
\*=========================================================================*/
|
\*=========================================================================*/
|
||||||
|
@ -17,11 +33,12 @@ static int inet_global_toip(lua_State *L);
|
||||||
static int inet_global_getaddrinfo(lua_State *L);
|
static int inet_global_getaddrinfo(lua_State *L);
|
||||||
static int inet_global_tohostname(lua_State *L);
|
static int inet_global_tohostname(lua_State *L);
|
||||||
static int inet_global_getnameinfo(lua_State *L);
|
static int inet_global_getnameinfo(lua_State *L);
|
||||||
|
static int inet_global_local_addresses(lua_State *L);
|
||||||
static void inet_pushresolved(lua_State *L, struct hostent *hp);
|
static void inet_pushresolved(lua_State *L, struct hostent *hp);
|
||||||
static int inet_global_gethostname(lua_State *L);
|
static int inet_global_gethostname(lua_State *L);
|
||||||
|
|
||||||
/* DNS functions */
|
/* DNS functions */
|
||||||
static luaL_Reg func[] = {
|
static luaL_Reg dns[] = {
|
||||||
{ "toip", inet_global_toip},
|
{ "toip", inet_global_toip},
|
||||||
{ "getaddrinfo", inet_global_getaddrinfo},
|
{ "getaddrinfo", inet_global_getaddrinfo},
|
||||||
{ "tohostname", inet_global_tohostname},
|
{ "tohostname", inet_global_tohostname},
|
||||||
|
@ -30,6 +47,12 @@ static luaL_Reg func[] = {
|
||||||
{ NULL, NULL}
|
{ NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* global functions */
|
||||||
|
static luaL_Reg func[] = {
|
||||||
|
{ "local_addresses", inet_global_local_addresses},
|
||||||
|
{ NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
* Exported functions
|
* Exported functions
|
||||||
\*=========================================================================*/
|
\*=========================================================================*/
|
||||||
|
@ -40,8 +63,11 @@ int inet_open(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_pushstring(L, "dns");
|
lua_pushstring(L, "dns");
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
luaL_openlib(L, NULL, func, 0);
|
luaL_openlib(L, NULL, dns, 0);
|
||||||
lua_settable(L, -3);
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
/* Export as global functions */
|
||||||
|
luaL_openlib(L, NULL, func, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +247,79 @@ static int inet_global_gethostname(lua_State *L)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*\
|
||||||
|
* Enumerate all locally configured IP addresses
|
||||||
|
\*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const char * const type_strings[] = {
|
||||||
|
"both",
|
||||||
|
"ipv4",
|
||||||
|
"ipv6",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int inet_global_local_addresses(lua_State *L)
|
||||||
|
{
|
||||||
|
/* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */
|
||||||
|
const long ip4_linklocal = htonl(0xa9fe0000); /* 169.254.0.0 */
|
||||||
|
const long ip4_mask = htonl(0xffff0000);
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct ifaddrs *addr = NULL, *a;
|
||||||
|
int n = 1;
|
||||||
|
#endif
|
||||||
|
int type = luaL_checkoption(L, 1, "both", type_strings);
|
||||||
|
const char link_local = lua_toboolean(L, 2); /* defaults to 0 (false) */
|
||||||
|
const char ipv4 = (type == 0 || type == 1);
|
||||||
|
const char ipv6 = (type == 0 || type == 2);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (getifaddrs(&addr) < 0) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_pushfstring(L, "getifaddrs failed (%d): %s", errno,
|
||||||
|
strerror(errno));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
for (a = addr; a; a = a->ifa_next) {
|
||||||
|
int family;
|
||||||
|
char ipaddr[INET6_ADDRSTRLEN];
|
||||||
|
const char *tmp = NULL;
|
||||||
|
|
||||||
|
if (a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
family = a->ifa_addr->sa_family;
|
||||||
|
|
||||||
|
if (ipv4 && family == AF_INET) {
|
||||||
|
struct sockaddr_in *sa = (struct sockaddr_in *)a->ifa_addr;
|
||||||
|
if (!link_local &&
|
||||||
|
((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal))
|
||||||
|
continue;
|
||||||
|
tmp = inet_ntop(family, &sa->sin_addr, ipaddr, sizeof(ipaddr));
|
||||||
|
} else if (ipv6 && family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)a->ifa_addr;
|
||||||
|
if (!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
|
||||||
|
continue;
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr))
|
||||||
|
continue;
|
||||||
|
tmp = inet_ntop(family, &sa->sin6_addr, ipaddr, sizeof(ipaddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp != NULL) {
|
||||||
|
lua_pushstring(L, tmp);
|
||||||
|
lua_rawseti(L, -2, n++);
|
||||||
|
}
|
||||||
|
/* TODO: Error reporting? */
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs(addr);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue