]> granicus.if.org Git - pdns/commitdiff
1) make everyting intrinsically case-insensitive
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 9 Apr 2006 17:09:34 +0000 (17:09 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 9 Apr 2006 17:09:34 +0000 (17:09 +0000)
2) clear up . oddness, removing all calls to toLowerCanonic

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@670 d19b8d6e-7fed-0310-83ef-9ca221ded41b

14 files changed:
pdns/dnsparser.cc
pdns/dnsrecords.cc
pdns/dnswriter.cc
pdns/dnswriter.hh
pdns/lwres.cc
pdns/misc.cc
pdns/misc.hh
pdns/mtasker.hh
pdns/pdns_recursor.cc
pdns/rcpgenerator.cc
pdns/recursor_cache.cc
pdns/recursor_cache.hh
pdns/syncres.cc
pdns/syncres.hh

index 08a367aeb19a26464254adf3cccd8431b94d14d0..840258cb3d8b252da489f7405516a78e61cf1fd5 100644 (file)
@@ -364,10 +364,10 @@ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t&
   for(;;) {
     unsigned char labellen=content.at(frompos++);
 
-    // cout<<"Labellen: "<<(int)labellen<<endl;
+    //    cerr<<"ret: '"<<ret<<"', Labellen: "<<(int)labellen<<endl;
     if(!labellen) {
-      //      if(ret.empty())
-      //       ret.append(1,'.');
+      if(ret.empty())
+       ret.append(1,'.');
       break;
     }
     if((labellen & 0xc0) == 0xc0) {
@@ -376,9 +376,8 @@ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t&
       return getLabelFromContent(content, offset, ret, ++recurs);
     }
     else {
-      if(!ret.empty())
-       ret.append(1,'.');
       ret.append(&content.at(frompos), &content.at(frompos+labellen));
+      ret.append(1,'.');
       frompos+=labellen;
     }
   }
index 7363a40ec32a569b62a111209a5d497cfe155752..13fb1cf996fa4148fd6cbc9fe434a89b4e76ec61 100644 (file)
@@ -28,7 +28,7 @@ uint32_t ARecordContent::getIP() const
 void ARecordContent::doRecordCheck(const DNSRecord& dr)
 {  
   if(dr.d_clen!=4)
-    throw MOADNSException("Wrong size for A record");
+    throw MOADNSException("Wrong size for A record ("+lexical_cast<string>(dr.d_clen)+")");
 }
 
 class AAAARecordContent : public DNSRecordContent
index 125ac7a12c1010e0d45106b1962b978721e78765..8bc378d75b85517bc58d0b477dddddb346d3f57c 100644 (file)
@@ -128,8 +128,9 @@ void DNSPacketWriter::xfrLabel(const string& label, bool compress)
   // d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
   unsigned int pos=d_content.size() + d_record.size() + d_stuff; 
   string chopped(label);
-  
+
   for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
+    //    cerr<<"chopped: '"<<chopped<<"'\n";
     map<string, uint16_t>::iterator li;
     // see if we've written out this domain before
     if(compress && (li=d_labelmap.find(chopped))!=d_labelmap.end()) {   
@@ -147,9 +148,9 @@ void DNSPacketWriter::xfrLabel(const string& label, bool compress)
     unsigned int len=d_record.size();
     d_record.resize(len + i->second - i->first);
     memcpy(((&*d_record.begin()) + len), label.c_str() + i-> first, i->second - i->first);
-
+    //    cerr<<"Added: '"<<string(label.c_str() + i->first, i->second - i->first) <<"'\n";
     pos+=(i->second - i->first)+1;
-    chopOff(chopped);                   // www.powerdns.com -> powerdns.com -> com 
+    chopOff(chopped);                   // www.powerdns.com. -> powerdns.com. -> com. -> .
   }
   d_record.push_back(0);
 
index a21f6092cba08c94bd03d8e0e2a220c4698c4463..d4f8796268756510d2a0184bc9a365f22a59c47a 100644 (file)
@@ -25,9 +25,9 @@ using namespace std;
 
     vector<uint8_t> content;
     DNSPacketWriter dpw(content, const string& qname, uint16_t qtype, uint16_t qclass=1);  // sets the question
-    dpw.startrecord("this.is.an.ip.address", ns_t_a);    // does nothing, except store qname and qtype
+    dpw.startrecord("this.is.an.ip.address.", ns_t_a);    // does nothing, except store qname and qtype
     dpw.xfr32BitInt(0x01020304);                         // adds 4 bytes (0x01020304) to the record buffer
-    dpw.startrecord("this.is.an.ip.address", ns_t_a);    // aha! writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer, which gets emptied
+    dpw.startrecord("this.is.an.ip.address.", ns_t_a);    // aha! writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer, which gets emptied
                                                          // new qname and qtype are stored
     dpw.xfr32BitInt(0x04030201);                         // adds 4 bytes (0x04030201) to the record buffer
     dpw.commit();                                        // writes out dnsrecord header containing qname and qtype and length 4, plus the recordbuffer
index 148d748d707043fc7a1dc04a115086111b6c69a4..25f7d8a16eae3f34bce66b7f24d079d1375247df 100644 (file)
@@ -152,7 +152,6 @@ LWRes::res_t LWRes::result()
       rr.qname=i->first.d_label;
       rr.ttl=i->first.d_ttl;
       rr.content=i->first.d_content->getZoneRepresentation();  // this should be the serialised form
-      
       rr.d_place=(DNSResourceRecord::Place) i->first.d_place;
       ret.push_back(rr);
     }
index f4d77cbf060f84009729d8edcbb60083b85646de..dd9ab4466e18b8f058003c949c0ab3534bc5433d 100644 (file)
@@ -91,7 +91,7 @@ bool stripDomainSuffix(string *qname, const string &domain)
   return true;
 }
 
