]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
recursor snap
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Mon, 1 Jun 2015 20:27:30 +0000 (22:27 +0200)
committermind04 <mind04@monshouwer.org>
Tue, 30 Jun 2015 06:12:44 +0000 (08:12 +0200)
17 files changed:
pdns/lua-recursor.cc
pdns/lua-recursor.hh
pdns/lwres.cc
pdns/lwres.hh
pdns/misc.cc
pdns/misc.hh
pdns/packetcache.hh
pdns/pdns_recursor.cc
pdns/rec_channel.hh
pdns/rec_channel_rec.cc
pdns/recpacketcache.cc
pdns/recpacketcache.hh
pdns/recursor_cache.cc
pdns/recursor_cache.hh
pdns/reczones.cc
pdns/syncres.cc
pdns/syncres.hh

index 3ff659f79978d68f1b6655fad7f88e60c842f815..d222c4931966ae598d8f2ad93bd93bd9c3a2adc5 100644 (file)
@@ -13,28 +13,28 @@ RecursorLua::RecursorLua(const std::string &fname)
   // empty
 }
 
-bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
 
-bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
 {
   return false;
 }
index 7e5019f5e05e502edd53d138cc06e57624065720..a4f7e24f35b4983b6d5434835ebaf5e2121606dc 100644 (file)
@@ -9,14 +9,14 @@ class RecursorLua : public PowerDNSLua
 public:
   explicit RecursorLua(const std::string& fname);
   // ~RecursorLua();
-  bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool nodata(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool postresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
-  bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+  bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+  bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+  bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+  bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
   bool ipfilter(const ComboAddress& remote, const ComboAddress& local);
 private:
-  bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
+  bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
 
   struct NoFuncs
   {
index fe4eb9dea4b72de3c9a8492d62cc492f2f5c14e2..79376f24dfc4d5a842598babeae932e2839b2fea 100644 (file)
@@ -52,7 +52,7 @@
 /** lwr is only filled out in case 1 was returned, and even when returning 1 for 'success', lwr might contain DNS errors
     Never throws! 
  */
-int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult *lwr)
+int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult *lwr)
 {
   int len; 
   int bufsize=1500;
@@ -170,7 +170,7 @@ int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool do
     }
 
     if(!pdns_iequals(domain, mdp.d_qname)) { 
-      if(!mdp.d_qname.empty() && domain.find((char)0) == string::npos) {// embedded nulls are too noisy, plus empty domains are too
+      if(!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) {// embedded nulls are too noisy, plus empty domains are too
         L<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl;
       }
       // unexpected count has already been done @ pdns_recursor.cc
index 0d43249c8f8051dee5f7badd0a657a89d73639ce..afcc53a5baeeb88160b72a4e165430eb0b8542fe 100644 (file)
@@ -42,9 +42,9 @@
 #include "namespaces.hh"
 
 int asendto(const char *data, int len, int flags, const ComboAddress& ip, uint16_t id, 
-            const string& domain, uint16_t qtype,  int* fd);
+            const DNSName& domain, uint16_t qtype,  int* fd);
 int arecvfrom(char *data, int len, int flags, const ComboAddress& ip, int *d_len, uint16_t id, 
-              const string& domain, uint16_t, int fd, struct timeval* now);
+              const DNSName& domain, uint16_t, int fd, struct timeval* now);
 
 class LWResException : public PDNSException
 {
@@ -67,6 +67,6 @@ public:
   bool d_haveEDNS;
 };
 
-int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
+int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
 
 #endif // PDNS_LWRES_HH
index 581513be0dc73f20ac6d781a821a7323b10a2f87..a8f016ccd9420a8351eec3ebf0dc61f171cb38a7 100644 (file)
@@ -222,6 +222,12 @@ 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) 
 {
index e77f051c47bddf61da955462182144a2ec66b153..63c3032312747aeb214b472bba2cda2809ae0e20 100644 (file)
@@ -53,6 +53,7 @@ bool chopOff(string &domain);
 bool chopOffDotted(string &domain);
 
 bool endsOn(const string &domain, const string &suffix);
+bool dottedEndsOn(const DNSName &domain, const DNSName &suffix); // REMOVE ME
 bool dottedEndsOn(const string &domain, const string &suffix);
 string nowTime();
 const string unquotify(const string &item);
@@ -346,7 +347,7 @@ inline bool pdns_iequals(const std::string& a, const std::string& b)
   return true;
 }
 
-// FIXME remove this
+// FIXME remove this, it's just here to move faster while we DNSName the things
 inline bool pdns_iequals(const DNSName& a, const DNSName& b) __attribute__((pure));
 inline bool pdns_iequals(const DNSName& a, const DNSName& b)
 {
@@ -435,7 +436,7 @@ private:
     #endif
 };
 
-
+// FIXME this should probably go?
 struct CIStringCompare: public std::binary_function<string, string, bool>  
 {
   bool operator()(const string& a, const string& b) const
@@ -493,11 +494,13 @@ inline bool isCanonical(const string& dom)
   return dom[dom.size()-1]=='.';
 }
 
+// get rid of this?
 inline string toCanonic(const DNSName& zone, const string& domain)
 {
   return toCanonic(zone.toString(), domain);
 }
 
+// and this?
 inline string toCanonic(const string& zone, const string& domain)
 {
   if(domain.length()==1 && domain[0]=='@')
index e5f65c3384e0ffa82c06cf704d1a68608b614a10..3b4e936dba3f36110da0d7502e15355cebfc05f5 100644 (file)
@@ -77,7 +77,7 @@ private:
   {
     CacheEntry() { qtype = ctype = 0; zoneID = -1; meritsRecursion=false; dnssecOk=false; hasEDNS=false;}
 
-    string qname;
+    DNSName qname;
     uint16_t qtype;
     uint16_t ctype;
     int zoneID;
index 7fb870fc5981876f0a180e15f5a6dd28d773dbef..6dc510e451009aafa0fc9c1eff1e4f024481b006 100644 (file)
@@ -70,6 +70,7 @@
 #include "version.hh"
 #include "responsestats.hh"
 #include "secpoll-recursor.hh"
+#include "dnsname.hh"
 #ifndef RECURSOR
 #include "statbag.hh"
 StatBag S;
@@ -87,7 +88,7 @@ __thread shared_ptr<RecursorLua>* t_pdl;
 
 __thread addrringbuf_t* t_remotes, *t_servfailremotes, *t_largeanswerremotes;
 
-__thread boost::circular_buffer<pair<std::string, uint16_t> >* t_queryring, *t_servfailqueryring;
+__thread boost::circular_buffer<pair<DNSName, uint16_t> >* t_queryring, *t_servfailqueryring;
 __thread shared_ptr<Regex>* t_traceRegex;
 
 RecursorControlChannel s_rcc; // only active in thread 0
@@ -384,7 +385,7 @@ static __thread UDPClientSocks* t_udpclientsocks;
 /* these two functions are used by LWRes */
 // -2 is OS error, -1 is error that depends on the remote, > 0 is success
 int asendto(const char *data, int len, int flags, 
-            const ComboAddress& toaddr, uint16_t id, const string& domain, uint16_t qtype, int* fd) 
+            const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd) 
 {
 
   PacketID pident;
@@ -429,7 +430,7 @@ int asendto(const char *data, int len, int flags,
 
 // -1 is error, 0 is timeout, 1 is success
 int arecvfrom(char *data, int len, int flags, const ComboAddress& fromaddr, int *d_len, 
-              uint16_t id, const string& domain, uint16_t qtype, int fd, struct timeval* now)
+              uint16_t id, const DNSName& domain, uint16_t qtype, int fd, struct timeval* now)
 {
   static optional<unsigned int> nearMissLimit;
   if(!nearMissLimit) 
@@ -497,7 +498,7 @@ AtomicCounter TCPConnection::s_currentConnections;
 void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
 
 // the idea is, only do things that depend on the *response* here. Incoming accounting is on incoming.
-void updateResponseStats(int res, const ComboAddress& remote, unsigned int packetsize, const std::string* query, uint16_t qtype)
+void updateResponseStats(int res, const ComboAddress& remote, unsigned int packetsize, const DNSName* query, uint16_t qtype)
 {
   if(packetsize > 1000 && t_largeanswerremotes)
     t_largeanswerremotes->push_back(remote);
@@ -524,7 +525,7 @@ ResponseStats g_rs;
 static string makeLoginfo(DNSComboWriter* dc)
 try
 {
-  return "("+dc->d_mdp.d_qname+"/"+DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)+" from "+(dc->d_remote.toString())+")";
+  return "("+dc->d_mdp.d_qname.toString()+"/"+DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)+" from "+(dc->d_remote.toString())+")";
 }
 catch(...)
 {
@@ -575,7 +576,7 @@ void startDoResolve(void *p)
       goto sendit;
     }
 
-    if(t_traceRegex->get() && (*t_traceRegex)->match(dc->d_mdp.d_qname)) {
+    if(t_traceRegex->get() && (*t_traceRegex)->match(dc->d_mdp.d_qname.toString())) {
       sr.setLogMode(SyncRes::Store);
       tracedQuery=true;
     }
@@ -2133,9 +2134,9 @@ try
     t_largeanswerremotes = new addrringbuf_t();
     t_largeanswerremotes->set_capacity(ringsize);   
 
-    t_queryring = new boost::circular_buffer<pair<string, uint16_t> >();
+    t_queryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
     t_queryring->set_capacity(ringsize);   
-    t_servfailqueryring = new boost::circular_buffer<pair<string, uint16_t> >();
+    t_servfailqueryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
     t_servfailqueryring->set_capacity(ringsize);   
   }
   
index 7d320c02d974967a97d705da273df2edcc784953..94f4ae82a2190d495d007fa928e511e5208a64df 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/un.h>
 #include <pthread.h>
 #include "iputils.hh"
+#include "dnsname.hh"
 
 /** this class is used both to send and answer channel commands to the PowerDNS Recursor */
 class RecursorControlChannel
@@ -43,10 +44,10 @@ private:
 std::map<std::string, std::string> getAllStatsMap();
 extern pthread_mutex_t g_carbon_config_lock;
 void sortPublicSuffixList();
-std::vector<std::pair<std::string, uint16_t> >* pleaseGetQueryRing();
-std::vector<std::pair<std::string, uint16_t> >* pleaseGetServfailQueryRing();
+std::vector<std::pair<DNSName, uint16_t> >* pleaseGetQueryRing();
+std::vector<std::pair<DNSName, uint16_t> >* pleaseGetServfailQueryRing();
 std::vector<ComboAddress>* pleaseGetRemotes();
 std::vector<ComboAddress>* pleaseGetServfailRemotes();
 std::vector<ComboAddress>* pleaseGetLargeAnswerRemotes();
-std::string getRegisteredName(const std::string& dom);
+DNSName getRegisteredName(const DNSName& dom);
 #endif 
index e61066417fb93feeb50c74c9c51d6f168baa25a4..a3a23ba73007331f6aa7fc483ae1bd6e109cbe3a 100644 (file)
@@ -149,7 +149,7 @@ static uint64_t dumpNegCache(SyncRes::negcache_t& negcache, int fd)
   BOOST_FOREACH(const NegCacheEntry& neg, sidx)
   {
     ++count;
-    fprintf(fp, "%s IN %s %d VIA %s\n", neg.d_name.c_str(), neg.d_qtype.getName().c_str(), (unsigned int) (neg.d_ttd - now), neg.d_qname.c_str());
+    fprintf(fp, "%s IN %s %d VIA %s\n", neg.d_name.toString().c_str(), neg.d_qtype.getName().c_str(), (unsigned int) (neg.d_ttd - now), neg.d_qname.toString().c_str());
   }
   fclose(fp);
   return count;
@@ -227,14 +227,14 @@ string doDumpEDNSStatus(T begin, T end)
   return "done\n";
 }
 
-uint64_t* pleaseWipeCache(const std::string& canon)
+uint64_t* pleaseWipeCache(const DNSName& canon)
 {
   // clear packet cache too
   return new uint64_t(t_RC->doWipeCache(canon) + t_packetCache->doWipePacketCache(canon));
 }
 
 
-uint64_t* pleaseWipeAndCountNegCache(const std::string& canon)
+uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon)
 {
   uint64_t res = t_sstorage->negcache.count(tie(canon));
   pair<SyncRes::negcache_t::iterator, SyncRes::negcache_t::iterator> range=t_sstorage->negcache.equal_range(tie(canon));
@@ -247,7 +247,7 @@ string doWipeCache(T begin, T end)
 {
   int count=0, countNeg=0;
   for(T i=begin; i != end; ++i) {
-    string canon=toCanonic("", *i);
+    DNSName canon=DNSName(*i);
     count+= broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon));
     countNeg+=broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon));
   }
@@ -317,7 +317,7 @@ static string* pleaseGetCurrentQueries()
   for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end() && n < 100; ++mthread, ++n) {
     const PacketID& pident = mthread->key;
     ostr << (fmt 
-             % pident.domain % DNSRecordContent::NumberToType(pident.type) 
+             % pident.domain.toString() /* ?? */ % DNSRecordContent::NumberToType(pident.type) 
              % pident.remote.toString() % (pident.sock ? 'Y' : 'n')
              % (pident.fd == -1 ? 'Y' : 'n')
              );
@@ -601,9 +601,9 @@ static void doExitNicely()
   doExitGeneric(true);
 }
 
-vector<pair<string, uint16_t> >* pleaseGetQueryRing()
+vector<pair<DNSName, uint16_t> >* pleaseGetQueryRing()
 {
-  typedef pair<string,uint16_t> query_t;
+  typedef pair<DNSName,uint16_t> query_t;
   vector<query_t >* ret = new vector<query_t>();
   if(!t_queryring)
     return ret;
@@ -614,9 +614,9 @@ vector<pair<string, uint16_t> >* pleaseGetQueryRing()
   }
   return ret;
 }
