diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index 77c22662c..32ef1436b 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -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 diff --git a/include/types/hlua.h b/include/types/hlua.h index 698786dd8..d2aaa4a3c 100644 --- a/include/types/hlua.h +++ b/include/types/hlua.h @@ -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 */ diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index b9ce84cde..a21065dc3 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -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);