string subdomain(qname);
set<string, CIStringCompare> nsset;
+ bool flawedNSSet=false;
for(int tries=0;tries<2 && nsset.empty();++tries) {
- subdomain=getBestNSNamesFromCache(subdomain,nsset,depth, beenthere); // pass beenthere to both occasions
+ subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
if(nsset.empty()) { // must've lost root records
LOG<<prefix<<qname<<": our root expired, repriming from hints and retrying"<<endl;
}
}
- if(!(res=doResolveAt(nsset, subdomain, qname, qtype, ret, depth, beenthere)))
+ if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
return 0;
LOG<<prefix<<qname<<": failed (res="<<res<<")"<<endl;
return ret;
}
-void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, int depth, set<GetBestNSAnswer>& beenthere)
+void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix, subdomain(qname);
if(s_log) {
do {
LOG<<prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl;
set<DNSResourceRecord> ns;
+ *flawedNSSet = false;
if(RC.get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
for(set<DNSResourceRecord>::const_iterator k=ns.begin();k!=ns.end();++k) {
if(k->ttl > (unsigned int)d_now.tv_sec ) {
LOG<<", not in cache / did not look at cache"<<endl;
}
}
- else
+ else {
+ *flawedNSSet=true;
LOG<<prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl;
+ }
}
}
if(!bestns.empty()) {
answer.qname=qname; answer.bestns=bestns;
if(beenthere.count(answer)) {
LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP! Trying less specific NS"<<endl;
- for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j)
- LOG<<prefix<<qname<<": beenthere: "<<j->qname<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl;
+ if(s_log)
+ for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j)
+ LOG<<prefix<<qname<<": beenthere: "<<j->qname<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl;
bestns.clear();
}
else {
beenthere.insert(answer);
- LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"'"<<endl;
+ LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl;
return;
}
}
}
/** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, int depth, set<GetBestNSAnswer>&beenthere)
+string SyncRes::getBestNSNamesFromCache(const string &qname, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere)
{
string subdomain(qname);
}
set<DNSResourceRecord> bestns;
- getBestNSFromCache(subdomain, bestns, depth, beenthere);
+ getBestNSFromCache(subdomain, bestns, flawedNSSet, depth, beenthere);
for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
nsset.insert(k->content);
/** returns -1 in case of no results, rcode otherwise */
-int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth, const string &qname, const QType &qtype,
+int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret,
int depth, set<GetBestNSAnswer>&beenthere)
{
for(vector<string>::const_iterator tns=rnameservers.begin();;++tns) {
if(tns==rnameservers.end()) {
LOG<<prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl;
- if(auth!=".") {
+ if(auth!="." && flawedNSSet) {
g_stats.nsSetInvalidations++;
LOG<<prefix<<qname<<": Invalidating nameservers for level '"<<auth<<"', next query might succeed"<<endl;
RC.doWipeCache(auth, QType::NS);
if(remoteIPs.empty()) {
LOG<<prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl;
+ flawedNSSet=true;
continue;
}
else {
void SyncRes::addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth)
{
set<DNSResourceRecord> bestns;
- set<GetBestNSAnswer>beenthere;
- getBestNSFromCache(qname, bestns, depth,beenthere);
+ set<GetBestNSAnswer> beenthere;
+ bool dontcare;
+ getBestNSFromCache(qname, bestns, &dontcare, depth, beenthere);
for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
DNSResourceRecord ns=*k;
static string s_serverID;
private:
struct GetBestNSAnswer;
- int doResolveAt(set<string, CIStringCompare> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
+ int doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
int depth, set<GetBestNSAnswer>&beenthere);
int doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
bool doOOBResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
domainmap_t::const_iterator getBestAuthZone(string* qname);
bool doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
bool doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
- void getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, int depth, set<GetBestNSAnswer>& beenthere);
+ void getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
- string getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, int depth, set<GetBestNSAnswer>&beenthere);
+ string getBestNSNamesFromCache(const string &qname,set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
void addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth);
inline vector<string> shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix);