From 0d6d892baec6cbafb01ca5e84df6830991929cd3 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 17 Nov 2013 22:26:08 +0000 Subject: [PATCH] Add IP addresses manipulation API to lua. --- src/lua/CMakeLists.txt | 3 +- src/lua/lua_common.c | 1 + src/lua/lua_common.h | 12 +++ src/lua/lua_ip.c | 226 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/lua/lua_ip.c diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index 4713b3405..10606a909 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -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}) diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c index 8017cd086..f60717adf 100644 --- a/src/lua/lua_common.c +++ b/src/lua/lua_common.c @@ -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; } diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h index fd4058c11..d04ad5c01 100644 --- a/src/lua/lua_common.h +++ b/src/lua/lua_common.h @@ -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 index 000000000..862e99a05 --- /dev/null +++ b/src/lua/lua_ip.c @@ -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; +} -- 2.39.5