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);
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;
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[])
{
--- /dev/null
+-- 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
+
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'),