From: Vladimír Čunát Date: Mon, 20 Feb 2017 10:26:27 +0000 (+0100) Subject: lua: add net.outgoing_{v4,v6} and documentation X-Git-Tag: v1.3.0~23^2~70^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=09645444bd41462ef6cde19a276508f57eb36245;p=thirdparty%2Fknot-resolver.git lua: add net.outgoing_{v4,v6} and documentation Fixes https://gitlab.labs.nic.cz/knot/resolver/issues/158 The naming is inspired by Unbound's "outgoing-interface". --- diff --git a/daemon/README.rst b/daemon/README.rst index 8d62ab648..aa8990179 100644 --- a/daemon/README.rst +++ b/daemon/README.rst @@ -601,6 +601,11 @@ For when listening on ``localhost`` just doesn't cut it. have size of multiplies of 64 (64, 128, 192, ...). Setting padding to value < 2 will disable it. +.. function:: net.outgoing_v4([string address]) + + Get/set the IPv4 address used to perform queries. There is also ``net.outgoing_v6`` for IPv6. + The default is ``nil``, which lets the OS choose any address. + Trust anchors and DNSSEC ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/daemon/bindings.c b/daemon/bindings.c index 26969087c..24f442753 100644 --- a/daemon/bindings.c +++ b/daemon/bindings.c @@ -21,6 +21,7 @@ #include "lib/cache.h" #include "lib/cdb.h" +#include "lib/utils.h" #include "daemon/bindings.h" #include "daemon/worker.h" #include "daemon/tls.h" @@ -421,6 +422,63 @@ static int net_tls_padding(lua_State *L) return 1; } +static int net_outgoing(lua_State *L, int family) +{ + struct worker_ctx *worker = wrk_luaget(L); + union inaddr *addr; + if (family == AF_INET) + addr = (union inaddr*)&worker->out_addr4; + else + addr = (union inaddr*)&worker->out_addr6; + + if (lua_gettop(L) == 0) { /* Return the current value. */ + if (addr->ip.sa_family == AF_UNSPEC) { + lua_pushnil(L); + return 1; + } + if (addr->ip.sa_family != family) { + assert(false); + lua_error(L); + } + char addr_buf[INET6_ADDRSTRLEN]; + int err; + if (family == AF_INET) + err = uv_ip4_name(&addr->ip4, addr_buf, sizeof(addr_buf)); + else + err = uv_ip6_name(&addr->ip6, addr_buf, sizeof(addr_buf)); + if (err) + lua_error(L); + lua_pushstring(L, addr_buf); + return 1; + } + + if ((lua_gettop(L) != 1) || (!lua_isstring(L, 1) && !lua_isnil(L, 1))) { + format_error(L, "net.outgoing_vX takes one address string parameter or nil"); + lua_error(L); + } + + if (lua_isnil(L, 1)) { + addr->ip.sa_family = AF_UNSPEC; + return 1; + } + + const char *addr_str = lua_tostring(L, 1); + int err; + if (family == AF_INET) + err = uv_ip4_addr(addr_str, 0, &addr->ip4); + else + err = uv_ip6_addr(addr_str, 0, &addr->ip6); + if (err) { + format_error(L, "net.outgoing_vX: failed to parse the address"); + lua_error(L); + } + lua_pushboolean(L, true); + return 1; +} + +static int net_outgoing_v4(lua_State *L) { return net_outgoing(L, AF_INET); } +static int net_outgoing_v6(lua_State *L) { return net_outgoing(L, AF_INET6); } + int lib_net(lua_State *L) { static const luaL_Reg lib[] = { @@ -432,6 +490,8 @@ int lib_net(lua_State *L) { "tcp_pipeline", net_pipeline }, { "tls", net_tls }, { "tls_padding", net_tls_padding }, + { "outgoing_v4", net_outgoing_v4 }, + { "outgoing_v6", net_outgoing_v6 }, { NULL, NULL } }; register_lib(L, "net", lib);