]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add `QNameSuffixRule`
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 11 Dec 2023 09:55:30 +0000 (10:55 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 11 Dec 2023 09:55:30 +0000 (10:55 +0100)
An easier to type alias to `SuffixMatchNodeRule`, as suggested
by HÃ¥kan Lindqvist.

pdns/dnsdist-lua-rules.cc
pdns/dnsdistdist/docs/rules-actions.rst
regression-tests.dnsdist/test_Basics.py
regression-tests.dnsdist/test_RulesActions.py

index 9cbeec7529d6d304cae6b2d34f3ccc4715d4c53f..502421c2c6b416ba0bc3f39c154211137469b3fa 100644 (file)
@@ -283,6 +283,29 @@ static boost::optional<T> getRuleFromSelector(const std::vector<T>& rules, const
   return boost::none;
 }
 
+namespace
+{
+std::shared_ptr<DNSRule> qnameSuffixRule(const boost::variant<const SuffixMatchNode&, std::string, const LuaArray<std::string>> names, boost::optional<bool> quiet)
+{
+  if (names.type() == typeid(string)) {
+    SuffixMatchNode smn;
+    smn.add(DNSName(*boost::get<std::string>(&names)));
+    return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
+  }
+
+  if (names.type() == typeid(LuaArray<std::string>)) {
+    SuffixMatchNode smn;
+    for (const auto& str : *boost::get<const LuaArray<std::string>>(&names)) {
+      smn.add(DNSName(str.second));
+    }
+    return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
+  }
+
+  const auto& smn = *boost::get<const SuffixMatchNode&>(&names);
+  return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
+}
+}
+
 // NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
 void setupLuaRules(LuaContext& luaCtx)
 {
@@ -521,24 +544,7 @@ void setupLuaRules(LuaContext& luaCtx)
       return std::shared_ptr<DNSRule>(new SNIRule(name));
   });
 
-  luaCtx.writeFunction("SuffixMatchNodeRule", [](const boost::variant<const SuffixMatchNode&, std::string, const LuaArray<std::string>> names, boost::optional<bool> quiet) {
-    if (names.type() == typeid(string)) {
-      SuffixMatchNode smn;
-      smn.add(DNSName(*boost::get<std::string>(&names)));
-      return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
-    }
-
-    if (names.type() == typeid(LuaArray<std::string>)) {
-      SuffixMatchNode smn;
-      for (const auto& str : *boost::get<const LuaArray<std::string>>(&names)) {
-        smn.add(DNSName(str.second));
-      }
-      return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
-    }
-
-    const auto& smn = *boost::get<const SuffixMatchNode&>(&names);
-    return std::shared_ptr<DNSRule>(new SuffixMatchNodeRule(smn, quiet ? *quiet : false));
-  });
+  luaCtx.writeFunction("SuffixMatchNodeRule", qnameSuffixRule);
 
   luaCtx.writeFunction("NetmaskGroupRule", [](const boost::variant<const NetmaskGroup&, std::string, const LuaArray<std::string>> netmasks, boost::optional<bool> src, boost::optional<bool> quiet) {
     if (netmasks.type() == typeid(string)) {
@@ -612,6 +618,8 @@ void setupLuaRules(LuaContext& luaCtx)
       return std::shared_ptr<DNSRule>(new QNameRule(DNSName(qname)));
     });
 
+  luaCtx.writeFunction("QNameSuffixRule", qnameSuffixRule);
+
   luaCtx.writeFunction("QTypeRule", [](boost::variant<unsigned int, std::string> str) {
       uint16_t qtype;
       if (auto dir = boost::get<unsigned int>(&str)) {
index b4266f05aa9dbac12f2aa8d4642659c75a40d909..31895927b9234c469a43d535c8f1452b0d2f6475 100644 (file)
@@ -73,7 +73,7 @@ The regex is applied case insensitively.
 
 Alternatively, if compiled in, :func:`RE2Rule` provides similar functionality, but against libre2.
 
-Note that to check if a name is in a list of domains, :func:`SuffixMatchNodeRule` is preferred over complex regular expressions or multiple instances of :func:`RegexRule`.
+Note that to check if a name is in a list of domains, :func:`QNameSuffixRule` is preferred over complex regular expressions or multiple instances of :func:`RegexRule`.
 
 Rule Generators
 ---------------
@@ -154,7 +154,7 @@ For Rules related to the incoming query:
     Added ``name`` to the ``options``.
 
   .. versionchanged:: 1.9.0
-    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead
 
   Add a Rule and Action to the existing rules.
   If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
@@ -299,7 +299,7 @@ For Rules related to responses:
     Added ``name`` to the ``options``.
 
   .. versionchanged:: 1.9.0
-    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead
 
   Add a Rule and Action for responses to the existing rules.
   If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
@@ -362,7 +362,7 @@ Functions for manipulating Cache Hit Response Rules:
     Added ``name`` to the ``options``.
 
   .. versionchanged:: 1.9.0
-    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead
 
   Add a Rule and ResponseAction for Cache Hits to the existing rules.
   If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
@@ -422,7 +422,7 @@ Functions for manipulating Cache Inserted Response Rules:
   .. versionadded:: 1.8.0
 
   .. versionchanged:: 1.9.0
-    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead
 
   Add a Rule and ResponseAction that is executed after a cache entry has been inserted to the existing rules.
   If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
@@ -479,7 +479,7 @@ Functions for manipulating Self-Answered Response Rules:
     Added ``name`` to the ``options``.
 
   .. versionchanged:: 1.9.0
-    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead
 
   Add a Rule and Action for Self-Answered queries to the existing rules.
   If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`.
@@ -761,10 +761,29 @@ These ``DNSRule``\ s be one of the following items:
 
    Matches if the set contains exact qname.
 
-   To match subdomain names, see :func:`SuffixMatchNodeRule`.
+   To match subdomain names, see :func:`QNameSuffixRule`.
 
    :param DNSNameSet set: Set with qnames.
 
+.. function:: QNameSuffixRule(suffixes [, quiet@)
+
+  .. versionadded:: 1.9.0
+
+  Matches based on a group of domain suffixes for rapid testing of membership.
+  The first parameter, ``suffixes``, can be a string, list of strings or a class:`SuffixMatchNode` object created with :func:`newSuffixMatchNode`.
+  Pass true as second parameter to prevent listing of all domains matched.
+
+  To match domain names exactly, see :func:`QNameSetRule`.
+
+  This rule existed before 1.9.0 but was called :func:`SuffixMatchNodeRule`, only accepting a :class:`SuffixMatchNode` parameter.
+
+  :param suffixes: A string, list of strings, or a :class:`SuffixMatchNode` to match on
+  :param bool quiet: Do not display the list of matched domains in Rules. Default is false.
+
+   Matches queries with the specified qname exactly.
+
+   :param string qname: Qname to match
+
 .. function:: QNameLabelsCountRule(min, max)
 
   Matches if the qname has less than ``min`` or more than ``max`` labels.
@@ -870,6 +889,8 @@ These ``DNSRule``\ s be one of the following items:
 
   To match domain names exactly, see :func:`QNameSetRule`.
 
+  Since 1.9.0, this rule can also be used via the alias :func:`QNameSuffixRule`.
+
   :param SuffixMatchNode smn: A string, list of strings, or a :class:`SuffixMatchNode` to match on
   :param bool quiet: Do not display the list of matched domains in Rules. Default is false.
 
@@ -945,7 +966,7 @@ Convenience Functions
 .. function:: makeRule(rule)
 
   .. versionchanged:: 1.9.0
-    This function is deprecated, please use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead
+    This function is deprecated, please use :func:`NetmaskGroupRule` or :func:`QnameSuffixRule` instead
 
   Make a :func:`NetmaskGroupRule` or a :func:`SuffixMatchNodeRule`, depending on how it is called.
   The `rule` parameter can be a string, or a list of strings, that should contain either:
index 241ca32692abad50789f2f2a3db12db730e60841..6292ab75b005d675af2d51e520eb0f074633d179 100644 (file)
@@ -13,7 +13,7 @@ class TestBasics(DNSDistTest):
     mySMN = newSuffixMatchNode()
     mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com."))
     addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(DNSRCode.NOTIMP))
-    addAction(SuffixMatchNodeRule({"drop.test.powerdns.com.", "drop2.test.powerdns.com."}), DropAction())
+    addAction(QNameSuffixRule({"drop.test.powerdns.com.", "drop2.test.powerdns.com."}), DropAction())
     addAction(AndRule({QTypeRule(DNSQType.A),QNameRule("ds9a.nl")}), SpoofAction("1.2.3.4"))
     addAction(newDNSName("dnsname.addaction.powerdns.com."), RCodeAction(DNSRCode.REFUSED))
     addAction({newDNSName("dnsname-table1.addaction.powerdns.com."), newDNSName("dnsname-table2.addaction.powerdns.com.")}, RCodeAction(DNSRCode.REFUSED))
index bdabfc3b49efb5217a16b81c5841f657ad7934df..4299fbc8faff5ba070c3024485a7e5e9544beee1 100644 (file)
@@ -14,7 +14,7 @@ class TestAdvancedAllow(DNSDistTest):
 
     _config_template = """
     addAction(AllRule(), NoneAction())
-    addAction(SuffixMatchNodeRule("allowed.advanced.tests.powerdns.com."), AllowAction())
+    addAction(QNameSuffixRule("allowed.advanced.tests.powerdns.com."), AllowAction())
     addAction(AllRule(), DropAction())
     newServer{address="127.0.0.1:%s"}
     """