From: Kees Monshouwer Date: Fri, 18 Sep 2015 08:12:15 +0000 (+0200) Subject: improve negative caching for SOA lookups X-Git-Tag: auth-3.4.7~8^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4549a7200dfc5c80cd3f1a24b0f058d4579b1dab;p=pdns improve negative caching for SOA lookups --- diff --git a/pdns/dnsbackend.cc b/pdns/dnsbackend.cc index 9615aaa08..09e02e47d 100644 --- a/pdns/dnsbackend.cc +++ b/pdns/dnsbackend.cc @@ -44,7 +44,7 @@ bool DNSBackend::getRemote(DNSPacket *p, struct sockaddr *sa, Utility::socklen_t return true; } -bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len) +bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map& negCacheMap) { bool found=false; string subdomain(target); @@ -52,13 +52,17 @@ bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int *z if( best_match_len >= (int)subdomain.length() ) break; - if( this->getSOA( subdomain, *sd, p ) ) { + map::iterator it = negCacheMap.find(subdomain); + bool negCached = ( it != negCacheMap.end() && it->second == 1 ); + + if(! negCached && this->getSOA( subdomain, *sd, p ) ) { sd->qname = subdomain; if(zoneId) *zoneId = sd->domain_id; if(p->qtype.getCode() == QType::DS && pdns_iequals(subdomain, target)) { // Found authoritative zone but look for parent zone with 'DS' record. + negCacheMap[subdomain]=2; found=true; } else return true; diff --git a/pdns/dnsbackend.hh b/pdns/dnsbackend.hh index b4122b96e..4a057be21 100644 --- a/pdns/dnsbackend.hh +++ b/pdns/dnsbackend.hh @@ -163,7 +163,7 @@ public: virtual void getAllDomains(vector *domains, bool include_disabled=false) { } /** Determines if we are authoritative for a zone, and at what level */ - virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len); + virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map& negCacheMap); struct KeyData { unsigned int id; diff --git a/pdns/ueberbackend.cc b/pdns/ueberbackend.cc index 0c48f6916..8ddfa981a 100644 --- a/pdns/ueberbackend.cc +++ b/pdns/ueberbackend.cc @@ -278,6 +278,7 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int { int best_match_len = -1; bool from_cache = false; // Was this result fetched from the cache? + map negCacheMap; // If not special case of caching explicitly disabled (sd->db = -1), first // find the best match from the cache. If DS then we need to find parent so @@ -308,22 +309,42 @@ bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const string &target, int best_match_len = sd->qname.length(); break; - } + } else if (cstat==0) { + negCacheMap[subdomain]=1; + } else + negCacheMap[subdomain]=0; loops++; } while( chopOff( subdomain ) ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> '' } - for(vector::const_iterator i=backends.begin(); i!=backends.end();++i) - if((*i)->getAuth(p, sd, target, zoneId, best_match_len)) { + for(vector::const_iterator i=backends.begin(); i!=backends.end();++i) { + if((*i)->getAuth(p, sd, target, zoneId, best_match_len, negCacheMap)) { best_match_len = sd->qname.length(); from_cache = false; // Shortcut for the case that we got a direct hit - no need to go // through the other backends then. if( best_match_len == (int)target.length() ) - goto auth_found; + goto auth_found; } + } + + if( sd->db != (DNSBackend *)-1 && d_cache_ttl) { + string shorter(target); + + d_question.qtype=QType::SOA; + d_question.zoneId=-1; + while((int)shorter.length() > best_match_len ) { + map::iterator it = negCacheMap.find(shorter); + if (it == negCacheMap.end() || it->second == 0) { + d_question.qname=shorter; + addNegCache(d_question); + } + if (!chopOff(shorter)) + break; + } + } if( best_match_len == -1 ) return false; diff --git a/pdns/ueberbackend.hh b/pdns/ueberbackend.hh index 6837ed1b7..07cd011c9 100644 --- a/pdns/ueberbackend.hh +++ b/pdns/ueberbackend.hh @@ -114,8 +114,8 @@ public: void lookup(const QType &, const string &qdomain, DNSPacket *pkt_p=0, int zoneId=-1); /* 5-arg version is only valid for backends and should never be called directly */ - virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len) { - throw PDNSException("5-arg version of getAuth should not be called in UeberBackend"); + virtual bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId, const int best_match_len, map& negCacheMap) { + throw PDNSException("6-arg version of getAuth should not be called in UeberBackend"); } bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);