]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
policy.ANSWER: minor fixes, mainly around NODATA answers
authorVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 28 Jan 2021 10:37:05 +0000 (11:37 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 8 Feb 2021 13:34:51 +0000 (14:34 +0100)
- return SOA in NODATA answers and allow customizing it
- only call ensure_answer() if really generating an answer
  (otherwise we might e.g. deplete XDP buffers, in extreme cases)

NEWS
modules/policy/policy.lua

diff --git a/NEWS b/NEWS
index fd665ac29224183ca490f879f18a31722dd090a3..bb584f9a0ee18d1dc60ad6e7c7984726bc4e72f5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Bugfixes
 --------
 - view: fail config if bad subnet is specified (!1112)
 - doh2: fix memory leak (!1117)
+- policy.ANSWER: minor fixes, mainly around NODATA answers (!1129)
 
 Incompatible changes
 --------------------
index b13ee798d0f32252e64d001b3eb5c9ff75b6bac1..e7c0cdbfdea885c0a3af9d8597a57890c90e9952 100644 (file)
@@ -200,25 +200,40 @@ function policy.FLAGS(opts_set, opts_clear)
        end
 end
 
+local function mkauth_soa(answer, dname, mname, ttl)
+       if mname == nil then
+               mname = dname
+       end
+       return answer:put(dname, ttl or 10800, answer:qclass(), kres.type.SOA,
+               mname .. '\6nobody\7invalid\0\0\0\0\1\0\0\14\16\0\0\4\176\0\9\58\128\0\0\42\48')
+end
+
 -- Create answer with passed arguments
 function policy.ANSWER(rtable, nodata)
        return function(_, req)
                local qry = req:current()
-               local answer = req:ensure_answer()
-               if answer == nil then return nil end
                local data = rtable[qry.stype]
+               if data == nil and nodata ~= true then
+                       return nil
+               end
+               -- now we're certain we want to generate an answer
 
+               local answer = req:ensure_answer()
+               if answer == nil then return nil end
                ffi.C.kr_pkt_make_auth_header(answer)
-
-               if data == nil then
-                       if nodata == true then
-                               answer:rcode(kres.rcode.NOERROR)
-                               return kres.DONE
+               local ttl = (data or {}).ttl or 1
+               answer:rcode(kres.rcode.NOERROR)
+
+               if data == nil then -- want NODATA, i.e. just a SOA
+                       answer:begin(kres.section.AUTHORITY)
+                       local soa = rtable[kres.type.SOA]
+                       if soa ~= nil then
+                               answer:put(qry.sname, soa.ttl or ttl, qry.sclass, kres.type.SOA,
+                                                       soa.rdata[1] or soa.rdata)
+                       else
+                               mkauth_soa(answer, kres.dname2wire(qry.sname), nil, ttl)
                        end
                else
-                       local ttl = data.ttl or 1
-
-                       answer:rcode(kres.rcode.NOERROR)
                        answer:begin(kres.section.ANSWER)
                        if type(data.rdata) == 'table' then
                                for _, rdato in ipairs(data.rdata) do
@@ -227,20 +242,11 @@ function policy.ANSWER(rtable, nodata)
                        else
                                answer:put(qry.sname, ttl, qry.sclass, qry.stype, data.rdata)
                        end
-
-                       return kres.DONE
                end
+               return kres.DONE
        end
 end
 
-local function mkauth_soa(answer, dname, mname)
-       if mname == nil then
-               mname = dname
-       end
-       return answer:put(dname, 10800, answer:qclass(), kres.type.SOA,
-               mname .. '\6nobody\7invalid\0\0\0\0\1\0\0\14\16\0\0\4\176\0\9\58\128\0\0\42\48')
-end
-
 local dname_localhost = todname('localhost.')
 
 -- Rule for localhost. zone; see RFC6303, sec. 3