MINOR: lua: add ip addresses and network manipulation function

Add two functions core.parse_addr() and core.match_addr() where are used
for matching networks.
This commit is contained in:
Thierry FOURNIER / OZON.IO 2016-11-10 20:38:11 +01:00 committed by Willy Tarreau
parent 65192f35d2
commit 62fec75183
3 changed files with 109 additions and 0 deletions

View File

@ -582,6 +582,28 @@ Core class
Give back the hand at the HAProxy scheduler. It is used when the LUA
processing consumes a lot of processing time.
.. js:function:: core.parse_addr(address)
**context**: body, init, task, action, sample-fetch, converter
:param network: is a string describing an ipv4 or ipv6 address and optionally
its network length, like this: "127.0.0.1/8" or "aaaa::1234/32".
:returns: a userdata containing network or nil if an error occurs.
Parse ipv4 or ipv6 adresses and its facultative associated network.
.. js:function:: core.match_addr(addr1, addr2)
**context**: body, init, task, action, sample-fetch, converter
:param addr1: is an address created with "core.parse_addr".
:param addr2: is an address created with "core.parse_addr".
:returns: boolean, true if the network of the addresses matche, else returns
false.
Match two networks. For example "127.0.0.1/32" matchs "127.0.0.0/8". The order
of network is not important.
.. _proxy_class:
Proxy class

View File

@ -150,6 +150,20 @@ struct hlua_concat {
int len;
};
struct hlua_addr {
union {
struct {
struct in_addr ip;
struct in_addr mask;
} v4;
struct {
struct in6_addr ip;
struct in6_addr mask;
} v6;
} addr;
int type;
};
#else /* USE_LUA */
/* Empty struct for compilation compatibility */

View File

@ -906,6 +906,77 @@ int hlua_fcn_post_init(lua_State *L)
return 1;
}
int hlua_parse_addr(lua_State *L)
{
struct hlua_addr *addr;
const char *str = luaL_checkstring(L, 1);
unsigned char mask;
addr = lua_newuserdata(L, sizeof(struct hlua_addr));
if (!addr) {
lua_pushnil(L);
return 1;
}
if (str2net(str, PAT_MF_NO_DNS, &addr->addr.v4.ip, &addr->addr.v4.mask)) {
addr->type = AF_INET;
return 1;
}
if (str62net(str, &addr->addr.v6.ip, &mask)) {
len2mask6(mask, &addr->addr.v6.mask);
addr->type = AF_INET6;
return 1;
}
lua_pop(L, 1);
lua_pushnil(L);
return 1;
}
int hlua_match_addr(lua_State *L)
{
struct hlua_addr *addr1;
struct hlua_addr *addr2;
if (!lua_isuserdata(L, 1) ||
!lua_isuserdata(L, 2)) {
lua_pushboolean(L, 0);
return 1;
}
addr1 = lua_touserdata(L, 1);
addr2 = lua_touserdata(L, 2);
if (addr1->type != addr2->type) {
lua_pushboolean(L, 0);
return 1;
}
if (addr1->type == AF_INET) {
if ((addr1->addr.v4.ip.s_addr & addr2->addr.v4.mask.s_addr) ==
(addr2->addr.v4.ip.s_addr & addr1->addr.v4.mask.s_addr)) {
lua_pushboolean(L, 1);
return 1;
}
} else {
if (((addr1->addr.v6.ip.s6_addr32[0] & addr2->addr.v6.mask.s6_addr32[0]) ==
(addr2->addr.v6.ip.s6_addr32[0] & addr1->addr.v6.mask.s6_addr32[0])) &&
((addr1->addr.v6.ip.s6_addr32[1] & addr2->addr.v6.mask.s6_addr32[1]) ==
(addr2->addr.v6.ip.s6_addr32[1] & addr1->addr.v6.mask.s6_addr32[1])) &&
((addr1->addr.v6.ip.s6_addr32[2] & addr2->addr.v6.mask.s6_addr32[2]) ==
(addr2->addr.v6.ip.s6_addr32[2] & addr1->addr.v6.mask.s6_addr32[2])) &&
((addr1->addr.v6.ip.s6_addr32[3] & addr2->addr.v6.mask.s6_addr32[3]) ==
(addr2->addr.v6.ip.s6_addr32[3] & addr1->addr.v6.mask.s6_addr32[3]))) {
lua_pushboolean(L, 1);
return 1;
}
}
lua_pushboolean(L, 0);
return 1;
}
int hlua_fcn_reg_core_fcn(lua_State *L)
{
if (!hlua_concat_init(L))
@ -918,6 +989,8 @@ int hlua_fcn_reg_core_fcn(lua_State *L)
hlua_class_function(L, "asctime_date", hlua_asctime_date);
hlua_class_function(L, "concat", hlua_concat_new);
hlua_class_function(L, "get_info", hlua_get_info);
hlua_class_function(L, "parse_addr", hlua_parse_addr);
hlua_class_function(L, "match_addr", hlua_match_addr);
/* Create listener object. */
lua_newtable(L);