From: Kees Monshouwer Date: Wed, 3 Jun 2015 18:32:18 +0000 (+0200) Subject: dnsname: isRoot() empty() clear() toStringNoDot() makeRelative() labelReverse() X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~58^2~21^2~5^2~48 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a61e8e59df2896fee9b31e0584c430f223d50272;p=pdns dnsname: isRoot() empty() clear() toStringNoDot() makeRelative() labelReverse() --- diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index a926b7c13..3b4f13038 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -18,6 +18,7 @@ DNSName::DNSName(const char* p) { + d_empty=false; auto labels = segmentDNSName(p); for(const auto& e : labels) appendRawLabel(e); @@ -25,6 +26,7 @@ DNSName::DNSName(const char* p) DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed) { + d_empty=false; d_recurse = 0; packetParser(pos, len, offset, uncompress, qtype, qclass, consumed); } @@ -71,19 +73,23 @@ void DNSName::packetParser(const char* pos, int len, int offset, bool uncompress } -std::string DNSName::toString() const +std::string DNSName::toString(const std::string& separator, const bool trailing) const { - if(d_storage.empty()) // I keep wondering if there is some deeper meaning to the need to do this - return "."; + if (d_empty) + return ""; + if(d_storage.empty() && trailing) // I keep wondering if there is some deeper meaning to the need to do this + return separator; std::string ret; for(const auto& s : getRawLabels()) { - ret+= escapeLabel(s) + "."; + ret+= escapeLabel(s) + separator; } - return ret; + return ret.substr(0, ret.size()-!trailing); } std::string DNSName::toDNSString() const { + if (d_empty) + return ""; string ret(d_storage.c_str(), d_storage.length()); ret.append(1,(char)0); return ret; @@ -96,6 +102,8 @@ size_t DNSName::length() const { // are WE part of parent bool DNSName::isPartOf(const DNSName& parent) const { + if(parent.d_empty || d_empty) + return false; if(parent.d_storage.empty()) return true; if(parent.d_storage.size() > d_storage.size()) @@ -115,6 +123,29 @@ bool DNSName::isPartOf(const DNSName& parent) const return false; } +DNSName DNSName::makeRelative(const DNSName& zone) const +{ + DNSName ret(*this); + if (ret.isPartOf(zone)) { + ret.d_storage.erase(ret.d_storage.size()-zone.d_storage.size()); + } else + ret.clear(); + return ret; +} + +DNSName DNSName::labelReverse() const +{ + DNSName ret; + if (!d_empty) { + vector l=getRawLabels(); + while(!l.empty()) { + ret.appendRawLabel(l.back()); + l.pop_back(); + } + } + return ret; +} + void DNSName::appendRawLabel(const std::string& label) { if(label.empty()) @@ -124,6 +155,7 @@ void DNSName::appendRawLabel(const std::string& label) if(d_storage.size() + label.size() > 253) // reserve two bytes, one for length and one for the root label throw std::range_error("name too long to append"); + d_empty=false; d_storage.append(1, (char)label.size()); d_storage.append(label.c_str(), label.length()); } @@ -137,6 +169,7 @@ void DNSName::prependRawLabel(const std::string& label) if(d_storage.size() + label.size() > 253) // reserve two bytes, one for length and one for the root label throw std::range_error("name too long to prepend"); + d_empty=false; string_t prep(1, (char)label.size()); prep.append(label.c_str(), label.size()); d_storage = prep+d_storage; @@ -191,7 +224,7 @@ void DNSName::trimToLabels(unsigned int to) bool DNSName::operator==(const DNSName& rhs) const { - if(rhs.d_storage.size() != d_storage.size()) + if(rhs.d_empty != d_empty || rhs.d_storage.size() != d_storage.size()) return false; auto us = d_storage.crbegin(); diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index da3effe8c..15d830bd3 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -26,7 +26,7 @@ class DNSName { public: - DNSName() {} //!< Constructs the root name + DNSName() : d_empty(true) {} //!< Don't constructs the root name DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation DNSName(const std::string& str) : DNSName(str.c_str()) {} //!< Constructs from a human formatted, escaped presentation DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); //!< Construct from a DNS Packet, taking the first question @@ -35,17 +35,21 @@ public: bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) bool operator!=(const DNSName& other) const { return !(*this == other); } - std::string toString() const; //!< Our human-friendly, escaped, representation + std::string toString(const std::string& separator=".", const bool trailing=true) const; //!< Our human-friendly, escaped, representation + std::string toStringNoDot() const { return toString(".", false); } std::string toDNSString() const; //!< Our representation in DNS native format void appendRawLabel(const std::string& str); //!< Append this unescaped label void prependRawLabel(const std::string& str); //!< Prepend this unescaped label std::vector getRawLabels() const; //!< Individual raw unescaped labels bool chopOff(); //!< Turn www.powerdns.com. into powerdns.com., returns false for . + DNSName makeRelative(const DNSName& zone) const; + DNSName labelReverse() const; bool isWildcard() const; unsigned int countLabels() const; - bool empty() const { return countLabels()==0; } // FIXME remove me? size_t length() const; // FIXME remove me? - void clear() { trimToLabels(0); } // FIXME remove me? + bool empty() const { return d_empty; } + bool isRoot() const { return !d_empty && d_storage.empty(); } + void clear() { d_storage.clear(); d_empty=true; } void trimToLabels(unsigned int); DNSName& operator+=(const DNSName& rhs) { @@ -53,6 +57,7 @@ public: throw std::range_error("name too long"); d_storage+=rhs.d_storage; + d_empty&=rhs.d_empty; return *this; } @@ -71,11 +76,13 @@ public: void serialize(Archive &ar, const unsigned int version) { ar & d_storage; + ar & d_empty; } private: // typedef __gnu_cxx::__sso_string string_t; typedef std::string string_t; string_t d_storage; + bool d_empty; int d_recurse; void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); diff --git a/pdns/misc.cc b/pdns/misc.cc index a8f016ccd..6e673a9ab 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -52,6 +52,7 @@ #include #include "iputils.hh" + bool g_singleThreaded; int writen2(int fd, const void *buf, size_t count) @@ -222,12 +223,6 @@ bool endsOn(const string &domain, const string &suffix) return true; } -// REMOVE ME -bool dottedEndsOn(const DNSName &domain, const DNSName &suffix) -{ - return domain.isPartOf(suffix); -} - /** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */ bool dottedEndsOn(const string &domain, const string &suffix) { diff --git a/pdns/packetcache.hh b/pdns/packetcache.hh index 6177e8007..556c81c73 100644 --- a/pdns/packetcache.hh +++ b/pdns/packetcache.hh @@ -122,7 +122,7 @@ private: }; vector d_maps; - MapCombo& getMap(const DNSName& qname) + MapCombo& getMap(const DNSName& qname) { return d_maps[burtle((const unsigned char*)qname.toString().c_str(), qname.toString().length(), 0) % d_maps.size()]; } diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index 8ca5b5d98..325cf68bf 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -263,7 +263,7 @@ vector PacketHandler::getBestDNAMESynth(DNSPacket *p, SOAData ret.push_back(rr); // put in the original rr.qtype = QType::CNAME; rr.qname = prefix + rr.qname; - rr.content = (prefix + rr.content).toString(); + rr.content = (prefix + rr.content).toStringNoDot(); rr.auth = 0; // don't sign CNAME target= rr.content; ret.push_back(rr); diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index 1c5806631..1607f6308 100644 --- a/pdns/test-dnsname_cc.cc +++ b/pdns/test-dnsname_cc.cc @@ -40,15 +40,21 @@ BOOST_AUTO_TEST_CASE(test_basic) { BOOST_CHECK(DNSName("www.ds9a.nl.").toString() == "www.ds9a.nl."); + { // Check root vs empty + DNSName name("."); // root + DNSName parent; // empty + BOOST_CHECK(name != parent); + } + { // Check root part of root DNSName name; DNSName parent; - BOOST_CHECK(name.isPartOf(parent)); + BOOST_CHECK(!name.isPartOf(parent)); } { // Check name part of root DNSName name("a."); - DNSName parent; + DNSName parent("."); BOOST_CHECK(name.isPartOf(parent)); } @@ -82,6 +88,26 @@ BOOST_AUTO_TEST_CASE(test_basic) { BOOST_CHECK(!name.isPartOf(parent)); } + { // Make relative + DNSName name("aaaa.bbb.cc.d."); + DNSName parent("cc.d."); + BOOST_CHECK( name.makeRelative(parent) == DNSName("aaaa.bbb.")); + } + + { // Labelreverse + DNSName name("aaaa.bbb.cc.d."); + BOOST_CHECK( name.labelReverse() == DNSName("d.cc.bbb.aaaa.")); + } + + { // empty() empty + DNSName name; + BOOST_CHECK(name.empty()); + } + + { // empty() root + DNSName name("."); + BOOST_CHECK(!name.empty()); + } DNSName left("ds9a.nl."); left.prependRawLabel("www"); @@ -92,7 +118,7 @@ BOOST_AUTO_TEST_CASE(test_basic) { BOOST_CHECK( left == DNSName("WwW.Ds9A.Nl.com.")); DNSName root; - BOOST_CHECK(root.toString() == "."); + BOOST_CHECK(root.toString() != "."); root.appendRawLabel("www"); root.appendRawLabel("powerdns.com"); @@ -123,7 +149,7 @@ BOOST_AUTO_TEST_CASE(test_basic) { BOOST_CHECK_EQUAL(n.toString(), "powerdns\\.dnsmaster.powerdns.com."); - BOOST_CHECK_EQUAL(DNSName().toString(), "."); + BOOST_CHECK(DNSName().toString() != "."); DNSName p; string label("power"); diff --git a/pdns/test-zoneparser_tng_cc.cc b/pdns/test-zoneparser_tng_cc.cc index 34de26b2d..cd801c83c 100644 --- a/pdns/test-zoneparser_tng_cc.cc +++ b/pdns/test-zoneparser_tng_cc.cc @@ -13,6 +13,7 @@ #include "dns.hh" #include "zoneparser-tng.hh" #include "dnsrecords.hh" +#include "dnsname.hh" #include #include