From ae14c1f36a49151dd014cf65c4a7d0869a37ffda Mon Sep 17 00:00:00 2001 From: bert hubert Date: Thu, 5 Nov 2015 12:25:53 +0100 Subject: [PATCH] remove d_empty, length() --- pdns/dnsname.cc | 72 +++++++++++++++++++++++------------------ pdns/dnsname.hh | 27 +++++++++------- pdns/syncres.cc | 2 +- pdns/test-dnsname_cc.cc | 56 ++++++++++++++++++++++---------- 4 files changed, 95 insertions(+), 62 deletions(-) diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index b039de179..8388391d4 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -8,11 +8,8 @@ #include /* raw storage - in DNS label format, without trailing 0. So the root is of length 0. - - www.powerdns.com = 3www8powerdns3com - - a primitive is nextLabel() + in DNS label format, with trailing 0. W/o trailing 0, we are 'empty' + www.powerdns.com = 3www8powerdns3com0 */ std::ostream & operator<<(std::ostream &os, const DNSName& d) @@ -23,16 +20,18 @@ std::ostream & operator<<(std::ostream &os, const DNSName& d) DNSName::DNSName(const char* p) { - d_empty=false; - d_storage.reserve(strlen(p)+1); - auto labels = segmentDNSName(p); - for(const auto& e : labels) - appendRawLabel(e); + if(p[0]=='.' && p[1]==0) { + d_storage.assign(1, (char)0); + } else { + d_storage.reserve(strlen(p)+1); + auto labels = segmentDNSName(p); + for(const auto& e : labels) + appendRawLabel(e); + } } DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed) { - d_empty=false; packetParser(pos, len, offset, uncompress, qtype, qclass, consumed); } @@ -81,22 +80,24 @@ void DNSName::packetParser(const char* pos, int len, int offset, bool uncompress std::string DNSName::toString(const std::string& separator, const bool trailing) const { if (empty()) - return ""; - if(empty() && trailing) // I keep wondering if there is some deeper meaning to the need to do this - return separator; + throw std::out_of_range("Attempt to print an unset dnsname"); + std::string ret; for(const auto& s : getRawLabels()) { ret+= escapeLabel(s) + separator; } + if(ret.empty()) + return trailing ? separator : ""; + return ret.substr(0, ret.size()-!trailing); } std::string DNSName::toDNSString() const { - // if (empty()) - // return ""; + if (empty()) + throw std::out_of_range("Attempt to DNSString an unset dnsname"); + string ret(d_storage.c_str(), d_storage.length()); - ret.append(1,(char)0); return toLower(ret); // toLower or not toLower, that is the question // return ret; } @@ -107,16 +108,15 @@ std::string DNSName::toDNSString() const * @return the total wirelength of the DNSName */ size_t DNSName::wirelength() const { - return d_storage.length() + 1; + return d_storage.length(); } -// are WE part of parent +// Are WE part of parent bool DNSName::isPartOf(const DNSName& parent) const { if(parent.empty() || empty()) - return false; - if(parent.d_storage.empty()) - return true; + throw std::out_of_range("empty dnsnames aren't part of anything"); + if(parent.d_storage.size() > d_storage.size()) return false; @@ -144,6 +144,7 @@ void DNSName::makeUsRelative(const DNSName& zone) { if (isPartOf(zone)) { d_storage.erase(d_storage.size()-zone.d_storage.size()); + d_storage.append(1, (char)0); // put back the trailing 0 } else clear(); @@ -168,12 +169,17 @@ void DNSName::appendRawLabel(const std::string& label) throw std::range_error("no such thing as an empty label to append"); if(label.size() > 63) throw std::range_error("label too long to append"); - if(d_storage.size() + label.size() > 253) // reserve two bytes, one for length and one for the root label + if(d_storage.size() + label.size() > 254) // 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()); + if(d_storage.empty()) { + d_storage.append(1, (char)label.size()); + } + else { + *d_storage.rbegin()=(char)label.size(); + } d_storage.append(label.c_str(), label.length()); + d_storage.append(1, (char)0); } void DNSName::prependRawLabel(const std::string& label) @@ -182,10 +188,12 @@ void DNSName::prependRawLabel(const std::string& label) throw std::range_error("no such thing as an empty label to prepend"); if(label.size() > 63) throw std::range_error("label too long to prepend"); - if(d_storage.size() + label.size() > 253) // reserve two bytes, one for length and one for the root label + if(d_storage.size() + label.size() > 254) // reserve two bytes, one for length and one for the root label throw std::range_error("name too long to prepend"); - d_empty=false; + if(d_storage.empty()) + d_storage.append(1, (char)0); + string_t prep(1, (char)label.size()); prep.append(label.c_str(), label.size()); d_storage = prep+d_storage; @@ -201,8 +209,8 @@ vector DNSName::getRawLabels() const { vector ret; - // 3www4ds9a2nl - for(const char* p = d_storage.c_str(); p < d_storage.c_str() + d_storage.size(); p+=*p+1) + // 3www4ds9a2nl0 + for(const char* p = d_storage.c_str(); p < d_storage.c_str() + d_storage.size() && *p; p+=*p+1) ret.push_back({p+1, (unsigned int)*p}); // XXX FIXME return ret; } @@ -210,7 +218,7 @@ vector DNSName::getRawLabels() const bool DNSName::chopOff() { - if(d_storage.empty()) + if(d_storage.empty() || d_storage[0]==0) return false; d_storage = d_storage.substr((unsigned int)d_storage[0]+1); return true; @@ -227,7 +235,7 @@ bool DNSName::isWildcard() const unsigned int DNSName::countLabels() const { unsigned int count=0; - for(const char* p = d_storage.c_str(); p < d_storage.c_str() + d_storage.size(); p+=*p+1) + for(const char* p = d_storage.c_str(); p < d_storage.c_str() + d_storage.size() && *p; p+=*p+1) ++count; return count; } @@ -245,7 +253,7 @@ bool DNSName::operator==(const DNSName& rhs) const auto us = d_storage.crbegin(); auto p = rhs.d_storage.crbegin(); - for(; us != d_storage.crend() && p != rhs.d_storage.crend(); ++us, ++p) { + for(; us != d_storage.crend() && p != rhs.d_storage.crend(); ++us, ++p) { // why does this go backward? if(tolower(*p) != tolower(*us)) return false; } diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index 6bc80a9a5..082249797 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -27,13 +27,13 @@ class DNSName { public: - DNSName() : d_empty(true) {} //!< Constructs an *empty* DNSName, NOT the root! + DNSName() {} //!< Constructs an *empty* DNSName, NOT the root! explicit DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation explicit 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 if offset=12 bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name? - bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) + bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) - empty compares to empty bool operator!=(const DNSName& other) const { return !(*this == other); } std::string toString(const std::string& separator=".", const bool trailing=true) const; //!< Our human-friendly, escaped, representation @@ -49,17 +49,22 @@ public: bool isWildcard() const; unsigned int countLabels() const; size_t wirelength() const; //!< Number of total bytes in the name - bool empty() const { return d_empty; } - bool isRoot() const { return !d_empty && d_storage.empty(); } - void clear() { d_storage.clear(); d_empty=true; } + bool empty() const { return d_storage.empty(); } + bool isRoot() const { return d_storage.size()==1 && d_storage[0]==0; } + void clear() { d_storage.clear(); } void trimToLabels(unsigned int); DNSName& operator+=(const DNSName& rhs) { - if(d_storage.size() + rhs.d_storage.size() > 254) // reserve one byte for the root label + if(d_storage.size() + rhs.d_storage.size() > 256) // reserve one byte for the root label throw std::range_error("name too long"); + if(rhs.empty()) + return *this; + + if(d_storage.empty()) + d_storage+=rhs.d_storage; + else + d_storage.replace(d_storage.length()-1, rhs.d_storage.length(), rhs.d_storage); - d_storage+=rhs.d_storage; - d_empty&=rhs.d_empty; return *this; } @@ -76,7 +81,6 @@ public: void serialize(Archive &ar, const unsigned int version) { ar & d_storage; - ar & d_empty; } inline bool canonCompare(const DNSName& rhs) const; @@ -86,7 +90,6 @@ private: typedef std::string string_t; string_t d_storage; - bool d_empty; void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0, int depth=0); static std::string escapeLabel(const std::string& orig); @@ -116,9 +119,9 @@ inline bool DNSName::canonCompare(const DNSName& rhs) const uint8_t ourpos[64], rhspos[64]; uint8_t ourcount=0, rhscount=0; //cout<<"Asked to compare "< nameservers, DNSName auth, bool flawedNSSe LOG(prefix<