]> granicus.if.org Git - pdns/commitdiff
recursor runs!
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Mon, 15 Jun 2015 13:47:10 +0000 (15:47 +0200)
committermind04 <mind04@monshouwer.org>
Tue, 30 Jun 2015 06:12:48 +0000 (08:12 +0200)
pdns/misc.cc
pdns/misc.hh
pdns/pdns_recursor.cc
pdns/recursor_cache.cc
pdns/syncres.cc
pdns/syncres.hh
pdns/ws-recursor.cc

index 6e673a9ab4ad3d9b3bb5a17bc1a0ade83ee602bc..5c7862d428fa98e26d78f872c75e13927163e84f 100644 (file)
@@ -59,7 +59,7 @@ int writen2(int fd, const void *buf, size_t count)
 {
   const char *ptr = (char*)buf;
   const char *eptr = ptr + count;
-  
+
   int res;
   while(ptr != eptr) {
     res = ::write(fd, ptr, eptr - ptr);
@@ -71,10 +71,10 @@ int writen2(int fd, const void *buf, size_t count)
     }
     else if (res == 0)
       throw std::runtime_error("could not write all bytes, got eof in writen2");
-    
+
     ptr += res;
   }
-  
+
   return count;
 }
 
@@ -84,15 +84,15 @@ int readn2(int fd, void* buffer, unsigned int len)
   int res;
   for(;;) {
     res = read(fd, (char*)buffer + pos, len - pos);
-    if(res == 0) 
+    if(res == 0)
       throw runtime_error("EOF while writing message");
     if(res < 0) {
       if (errno == EAGAIN)
         throw std::runtime_error("used writen2 on non-blocking socket, got EAGAIN");
       else
         unixDie("failed in writen2");
-    } 
-    
+    }
+
     pos+=res;
     if(pos == len)
       break;
@@ -150,14 +150,14 @@ bool stripDomainSuffix(string *qname, const string &domain)
 }
 
 /** Chops off the start of a domain, so goes from 'www.ds9a.nl' to 'ds9a.nl' to 'nl' to ''. Return zero on the empty string */
-bool chopOff(string &domain) 
+bool chopOff(string &domain)
 {
   if(domain.empty())
     return false;
 
   string::size_type fdot=domain.find('.');
 
-  if(fdot==string::npos) 
+  if(fdot==string::npos)
     domain="";
   else {
     string::size_type remain = domain.length() - (fdot + 1);
@@ -178,7 +178,7 @@ bool chopOffDotted(string &domain)
   if(fdot == string::npos)
     return false;
 
-  if(fdot==domain.size()-1) 
+  if(fdot==domain.size()-1)
     domain=".";
   else  {
     string::size_type remain = domain.length() - (fdot + 1);
@@ -203,14 +203,14 @@ bool ciEqual(const string& a, const string& b)
 }
 
 /** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
-bool endsOn(const string &domain, const string &suffix) 
+bool endsOn(const string &domain, const string &suffix)
 {
   if( suffix.empty() || ciEqual(domain, suffix) )
     return true;
 
   if(domain.size()<=suffix.size())
     return false;
-  
+
   string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
 
   if(domain[dpos++]!='.')
@@ -223,15 +223,22 @@ 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) 
+bool dottedEndsOn(const string &domain, const string &suffix)
 {
   if( suffix=="." || ciEqual(domain, suffix) )
     return true;
 
   if(domain.size()<=suffix.size())
     return false;
-  
+
   string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
 
   if(domain[dpos++]!='.')
@@ -299,7 +306,7 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds)
   struct pollfd pfd;
   memset(&pfd, 0, sizeof(pfd));
   pfd.fd = fd;
-  
+
   if(waitForRead)
     pfd.events=POLLIN;
   else
@@ -321,7 +328,7 @@ int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
   memset(&pfds[0], 0, 2*sizeof(struct pollfd));
   pfds[0].fd = fd1;
   pfds[1].fd = fd2;
-  
+
   pfds[0].events= pfds[1].events = POLLIN;
 
   int nsocks = 1 + (fd2 >= 0); // fd2 can optionally be -1
@@ -332,7 +339,7 @@ int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
     ret = poll(pfds, nsocks, -1);
   if(!ret || ret < 0)
     return ret;
-    
+
   if((pfds[0].revents & POLLIN) && !(pfds[1].revents & POLLIN))
     *fd = pfds[0].fd;
   else if((pfds[1].revents & POLLIN) && !(pfds[0].revents & POLLIN))
@@ -342,7 +349,7 @@ int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
   }
   else
     *fd = -1; // should never happen
-  
+
   return 1;
 }
 
@@ -386,7 +393,7 @@ const string unquotify(const string &item)
 
   string::size_type bpos=0, epos=item.size();
 
-  if(item[0]=='"') 
+  if(item[0]=='"')
     bpos=1;
 
   if(item[epos-1]=='"')
@@ -478,7 +485,7 @@ bool IpToU32(const string &str, uint32_t *ip)
     *ip=0;
     return true;
   }
-  
+
   struct in_addr inp;
   if(inet_aton(str.c_str(), &inp)) {
     *ip=inp.s_addr;
@@ -490,7 +497,7 @@ bool IpToU32(const string &str, uint32_t *ip)
 string U32ToIP(uint32_t val)
 {
   char tmp[17];
-  snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u", 
+  snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u",
            (val >> 24)&0xff,
            (val >> 16)&0xff,
            (val >>  8)&0xff,
@@ -516,24 +523,24 @@ string makeHexDump(const string& str)
 void shuffle(vector<DNSResourceRecord>& rrs)
 {
   vector<DNSResourceRecord>::iterator first, second;
-  for(first=rrs.begin();first!=rrs.end();++first) 
+  for(first=rrs.begin();first!=rrs.end();++first)
     if(first->d_place==DNSResourceRecord::ANSWER && first->qtype.getCode() != QType::CNAME) // CNAME must come first
       break;
   for(second=first;second!=rrs.end();++second)
     if(second->d_place!=DNSResourceRecord::ANSWER)
       break;
-  
+
   if(second-first>1)
     random_shuffle(first,second);
-  
+
   // now shuffle the additional records
-  for(first=second;first!=rrs.end();++first) 
+  for(first=second;first!=rrs.end();++first)
     if(first->d_place==DNSResourceRecord::ADDITIONAL && first->qtype.getCode() != QType::CNAME) // CNAME must come first
       break;
   for(second=first;second!=rrs.end();++second)
     if(second->d_place!=DNSResourceRecord::ADDITIONAL)
       break;
-  
+
   if(second-first>1)
     random_shuffle(first,second);
 
@@ -658,7 +665,7 @@ string labelReverse(const std::string& qname)
 string makeRelative(const std::string& fqdn, const std::string& zone)
 {
   if(zone.empty())
-    return fqdn;  
+    return fqdn;
   if(toLower(fqdn) != toLower(zone))
     return fqdn.substr(0, fqdn.size() - zone.length() - 1); // strip domain name
   return "";
@@ -668,7 +675,7 @@ string dotConcat(const std::string& a, const std::string &b)
 {
   if(a.empty() || b.empty())
     return a+b;
-  else 
+  else
     return a+"."+b;
 }
 
@@ -683,7 +690,7 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
     if(pos == string::npos || pos + 2 > addr.size() || addr[pos+1]!=':')
       return -1;
     ourAddr.assign(addr.c_str() + 1, pos-1);
-    port = atoi(addr.c_str()+pos+2);  
+    port = atoi(addr.c_str()+pos+2);
   }
   ret->sin6_scope_id=0;
   ret->sin6_family=AF_INET6;
@@ -692,15 +699,15 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
     struct addrinfo* res;
     struct addrinfo hints;
     memset(&hints, 0, sizeof(hints));
-    
+
     hints.ai_family = AF_INET6;
     hints.ai_flags = AI_NUMERICHOST;
-    
+
     int error;
     if((error=getaddrinfo(ourAddr.c_str(), 0, &hints, &res))) { // this is correct
       return -1;
     }
-  
+
     memcpy(ret, res->ai_addr, res->ai_addrlen);
     freeaddrinfo(res);
   }
@@ -717,7 +724,7 @@ int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret)
     return -1;
   }
   struct in_addr inp;
-  
+
   string::size_type pos = str.find(':');
   if(pos == string::npos) { // no port specified, not touching the port
     if(inet_aton(str.c_str(), &inp)) {
@@ -727,13 +734,13 @@ int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret)
     return -1;
   }
   if(!*(str.c_str() + pos + 1)) // trailing :
-    return -1; 
-    
+    return -1;
+
   char *eptr = (char*)str.c_str() + str.size();
   int port = strtol(str.c_str() + pos + 1, &eptr, 10);
   if(*eptr)
     return -1;
-  
+
   ret->sin_port = htons(port);
   if(inet_aton(str.substr(0, pos).c_str(), &inp)) {
     ret->sin_addr.s_addr=inp.s_addr;
@@ -761,12 +768,12 @@ bool stringfgets(FILE* fp, std::string& line)
 {
   char buffer[1024];
   line.clear();
-  
+
   do {
     if(!fgets(buffer, sizeof(buffer), fp))
       return !line.empty();
-    
-    line.append(buffer); 
+
+    line.append(buffer);
   } while(!strchr(buffer, '\n'));
   return true;
 }
@@ -933,14 +940,14 @@ uint32_t pdns_strtoui(const char *nptr, char **endptr, int base)
   if (val > UINT_MAX) {
    errno = ERANGE;
    return UINT_MAX;
-  } 
+  }
 
   return val;
 #endif
 }
 bool setNonBlocking(int sock)
 {
-  int flags=fcntl(sock,F_GETFL,0);    
+  int flags=fcntl(sock,F_GETFL,0);
   if(flags<0 || fcntl(sock, F_SETFL,flags|O_NONBLOCK) <0)
     return false;
   return true;
@@ -948,7 +955,7 @@ bool setNonBlocking(int sock)
 
 bool setBlocking(int sock)
 {
-  int flags=fcntl(sock,F_GETFL,0);    
+  int flags=fcntl(sock,F_GETFL,0);
   if(flags<0 || fcntl(sock, F_SETFL,flags&(~O_NONBLOCK)) <0)
     return false;
   return true;
@@ -960,14 +967,14 @@ int closesocket( int socket )
   int ret=::close(socket);
   if(ret < 0 && errno == ECONNRESET) // see ticket 192, odd BSD behaviour
     return 0;
-  if(ret < 0) 
+  if(ret < 0)
     throw PDNSException("Error closing socket: "+stringerror());
   return ret;
 }
 
 bool setCloseOnExec(int sock)
 {
-  int flags=fcntl(sock,F_GETFD,0);    
+  int flags=fcntl(sock,F_GETFD,0);
   if(flags<0 || fcntl(sock, F_SETFD,flags|FD_CLOEXEC) <0)
     return false;
   return true;
index 90bf5b7983344f19af41466566e887cf8a31de40..e1aaeab14006265567f1d6aed8acf4edeb7987c0 100644 (file)
@@ -89,23 +89,23 @@ stringtok (Container &container, string const &in,
 {
   const string::size_type len = in.length();
   string::size_type i = 0;
-  
+
   while (i<len) {
     // eat leading whitespace
     i = in.find_first_not_of (delimiters, i);
     if (i == string::npos)
       return;   // nothing left but white space
-    
+
     // find the end of the token
     string::size_type j = in.find_first_of (delimiters, i);
-    
+
     // push token
     if (j == string::npos) {
       container.push_back (in.substr(i));
       return;
     } else
       container.push_back (in.substr(i, j-i));
-    
+
     // set up for next loop
     i = j + 1;
   }
@@ -124,23 +124,23 @@ vstringtok (Container &container, string const &in,
 {
   const string::size_type len = in.length();
   string::size_type i = 0;
-  
+
   while (i<len) {
     // eat leading whitespace
     i = in.find_first_not_of (delimiters, i);
     if (i == string::npos)
       return;   // nothing left but white space
-    
+
     // find the end of the token
     string::size_type j = in.find_first_of (delimiters, i);
-    
+
     // push token
     if (j == string::npos) {
       container.push_back (make_pair(i, len));
       return;
     } else
       container.push_back (make_pair(i, j));
-    
+
     // set up for next loop
     i = j + 1;
   }
@@ -183,11 +183,11 @@ public:
 private:
   struct timespec d_start;
 };
-#endif 
+#endif
 
-/** The DTime class can be used for timing statistics with microsecond resolution. 
+/** The DTime class can be used for timing statistics with microsecond resolution.
 On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
-class DTime 
+class DTime
 {
 public:
   DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls
@@ -264,11 +264,11 @@ inline const string toLowerCanonic(const string &upper)
       c = dns_tolower(upper[i]);
       if(c != upper[i])
         reply[i] = c;
-    }   
+    }
     if(upper[i-1]=='.')
       reply.resize(i-1);
   }
-      
+
   return reply;
 }
 
@@ -288,7 +288,7 @@ inline double getTime()
 {
   struct timeval now;
   gettimeofday(&now,0);
-  
+
   return now.tv_sec+now.tv_usec/1000000.0;
 }
 
@@ -309,7 +309,7 @@ inline float makeFloat(const struct timeval& tv)
   return tv.tv_sec + tv.tv_usec/1000000.0f;
 }
 
-inline bool operator<(const struct timeval& lhs, const struct timeval& rhs) 
+inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
 {
   return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
 }
@@ -406,8 +406,8 @@ public:
 
 private:
     mutable native_t value_;
-    
-    // the below is necessary because __sync_fetch_and_add is not universally available on i386.. I 3> RHEL5. 
+
+    // the below is necessary because __sync_fetch_and_add is not universally available on i386.. I 3> RHEL5.
 #if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
     static native_t atomic_exchange_and_add( native_t * pw, native_t dv )
     {
@@ -428,7 +428,7 @@ private:
 
         return r;
     }
-    #else 
+    #else
     static native_t atomic_exchange_and_add( native_t * pw, native_t dv )
     {
       return __sync_fetch_and_add(pw, dv);
@@ -437,7 +437,7 @@ private:
 };
 
 // FIXME this should probably go?
-struct CIStringCompare: public std::binary_function<string, string, bool>  
+struct CIStringCompare: public std::binary_function<string, string, bool>
 {
   bool operator()(const string& a, const string& b) const
   {
@@ -461,7 +461,7 @@ struct CIStringComparePOSIX
    }
 };
 
-struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>  
+struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
 {
   bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
   {
@@ -494,6 +494,14 @@ inline bool isCanonical(const string& qname)
   return qname[qname.size()-1]=='.';
 }
 
+inline bool isCanonical(const DNSName& qname)
+{
+  if(qname.empty())
+    return false;
+  return true;
+}
+
+
 inline DNSName toCanonic(const DNSName& zone, const string& qname)
 {
   if(qname.size()==1 && qname[0]=='@')
@@ -529,7 +537,7 @@ class Regex
 public:
   /** constructor that accepts the expression to regex */
   Regex(const string &expr);
-  
+
   ~Regex()
   {
     regfree(&d_preg);
index 6dc510e451009aafa0fc9c1eff1e4f024481b006..fabc2f88c18bec497657c901843be12c6c5efe96 100644 (file)
@@ -3,7 +3,7 @@
     Copyright (C) 2003 - 2015  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License version 2 
+    it under the terms of the GNU General Public License version 2
     as published by the Free Software Foundation
 
     Additionally, the license of this program contains a special
@@ -30,7 +30,7 @@
 #include "ws-recursor.hh"
 #include <pthread.h>
 #include "recpacketcache.hh"
-#include "utility.hh" 
+#include "utility.hh"
 #include "dns_random.hh"
 #include <iostream>
 #include <errno.h>
@@ -135,7 +135,7 @@ unsigned int g_numThreads, g_numWorkerThreads;
 
 #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
 // Bad Nets taken from both:
-// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml 
+// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
 // and
 // http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
 // where such a network may not be considered a valid destination
@@ -144,7 +144,7 @@ unsigned int g_numThreads, g_numWorkerThreads;
 
 //! used to send information to a newborn mthread
 struct DNSComboWriter {
-  DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), 
+  DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now),
                                                                                                         d_tcp(false), d_socket(-1)
   {}
   MOADNSParser d_mdp;
@@ -187,12 +187,12 @@ ArgvMap &arg()
 void handleTCPClientWritable(int fd, FDMultiplexer::funcparam_t& var);
 
 // -1 is error, 0 is timeout, 1 is success
-int asendtcp(const string& data, Socket* sock) 
+int asendtcp(const string& data, Socket* sock)
 {
   PacketID pident;
   pident.sock=sock;
   pident.outMSG=data;
-  
+
   t_fdm->addWriteFD(sock->getHandle(), handleTCPClientWritable, pident);
   string packet;
 
@@ -230,7 +230,7 @@ int arecvtcp(string& data, int len, Socket* sock, bool incompleteOkay)
   return ret;
 }
 
-vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6; 
+vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
 const ComboAddress g_local4("0.0.0.0"), g_local6("::");
 
 //! pick a random query local address
@@ -238,9 +238,9 @@ ComboAddress getQueryLocalAddress(int family, uint16_t port)
 {
   ComboAddress ret;
   if(family==AF_INET) {
-    if(g_localQueryAddresses4.empty()) 
+    if(g_localQueryAddresses4.empty())
       ret = g_local4;
-    else 
+    else
       ret = g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())];
     ret.sin4.sin_port = htons(port);
   }
@@ -249,7 +249,7 @@ ComboAddress getQueryLocalAddress(int family, uint16_t port)
       ret = g_local6;
     else
       ret = g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())];
-      
+
     ret.sin6.sin6_port = htons(port);
   }
   return ret;
@@ -261,10 +261,10 @@ void setSocketBuffer(int fd, int optname, uint32_t size)
 {
   uint32_t psize=0;
   socklen_t len=sizeof(psize);
-  
+
   if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
     L<<Logger::Error<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
-    return; 
+    return;
   }
 
   if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
@@ -340,7 +340,7 @@ public:
       // we sometimes return a socket that has not yet been assigned to t_fdm
     }
     closesocket(*i);
-    
+
     d_socks.erase(i++);
     --d_numsocks;
   }
@@ -352,8 +352,8 @@ public:
 
     if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
       return ret;
-    
-    if(ret<0) 
+
+    if(ret<0)
       throw PDNSException("Making a socket for resolver (family = "+lexical_cast<string>(family)+"): "+stringerror());
 
     setCloseOnExec(ret);
@@ -361,20 +361,20 @@ public:
     int tries=10;
     while(--tries) {
       uint16_t port;
-      
+
       if(tries==1)  // fall back to kernel 'random'
         port = 0;
       else
         port = 1025 + dns_random(64510);
-      
+
       ComboAddress sin=getQueryLocalAddress(family, port); // does htons for us
 
-      if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0) 
+      if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)
         break;
     }
     if(!tries)
       throw PDNSException("Resolver binding to local query client socket: "+stringerror());
-    
+
     setNonBlocking(ret);
     return ret;
   }
@@ -384,8 +384,8 @@ 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 DNSName& domain, uint16_t qtype, int* fd) 
+int asendto(const char *data, int len, int flags,
+            const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd)
 {
 
   PacketID pident;
@@ -415,7 +415,7 @@ int asendto(const char *data, int len, int flags,
 
   pident.fd=*fd;
   pident.id=id;
-  
+
   t_fdm->addReadFD(*fd, handleUDPServerResponse, pident);
   ret = send(*fd, data, len, 0);
 
@@ -429,11 +429,11 @@ 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, 
+int arecvfrom(char *data, int len, int flags, const ComboAddress& fromaddr, int *d_len,
               uint16_t id, const DNSName& domain, uint16_t qtype, int fd, struct timeval* now)
 {
   static optional<unsigned int> nearMissLimit;
-  if(!nearMissLimit) 
+  if(!nearMissLimit)
     nearMissLimit=::arg().asNum("spoof-nearmiss-max");
 
   PacketID pident;
@@ -448,7 +448,7 @@ int arecvfrom(char *data, int len, int flags, const ComboAddress& fromaddr, int
 
   if(ret > 0) {
     if(packet.empty()) // means "error"
-      return -1; 
+      return -1;
 
     *d_len=(int)packet.size();
     memcpy(data,packet.c_str(),min(len,*d_len));
@@ -480,21 +480,21 @@ typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClient
 tcpClientCounts_t __thread* t_tcpClientCounts;
 
 TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : d_remote(addr), d_fd(fd)
-{ 
-  ++s_currentConnections; 
+{
+  ++s_currentConnections;
   (*t_tcpClientCounts)[d_remote]++;
 }
 
 TCPConnection::~TCPConnection()
 {
-  if(closesocket(d_fd) < 0) 
+  if(closesocket(d_fd) < 0)
     unixDie("closing socket for TCPConnection");
-  if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--) 
+  if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
     t_tcpClientCounts->erase(d_remote);
   --s_currentConnections;
 }
 
-AtomicCounter TCPConnection::s_currentConnections; 
+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.
@@ -543,12 +543,12 @@ void startDoResolve(void *p)
     if(getEDNSOpts(dc->d_mdp, &edo) && !dc->d_tcp) {
       maxanswersize = min(edo.d_packetsize, g_udpTruncationThreshold);
     }
-    ComboAddress local;    
+    ComboAddress local;
     listenSocketsAddresses_t::const_iterator lociter;
     vector<DNSResourceRecord> ret;
     vector<uint8_t> packet;
 
-    DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass); 
+    DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
 
     pw.getHeader()->aa=0;
     pw.getHeader()->ra=1;
@@ -580,7 +580,7 @@ void startDoResolve(void *p)
       sr.setLogMode(SyncRes::Store);
       tracedQuery=true;
     }
-    
+
     if(!g_quiet || tracedQuery)
       L<<Logger::Warning<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
        <<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
@@ -600,7 +600,7 @@ void startDoResolve(void *p)
       getsockname(dc->d_socket, (sockaddr*)&local, &len); // if this fails, we're ok with it
     }
 
-    // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve      
+    // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
     if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
       try {
         res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
@@ -614,7 +614,7 @@ void startDoResolve(void *p)
       if(t_pdl->get()) {
         if(res == RCode::NoError) {
                 vector<DNSResourceRecord>::const_iterator i;
-                for(i=ret.begin(); i!=ret.end(); ++i) 
+                for(i=ret.begin(); i!=ret.end(); ++i)
                   if(i->qtype.getCode() == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
                           break;
                 if(i == ret.end())
@@ -622,17 +622,17 @@ void startDoResolve(void *p)
               }
               else if(res == RCode::NXDomain)
           (*t_pdl)->nxdomain(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
-      
+
       (*t_pdl)->postresolve(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
       }
     }
-    
+
     if(res == PolicyDecision::DROP) {
       g_stats.policyDrops++;
       delete dc;
       dc=0;
       return;
-    }  
+    }
     if(tracedQuery || res == PolicyDecision::PASS || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail)
     {
       string trace(sr.getTrace());
@@ -645,7 +645,7 @@ void startDoResolve(void *p)
         }
       }
     }
-    
+
     if(res == PolicyDecision::PASS) {
       pw.getHeader()->rcode=RCode::ServFail;
       // no commit here, because no record
@@ -654,18 +654,18 @@ void startDoResolve(void *p)
     else {
       pw.getHeader()->rcode=res;
 
-      
+
       if(ret.size()) {
         orderAndShuffle(ret);
         for(vector<DNSResourceRecord>::const_iterator i=ret.begin(); i!=ret.end(); ++i) {
-          pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place); 
+          pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place);
           minTTL = min(minTTL, i->ttl);
           if(i->qtype.getCode() == QType::A) { // blast out A record w/o doing whole dnswriter thing
             uint32_t ip=0;
             IpToU32(i->content, &ip);
             pw.xfr32BitInt(htonl(ip));
           } else {
-            shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content)); 
+            shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content));
             drc->toPacket(pw);
           }
           if(pw.size() > maxanswersize) {
@@ -697,10 +697,10 @@ void startDoResolve(void *p)
       sendmsg(dc->d_socket, &msgh, 0);
       if(!SyncRes::s_nopacketcache && !variableAnswer ) {
         t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()),
-                                            g_now.tv_sec, 
-                                            min(minTTL, 
+                                            g_now.tv_sec,
+                                            min(minTTL,
                                                 (pw.getHeader()->rcode == RCode::ServFail) ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
-                                            ) 
+                                            )
         );
       }
     }
