]> source.dussan.org Git - rspamd.git/commitdiff
Add IP addresses manipulation API to lua.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 17 Nov 2013 22:26:08 +0000 (22:26 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 17 Nov 2013 22:26:08 +0000 (22:26 +0000)
src/lua/CMakeLists.txt
src/lua/lua_common.c
src/lua/lua_common.h
src/lua/lua_ip.c [new file with mode: 0644]

index 4713b34051600d5c1c9be9817317c8a9c2aded96..10606a909d9e019fbd9abd17e2cfb17384733c9d 100644 (file)
@@ -16,7 +16,8 @@ SET(LUASRC                      lua_common.c
                                          lua_session.c
                                          lua_buffer.c
                                          lua_dns.c
-                                         lua_rsa.c)
+                                         lua_rsa.c
+                                         lua_ip.c)
 
 ADD_LIBRARY(rspamd-lua ${LINK_TYPE} ${LUASRC})
 SET_TARGET_PROPERTIES(rspamd-lua PROPERTIES VERSION ${RSPAMD_VERSION})
index 8017cd086e5be69c75dfd03766a4e4ee224bccd1..f60717adf116c5083ecf7d68e8358ed78d2fb1db 100644 (file)
@@ -449,6 +449,7 @@ init_lua (struct config_file *cfg)
        (void)luaopen_io_dispatcher (L);
        (void)luaopen_dns_resolver (L);
        (void)luaopen_rsa (L);
+       (void)luaopen_ip (L);
 
        return L;
 }
index fd4058c11ce0d97537abff7acf12038ce758d54d..d04ad5c010f32f1d3966f260df7e352c0097738e 100644 (file)
@@ -118,6 +118,17 @@ gint lua_rcl_obj_push (lua_State *L, ucl_object_t *obj, gboolean allow_array);
  */
 ucl_object_t * lua_rcl_obj_get (lua_State *L, gint idx);
 
+/**
+ * Lua IP address structure
+ */
+struct rspamd_lua_ip {
+       union {
+               struct in6_addr ip6;
+               struct in_addr ip4;
+       } data;
+       int af;
+};
+
 /**
  * Open libraries functions
  */
@@ -145,6 +156,7 @@ gint luaopen_session (lua_State * L);
 gint luaopen_io_dispatcher (lua_State * L);
 gint luaopen_dns_resolver (lua_State * L);
 gint luaopen_rsa (lua_State * L);
+gint luaopen_ip (lua_State * L);
 
 gint lua_call_filter (const gchar *function, struct worker_task *task);
 gint lua_call_chain_filter (const gchar *function, struct worker_task *task, gint *marks, guint number);
