]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
fallback WIP: seems to work, kind-of
authorVladimír Čunát <vladimir.cunat@nic.cz>
Sun, 27 Jul 2025 07:57:54 +0000 (09:57 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 21 Aug 2025 14:11:56 +0000 (16:11 +0200)
daemon/lua/kres-gen-33.lua
daemon/lua/kres-gen.sh
lib/rules/api.h
lib/rules/forward.c
lib/utils.c
lib/utils.h
modules/fallback/fallback.lua [new file with mode: 0644]
modules/meson.build

index 83269222ca51b42c72421d9a52f45d008bbac38d..6a5482884aba7e63ac77137c0935ab656120e4b5 100644 (file)
@@ -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;
index a5bc6f9a4d18cd4c23b960a28600c4e885a2ea9d..5e7fc5b5a995238e6c122a1fc5070ce4d84c6ade 100755 (executable)
@@ -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
 
 
index 7e972dde3f0ce7446de01f33e4add5a985f6d4d1..f5c06e4d5cd698119af7727906bc6d98e63647a3 100644 (file)
@@ -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.
index ef2cf9dad1f7718a3a63ed91930b133f7ad597fc..aee46a91702b1ecb622a3e0c2342ae67684d2aad 100644 (file)
@@ -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[])
 {
index 5bd476cdb26a55721f74b54afb07562e92e74fc7..fc4c6c9674ed611a2a3a739e04fb9656b12ec69b 100644 (file)
@@ -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) {
index 5ca0378e228203bf4974545b27b10ef798a8d131..387882f54ae389ef673032e4341c2dc365114bd4 100644 (file)
@@ -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 (file)
index 0000000..36e7e12
--- /dev/null
@@ -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
+
index 5ffe95f85843edb3f12ee18b1ee84df3f4979b3b..d67750f4b58641c99bb1ef5c31a08d5df56b711c 100644 (file)
@@ -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'),