Commit 732a6616 authored by Vladimír Čunát's avatar Vladimír Čunát Committed by Petr Špaček

view: change :addr to a more natural semantics

Continue executing :addr rules until a non-chain action is executed.
Before this, the only the first match in view:addr rules got a chance,
even though the inner policy rule might not trigger in that case
or be a chain action.
parent c5f04144
Knot Resolver 3.x.y (201y-mm-dd) Knot Resolver 3.x.y (201y-mm-dd)
================================ ================================
Incompatible changes
--------------------
- view module: keep trying rules until a "non-chain" action is executed.
This improves consistency with the policy module.
New features New features
------------ ------------
- module edns_keepalive to implement server side of RFC 7828 (#408) - module edns_keepalive to implement server side of RFC 7828 (#408)
......
...@@ -15,6 +15,8 @@ There are two identification mechanisms: ...@@ -15,6 +15,8 @@ There are two identification mechanisms:
- identifies the client based on a TSIG key - identifies the client based on a TSIG key
You can combine this information with :ref:`policy <mod-policy>` rules. You can combine this information with :ref:`policy <mod-policy>` rules.
Just as with policies, the rules for a request get tried until one "non-chain"
action is executed.
.. code-block:: lua .. code-block:: lua
......
...@@ -29,31 +29,46 @@ local function match_subnet(family, subnet, bitlen, addr) ...@@ -29,31 +29,46 @@ local function match_subnet(family, subnet, bitlen, addr)
return (family == addr:family()) and (C.kr_bitcmp(subnet, addr:ip(), bitlen) == 0) return (family == addr:family()) and (C.kr_bitcmp(subnet, addr:ip(), bitlen) == 0)
end end
-- @function Find view for given request -- @function Execute a policy callback (may be nil);
local function evaluate(_, req) -- return boolean: whether to continue trying further rules.
local function execute(state, req, match_cb)
if match_cb == nil then return false end
local action = match_cb(req, req:current())
if action == nil then return false end
local next_state = action(state, req)
if next_state then -- Not a chain rule,
req.state = next_state
return true
else
return false
end
end
-- @function Try all the rules in order, until a non-chain rule gets executed.
local function evaluate(state, req)
-- Try :tsig first.
local client_key = req.qsource.packet.tsig_rr local client_key = req.qsource.packet.tsig_rr
local match_cb = (client_key ~= nil) and view.key[client_key:owner()] or nil local match_cb = (client_key ~= nil) and view.key[client_key:owner()] or nil
-- Search subnets otherwise if execute(state, req, match_cb) then return end
if match_cb == nil then -- Then try :addr by the source.
if req.qsource.addr ~= nil then if req.qsource.addr ~= nil then
for i = 1, #view.src do for i = 1, #view.src do
local pair = view.src[i] local pair = view.src[i]
if match_subnet(pair[1], pair[2], pair[3], req.qsource.addr) then if match_subnet(pair[1], pair[2], pair[3], req.qsource.addr) then
match_cb = pair[4] match_cb = pair[4]
break if execute(state, req, match_cb) then return end
end
end end
elseif req.qsource.dst_addr ~= nil then end
for i = 1, #view.dst do -- Finally try :addr by the destination.
local pair = view.dst[i] elseif req.qsource.dst_addr ~= nil then
if match_subnet(pair[1], pair[2], pair[3], req.qsource.dst_addr) then for i = 1, #view.dst do
match_cb = pair[4] local pair = view.dst[i]
break if match_subnet(pair[1], pair[2], pair[3], req.qsource.dst_addr) then
end match_cb = pair[4]
if execute(state, req, match_cb) then return end
end end
end end
end end
return match_cb
end end
-- @function Return policy based on source address -- @function Return policy based on source address
...@@ -87,17 +102,8 @@ view.layer = { ...@@ -87,17 +102,8 @@ view.layer = {
begin = function(state, req) begin = function(state, req)
if state == kres.FAIL then return state end if state == kres.FAIL then return state end
req = kres.request_t(req) req = kres.request_t(req)
local match_cb = evaluate(view, req) evaluate(state, req)
if match_cb ~= nil then return req.state
local action = match_cb(req, req:current())
if action then
local next_state = action(state, req)
if next_state then -- Not a chain rule,
return next_state -- stop on first match
end
end
end
return state
end end
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment