// the two retries allow getBestNSNamesFromCache&co to reprime the root
// hints, in case they ever go missing
for(int tries=0;tries<2 && nsset.empty();++tries) {
- subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
+ subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
}
if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
for(int j=1; j<2+s_doIPv6; j++)
{
- set<GetBestNSAnswer> rbeenthere(beenthere);
bool done=false;
- // j=0: ANY
- // j=1: A
- // j=2: AAAA
-
switch(j) {
case 0:
type = QType::ANY;
break;
}
- if(!doResolve(qname, type, res,depth+1, j==1 ? beenthere : rbeenthere) && !res.empty()) { // this consults cache, OR goes out
+ if(!doResolve(qname, type, res,depth+1, beenthere) && !res.empty()) { // this consults cache, OR goes out
for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
if(i->qtype.getCode()==QType::A || i->qtype.getCode()==QType::AAAA) {
ret.push_back(ComboAddress(i->content, 53));
return ret;
}
-void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
+void SyncRes::getBestNSFromCache(const string &qname, const QType& qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix, subdomain(qname);
if(doLog()) {
}
if(!bestns.empty()) {
GetBestNSAnswer answer;
- answer.qname=qname; answer.bestns=bestns;
+ answer.qname=qname;
+ answer.qtype=qtype.getCode();
+ BOOST_FOREACH(const DNSResourceRecord& rr, bestns)
+ answer.bestns.insert(make_pair(rr.qname, rr.content));
+
if(beenthere.count(answer)) {
LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
if(doLog())
for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
- LOG(prefix<<qname<<": beenthere: "<<j->qname<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
+ LOG(prefix<<qname<<": beenthere: "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
}
bestns.clear();
}
}
/** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere)
+string SyncRes::getBestNSNamesFromCache(const string &qname, const QType& qtype, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere)
{
string subdomain(qname);
string authdomain(qname);
}
set<DNSResourceRecord> bestns;
- getBestNSFromCache(subdomain, bestns, flawedNSSet, depth, beenthere);
+ getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
nsset.insert(k->content);
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, bool* flawedNSSet, 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);
+ void getBestNSFromCache(const string &qname, const QType &qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
+ string getBestNSNamesFromCache(const string &qname, const QType &qtype, set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
inline vector<string> shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix);
bool moreSpecificThan(const string& a, const string &b);
struct GetBestNSAnswer
{
string qname;
- set<DNSResourceRecord> bestns;
+ set<pair<string,string> > bestns;
+ uint8_t qtype; // only A and AAAA anyhow
bool operator<(const GetBestNSAnswer &b) const
{
- if(qname<b.qname)
- return true;
- if(qname==b.qname)
- return bestns<b.bestns;
- return false;
+ return boost::tie(qname, qtype, bestns) <
+ boost::tie(b.qname, qtype, b.bestns);
}
};