]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge remote-tracking branch 'main/master' into ednssurg
authorbert hubert <bert.hubert@powerdns.com>
Thu, 24 Sep 2015 14:49:23 +0000 (16:49 +0200)
committerbert hubert <bert.hubert@powerdns.com>
Thu, 24 Sep 2015 14:49:23 +0000 (16:49 +0200)
Conflicts:
pdns/recursor_cache.cc
pdns/recursor_cache.hh
pdns/syncres.cc
pdns/syncres.hh

1  2 
pdns/dnsparser.cc
pdns/lwres.cc
pdns/lwres.hh
pdns/pdns_recursor.cc
pdns/recursor_cache.cc
pdns/recursor_cache.hh
pdns/reczones.cc
pdns/secpoll-recursor.cc
pdns/syncres.cc
pdns/syncres.hh

Simple merge
diff --cc pdns/lwres.cc
Simple merge
diff --cc pdns/lwres.hh
index 23edb17c30b6516edab3897abca766b4e5d01b0d,afcc53a5baeeb88160b72a4e165430eb0b8542fe..82bb0050ad7d51a6f5c6a5b468aebbd274d9cb20
@@@ -65,11 -63,10 +65,11 @@@ public
    int d_rcode;
    bool d_aabit, d_tcbit;
    uint32_t d_usec;
 -  bool d_pingCorrect;
    bool d_haveEDNS;
 +
 +  vector<DNSResourceRecord> d_result;
  };
  
- int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
+ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
  
  #endif // PDNS_LWRES_HH
Simple merge
index 37a1bceaa5d2f80b1506c992df8af912b2144c89,71c45fb789b567f8b99e614db226745fceb0c315..a15df95c768b0f925c9bd25f989c2c054f2ca620
@@@ -107,7 -107,7 +107,7 @@@ unsigned int MemRecursorCache::bytes(
    return ret;
  }
  
- int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures)
 -int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res)
++int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures)
  {
    unsigned int ttd=0;
    //  cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n";
@@@ -188,10 -186,10 +188,10 @@@ bool MemRecursorCache::attemptToRefresh
  /* the code below is rather tricky - it basically replaces the stuff cached for qname by content, but it is special
     cased for when inserting identical records with only differing ttls, in which case the entry is not
     touched, but only given a new ttd */
- void MemRecursorCache::replace(time_t now, const string &qname, const QType& qt,  const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
 -void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth)
++void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
  {
    d_cachecachevalid=false;
-   boost::tuple<string, uint16_t> key=boost::make_tuple(qname, qt.getCode());
+   boost::tuple<DNSName, uint16_t> key=boost::make_tuple(qname, qt.getCode());
    cache_t::iterator stored=d_cache.find(key);
    uint32_t maxTTD=UINT_MAX;
  
index de92b702dcba2333712916fa18e20fdd60654225,c316ca5cdde4f5f56ea08daecc6f8c1f5475ef77..4e21bac02f72e2585cc40ecb75045193b83308c0
@@@ -5,8 -5,9 +5,9 @@@
  #include "dns.hh"
  #include "qtype.hh"
  #include "misc.hh"
+ #include "dnsname.hh"
  #include <iostream>
 -
 +#include "dnsrecords.hh"
  #include <boost/utility.hpp>
  #undef L
  #include <boost/multi_index_container.hpp>
@@@ -31,10 -32,10 +32,10 @@@ public
    }
    unsigned int size();
    unsigned int bytes();
-   int get(time_t, const string &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=0);
 -  int get(time_t, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res);
++  int get(time_t, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=0);
  
    int getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10]);
-   void replace(time_t, const string &qname, const QType& qt,  const set<DNSResourceRecord>& content, const vector<std::shared_ptr<RRSIGRecordContent>>& signatures, bool auth);
 -  void replace(time_t, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, bool auth);
++  void replace(time_t, const DNSName &qname, const QType& qt,  const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth);
    void doPrune(void);
    void doSlash(int perc);
    uint64_t doDump(int fd);
index b38ea35f131797dc1b76e4da157026bd1f3159e8,03f6c4842c602d17f297e814bef0b7281433a042..f73eb8557aebe6d68ce03a74f7f4021f22bceb96
@@@ -96,10 -96,10 +96,10 @@@ void primeHints(void
        }
      }
    }
 -  t_RC->replace(time(0),".", QType(QType::NS), nsset, true); // and stuff in the cache (auth)
 +  t_RC->replace(time(0),".", QType(QType::NS), nsset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // and stuff in the cache (auth)
  }
  
