SyncRes::s_serverID=::arg()["server-id"];
SyncRes::s_maxqperq=::arg().asNum("max-qperq");
SyncRes::s_maxtotusec=1000*::arg().asNum("max-total-msec");
+ SyncRes::s_rootNXTrust = ::arg().mustDo( "root-nx-trust");
if(SyncRes::s_serverID.empty()) {
char tmp[128];
gethostname(tmp, sizeof(tmp)-1);
::arg().setSwitch( "disable-edns", "Disable EDNS - EXPERIMENTAL, LEAVE DISABLED" )= "";
::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads")="";
+ ::arg().setSwitch( "root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist")="";
::arg().setSwitch( "any-to-tcp","Answer ANY queries with tc=1, shunting to TCP" )="no";
::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
::arg().set("minimum-ttl-override", "Set under adverse conditions, a minimum TTL")="0";
unsigned int SyncRes::s_minimumTTL;
bool SyncRes::s_doIPv6;
bool SyncRes::s_nopacketcache;
+bool SyncRes::s_rootNXTrust;
unsigned int SyncRes::s_maxqperq;
unsigned int SyncRes::s_maxtotusec;
string SyncRes::s_serverID;
}
+static const string getLastLabel(const std::string& qname)
+{
+ string ret=qname.substr(0, qname.length()-1);
+ string::size_type pos = ret.rfind('.');
+ if(pos != string::npos) {
+ ret = ret.substr(pos+1) + ".";
+ }
+ return ret;
+}
bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
{
string sqname(qname);
QType sqt(qtype);
uint32_t sttl=0;
- // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"'\n";
+ // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
- pair<negcache_t::const_iterator, negcache_t::const_iterator> range=t_sstorage->negcache.equal_range(tie(qname));
- negcache_t::iterator ni;
- for(ni=range.first; ni != range.second; ni++) {
- // we have something
- if(ni->d_qtype.getCode() == 0 || ni->d_qtype == qtype) {
- res=0;
- if((uint32_t)d_now.tv_sec < ni->d_ttd) {
- sttl=ni->d_ttd - d_now.tv_sec;
- if(ni->d_qtype.getCode()) {
- LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
- res = RCode::NoError;
- }
- else {
- LOG(prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
- res= RCode::NXDomain;
- }
- giveNegative=true;
- sqname=ni->d_qname;
- sqt=QType::SOA;
- moveCacheItemToBack(t_sstorage->negcache, ni);
- break;
- }
- else {
- LOG(prefix<<qname<<": Entire record '"<<qname<<"' or type was negatively cached, but entry expired"<<endl);
- moveCacheItemToFront(t_sstorage->negcache, ni);
+ pair<negcache_t::const_iterator, negcache_t::const_iterator> range;
+ QType qtnull(0);
+ range.first=t_sstorage->negcache.find(tie(getLastLabel(qname), qtnull));
+ // cerr<< "eq: "<<(range.first != t_sstorage->negcache.end() )<<endl;
+ if(s_rootNXTrust && range.first != t_sstorage->negcache.end()
+ && range.first->d_qname=="." && (uint32_t)d_now.tv_sec < range.first->d_ttd ) {
+ sttl=range.first->d_ttd - d_now.tv_sec;
+
+ cerr<<prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<range.first->d_name<<"' & '"<<range.first->d_qname<<"' for another "<<sttl<<" seconds"<<endl;
+ res= RCode::NXDomain;
+ sqname=range.first->d_qname;
+ sqt=QType::SOA;
+ moveCacheItemToBack(t_sstorage->negcache, range.first);
+
+ giveNegative=true;
+ }
+ else {
+ range=t_sstorage->negcache.equal_range(tie(qname));
+ negcache_t::iterator ni;
+ for(ni=range.first; ni != range.second; ni++) {
+ // we have something
+ if(ni->d_qtype.getCode() == 0 || ni->d_qtype == qtype) {
+ res=0;
+ if((uint32_t)d_now.tv_sec < ni->d_ttd) {
+ sttl=ni->d_ttd - d_now.tv_sec;
+ if(ni->d_qtype.getCode()) {
+ LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
+ res = RCode::NoError;
+ }
+ else {
+ LOG(prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
+ res= RCode::NXDomain;
+ }
+ giveNegative=true;
+ sqname=ni->d_qname;
+ sqt=QType::SOA;
+ moveCacheItemToBack(t_sstorage->negcache, ni);
+ break;
+ }
+ else {
+ LOG(prefix<<qname<<": Entire record '"<<qname<<"' or type was negatively cached, but entry expired"<<endl);
+ moveCacheItemToFront(t_sstorage->negcache, ni);
+ }
}
}
}
-
set<DNSResourceRecord> cset;
bool found=false, expired=false;
ne.d_qtype=QType(0); // this encodes 'whole record'
replacing_insert(t_sstorage->negcache, ne);
+ if(s_rootNXTrust && auth==".") {
+ ne.d_name = getLastLabel(ne.d_name);
+ replacing_insert(t_sstorage->negcache, ne);
+ }
negindic=true;
}