Skip to content
Snippets Groups Projects
Verified Commit 073b6f11 authored by Vladimír Čunát's avatar Vladimír Čunát Committed by Petr Špaček
Browse files

modules/policy: optimize special domain processing

Running the full special-domain checks is relatively expensive.
parent 40ea5f2e
1 merge request!874performance: lua-related improvements
...@@ -577,28 +577,6 @@ function policy.evaluate(rules, req, query, state) ...@@ -577,28 +577,6 @@ function policy.evaluate(rules, req, query, state)
return return
end end
-- Top-down policy list walk until we hit a match
-- the caller is responsible for reordering policy list
-- from most specific to least specific.
-- Some rules may be chained, in this case they are evaluated
-- as a dependency chain, e.g. r1,r2,r3 -> r3(r2(r1(state)))
policy.layer = {
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
return policy.evaluate(policy.rules, req, req:current(), state) or
policy.evaluate(policy.special_names, req, req:current(), state) or
state
end,
finish = function(state, req)
-- Optimization for the typical case
if #policy.postrules == 0 then return state end
-- Don't act on "resolved" cases.
if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
return policy.evaluate(policy.postrules, req, req:current(), state) or state
end
}
-- Add rule to policy list -- Add rule to policy list
function policy.add(rule, postrule) function policy.add(rule, postrule)
-- Compatibility with 1.0.0 API -- Compatibility with 1.0.0 API
...@@ -755,6 +733,7 @@ policy.todnames(private_zones) ...@@ -755,6 +733,7 @@ policy.todnames(private_zones)
policy.rules = {} policy.rules = {}
policy.postrules = {} policy.postrules = {}
policy.special_names = { policy.special_names = {
-- XXX: beware of special_names_optim() when modifying these filters
{ {
cb=policy.suffix_common(policy.DENY_MSG( cb=policy.suffix_common(policy.DENY_MSG(
'Blocking is mandated by standards, see references on ' 'Blocking is mandated by standards, see references on '
...@@ -789,4 +768,44 @@ policy.special_names = { ...@@ -789,4 +768,44 @@ policy.special_names = {
}, },
} }
-- Return boolean; false = no special name may apply, true = some might apply.
-- The point is to *efficiently* filter almost all QNAMEs that do not apply.
local function special_names_optim(req, sname)
local qname_size = req.qsource.packet.qname_size
if qname_size < 9 then return true end -- don't want to special-case bad array access
local root = sname + qname_size - 1
return
-- .a???. or .t???.
(root[-5] == 4 and (root[-4] == 97 or root[-4] == 116))
-- .on???. or .in?????. or lo???. or *ost.
or (root[-6] == 5 and root[-5] == 111 and root[-4] == 110)
or (root[-8] == 7 and root[-7] == 105 and root[-6] == 110)
or (root[-6] == 5 and root[-5] == 108 and root[-4] == 111)
or (root[-3] == 111 and root[-2] == 115 and root[-1] == 116)
end
-- Top-down policy list walk until we hit a match
-- the caller is responsible for reordering policy list
-- from most specific to least specific.
-- Some rules may be chained, in this case they are evaluated
-- as a dependency chain, e.g. r1,r2,r3 -> r3(r2(r1(state)))
policy.layer = {
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
local qry = req:current()
return policy.evaluate(policy.rules, req, qry, state)
or (special_names_optim(req, qry.sname)
and policy.evaluate(policy.special_names, req, qry, state))
or state
end,
finish = function(state, req)
-- Optimization for the typical case
if #policy.postrules == 0 then return state end
-- Don't act on "resolved" cases.
if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
return policy.evaluate(policy.postrules, req, req:current(), state) or state
end
}
return policy return policy
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