From 787737ae0990048ce9178d02ae963cfdaa9158c7 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 23 Jun 2017 16:12:30 +0200 Subject: [PATCH] rec: Update validation status of records cached as Indeterminate --- pdns/recursor_cache.cc | 133 ++++++++++++++++++++++++++--------------- pdns/recursor_cache.hh | 7 ++- pdns/syncres.cc | 25 ++++++-- 3 files changed, 111 insertions(+), 54 deletions(-) diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index 765216efa9..4105055633 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -34,9 +34,8 @@ unsigned int MemRecursorCache::bytes() } // returns -1 for no hits -int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures, std::vector>* authorityRecs, bool* variable, vState* state, bool* wasAuth) +std::pair MemRecursorCache::getEntries(const DNSName &qname, const QType& qt) { - time_t ttd=0; // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; if(!d_cachecachevalid || d_cachedqname!= qname) { @@ -47,58 +46,79 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, } // else cerr<<"had cache cache hit!"<d_auth) + return false; + + return ((entry->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || + (qt.getCode()==QType::ADDR && (entry->d_qtype == QType::A || entry->d_qtype == QType::AAAA))) + && (entry->d_netmask.empty() || entry->d_netmask.match(who))); +} + +// returns -1 for no hits +int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures, std::vector>* authorityRecs, bool* variable, vState* state, bool* wasAuth) +{ + time_t ttd=0; + // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; + + auto entries = getEntries(qname, qt); + if(res) res->clear(); - if(d_cachecache.first!=d_cachecache.second) { - for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i) { - if (requireAuth && !i->d_auth) + if(entries.first!=entries.second) { + for(cache_t::const_iterator i=entries.first; i != entries.second; ++i) { + + if (i->d_ttd <= now) { + moveCacheItemToFront(d_cache, i); continue; + } - //cerr<<"TTD is "<d_ttd<<", now is "<d_qtype<d_ttd > now && ((i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || - (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) )) - && (i->d_netmask.empty() || i->d_netmask.match(who))) - ) { - if(variable && !i->d_netmask.empty()) { - *variable=true; - } - ttd = i->d_ttd; - // cerr<<"Looking at "<d_records.size()<<" records for this name"<d_records.begin(); k != i->d_records.end(); ++k) { - if(res) { - DNSRecord dr; - dr.d_name = qname; - dr.d_type = i->d_qtype; - dr.d_class = QClass::IN; - dr.d_content = *k; - dr.d_ttl = static_cast(i->d_ttd); - dr.d_place = DNSResourceRecord::ANSWER; - res->push_back(dr); - } - } - - if(signatures) // if you do an ANY lookup you are hosed XXXX - *signatures=i->d_signatures; - - if(authorityRecs) // if you do an ANY lookup you are hosed here too XXXX - *authorityRecs=i->d_authorityRecs; + if (!entryMatches(i, qt, requireAuth, who)) + continue; + + if(variable && !i->d_netmask.empty()) { + *variable=true; + } + + ttd = i->d_ttd; + // cerr<<"Looking at "<d_records.size()<<" records for this name"<d_records.begin(); k != i->d_records.end(); ++k) { if(res) { - if(res->empty()) - moveCacheItemToFront(d_cache, i); - else - moveCacheItemToBack(d_cache, i); + DNSRecord dr; + dr.d_name = qname; + dr.d_type = i->d_qtype; + dr.d_class = QClass::IN; + dr.d_content = *k; + dr.d_ttl = static_cast(i->d_ttd); + dr.d_place = DNSResourceRecord::ANSWER; + res->push_back(dr); } - if(state) { - *state = i->d_state; - } - if(wasAuth) { - *wasAuth = i->d_auth; - } - if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done - break; } + + if(signatures) // if you do an ANY lookup you are hosed XXXX + *signatures=i->d_signatures; + + if(authorityRecs) // if you do an ANY lookup you are hosed here too XXXX + *authorityRecs=i->d_authorityRecs; + + moveCacheItemToBack(d_cache, i); + + if(state) { + *state = i->d_state; + } + + if(wasAuth) { + *wasAuth = i->d_auth; + } + + if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done + break; } // cerr<<"time left : "<size() : 0) <<"\n"; @@ -107,8 +127,6 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, return -1; } - - bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const vector& content, const CacheEntry& stored) { if(!stored.d_auth) { @@ -261,6 +279,27 @@ bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, uint16_t qtyp return false; } +bool MemRecursorCache::updateValidationStatus(const DNSName &qname, const QType& qt, const ComboAddress& who, bool requireAuth, vState newState) +{ + bool updated = false; + auto entries = getEntries(qname, qt); + + for(auto i = entries.first; i != entries.second; ++i) { + + if (!entryMatches(i, qt, requireAuth, who)) + continue; + + i->d_state = newState; + updated = true; + + if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done + break; + + } + + return updated; +} + uint64_t MemRecursorCache::doDump(int fd) { FILE* fp=fdopen(dup(fd), "w"); diff --git a/pdns/recursor_cache.hh b/pdns/recursor_cache.hh index 1eacf12b34..0f3fbc91bb 100644 --- a/pdns/recursor_cache.hh +++ b/pdns/recursor_cache.hh @@ -63,6 +63,7 @@ public: int doWipeCache(const DNSName& name, bool sub, uint16_t qtype=0xffff); bool doAgeCache(time_t now, const DNSName& name, uint16_t qtype, uint32_t newTTL); + bool updateValidationStatus(const DNSName &qname, const QType& qt, const ComboAddress& who, bool requireAuth, vState newState); uint64_t cacheHits, cacheMisses; @@ -88,7 +89,7 @@ private: records_t d_records; std::vector> d_authorityRecs; Netmask d_netmask; - vState d_state; + mutable vState d_state; }; typedef multi_index_container< @@ -111,6 +112,10 @@ private: pair d_cachecache; DNSName d_cachedqname; bool d_cachecachevalid; + bool attemptToRefreshNSTTL(const QType& qt, const vector& content, const CacheEntry& stored); + bool entryMatches(cache_t::const_iterator& entry, const QType& qt, bool requireAuth, const ComboAddress& who); + std::pair getEntries(const DNSName &qname, const QType& qt); + }; #endif diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 07957a3f78..4ec365d4e1 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -823,9 +823,15 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector if (validationEnabled() && wasAuth && state == Indeterminate && d_requireAuthData) { /* This means we couldn't figure out the state when this entry was cached, most likely because we hadn't computed the zone cuts yet. */ - LOG(prefix<updateValidationStatus(qname, QType(QType::CNAME), d_requestor, d_requireAuthData, state); + } + } } LOG(prefix<d_content->getZoneRepresentation()<<"', validation state is "<updateValidationStatus(sqname, sqt, d_requestor, d_requireAuthData, cachedState); + } + } } for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) { -- 2.47.2