From: Andrey Domas Date: Fri, 1 Mar 2019 14:47:05 +0000 (+0300) Subject: DNSNameSet and QNameSetRule X-Git-Tag: auth-4.2.0-rc1~18^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f618bcc6c307db3a75903ef0607c0fa9a791fda;p=thirdparty%2Fpdns.git DNSNameSet and QNameSetRule --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 10f1e91918..6575cd4623 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -389,6 +389,7 @@ const std::vector g_consoleKeywords{ { "newServer", true, "{address=\"ip:port\", qps=1000, order=1, weight=10, pool=\"abuse\", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName=\"a.root-servers.net.\", checkType=\"A\", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source=\"address|interface name|address@interface\", sockets=1}", "instantiate a server" }, { "newServerPolicy", true, "name, function", "create a policy object from a Lua function" }, { "newSuffixMatchNode", true, "", "returns a new SuffixMatchNode" }, + { "newDNSNameSet", true, "", "returns a new DNSNameSet" }, { "NoRecurseAction", true, "", "strip RD bit from the question, let it go through" }, { "PoolAction", true, "poolname", "set the packet into the specified pool" }, { "printDNSCryptProviderFingerprint", true, "\"/path/to/providerPublic.key\"", "display the fingerprint of the provided resolver public key" }, diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index bec7c24bc9..ee966ab588 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -175,6 +175,16 @@ void setupLuaBindings(bool client) g_lua.registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); g_lua.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); }); g_lua.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); }); + g_lua.writeFunction("newDNSNameSet", []() { return DNSNameSet(); }); + + /* DNSNameSet */ + g_lua.registerFunction("toString", [](const DNSNameSet&dns ) { return dns.toString(); }); + g_lua.registerFunction("add", [](DNSNameSet& dns, DNSName& dn) { dns.insert(dn); }); + g_lua.registerFunction("contains", [](DNSNameSet& dns, DNSName& dn) { return dns.find(dn) != dns.end(); }); + g_lua.registerFunction("delete",(size_t (DNSNameSet::*)(const DNSName&)) &DNSNameSet::erase); + g_lua.registerFunction("size",(size_t (DNSNameSet::*)() const) &DNSNameSet::size); + g_lua.registerFunction("clear",(void (DNSNameSet::*)()) &DNSNameSet::clear); + g_lua.registerFunction("empty",(bool (DNSNameSet::*)()) &DNSNameSet::empty); /* SuffixMatchNode */ g_lua.registerFunction("add",(void (SuffixMatchNode::*)(const DNSName&)) &SuffixMatchNode::add); diff --git a/pdns/dnsdist-lua-rules.cc b/pdns/dnsdist-lua-rules.cc index c209d10a50..468c5d479a 100644 --- a/pdns/dnsdist-lua-rules.cc +++ b/pdns/dnsdist-lua-rules.cc @@ -459,4 +459,8 @@ void setupLuaRules() g_lua.registerFunction(std::shared_ptr::*)()>("slice", [](std::shared_ptr tisr) { return std::dynamic_pointer_cast(tisr); }); + + g_lua.writeFunction("QNameSetRule", [](const DNSNameSet& names) { + return std::shared_ptr(new QNameSetRule(names)); + }); } diff --git a/pdns/dnsdistdist/dnsdist-rules.hh b/pdns/dnsdistdist/dnsdist-rules.hh index f343f4f5db..c29e48d65c 100644 --- a/pdns/dnsdistdist/dnsdist-rules.hh +++ b/pdns/dnsdistdist/dnsdist-rules.hh @@ -530,6 +530,7 @@ public: QNameRule(const DNSName& qname) : d_qname(qname) { } + bool matches(const DNSQuestion* dq) const override { return d_qname==*dq->qname; @@ -542,6 +543,22 @@ private: DNSName d_qname; }; +class QNameSetRule : public DNSRule { +public: + QNameSetRule(const DNSNameSet names) : qname_idx(names) {} + + bool matches(const DNSQuestion* dq) const override { + return qname_idx.find(*dq->qname) != qname_idx.end(); + } + + string toString() const override { + std::stringstream ss; + ss << "qname in DNSNameSet(" << qname_idx.size() << " FQDNs)"; + return ss.str(); + } +private: + DNSNameSet qname_idx; +}; class QTypeRule : public DNSRule { diff --git a/pdns/dnsdistdist/docs/reference/dnsnameset.rst b/pdns/dnsdistdist/docs/reference/dnsnameset.rst new file mode 100644 index 0000000000..49b28602c5 --- /dev/null +++ b/pdns/dnsdistdist/docs/reference/dnsnameset.rst @@ -0,0 +1,60 @@ +.. _DNSNameSet: + +DNSNameSet objects +================== + +A :class:`DNSNameSet` object is a set of :class:`DNSName` objects. +Based on std::set (usually implemented as red-black trees). +Creating a ``DNSName`` is done with the :func:`newDNSNameSet`:: + + myset = newDNSNameSet() + +The set can be filled by func:`DNSNameSet:add`:: + + myset.add(newDNSName("domain1.tld")) + myset.add(newDNSName("domain2.tld")) + +Functions and methods of a ``DNSNameSet`` +----------------------------------------- + +.. function:: newDNSNameSet(name) -> DNSNameSet + + Returns the :class:`DNSNameSet`. + +.. class:: DNSNameSet + + A ``DNSNameSet`` object is a set of :class:`DNSName` objects. + + .. method:: DNSNameSet:add(name) + + Adds the name to the set. + + :param DNSName name The name to add. + + .. method:: DNSNameSet:empty() -> bool + + Returns true is the DNSNameSet is empty. + + .. method:: DNSNameSet:clear() + + Clean up the set. + + .. method:: DNSNameSet:toString() -> string + + Returns a human-readable form of the DNSName. + + .. method:: DNSNameSet:size() -> int + + Returns the number of names in the set. + + .. method:: DNSNameSet:delete(name) -> int + + Removes the name from the set. Returns the number of deleted elements. + + :param DNSName name The name to remove. + + .. method:: DNSNameSet:contains(name) -> bool + + Returns true if the set contains the name. + + :param DNSname name The name. diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index 7838f6dd4e..b6f2d980e4 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -610,6 +610,11 @@ These ``DNSRule``\ s be one of the following items: :param string qname: Qname to match +.. function:: QNameSetRule(set) + Matches if the set contains qname. + + :param DNSNameSet set: Set with qnames. + .. function:: QNameLabelsCountRule(min, max) Matches if the qname has less than ``min`` or more than ``max`` labels. diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index f2d9eee21c..0f64376f6e 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include @@ -376,3 +378,11 @@ bool DNSName::operator==(const DNSName& rhs) const } extern const DNSName g_rootdnsname, g_wildcarddnsname; + +struct DNSNameSet: public std::set { + std::string toString() const { + std::ostringstream oss; + std::copy(begin(), end(), std::ostream_iterator(oss, "\n")); + return oss.str(); + } +};