@@ -717,17 +717,17 @@ void startDoResolve(void *p)
       int ret=Utility::writev(dc->d_socket, iov, 2);
       bool hadError=true;
 
-      if(ret == 0) 
+      if(ret == 0)
         L<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl;
-      else if(ret < 0 )  
+      else if(ret < 0 )
         L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl;
       else if((unsigned int)ret != 2 + packet.size())
         L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<ret<<")"<<endl;
       else
         hadError=false;
-      
+
       // update tcp connection status, either by closing or moving to 'BYTE0'
-    
+
       if(hadError) {
         // no need to remove us from FDM, we weren't there
         dc->d_socket = -1;
@@ -739,7 +739,7 @@ void startDoResolve(void *p)
         t_fdm->setReadTTD(dc->d_socket, g_now, g_tcpTimeout);
       }
     }
-    
+
     if(!g_quiet) {
       L<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] answer to "<<(dc->d_mdp.d_header.rd?"":"non-rd ")<<"question '"<<dc->d_mdp.d_qname<<"|"<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype);
       L<<"': "<<ntohs(pw.getHeader()->ancount)<<" answers, "<<ntohs(pw.getHeader()->arcount)<<" additional, took "<<sr.d_outqueries<<" packets, "<<
@@ -747,7 +747,7 @@ void startDoResolve(void *p)
        sr.d_throttledqueries<<" throttled, "<<sr.d_timeouts<<" timeouts, "<<sr.d_tcpoutqueries<<" tcp connections, rcode="<<res<<endl;
     }
 
-    sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++; 
+    sr.d_outqueries ? t_RC->cacheMisses++ : t_RC->cacheHits++;
     float spent=makeFloat(sr.d_now-dc->d_now);
     if(spent < 0.001)
       g_stats.answers0_1++;
@@ -783,7 +783,7 @@ void startDoResolve(void *p)
   catch(...) {
     L<<Logger::Error<<"Any other exception in a resolver context "<< makeLoginfo(dc) <<endl;
   }
-  
+
   g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
 }
 
@@ -794,7 +794,7 @@ void makeControlChannelSocket(int processNum=-1)
     sockname += "."+lexical_cast<string>(processNum);
   sockname+=".controlsocket";
   s_rcc.listen(sockname);
-  
+
   int sockowner = -1;
   int sockgroup = -1;
 
@@ -802,7 +802,7 @@ void makeControlChannelSocket(int processNum=-1)
     sockgroup=::arg().asGid("socket-group");
   if (!::arg().isEmpty("socket-owner"))
     sockowner=::arg().asUid("socket-owner");
-  
+
   if (sockgroup > -1 || sockowner > -1) {
     if(chown(sockname.c_str(), sockowner, sockgroup) < 0) {
       unixDie("Failed to chown control socket");
@@ -824,7 +824,7 @@ void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
     int bytes=recv(conn->getFD(), conn->data, 2, 0);
     if(bytes==1)
       conn->state=TCPConnection::BYTE1;
-    if(bytes==2) { 
+    if(bytes==2) {
       conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
       conn->bytesread=0;
       conn->state=TCPConnection::GETQUESTION;
@@ -864,7 +864,7 @@ void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
         dc=new DNSComboWriter(conn->data, conn->qlen, g_now);
       }
       catch(MOADNSException &mde) {
-        g_stats.clientParseError++; 
+        g_stats.clientParseError++;
         if(g_logCommonErrors)
           L<<Logger::Error<<"Unable to parse packet from TCP client "<< conn->d_remote.toString() <<endl;
         return;
@@ -909,7 +909,7 @@ void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
     if(t_remotes)
       t_remotes->push_back(addr);
     if(t_allowFrom && !t_allowFrom->match(&addr)) {
-      if(!g_quiet) 
+      if(!g_quiet)
         L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
 
       g_stats.unauthorizedTCP++;
@@ -921,11 +921,11 @@ void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
       closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
       return;
     }
-    
+
     setNonBlocking(newsock);
     shared_ptr<TCPConnection> tc(new TCPConnection(newsock, addr));
     tc->state=TCPConnection::BYTE0;
-    
+
     t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
 
     struct timeval now;
@@ -933,7 +933,7 @@ void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
     t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
   }
 }
+
 string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd)
 {
   gettimeofday(&g_now, 0);
@@ -956,7 +956,7 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr
       if(!g_quiet)
         L<<Logger::Notice<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl;
       // t_queryring->push_back("packetcached");
-      
+
       g_stats.packetCacheHits++;
       SyncRes::s_queries++;
       ageDNSPacket(response, age);
@@ -980,12 +980,12 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr
       g_stats.avgLatencyUsec=(1-1.0/g_latencyStatSize)*g_stats.avgLatencyUsec + 0.0; // we assume 0 usec
       return 0;
     }
-  } 
+  }
   catch(std::exception& e) {
     L<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
     return 0;
   }
-  
+
   if(t_pdl->get()) {
     if((*t_pdl)->ipfilter(fromaddr, destaddr)) {
       if(!g_quiet)
@@ -1002,7 +1002,7 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr
     g_stats.overCapacityDrops++;
     return 0;
   }
-  
+
   DNSComboWriter* dc = new DNSComboWriter(question.c_str(), question.size(), g_now);
   dc->setSocket(fd);
   dc->setRemote(&fromaddr);
@@ -1011,8 +1011,8 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr
   dc->d_tcp=false;
   MT->makeThread(startDoResolve, (void*) dc); // deletes dc
   return 0;
-} 
+}
+
 
 void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
 {
@@ -1026,13 +1026,13 @@ void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
   fromaddr.sin6.sin6_family=AF_INET6; // this makes sure fromaddr is big enough
   fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), data, sizeof(data), &fromaddr);
 
-  for(;;) 
+  for(;;)
   if((len=recvmsg(fd, &msgh, 0)) >= 0) {
     if(t_remotes)
       t_remotes->push_back(fromaddr);
 
     if(t_allowFrom && !t_allowFrom->match(&fromaddr)) {
-      if(!g_quiet) 
+      if(!g_quiet)
         L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toString()<<", address not matched by allow-from"<<endl;
 
       g_stats.unauthorizedUDP++;
@@ -1040,7 +1040,7 @@ void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
     }
     BOOST_STATIC_ASSERT(offsetof(sockaddr_in, sin_port) == offsetof(sockaddr_in6, sin6_port));
     if(!fromaddr.sin4.sin_port) { // also works for IPv6
-     if(!g_quiet) 
+     if(!g_quiet)
         L<<Logger::Error<<"["<<MT->getTid()<<"] dropping UDP query from "<<fromaddr.toStringWithPort()<<", can't deal with port 0"<<endl;
 
       g_stats.clientParseError++; // not quite the best place to put it, but needs to go somewhere
@@ -1048,7 +1048,7 @@ void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
     }
     try {
       dnsheader* dh=(dnsheader*)data;
-      
+
       if(dh->qr) {
         if(g_logCommonErrors)
           L<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
@@ -1071,14 +1071,14 @@ void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
       }
     }
     catch(MOADNSException& mde) {
-      g_stats.clientParseError++; 
+      g_stats.clientParseError++;
       if(g_logCommonErrors)
         L<<Logger::Error<<"Unable to parse packet from remote UDP client "<<fromaddr.toString() <<": "<<mde.what()<<endl;
     }
   }
   else {
     // cerr<<t_id<<" had error: "<<stringerror()<<endl;
-    if(errno == EAGAIN) 
+    if(errno == EAGAIN)
       g_stats.noPacketError++;
     break;
   }
@@ -1096,12 +1096,12 @@ void makeTCPServerSockets()
 
   if(locals.empty())
     throw PDNSException("No local address specified");
-  
+
   for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
     ServiceTuple st;
     st.port=::arg().asNum("local-port");
     parseService(*i, st);
-    
+
     ComboAddress sin;
 
     memset((char *)&sin,0, sizeof(sin));
@@ -1109,11 +1109,11 @@ void makeTCPServerSockets()
     if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
       sin.sin6.sin6_family = AF_INET6;
       if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
-        throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'"); 
+        throw PDNSException("Unable to resolve local address for TCP server on '"+ st.host +"'");
     }
 
     fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
-    if(fd<0) 
+    if(fd<0)
       throw PDNSException("Making a TCP server socket for resolver: "+stringerror());
 
     setCloseOnExec(fd);
@@ -1139,9 +1139,9 @@ void makeTCPServerSockets()
 
     sin.sin4.sin_port = htons(st.port);
     int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
-    if (::bind(fd, (struct sockaddr *)&sin, socklen )<0) 
+    if (::bind(fd, (struct sockaddr *)&sin, socklen )<0)
       throw PDNSException("Binding TCP server socket for "+ st.host +": "+stringerror());