-vector<pair<string,uint16_t> >* pleaseGetServfailQueryRing()
+vector<pair<DNSName,uint16_t> >* pleaseGetServfailQueryRing()
 {
-  typedef pair<string,uint16_t> query_t;
+  typedef pair<DNSName,uint16_t> query_t;
   vector<query_t>* ret = new vector<query_t>();
   if(!t_servfailqueryring)
     return ret;
@@ -630,7 +630,7 @@ vector<pair<string,uint16_t> >* pleaseGetServfailQueryRing()
 
 
 typedef boost::function<vector<ComboAddress>*()> pleaseremotefunc_t;
-typedef boost::function<vector<pair<string,uint16_t> >*()> pleasequeryfunc_t;
+typedef boost::function<vector<pair<DNSName,uint16_t> >*()> pleasequeryfunc_t;
 
 vector<ComboAddress>* pleaseGetRemotes()
 {
@@ -720,10 +720,9 @@ void sortPublicSuffixList()
   sort(g_pubs.begin(), g_pubs.end());
 }
 
-string getRegisteredName(const std::string& dom)
+DNSName getRegisteredName(const DNSName& dom)
 {
-  vector<string> parts;
-  stringtok(parts, dom, ".");
+  auto parts=dom.getRawLabels();
   if(parts.size()<=2)
     return dom;
   reverse(parts.begin(), parts.end());
@@ -750,14 +749,14 @@ string getRegisteredName(const std::string& dom)
   return "??";
 }
 
-static string nopFilter(const std::string& str)
+static DNSName nopFilter(const DNSName& name)
 {
-  return str;
+  return name;
 }
 
-string doGenericTopQueries(pleasequeryfunc_t func, boost::function<string(const std::string&)> filter=nopFilter)
+string doGenericTopQueries(pleasequeryfunc_t func, boost::function<DNSName(const DNSName&)> filter=nopFilter)
 {
-  typedef pair<string,uint16_t> query_t;
+  typedef pair<DNSName,uint16_t> query_t;
   typedef map<query_t, int> counts_t;
   counts_t counts;
   vector<query_t> queries=broadcastAccFunction<vector<query_t> >(func);
@@ -765,7 +764,7 @@ string doGenericTopQueries(pleasequeryfunc_t func, boost::function<string(const
   unsigned int total=0;
   BOOST_FOREACH(const query_t& q, queries) {
     total++;
-    counts[make_pair(toLower(filter(q.first)),q.second)]++;
+    counts[make_pair(filter(q.first),q.second)]++;
   }
 
   typedef std::multimap<int, query_t> rcounts_t;
@@ -780,7 +779,7 @@ string doGenericTopQueries(pleasequeryfunc_t func, boost::function<string(const
   int limit=0, accounted=0;
   if(total) {
     for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit) {
-      ret<< fmt % (-100.0*i->first/total) % (i->second.first+"|"+DNSRecordContent::NumberToType(i->second.second));
+      ret<< fmt % (-100.0*i->first/total) % (i->second.first.toString()+"|"+DNSRecordContent::NumberToType(i->second.second));
       accounted+= -i->first;
     }
     ret<< '\n' << fmt % (100.0*(total-accounted)/total) % "rest";
index f22a4c663804ed5ac261822ba25b0589bb790cb6..665ca32cdee3d3168ddbf5887b54128c111cc0e4 100644 (file)
@@ -15,10 +15,10 @@ RecursorPacketCache::RecursorPacketCache()
   d_hits = d_misses = 0;
 }
 
-int RecursorPacketCache::doWipePacketCache(const string& name, uint16_t qtype)
+int RecursorPacketCache::doWipePacketCache(const DNSName& name, uint16_t qtype)
 {
   vector<uint8_t> packet;
-  DNSPacketWriter pw(packet, toLower(name), 0);
+  DNSPacketWriter pw(packet, name, 0);
   pw.getHeader()->rd=1;
   Entry e;
   e.d_packet.assign((const char*)&*packet.begin(), packet.size());
index 3d7d3d9a9268229bc2c4756e11860e112cf2a253..53f5554e491a0487ca23f751931ed9b85b1c8745 100644 (file)
@@ -22,7 +22,7 @@ public:
   bool getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age);
   void insertResponsePacket(const std::string& responsePacket, time_t now, uint32_t ttd);
   void doPruneTo(unsigned int maxSize=250000);
-  int doWipePacketCache(const string& name, uint16_t qtype=0xffff);
+  int doWipePacketCache(const DNSName& name, uint16_t qtype=0xffff);
   
   void prune();
   uint64_t d_hits, d_misses;
index c2b2c778d6e3d766622945b56a906d18b9f986b7..bcc6d898f00598695c772423140bbc1d68d29312 100644 (file)
@@ -59,7 +59,7 @@ DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const strin
     rr.content=regen->getZoneRepresentation();
   }
   rr.content.reserve(0);
-  rr.qname.reserve(0);
+  // rr.qname.reserve(0);
   return rr;
 }
 
@@ -78,7 +78,7 @@ string DNSRR2String(const DNSResourceRecord& rr)
     return string((char*)&ca.sin6.sin6_addr.s6_addr, 16);
   }
   else if(type==QType::NS || type==QType::CNAME)
-      return simpleCompress(rr.content, rr.qname);
+      return simpleCompress(rr.content, rr.qname.toString());
   else {
     string ret;
     shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(type, 1, rr.content));
@@ -100,14 +100,14 @@ unsigned int MemRecursorCache::bytes()
 
   for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
     ret+=sizeof(struct CacheEntry);
-    ret+=(unsigned int)i->d_qname.length();
+    ret+=(unsigned int)i->d_qname.toString().length();
     for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j)
       ret+=j->size();
   }
   return ret;
 }
 
-int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res)
+int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res)
 {
   unsigned int ttd=0;
   //  cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n";
@@ -186,10 +186,10 @@ bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResou
 /* the code below is rather tricky - it basically replaces the stuff cached for qname by content, but it is special
    cased for when inserting identical records with only differing ttls, in which case the entry is not
    touched, but only given a new ttd */
-void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth)
+void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth)
 {
   d_cachecachevalid=false;
-  boost::tuple<string, uint16_t> key=boost::make_tuple(qname, qt.getCode());
+  boost::tuple<DNSName, uint16_t> key=boost::make_tuple(qname, qt.getCode());
   cache_t::iterator stored=d_cache.find(key);
   uint32_t maxTTD=UINT_MAX;
 
@@ -225,7 +225,7 @@ void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt,
   }
   
   // limit TTL of auth->auth NSset update if needed, except for root