- static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const string& hostname, const string& ip)
+ static void makeNameToIPZone(SyncRes::domainmap_t* newMap, const DNSName& hostname, const string& ip)
  {
    SyncRes::AuthDomain ad;
    ad.d_rdForward=false;
Simple merge
diff --cc pdns/syncres.cc
index 86ae430934c3570ed28961526c2af1895727d668,acaab1ba71d24c1aa807a86fd90141a80e195bd9..1d8ac40eb087db36d81c28948ece4fb46a68f038
@@@ -1,9 -1,9 +1,9 @@@
  /*
      PowerDNS Versatile Database Driven Nameserver
--    Copyright (C) 2003 - 2014  PowerDNS.COM BV
++    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 as published 
+     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
@@@ -250,32 -251,45 +250,32 @@@ void SyncRes::doEDNSDumpAndClose(int fd
    fclose(fp);
  }
  
- int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res) 
+ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res)
  {
    /* what is your QUEST?
 -     the goal is to get as many remotes as possible on the highest level of hipness: EDNS PING responders.
 +     the goal is to get as many remotes as possible on the highest level of EDNS support
       The levels are:
  
 -     -1) CONFIRMEDPINGER: Confirmed pinger!
 -     0) UNKNOWN Unknown state
 -     1) EDNSNOPING: Honors EDNS0 if no PING is included
 -     2) EDNSPINGOK: Ignores EDNS0+PING, but does generate EDNS0 response
 -     3) EDNSIGNORANT: Ignores EDNS0+PING, gives replies without EDNS0 nor PING
 -     4) NOEDNS: Generates FORMERR on EDNS queries
 +     0) UNKNOWN Unknown state 
 +     1) EDNS: Honors EDNS0
 +     2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
 +     3) NOEDNS: Generates FORMERR on EDNS queries
  
       Everybody starts out assumed to be '0'.
 -     If '-1', send out EDNS0+Ping
 -        If we get a FormErr, ignore
 -        If we get a incorrect PING, ignore
 -        If we get no PING, ignore
 -     If '0', send out EDNS0+Ping
 -        If we get a pure EDNS response, you are downgraded to '2'.
 -        If you FORMERR us, go to '1',
 -        If no EDNS in response, go to '3' - 3 and 0 are really identical, except confirmed
 -        If with correct PING, upgrade to -1
 -     If '1', send out EDNS0, no PING
 -        If FORMERR, downgrade to 4
 -     If '2', keep on including EDNS0+PING, just don't expect PING to be correct
 -        If PING correct, move to '0', and cheer in the log file!
 -     If '3', keep on including EDNS0+PING, see what happens
 -        Same behaviour as 0
 -     If '4', send bare queries
 +     If '0', send out EDNS0
 +        If you FORMERR us, go to '3', 
 +        If no EDNS in response, go to '2'
 +     If '1', send out EDNS0
 +        If FORMERR, downgrade to 3
 +     If '2', keep on including EDNS0, see what happens
 +        Same behaviour as 0 
 +     If '3', send bare queries
    */
  
 -  if(s_noEDNS) {
 -    g_stats.noEdnsOutQueries++;
 -    return asyncresolve(ip, domain, type, doTCP, sendRDQuery, 0, now, res);
 -  }
 -
 +  g_stats.noEdnsOutQueries++;
 +  
    SyncRes::EDNSStatus* ednsstatus;
 -  ednsstatus = &t_sstorage->ednsstatus[ip];
 +  ednsstatus = &t_sstorage->ednsstatus[ip]; // does this include port? 
  
    if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
      *ednsstatus=SyncRes::EDNSStatus();
@@@ -353,12 -409,12 +353,12 @@@ int SyncRes::doResolve(const DNSName &q
          }
          else {
            const ComboAddress remoteIP = servers.front();
-           LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
+           LOG(prefix<<qname.toString()<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname.toString()<<"'"<<endl);
  
-           res=asyncresolveWrapper(remoteIP, qname, qtype.getCode(), false, false, &d_now, &lwr);    
+           res=asyncresolveWrapper(remoteIP, qname, qtype.getCode(), false, false, &d_now, &lwr);
            // filter out the good stuff from lwr.result()
  
 -          for(LWResult::res_t::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) {
 +          for(LWResult::res_t::const_iterator i=lwr.getResult().begin();i!=lwr.getResult().end();++i) {
              if(i->d_place == DNSResourceRecord::ANSWER)
                ret.push_back(*i);
            }
@@@ -701,10 -752,9 +696,10 @@@ bool SyncRes::doCacheCheck(const DNSNam
    }
    set<DNSResourceRecord> cset;
    bool found=false, expired=false;
 -
 -  if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset) > 0) {
 +  vector<std::shared_ptr<RRSIGRecordContent>> signatures;
 +  uint32_t ttl=0;
 +  if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_doDNSSEC ? &signatures : 0) > 0) {
-     LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
+     LOG(prefix<<sqname.toString()<<": Found cache hit for "<<sqt.getName()<<": ");
      for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
        LOG(j->content);
        if(j->ttl>(unsigned int) d_now.tv_sec) {
@@@ -1007,14 -1032,14 +988,13 @@@ int SyncRes::doResolveAt(set<DNSName> n
          if(lwr.d_tcbit) {
            if(!doTCP) {
              doTCP=true;
-             LOG(prefix<<qname<<": truncated bit set, retrying via TCP"<<endl);
+             LOG(prefix<<qname.toString()<<": truncated bit set, retrying via TCP"<<endl);
              goto TryTCP;
            }
-           LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
+           LOG(prefix<<qname.toString()<<": truncated bit set, over TCP?"<<endl);
            return RCode::ServFail;
          }
-         
-         LOG(prefix<<qname<<": Got "<<(unsigned int)lwr.getResult().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)
        }
        }
  
 -      typedef map<pair<DNSName, QType>, set<DNSResourceRecord>, TCacheComp > tcache_t;
 +      struct CachePair
 +      {
 +      set<DNSResourceRecord> records;
 +      vector<shared_ptr<RRSIGRecordContent>> signatures;
 +      };
-       typedef map<pair<string, QType>, CachePair, TCacheComp > tcache_t;
++      typedef map<pair<DNSName, QType>, CachePair, TCacheComp > tcache_t;
        tcache_t tcache;
  
-           cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<stripDot(rec.first.d_label)<<"'"<<endl;
 +      if(d_doDNSSEC) {
 +      for(const auto& rec : lwr.d_records) {
 +        if(rec.first.d_type == QType::RRSIG) {
 +          auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rec.first.d_content);
++          cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.first.d_label.toString()<<"'"<<endl;
 +          tcache[make_pair(rec.first.d_label, QType(rrsig->d_type))].signatures.push_back(rrsig);
 +        }
 +      }
 +      }
 +
        // reap all answers from this packet that are acceptable
 -      for(LWResult::res_t::iterator i=lwr.d_result.begin();i != lwr.d_result.end();++i) {
 +      for(LWResult::res_t::iterator i=lwr.getResult().begin();i != lwr.getResult().end();++i) {
          if(i->qtype.getCode() == QType::OPT) {
-           LOG(prefix<<qname<<": skipping OPT answer '"<<i->qname<<"' from '"<<auth<<"' nameservers" <<endl);
+           LOG(prefix<<qname.toString()<<": skipping OPT answer '"<<i->qname.toString()<<"' from '"<<auth.toString()<<"' nameservers" <<endl);
            continue;
          }
-         LOG(prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ");
+         LOG(prefix<<qname.toString()<<": accept answer '"<<i->qname.toString()<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth.toString()<<"' nameservers? ");
          if(i->qtype.getCode()==QType::ANY) {
            LOG("NO! - we don't accept 'ANY' data"<<endl);
            continue;
  
              if(rr.qtype.getCode() == QType::NS) // people fiddle with the case
                rr.content=toLower(rr.content); // this must stay! (the cache can't be case-insensitive on the RHS of records)
-             
 -
 -            tcache[make_pair(i->qname,i->qtype)].insert(rr);
 +            tcache[make_pair(i->qname,i->qtype)].records.insert(rr);
            }
-         }          
+         }
          else
            LOG("NO!"<<endl);
        }
