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<string,int>& negCacheMap)
{
bool found=false;
string subdomain(target);
if( best_match_len >= (int)subdomain.length() )
break;
- if( this->getSOA( subdomain, *sd, p ) ) {
+ map<string,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(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;
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 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<string,int>& negCacheMap);
struct KeyData {
unsigned int id;
{
int best_match_len = -1;
bool from_cache = false; // Was this result fetched from the cache?
+ map<string,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.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<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
- if((*i)->getAuth(p, sd, target, zoneId, best_match_len)) {
+ for(vector<DNSBackend *>::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<string,int>::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;
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<string,int>& 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);