-  if(ce.d_auth && auth && qt.getCode()==QType::NS && !((qname.length()==1 && qname[0]=='.'))) {
+  if(ce.d_auth && auth && qt.getCode()==QType::NS && !(qname == DNSName("."))) {
     // cerr<<"\tLimiting TTL of auth->auth NS set replace"<<endl;
     vector<StoredRecord>::iterator j;
     for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) {
@@ -234,7 +234,7 @@ void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt,
   }
 
   // make sure that we CAN refresh the root
-  if(auth && ((qname.length()==1 && qname[0]=='.') || !attemptToRefreshNSTTL(qt, content, ce) ) ) {
+  if(auth && ((qname == DNSName(".")) || !attemptToRefreshNSTTL(qt, content, ce) ) ) {
     // cerr<<"\tGot auth data, and it was not refresh attempt of an unchanged NS set, nuking storage"<<endl;
     ce.d_records.clear(); // clear non-auth data
     ce.d_auth = true;
@@ -295,7 +295,7 @@ void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt,
   d_cache.replace(stored, ce);
 }
 
-int MemRecursorCache::doWipeCache(const string& name, uint16_t qtype)
+int MemRecursorCache::doWipeCache(const DNSName& name, uint16_t qtype)
 {
   int count=0;
   d_cachecachevalid=false;
@@ -362,7 +362,7 @@ uint64_t MemRecursorCache::doDumpNSSpeeds(int fd)
   for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); ++i)
   {
     count++;
-    fprintf(fp, "%s -> ", i->first.c_str());
+    fprintf(fp, "%s -> ", i->first.toString().c_str());
     for(SyncRes::DecayingEwmaCollection::collection_t::iterator j = i->second.d_collection.begin(); j!= i->second.d_collection.end(); ++j)
     {
       // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
@@ -391,10 +391,10 @@ uint64_t MemRecursorCache::doDump(int fd)
       count++;
       try {
         DNSResourceRecord rr=String2DNSRR(i->d_qname, QType(i->d_qtype), j->d_string, j->d_ttd - now);
-        fprintf(fp, "%s %d IN %s %s\n", rr.qname.c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
+        fprintf(fp, "%s %d IN %s %s\n", rr.qname.toString().c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
       }
       catch(...) {
-        fprintf(fp, "; error printing '%s'\n", i->d_qname.c_str());
+        fprintf(fp, "; error printing '%s'\n", i->d_qname.toString().c_str());
       }
     }
   }
index d8ce136d71b4f36d33dabe227053872fa86621cb..73ada3bdbbbabce689f671ea4d4f01a44dc818d9 100644 (file)
@@ -5,6 +5,7 @@
 #include "dns.hh"
 #include "qtype.hh"
 #include "misc.hh"
+#include "dnsname.hh"
 #include <iostream>
 
 #include <boost/utility.hpp>
@@ -31,16 +32,16 @@ public:
   }
   unsigned int size();
   unsigned int bytes();
-  int get(time_t, const string &qname, const QType& qt, set<DNSResourceRecord>* res);
+  int get(time_t, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res);
 
   int getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10]);
-  void replace(time_t, const string &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth);
+  void replace(time_t, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth);
   void doPrune(void);
   void doSlash(int perc);
   uint64_t doDump(int fd);
   uint64_t doDumpNSSpeeds(int fd);
 
-  int doWipeCache(const string& name, uint16_t qtype=0xffff);
+  int doWipeCache(const DNSName& name, uint16_t qtype=0xffff);
   bool doAgeCache(time_t now, const string& name, uint16_t qtype, int32_t newTTL);
   uint64_t cacheHits, cacheMisses;
 
@@ -65,7 +66,7 @@ private:
 
   struct CacheEntry
   {
-    CacheEntry(const boost::tuple<string, uint16_t>& key, const vector<StoredRecord>& records, bool auth) : 
+    CacheEntry(const boost::tuple<DNSName, uint16_t>& key, const vector<StoredRecord>& records, bool auth) : 
       d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records)
     {}
 
@@ -82,7 +83,7 @@ private:
       return earliest;
     }
 
-    string d_qname;
+    DNSName d_qname;
     uint16_t d_qtype;
     bool d_auth;
     records_t d_records;
@@ -94,10 +95,10 @@ private:
                 ordered_unique<
                       composite_key< 
                         CacheEntry,
-                        member<CacheEntry,string,&CacheEntry::d_qname>,
+                        member<CacheEntry,DNSName,&CacheEntry::d_qname>,
                         member<CacheEntry,uint16_t,&CacheEntry::d_qtype>
                       >,
-                      composite_key_compare<CIStringCompare, std::less<uint16_t> >
+                      composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
                 >,
                sequenced<>
                >
@@ -105,11 +106,11 @@ private:
 
   cache_t d_cache;
   pair<cache_t::iterator, cache_t::iterator> d_cachecache;
-  string d_cachedqname;
+  DNSName d_cachedqname;
   bool d_cachecachevalid;
   bool attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored);
 };
 string DNSRR2String(const DNSResourceRecord& rr);
-DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const string& serial, uint32_t ttd);
+DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd);
 
 #endif
index a6e3291449e52b5e8d36b8561176d0d0b92860da..6552e8086560b00d195cce395448ee29feac7e5e 100644 (file)
@@ -99,13 +99,13 @@ void primeHints(void)
   t_RC->replace(time(0),".", QType(QType::NS), nsset, true); // and stuff in the cache (auth)
 }
 
-static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const string& hostname, const string& ip)
+static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const DNSName& hostname, const string& ip)
 {
   SyncRes::AuthDomain ad;
   ad.d_rdForward=false;
 
   DNSResourceRecord rr;
-  rr.qname=toCanonic("", hostname);
+  rr.qname=hostname;
   rr.d_place=DNSResourceRecord::ANSWER;
   rr.ttl=86400;
   rr.qtype=QType::SOA;
@@ -143,10 +143,10 @@ static void makeIPToNamesZone(SyncRes::domainmap_t* newMap, const vector<string>
 
   DNSResourceRecord rr;
   for(int n=ipparts.size()-1; n>=0 ; --n) {
-    rr.qname.append(ipparts[n]);
-    rr.qname.append(1,'.');
+    rr.qname.appendRawLabel(ipparts[n]);
   }
-  rr.qname.append("in-addr.arpa.");
+  rr.qname.appendRawLabel("in-addr");
+  rr.qname.appendRawLabel("arpa");
 
   rr.d_place=DNSResourceRecord::ANSWER;
   rr.ttl=86400;
@@ -163,7 +163,7 @@ static void makeIPToNamesZone(SyncRes::domainmap_t* newMap, const vector<string>
 
   if(ipparts.size()==4)  // otherwise this is a partial zone
     for(unsigned int n=1; n < parts.size(); ++n) {
-      rr.content=toCanonic("", parts[n]);
+      rr.content=DNSName(parts[n]).toString();
       ad.d_records.insert(rr);
     }
 
@@ -329,11 +329,11 @@ SyncRes::domainmap_t* parseAuthAndForwards()
       pair<string,string> headers=splitField(*iter, '=');
       trim(headers.first);
       trim(headers.second);
-      headers.first=toCanonic("", headers.first);
+      // headers.first=toCanonic("", headers.first);
       if(n==0) {
         ad.d_rdForward = false;
         L<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
-        ZoneParserTNG zpt(headers.second, headers.first);
+        ZoneParserTNG zpt(headers.second, DNSName(headers.first));
         DNSResourceRecord rr;
         while(zpt.get(rr)) {
           try {
@@ -342,11 +342,11 @@ SyncRes::domainmap_t* parseAuthAndForwards()
           }
           catch(std::exception &e) {
             delete newMap;
-            throw PDNSException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what());
+            throw PDNSException("Error parsing record '"+rr.qname.toString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what());
           }
           catch(...) {
             delete newMap;
-            throw PDNSException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
+            throw PDNSException("Error parsing record '"+rr.qname.toString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
           }
 
           ad.d_records.insert(rr);
@@ -413,7 +413,7 @@ SyncRes::domainmap_t* parseAuthAndForwards()
         throw PDNSException("Conversion error parsing line "+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]);
       }
 
-      (*newMap)[toCanonic("", domain)]=ad;
+      (*newMap)[domain]=ad;
     }
     L<<Logger::Warning<<"Done parsing " << newMap->size() - before<<" forwarding instructions from file '"<<::arg()["forward-zones-file"]<<"'"<<endl;
   }
index db5993f2a6839a419d9a885589f9da6f2705fcac..f53d2c0aef39d2a9fa798743f7fd706221dc12fa 100644 (file)
@@ -88,7 +88,7 @@ SyncRes::SyncRes(const struct timeval& now) :  d_outqueries(0), d_tcpoutqueries(
 }
 
 /** everything begins here - this is the entry point just after receiving a packet */
-int SyncRes::beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret)
+int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret)
 {
   s_queries++;
 
@@ -96,7 +96,7 @@ int SyncRes::beginResolve(const string &qname, const QType &qtype, uint16_t qcla
     return -1;
 
   if( (qtype.getCode()==QType::PTR && pdns_iequals(qname, "1.0.0.127.in-addr.arpa.")) ||
-      (qtype.getCode()==QType::A && qname.length()==10 && pdns_iequals(qname, "localhost."))) {
+      (qtype.getCode()==QType::A && pdns_iequals(qname, "localhost."))) {
     ret.clear();
     DNSResourceRecord rr;
     rr.qname=qname;
@@ -139,7 +139,7 @@ int SyncRes::beginResolve(const string &qname, const QType &qtype, uint16_t qcla
 }
 
 //! This is the 'out of band resolver', in other words, the authoritative server
-bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int& res)
+bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int& res)
 {
   string prefix;
   if(doLog()) {
@@ -147,15 +147,15 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
     prefix.append(depth, ' ');
   }
 
-  LOG(prefix<<qname<<": checking auth storage for '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
-  string authdomain(qname);
+  LOG(prefix<<qname.toString()<<": checking auth storage for '"<<qname.toString()<<"|"<<qtype.getName()<<"'"<<endl);
+  DNSName authdomain(qname);
 
   domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
   if(iter==t_sstorage->domainmap->end()) {
-    LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
+    LOG(prefix<<qname.toString()<<": auth storage has no zone for this query!"<<endl);
     return false;
   }
-  LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
+  LOG(prefix<<qname.toString()<<": auth storage has data, zone='"<<authdomain.toString()<<"'"<<endl);
   pair<AuthDomain::records_t::const_iterator, AuthDomain::records_t::const_iterator> range;
 
   range=iter->second.d_records.equal_range(tie(qname)); // partial lookup
@@ -169,12 +169,12 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
       ret.push_back(*ziter);
   }
   if(!ret.empty()) {
-    LOG(prefix<<qname<<": exact match in zone '"<<authdomain<<"'"<<endl);
+    LOG(prefix<<qname.toString()<<": exact match in zone '"<<authdomain.toString()<<"'"<<endl);
     res=0;
     return true;
   }
   if(somedata) {
-    LOG(prefix<<qname<<": found record in '"<<authdomain<<"', but nothing of the right type, sending SOA"<<endl);
+    LOG(prefix<<qname.toString()<<": found record in '"<<authdomain.toString()<<"', but nothing of the right type, sending SOA"<<endl);
     ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA)));
     if(ziter!=iter->second.d_records.end()) {
       DNSResourceRecord rr=*ziter;
@@ -182,16 +182,16 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
       ret.push_back(rr);
     }
     else