diff --git a/src/lua/lua_ip.c b/src/lua/lua_ip.c
new file mode 100644 (file)
index 0000000..862e99a
--- /dev/null
@@ -0,0 +1,226 @@
+/* Copyright (c) 2013, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * Redistributions in binary form must reproduce the above copyright
+ *         notice, this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lua_common.h"
+
+LUA_FUNCTION_DEF (ip, to_string);
+LUA_FUNCTION_DEF (ip, to_table);
+LUA_FUNCTION_DEF (ip, str_octets);
+LUA_FUNCTION_DEF (ip, inversed_str_octets);
+LUA_FUNCTION_DEF (ip, from_string);
+LUA_FUNCTION_DEF (ip, destroy);
+
+static const struct luaL_reg    iplib_m[] = {
+       LUA_INTERFACE_DEF (ip, to_string),
+       LUA_INTERFACE_DEF (ip, to_table),
+       LUA_INTERFACE_DEF (ip, str_octets),
+       LUA_INTERFACE_DEF (ip, inversed_str_octets),
+       {"__tostring", lua_ip_to_string},
+       {"__gc", lua_ip_destroy},
+       {NULL, NULL}
+};
+
+static const struct luaL_reg    iplib_f[] = {
+       LUA_INTERFACE_DEF (ip, from_string),
+       {NULL, NULL}
+};
+
+static struct rspamd_lua_ip    *
+lua_check_ip (lua_State * L, gint pos)
+{
+       void *ud = luaL_checkudata (L, pos, "rspamd{ip}");
+
+       luaL_argcheck (L, ud != NULL, pos, "'ip' expected");
+       return ud ? *((struct rspamd_lua_ip **)ud) : NULL;
+}
+
+static gint
+lua_ip_to_table (lua_State *L)
+{
+       struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
+       int max, i;
+       guint8 *ptr;
+
+       if (ip != NULL) {
+               lua_newtable (L);
+               if (ip->af == AF_INET) {
+                       max = 32 / 8;
+               }
+               else {
+                       max = 128 / 8;
+               }
+               ptr = (guint8 *)&ip->data;
+               for (i = 1; i <= max; i ++, ptr ++) {
+                       lua_pushnumber (L, i);
+                       lua_pushnumber (L, *ptr);
+                       lua_settable (L, -2);
+               }
+       }
+       else {
+               lua_pushnil (L);
+       }
+
+       return 1;
+}
+
+static gint
+lua_ip_str_octets (lua_State *L)
+{
+       struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
+       int max, i;
+       guint8 *ptr;
+       char numbuf[4];
+
+       if (ip != NULL) {
+               lua_newtable (L);
+               if (ip->af == AF_INET) {
+                       max = 32 / 8;
+               }
+               else {
+                       max = 128 / 8;
+               }
+               ptr = (guint8 *)&ip->data;
+               for (i = 1; i <= max; i ++, ptr ++) {
+                       rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr);
+                       lua_pushnumber (L, i);
+                       lua_pushstring (L, numbuf);
+                       lua_settable (L, -2);
+               }
+       }
+       else {
+               lua_pushnil (L);
+       }
+
+       return 1;
+}
+
+static gint
+lua_ip_inversed_str_octets (lua_State *L)
+{
+       struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
+       int max, i;
+       guint8 *ptr;
+       char numbuf[4];
+
+       if (ip != NULL) {
+               lua_newtable (L);
+               if (ip->af == AF_INET) {
+                       max = 32 / 8;
+               }
+               else {
+                       max = 128 / 8;
+               }
+               ptr = (guint8 *)&ip->data;
+               ptr += max - 1;
+               for (i = 1; i <= max; i ++, ptr --) {
+                       rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr);
+                       lua_pushnumber (L, i);
+                       lua_pushstring (L, numbuf);
+                       lua_settable (L, -2);
+               }
+       }
+       else {
+               lua_pushnil (L);
+       }
+
+       return 1;
+}
+
+static gint
+lua_ip_to_string (lua_State *L)
+{
+       struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
+       gchar dst[INET6_ADDRSTRLEN + 1];
+
+       if (ip != NULL) {
+               lua_pushstring (L, inet_ntop (ip->af, &ip->data, dst, sizeof (dst)));
+       }
+       else {
+               lua_pushnil (L);
+       }
+
+       return 1;
+}
+
+static gint
+lua_ip_from_string (lua_State *L)
+{
+       struct rspamd_lua_ip *ip, **pip;
+       const gchar *ip_str;
+
+       ip_str = luaL_checkstring (L, 1);
+       if (ip_str) {
+               ip = g_slice_alloc (sizeof (struct rspamd_lua_ip));
+               if (inet_pton (AF_INET, ip_str, &ip->data.ip4) == 1) {
+                       ip->af = AF_INET;
+               }
+               else if (inet_pton (AF_INET6, ip_str, &ip->data.ip6) == 1) {
+                       ip->af = AF_INET6;
+               }
+               else {
+                       g_slice_free1 (sizeof (struct rspamd_lua_ip), ip);
+                       lua_pushnil (L);
+                       return 1;
+               }
+               pip = lua_newuserdata (L, sizeof (struct rspamd_lua_ip *));
+               lua_setclass (L, "rspamd{ip}", -1);
+               *pip = ip;
+       }
+       else {
+               lua_pushnil (L);
+       }
+
+       return 1;
+}
+
+static gint
+lua_ip_destroy (lua_State *L)
+{
+       struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
+
+       if (ip) {
+               g_slice_free1 (sizeof (struct rspamd_lua_ip), ip);
+       }
+
+       return 0;
+}
+
+gint
+luaopen_ip (lua_State * L)
+{
+       luaL_newmetatable (L, "rspamd{ip}");
+       lua_pushstring (L, "__index");
+       lua_pushvalue (L, -2);
+       lua_settable (L, -3);
+
+       lua_pushstring (L, "class");
+       lua_pushstring (L, "rspamd{ip}");
+       lua_rawset (L, -3);
+
+       luaL_register (L, NULL, iplib_m);
+       luaL_register (L, "ip", iplib_f);
+
+       lua_pop (L, 1);                      /* remove metatable from stack */
+
+       return 1;
+}