]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lua: add ip addresses and network manipulation function
authorThierry FOURNIER / OZON.IO <thierry.fournier@ozon.io>
Thu, 10 Nov 2016 19:38:11 +0000 (20:38 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 12 Nov 2016 09:42:30 +0000 (10:42 +0100)
Add two functions core.parse_addr() and core.match_addr() where are used
for matching networks.

doc/lua-api/index.rst
include/types/hlua.h
src/hlua_fcn.c

index 77c22662c9119b0a4e9fb0fe02bd6ceb7284736d..32ef1436b96cbb78bb098e48b19a5233c8170942 100644 (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
index 698786dd8d65320da52261022e0df91abfadb205..d2aaa4a3c69de399fecc920dda9fb5ad6785298c 100644 (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 */
index b9ce84cde7c0e5649070d0fc19e8653d175eee6b..a21065dc3472698ed0876c51105c27da4df84e95 100644 (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);