-/** Chops off the start of a domain, so goes from 'www.ds9a.nl' to 'ds9a.nl' to ''. Return zero on the empty string */
+/** 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)
 {
   if(domain.empty())
@@ -106,6 +106,22 @@ bool chopOff(string &domain)
   return true;
 }
 
+/** 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 chopOffDotted(string &domain)
+{
+  if(domain.empty() || (domain.size()==1 && domain[0]=='.'))
+    return false;
+
+  string::size_type fdot=domain.find('.');
+
+  if(fdot==domain.size()-1) 
+    domain=".";
+  else 
+    domain=domain.substr(fdot+1);
+  return true;
+}
+
+
 bool ciEqual(const string& a, const string& b)
 {
   if(a.size()!=b.size())
@@ -123,10 +139,12 @@ 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++]!='.')
     return false;
 
@@ -137,6 +155,28 @@ bool endsOn(const string &domain, const string &suffix)
   return true;
 }
 
+/** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
+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++]!='.')
+    return false;
+
+  for(; dpos < domain.size(); ++dpos, ++spos)
+    if(dns_tolower(domain[dpos]) != dns_tolower(suffix[spos]))
+      return false;
+
+  return true;
+}
+
+
 int sendData(const char *buffer, int replen, int outsock)
 {
   uint16_t nlen=htons(replen);
index 5382486b3b0cccc1f82f13fd79801a3102c82a5a..f2d3dc718699957111ad8e18df153eca0e08eb97 100644 (file)
 
 using namespace std;
 bool chopOff(string &domain);
+bool chopOffDotted(string &domain);
+
 bool endsOn(const string &domain, const string &suffix);
+bool dottedEndsOn(const string &domain, const string &suffix);
 string nowTime();
 const string unquotify(const string &item);
 string humanDuration(time_t passed);
@@ -286,4 +289,12 @@ inline float makeFloat(const struct timeval& tv)
 {
   return tv.tv_sec + tv.tv_usec/1000000.0;
 }
+struct CIStringCompare: public binary_function<string, string, bool>  
+{
+  bool operator()(const string& a, const string& b) const
+  {
+    return strcasecmp(a.c_str(), b.c_str()) < 0;
+  }
+};
+
 #endif
index 339a95293a7a037699df09ede62e16fa7cdc66d9..c18b541915d1b718458295dd78ae6c9de4e1a7b6 100644 (file)
@@ -70,7 +70,7 @@ private:
 
   waiters_t d_waiters;
 
-  typedef std::map<int,ucontext_t* > mthreads_t;
+  typedef std::map<int, ucontext_t*> mthreads_t;
   mthreads_t d_threads;
   int d_tid;
   int d_maxtid;
index 03f97ae57dca8aa800e836ea1f6b12aa7a419d85..30897900252a4840b969b68a4a0ede8e3bef0d53 100644 (file)
@@ -226,7 +226,7 @@ void primeHints(void)
     
     for(char c='a';c<='m';++c) {
       static char templ[40];
-      strncpy(templ,"a.root-servers.net", sizeof(templ) - 1);
+      strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1);
       *templ=c;
       arr.qname=nsrr.content=templ;
       arr.content=ips[c-'a'];
@@ -255,7 +255,7 @@ void primeHints(void)
       }
     }
   }
-  RC.replace("", QType(QType::NS), nsset); // and stuff in the cache
+  RC.replace(".", QType(QType::NS), nsset); // and stuff in the cache
 }
 
 void startDoResolve(void *p)
@@ -591,7 +591,7 @@ static void houseKeeping(void *)
     vector<DNSResourceRecord> ret;
 
     sr.setNoCache();
-    int res=sr.beginResolve("", QType(QType::NS), ret);
+    int res=sr.beginResolve(".", QType(QType::NS), ret);
     if(!res) {
       L<<Logger::Error<<"Refreshed . records"<<endl;
       last_rootupdate=now.tv_sec;
index 91c39be2cae1f3d08fc77624b95376ef21461dc3..ae4bec536a614ee3ccb25bdd7bd8367ee99f727e 100644 (file)
@@ -305,7 +305,7 @@ void RecordTextWriter::xfrLabel(const string& val, bool)
       else
        d_string.append(1,val[pos]);
   }
-  d_string.append(1,'.');
+  //  d_string.append(1,'.');
 }
 
 void RecordTextWriter::xfrBlob(const string& val)
index c29a34c017e8bccd814c70889bf2371ba2d46265..28c682c84b34ce34534d80cbae4171c671472cd9 100644 (file)
@@ -35,13 +35,14 @@ namespace __gnu_cxx
 
 DNSResourceRecord String2DNSRR(const string& qname, const QType& qt, const string& serial, uint32_t ttd)
 {
+  //  cerr<<"Serial: '"<<makeHexDump(serial)<<"'"<<endl;
   shared_ptr<DNSRecordContent> regen=DNSRecordContent::unserialize(qname,qt.getCode(), serial);
   DNSResourceRecord rr;
   rr.qname=regen->label;
   rr.ttl=ttd; 
   rr.content=regen->getZoneRepresentation();
   rr.qtype=regen->d_qtype;
-  //  cerr<<"Returning: '"<<rr.qname<<"' "<<rr.qtype.getName()<<"  "<<rr.ttl<<"  '"<<rr.content<<"'\n";
+
   rr.content.reserve(0);
   rr.qname.reserve(0);
   return rr;
@@ -79,14 +80,13 @@ unsigned int MemRecursorCache::bytes()
 int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res)
 {
   unsigned int ttd=0;
-  string lqname(toLowerCanonic(qname));
 
-  //  cerr<<"looking up "<< toLowerCanonic(qname)+"|"+qt.getName()<<"\n";
+  //  cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n";
 
-  if(!d_cachecachevalid || d_cachedqname != lqname) {
+  if(!d_cachecachevalid || strcasecmp(d_cachedqname.c_str(), qname.c_str())) {
     //    cerr<<"had cache cache miss"<<endl;
-    d_cachedqname=lqname;
-    d_cachecache=d_cache.equal_range(tie(lqname));
+    d_cachedqname=qname;
+    d_cachecache=d_cache.equal_range(tie(qname));
     d_cachecachevalid=true;
   }
   else
@@ -122,7 +122,6 @@ int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<
     //    cerr<<"time left : "<<ttd - now<<", "<< (res ? res->size() : 0) <<"\n";
     return (unsigned int)ttd-now;
   }
-  
   return -1;
 }
  
@@ -132,10 +131,10 @@ int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<
 void MemRecursorCache::replace(const string &qname, const QType& qt,  const set<DNSResourceRecord>& content)
 {
   d_cachecachevalid=false;
-  tuple<string, uint16_t> key=make_tuple(toLowerCanonic(qname), qt.getCode());
+  tuple<string, uint16_t> key=make_tuple(qname, qt.getCode());
   cache_t::iterator stored=d_cache.find(key);
 
-  //  cerr<<"storing "<< toLowerCanonic(qname)+"|"+qt.getName()<<"\n";
+  //  cerr<<"storing "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"'\n";
 
   bool isNew=false;
   if(stored == d_cache.end()) {
@@ -204,7 +203,7 @@ void MemRecursorCache::doDumpAndClose(int fd)
   for(sequence_t::const_iterator i=sidx.begin(); i != sidx.end(); ++i) {
     for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j != i->d_records.end(); ++j) {
       DNSResourceRecord rr=String2DNSRR(i->d_qname, QType(i->d_qtype), j->d_string, j->d_ttd - now);
-      fprintf(fp, "%s. %d IN %s %s\n", rr.qname.c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
+      fprintf(fp, "%s %d IN %s %s\n", rr.qname.c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
     }
   }
   fclose(fp);
index c7d34d432d7446f78c462e1adc8e2c7928cfa445..96bdb1cb5f7a309473de100fd845f541d216959c 100644 (file)
@@ -4,6 +4,7 @@
 #include <set>
 #include "dns.hh"
 #include "qtype.hh"
+#include "misc.hh"
 #include <iostream>
 #include <boost/utility.hpp>
 #undef L
@@ -22,6 +23,7 @@ using namespace boost;
 using namespace ::boost::multi_index;
 
 
+
 class MemRecursorCache : public boost::noncopyable //  : public RecursorCache
 {
 public:
@@ -102,7 +104,8 @@ private:
                         CacheEntry,
                         member<CacheEntry,string,&CacheEntry::d_qname>,
                         member<CacheEntry,uint16_t,&CacheEntry::d_qtype>
-                      >
+                      >,
+                      composite_key_compare<CIStringCompare, std::less<uint16_t> >
                 >,
                sequenced<>
                >
index 66c86c8298b4e517085d0a26bfcf0181c816a0a5..7bcf4aa3d509e3f923877bc489b5e2bf34fb0964 100644 (file)
@@ -87,7 +87,7 @@ int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResour
 
   string subdomain(qname);
 
-  set<string> nsset;
+  set<string, CIStringCompare> nsset;
   for(int tries=0;tries<2 && nsset.empty();++tries) {
     subdomain=getBestNSNamesFromCache(subdomain,nsset,depth, beenthere); //  pass beenthere to both occasions
 
@@ -136,20 +136,19 @@ void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bes
 
   do {
     LOG<<prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl;
-    set<DNSResourceRecord>ns;
-    if(RC.get(d_now.tv_sec, subdomain, QType(QType::NS), &ns)>0) {
-
+    set<DNSResourceRecord> ns;
+    if(RC.get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
       for(set<DNSResourceRecord>::const_iterator k=ns.begin();k!=ns.end();++k) {
        if(k->ttl > (unsigned int)d_now.tv_sec ) { 
          set<DNSResourceRecord>aset;
 
          DNSResourceRecord rr=*k;
-         rr.content=toLowerCanonic(k->content);
-         if(!endsOn(rr.content,subdomain) || RC.get(d_now.tv_sec, rr.content ,QType(QType::A),&aset) > 5) {
+         rr.content=k->content;
+         if(!dottedEndsOn(rr.content,subdomain) || RC.get(d_now.tv_sec, rr.content ,QType(QType::A),&aset) > 5) {
            bestns.insert(rr);
            
            LOG<<prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<rr.content<<"'"<<endl;
-           LOG<<prefix<<qname<<": within bailiwick: "<<endsOn(rr.content,subdomain);
+           LOG<<prefix<<qname<<": within bailiwick: "<<dottedEndsOn(rr.content, subdomain);
            if(!aset.empty()) {
              LOG<<", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl;
            }
@@ -158,12 +157,12 @@ void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bes
            }
          }
          else
-           LOG<<prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<toLowerCanonic(k->content)<<") which we miss or is expired"<<endl;
+           LOG<<prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl;
        }
       }
       if(!bestns.empty()) {
        GetBestNSAnswer answer;
-       answer.qname=toLower(qname); answer.bestns=bestns;
+       answer.qname=qname; answer.bestns=bestns;
        if(beenthere.count(answer)) {
          LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP! Trying less specific NS"<<endl;
          for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j)
@@ -177,12 +176,12 @@ void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bes
        }
       }
     }
-  }while(chopOff(subdomain));
+  }while(chopOffDotted(subdomain));
 }
 
 
 /** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname,set<string>& nsset, int depth, set<GetBestNSAnswer>&beenthere)
+string SyncRes::getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, int depth, set<GetBestNSAnswer>&beenthere)
 {
   string subdomain(qname);
 
@@ -210,19 +209,19 @@ bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<
     return true;
   }
   
-  LOG<<prefix<<qname<<": Looking for CNAME cache hit of '"<<(toLowerCanonic(qname)+"|CNAME")<<"'"<<endl;
+  LOG<<prefix<<qname<<": Looking for CNAME cache hit of '"<<(qname+"|CNAME")<<"'"<<endl;
   set<DNSResourceRecord> cset;
   if(RC.get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) {
 
     for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
       if(j->ttl>(unsigned int) d_now.tv_sec) {
-       LOG<<prefix<<qname<<": Found cache CNAME hit for '"<< (toLowerCanonic(qname)+"|CNAME") <<"' to '"<<j->content<<"'"<<endl;    
+       LOG<<prefix<<qname<<": Found cache CNAME hit for '"<< (qname+"|CNAME") <<"' to '"<<j->content<<"'"<<endl;    
        DNSResourceRecord rr=*j;
        rr.ttl-=d_now.tv_sec;
        ret.push_back(rr);
        if(!(qtype==QType(QType::CNAME))) { // perhaps they really wanted a CNAME!
          set<GetBestNSAnswer>beenthere;
-         res=doResolve(toLowerCanonic(j->content), qtype, ret, depth+1, beenthere);
+         res=doResolve(j->content, qtype, ret, depth+1, beenthere);
        }
        else
          res=0;
@@ -230,7 +229,7 @@ bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<
       }
     }
   }
-  LOG<<prefix<<qname<<": No CNAME cache hit of '"<< (toLowerCanonic(qname)+"|CNAME") <<"' found"<<endl;
+  LOG<<prefix<<qname<<": No CNAME cache hit of '"<< (qname+"|CNAME") <<"' found"<<endl;
   return false;
 }
 
@@ -249,7 +248,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
   uint32_t sttl=0;
   //  cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"'\n";
 
-  pair<negcache_t::const_iterator, negcache_t::const_iterator> range=s_negcache.equal_range(tie(toLower(qname)));
+  pair<negcache_t::const_iterator, negcache_t::const_iterator> range=s_negcache.equal_range(tie(qname));
   negcache_t::iterator ni;
   for(ni=range.first; ni != range.second; ni++) {
     // we have something
@@ -262,7 +261,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
          res = RCode::NoError;
        }
        else {
-         LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"', is negatively cached for another "<<sttl<<" seconds"<<endl;
+         LOG<<prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached for another "<<sttl<<" seconds"<<endl;
          res= RCode::NXDomain; 
        }
        giveNegative=true;
@@ -271,7 +270,7 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
        break;
       }
       else {
-       LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"' was negatively cached, but entry expired"<<endl;
+       LOG<<prefix<<qname<<": Entire record '"<<qname<<"' was negatively cached, but entry expired"<<endl;
       }
     }
   }
@@ -314,7 +313,8 @@ bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSRe
 
 bool SyncRes::moreSpecificThan(const string& a, const string &b)
 {
-  int counta=!a.empty(), countb=!b.empty();
+  static string dot(".");
+  int counta=(a!=dot), countb=(b!=dot);
   
   for(string::size_type n=0;n<a.size();++n)
     if(a[n]=='.')
@@ -325,8 +325,6 @@ bool SyncRes::moreSpecificThan(const string& a, const string &b)
   return counta>countb;
 }
 
-
-
 struct speedOrder
 {
   speedOrder(map<string,double> &speeds) : d_speeds(speeds) {}
@@ -337,15 +335,15 @@ struct speedOrder
   map<string,double>& d_speeds;
 };
 
-inline vector<string> SyncRes::shuffle(set<string> &nameservers, const string &prefix)
+inline vector<string> SyncRes::shuffle(set<string, CIStringCompare> &nameservers, const string &prefix)
 {
   vector<string> rnameservers;
   rnameservers.reserve(nameservers.size());
   map<string,double> speeds;
 
-  for(set<string>::const_iterator i=nameservers.begin();i!=nameservers.end();++i) {
+  for(set<string, CIStringCompare>::const_iterator i=nameservers.begin();i!=nameservers.end();++i) {
     rnameservers.push_back(*i);
-    DecayingEwma& temp=s_nsSpeeds[toLower(*i)];
+    DecayingEwma& temp=s_nsSpeeds[*i];
     speeds[*i]=temp.get(&d_now);
   }
   random_shuffle(rnameservers.begin(),rnameservers.end());
@@ -366,8 +364,24 @@ inline vector<string> SyncRes::shuffle(set<string> &nameservers, const string &p
   return rnameservers;
 }
 
+struct TCacheComp
+{
+  bool operator()(const pair<string, QType>& a, const pair<string, QType>& b) const
+  {
+    int cmp=strcasecmp(a.first.c_str(), b.first.c_str());
+    if(cmp < 0)
+      return true;
+    if(cmp > 0)
+      return false;
+
+    return a.second < b.second;
+  }
+};
+
+
+
 /** returns -1 in case of no results, rcode otherwise */