-     
        // supplant
        for(tcache_t::iterator i=tcache.begin();i!=tcache.end();++i) {
 -        if(i->second.size() > 1) {  // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
 +        if(i->second.records.size() > 1) {  // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
            uint32_t lowestTTL=std::numeric_limits<uint32_t>::max();
 -          for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j)
 -            lowestTTL=min(lowestTTL, j->ttl);
 -
 -          for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j)
 -            ((tcache_t::value_type::second_type::value_type*)&(*j))->ttl=lowestTTL;
 +        for(auto& record : i->second.records) 
 +            lowestTTL=min(lowestTTL, record.ttl);
 +          
 +        for(auto& record : i->second.records) 
 +          *const_cast<uint32_t*>(&record.ttl)=lowestTTL;
          }
  
-       cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first;
 -        t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit);
++      cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first.toString();
 +      cout<<'|'<<DNSRecordContent::NumberToType(i->first.second.getCode())<<endl;
 +        t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second.records, i->second.signatures, lwr.d_aabit);
        }
-       set<string, CIStringCompare> nsset;  
-       LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
+       set<DNSName> nsset;
+       LOG(prefix<<qname.toString()<<": determining status after receiving this packet"<<endl);
  
 -      bool done=false, realreferral=false, negindic=false;
 -      DNSName newauth, newtarget;
 +      bool done=false, realreferral=false, negindic=false, sawDS=false;