-      LOG(prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl);
+      LOG(prefix<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
     res=RCode::NoError;
     return true;
   }
 
-  LOG(prefix<<qname<<": nothing found so far in '"<<authdomain<<"', trying wildcards"<<endl);
-  string wcarddomain(qname);
-  while(!pdns_iequals(wcarddomain, iter->first) && chopOffDotted(wcarddomain)) {
-    LOG(prefix<<qname<<": trying '*."+wcarddomain+"' in "<<authdomain<<endl);
-    range=iter->second.d_records.equal_range(boost::make_tuple("*."+wcarddomain));
+  LOG(prefix<<qname.toString()<<": nothing found so far in '"<<authdomain.toString()<<"', trying wildcards"<<endl);
+  DNSName wcarddomain(qname);
+  while(!pdns_iequals(wcarddomain, iter->first) && wcarddomain.chopOff()) {
+    LOG(prefix<<qname.toString()<<": trying '*."+wcarddomain.toString()+"' in "<<authdomain.toString()<<endl);
+    range=iter->second.d_records.equal_range(boost::make_tuple(DNSName("*")+wcarddomain)); 
     if(range.first==range.second)
       continue;
 
@@ -203,15 +203,15 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
         ret.push_back(rr);
       }
     }
-    LOG(prefix<<qname<<": in '"<<authdomain<<"', had wildcard match on '*."+wcarddomain+"'"<<endl);
+    LOG(prefix<<qname.toString()<<": in '"<<authdomain.toString()<<"', had wildcard match on '*."+wcarddomain.toString()+"'"<<endl);
     res=RCode::NoError;
     return true;
   }
 
-  string nsdomain(qname);
+  DNSName nsdomain(qname);
 
-  while(chopOffDotted(nsdomain) && !pdns_iequals(nsdomain, iter->first)) {
-    range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS)));
+  while(nsdomain.chopOff() && !pdns_iequals(nsdomain, iter->first)) {
+    range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS))); 
     if(range.first==range.second)
       continue;
 
@@ -221,8 +221,8 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
       ret.push_back(rr);
     }
   }
-  if(ret.empty()) {
-    LOG(prefix<<qname<<": no NS match in zone '"<<authdomain<<"' either, handing out SOA"<<endl);
+  if(ret.empty()) { 
+    LOG(prefix<<qname.toString()<<": no NS match in zone '"<<authdomain.toString()<<"' either, handing out SOA"<<endl);
     ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA)));
     if(ziter!=iter->second.d_records.end()) {
       DNSResourceRecord rr=*ziter;
@@ -230,7 +230,7 @@ bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSRe
       ret.push_back(rr);
     }
     else
-      LOG(prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl);
+      LOG(prefix<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
     res=RCode::NXDomain;
   }
   else
@@ -251,7 +251,7 @@ void SyncRes::doEDNSDumpAndClose(int fd)
   fclose(fp);
 }
 
