From: bert hubert Date: Thu, 24 Sep 2015 14:49:23 +0000 (+0200) Subject: Merge remote-tracking branch 'main/master' into ednssurg X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~28^2~27^2~8 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e2e4419628db6bcb0428a07bd268abd035a1c7d;p=pdns Merge remote-tracking branch 'main/master' into ednssurg Conflicts: pdns/recursor_cache.cc pdns/recursor_cache.hh pdns/syncres.cc pdns/syncres.hh --- 7e2e4419628db6bcb0428a07bd268abd035a1c7d diff --cc pdns/lwres.hh index 23edb17c3,afcc53a5b..82bb0050a --- a/pdns/lwres.hh +++ b/pdns/lwres.hh @@@ -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 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 diff --cc pdns/recursor_cache.cc index 37a1bceaa,71c45fb78..a15df95c7 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@@ -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* res, vector>* signatures) -int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set* res) ++int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set* res, vector>* 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& content, const vector>& signatures, bool auth) -void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const set& content, bool auth) ++void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const set& content, const vector>& signatures, bool auth) { d_cachecachevalid=false; - boost::tuple key=boost::make_tuple(qname, qt.getCode()); + boost::tuple key=boost::make_tuple(qname, qt.getCode()); cache_t::iterator stored=d_cache.find(key); uint32_t maxTTD=UINT_MAX; diff --cc pdns/recursor_cache.hh index de92b702d,c316ca5cd..4e21bac02 --- a/pdns/recursor_cache.hh +++ b/pdns/recursor_cache.hh @@@ -5,8 -5,9 +5,9 @@@ #include "dns.hh" #include "qtype.hh" #include "misc.hh" + #include "dnsname.hh" #include - +#include "dnsrecords.hh" #include #undef L #include @@@ -31,10 -32,10 +32,10 @@@ public } unsigned int size(); unsigned int bytes(); - int get(time_t, const string &qname, const QType& qt, set* res, vector>* signatures=0); - int get(time_t, const DNSName &qname, const QType& qt, set* res); ++ int get(time_t, const DNSName &qname, const QType& qt, set* res, vector>* 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& content, const vector>& signatures, bool auth); - void replace(time_t, const DNSName &qname, const QType& qt, const set& content, bool auth); ++ void replace(time_t, const DNSName &qname, const QType& qt, const set& content, const vector>& signatures, bool auth); void doPrune(void); void doSlash(int perc); uint64_t doDump(int fd); diff --cc pdns/reczones.cc index b38ea35f1,03f6c4842..f73eb8557 --- a/pdns/reczones.cc +++ b/pdns/reczones.cc @@@ -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>(), 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; diff --cc pdns/syncres.cc index 86ae43093,acaab1ba7..1d8ac40eb --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@@ -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<d_place == DNSResourceRecord::ANSWER) ret.push_back(*i); } @@@ -701,10 -752,9 +696,10 @@@ bool SyncRes::doCacheCheck(const DNSNam } set cset; bool found=false, expired=false; - - if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset) > 0) { + vector> signatures; + uint32_t ttl=0; + if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_doDNSSEC ? &signatures : 0) > 0) { - LOG(prefix<::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 n if(lwr.d_tcbit) { if(!doTCP) { doTCP=true; - LOG(prefix<toString() <<"), rcode="<toString()<<" ("<< remoteIP->toString() <<"), rcode="<sin4.sin_family==AF_INET6) @@@ -1031,31 -1056,16 +1011,31 @@@ } } - typedef map, set, TCacheComp > tcache_t; + struct CachePair + { + set records; + vector> signatures; + }; - typedef map, CachePair, TCacheComp > tcache_t; ++ typedef map, CachePair, TCacheComp > tcache_t; tcache_t tcache; + if(d_doDNSSEC) { + for(const auto& rec : lwr.d_records) { + if(rec.first.d_type == QType::RRSIG) { + auto rrsig = std::dynamic_pointer_cast(rec.first.d_content); - cerr<<"Got an RRSIG for "<d_type)<<" with name '"<d_type)<<" with name '"<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<<"' from '"<qname.toString()<<"' from '"<qname<<"|"<qtype.getName()<<"|"<content<<"' from '"<qname.toString()<<"|"<qtype.getName()<<"|"<content<<"' from '"<qtype.getCode()==QType::ANY) { LOG("NO! - we don't accept 'ANY' data"<qname,i->qtype)].insert(rr); + tcache[make_pair(i->qname,i->qtype)].records.insert(rr); } - } + } else LOG("NO!"<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::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(&record.ttl)=lowestTTL; } - cout<<"Have "<second.records.size()<<" records and "<second.signatures.size()<<" signatures for "<first.first; - t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit); ++ cout<<"Have "<second.records.size()<<" records and "<second.signatures.size()<<" signatures for "<first.first.toString(); + cout<<'|'<first.second.getCode())<replace(d_now.tv_sec, i->first.first, i->first.second, i->second.records, i->second.signatures, lwr.d_aabit); } - set nsset; - LOG(prefix< nsset; + LOG(prefix<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<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); @@@ -1142,42 -1162,35 +1137,42 @@@ 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<content<<"|"<qtype.getName()<<"'"<content<<"|"<qtype.getName()<<"'"<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<<"' -> '"<content<<"'"<qname.toString()<<"' -> '"<content<<"'"<qname<<"' -> '"<content<<"', had '"<qname.toString()<<"' -> '"<content<<"', had '"<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<<"' -> '"<content<<"'"<qname.toString()<<"' -> '"<content<<"'"<d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && lwr.d_rcode==RCode::NoError) { - LOG(prefix< ttl = min(s_maxnegttl, i->ttl); @@@ -1222,16 -1235,10 +1217,16 @@@ return 0; } else if(realreferral) { - LOG(prefix<dnssecmap[newauth]=true; + for(const auto& e : t_sstorage->dnssecmap) - cout< dnssecmap; ++ map dnssecmap; }; private: