Permalink
Browse files

Optimize AXFR disabled case

When disable-axfr=yes or client ACLs don't allow the AXFR to go through,
skip all backend launching activities (possibly expensive for pipe- and
remotebackend users).
Same for IXFR.

[Backport of 2289314 from master.]
  • Loading branch information...
1 parent 32ac4fa commit 1ecc3a5579492c65ea2406db7320bb1d5f510541 @zeha zeha committed Mar 19, 2015
Showing with 49 additions and 46 deletions.
  1. +49 −46 pdns/tcpreceiver.cc
View
@@ -513,38 +513,13 @@ namespace {
/** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int outsock)
{
- bool noAXFRBecauseOfNSEC3Narrow=false;
- NSEC3PARAMRecordContent ns3pr;
- bool narrow;
- bool NSEC3Zone=false;
-
- DNSSECKeeper dk;
- dk.clearCaches(target);
- bool securedZone = dk.isSecuredZone(target);
- bool presignedZone = dk.isPresigned(target);
-
- if(dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
- NSEC3Zone=true;
- if(narrow) {
- L<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone.."<<endl;
- noAXFRBecauseOfNSEC3Narrow=true;
- }
- }
-
shared_ptr<DNSPacket> outpacket= getFreshAXFRPacket(q);
if(q->d_dnssecOk)
outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
-
- if(noAXFRBecauseOfNSEC3Narrow) {
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
- outpacket->setRcode(RCode::Refused);
- // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
- sendPacket(outpacket,outsock);
- return 0;
- }
-
+
L<<Logger::Error<<"AXFR of domain '"<<target<<"' initiated by "<<q->getRemote()<<endl;
+ // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
SOAData sd;
sd.db=(DNSBackend *)-1; // force uncached answer
{
@@ -555,14 +530,15 @@ int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int out
s_P=new PacketHandler;
}
- if(!s_P->getBackend()->getSOA(target, sd) || !canDoAXFR(q)) {
+ // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
+ if(!canDoAXFR(q) || !s_P->getBackend()->getSOA(target, sd)) {
L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative"<<endl;
outpacket->setRcode(9); // 'NOTAUTH'
sendPacket(outpacket,outsock);
return 0;
}
}
-
+
UeberBackend db;
sd.db=(DNSBackend *)-1; // force uncached answer
if(!db.getSOA(target, sd)) {
@@ -579,6 +555,31 @@ int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int out
return 0;
}
+ DNSSECKeeper dk;
+ dk.clearCaches(target);
+ bool securedZone = dk.isSecuredZone(target);
+ bool presignedZone = dk.isPresigned(target);
+
+ bool noAXFRBecauseOfNSEC3Narrow=false;
+ NSEC3PARAMRecordContent ns3pr;
+ bool narrow;
+ bool NSEC3Zone=false;
+ if(dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
+ NSEC3Zone=true;
+ if(narrow) {
+ L<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone '"<<target<<"' for "<<q->getRemote()<<endl;
+ noAXFRBecauseOfNSEC3Narrow=true;
+ }
+ }
+
+ if(noAXFRBecauseOfNSEC3Narrow) {
+ L<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
+ outpacket->setRcode(RCode::Refused);
+ // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
+ sendPacket(outpacket,outsock);
+ return 0;
+ }
+
TSIGRecordContent trc;
string tsigkeyname, tsigsecret;
@@ -933,22 +934,6 @@ int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
if(q->d_dnssecOk)
outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
- DNSSECKeeper dk;
- NSEC3PARAMRecordContent ns3pr;
- bool narrow;
-
- dk.clearCaches(q->qdomain);
- bool securedZone = dk.isSecuredZone(q->qdomain);
- if(dk.getNSEC3PARAM(q->qdomain, &ns3pr, &narrow)) {
- if(narrow) {
- L<<Logger::Error<<"Not doing IXFR of an NSEC3 narrow zone."<<endl;
- L<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' denied to "<<q->getRemote()<<endl;
- outpacket->setRcode(RCode::Refused);
- sendPacket(outpacket,outsock);
- return 0;
- }
- }
-
uint32_t serial = 0;
MOADNSParser mdp(q->getString());
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
@@ -974,6 +959,7 @@ int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
L<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' initiated by "<<q->getRemote()<<" with serial "<<serial<<endl;
+ // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend.
SOAData sd;
sd.db=(DNSBackend *)-1; // force uncached answer
{
@@ -984,14 +970,31 @@ int TCPNameserver::doIXFR(shared_ptr<DNSPacket> q, int outsock)
s_P=new PacketHandler;
}
- if(!s_P->getBackend()->getSOA(q->qdomain, sd) || !canDoAXFR(q)) {
+ // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first.
+ if(!canDoAXFR(q) || !s_P->getBackend()->getSOA(q->qdomain, sd)) {
L<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' failed: not authoritative"<<endl;
outpacket->setRcode(9); // 'NOTAUTH'
sendPacket(outpacket,outsock);
return 0;
}
}
+ DNSSECKeeper dk;
+ NSEC3PARAMRecordContent ns3pr;
+ bool narrow;
+
+ dk.clearCaches(q->qdomain);
+ bool securedZone = dk.isSecuredZone(q->qdomain);
+ if(dk.getNSEC3PARAM(q->qdomain, &ns3pr, &narrow)) {
+ if(narrow) {
+ L<<Logger::Error<<"Not doing IXFR of an NSEC3 narrow zone."<<endl;
+ L<<Logger::Error<<"IXFR of domain '"<<q->qdomain<<"' denied to "<<q->getRemote()<<endl;
+ outpacket->setRcode(RCode::Refused);
+ sendPacket(outpacket,outsock);
+ return 0;
+ }
+ }
+
string target = q->qdomain;
UeberBackend db;

0 comments on commit 1ecc3a5

Please sign in to comment.