DNSName::DNSName(const char* p)
{
+ d_empty=false;
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;
d_recurse = 0;
packetParser(pos, len, offset, uncompress, qtype, qclass, consumed);
}
}
-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;
// 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())
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<string> l=getRawLabels();
+ while(!l.empty()) {
+ ret.appendRawLabel(l.back());
+ l.pop_back();
+ }
+ }
+ return ret;
+}
+
void DNSName::appendRawLabel(const std::string& label)
{
if(label.empty())
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());
}
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;
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();
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
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<std::string> 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)
{
throw std::range_error("name too long");
d_storage+=rhs.d_storage;
+ d_empty&=rhs.d_empty;
return *this;
}
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);
#include <boost/algorithm/string.hpp>
#include "iputils.hh"
+
bool g_singleThreaded;
int writen2(int fd, const void *buf, size_t count)
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)
{
};
vector<MapCombo> 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()];
}
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);
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));
}
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");
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");
BOOST_CHECK_EQUAL(n.toString(), "powerdns\\.dnsmaster.powerdns.com.");
- BOOST_CHECK_EQUAL(DNSName().toString(), ".");
+ BOOST_CHECK(DNSName().toString() != ".");
DNSName p;
string label("power");
#include "dns.hh"
#include "zoneparser-tng.hh"
#include "dnsrecords.hh"
+#include "dnsname.hh"
#include <fstream>
#include <cstdlib>