-int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res)
+int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res) 
 {
   /* what is your QUEST?
      the goal is to get as many remotes as possible on the highest level of hipness: EDNS PING responders.
@@ -385,7 +385,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const string& domain, i
   return ret;
 }
 
-int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
+int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
 {
   string prefix;
   if(doLog()) {
@@ -397,8 +397,8 @@ int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResour
   if(!(d_nocache && qtype.getCode()==QType::NS && qname==".")) {
     if(d_cacheonly) { // very limited OOB support
       LWResult lwr;
-      LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
-      string authname(qname);
+      LOG(prefix<<qname.toString()<<": Recursion not requested for '"<<qname.toString()<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
+      DNSName authname(qname);
       domainmap_t::const_iterator iter=getBestAuthZone(&authname);
       if(iter != t_sstorage->domainmap->end()) {
         const vector<ComboAddress>& servers = iter->second.d_servers;
@@ -409,7 +409,7 @@ int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResour
         }
         else {
           const ComboAddress remoteIP = servers.front();
-          LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
+          LOG(prefix<<qname.toString()<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname.toString()<<"'"<<endl);
 
           res=asyncresolveWrapper(remoteIP, qname, qtype.getCode(), false, false, &d_now, &lwr);
           // filter out the good stuff from lwr.result()
@@ -432,12 +432,12 @@ int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResour
 
   if(d_cacheonly)
     return 0;
+    
+  LOG(prefix<<qname.toString()<<": No cache hit for '"<<qname.toString()<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
 
-  LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
+  DNSName subdomain(qname);
 
-  string subdomain(qname);
-
-  set<string, CIStringCompare> nsset;
+  set<DNSName> nsset;
   bool flawedNSSet=false;
 
   // the two retries allow getBestNSNamesFromCache&co to reprime the root
@@ -448,8 +448,8 @@ int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResour
 
   if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
     return 0;
-
-  LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
+  
+  LOG(prefix<<qname.toString()<<": failed (res="<<res<<")"<<endl);
   return res<0 ? RCode::ServFail : res;
 }
 
@@ -463,7 +463,7 @@ static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
 
 /** This function explicitly goes out for A or AAAA addresses
 */
-vector<ComboAddress> SyncRes::getAddrs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere)
+vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetBestNSAnswer>& beenthere)
 {
   typedef vector<DNSResourceRecord> res_t;
   res_t res;
@@ -532,9 +532,10 @@ vector<ComboAddress> SyncRes::getAddrs(const string &qname, int depth, set<GetBe
   return ret;
 }
 
-void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
+void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
 {
-  string prefix, subdomain(qname);
+  string prefix;
+  DNSName subdomain(qname);
   if(doLog()) {
     prefix=d_prefix;
     prefix.append(depth, ' ');
@@ -543,7 +544,7 @@ void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DN
   bool brokeloop;
   do {
     brokeloop=false;
-    LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
+    LOG(prefix<<qname.toString()<<": Checking if we have NS in cache for '"<<subdomain.toString()<<"'"<<endl);
     set<DNSResourceRecord> ns;
     *flawedNSSet = false;
     if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
@@ -553,11 +554,11 @@ void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DN
 
           DNSResourceRecord rr=*k;
           rr.content=k->content;
-          if(!dottedEndsOn(rr.content, subdomain) || t_RC->get(d_now.tv_sec, rr.content, s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
+          if(!DNSName(rr.content).isPartOf(subdomain) || t_RC->get(d_now.tv_sec, rr.content, s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
                                                             doLog() ? &aset : 0) > 5) {
             bestns.insert(rr);
-            LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<rr.content<<"'"<<endl);
-            LOG(prefix<<qname<<": within bailiwick: "<<dottedEndsOn(rr.content, subdomain));
+            LOG(prefix<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<rr.content<<"'"<<endl);
+            LOG(prefix<<qname.toString()<<": within bailiwick: "<<DNSName(rr.content).isPartOf(subdomain) /* ugh */);
             if(!aset.empty()) {
               LOG(",  in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl);
             }
@@ -567,7 +568,7 @@ void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DN
           }
           else {
             *flawedNSSet=true;
-            LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl);
+            LOG(prefix<<qname.toString()<<": NS in cache for '"<<subdomain.toString()<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl);
           }
         }
       }
@@ -580,46 +581,46 @@ void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DN
 
         if(beenthere.count(answer)) {
          brokeloop=true;
-          LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
+          LOG(prefix<<qname.toString()<<": We have NS in cache for '"<<subdomain.toString()<<"' but part of LOOP (already seen "<<answer.qname.toString()<<")! Trying less specific NS"<<endl);
           if(doLog())
             for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
              bool neo = !(*j< answer || answer<*j);
-             LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
+             LOG(prefix<<qname.toString()<<": beenthere"<<(neo?"*":"")<<": "<<j->qname.toString()<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
             }
           bestns.clear();
         }
         else {
          beenthere.insert(answer);
-          LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
+          LOG(prefix<<qname.toString()<<": We have NS in cache for '"<<subdomain.toString()<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
           return;
         }
       }
     }
-    LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
-    if(subdomain=="." && !brokeloop) {
-      primeHints();
-      LOG(prefix<<qname<<": reprimed the root"<<endl);
+    LOG(prefix<<qname.toString()<<": no valid/useful NS in cache for '"<<subdomain.toString()<<"'"<<endl);
+    if(subdomain=="." && !brokeloop) { 
+      primeHints(); 
+      LOG(prefix<<qname.toString()<<": reprimed the root"<<endl);
     }
-  }while(chopOffDotted(subdomain));
+  }while(subdomain.chopOff());
 }
 
-SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(string* qname)
+SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname)
 {
   SyncRes::domainmap_t::const_iterator ret;
   do {
     ret=t_sstorage->domainmap->find(*qname);
     if(ret!=t_sstorage->domainmap->end())
       break;
-  }while(chopOffDotted(*qname));
+  }while(qname->chopOff());
   return ret;
 }
 
 /** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname, const QType& qtype, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere)
+DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, set<DNSName>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere)
 {
-  string subdomain(qname);
-  string authdomain(qname);
-
+  DNSName subdomain(qname);
+  DNSName authdomain(qname);
+  
   domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
   if(iter!=t_sstorage->domainmap->end()) {
     if( iter->second.d_servers.empty() )
@@ -643,7 +644,7 @@ string SyncRes::getBestNSNamesFromCache(const string &qname, const QType& qtype,
   return subdomain;
 }
 
-bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
+bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
 {
   string prefix;
   if(doLog()) {
@@ -652,18 +653,18 @@ bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<
   }
 
   if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
-    LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
+    LOG(prefix<<qname.toString()<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
     res=RCode::ServFail;
     return true;
   }
-
-  LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<(qname+"|CNAME")<<"'"<<endl);
+  
+  LOG(prefix<<qname.toString()<<": Looking for CNAME cache hit of '"<<(qname.toString()+"|CNAME")<<"'"<<endl);
   set<DNSResourceRecord> cset;
   if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) {
 
     for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
       if(j->ttl>(unsigned int) d_now.tv_sec) {
-        LOG(prefix<<qname<<": Found cache CNAME hit for '"<< (qname+"|CNAME") <<"' to '"<<j->content<<"'"<<endl);
+        LOG(prefix<<qname.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|CNAME") <<"' to '"<<j->content<<"'"<<endl);    
         DNSResourceRecord rr=*j;
         rr.ttl-=d_now.tv_sec;
         ret.push_back(rr);
@@ -677,24 +678,18 @@ bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<
       }
     }
   }
-  LOG(prefix<<qname<<": No CNAME cache hit of '"<< (qname+"|CNAME") <<"' found"<<endl);
+  LOG(prefix<<qname.toString()<<": No CNAME cache hit of '"<< (qname.toString()+"|CNAME") <<"' found"<<endl);
   return false;
 }
 
 // accepts . terminated names, www.powerdns.com. -> com.
-static const string getLastLabel(const std::string& qname)
+static const string getLastLabel(const DNSName& qname)
 {
-  if(qname.empty() || qname == ".")
-    return qname;
-
-  labelparts_t parts;
-  labeltokUnescape(parts, qname);
-  int offset = (parts.end()-1)->first;
-
-  return qname.substr(offset, qname.size()-offset);
+  auto parts = qname.getRawLabels();
+  return parts[parts.size()-1];
 }
 
-bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
+bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
 {
   bool giveNegative=false;
 
@@ -704,7 +699,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
     prefix.append(depth, ' ');
   }
 
-  string sqname(qname);
+  DNSName sqname(qname);
   QType sqt(qtype);
   uint32_t sttl=0;
   //  cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
@@ -716,9 +711,9 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
      (range.first=t_sstorage->negcache.find(tie(getLastLabel(qname), qtnull))) != t_sstorage->negcache.end() &&
       range.first->d_qname=="." && (uint32_t)d_now.tv_sec < range.first->d_ttd ) {
     sttl=range.first->d_ttd - d_now.tv_sec;
-
-    LOG(prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<range.first->d_name<<"' & '"<<range.first->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
-    res = RCode::NXDomain;
+    
+    LOG(prefix<<qname.toString()<<": Entire name '"<<qname.toString()<<"', is negatively cached via '"<<range.first->d_name.toString()<<"' & '"<<range.first->d_qname.toString()<<"' for another "<<sttl<<" seconds"<<endl);
+    res = RCode::NXDomain; 
     sqname=range.first->d_qname;
     sqt=QType::SOA;
     moveCacheItemToBack(t_sstorage->negcache, range.first);
@@ -735,12 +730,12 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
        if((uint32_t)d_now.tv_sec < ni->d_ttd) {
          sttl=ni->d_ttd - d_now.tv_sec;
          if(ni->d_qtype.getCode()) {
-           LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
+           LOG(prefix<<qname.toString()<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
            res = RCode::NoError;
          }
          else {
-           LOG(prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
-           res= RCode::NXDomain;
+           LOG(prefix<<qname.toString()<<": Entire name '"<<qname.toString()<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
+           res= RCode::NXDomain; 
          }
          giveNegative=true;
          sqname=ni->d_qname;
@@ -749,7 +744,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
          break;
        }
        else {
-         LOG(prefix<<qname<<": Entire record '"<<qname<<"' or type was negatively cached, but entry expired"<<endl);
+         LOG(prefix<<qname.toString()<<": Entire name '"<<qname<<"' or type was negatively cached, but entry expired"<<endl);
          moveCacheItemToFront(t_sstorage->negcache, ni);
        }
       }
@@ -759,7 +754,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
   bool found=false, expired=false;
 
   if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset) > 0) {
-    LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
+    LOG(prefix<<sqname.toString()<<": Found cache hit for "<<sqt.getName()<<": ");
     for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
       LOG(j->content);
       if(j->ttl>(unsigned int) d_now.tv_sec) {
@@ -786,12 +781,13 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
       return true;
     }
     else
-      LOG(prefix<<qname<<": cache had only stale entries"<<endl);
+      LOG(prefix<<qname.toString()<<": cache had only stale entries"<<endl);
   }
 
   return false;
 }
 
+// FIXME use DNSName.isPartOf
 bool SyncRes::moreSpecificThan(const string& a, const string &b)
 {
   static string dot(".");
@@ -871,8 +867,8 @@ static bool magicAddrMatch(const QType& query, const QType& answer)
 }
 
 /** returns -1 in case of no results, rcode otherwise */
