#include "dnspacket.hh"
#include "dns.hh"
-bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len)
+bool DNSBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len, map<DNSName,int>& negCacheMap)
{
bool found=false;
DNSName subdomain(target);
if( best_match_len >= (int)subdomain.toString().length() )
break;
- if( this->getSOA( subdomain, *sd, p ) ) {
+ map<DNSName,int>::iterator it = negCacheMap.find(subdomain);
+ bool negCached = ( it != negCacheMap.end() && it->second == 1 );
+
+ if(! negCached && this->getSOA( subdomain, *sd, p ) ) {
sd->qname = subdomain;
if(p->qtype.getCode() == QType::DS && subdomain==target) {
// Found authoritative zone but look for parent zone with 'DS' record.
+ negCacheMap[subdomain]=2;
found=true;
} else
return true;
virtual void getAllDomains(vector<DomainInfo> *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 DNSName &target, const int best_match_len);
+ virtual bool getAuth(DNSPacket *p, SOAData *sd, const DNSName &target, const int best_match_len, map<DNSName,int>& negCacheMap);
struct KeyData {
std::string content;
{
int best_match_len = -1;
bool from_cache = false; // Was this result fetched from the cache?
+ map<DNSName,int> 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
best_match_len = sd->qname.countLabels();
break;
- }
+ } else if (cstat==0) {
+ negCacheMap[subdomain]=1;
+ } else
+ negCacheMap[subdomain]=0;
loops++;
}
while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
}
- for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
- if((*i)->getAuth(p, sd, target, best_match_len)) {
+ for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i) {
+ if((*i)->getAuth(p, sd, target, best_match_len, negCacheMap)) {
best_match_len = sd->qname.countLabels(); // FIXME400
from_cache = false;
if( best_match_len == (int)target.countLabels() )
goto auth_found;
}
+ }
+
+ if( sd->db != (DNSBackend *)-1 && d_negcache_ttl) {
+ DNSName shorter(target);
+
+ d_question.qtype=QType::SOA;
+ d_question.zoneId=-1;
+ while((int)shorter.countLabels() > best_match_len ) {
+ map<DNSName,int>::iterator it = negCacheMap.find(shorter);
+ if (it == negCacheMap.end() || it->second == 0) {
+ d_question.qname=shorter;
+ addNegCache(d_question);
+ }
+ if (!shorter.chopOff())
+ break;
+ }
+ }
if( best_match_len == -1 )
return false;