-- Query for AAAA record
resolve('example.com', kres.type.AAAA, kres.class.IN, 0,
- function (answer, req)
+ function (pkt, req)
-- Check answer RCODE
- local pkt = kres.pkt_t(answer)
if pkt:rcode() == kres.rcode.NOERROR then
-- Print matching records
local records = pkt:section(kres.section.ANSWER)
finish_cb = ffi.cast('trace_callback_f',
function (req)
jit.off(true, true) -- JIT for (C -> lua)^2 nesting isn't allowed
- req = kres.request_t(req)
finish(req.answer, req)
finish_cb:free()
end)
.. code-block:: lua
consume = function (state, req, answer)
- answer = kres.pkt_t(answer)
if answer:qtype() == kres.type.NS then
- req = kres.request_t(req)
local qry = req:push(answer:qname(), kres.type.SOA, kres.class.IN)
qry.flags.AWAIT_CUT = true
end
.. code-block:: lua
consume = function (state, req, answer)
- answer = kres.pkt_t(answer)
if state == kres.YIELD then
print('continuing yielded layer')
return kres.DONE
else
if answer:qtype() == kres.type.NS then
- req = kres.request_t(req)
local qry = req:push(answer:qname(), kres.type.SOA, kres.class.IN)
qry.flags.AWAIT_CUT = true
print('planned SOA query, yielding')
.. code-block:: lua
consume = function (state, req, pkt)
- pkt = kres.pkt_t(answer)
print('rcode:', pkt:rcode())
print('query:', kres.dname2str(pkt:qname()), pkt:qclass(), pkt:qtype())
if pkt:rcode() ~= kres.rcode.NOERROR then
.. code-block:: lua
consume = function (state, req, pkt)
- req = kres.request_t(req)
print(req.options)
print(req.state)
-- Check time validity of RRSIGs in priming query
-- luacheck: no unused args
local function check_time_callback(pkt, req)
- pkt = kres.pkt_t(pkt)
if pkt:rcode() ~= kres.rcode.NOERROR then
warn("[detect_time_skew] cannot resolve '.' NS")
return nil
M.layer = { }
function M.layer.consume(state, req, pkt)
if state == kres.FAIL then return state end
- pkt = kres.pkt_t(pkt)
- req = kres.request_t(req)
local qry = req:current()
-- Observe only final answers in IN class where request has no CD flag.
if M.proxy == nil or not qry.flags.RESOLVED
name = qname,
type = qtype,
finish = function (answer, _)
- answer = kres.pkt_t(answer)
rcode = answer:rcode()
answers = answer:section(kres.section.ANSWER)
-- Signal as completed
-- Handle DoT signalling NS domains.
function M.layer.consume(state, _, pkt)
- if state == kres.FAIL then return state end
-- Only successful answers
- pkt = kres.pkt_t(pkt)
+ if state == kres.FAIL then return state end
-- log("%s", pkt:tostring())
local authority = pkt:section(kres.section.AUTHORITY)
local additional = pkt:section(kres.section.ADDITIONAL)
local cond = condition.new()
local waiting, done = false, false
local finish_cb = ffi.cast('trace_callback_f', function (req)
- req = kres.request_t(req)
add_selected_records(answers, req.answ_selected)
add_selected_records(authority, req.auth_selected)
if waiting then
type = qtype,
options = {'TRACE'},
init = function (req)
- req = kres.request_t(req)
req.trace_log = buffer_log_cb
req.trace_finish = finish_cb
end
endpoints = {
['/trace'] = {'text/plain', serve_trace},
}
-}
\ No newline at end of file
+}
begin = function(state, req)
-- Don't act on "resolved" cases.
if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
-
- req = kres.request_t(req)
return policy.evaluate(policy.rules, req, req:current(), state) or
policy.evaluate(policy.special_names, req, req:current(), state) or
state
finish = function(state, req)
-- Don't act on "resolved" cases.
if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
-
- req = kres.request_t(req)
return policy.evaluate(policy.postrules, req, req:current(), state) or state
end
}
-- Prefetch all expiring (sub-)queries immediately after the request finishes.
-- Doing that immediately is simplest and avoids creating (new) large bursts of activity.
finish = function (_, req)
- req = kres.request_t(req)
local qrys = req.rplan.resolved
for i = 0, (tonumber(qrys.len) - 1) do -- size_t doesn't work for some reason
local qry = qrys.at[i]
-- When all response is processed internal.nsset is published in resolver engine
-- luacheck: no unused args
local function address_callback(pkt, req)
- pkt = kres.pkt_t(pkt)
- -- req = kres.request_t(req)
if pkt:rcode() ~= kres.rcode.NOERROR then
warn("[priming] cannot resolve address '%s', type: %d", kres.dname2str(pkt:qname()), pkt:qtype())
else
-- These new queries should be resolved from cache.
-- luacheck: no unused args
local function priming_callback(pkt, req)
- pkt = kres.pkt_t(pkt)
- -- req = kres.request_t(req)
if pkt:rcode() ~= kres.rcode.NOERROR then
warn("[priming] cannot resolve '.' NS, next priming query in %d seconds", priming.retry_time / sec)
internal.event = event.after(priming.retry_time, internal.prime)
if state == kres.FAIL then
return state end
- req = kres.request_t(req)
local qry = req:current()
if qry.flags.CACHED then -- do not slow down cached queries
return state end
- pkt = kres.pkt_t(pkt)
local bad_rr = check_pkt(pkt)
if not bad_rr then
return state end
local function rule()
return function (state, req)
if state == kres.FAIL then return state end
- req = kres.request_t(req)
- local pkt = kres.pkt_t(req.answer)
+ local pkt = req.answer
-- Only successful answers
local records = pkt:section(kres.section.ANSWER)
local ancount = #records
M.layer = {
produce = function (state, req)
- req = kres.request_t(req)
local qry = req:current()
-- Don't do anything for priming, prefetching, etc.
-- TODO: not all cases detected ATM.
local ffi = require('ffi')
function M.layer.finish(state, req, pkt)
- local kreq = kres.request_t(req)
-
if bit.band(state, kres.DONE) == 0 then
return state end -- not resolved yet, exit
- local qry = kreq:resolved()
+ local qry = req:resolved()
if qry.parent ~= nil then
return state end -- an internal query, exit
- local kpkt = kres.pkt_t(pkt)
- if not (kpkt:qtype() == kres.type.A or kpkt:qtype() == kres.type.AAAA) then
+ if not (pkt:qtype() == kres.type.A or pkt:qtype() == kres.type.AAAA) then
return state end
-- fast filter by the length of the first label
end
if not keytag then return state end
- if kreq.rank ~= ffi.C.KR_RANK_SECURE or kreq.answer:cd() then
+ if req.rank ~= ffi.C.KR_RANK_SECURE or req.answer:cd() then
if verbose() then
log('[ta_sentinel] name+type OK but not AD+CD conditions')
end
end
if sentype ~= found then -- expected key is not there, or unexpected key is there
- kpkt:clear_payload()
- kpkt:rcode(kres.rcode.SERVFAIL)
- kpkt:ad(false)
+ pkt:clear_payload()
+ pkt:rcode(kres.rcode.SERVFAIL)
+ pkt:ad(false)
end
return state -- do not break resolution process
end
-- act on DNSKEY queries which were not answered from cache
function M.layer.consume(state, req, _)
- req = kres.request_t(req)
local qry = req:current()
if qry.stype == kres.type.DNSKEY and not qry.flags.CACHED then
send_ta_query(qry:name())
resolve(owner_str, kres.type.DNSKEY, kres.class.IN, 'NO_CACHE',
function (pkt)
-- Schedule itself with updated timeout
- local delay_new = active_refresh(keyset, kres.pkt_t(pkt))
+ local delay_new = active_refresh(keyset, pkt)
delay_new = keyset.refresh_time or ta_update.refresh_time or delay_new
log('[ta_update] next refresh for ' .. owner_str .. ' in '
.. delay_new/hour .. ' hours')
-- Don't act on "resolved" cases.
if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
- req = kres.request_t(req)
evaluate(state, req)
return req.state
end
-- Just listing the *.in-addr.arpa suffixes would be tedious, as there are many.
M.layer = {
produce = function (state, req)
- req = kres.request_t(req)
local qry = req:current()
if qry.stype ~= kres.type.PTR
or bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0
%s
return resolve("%s", kres.type.%s, kres.class.%s, 0,
function (pkt, req)
- pkt = kres.pkt_t(pkt)
- req = kres.request_t(req)
local ok, err = pcall(function () %s end)
if not ok then
print(err)