-       string newauth, soaname, newtarget;
++      DNSName newauth, soaname;
++      DNSName newtarget;
  
 -      for(LWResult::res_t::iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) {
 -        if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::SOA &&
 +      for(LWResult::res_t::iterator i=lwr.getResult().begin();i!=lwr.getResult().end();++i) {
 +        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<<": got negative caching indication for RECORD '"<<qname+"' (accept="<<dottedEndsOn(i->qname, auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
-           
+           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);
            ret.push_back(*i);
            newtarget=i->content;
          }
 +      else if(d_doDNSSEC && (i->qtype==QType::RRSIG || i->qtype==QType::NSEC || i->qtype==QType::NSEC3) && i->d_place==DNSResourceRecord::ANSWER){
 +        ret.push_back(*i); // enjoy your DNSSEC
 +      }
          // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
-         else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && 
+         else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) &&
                  (
                   i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) ) || sendRDQuery
-                 ) 
-                )   
+                 )
+                )
            {
-           
-           LOG(prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
+           LOG(prefix<<qname.toString()<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
  
            done=true;
            ret.push_back(*i);
          }
-         else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { 
+         else if(i->d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(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);
+             LOG(prefix<<qname.toString()<<": got NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
              realreferral=true;
            }
-           else 
-             LOG(prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl);
+           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 &&
 +        else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::DS) { 
-         LOG(prefix<<qname<<": got DS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl);
++        LOG(prefix<<qname.toString()<<": got DS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
 +        sawDS=true;
 +      }
 +        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<<": got negative caching indication for '"<< (qname+"|"+qtype.getName()+"'") <<endl);
-           
+           LOG(prefix<<qname.toString()<<": got negative caching indication for '"<< (qname.toString()+"|"+qtype.getName()+"'") <<endl);
            if(!newtarget.empty()) {
-             LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
+             LOG(prefix<<qname.toString()<<": Hang on! Got a redirect to '"<<newtarget.toString()<<"' already"<<endl);
            }
            else {
              i-> ttl = min(s_maxnegttl, i->ttl);
          return 0;
        }
        else if(realreferral) {
-         LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl);
+         LOG(prefix<<qname.toString()<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl);
 +      if(sawDS) {
 +        t_sstorage->dnssecmap[newauth]=true;
 +        for(const auto& e : t_sstorage->dnssecmap)
-           cout<<e.first<<' ';
++          cout<<e.first.toString()<<' ';
 +        cout<<endl;
 +      }
          auth=newauth;
          nameservers=nsset;
-         break; 
+         break;
        }
        else if(isCanonical(*tns)) { // means: not OOB (I think)
          goto wasLame;
diff --cc pdns/syncres.hh
index 403f3ed15c1b512150597a813ca2a046c84d6071,92b3d8e6bcf7a20559da0895a4aa10e3426769ba..eb1dcc16a82e62ef3cf136faf0d7e45bf0521380
@@@ -434,7 -434,6 +434,7 @@@ public
      throttle_t throttle;
      fails_t fails;
      domainmap_t* domainmap;
-     map<string,bool> dnssecmap;
++    map<DNSName, bool> dnssecmap;
    };
  
  private: