summaryrefslogtreecommitdiffstats
path: root/modules/serve_stale
diff options
context:
space:
mode:
Diffstat (limited to 'modules/serve_stale')
-rw-r--r--modules/serve_stale/.packaging/test.config4
-rw-r--r--modules/serve_stale/README.rst23
-rw-r--r--modules/serve_stale/serve_stale.lua42
-rw-r--r--modules/serve_stale/test.integr/deckard.yaml12
-rw-r--r--modules/serve_stale/test.integr/kresd_config.j270
-rw-r--r--modules/serve_stale/test.integr/module_serve_stale.rpl280
6 files changed, 431 insertions, 0 deletions
diff --git a/modules/serve_stale/.packaging/test.config b/modules/serve_stale/.packaging/test.config
new file mode 100644
index 0000000..362c4ec
--- /dev/null
+++ b/modules/serve_stale/.packaging/test.config
@@ -0,0 +1,4 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+modules.load('serve_stale')
+assert(serve_stale)
+quit()
diff --git a/modules/serve_stale/README.rst b/modules/serve_stale/README.rst
new file mode 100644
index 0000000..6d2230c
--- /dev/null
+++ b/modules/serve_stale/README.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-3.0-or-later
+
+.. _mod-serve_stale:
+
+Serve stale
+===========
+
+Demo module that allows using timed-out records in case kresd is
+unable to contact upstream servers.
+
+By default it allows stale-ness by up to one day,
+after roughly four seconds trying to contact the servers.
+It's quite configurable/flexible; see the beginning of the module source for details.
+See also the RFC draft_ (not fully followed) and :any:`cache.ns_tout`.
+
+Running
+-------
+.. code-block:: lua
+
+ modules = { 'serve_stale < cache' }
+
+.. _draft: https://tools.ietf.org/html/draft-ietf-dnsop-serve-stale-00
+
diff --git a/modules/serve_stale/serve_stale.lua b/modules/serve_stale/serve_stale.lua
new file mode 100644
index 0000000..faf07fb
--- /dev/null
+++ b/modules/serve_stale/serve_stale.lua
@@ -0,0 +1,42 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+local M = {} -- the module
+
+local ffi = require('ffi')
+
+-- Beware that the timeout is only considered at certain points in time;
+-- approximately at multiples of KR_CONN_RTT_MAX.
+M.timeout = 3*sec
+
+M.callback = ffi.cast("kr_stale_cb",
+ function (ttl) --, name, type, qry)
+ --log_debug(ffi.C.SRVSTALE, ' => called back with TTL: ' .. tostring(ttl))
+ if ttl + 3600 * 24 > 0 then -- at most one day stale
+ return 1
+ else
+ return -1
+ end
+ end)
+
+M.layer = {
+ produce = function (state, req)
+ 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
+
+ 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_debug(ffi.C.LOG_GRP_SRVSTALE, ' => no reachable NS, using stale data')
+ qry.stale_cb = M.callback
+ -- TODO: probably start the same request that doesn't stale-serve,
+ -- but first we need some detection of non-interactive / internal requests.
+ -- resolve(kres.dname2str(qry.sname), qry.stype, qry.sclass)
+ end
+
+ return state
+ end,
+}
+
+return M
+
diff --git a/modules/serve_stale/test.integr/deckard.yaml b/modules/serve_stale/test.integr/deckard.yaml
new file mode 100644
index 0000000..c191345
--- /dev/null
+++ b/modules/serve_stale/test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - --noninteractive
+ templates:
+ - modules/serve_stale/test.integr/kresd_config.j2
+ - tests/integration/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/serve_stale/test.integr/kresd_config.j2 b/modules/serve_stale/test.integr/kresd_config.j2
new file mode 100644
index 0000000..8570833
--- /dev/null
+++ b/modules/serve_stale/test.integr/kresd_config.j2
@@ -0,0 +1,70 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+{% raw %}
+modules = { 'serve_stale < cache' }
+
+-- make sure DNSSEC is turned off for tests
+trust_anchors.remove('.')
+
+-- Disable RFC5011 TA update
+if ta_update then
+ modules.unload('ta_update')
+end
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+log_level('debug')
+{% endraw %}
+
+{% if DO_IP6 == "true" %}
+net.ipv6 = true
+{% else %}
+net.ipv6 = false
+{% endif %}
+
+{% if DO_IP4 == "true" %}
+net.ipv4 = true
+{% else %}
+net.ipv4 = false
+{% endif %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()[1].transport.ip == '{{SELF_ADDR}}')
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/serve_stale/test.integr/module_serve_stale.rpl b/modules/serve_stale/test.integr/module_serve_stale.rpl
new file mode 100644
index 0000000..3ab3a84
--- /dev/null
+++ b/modules/serve_stale/test.integr/module_serve_stale.rpl
@@ -0,0 +1,280 @@
+do-ip6: no
+; SPDX-License-Identifier: GPL-3.0-or-later
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Modified iter_resolve.rpl to test serve_stale module.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. 30 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. 30 IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. 30 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 30 IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. 30 IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 30 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 30 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 30 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; K.ROOT-SERVERS.NET.
+; return REFUSED to all queries
+RANGE_BEGIN 101 200
+ ADDRESS 193.0.14.129
+ ADDRESS 192.5.6.30
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 101 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Must be resolved from cache
+STEP 110 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; Expire cached records (TTL is 30)
+STEP 120 TIME_PASSES ELAPSE 60
+
+STEP 121 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Must be resolved from expired cache by serve_stale module
+STEP 130 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END