-    
+
     setNonBlocking(fd);
     setSocketSendBuffer(fd, 65000);
     listen(fd, 128);
@@ -1149,7 +1149,7 @@ void makeTCPServerSockets()
     g_tcpListenSockets.push_back(fd);
     // we don't need to update g_listenSocketsAddresses since it doesn't work for TCP/IP:
     //  - fd is not that which we know here, but returned from accept()
-    if(sin.sin4.sin_family == AF_INET) 
+    if(sin.sin4.sin_family == AF_INET)
       L<<Logger::Error<<"Listening for TCP queries on "<< sin.toString() <<":"<<st.port<<endl;
     else
       L<<Logger::Error<<"Listening for TCP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
@@ -1164,7 +1164,7 @@ void makeUDPServerSockets()
 
   if(locals.empty())
     throw PDNSException("No local address specified");
-  
+
   for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
     ServiceTuple st;
     st.port=::arg().asNum("local-port");
@@ -1177,9 +1177,9 @@ void makeUDPServerSockets()
     if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
       sin.sin6.sin6_family = AF_INET6;
       if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
-        throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'"); 
+        throw PDNSException("Unable to resolve local address for UDP server on '"+ st.host +"'");
     }
-    
+
     int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
     if(fd < 0) {
       throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
@@ -1190,7 +1190,7 @@ void makeUDPServerSockets()
     if(IsAnyAddress(sin)) {
       setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));     // linux supports this, so why not - might fail on other systems
 #ifdef IPV6_RECVPKTINFO
-      setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); 
+      setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
 #endif
       if(sin.sin6.sin6_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0) {
        L<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
@@ -1206,14 +1206,14 @@ void makeUDPServerSockets()
     sin.sin4.sin_port = htons(st.port);
 
     int socklen=sin.sin4.sin_family==AF_INET ? sizeof(sin.sin4) : sizeof(sin.sin6);
-    if (::bind(fd, (struct sockaddr *)&sin, socklen)<0) 
+    if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
       throw PDNSException("Resolver binding to server socket on port "+ lexical_cast<string>(st.port) +" for "+ st.host+": "+stringerror());
-    
+
     setNonBlocking(fd);
 
     deferredAdd.push_back(make_pair(fd, handleNewUDPQuestion));
     g_listenSocketsAddresses[fd]=sin;  // this is written to only from the startup thread, not from the workers
-    if(sin.sin4.sin_family == AF_INET) 
+    if(sin.sin4.sin_family == AF_INET)
       L<<Logger::Error<<"Listening for UDP queries on "<< sin.toString() <<":"<<st.port<<endl;
     else
       L<<Logger::Error<<"Listening for UDP queries on ["<< sin.toString() <<"]:"<<st.port<<endl;
@@ -1225,11 +1225,11 @@ void daemonize(void)
 {
   if(fork())
     exit(0); // bye bye
-  
-  setsid(); 
+
+  setsid();
 
   int i=open("/dev/null",O_RDWR); /* open stdin */
-  if(i < 0) 
+  if(i < 0)
     L<<Logger::Critical<<"Unable to open /dev/null: "<<stringerror()<<endl;
   else {
     dup2(i,0); /* stdin */
@@ -1261,16 +1261,16 @@ void doStats(void)
 
   uint64_t cacheHits = broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
   uint64_t cacheMisses = broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
-  
+
   if(g_stats.qcounter && (cacheHits + cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) {
     L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<
       broadcastAccFunction<uint64_t>(pleaseGetCacheSize)<< " cache entries, "<<
       broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize)<<" negative entries, "<<
-      (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl; 
-    
+      (int)((cacheHits*100.0)/(cacheHits+cacheMisses))<<"% cache hits"<<endl;
+
     L<<Logger::Warning<<"stats: throttle map: "
       << broadcastAccFunction<uint64_t>(pleaseGetThrottleSize) <<", ns speeds: "
-      << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;  
+      << broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize)<<endl;
     L<<Logger::Warning<<"stats: outpacket/query ratio "<<(int)(SyncRes::s_outqueries*100.0/SyncRes::s_queries)<<"%";
     L<<Logger::Warning<<", "<<(int)(SyncRes::s_throttledqueries*100.0/(SyncRes::s_outqueries+SyncRes::s_throttledqueries))<<"% throttled, "
      <<SyncRes::s_nodelegated<<" no-delegation drops"<<endl;
@@ -1279,10 +1279,10 @@ void doStats(void)
 
     //L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<<
       //g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl;
-    
+
     L<<Logger::Warning<<"stats: " <<  broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize) <<
     " packet cache entries, "<<(int)(100.0*broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits)/SyncRes::s_queries) << "% packet cache hits"<<endl;
-    
+
     time_t now = time(0);
     if(lastOutputTime && lastQueryCount && now != lastOutputTime) {
       L<<Logger::Warning<<"stats: "<< (SyncRes::s_queries - lastQueryCount) / (now - lastOutputTime) <<" qps (average over "<< (now - lastOutputTime) << " seconds)"<<endl;
@@ -1290,7 +1290,7 @@ void doStats(void)
     lastOutputTime = now;
     lastQueryCount = SyncRes::s_queries;
   }
-  else if(statsWanted) 
+  else if(statsWanted)
     L<<Logger::Warning<<"stats: no stats yet!"<<endl;
 
   statsWanted=false;
@@ -1305,18 +1305,18 @@ static void houseKeeping(void *)
     if(s_running)
       return;
     s_running=true;
-    
+
     struct timeval now;
     Utility::gettimeofday(&now, 0);
-    
-    if(now.tv_sec - last_prune > (time_t)(5 + t_id)) { 
+
+    if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
       DTime dt;
       dt.setTimeval(now);
       t_RC->doPrune(); // this function is local to a thread, so fine anyhow
       t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numWorkerThreads);
-      
+
       pruneCollection(t_sstorage->negcache, ::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10), 200);
-      
+
       if(!((cleanCounter++)%40)) {  // this is a full scan!
        time_t limit=now.tv_sec-300;
        for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); )
@@ -1327,12 +1327,12 @@ static void houseKeeping(void *)
       }
       last_prune=time(0);
     }
