summaryrefslogtreecommitdiffstats
path: root/daemon/bindings
diff options
context:
space:
mode:
authorOto Šťáva <oto.stava@nic.cz>2022-01-27 15:19:02 +0100
committerOto Šťáva <oto.stava@nic.cz>2022-01-31 09:15:12 +0100
commitd6cfa7f62020ad6b3d43fa811b703603b40346c5 (patch)
tree506beb8188d627abb50cc40e428cef48b9e601cd /daemon/bindings
parentMerge branch 'update-tests' into 'master' (diff)
downloadknot-resolver-d6cfa7f62020ad6b3d43fa811b703603b40346c5.tar.xz
knot-resolver-d6cfa7f62020ad6b3d43fa811b703603b40346c5.zip
daemon/bindings/net: add interface name to link-local IPv6 addresses
Diffstat (limited to 'daemon/bindings')
-rw-r--r--daemon/bindings/net.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/daemon/bindings/net.c b/daemon/bindings/net.c
index ec9c822c..ff6a6c37 100644
--- a/daemon/bindings/net.c
+++ b/daemon/bindings/net.c
@@ -5,6 +5,7 @@
#include "daemon/bindings/impl.h"
#include "contrib/base64.h"
+#include "contrib/cleanup.h"
#include "daemon/network.h"
#include "daemon/tls.h"
@@ -303,6 +304,18 @@ static int net_close(lua_State *L)
return 1;
}
+/** Check whether `addr` points to an `AF_INET6` address and whether the address
+ * is link-local. */
+static bool ip6_link_local(struct sockaddr_in6 *addr)
+{
+ if (addr->sin6_family != AF_INET6)
+ return false;
+
+ /* Link-local: https://tools.ietf.org/html/rfc4291#section-2.4 */
+ const uint8_t prefix[] = { 0xFE, 0x80 };
+ return kr_bitcmp((char *) addr->sin6_addr.s6_addr, (char *) prefix, 10) == 0;
+}
+
/** List available interfaces. */
static int net_interfaces(lua_State *L)
{
@@ -333,7 +346,17 @@ static int net_interfaces(lua_State *L)
} else {
buf[0] = '\0';
}
- lua_pushstring(L, buf);
+
+ if (ip6_link_local(&iface.address.address6)) {
+ /* Link-local IPv6: add %interface prefix */
+ auto_free char *str = NULL;
+ int ret = asprintf(&str, "%s%%%s", buf, iface.name);
+ kr_assert(ret > 0);
+ lua_pushstring(L, str);
+ } else {
+ lua_pushstring(L, buf);
+ }
+
lua_rawseti(L, -2, lua_objlen(L, -2) + 1);
lua_setfield(L, -2, "addr");