From: Vladimír Čunát Date: Sun, 27 Jul 2025 07:57:54 +0000 (+0200) Subject: fallback WIP: seems to work, kind-of X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b537f5cb5d305428e7ee45913dd2cf8dc28d176;p=thirdparty%2Fknot-resolver.git fallback WIP: seems to work, kind-of --- diff --git a/daemon/lua/kres-gen-33.lua b/daemon/lua/kres-gen-33.lua index 83269222c..6a5482884 100644 --- a/daemon/lua/kres-gen-33.lua +++ b/daemon/lua/kres-gen-33.lua @@ -373,6 +373,7 @@ _Bool kr_dbg_assertion_abort; int kr_dbg_assertion_fork; const uint32_t KR_RULE_TTL_DEFAULT; const kr_rule_opts_t KR_RULE_OPTS_DEFAULT; +const size_t KR_SOCKADDR_SIZE; typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type, const struct kr_query *qry); @@ -528,6 +529,7 @@ int kr_rule_zonefile(const struct kr_rule_zonefile_config *); int kr_rule_forward(const knot_dname_t *, kr_rule_fwd_flags_t, const struct sockaddr **); int kr_rule_local_address(const char *, const char *, _Bool, uint32_t, kr_rule_tags_t, kr_rule_opts_t); int kr_rule_local_hosts(const char *, _Bool, uint32_t, kr_rule_tags_t, kr_rule_opts_t); +void kr_rule_coalesce_targets(const struct sockaddr **, void *); struct tls_credentials; typedef struct { int sock_type; diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index a5bc6f9a4..5e7fc5b5a 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -172,6 +172,7 @@ ${CDEFS} ${LIBKRES} variables <<-EOF kr_dbg_assertion_fork KR_RULE_TTL_DEFAULT KR_RULE_OPTS_DEFAULT + KR_SOCKADDR_SIZE EOF printf " @@ -320,6 +321,7 @@ ${CDEFS} ${LIBKRES} functions <<-EOF kr_rule_forward kr_rule_local_address kr_rule_local_hosts + kr_rule_coalesce_targets EOF diff --git a/lib/rules/api.h b/lib/rules/api.h index 7e972dde3..f5c06e4d5 100644 --- a/lib/rules/api.h +++ b/lib/rules/api.h @@ -259,6 +259,9 @@ struct kr_rule_zonefile_config { KR_EXPORT int kr_rule_zonefile(const struct kr_rule_zonefile_config *c); +/** FIXME docs */ +KR_EXPORT +void kr_rule_coalesce_targets(const struct sockaddr * targets[], void *data); struct kr_rule_fwd_flags { /// Beware of ABI: this struct is memcpy'd to/from rule DB. diff --git a/lib/rules/forward.c b/lib/rules/forward.c index ef2cf9dad..aee46a917 100644 --- a/lib/rules/forward.c +++ b/lib/rules/forward.c @@ -127,6 +127,13 @@ fallback: return kr_ok(); } + +void kr_rule_coalesce_targets(const struct sockaddr * targets[], void *data) +{ + for (uint8_t *d = data; *targets; ++targets, d += sizeof(union kr_sockaddr)) + memcpy(d, *targets, kr_sockaddr_len(*targets)); +} + int kr_rule_forward(const knot_dname_t *apex, kr_rule_fwd_flags_t flags, const struct sockaddr * targets[]) { diff --git a/lib/utils.c b/lib/utils.c index 5bd476cdb..fc4c6c967 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -273,6 +273,8 @@ void kr_pkt_make_auth_header(knot_pkt_t *pkt) knot_wire_set_aa(pkt->wire); } +const size_t KR_SOCKADDR_SIZE = sizeof(union kr_sockaddr); + const char *kr_inaddr(const struct sockaddr *addr) { if (!addr) { diff --git a/lib/utils.h b/lib/utils.h index 5ca0378e2..387882f54 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -270,6 +270,7 @@ union kr_sockaddr { struct sockaddr_in ip4; struct sockaddr_in6 ip6; }; +KR_EXPORT extern const size_t KR_SOCKADDR_SIZE; /** Simple storage for IPx addresses. */ union kr_in_addr { diff --git a/modules/fallback/fallback.lua b/modules/fallback/fallback.lua new file mode 100644 index 000000000..36e7e12f4 --- /dev/null +++ b/modules/fallback/fallback.lua @@ -0,0 +1,56 @@ +-- SPDX-License-Identifier: GPL-3.0-or-later +local M = {} -- the module + +local ffi = require('ffi') + +function M.config(cfg) + if not cfg then return end + + -- Beware that the timeout is only considered at certain points in time; + -- approximately at multiples of KR_CONN_RTT_MAX. + M.timeout = cfg.timeout or 3*sec + + local targets_split = policy.forward_convert_targets(cfg.options, cfg.targets) + + M.targets_ptr = ffi.new('knot_db_val_t') + M.targets_ptr.len = #cfg.targets * ffi.C.KR_SOCKADDR_SIZE + M.targets_ptr_data = ffi.new('char [?]', #cfg.targets * ffi.C.KR_SOCKADDR_SIZE) + M.targets_ptr.data = M.targets_ptr_data -- TODO: explain + ffi.C.kr_rule_coalesce_targets(targets_split, M.targets_ptr.data) +end + +M.layer = {} +M.layer.produce = function (state, req, pkt) + if not M.targets_ptr or state == kres.FAIL or state == kres.DONE then return state end + + local qry = req:current() + -- Don't do anything for priming, prefetching, etc. + -- TODO: not all cases detected ATM. + if qry.flags.NO_CACHE then return state end + + -- FIXME: also check the source of traffic + local now = ffi.C.kr_now() + local deadline = qry.creation_time_mono + M.timeout + if now > deadline or qry.flags.NO_NS_FOUND then + log_qry(qry, ffi.C.LOG_GRP_SRVSTALE, + ' => no reachable NS, activating fallback forwarding', + kres.dname2str(qry:name())) + + qry.data_src.initialized = true + qry.data_src.all_set = false + qry.data_src.rule_depth = 0 + qry.data_src.flags.is_auth = false + qry.data_src.flags.is_tcp = true -- FIXME + qry.data_src.flags.is_nods = false + qry.data_src.targets_ptr = M.targets_ptr + qry.flags.FORWARD = true + qry.flags.STUB = false + if qry.data_src.flags.is_tcp then qry.flags.TCP = true end + ffi.C.kr_make_query(qry, pkt) + end + + return state +end + +return M + diff --git a/modules/meson.build b/modules/meson.build index 5ffe95f85..d67750f4b 100644 --- a/modules/meson.build +++ b/modules/meson.build @@ -6,6 +6,7 @@ lua_mod_src = [ # add lua modules without separate meson.build files('detect_time_skew/detect_time_skew.lua'), files('dns64/dns64.lua'), files('etcd/etcd.lua'), + files('fallback/fallback.lua'), files('graphite/graphite.lua'), files('prefetch/prefetch.lua'), files('predict/predict.lua'),