-    
+
     if(now.tv_sec - last_rootupdate > 7200) {
       SyncRes sr(now);
       sr.setDoEDNS0(true);
       vector<DNSResourceRecord> ret;
-      
+
       sr.setNoCache();
       int res=-1;
       try {
@@ -1349,13 +1349,13 @@ static void houseKeeping(void *)
       else
        L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
     }
-    
+
     if(!t_id) {
-      if(now.tv_sec - last_stat >= 1800) { 
+      if(now.tv_sec - last_stat >= 1800) {
        doStats();
        last_stat=time(0);
       }
-      
+
       if(now.tv_sec - last_secpoll >= 3600) {
        try {
          doSecPoll(&last_secpoll);
@@ -1380,15 +1380,15 @@ void makeThreadPipes()
     int fd[2];
     if(pipe(fd) < 0)
       unixDie("Creating pipe for inter-thread communications");
-    
+
     tps.readToThread = fd[0];
     tps.writeToThread = fd[1];
-    
+
     if(pipe(fd) < 0)
       unixDie("Creating pipe for inter-thread communications");
     tps.readFromThread = fd[0];
     tps.writeFromThread = fd[1];
-    
+
     g_pipes.push_back(tps);
   }
 }
@@ -1402,24 +1402,24 @@ struct ThreadMSG
 void broadcastFunction(const pipefunc_t& func, bool skipSelf)
 {
   unsigned int n = 0;
-  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes) 
+  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes)
   {
     if(n++ == t_id) {
       if(!skipSelf)
         func(); // don't write to ourselves!
       continue;
     }
-  
+
     ThreadMSG* tmsg = new ThreadMSG();
     tmsg->func = func;
     tmsg->wantAnswer = true;
     if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
       unixDie("write to thread pipe returned wrong size or error");
-    
+
     string* resp;
     if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
       unixDie("read from thread pipe returned wrong size or error");
-    
+
     if(resp) {
 //      cerr <<"got response: " << *resp << endl;
       delete resp;
@@ -1428,32 +1428,33 @@ void broadcastFunction(const pipefunc_t& func, bool skipSelf)
 }
 
 uint32_t g_disthashseed;
-void distributeAsyncFunction(const std::string& question, const pipefunc_t& func)
+void distributeAsyncFunction(const DNSName& question, const pipefunc_t& func)
 {
-  unsigned int hash = hashQuestion(question.c_str(), question.length(), g_disthashseed);
+  string squestion = question.toString();
+  unsigned int hash = hashQuestion(squestion.c_str(), squestion.length(), g_disthashseed);
   unsigned int target = 1 + (hash % (g_pipes.size()-1));
 
   if(target == t_id) {
     func();
     return;
   }
-  ThreadPipeSet& tps = g_pipes[target];    
+  ThreadPipeSet& tps = g_pipes[target];
   ThreadMSG* tmsg = new ThreadMSG();
   tmsg->func = func;
   tmsg->wantAnswer = false;
-  
+
   if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
-    unixDie("write to thread pipe returned wrong size or error");    
+    unixDie("write to thread pipe returned wrong size or error");
 }
 
 void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
 {
   ThreadMSG* tmsg;
-  
-  if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread 
+
+  if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread
     unixDie("read from thread pipe returned wrong size or error");
   }
-  
+
   void *resp=0;
   try {
     resp = tmsg->func();
@@ -1467,7 +1468,7 @@ void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
   if(tmsg->wantAnswer)
     if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
       unixDie("write to thread pipe returned wrong size or error");
-  
+
   delete tmsg;
 }
 
@@ -1488,12 +1489,18 @@ vector<pair<string, uint16_t> >& operator+=(vector<pair<string, uint16_t> >&a, c
   return a;
 }
 
+vector<pair<DNSName, uint16_t> >& operator+=(vector<pair<DNSName, uint16_t> >&a, const vector<pair<DNSName, uint16_t> >& b)
+{
+  a.insert(a.end(), b.begin(), b.end());
+  return a;
+}
+
 
 template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf)
 {
   unsigned int n = 0;
   T ret=T();
-  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes) 
+  BOOST_FOREACH(ThreadPipeSet& tps, g_pipes)
   {
     if(n++ == t_id) {
       if(!skipSelf) {
@@ -1506,19 +1513,19 @@ template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool
       }
       continue;
     }
-      
+
     ThreadMSG* tmsg = new ThreadMSG();
     tmsg->func = boost::bind(voider<T>, func);
     tmsg->wantAnswer = true;
-  
+
     if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
       unixDie("write to thread pipe returned wrong size or error");
-  
-    
+
+
     T* resp;
     if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
       unixDie("read from thread pipe returned wrong size or error");
-    
+
     if(resp) {
       //~ cerr <<"got response: " << *resp << endl;
       ret += *resp;
@@ -1531,7 +1538,7 @@ template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool
 template string broadcastAccFunction(const boost::function<string*()>& fun, bool skipSelf); // explicit instantiation
 template uint64_t broadcastAccFunction(const boost::function<uint64_t*()>& fun, bool skipSelf); // explicit instantiation
 template vector<ComboAddress> broadcastAccFunction(const boost::function<vector<ComboAddress> *()>& fun, bool skipSelf); // explicit instantiation
-template vector<pair<string,uint16_t> > broadcastAccFunction(const boost::function<vector<pair<string, uint16_t> > *()>& fun, bool skipSelf); // explicit instantiation
+template vector<pair<DNSName,uint16_t> > broadcastAccFunction(const boost::function<vector<pair<DNSName, uint16_t> > *()>& fun, bool skipSelf); // explicit instantiation
 
 void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
 {
@@ -1539,7 +1546,7 @@ void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
   string msg=s_rcc.recv(&remote);
   RecursorControlParser rcp;
   RecursorControlParser::func_t* command;
-  
+
   string answer=rcp.getAnswer(msg, &command);
   try {
     s_rcc.send(answer, &remote);
@@ -1568,9 +1575,9 @@ void handleTCPClientReadable(int fd, FDMultiplexer::funcparam_t& var)
       //      cerr<<"Got entire load of "<<pident->inMSG.size()<<" bytes"<<endl;
       PacketID pid=*pident;
       string msg=pident->inMSG;
-      
+
       t_fdm->removeReadFD(fd);
-      MT->sendEvent(pid, &msg); 
+      MT->sendEvent(pid, &msg);
     }
     else {
       //      cerr<<"Still have "<<pident->inNeeded<<" left to go"<<endl;
@@ -1634,7 +1641,7 @@ void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
     if(len < 0)
       ; //      cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
     else {
-      g_stats.serverParseError++; 
+      g_stats.serverParseError++;
       if(g_logCommonErrors)
         L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
           ": packet smaller than DNS header"<<endl;
@@ -1644,16 +1651,16 @@ void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
     string empty;
 
     MT_t::waiters_t::iterator iter=MT->d_waiters.find(pid);
-    if(iter != MT->d_waiters.end()) 
+    if(iter != MT->d_waiters.end())
       doResends(iter, pid, empty);
-    
+
     MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
     return;
-  }  
+  }
 
   dnsheader dh;
   memcpy(&dh, data, sizeof(dh));
-  
+
   PacketID pident;
   pident.remote=fromaddr;
   pident.id=dh.id;
@@ -1697,7 +1704,7 @@ retryWithName:
       }
 
       // be a bit paranoid here since we're weakening our matching
-      if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type && 
+      if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
          pident.id  == mthread->key.id && mthread->key.remote == pident.remote) {
         // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
         pident.domain = mthread->key.domain;
@@ -1735,7 +1742,7 @@ FDMultiplexer* getMultiplexer()
   exit(1);
 }
 
-  
+
 string* doReloadLuaScript()
 {
   string fname= ::arg()["lua-dns-script"];
@@ -1753,18 +1760,18 @@ string* doReloadLuaScript()
     L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
     return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
   }
-    
+
   L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
   return new string("(re)loaded '"+fname+"'\n");
 }
 
 string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
 {
-  if(begin != end) 
+  if(begin != end)
     ::arg().set("lua-dns-script") = *begin;
-  
+
   return broadcastAccFunction<string>(doReloadLuaScript);
-}  
+}
 
 string* pleaseUseNewTraceRegex(const std::string& newRegex)
 try
@@ -1831,12 +1838,12 @@ char** g_argv;
 void parseACLs()
 {
   static bool l_initialized;
-  
+
   if(l_initialized) { // only reload configuration file on second call
     string configname=::arg()["config-dir"]+"/recursor.conf";
     cleanSlashes(configname);
-    
-    if(!::arg().preParseFile(configname.c_str(), "allow-from-file")) 
+
+    if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
       throw runtime_error("Unable to re-parse configuration file '"+configname+"'");
     ::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
     ::arg().preParseFile(configname.c_str(), "include-dir");
@@ -1858,12 +1865,12 @@ void parseACLs()
   }
 
   NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup;
-  
+
   if(!::arg()["allow-from-file"].empty()) {
     string line;
     ifstream ifs(::arg()["allow-from-file"].c_str());
     if(!ifs) {
-      delete allowFrom; 
+      delete allowFrom;
       throw runtime_error("Could not open '"+::arg()["allow-from-file"]+"': "+stringerror());
     }
 
@@ -1883,7 +1890,7 @@ void parseACLs()
   else if(!::arg()["allow-from"].empty()) {
     vector<string> ips;
     stringtok(ips, ::arg()["allow-from"], ", ");
-    
+
     L<<Logger::Warning<<"Only allowing queries from: ";
     for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
       allowFrom->addMask(*i);
@@ -1894,16 +1901,16 @@ void parseACLs()
     L<<Logger::Warning<<endl;
   }
   else {
-    if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53) 
+    if(::arg()["local-address"]!="127.0.0.1" && ::arg().asNum("local-port")==53)
       L<<Logger::Error<<"WARNING: Allowing queries from all IP addresses - this can be a security risk!"<<endl;
     delete allowFrom;
     allowFrom = 0;
   }
-  
+
   g_initialAllowFrom = allowFrom;
   broadcastFunction(boost::bind(pleaseSupplantACLs, allowFrom));
   delete oldAllowFrom;
-  
+
   l_initialized = true;
 }
 
@@ -1946,12 +1953,12 @@ int serviceMain(int argc, char*argv[])
   }
 
   g_quiet=::arg().mustDo("quiet");
-  
+
   g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
   if(g_weDistributeQueries) {
       L<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
   }
-  
+
   if(::arg()["trace"]=="fail") {
     SyncRes::setDefaultLogMode(SyncRes::Store);
   }
@@ -1960,16 +1967,16 @@ int serviceMain(int argc, char*argv[])
     ::arg().set("quiet")="no";
     g_quiet=false;
   }
-  
+
   SyncRes::s_minimumTTL = ::arg().asNum("minimum-ttl-override");
 
   checkLinuxIPv6Limits();
   try {
-    vector<string> addrs;  
+    vector<string> addrs;
     if(!::arg()["query-local-address6"].empty()) {
       SyncRes::s_doIPv6=true;
       L<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
-      
+
       stringtok(addrs, ::arg()["query-local-address6"], ", ;");
       BOOST_FOREACH(const string& addr, addrs) {
         g_localQueryAddresses6.push_back(ComboAddress(addr));
@@ -2012,13 +2019,13 @@ int serviceMain(int argc, char*argv[])
     gethostname(tmp, sizeof(tmp)-1);
     SyncRes::s_serverID=tmp;
   }
-  
+
   g_networkTimeoutMsec = ::arg().asNum("network-timeout");
 
   g_initialDomainMap = parseAuthAndForwards();
+
   g_latencyStatSize=::arg().asNum("latency-statistic-size");
-    
+
   g_logCommonErrors=::arg().mustDo("log-common-errors");
 
   g_anyToTcp = ::arg().mustDo("any-to-tcp");
@@ -2032,11 +2039,11 @@ int serviceMain(int argc, char*argv[])
     if(!fork()) // we are child
       break;
   }
-  
+
   s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
   if(!s_pidfname.empty())
-    unlink(s_pidfname.c_str()); // remove possible old pid file 
-  
+    unlink(s_pidfname.c_str()); // remove possible old pid file
+
   if(::arg().mustDo("daemon")) {
     L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
     L.toConsole(Logger::Critical);
@@ -2050,7 +2057,7 @@ int serviceMain(int argc, char*argv[])
   g_numThreads = ::arg().asNum("threads") + ::arg().mustDo("pdns-distributes-queries");
   g_maxMThreads = ::arg().asNum("max-mthreads");
   checkOrFixFDS();
-  
+
   int newgid=0;
   if(!::arg()["setgid"].empty())
     newgid=Utility::makeGidNumeric(::arg()["setgid"]);
@@ -2071,7 +2078,7 @@ int serviceMain(int argc, char*argv[])
   g_numThreads = ::arg().asNum("threads") + ::arg().mustDo("pdns-distributes-queries");
   g_numWorkerThreads = ::arg().asNum("threads");
   makeThreadPipes();
-  
+
   g_tcpTimeout=::arg().asNum("client-tcp-timeout");
   g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
 
@@ -2087,7 +2094,7 @@ int serviceMain(int argc, char*argv[])
     }
     void* res;
 
-    
+
     pthread_join(tid, &res);
   }
   return 0;
@@ -2103,13 +2110,13 @@ try
   t_udpclientsocks = new UDPClientSocks();
   t_tcpClientCounts = new tcpClientCounts_t();
   primeHints();
-  
+
   t_packetCache = new RecursorPacketCache();
-  
+
   L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
-    
+
   t_pdl = new shared_ptr<RecursorLua>();
-  
+
   try {
     if(!::arg()["lua-dns-script"].empty()) {
       *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(::arg()["lua-dns-script"]));
@@ -2120,28 +2127,28 @@ try
     L<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
     _exit(99);
   }
-  
+
   t_traceRegex = new shared_ptr<Regex>();
   unsigned int ringsize=::arg().asNum("stats-ringbuffer-entries") / g_numWorkerThreads;
   if(ringsize) {
     t_remotes = new addrringbuf_t();
     if(g_weDistributeQueries)  // if so, only 1 thread does recvfrom
-      t_remotes->set_capacity(::arg().asNum("stats-ringbuffer-entries"));   
+      t_remotes->set_capacity(::arg().asNum("stats-ringbuffer-entries"));
     else
-      t_remotes->set_capacity(ringsize);   
+      t_remotes->set_capacity(ringsize);
     t_servfailremotes = new addrringbuf_t();
-    t_servfailremotes->set_capacity(ringsize);   
+    t_servfailremotes->set_capacity(ringsize);
     t_largeanswerremotes = new addrringbuf_t();
-    t_largeanswerremotes->set_capacity(ringsize);   
+    t_largeanswerremotes->set_capacity(ringsize);
 
     t_queryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
-    t_queryring->set_capacity(ringsize);   
+    t_queryring->set_capacity(ringsize);
     t_servfailqueryring = new boost::circular_buffer<pair<DNSName, uint16_t> >();
-    t_servfailqueryring->set_capacity(ringsize);   
+    t_servfailqueryring->set_capacity(ringsize);
   }
-  
+
   MT=new MTasker<PacketID,string>(::arg().asNum("stack-size"));
-  
+
   PacketID pident;
 
   t_fdm=getMultiplexer();
@@ -2162,15 +2169,15 @@ try
   t_fdm->addReadFD(g_pipes[t_id].readToThread, handlePipeRequest);
 
   if(!g_weDistributeQueries || !t_id)  // if we distribute queries, only t_id = 0 listens
-    for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i) 
+    for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)
       t_fdm->addReadFD(i->first, i->second);
-  
+
   if(!t_id) {
     t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
   }
 
   unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
-  
+
   bool listenOnTCP(true);
 
   time_t last_carbon=0;
@@ -2178,7 +2185,7 @@ try
   counter=AtomicCounter(0); // used to periodically execute certain tasks
   for(;;) {
     while(MT->schedule(&g_now)); // MTasker letting the mthreads do their thing
-      
+
     if(!(counter%500)) {
       MT->makeThread(houseKeeping, 0);
     }
@@ -2186,7 +2193,7 @@ try
     if(!(counter%55)) {
       typedef vector<pair<int, FDMultiplexer::funcparam_t> > expired_t;
       expired_t expired=t_fdm->getTimeouts(g_now);
-        
+
       for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
         shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
         if(g_logCommonErrors)
@@ -2194,7 +2201,7 @@ try
         t_fdm->removeReadFD(i->first);
       }
     }
