diff --git a/tdns/dns-storage.cc b/tdns/dns-storage.cc index 294ac02..ba16885 100644 --- a/tdns/dns-storage.cc +++ b/tdns/dns-storage.cc @@ -21,6 +21,27 @@ bool DNSName::makeRelative(const DNSName& root) return true; } +//! Checks is this DNSName is part of root +bool DNSName::isPartOf(const DNSName& root) const +{ + auto them = root.d_name.crbegin(), us = d_name.crbegin(); + for(;;) { + if(them == root.d_name.crend()) + return true; + if(us == d_name.crend()) + return false; + + if(*them == *us) { + ++them; + ++us; + } + else + break; + } + return false; +} + + //! Append two DNSNames DNSName operator+(const DNSName& a, const DNSName& b) { diff --git a/tdns/dns-storage.hh b/tdns/dns-storage.hh index 127c648..7f6b6d7 100644 --- a/tdns/dns-storage.hh +++ b/tdns/dns-storage.hh @@ -146,6 +146,7 @@ struct DNSName auto size() { return d_name.size(); } void clear() { d_name.clear(); } bool makeRelative(const DNSName& root); + bool isPartOf(const DNSName& root) const; std::string toString() const; bool operator==(const DNSName& rhs) const { diff --git a/tdns/tests.cc b/tdns/tests.cc index 6f0610e..5b115b3 100644 --- a/tdns/tests.cc +++ b/tdns/tests.cc @@ -39,6 +39,18 @@ TEST_CASE("DNSName operations", "[dnsname]") { REQUIRE(test2.makeRelative({"org"})); REQUIRE(test2 == DNSName({"www", "powerdns"})); + + DNSName parent({"powerdns", "com"}), root({}), child({"www", "powerdns", "com"}); + DNSName unrelated({"www", "isc", "org"}); + DNSName Org({"Org"}); + REQUIRE(parent.isPartOf(root)); + REQUIRE(child.isPartOf(parent)); + REQUIRE(child.isPartOf(root)); + REQUIRE(!root.isPartOf(parent)); + REQUIRE(!parent.isPartOf(child)); + REQUIRE(!unrelated.isPartOf(child)); + REQUIRE(!child.isPartOf(unrelated)); + REQUIRE(unrelated.isPartOf(Org)); } TEST_CASE("DNS Messages", "[dnsmessage]") {