From: bert hubert Date: Tue, 16 Jun 2015 11:14:32 +0000 (+0200) Subject: implement a canonical ordering mode for DNSName plus add testcases for it. Preliminar... X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~78^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6d8bc3c6cbffdf42f60080779b9f6d6da0e6d1a3;p=thirdparty%2Fpdns.git implement a canonical ordering mode for DNSName plus add testcases for it. Preliminary slow but correct implementation. --- diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index a3d2778e9d..85f5c277f2 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -1,6 +1,7 @@ #include "dnsname.hh" #include #include + #include "dnswriter.hh" /* raw storage @@ -143,6 +144,13 @@ vector DNSName::getRawLabels() const return ret; } + +bool DNSName::canonCompare(const DNSName& rhs) const +{ + auto ours=getRawLabels(), rhsLabels = rhs.getRawLabels(); + return std::lexicographical_compare(ours.rbegin(), ours.rend(), rhsLabels.rbegin(), rhsLabels.rend(), CIStringCompare()); +} + bool DNSName::chopOff() { if(d_storage.empty()) diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index de5623502c..542c85fa3c 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -47,15 +47,17 @@ public: return *this; } - bool operator<(const DNSName& rhs) const + bool operator<(const DNSName& rhs) const // this delivers _some_ kind of ordering, but not one useful in a DNS context. Really fast though. { return std::lexicographical_compare(d_storage.rbegin(), d_storage.rend(), rhs.d_storage.rbegin(), rhs.d_storage.rend(), [](const char& a, const char& b) { return tolower(a) < tolower(b); - }); + }); // note that this is case insensitive, including on the label lengths } + bool canonCompare(const DNSName& rhs) const; + private: // typedef __gnu_cxx::__sso_string string_t; typedef std::string string_t; @@ -67,6 +69,14 @@ private: static std::string unescapeLabel(const std::string& orig); }; +struct CanonDNSNameCompare: public std::binary_function +{ + bool operator()(const DNSName&a, const DNSName& b) const + { + return a.canonCompare(b); + } +}; + inline DNSName operator+(const DNSName& lhs, const DNSName& rhs) { DNSName ret=lhs; diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index a457a9e12f..1c58066316 100644 --- a/pdns/test-dnsname_cc.cc +++ b/pdns/test-dnsname_cc.cc @@ -267,8 +267,42 @@ BOOST_AUTO_TEST_CASE(test_suffixmatch) { smn.add(DNSName()); // block the root BOOST_CHECK(smn.check(DNSName("a.root-servers.net."))); +} + + +BOOST_AUTO_TEST_CASE(test_concat) { + DNSName first("www."), second("powerdns.com."); + BOOST_CHECK_EQUAL((first+second).toString(), "www.powerdns.com."); +} + +BOOST_AUTO_TEST_CASE(test_compare_naive) { + BOOST_CHECK(DNSName("abc.com.") < DNSName("zdf.com.")); + BOOST_CHECK(DNSName("Abc.com.") < DNSName("zdf.com.")); + BOOST_CHECK(DNSName("Abc.com.") < DNSName("Zdf.com.")); + BOOST_CHECK(DNSName("abc.com.") < DNSName("Zdf.com.")); +} + +BOOST_AUTO_TEST_CASE(test_compare_canonical) { + DNSName lower("bert.com."), higher("alpha.nl."); + BOOST_CHECK(lower.canonCompare(higher)); + + vector vec({"bert.com.", "alpha.nl.", "articles.xxx.", + "Aleph1.powerdns.com.", "ZOMG.powerdns.com.", "aaa.XXX.", "yyy.XXX.", + "test.powerdns.com."}); + sort(vec.begin(), vec.end(), CanonDNSNameCompare()); + // for(const auto& v : vec) + // cerr<<'"'< right({"bert.com.", "Aleph1.powerdns.com.", + "test.powerdns.com.", + "ZOMG.powerdns.com.", + "alpha.nl.", + "aaa.XXX.", + "articles.xxx.", + "yyy.XXX."}); + + BOOST_CHECK(vec==right); } @@ -366,6 +400,7 @@ BOOST_AUTO_TEST_CASE(test_name_length_too_long) { // 256 char name } } + BOOST_AUTO_TEST_CASE(test_invalid_label_length) { // Invalid label length in qname string name("\x02""ns\x07""example\x04""com\x00", 16);