-      
+
     counter++;
 
     if(!t_id && statsWanted) {
@@ -2243,7 +2250,7 @@ catch(...) {
 }
 
 
-int main(int argc, char **argv) 
+int main(int argc, char **argv)
 {
   g_argc = argc;
   g_argv = argv;
@@ -2272,7 +2279,7 @@ int main(int argc, char **argv)
     ::arg().set("threads", "Launch this number of threads")="2";
     ::arg().set("processes", "Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)")="1";
     ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
-    ::arg().set( "experimental-logfile", "Filename of the log file for JSON parser" )= "/var/log/pdns.log"; 
+    ::arg().set( "experimental-logfile", "Filename of the log file for JSON parser" )= "/var/log/pdns.log";
     ::arg().setSwitch("experimental-webserver", "Start a webserver for monitoring") = "no";
     ::arg().set("experimental-webserver-address", "IP Address of webserver to listen on") = "127.0.0.1";
     ::arg().set("experimental-webserver-port", "Port of webserver to listen on") = "8082";
@@ -2290,7 +2297,7 @@ int main(int argc, char **argv)
     ::arg().set("socket-owner","Owner of socket")="";
     ::arg().set("socket-group","Group of socket")="";
     ::arg().set("socket-mode", "Permissions for socket")="";
-    
+
     ::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
     ::arg().set("delegation-only","Which domains we only accept delegations from")="";
     ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
@@ -2313,7 +2320,7 @@ int main(int argc, char **argv)
     ::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
     ::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
     ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
-    ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=DONT_QUERY; 
+    ::arg().set("dont-query", "If set, do not query these netmasks for DNS data")=DONT_QUERY;
     ::arg().set("max-tcp-per-client", "If set, maximum number of TCP sessions per client (IP address)")="0";
     ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
     ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
@@ -2327,9 +2334,9 @@ int main(int argc, char **argv)
     ::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="";
     ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
     ::arg().set("latency-statistic-size","Number of latency values to calculate the qa-latency average")="10000";
-//    ::arg().setSwitch( "disable-edns-ping", "Disable EDNSPing - EXPERIMENTAL, LEAVE DISABLED" )= "no"; 
-    ::arg().setSwitch( "disable-edns", "Disable EDNS - EXPERIMENTAL, LEAVE DISABLED" )= ""; 
-    ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no"; 
+//    ::arg().setSwitch( "disable-edns-ping", "Disable EDNSPing - EXPERIMENTAL, LEAVE DISABLED" )= "no";
+    ::arg().setSwitch( "disable-edns", "Disable EDNS - EXPERIMENTAL, LEAVE DISABLED" )= "";
+    ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
     ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")="";
     ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="no";
     ::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
@@ -2359,7 +2366,7 @@ int main(int argc, char **argv)
       exit(0);
     }
 
-    if(!::arg().file(configname.c_str())) 
+    if(!::arg().file(configname.c_str()))
       L<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl;
 
     ::arg().parse(argc,argv);
@@ -2404,6 +2411,6 @@ int main(int argc, char **argv)
     L<<Logger::Error<<"any other exception in main: "<<endl;
     ret=EXIT_FAILURE;
   }
-  
+
   return ret;
 }
index 53affea3e66812ae122a90b28b98f9c7ba0255e9..71c45fb789b567f8b99e614db226745fceb0c315 100644 (file)
 #include "namespaces.hh"
 
 
-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)
 {
   DNSResourceRecord rr;
-  rr.ttl=ttd; 
+  rr.ttl=ttd;
   rr.qtype=qt;
   rr.qname=qname;
 
@@ -40,7 +40,7 @@ DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const strin
 
     while((labellen=serial.at(frompos++))) {
       if((labellen & 0xc0) == 0xc0) {
-        string encoded=simpleCompress(qname);
+        string encoded=qname.toDNSString();
         uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)serial.at(frompos++) - sizeof(dnsheader)-5;
 
         simpleExpandTo(encoded, offset, rr.content);
@@ -123,16 +123,16 @@ int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set
   if(res)
     res->clear();
 
-  if(d_cachecache.first!=d_cachecache.second) { 
-    for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i) 
-      if(i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || 
+  if(d_cachecache.first!=d_cachecache.second) {
+    for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i)
+      if(i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY ||
          (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) )
-         ) {     
+         ) {
         for(vector<StoredRecord>::const_iterator k=i->d_records.begin(); k != i->d_records.end(); ++k) {
           if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) {  // FIXME what does the 100000000 number mean?
             ttd=k->d_ttd;
             if(res) {
-              DNSResourceRecord rr=String2DNSRR(qname, QType(i->d_qtype),  k->d_string, ttd); 
+              DNSResourceRecord rr=String2DNSRR(qname, QType(i->d_qtype),  k->d_string, ttd);
               res->insert(rr);
             }
           }
@@ -154,7 +154,7 @@ int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set
 }
 
 
+
 bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored)
 {
   if(!stored.d_auth) {
@@ -212,8 +212,8 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt
 
   if(!auth && ce.d_auth) {  // unauth data came in, we have some auth data, but is it fresh?
     vector<StoredRecord>::iterator j;
-    for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) 
-      if((time_t)j->d_ttd > now) 
+    for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j)
+      if((time_t)j->d_ttd > now)
         break;
     if(j != ce.d_records.end()) { // we still have valid data, ignore unauth data
       //      cerr<<"\tStill hold valid auth data, and the new data is unauth, return\n";
@@ -223,14 +223,14 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt
       ce.d_auth = false;  // new data won't be auth
     }
   }
-  
+
   // limit TTL of auth->auth NSset update if needed, except for root
   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) {
       maxTTD=min(maxTTD, j->d_ttd);
-    }      
+    }
   }
 
   // make sure that we CAN refresh the root
@@ -253,8 +253,8 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt
     // cerr<<"To store: "<<i->content<<" with ttl/ttd "<<i->ttl<<endl;
     dr.d_ttd=min(maxTTD, i->ttl);
     dr.d_string=DNSRR2String(*i);
-    
-    if(isNew) 
+
+    if(isNew)
       ce.d_records.push_back(dr);
     else {
       range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr);
@@ -288,10 +288,10 @@ void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt
     //    cerr<<"\tSorting (because of isNew)\n";
     sort(ce.d_records.begin(), ce.d_records.end());
   }
-  
+
   if(ce.d_records.capacity() != ce.d_records.size())
     vector<StoredRecord>(ce.d_records).swap(ce.d_records);
-  
+
   d_cache.replace(stored, ce);
 }
 
@@ -339,12 +339,12 @@ bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, uint16_t qtyp
     d_cachecachevalid=false;
 
     uint32_t newTTD = now + newTTL;
-    
+
     for(vector<StoredRecord>::iterator j = ce.d_records.begin() ; j != ce.d_records.end(); ++j)  {
       if(j->d_ttd>newTTD) // do never renew expired or older TTLs
         j->d_ttd = newTTD;
     }
-    
+
     d_cache.replace(iter, ce);
     return true;
   }
@@ -409,4 +409,3 @@ void MemRecursorCache::doPrune(void)
   unsigned int maxCached=::arg().asNum("max-cache-entries") / g_numThreads;
   pruneCollection(d_cache, maxCached);
 }
-
index 704f2b11f6c48a5362cab91a2a33004408b1c44c..5f4236d538980784ae3c41ff135acbdb91fc2925 100644 (file)
@@ -191,7 +191,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
   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)); 
+    range=iter->second.d_records.equal_range(boost::make_tuple(DNSName("*")+wcarddomain));
     if(range.first==range.second)
       continue;
 
@@ -211,7 +211,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
   DNSName nsdomain(qname);
 
   while(nsdomain.chopOff() && !pdns_iequals(nsdomain, iter->first)) {
-    range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS))); 
+    range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS)));
     if(range.first==range.second)
       continue;
 
@@ -221,7 +221,7 @@ bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSR
       ret.push_back(rr);
     }
   }
-  if(ret.empty()) { 
+  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()) {
@@ -251,7 +251,7 @@ void SyncRes::doEDNSDumpAndClose(int fd)
   fclose(fp);
 }
 
-int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const DNSName& 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.
@@ -432,7 +432,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResou
 
   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);
 
   DNSName subdomain(qname);
@@ -448,7 +448,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResou
 
   if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
     return 0;
-  
+
   LOG(prefix<<qname.toString()<<": failed (res="<<res<<")"<<endl);
   return res<0 ? RCode::ServFail : res;
 }
@@ -597,8 +597,8 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<D
       }
     }
     LOG(prefix<<qname.toString()<<": no valid/useful NS in cache for '"<<subdomain.toString()<<"'"<<endl);
-    if(subdomain=="." && !brokeloop) { 
-      primeHints(); 
+    if(subdomain=="." && !brokeloop) {
+      primeHints();
       LOG(prefix<<qname.toString()<<": reprimed the root"<<endl);
     }
   }while(subdomain.chopOff());
@@ -620,7 +620,7 @@ DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtyp
 {
   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() )
@@ -657,14 +657,14 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector
     res=RCode::ServFail;
     return true;
   }
-  
+
   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.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|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);
@@ -703,7 +703,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
   QType sqt(qtype);
   uint32_t sttl=0;
   //  cout<<"Lookup for '"<<qname.toString()<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
-  
+
   pair<negcache_t::const_iterator, negcache_t::const_iterator> range;
   QType qtnull(0);
 
@@ -711,9 +711,9 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
      (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.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; 
+    res = RCode::NXDomain;
     sqname=range.first->d_qname;
     sqt=QType::SOA;
     moveCacheItemToBack(t_sstorage->negcache, range.first);
@@ -735,7 +735,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
          }
          else {
            LOG(prefix<<qname.toString()<<": Entire name '"<<qname.toString()<<"', is negatively cached via '"<<ni->d_qname.toString()<<"' for another "<<sttl<<" seconds"<<endl);
-           res= RCode::NXDomain; 
+           res= RCode::NXDomain;
          }
          giveNegative=true;
          sqname=ni->d_qname;
@@ -795,12 +795,12 @@ bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b)
 
 struct speedOrder
 {
-  speedOrder(map<string,double> &speeds) : d_speeds(speeds) {}
-  bool operator()(const string &a, const string &b) const
+  speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
+  bool operator()(const DNSName &a, const DNSName &b) const
   {
     return d_speeds[a] < d_speeds[b];
   }
-  map<string, double>& d_speeds;
+  map<DNSName, double>& d_speeds;
 };
 
 inline vector<DNSName> SyncRes::shuffleInSpeedOrder(set<DNSName> &tnameservers, const string &prefix)
