From 6dfff36f9cba7036b60899d49458bf13407112ba Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 5 Apr 2017 19:57:56 +0200 Subject: [PATCH] rec: Refactoring of SyncRes::doResolveAt() --- pdns/recursordist/test-syncres_cc.cc | 13 + pdns/syncres.cc | 484 +++++++++++++++------------ pdns/syncres.hh | 9 +- pdns/ws-recursor.cc | 2 +- 4 files changed, 299 insertions(+), 209 deletions(-) diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index 9072f63c5..d0d51ded5 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -8,6 +8,7 @@ #include "rec-lua-conf.hh" #include "root-dnssec.hh" #include "syncres.hh" +#include "utility.hh" #include "validate-recursor.hh" RecursorStats g_stats; @@ -128,9 +129,13 @@ static void init(bool debug=false) SyncRes::clearDontQuery(); SyncRes::clearNSSpeeds(); + BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0); SyncRes::clearEDNSStatuses(); + BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0); SyncRes::clearThrottle(); + BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0); SyncRes::clearFailedServers(); + BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0); auto luaconfsCopy = g_luaconfs.getCopy(); luaconfsCopy.dfe.clear(); @@ -2295,6 +2300,8 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_nord) { sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { if (ip == forwardedNS) { + BOOST_CHECK_EQUAL(sendRDQuery, false); + setLWResult(res, 0, true, false, true); addRecordToLW(res, domain, QType::A, "192.0.2.42"); return 1; @@ -2331,6 +2338,8 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_rd) { sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { if (ip == forwardedNS) { + BOOST_CHECK_EQUAL(sendRDQuery, false); + setLWResult(res, 0, true, false, true); addRecordToLW(res, domain, QType::A, "192.0.2.42"); return 1; @@ -2364,6 +2373,8 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord) { sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { if (ip == forwardedNS) { + BOOST_CHECK_EQUAL(sendRDQuery, false); + setLWResult(res, 0, true, false, true); addRecordToLW(res, domain, QType::A, "192.0.2.42"); return 1; @@ -2400,6 +2411,8 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd) { sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { if (ip == forwardedNS) { + BOOST_CHECK_EQUAL(sendRDQuery, true); + setLWResult(res, 0, true, false, true); addRecordToLW(res, domain, QType::A, "192.0.2.42"); return 1; diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 3e1746741..9aa7cb60e 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -22,33 +22,18 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include "lua-recursor4.hh" -#include "utility.hh" -#include "syncres.hh" -#include -#include -#include "dnsrecords.hh" -#include -#include -#include -#include -#include -#include -#include -#include "logger.hh" -#include "validate.hh" -#include "misc.hh" #include "arguments.hh" -#include "lwres.hh" -#include "recursor_cache.hh" -#include "dnsparser.hh" +#include "cachecleaner.hh" #include "dns_random.hh" -#include "lock.hh" +#include "dnsparser.hh" +#include "dnsrecords.hh" #include "ednssubnet.hh" -#include "cachecleaner.hh" +#include "logger.hh" +#include "lua-recursor4.hh" #include "rec-lua-conf.hh" +#include "syncres.hh" + thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage; unsigned int SyncRes::s_maxnegttl; @@ -159,7 +144,7 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl * - version.pdns. CH TXT * - id.server. CH TXT */ -bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t &qclass, vector &ret) +bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector &ret) { static const DNSName arpa("1.0.0.127.in-addr.arpa."), ip6_arpa("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns."); @@ -751,6 +736,7 @@ DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtyp else { // Again, picked up in doResolveAt. An empty DNSName, combined with a // non-empty vector of ComboAddresses means 'this is a forwarded domain' + // This is actually picked up in retrieveAddressesForNS called from doResolveAt. nsset.insert({DNSName(), {iter->second.d_servers, iter->second.d_rdForward}}); } return authdomain; @@ -1118,7 +1104,7 @@ bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& return true; } else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) { - LOG(prefix< ednsmask) +RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional ednsmask) { struct CachePair { @@ -1193,7 +1179,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResu continue; } else { LOG("YES! - This answer was "); - if (nameservers[tns].first.empty()) { + if (!wasForwarded) { LOG("retrieved from the local auth store."); } else { LOG("received from a server we forward to."); @@ -1235,7 +1221,9 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResu // cout<<'|'<first.type)<second.records.empty()) // this happens when we did store signatures, but passed on the records themselves continue; + t_RC->replace(d_now.tv_sec, i->first.name, QType(i->first.type), i->second.records, i->second.signatures, lwr.d_aabit, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::optional()); + if(i->first.place == DNSResourceRecord::ANSWER && ednsmask) d_wasVariable=true; } @@ -1243,7 +1231,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResu return RCode::NoError; } -bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, bool& sawDS) +bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic) { bool done = false; @@ -1312,7 +1300,6 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co } else if(rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::DS) { LOG(prefix< '"<getZoneRepresentation()<<"'"<& ednsmask, const DNSName& auth, bool const sendRDQuery, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated) +{ + int resolveret; + s_outqueries++; + d_outqueries++; + + if(d_outqueries + d_throttledqueries > s_maxqperq) { + throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString()); + } + + if(s_maxtotusec && d_totUsec > s_maxtotusec) { + throw ImmediateServFailException("Too much time waiting for "+qname.toLogString()+"|"+qtype.getName()+", timeouts: "+std::to_string(d_timeouts) +", throttles: "+std::to_string(d_throttledqueries) + ", queries: "+std::to_string(d_outqueries)+", "+std::to_string(d_totUsec/1000)+"msec"); + } + + if(doTCP) { + LOG(prefix<preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) { + LOG(prefix<toString()<<" to query"<toString()<<" on response"< 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) { + LOG(prefix< 0) { + t_sstorage.fails.clear(remoteIP); + } + + if(lwr.d_tcbit) { + *truncated = true; + + if (doTCP) { + LOG(prefix< ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode) +{ + string prefix; + if(doLog()) { + prefix=d_prefix; + prefix.append(depth, ' '); + } + + if(s_minimumTTL) { + for(auto& rec : lwr.d_records) { + rec.d_ttl = max(rec.d_ttl, s_minimumTTL); + } + } + + *rcode = updateCacheFromRecords(prefix, lwr, qname, auth, wasForwarded, ednsmask); + if (*rcode != RCode::NoError) { + return true; + } + + LOG(prefix< nsset; + bool realreferral=false, negindic=false; + DNSName newauth; + DNSName newtarget; + + bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic); + + if(done){ + LOG(prefix< 10) { + LOG(prefix< beenthere2; + *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2); + return true; + } + + if(lwr.d_rcode == RCode::NXDomain) { + LOG(prefix< (size_t)(1+1*s_doIPv6)) { LOG(prefix< remoteIPs_t; remoteIPs_t remoteIPs; remoteIPs_t::const_iterator remoteIP; - bool doTCP=false; bool pierceDontQuery=false; bool sendRDQuery=false; boost::optional ednsmask; LWResult lwr; - if(tns->empty() && nameservers[*tns].first.empty() ) { + const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty()); + int rcode = RCode::NoError; + bool gotNewServers = false; + + if(tns->empty() && !wasForwarded) { LOG(prefix<dfe, &gotNewServers, &rcode); + if (done) { + return rcode; + } + if (gotNewServers) { + break; + } } else { + /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */ remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet); if(remoteIPs.empty()) { @@ -1428,197 +1646,53 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) { LOG(prefix<toStringWithPort() <<", asking '"< s_maxqperq) throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString()); - TryTCP: - if(doTCP) { - LOG(prefix<toStringWithPort() < s_maxtotusec) - throw ImmediateServFailException("Too much time waiting for "+qname.toLogString()+"|"+qtype.getName()+", timeouts: "+std::to_string(d_timeouts) +", throttles: "+std::to_string(d_throttledqueries) + ", queries: "+std::to_string(d_outqueries)+", "+std::to_string(d_totUsec/1000)+"msec"); - if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) { - LOG(prefix<toString()<<" to query"<toString()<<" on response"<sin4.sin_family); - if(resolveret != 1) { - if(resolveret==0) { - LOG(prefix<sin4.sin_family == AF_INET) - s_outgoing4timeouts++; - else - s_outgoing6timeouts++; - } - else if(resolveret==-2) { - LOG(prefix<toString()<< (doTCP ? " over TCP" : "") <<", possible error: "< 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(*remoteIP) >= s_serverdownmaxfails) { - LOG(prefix<toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" < 6.0 && d_timeouts > 2) throw ImmediateServFailException("Too much work resolving "+qname+"|"+qtype.getName()+", timeouts: "+std::to_string(d_timeouts) +", throttles: "+std::to_string(d_throttledqueries)); + LOG(prefix<toString() <<"), rcode="<toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<sin4.sin_family==AF_INET6) + lwr.d_usec/=3; + */ + // cout<<"msec: "< 0) - t_sstorage.fails.clear(*remoteIP); + t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now); - break; // this IP address worked! - wasLame:; // well, it didn't - LOG(prefix<toString() <<") is lame for '"<dfe, &gotNewServers, &rcode); + if (done) { + return rcode; } - } - - if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked - continue; - - if(lwr.d_tcbit) { - if(!doTCP) { - doTCP=true; - LOG(prefix<toString() <<"), rcode="<sin4.sin_family==AF_INET6) - lwr.d_usec/=3; - */ - // cout<<"msec: "< nsset; - bool realreferral=false, negindic=false, sawDS=false; - DNSName newauth; - DNSName newtarget; - - bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, sawDS); - - if(done){ - LOG(prefix< 10) { - LOG(prefix< beenthere2; - return doResolve(newtarget, qtype, ret, depth + 1, beenthere2); - } - if(lwr.d_rcode==RCode::NXDomain) { - LOG(prefix<dfe.getProcessingPolicy(nameserver, d_discardedPolicies); - if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response - LOG("however "<empty()) { // means: not OOB, OOB == empty - goto wasLame; } } } diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 83f6dddf3..8f15c0284 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -676,6 +676,9 @@ private: int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set&beenthere); + bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType& qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated); + bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode); + int doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere); bool doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res); domainmap_t::const_iterator getBestAuthZone(DNSName* qname) const; @@ -693,10 +696,10 @@ private: bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery); vector retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector::const_iterator& tns, const unsigned int depth, set& beenthere, const vector& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet); - RCode::rcodes_ updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, NsSet& nameservers, const DNSName& tns, const boost::optional); - bool processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, bool& sawDS); + RCode::rcodes_ updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional); + bool processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic); - bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t &qclass, vector &ret); + bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector &ret); int asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, boost::optional& srcmask, LWResult* res) const; diff --git a/pdns/ws-recursor.cc b/pdns/ws-recursor.cc index 92d5494c4..97734a703 100644 --- a/pdns/ws-recursor.cc +++ b/pdns/ws-recursor.cc @@ -40,7 +40,7 @@ #include "logger.hh" #include "ext/incbin/incbin.h" -extern __thread FDMultiplexer* t_fdm; +extern thread_local FDMultiplexer* t_fdm; using json11::Json; -- 2.40.0