From 832c1792ec220b60310d3e99a4ecc56de88a28e4 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 17 Jul 2017 20:37:56 +0200 Subject: [PATCH] dnsdist: Deprecate syntactic sugar functions in 1.2.0 Deprecates: * addAnyTCRule * addDomainBlock * addDomainSpoof * addDomainCNAMESpoof * addPoolRule * addNoRecurseRule * addDisableValidationRule * addQPSPoolRule * setDNSSECPool * addQPSLimit * addDelay --- pdns/dnsdist-console.cc | 22 ++++---- pdns/dnsdist-lua.cc | 23 +++++++- pdns/dnsdistconf.lua | 26 ++++----- pdns/dnsdistdist/docs/advanced/qpslimits.rst | 2 +- pdns/dnsdistdist/docs/advanced/tuning.rst | 3 +- pdns/dnsdistdist/docs/guides/serverpools.rst | 6 +-- pdns/dnsdistdist/docs/rules-actions.rst | 57 +++++++++++++++++--- regression-tests.dnsdist/test_Basics.py | 2 +- regression-tests.dnsdist/test_CheckConfig.py | 2 +- 9 files changed, 98 insertions(+), 45 deletions(-) diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 6a28b5437..b50721f4d 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -272,20 +272,20 @@ const std::vector g_consoleKeywords{ /* keyword, function, parameters, description */ { "addACL", true, "netmask", "add to the ACL set who can use this server" }, { "addAction", true, "DNS rule, DNS action", "add a rule" }, - { "addAnyTCRule", true, "", "generate TC=1 answers to ANY queries received over UDP, moving them to TCP" }, - { "addDelay", true, "domain, n", "delay answers within that domain by n milliseconds" }, - { "addDisableValidationRule", true, "DNS rule", "set the CD flags to 1 for all queries matching the specified domain" }, + { "addAnyTCRule", true, "", "(deprecated) generate TC=1 answers to ANY queries received over UDP, moving them to TCP" }, + { "addDelay", true, "domain, n", "(deprecated) delay answers within that domain by n milliseconds" }, + { "addDisableValidationRule", true, "DNS rule", "(deprecated) set the CD flags to 1 for all queries matching the specified domain" }, { "addDNSCryptBind", true, "\"127.0.0.1:8443\", \"provider name\", \"/path/to/resolver.cert\", \"/path/to/resolver.key\", {reusePort=false, tcpFastOpenSize=0, interface=\"\"}", "listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of `provider name`, using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth optional parameter is a table of parameters" }, - { "addDomainBlock", true, "domain", "block queries within this domain" }, - { "addDomainSpoof", true, "domain, ip[, ip6]", "generate answers for A/AAAA/ANY queries using the ip parameters" }, + { "addDomainBlock", true, "domain", "(deprecated) block queries within this domain" }, + { "addDomainSpoof", true, "domain, ip[, ip6]", "(deprecated) generate answers for A/AAAA/ANY queries using the ip parameters" }, { "addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" }, { "addLocal", true, "addr [, {doTCP=true, reusePort=false, tcpFastOpenSize=0, interface=\"\"}]", "add `addr` to the list of addresses we listen on" }, - { "addLuaAction", true, "x, func", "where 'x' is all the combinations from `addPoolRule`, and func is a function with the parameter `dq`, which returns an action to be taken on this packet. Good for rare packets but where you want to do a lot of processing" }, - { "addLuaResponseAction", true, "x, func", "where 'x' is all the combinations from `addPoolRule`, and func is a function with the parameter `dr`, which returns an action to be taken on this response packet. Good for rare packets but where you want to do a lot of processing" }, - { "addNoRecurseRule", true, "domain", "clear the RD flag for all queries matching the specified domain" }, - { "addPoolRule", true, "domain, pool", "send queries to this domain to that pool" }, - { "addQPSLimit", true, "domain, n", "limit queries within that domain to n per second" }, - { "addQPSPoolRule", true, "x, limit, pool", "like `addPoolRule`, but only select at most 'limit' queries/s for this pool, letting the subsequent rules apply otherwise" }, + { "addLuaAction", true, "x, func", "where 'x' is all the combinations from `addAction`, and func is a function with the parameter `dq`, which returns an action to be taken on this packet. Good for rare packets but where you want to do a lot of processing" }, + { "addLuaResponseAction", true, "x, func", "where 'x' is all the combinations from `addAction`, and func is a function with the parameter `dr`, which returns an action to be taken on this response packet. Good for rare packets but where you want to do a lot of processing" }, + { "addNoRecurseRule", true, "domain", "(deprecated) clear the RD flag for all queries matching the specified domain" }, + { "addPoolRule", true, "domain, pool", "(deprecated) send queries to this domain to that pool" }, + { "addQPSLimit", true, "domain, n", "(deprecated) limit queries within that domain to n per second" }, + { "addQPSPoolRule", true, "x, limit, pool", "(deprecated) like `addPoolRule`, but only select at most 'limit' queries/s for this pool, letting the subsequent rules apply otherwise" }, { "addCacheHitResponseAction", true, "DNS rule, DNS response action", "add a cache hit response rule" }, { "addResponseAction", true, "DNS rule, DNS response action", "add a response rule" }, { "AllowAction", true, "", "let these packets go through" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index c3c58162f..799c10eb1 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -499,6 +499,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addAnyTCRule", []() { setLuaSideEffect(); + warnlog("addAnyTCRule() is deprecated and will be removed in 1.3.0, please use addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction()) instead"); + auto rules=g_rulactions.getCopy(); std::vector >> v; v.push_back({1, std::make_shared(0xff)}); @@ -707,6 +709,7 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addDomainBlock", [](const std::string& domain) { setLuaSideEffect(); + warnlog("addDomainBlock() is deprecated and will be removed in 1.3.0, please use addAction(\"%s\", DropAction()) instead", domain); SuffixMatchNode smn; smn.add(DNSName(domain)); g_rulactions.modify([smn](decltype(g_rulactions)::value_type& rulactions) { @@ -809,6 +812,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addDomainSpoof", [](const std::string& domain, boost::variant>> inp, boost::optional b) { setLuaSideEffect(); + warnlog("addDomainSpoof() is deprecated and will be removed in 1.3.0, please use addAction(\"%s\", SpoofAction(...)) instead", domain); + SuffixMatchNode smn; vector outp; try @@ -840,6 +845,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addDomainCNAMESpoof", [](const std::string& domain, const std::string& cname) { setLuaSideEffect(); + warnlog("addDomainCNAMESpoof() is deprecated and will be removed in 1.3.0, please use addAction(\"%s\", SpoofCNAMEAction(\"%s\")) instead", domain, cname); + SuffixMatchNode smn; try { @@ -1048,6 +1055,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addPoolRule", [](luadnsrule_t var, string pool) { setLuaSideEffect(); + warnlog("addPoolRule() is deprecated and will be removed in 1.3.0, please use addAction(..., PoolAction(\"%s\")) instead", pool); + auto rule=makeRule(var); g_rulactions.modify([rule, pool](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({ @@ -1058,6 +1067,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addNoRecurseRule", [](luadnsrule_t var) { setLuaSideEffect(); + warnlog("addNoRecurseRule() is deprecated and will be removed in 1.3.0, please use addAction(..., NoRecurseAction()) instead"); + auto rule=makeRule(var); g_rulactions.modify([rule](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({ @@ -1068,6 +1079,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addDisableValidationRule", [](luadnsrule_t var) { setLuaSideEffect(); + warnlog("addDisableValidationRule() is deprecated and will be removed in 1.3.0, please use addAction(..., DisableValidationAction()) instead"); + auto rule=makeRule(var); g_rulactions.modify([rule](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({ @@ -1079,6 +1092,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addQPSPoolRule", [](luadnsrule_t var, int limit, string pool) { setLuaSideEffect(); + warnlog("addQPSPoolRule() is deprecated and will be removed in 1.3.0, please use addAction(..., QPSPoolAction(%d, \"%s\")) instead", limit, pool); + auto rule = makeRule(var); g_rulactions.modify([rule, pool,limit](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({ @@ -1089,6 +1104,8 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("setDNSSECPool", [](const std::string& pool) { setLuaSideEffect(); + warnlog("setDNSSECPool() is deprecated and will be removed in 1.3.0, please use addAction(DNSSECRule(), PoolAction(\"%s\")) instead", pool); + g_rulactions.modify([pool](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({std::make_shared(), std::make_shared(pool)}); @@ -1097,15 +1114,19 @@ vector> setupLua(bool client, const std::string& confi g_lua.writeFunction("addQPSLimit", [](luadnsrule_t var, int lim) { setLuaSideEffect(); + warnlog("addQPSLimit() is deprecated and will be removed in 1.3.0, please use addAction(..., QPSAction(%d)) instead", lim); + auto rule = makeRule(var); g_rulactions.modify([lim,rule](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({rule, std::make_shared(lim)}); }); }); - + g_lua.writeFunction("addDelay", [](luadnsrule_t var, int msec) { setLuaSideEffect(); + warnlog("addDelay() is deprecated and will be removed in 1.3.0, please use addAction(..., DelayAction(%d)) instead", msec); + auto rule = makeRule(var); g_rulactions.modify([msec,rule](decltype(g_rulactions)::value_type& rulactions) { rulactions.push_back({rule, diff --git a/pdns/dnsdistconf.lua b/pdns/dnsdistconf.lua index 9d94ae790..ed0b7915d 100644 --- a/pdns/dnsdistconf.lua +++ b/pdns/dnsdistconf.lua @@ -36,15 +36,15 @@ newServer({address="192.168.1.30:5300", pool="abuse"}) -- send the queries for selected domain suffixes to the server -- in the 'abuse' pool -addPoolRule({"ezdns.it.", "xxx."}, "abuse") +addAction({"ezdns.it.", "xxx."}, PoolAction("abuse")) -- send the queries from a selected subnet to the -- abuse pool -addPoolRule("192.168.1.0/24", "abuse") +addAction("192.168.1.0/24", PoolAction("abuse")) -- send the queries for the "com" suffix to the "abuse" -- pool, but only up to 100 qps -addQPSPoolRule("com.", 100, "abuse") +addAction("com.", QPSPoolRule(100, "abuse")) -- declare a Lua action function, routing NAPTR queries -- to the abuse pool @@ -68,10 +68,8 @@ addAction(MaxQPSIPRule(5, 24, 64), DropAction()) topRule() -- drop queries for the following suffixes: -addDomainBlock("powerdns.org.") -addDomainBlock("spectre.") --- this is equivalent to addAction("isis.", DropAction()) -addDomainBlock("isis.") +addAction("powerdns.org.", DropAction()) +addAction("spectre.", DropAction()) -- called before we distribute a question block=newDNSName("powerdns.org.") @@ -92,7 +90,7 @@ end newServer({address="2001:888:2000:1d::2", pool={"auth", "dnssec"}}) newServer({address="2a01:4f8:110:4389::2", pool={"auth", "dnssec"}}) ---setDNSSECPool("dnssec") +--addAction(DNSSECRule(), PoolAction("dnssec")) --topRule() -- split queries between the 'auth' pool and the regular one, @@ -119,20 +117,16 @@ end -- addAction(AllRule(), DropAction()) -- clear the RD flag in queries for powerdns.com. --- addNoRecurseRule("powerdns.com.") --- another way to do the exact same thing: -- addAction("powerdns.com.", NoRecurseAction()) -- set the CD flag in queries for powerdns.com. --- addDisableValidationRule("powerdns.com.") --- or: -- addAction("powerdns.com.", DisableValidationAction()) -- delay all responses for 1000ms -- addAction(AllRule(), DelayAction(1000)) -- truncate ANY queries over UDP only --- addAnyTCRule() +-- addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction()) -- truncate ANY queries over TCP only -- addAction(AndRule({QTypeRule(dnsdist.ANY), TCPRule(true)}), TCAction()) @@ -166,15 +160,15 @@ end -- spoof responses for A, AAAA and ANY for spoof.powerdns.com. -- A queries will get 192.0.2.1, AAAA 2001:DB8::1 and ANY both --- addDomainSpoof("spoof.powerdns.com.", "192.0.2.1", "2001:DB8::1") +-- addAction("spoof.powerdns.com.", SpoofAction({"192.0.2.1", "2001:DB8::1"})) -- spoof responses will multiple records -- A will get 192.0.2.1 and 192.0.2.2, AAAA 20B8::1 and 2001:DB8::2 -- ANY all of that --- addDomainSpoof("spoof.powerdns.com", {"192.0.2.1", "192.0.2.2", "20B8::1", "2001:DB8::2"}) +-- addAction("spoof.powerdns.com", SpoofAction({"192.0.2.1", "192.0.2.2", "20B8::1", "2001:DB8::2"})) -- spoof responses with a CNAME --- addDomainCNAMESpoof("cnamespoof.powerdns.com.", "cname.powerdns.com.") +-- addAction("cnamespoof.powerdns.com.", SpoofCNAMEAction("cname.powerdns.com.")) -- spoof responses in Lua --[[ diff --git a/pdns/dnsdistdist/docs/advanced/qpslimits.rst b/pdns/dnsdistdist/docs/advanced/qpslimits.rst index dc1795b3f..81eeb7da4 100644 --- a/pdns/dnsdistdist/docs/advanced/qpslimits.rst +++ b/pdns/dnsdistdist/docs/advanced/qpslimits.rst @@ -5,7 +5,7 @@ Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by .. code-block:: lua - addDelay(MaxQPSIPRule(5, 32, 48), 100) + addAction(MaxQPSIPRule(5, 32, 48), DelayAction(100)) This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such an address (range) exceeds 5 :term:`qps`, it gets delayed by 100ms. diff --git a/pdns/dnsdistdist/docs/advanced/tuning.rst b/pdns/dnsdistdist/docs/advanced/tuning.rst index 1c90e25d1..e23bd77c6 100644 --- a/pdns/dnsdistdist/docs/advanced/tuning.rst +++ b/pdns/dnsdistdist/docs/advanced/tuning.rst @@ -29,12 +29,11 @@ Large installations are advised to increase the default value at the cost of a s Most of the query processing is done in C++ for maximum performance, but some operations are executed in Lua for maximum flexibility: - * The :func:`blockfilter` function * Rules added by :func:`addLuaAction` * Server selection policies defined via :func:`setServerPolicyLua` or :func:`newServerPolicy` While Lua is fast, its use should be restricted to the strict necessary in order to achieve maximum performance, it might be worth considering using LuaJIT instead of Lua. -When Lua inspection is needed, the best course of action is to restrict the queries sent to Lua inspection by using :func:`addLuaAction` instead of inspecting all queries in the :func:`blockfilter` function. +When Lua inspection is needed, the best course of action is to restrict the queries sent to Lua inspection by using :func:`addLuaAction` with a selector. :program:`dnsdist` design choices mean that the processing of UDP queries is done by only one thread per local bind. This is great to keep lock contention to a low level, but might not be optimal for setups using a lot of processing power, caused for example by a large number of complicated rules. diff --git a/pdns/dnsdistdist/docs/guides/serverpools.rst b/pdns/dnsdistdist/docs/guides/serverpools.rst index c2aa4acee..23e429b0f 100644 --- a/pdns/dnsdistdist/docs/guides/serverpools.rst +++ b/pdns/dnsdistdist/docs/guides/serverpools.rst @@ -25,18 +25,16 @@ We can similarly add clients to the abuse server: .. code-block:: lua - addPoolRule({"192.168.12.0/24", "192.168.13.14"}, "abuse") + addAction({"192.168.12.0/24", "192.168.13.14"}, PoolAction("abuse")) To define a pool that should receive only a :term:`QPS`-limited amount of traffic, do: .. code-block:: lua - addQPSPoolRule("com.", 10000, "gtld-cluster") + addAction("com.", QPSPoolAction(10000, "gtld-cluster")) Traffic exceeding the :term:`QPS` limit will not match that rule, and subsequent rules will apply normally. -Both :func:`addDomainBlock` and addPoolRule end up the list of Rules and Actions (for which see below). - :class:`Servers ` can be added to or removed from pools with the :func:`Server:addPool` and :func:`Server:rmPool` functions respectively: .. code-block:: lua diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index 3b31784e5..dfea1ec4f 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -30,7 +30,7 @@ Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by For example:: - addDelay(MaxQPSIPRule(5, 32, 48), 100) + addAction(MaxQPSIPRule(5, 32, 48), DelayAction(100)) This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such an address (range) exceeds 5 qps, it gets delayed by 100ms. @@ -76,6 +76,8 @@ Rule Generators .. function:: addAnyTCRule() + .. deprecated:: 1.2.0 + Set the TC-bit (truncate) on ANY queries received over UDP. Forcing a retry over TCP. This is equivalent to doing:: @@ -84,26 +86,47 @@ Rule Generators .. function:: addDelay(DNSrule, delay) + .. deprecated:: 1.2.0 + Delay the query for ``delay`` milliseconds before sending to a backend. + This function is deprecated as of 1.2.0, please use instead: + + addAction(DNSRule, DelayAction(delay)) :param DNSRule: The DNSRule to match traffic :param int delay: The delay time in milliseconds. .. function:: addDisableValidationRule(DNSrule) + .. deprecated:: 1.2.0 + Set the CD (Checking Disabled) flag to 1 for all queries matching the DNSRule. - Using this function is equal to using the :func:`DisableValidationAction`. + Using this function is equal to using the :func:`DisableValidationAction` action. .. function:: addDomainBlock(domain) + .. deprecated:: 1.2.0 + Drop all queries for ``domain`` and all names below it. + Deprecated as of 1.2.0, please use instead: + + addAction(domain, DropAction()) :param string domain: The domain name to block .. function:: addDomainSpoof(domain, IPv4[, IPv6]) addDomainSpoof(domain, {IP[,...]}) + .. deprecated:: 1.2.0 + Generate answers for A/AAAA/ANY queries. + This function is deprecated as of 1.2.0, please use: + + addAction(domain, SpoofAction({IP[,...]})) + + or: + + addAction(domain, SpoofAction(IPv4[, IPv6])) :param string domain: Domain name to spoof for :param string IPv4: IPv4 address to spoof in the reply @@ -112,7 +135,11 @@ Rule Generators .. function:: addDomainCNAMESpoof(domain, cname) - Generate CNAME answers for queries. + .. deprecated:: 1.2.0 + + Generate CNAME answers for queries. This function is deprecated as of 1.2.0 in favor of using: + + addAction(domain, SpoofCNAMEAction(cname)) :param string domain: Domain name to spoof for :param string cname: Domain name to add CNAME to @@ -139,18 +166,25 @@ Rule Generators .. function:: addNoRecurseRule(DNSrule) + .. deprecated:: 1.2.0 + Clear the RD flag for all queries matching the rule. + This function is deprecated as of 1.2.0, please use: + + addAction(DNSRule, NoRecurseAction()) :param DNSRule: match queries based on this rule .. function:: addPoolRule(DNSRule, pool) + .. deprecated:: 1.2.0 + Send queries matching the first argument to the pool ``pool``. e.g.:: addPoolRule("example.com", "myPool") - This is equivalent to:: + This function is deprecated as of 1.2.0, this is equivalent to:: addAction("example.com", PoolAction("myPool")) @@ -159,16 +193,23 @@ Rule Generators .. function:: addQPSLimit(DNSrule, limit) + .. deprecated:: 1.2.0 + Limit queries matching the DNSRule to ``limit`` queries per second. All queries over the limit are dropped. + This function is deprecated as of 1.2.0, please use: + + addAction(DNSRule, QPSLimitAction(limit)) :param DNSRule: match queries based on this rule :param int limit: QPS limit for this rule .. function:: addQPSPoolRule(DNSRule, limit, pool) + .. deprecated:: 1.2.0 + Send at most ``limit`` queries/s for this pool, letting the subsequent rules apply otherwise. - This is a convience function for the following syntax:: + This function is deprecated as of 1.2.0, as it is only a convience function for the following syntax:: addAction("192.0.2.0/24", QPSPoolAction(15, "myPool") @@ -182,9 +223,9 @@ Managing Rules Active Rules can be shown with :func:`showRules` and removed with :func:`rmRule`:: - > addQPSLimit("h4xorbooter.xyz.", 10) - > addQPSLimit({"130.161.0.0/16", "145.14.0.0/16"} , 20) - > addQPSLimit({"nl.", "be."}, 1) + > addAction("h4xorbooter.xyz.", QPSLimitAction(10)) + > addAction({"130.161.0.0/16", "145.14.0.0/16"} , QPSLimitAction(20)) + > addAction({"nl.", "be."}, QPSLimitAction(1)) > showRules() # Matches Rule Action 0 0 h4xorbooter.xyz. qps limit to 10 diff --git a/regression-tests.dnsdist/test_Basics.py b/regression-tests.dnsdist/test_Basics.py index e1e797c8f..e9c122e70 100644 --- a/regression-tests.dnsdist/test_Basics.py +++ b/regression-tests.dnsdist/test_Basics.py @@ -9,7 +9,7 @@ class TestBasics(DNSDistTest): _config_template = """ newServer{address="127.0.0.1:%s"} truncateTC(true) - addAnyTCRule() + addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction()) addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(dnsdist.REFUSED)) mySMN = newSuffixMatchNode() mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com.")) diff --git a/regression-tests.dnsdist/test_CheckConfig.py b/regression-tests.dnsdist/test_CheckConfig.py index be973e0c1..ba3befb18 100644 --- a/regression-tests.dnsdist/test_CheckConfig.py +++ b/regression-tests.dnsdist/test_CheckConfig.py @@ -33,7 +33,7 @@ class TestCheckConfig(unittest.TestCase): configTemplate = """ newServer{address="127.0.0.1:53"} truncateTC(true) - addAnyTCRule() + addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction()) addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(dnsdist.REFUSED)) mySMN = newSuffixMatchNode() mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com.")) -- 2.40.0