-int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype,
-                         vector<DNSResourceRecord>&ret,
+int SyncRes::doResolveAt(set<DNSName> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype, 
+                         vector<DNSResourceRecord>&ret, 
                          int depth, set<GetBestNSAnswer>&beenthere)
 {
   string prefix;
@@ -880,25 +876,25 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
     prefix=d_prefix;
     prefix.append(depth, ' ');
   }
-
-  LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl);
+  
+  LOG(prefix<<qname.toString()<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl);
 
   for(;;) { // we may get more specific nameservers
     vector<string > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname+": ") : string() );
 
     for(vector<string >::const_iterator tns=rnameservers.begin();;++tns) {
       if(tns==rnameservers.end()) {
-        LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
+        LOG(prefix<<qname.toString()<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
         if(auth!="." && flawedNSSet) {
-          LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
+          LOG(prefix<<qname.toString()<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
           if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
             g_stats.nsSetInvalidations++;
         }
         return -1;
       }
       // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
-      if(pdns_iequals(qname, *tns) && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) {
-        LOG(prefix<<qname<<": Not using NS to resolve itself!"<<endl);
+      if(pdns_iequals(qname, *tns) && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) { 
+        LOG(prefix<<qname.toString()<<": Not using NS to resolve itself!"<<endl);
         continue;
       }
 
@@ -911,16 +907,16 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
       bool sendRDQuery=false;
       LWResult lwr;
       if(tns->empty()) {
-        LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
+        LOG(prefix<<qname.toString()<<": Domain is out-of-band"<<endl);
         doOOBResolve(qname, qtype, lwr.d_result, depth, lwr.d_rcode);
         lwr.d_tcbit=false;
         lwr.d_aabit=true;
       }
       else {
-        LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
+        LOG(prefix<<qname.toString()<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
 
         if(!isCanonical(*tns)) {
-          LOG(prefix<<qname<<": Domain has hardcoded nameserver(s)"<<endl);
+          LOG(prefix<<qname.toString()<<": Domain has hardcoded nameserver(s)"<<endl);
 
           string txtAddr = *tns;
           if(!tns->empty()) {
@@ -938,13 +934,13 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
         }
 
         if(remoteIPs.empty()) {
-          LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
+          LOG(prefix<<qname.toString()<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
           flawedNSSet=true;
           continue;
         }
         else {
 
-          LOG(prefix<<qname<<": Resolved '"+auth+"' NS "<<*tns<<" to: ");
+          LOG(prefix<<qname.toString()<<": Resolved '"+auth+"' NS "<<*tns<<" to: ");
           for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
             if(remoteIP != remoteIPs.begin()) {
               LOG(", ");
@@ -956,21 +952,21 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
         }
 
         for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
-          LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
+          LOG(prefix<<qname.toString()<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname.toString()<<"|"<<qtype.getName()<<"'"<<endl);
           extern NetmaskGroup* g_dontQuery;
 
           if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(*remoteIP, "", 0))) {
-            LOG(prefix<<qname<<": server throttled "<<endl);
+            LOG(prefix<<qname.toString()<<": server throttled "<<endl);
             s_throttledqueries++; d_throttledqueries++;
             continue;
           }
           else if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()))) {
-            LOG(prefix<<qname<<": query throttled "<<endl);
+            LOG(prefix<<qname.toString()<<": query throttled "<<endl);
             s_throttledqueries++; d_throttledqueries++;
             continue;
           }
           else if(!pierceDontQuery && g_dontQuery && g_dontQuery->match(&*remoteIP)) {
-            LOG(prefix<<qname<<": not sending query to " << remoteIP->toString() << ", blocked by 'dont-query' setting" << endl);
+            LOG(prefix<<qname.toString()<<": not sending query to " << remoteIP->toString() << ", blocked by 'dont-query' setting" << endl);
             s_dontqueries++;
             continue;
           }
@@ -979,7 +975,7 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
             if(d_outqueries + d_throttledqueries > s_maxqperq) throw ImmediateServFailException("more than "+lexical_cast<string>(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname);
           TryTCP:
             if(doTCP) {
-              LOG(prefix<<qname<<": using TCP with "<< remoteIP->toStringWithPort() <<endl);
+              LOG(prefix<<qname.toString()<<": using TCP with "<< remoteIP->toStringWithPort() <<endl);
               s_tcpoutqueries++; d_tcpoutqueries++;
             }
 
@@ -987,7 +983,7 @@ int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth,
              throw ImmediateServFailException("Too much time waiting for "+qname+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries) + ", queries: "+lexical_cast<string>(d_outqueries)+", "+lexical_cast<string>(d_totUsec/1000)+"msec");
 
            if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_result, resolveret)) {
-             LOG(prefix<<qname<<": query handled by Lua"<<endl);
+             LOG(prefix<<qname.toString()<<": query handled by Lua"<<endl);
            }
            else
              resolveret=asyncresolveWrapper(*remoteIP, qname,  qtype.getCode(),
index 711bfa3c83c971e8ea6c94b7149db515002e1e96..909a95342c000c88409cb52702a205db9b966584 100644 (file)
@@ -27,9 +27,9 @@ void primeHints(void);
 class RecursorLua;
 struct NegCacheEntry
 {
-  string d_name;
+  DNSName d_name;
   QType d_qtype;
-  string d_qname;
+  DNSName d_qname;
   uint32_t d_ttd;
   uint32_t getTTD() const
   {
@@ -239,7 +239,7 @@ public:
 
   explicit SyncRes(const struct timeval& now);
 
-  int beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
+  int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
   void setId(int id)
   {
     if(doLog())
@@ -285,7 +285,7 @@ public:
   }
 
 
-  int asyncresolveWrapper(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res);
+  int asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res);
   
   static void doEDNSDumpAndClose(int fd);
 
@@ -315,10 +315,10 @@ public:
        ordered_unique<
            composite_key<
                  NegCacheEntry,
-                    member<NegCacheEntry, string, &NegCacheEntry::d_name>,
+                    member<NegCacheEntry, DNSName, &NegCacheEntry::d_name>,
                     member<NegCacheEntry, QType, &NegCacheEntry::d_qtype>
            >,
-           composite_key_compare<CIStringCompare, std::less<QType> >
+           composite_key_compare<std::less<DNSName>, std::less<QType> >
        >,
        sequenced<> 
     >
@@ -374,7 +374,7 @@ public:
     ComboAddress d_best;
   };
 
-  typedef map<string, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;  
+  typedef map<DNSName, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;  
 
   struct EDNSStatus
   {
@@ -398,10 +398,10 @@ public:
       indexed_by < 
         ordered_non_unique< 
           composite_key< DNSResourceRecord,
-                        member<DNSResourceRecord, string, &DNSResourceRecord::qname>,
+                        member<DNSResourceRecord, DNSName, &DNSResourceRecord::qname>,
                         member<DNSResourceRecord, QType, &DNSResourceRecord::qtype>
                        >,
-          composite_key_compare<CIStringCompare, std::less<QType> >
+          composite_key_compare<std::less<DNSName>, std::less<QType> >
         >
       >
     > records_t;
@@ -409,10 +409,10 @@ public:
   };
   
 
-  typedef map<string, AuthDomain, CIStringCompare> domainmap_t;
+  typedef map<DNSName, AuthDomain> domainmap_t;
   
 
-  typedef Throttle<boost::tuple<ComboAddress,string,uint16_t> > throttle_t;
+  typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t;
 
   typedef Counters<ComboAddress> fails_t;
   
@@ -438,19 +438,19 @@ public:
 
 private:
   struct GetBestNSAnswer;
-  int doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
+  int doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
                  int depth, set<GetBestNSAnswer>&beenthere);
-  int doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
-  bool doOOBResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
-  domainmap_t::const_iterator getBestAuthZone(string* qname);
-  bool doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
-  bool doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
-  void getBestNSFromCache(const string &qname, const QType &qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
-  string getBestNSNamesFromCache(const string &qname, const QType &qtype, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
-
-  inline vector<string> shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix);
+  int doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
+  bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
+  domainmap_t::const_iterator getBestAuthZone(DNSName* qname);
+  bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
+  bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
+  void getBestNSFromCache(const DNSName &qname, const QType &qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
+  DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, set<DNSName>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
+
+  inline vector<DNSName> shuffleInSpeedOrder(set<DNSName> &nameservers, const string &prefix);
   bool moreSpecificThan(const string& a, const string &b);
-  vector<ComboAddress> getAddrs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);
+  vector<ComboAddress> getAddrs(const DNSName &qname, int depth, set<GetBestNSAnswer>& beenthere);
 private:
   ostringstream d_trace;
   shared_ptr<RecursorLua> d_pdl;
@@ -463,8 +463,8 @@ private:
 
   struct GetBestNSAnswer
   {
-    string qname;
-    set<pair<string,string> > bestns;
+    DNSName qname;
+    set<pair<DNSName,string> > bestns; // FIXME right side really should be DNSName too
     uint8_t qtype; // only A and AAAA anyhow
     bool operator<(const GetBestNSAnswer &b) const
     {
@@ -491,7 +491,7 @@ struct PacketID
 
   uint16_t id;  // wait for a specific id/remote pair
   ComboAddress remote;  // this is the remote
-  string domain;             // this is the question 
+  DNSName domain;             // this is the question 
   uint16_t type;             // and this is its type
 
   Socket* sock;  // or wait for an event on a TCP fd
@@ -516,12 +516,7 @@ struct PacketID
     if( tie(remote, ourSock, type) > tie(b.remote, bSock, b.type))
       return false;
 
-    if(pdns_ilexicographical_compare(domain, b.domain))
-      return true;
-    if(pdns_ilexicographical_compare(b.domain, domain))
-      return false;
-
-    return tie(fd, id) < tie(b.fd, b.id);
+    return tie(domain, fd, id) < tie(b.domain, b.fd, b.id);
   }
 };
 
@@ -536,7 +531,7 @@ struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID,
     if( tie(a.remote, ourSock, a.type) > tie(b.remote, bSock, b.type))
       return false;
 
-    return pdns_ilexicographical_compare(a.domain, b.domain);
+    return pdns_ilexicographical_compare(a.domain.toString(), b.domain.toString()); // FIXME
   }
 };
 extern __thread MemRecursorCache* t_RC;
@@ -616,7 +611,7 @@ typedef boost::circular_buffer<ComboAddress> addrringbuf_t;
 #endif
 extern __thread addrringbuf_t* t_servfailremotes, *t_largeanswerremotes, *t_remotes;
 
-extern __thread boost::circular_buffer<pair<std::string,uint16_t> >* t_queryring, *t_servfailqueryring;
+extern __thread boost::circular_buffer<pair<DNSName,uint16_t> >* t_queryring, *t_servfailqueryring;
 extern __thread NetmaskGroup* t_allowFrom;
 string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
 string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end);
@@ -629,9 +624,9 @@ ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
 ComboAddress getQueryLocalAddress(int family, uint16_t port);
 typedef boost::function<void*(void)> pipefunc_t;
 void broadcastFunction(const pipefunc_t& func, bool skipSelf = false);
-void distributeAsyncFunction(const std::string& question, const pipefunc_t& func);
+void distributeAsyncFunction(const DNSName& question, const pipefunc_t& func);
 
-int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
+int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
 
 template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
 
@@ -646,7 +641,7 @@ uint64_t* pleaseGetConcurrentQueries();
 uint64_t* pleaseGetThrottleSize();
 uint64_t* pleaseGetPacketCacheHits();
 uint64_t* pleaseGetPacketCacheSize();
-uint64_t* pleaseWipeCache(const std::string& canon);
-uint64_t* pleaseWipeAndCountNegCache(const std::string& canon);
+uint64_t* pleaseWipeCache(const DNSName& canon);
+uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon);
 void doCarbonDump(void*);
 #endif