]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
modules/policy: make actions usable in postrules
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 4 Dec 2019 08:18:57 +0000 (09:18 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 2 Apr 2020 12:35:41 +0000 (14:35 +0200)
DENY, DENY_MSG, DROP, REFUSE and TC will now clear the _selected RRs.
I believe that's what people usually expect of these actions anyway.

modules/policy/policy.lua

index 683c68a968e7d48268e24655afdd613b35ec08bc..b413eb07a6a4914755bdf74af29b972a12cb54c7 100644 (file)
@@ -506,6 +506,21 @@ function policy.slice_randomize_psl(seed)
        end
 end
 
+-- Prepare for making an answer from scratch.  (Return the packet for convenience.)
+local function answer_clear(req)
+       -- If we're in postrules, previous resolving might have chosen some RRs
+       -- for inclusion in the answer, so we need to avoid those.
+       -- *_selected arrays are in mempool, so explicit deallocation is not necessary.
+       req.answ_selected.len = 0
+       req.auth_selected.len = 0
+       req.add_selected.len = 0
+
+       -- Let's be defensive and clear the answer, too.
+       local pkt = req.answer
+       pkt:clear_payload()
+       return pkt
+end
+
 function policy.DENY_MSG(msg)
        if msg and (type(msg) ~= 'string' or #msg >= 255) then
                error('DENY_MSG: optional msg must be string shorter than 256 characters')
@@ -513,7 +528,7 @@ function policy.DENY_MSG(msg)
 
        return function (_, req)
                -- Write authority information
-               local answer = req.answer
+               local answer = answer_clear(req)
                ffi.C.kr_pkt_make_auth_header(answer)
                answer:rcode(kres.rcode.NXDOMAIN)
                answer:begin(kres.section.AUTHORITY)
@@ -600,26 +615,28 @@ policy.DEBUG_CACHE_MISS = policy.DEBUG_IF(
 
 policy.DENY = policy.DENY_MSG() -- compatibility with < 2.0
 
-function policy.DROP(_, _)
+function policy.DROP(_, req)
+       answer_clear(req)
        return kres.FAIL
 end
 
 function policy.REFUSE(_, req)
-       local answer = req.answer
+       local answer = answer_clear(req)
        answer:rcode(kres.rcode.REFUSED)
        answer:ad(false)
        return kres.DONE
 end
 
 function policy.TC(state, req)
-       local answer = req.answer
-       if answer.max_size ~= 65535 then
-               answer:tc(1) -- ^ Only UDP queries
-               answer:ad(false)
-               return kres.DONE
-       else
+       -- Skip non-UDP queries
+       if req.answer.max_size == 65535 then
                return state
        end
+
+       local answer = answer_clear(req)
+       answer:tc(1)
+       answer:ad(false)
+       return kres.DONE
 end
 
 function policy.QTRACE(_, req)