-int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, 
+int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, 
                int depth, set<GetBestNSAnswer>&beenthere)
 {
   string prefix;
@@ -431,7 +445,7 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
            else
              LOG<<prefix<<qname<<": error resolving"<<endl;
            
-           s_nsSpeeds[toLower(*tns)].submit(1000000, &d_now); // 1 sec
+           s_nsSpeeds[*tns].submit(1000000, &d_now); // 1 sec
          
            s_throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()),20,5);
            continue;
@@ -462,16 +476,16 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
        continue;
       }
       LOG<<prefix<<qname<<": Got "<<result.size()<<" answers from "<<*tns<<" ("<<U32ToIP(*remoteIP)<<"), rcode="<<d_lwr.d_rcode<<", in "<<d_lwr.d_usec/1000<<"ms"<<endl;
-      s_nsSpeeds[toLower(*tns)].submit(d_lwr.d_usec, &d_now);
+      s_nsSpeeds[*tns].submit(d_lwr.d_usec, &d_now);
 
-      typedef map<pair<string, QType> ,set<DNSResourceRecord> > tcache_t;
+      typedef map<pair<string, QType>, set<DNSResourceRecord>, TCacheComp > tcache_t;
       tcache_t tcache;
 
       // reap all answers from this packet that are acceptable
       for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) {
        LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ";
        
-       if(endsOn(i->qname, auth)) {
+       if(dottedEndsOn(i->qname, auth)) {
          if(d_lwr.d_aabit && d_lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth)) {
            LOG<<"NO! Is from delegation-only zone"<<endl;
            s_nodelegated++;
@@ -484,8 +498,8 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
            rr.d_place=DNSResourceRecord::ANSWER;
            rr.ttl+=d_now.tv_sec;
            if(rr.qtype.getCode() == QType::NS) // people fiddle with the case
-             rr.content=toLower(rr.content);
-           tcache[make_pair(toLower(i->qname),i->qtype)].insert(rr);
+             rr.content=toLower(rr.content); // this must stay!
+           tcache[make_pair(i->qname,i->qtype)].insert(rr);
          }
        }         
        else
@@ -496,30 +510,30 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
       for(tcache_t::const_iterator i=tcache.begin();i!=tcache.end();++i) {
        RC.replace(i->first.first, i->first.second, i->second);
       }
-      set<string> nsset;  
+      set<string, CIStringCompare> nsset;  
       LOG<<prefix<<qname<<": determining status after receiving this packet"<<endl;
 
       bool done=false, realreferral=false, negindic=false;
       string newauth, soaname, newtarget;
 
       for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) {
-       if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
+       if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
           d_lwr.d_rcode==RCode::NXDomain) {
-         LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<toLower(qname)+"'"<<endl;
+         LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"'"<<endl;
          ret.push_back(*i);
 
          NegCacheEntry ne;
 
          ne.d_qname=i->qname;
          ne.d_ttd=d_now.tv_sec + min(i->ttl, 3600U); // controversial
-         ne.d_name=toLower(qname);
+         ne.d_name=qname;
          ne.d_qtype=QType(0);
          s_negcache.insert(ne);
          negindic=true;
        }
        else if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
          ret.push_back(*i);