@@ -823,14 +823,14 @@ inline vector<DNSName> SyncRes::shuffleInSpeedOrder(set<DNSName> &tnameservers,
 
   if(doLog()) {
     LOG(prefix<<"Nameservers: ");
-    for(const auto & i: rnameservers) {
-      if(i!=rnameservers.begin()) {
+               for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
+                       if(i!=rnameservers.begin()) {
         LOG(", ");
         if(!((i-rnameservers.begin())%3)) {
           LOG(endl<<prefix<<"             ");
         }
       }
-      LOG(*i<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
+      LOG(i->toString()<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
     }
     LOG(endl);
   }
@@ -839,14 +839,9 @@ inline vector<DNSName> SyncRes::shuffleInSpeedOrder(set<DNSName> &tnameservers,
 
 struct TCacheComp
 {
-  bool operator()(const pair<string, QType>& a, const pair<string, QType>& b) const
+  bool operator()(const pair<DNSName, QType>& a, const pair<DNSName, QType>& b) const
   {
-    if(pdns_ilexicographical_compare(a.first, b.first))
-      return true;
-    if(pdns_ilexicographical_compare(b.first, a.first))
-      return false;
-
-    return a.second < b.second;
+    return tie(a.first, a.second) < tie(b.first, b.second);
   }
 };
 
@@ -858,8 +853,8 @@ static bool magicAddrMatch(const QType& query, const QType& answer)
 }
 
 /** returns -1 in case of no results, rcode otherwise */
-int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, 
-                         vector<DNSResourceRecord>&ret, 
+int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
+                         vector<DNSResourceRecord>&ret,
                          int depth, set<GetBestNSAnswer>&beenthere)
 {
   string prefix;
@@ -867,13 +862,13 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
     prefix=d_prefix;
     prefix.append(depth, ' ');
   }
-  
+
   LOG(prefix<<qname.toString()<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl);
 
   for(;;) { // we may get more specific nameservers
     vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
-    
-    for(const auto &tns: rnameservers) { 
+
+               for(vector<DNSName >::const_iterator tns=rnameservers.begin();;++tns) {
       if(tns==rnameservers.end()) {
         LOG(prefix<<qname.toString()<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth.toString()<<"'"<<endl);
         if(auth!="." && flawedNSSet) {
@@ -884,7 +879,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         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)) { 
+      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;
       }
@@ -904,12 +899,12 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         lwr.d_aabit=true;
       }
       else {
-        LOG(prefix<<qname.toString()<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
+        LOG(prefix<<qname.toString()<<": Trying to resolve NS '"<<tns->toString()<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
 
         if(!isCanonical(*tns)) {
           LOG(prefix<<qname.toString()<<": Domain has hardcoded nameserver(s)"<<endl);
 
-          string txtAddr = *tns;
+          string txtAddr = tns->toString();
           if(!tns->empty()) {
             sendRDQuery = txtAddr[0] == '+';
             txtAddr=txtAddr.c_str()+1;
@@ -925,7 +920,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         }
 
         if(remoteIPs.empty()) {
-          LOG(prefix<<qname.toString()<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
+          LOG(prefix<<qname.toString()<<": Failed to get IP for NS "<<tns->toString()<<", trying next if available"<<endl);
           flawedNSSet=true;
           continue;
         }
@@ -969,8 +964,8 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
               LOG(prefix<<qname.toString()<<": using TCP with "<< remoteIP->toStringWithPort() <<endl);
               s_tcpoutqueries++; d_tcpoutqueries++;
             }
-            
-           if(s_maxtotusec && d_totUsec > s_maxtotusec) 
+
+           if(s_maxtotusec && d_totUsec > s_maxtotusec)
              throw ImmediateServFailException("Too much time waiting for "+qname.toString()+"|"+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)) {
@@ -1017,7 +1012,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
 //         if(d_timeouts + 0.5*d_throttledqueries > 6.0 && d_timeouts > 2) throw ImmediateServFailException("Too much work resolving "+qname+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries));
 
             if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
-              LOG(prefix<<qname.toString()<<": "<<*tns<<" returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
+              LOG(prefix<<qname.toString()<<": "<<tns->toString()<<" returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
               t_sstorage->throttle.throttle(d_now.tv_sec,boost::make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused
               continue;
             }
@@ -1027,7 +1022,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
 
             break;  // this IP address worked!
           wasLame:; // well, it didn't
-            LOG(prefix<<qname.toString()<<": status=NS "<<*tns<<" ("<< remoteIP->toString() <<") is lame for '"<<auth<<"', trying sibling IP or NS"<<endl);
+            LOG(prefix<<qname.toString()<<": status=NS "<<tns->toString()<<" ("<< remoteIP->toString() <<") is lame for '"<<auth.toString()<<"', trying sibling IP or NS"<<endl);
             t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame
           }
         }
@@ -1044,8 +1039,8 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
           LOG(prefix<<qname.toString()<<": truncated bit set, over TCP?"<<endl);
           return RCode::ServFail;
         }
-        
-        LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
+
+        LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<tns->toString()<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
 
         /*  // for you IPv6 fanatics :-)
         if(remoteIP->sin4.sin_family==AF_INET6)
@@ -1076,7 +1071,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
           LOG("NO! - we don't accept 'ANY' data"<<endl);
           continue;
         }
-          
+
         if(i->qname.isPartOf(auth)) {
           if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth.toString() /* ugh */)) {
             LOG("NO! Is from delegation-only zone"<<endl);
@@ -1116,7 +1111,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
 
         t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit);
       }
-      set<DNSName> nsset;  
+      set<DNSName> nsset;
       LOG(prefix<<qname.toString()<<": determining status after receiving this packet"<<endl);
 
       bool done=false, realreferral=false, negindic=false;
@@ -1126,7 +1121,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::SOA &&
            lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,i->qname) && dottedEndsOn(i->qname, auth)) {
           LOG(prefix<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<dottedEndsOn(i->qname, auth)<<"), newtarget='"<<newtarget.toString()<<"'"<<endl);
-          
+
           i->ttl = min(i->ttl, s_maxnegttl);
           if(!newtarget.length()) // only add a SOA if we're not going anywhere after this
             ret.push_back(*i);
@@ -1159,7 +1154,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
                 )
                )
           {
-          
+
           LOG(prefix<<qname.toString()<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
 
           done=true;
@@ -1171,14 +1166,14 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
             LOG(prefix<<qname.toString()<<": got NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
             realreferral=true;
           }
-          else 
+          else
             LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"', had '"<<auth.toString()<<"'"<<endl);
           nsset.insert(i->content);
         }
         else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
            lwr.d_rcode==RCode::NoError) {
           LOG(prefix<<qname.toString()<<": got negative caching indication for '"<< (qname.toString()+"|"+qtype.getName()+"'") <<endl);
-          
+
           if(!newtarget.empty()) {
             LOG(prefix<<qname.toString()<<": Hang on! Got a redirect to '"<<newtarget.toString()<<"' already"<<endl);
           }
@@ -1198,7 +1193,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
         }
       }
 
-      if(done){ 
+      if(done){
         LOG(prefix<<qname.toString()<<": status=got results, this level of recursion done"<<endl);
         return 0;
       }
index d561b22aafcd8c8c30677d2aa42cf0880b2d8d71..930d2ec9be32cfd8015a622b943738b0e946b824 100644 (file)
@@ -71,18 +71,18 @@ public:
 
     return true; // still listed, still blocked
   }
-  void throttle(time_t now, const Thing& t, time_t ttl=0, unsigned int tries=0) 
+  void throttle(time_t now, const Thing& t, time_t ttl=0, unsigned int tries=0)
   {
     typename cont_t::iterator i=d_cont.find(t);
     entry e={ now+(ttl ? ttl : d_ttl), tries ? tries : d_limit};
 
     if(i==d_cont.end()) {
       d_cont[t]=e;
-    } 
-    else if(i->second.ttd > e.ttd || (i->second.count) < e.count) 
+    }
+    else if(i->second.ttd > e.ttd || (i->second.count) < e.count)
       d_cont[t]=e;
   }
-  
+
   unsigned int size()
   {
     return (unsigned int)d_cont.size();
@@ -91,7 +91,7 @@ private:
   unsigned int d_limit;
   time_t d_ttl;
   time_t d_last_clean;
-  struct entry 
+  struct entry
   {
     time_t ttd;
     unsigned int count;
@@ -108,7 +108,7 @@ private:
 class DecayingEwma
 {
 public:
-  DecayingEwma() :  d_val(0.0) 
+  DecayingEwma() :  d_val(0.0)
   {
     d_needinit=true;
     d_last.tv_sec = d_last.tv_usec = 0;
@@ -145,7 +145,7 @@ public:
 
       d_last=now;
       double factor=exp(diff)/2.0; // might be '0.5', or 0.0001
-      d_val=(float)((1-factor)*val+ (float)factor*d_val); 
+      d_val=(float)((1-factor)*val+ (float)factor*d_val);
     }
   }
 
@@ -235,7 +235,7 @@ private:
 class SyncRes : public boost::noncopyable
 {
 public:
-  enum LogMode { LogNone, Log, Store}; 
+  enum LogMode { LogNone, Log, Store};
 
   explicit SyncRes(const struct timeval& now);
 
@@ -249,15 +249,15 @@ public:
   {
     s_lm = lm;
   }
-  void setLogMode(LogMode lm) 
+
+  void setLogMode(LogMode lm)
   {
     d_lm = lm;
   }
 
   bool doLog()
   {
-    return d_lm != LogNone; 
+    return d_lm != LogNone;
   }
 
   void setCacheOnly(bool state=true)
@@ -286,7 +286,7 @@ public:
 
 
   int asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res);
-  
+
   static void doEDNSDumpAndClose(int fd);
 
   static uint64_t s_queries;
@@ -320,16 +320,16 @@ public:
            >,
            composite_key_compare<std::less<DNSName>, std::less<QType> >
        >,
-       sequenced<> 
+       sequenced<>
     >
   > negcache_t;
-  
-  //! This represents a number of decaying Ewmas, used to store performance per nameserver-name. 
+
+  //! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
   /** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
       d_best is filled out with the best address for this collection */
   struct DecayingEwmaCollection
   {
-    void submit(const ComboAddress& remote, int usecs, struct timeval* now) 
+    void submit(const ComboAddress& remote, int usecs, struct timeval* now)
     {
       collection_t::iterator pos;
       for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
@@ -357,13 +357,13 @@ public:
           d_best=pos->first;
         }
       }
-      
+
       return ret;
     }
-    
+
     bool stale(time_t limit) const
     {
-      for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) 
+      for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos)
         if(!pos->second.stale(limit))
           return false;
       return true;
@@ -374,7 +374,7 @@ public:
     ComboAddress d_best;
   };
 
-  typedef map<DNSName, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;  
+  typedef map<DNSName, DecayingEwmaCollection> nsspeeds_t;  
 
   struct EDNSStatus
   {
@@ -395,8 +395,8 @@ public:
     bool d_rdForward;
     typedef multi_index_container <
       DNSResourceRecord,
-      indexed_by < 
-        ordered_non_unique< 
+      indexed_by <
+        ordered_non_unique<
           composite_key< DNSResourceRecord,
                         member<DNSResourceRecord, DNSName, &DNSResourceRecord::qname>,
                         member<DNSResourceRecord, QType, &DNSResourceRecord::qtype>
@@ -405,17 +405,17 @@ public:
         >
       >
     > records_t;
-    records_t d_records;       
+    records_t d_records;
   };
-  
+
 
   typedef map<DNSName, AuthDomain> domainmap_t;
-  
+
 
   typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t;
 
   typedef Counters<ComboAddress> fails_t;
-  
+
   struct timeval d_now;
   static unsigned int s_maxnegttl;
   static unsigned int s_maxcachettl;
@@ -425,10 +425,10 @@ public:
   static unsigned int s_serverdownthrottletime;
   static bool s_nopacketcache;
   static string s_serverID;
-  
-  
+
+
   struct StaticStorage {
-    negcache_t negcache;    
+    negcache_t negcache;
     nsspeeds_t nsSpeeds;
     ednsstatus_t ednsstatus;
     throttle_t throttle;
@@ -468,7 +468,7 @@ private:
     uint8_t qtype; // only A and AAAA anyhow
     bool operator<(const GetBestNSAnswer &b) const
     {
-      return boost::tie(qname, qtype, bestns) < 
+      return boost::tie(qname, qtype, bestns) <
        boost::tie(b.qname, b.qtype, b.bestns);
     }
   };
@@ -491,7 +491,7 @@ struct PacketID
 
   uint16_t id;  // wait for a specific id/remote pair
   ComboAddress remote;  // this is the remote
-  DNSName 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
@@ -520,7 +520,7 @@ struct PacketID
   }
 };
 
-struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID, bool>  
+struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID, bool>
 {
   bool operator()(const PacketID& a, const PacketID& b) const
   {
@@ -579,7 +579,7 @@ class TCPConnection : public boost::noncopyable
 public:
   TCPConnection(int fd, const ComboAddress& addr);
   ~TCPConnection();
-  
+
   int getFD()
   {
     return d_fd;
index 8f582bfe9278e5ed9a9c7b9af7c2e47d9909c301..0baa019aabd444ecf0dbc2fdbe95d78e0c49feb6 100644 (file)
@@ -149,7 +149,7 @@ static void fillZone(const string& zonename, HttpResponse* resp)
   string url = "/servers/localhost/zones/" + zoneId;
   Value jurl(url.c_str(), doc.GetAllocator()); // copy
   doc.AddMember("url", jurl, doc.GetAllocator());
-  doc.AddMember("name", iter->first.c_str(), doc.GetAllocator());
+  doc.AddMember("name", iter->first.toString().c_str(), doc.GetAllocator());
   doc.AddMember("kind", zone.d_servers.empty() ? "Native" : "Forwarded", doc.GetAllocator());
   Value servers;
   servers.SetArray();
@@ -166,7 +166,7 @@ static void fillZone(const string& zonename, HttpResponse* resp)
   BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) {
     Value object;
     object.SetObject();
-    Value jname(rr.qname.c_str(), doc.GetAllocator()); // copy
+    Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy
     object.AddMember("name", jname, doc.GetAllocator());
     Value jtype(rr.qtype.getName().c_str(), doc.GetAllocator()); // copy
     object.AddMember("type", jtype, doc.GetAllocator());
@@ -311,13 +311,13 @@ static void apiServerZones(HttpRequest* req, HttpResponse* resp)
     Value jdi;
     jdi.SetObject();
     // id is the canonical lookup key, which doesn't actually match the name (in some cases)
-    string zoneId = apiZoneNameToId(val.first);
+    string zoneId = apiZoneNameToId(val.first.toString());
     Value jzoneid(zoneId.c_str(), doc.GetAllocator()); // copy
     jdi.AddMember("id", jzoneid, doc.GetAllocator());
     string url = "/servers/localhost/zones/" + zoneId;
     Value jurl(url.c_str(), doc.GetAllocator()); // copy
     jdi.AddMember("url", jurl, doc.GetAllocator());
-    jdi.AddMember("name", val.first.c_str(), doc.GetAllocator());
+    jdi.AddMember("name", val.first.toString().c_str(), doc.GetAllocator());
     jdi.AddMember("kind", zone.d_servers.empty() ? "Native" : "Forwarded", doc.GetAllocator());
     Value servers;
     servers.SetArray();
@@ -379,14 +379,14 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {
   doc.SetArray();
 
   BOOST_FOREACH(const SyncRes::domainmap_t::value_type& val, *t_sstorage->domainmap) {
-    string zoneId = apiZoneNameToId(val.first);
-    if (pdns_ci_find(val.first, q) != string::npos) {
+    string zoneId = apiZoneNameToId(val.first.toString());
+    if (pdns_ci_find(val.first.toString(), q) != string::npos) {
       Value object;
       object.SetObject();
       object.AddMember("type", "zone", doc.GetAllocator());
       Value jzoneId(zoneId.c_str(), doc.GetAllocator()); // copy
       object.AddMember("zone_id", jzoneId, doc.GetAllocator());
-      Value jzoneName(val.first.c_str(), doc.GetAllocator()); // copy
+      Value jzoneName(val.first.toString().c_str(), doc.GetAllocator()); // copy
       object.AddMember("name", jzoneName, doc.GetAllocator());
       doc.PushBack(object, doc.GetAllocator());
     }
@@ -399,7 +399,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {
     const SyncRes::AuthDomain& zone = val.second;
 
     BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) {
-      if (pdns_ci_find(rr.qname, q) == string::npos && pdns_ci_find(rr.content, q) == string::npos)
+      if (pdns_ci_find(rr.qname.toString(), q) == string::npos && pdns_ci_find(rr.content, q) == string::npos)
         continue;
 
       Value object;
@@ -407,9 +407,9 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {
       object.AddMember("type", "record", doc.GetAllocator());
       Value jzoneId(zoneId.c_str(), doc.GetAllocator()); // copy
       object.AddMember("zone_id", jzoneId, doc.GetAllocator());
-      Value jzoneName(val.first.c_str(), doc.GetAllocator()); // copy
+      Value jzoneName(val.first.toString().c_str(), doc.GetAllocator()); // copy
       object.AddMember("zone_name", jzoneName, doc.GetAllocator());
-      Value jname(rr.qname.c_str(), doc.GetAllocator()); // copy
+      Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy
       object.AddMember("name", jname, doc.GetAllocator());
       Value jcontent(rr.content.c_str(), doc.GetAllocator()); // copy
       object.AddMember("content", jcontent, doc.GetAllocator());
@@ -424,7 +424,7 @@ static void apiServerFlushCache(HttpRequest* req, HttpResponse* resp) {
   if(req->method != "PUT")
     throw HttpMethodNotAllowedException();
 
-  string canon = toCanonic("", req->getvars["domain"]);
+  DNSName canon = req->getvars["domain"];
   int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon));
   count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon));
   map<string, string> object;
@@ -465,31 +465,31 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
     req->getvars.erase("command");
   }
 
-  map<string, string> stats; 
+  map<string, string> stats;
   if(command == "get-query-ring") {
-    typedef pair<string,uint16_t> query_t;
+    typedef pair<DNSName,uint16_t> query_t;
     vector<query_t> queries;
     bool filter=!req->getvars["public-filtered"].empty();
-      
+
     if(req->getvars["name"]=="servfail-queries")
       queries=broadcastAccFunction<vector<query_t> >(pleaseGetServfailQueryRing);
     else if(req->getvars["name"]=="queries")
       queries=broadcastAccFunction<vector<query_t> >(pleaseGetQueryRing);
-    
+
     typedef map<query_t,unsigned int> counts_t;
     counts_t counts;
     unsigned int total=0;
     BOOST_FOREACH(const query_t& q, queries) {
       total++;
       if(filter)
-       counts[make_pair(getRegisteredName(toLower(q.first)), q.second)]++;
-      else 
-       counts[make_pair(toLower(q.first), q.second)]++;
+       counts[make_pair(getRegisteredName(q.first), q.second)]++;
+      else
+       counts[make_pair(q.first, q.second)]++;
     }
-    
+
     typedef std::multimap<int, query_t> rcounts_t;
     rcounts_t rcounts;
-  
+
     for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
       rcounts.insert(make_pair(-i->second, i->first));
 
@@ -500,11 +500,11 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
     unsigned int tot=0, totIncluded=0;
     BOOST_FOREACH(const rcounts_t::value_type& q, rcounts) {
       Value arr;
-      
+
       arr.SetArray();
       totIncluded-=q.first;
       arr.PushBack(-q.first, doc.GetAllocator());
-      arr.PushBack(q.second.first.c_str(), doc.GetAllocator());
+      arr.PushBack(q.second.first.toString().c_str(), doc.GetAllocator());
       arr.PushBack(DNSRecordContent::NumberToType(q.second.second).c_str(), doc.GetAllocator());
       entries.PushBack(arr, doc.GetAllocator());
       if(tot++>=100)
@@ -518,7 +518,7 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
       arr.PushBack("", doc.GetAllocator());
       entries.PushBack(arr, doc.GetAllocator());
     }
-    doc.AddMember("entries", entries, doc.GetAllocator());  
+    doc.AddMember("entries", entries, doc.GetAllocator());
     resp->setBody(doc);
     return;
   }
@@ -530,7 +530,7 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
       queries=broadcastAccFunction<vector<ComboAddress> >(pleaseGetServfailRemotes);
     else if(req->getvars["name"]=="large-answer-remotes")
       queries=broadcastAccFunction<vector<ComboAddress> >(pleaseGetLargeAnswerRemotes);
-    
+
     typedef map<ComboAddress,unsigned int,ComboAddress::addressOnlyLessThan> counts_t;
     counts_t counts;
     unsigned int total=0;
@@ -538,14 +538,14 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
       total++;
       counts[q]++;
     }
-    
+
     typedef std::multimap<int, ComboAddress> rcounts_t;
     rcounts_t rcounts;
-  
+
     for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
       rcounts.insert(make_pair(-i->second, i->first));
 
-    
+
     Document doc;
     doc.SetObject();
     Value entries;
@@ -554,10 +554,10 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
     BOOST_FOREACH(const rcounts_t::value_type& q, rcounts) {
       totIncluded-=q.first;
       Value arr;
-      
+
       arr.SetArray();
       arr.PushBack(-q.first, doc.GetAllocator());
-      Value jname(q.second.toString().c_str(), doc.GetAllocator()); // copy 
+      Value jname(q.second.toString().c_str(), doc.GetAllocator()); // copy
       arr.PushBack(jname, doc.GetAllocator());
       entries.PushBack(arr, doc.GetAllocator());
       if(tot++>=100)
@@ -571,7 +571,7 @@ void RecursorWebServer::jsonstat(HttpRequest* req, HttpResponse *resp)
       entries.PushBack(arr, doc.GetAllocator());
     }
 
-    doc.AddMember("entries", entries, doc.GetAllocator());  
+    doc.AddMember("entries", entries, doc.GetAllocator());
     resp->setBody(doc);
     return;
   } else {
@@ -611,7 +611,7 @@ void AsyncWebServer::serveConnection(Socket *client)
   YaHTTP::AsyncRequestLoader yarl;
   yarl.initialize(&req);
   client->setNonBlocking();
+
   string data;
   try {
     while(!req.complete) {