From: Otto Moerbeek Date: Wed, 29 Jun 2022 09:03:14 +0000 (+0200) Subject: Handle serve stale for infra queries X-Git-Tag: rec-4.8.0-alpha1~24^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7f80bac50288b0a1e17fd8bf3dec9d29f8db9331;p=thirdparty%2Fpdns.git Handle serve stale for infra queries --- diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 8268da90ee..e7fc6bd34b 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1974,7 +1974,7 @@ int SyncRes::doResolveNoQNameMinimization(const DNSName &qname, const QType qtyp subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions } - res = doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, stopAtDelegation, nullptr); + res = doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, stopAtDelegation, nullptr, serveStale); if (res == -1 && s_save_parent_ns_set) { // It did not work out, lets check if we have a saved parent NS set @@ -1994,7 +1994,7 @@ int SyncRes::doResolveNoQNameMinimization(const DNSName &qname, const QType qtyp } if (fallBack.size() > 0) { LOG(prefix<inc(subdomain); @@ -2040,7 +2040,7 @@ struct speedOrderCA /** This function explicitly goes out for A or AAAA addresses */ -vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS) +vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS, bool serveStale) { typedef vector res_t; typedef vector ret_t; @@ -2056,17 +2056,21 @@ vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, d_DNSSECValidationRequested = false; d_followCNAME = true; + MemRecursorCache::Flags flags = MemRecursorCache::None; + if (serveStale) { + flags |= MemRecursorCache::ServeStale; + } try { // First look for both A and AAAA in the cache res_t cset; - if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, MemRecursorCache::None, &cset, d_cacheRemote, d_routingTag) > 0) { + if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, flags, &cset, d_cacheRemote, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR(i)) { ret.push_back(rec->getCA(53)); } } } - if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, MemRecursorCache::None, &cset, d_cacheRemote, d_routingTag) > 0) { + if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, flags, &cset, d_cacheRemote, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR(i)) { seenV6 = true; @@ -2106,7 +2110,7 @@ vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, } else { // We have some IPv4 records, consult the cache, we might have encountered some IPv6 glue cset.clear(); - if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, MemRecursorCache::None, &cset, d_cacheRemote, d_routingTag) > 0) { + if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, flags, &cset, d_cacheRemote, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR(i)) { seenV6 = true; @@ -3317,7 +3321,7 @@ bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAd return false; } -vector SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, std::vector>::const_iterator& tns, const unsigned int depth, set& beenthere, const vector>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int &nretrieveAddressesForNS) +vector SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, std::vector>::const_iterator& tns, const unsigned int depth, set& beenthere, const vector>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int &nretrieveAddressesForNS, bool serveStale) { vector result; @@ -3334,7 +3338,7 @@ vector SyncRes::retrieveAddressesForNS(const std::string& prefix, LOG(prefix<first<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<first, depth, beenthere, cacheOnly, nretrieveAddressesForNS); + result = getAddrs(tns->first, depth, beenthere, cacheOnly, nretrieveAddressesForNS, serveStale); } // Other exceptions should likely not throttle... catch (const ImmediateServFailException& ex) { @@ -4239,7 +4243,7 @@ void SyncRes::rememberParentSetIfNeeded(const DNSName& domain, const vectorgetNS(); set beenthereIgnored; unsigned int nretrieveAddressesForNSIgnored; - auto addresses = getAddrs(name, depth, beenthereIgnored, true, nretrieveAddressesForNSIgnored); + auto addresses = getAddrs(name, depth, beenthereIgnored, true, nretrieveAddressesForNSIgnored, false); entries.emplace(name, addresses); } s_savedParentNSSet.lock()->emplace(domain, std::move(entries), d_now.tv_sec + ttl); @@ -5485,7 +5489,7 @@ bool SyncRes::doDoTtoAuth(const DNSName& ns) const int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType qtype, vector&ret, unsigned int depth, set&beenthere, vState& state, StopAtDelegation* stopAtDelegation, - map>* fallBack) + map>* fallBack, bool serveStale) { auto luaconfsLocal = g_luaconfs.getLocal(); string prefix; @@ -5588,7 +5592,7 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con } } if (remoteIPs.size() == 0) { - remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly, addressQueriesForNS); + remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly, addressQueriesForNS, serveStale); } if(remoteIPs.empty()) { diff --git a/pdns/syncres.hh b/pdns/syncres.hh index ef1575c198..527c3986e9 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -551,7 +551,7 @@ private: bool doDoTtoAuth(const DNSName& ns) const; int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, QType qtype, vector&ret, unsigned int depth, set&beenthere, vState& state, StopAtDelegation* stopAtDelegation, - std::map>* fallback); + std::map>* fallback, bool serveStale); bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed, bool dontThrottle = false); 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, vState& state, const ComboAddress& remoteIP); @@ -570,14 +570,14 @@ private: inline vector> shuffleInSpeedOrder(NsSet &nameservers, const string &prefix); inline vector shuffleForwardSpeed(const vector &rnameservers, const string &prefix, const bool wasRd); bool moreSpecificThan(const DNSName& a, const DNSName &b) const; - vector getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS); + vector getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, bool cacheOnly, unsigned int& addressQueriesForNS, bool serveStale); bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers); bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&); void checkMaxQperQ(const DNSName& qname) const; bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, 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, bool cacheOnly, unsigned int& addressQueriesForNS); + 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, bool cacheOnly, unsigned int& addressQueriesForNS, bool serveStale); void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); /* This function will check whether the answer should have the AA bit set, and will set if it should be set and isn't.