-         newtarget=toLowerCanonic(i->content);
+         newtarget=i->content;
        }
        // for ANY answers we *must* have an authoritive answer
        else if(i->d_place==DNSResourceRecord::ANSWER && !strcasecmp(i->qname.c_str(),qname.c_str()) && 
@@ -532,7 +546,7 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
          done=true;
          ret.push_back(*i);
        }
-       else if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { 
+       else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { 
          if(moreSpecificThan(i->qname,auth)) {
            newauth=i->qname;
            LOG<<prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl;
@@ -540,17 +554,17 @@ int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qna
          }
          else 
            LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl;
-         nsset.insert(toLowerCanonic(i->content));
+         nsset.insert(i->content);
        }
-       else if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
+       else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
           d_lwr.d_rcode==RCode::NoError) {
-         LOG<<prefix<<qname<<": got negative caching indication for '"<<toLower(qname)+"|"+i->qtype.getName()+"'"<<endl;
+         LOG<<prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+i->qtype.getName()+"'") <<endl;
          ret.push_back(*i);
          
          NegCacheEntry ne;
          ne.d_qname=i->qname;
          ne.d_ttd=d_now.tv_sec + min(3600U,i->ttl);
-         ne.d_name=toLower(qname);
+         ne.d_name=qname;
          ne.d_qtype=qtype;
          if(qtype.getCode())   // prevents us from blacking out a whole domain
            s_negcache.insert(ne);
@@ -614,14 +628,14 @@ void SyncRes::addCruft(const string &qname, vector<DNSResourceRecord>& ret)
       if(k->qtype==QType(QType::MX)) {
        string::size_type pos=k->content.find_first_not_of(" \t0123456789"); // chop off the priority
        if(pos!=string::npos) {
-         doResolve(toLowerCanonic(k->content.substr(pos)), QType(QType::A),addit,1,beenthere);
+         doResolve(k->content.substr(pos), QType(QType::A),addit,1,beenthere);
          if(*l_doIPv6AP)
-           doResolve(toLowerCanonic(k->content.substr(pos)), QType(QType::AAAA),addit,1,beenthere);
+           doResolve(k->content.substr(pos), QType(QType::AAAA),addit,1,beenthere);
        }
        else {
-         doResolve(toLowerCanonic(k->content), QType(QType::A),addit,1,beenthere);
+         doResolve(k->content, QType(QType::A),addit,1,beenthere);
          if(*l_doIPv6AP)
-           doResolve(toLowerCanonic(k->content.substr(pos)), QType(QType::AAAA),addit,1,beenthere);
+           doResolve(k->content.substr(pos), QType(QType::AAAA),addit,1,beenthere);
        }
       }
       else {
index c060648e896409901a0ad88f994ce2354983d2b2..2a6fbea84a87297f8980bebe2290d52979355c16 100644 (file)
@@ -252,7 +252,8 @@ public:
                  NegCacheEntry,
                     member<NegCacheEntry, string, &NegCacheEntry::d_name>,
                     member<NegCacheEntry, QType, &NegCacheEntry::d_qtype>
-           >
+           >,
+           composite_key_compare<CIStringCompare, std::less<QType> >
        >,
        ordered_non_unique<
            member<NegCacheEntry, uint32_t, &NegCacheEntry::d_ttd>
@@ -261,7 +262,7 @@ public:
   >negcache_t;
   static negcache_t s_negcache;    
 
-  typedef map<string,DecayingEwma> nsspeeds_t;
+  typedef map<string,DecayingEwma, CIStringCompare> nsspeeds_t;
   static nsspeeds_t s_nsSpeeds;
 
   typedef Throttle<tuple<uint32_t,string,uint16_t> > throttle_t;
@@ -269,17 +270,17 @@ public:
   struct timeval d_now;
 private:
   struct GetBestNSAnswer;
-  int doResolveAt(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
+  int doResolveAt(set<string, CIStringCompare> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
                  int depth, set<GetBestNSAnswer>&beenthere);
   int doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
   bool doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
   bool doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
   void getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, int depth, set<GetBestNSAnswer>& beenthere);
   void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
-  string getBestNSNamesFromCache(const string &qname,set<string>& nsset, int depth, set<GetBestNSAnswer>&beenthere);
+  string getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, int depth, set<GetBestNSAnswer>&beenthere);
   void addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth);
 
-  inline vector<string> shuffle(set<string> &nameservers, const string &prefix);
+  inline vector<string> shuffle(set<string, CIStringCompare> &nameservers, const string &prefix);
   bool moreSpecificThan(const string& a, const string &b);
   vector<uint32_t> getAs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);