From d3ee36f26c9b04ccc6b2d7abe1c8dd37f6a3d28e Mon Sep 17 00:00:00 2001 From: bert hubert Date: Wed, 1 Jun 2016 16:14:35 +0200 Subject: [PATCH] more wip --- pdns/communicator.cc | 2 +- pdns/communicator.hh | 7 +- pdns/dynhandler.cc | 2 +- pdns/slavecommunicator.cc | 343 +++++++++++++++++++------------------- pdns/ws-auth.cc | 2 +- 5 files changed, 182 insertions(+), 174 deletions(-) diff --git a/pdns/communicator.cc b/pdns/communicator.cc index cba4180e2..daf405a2e 100644 --- a/pdns/communicator.cc +++ b/pdns/communicator.cc @@ -52,7 +52,7 @@ void CommunicatorClass::retrievalLoopThread(void) sr=d_suckdomains.front(); d_suckdomains.pop_front(); } - suck(sr.domain, sr.master, sr.currentSerial ? &sr.currentSerial : 0); + suck(sr.domain, sr.master); } } diff --git a/pdns/communicator.hh b/pdns/communicator.hh index a1e84319f..767410a27 100644 --- a/pdns/communicator.hh +++ b/pdns/communicator.hh @@ -46,7 +46,6 @@ struct SuckRequest { DNSName domain; string master; - uint32_t currentSerial; bool operator<(const SuckRequest& b) const { return tie(domain, master) < tie(b.domain, b.master); @@ -165,7 +164,7 @@ public: void drillHole(const DNSName &domain, const string &ip); bool justNotified(const DNSName &domain, const string &ip); - void addSuckRequest(const DNSName &domain, const string &master, uint32_t curser); + void addSuckRequest(const DNSName &domain, const string &master); void addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote); void addTrySuperMasterRequest(DNSPacket *p); void notify(const DNSName &domain, const string &ip); @@ -191,8 +190,8 @@ private: map,time_t>d_holes; pthread_mutex_t d_holelock; void launchRetrievalThreads(); - void suck(const DNSName &domain, const string &remote, uint32_t* curser); - void ixfrSuck(const DNSName &domain, const string &remote, uint32_t curser); + void suck(const DNSName &domain, const string &remote); + void ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote); void slaveRefresh(PacketHandler *P); void masterUpdateCheck(PacketHandler *P); diff --git a/pdns/dynhandler.cc b/pdns/dynhandler.cc index f1e6833ee..9c4a8707b 100644 --- a/pdns/dynhandler.cc +++ b/pdns/dynhandler.cc @@ -251,7 +251,7 @@ string DLNotifyRetrieveHandler(const vector&parts, Utility::pid_t ppid) return "Domain '"+domain.toString()+"' is not a slave domain (or has no master defined)"; random_shuffle(di.masters.begin(), di.masters.end()); - Communicator.addSuckRequest(domain, di.masters.front(), 0); // we don't know serial + Communicator.addSuckRequest(domain, di.masters.front()); return "Added retrieval request for '"+domain.toString()+"' from master "+di.masters.front(); } diff --git a/pdns/slavecommunicator.cc b/pdns/slavecommunicator.cc index 86e0de915..4280361d4 100644 --- a/pdns/slavecommunicator.cc +++ b/pdns/slavecommunicator.cc @@ -50,13 +50,12 @@ using boost::scoped_ptr; -void CommunicatorClass::addSuckRequest(const DNSName &domain, const string &master, uint32_t curser) +void CommunicatorClass::addSuckRequest(const DNSName &domain, const string &master) { Lock l(&d_lock); SuckRequest sr; sr.domain = domain; sr.master = master; - sr.currentSerial = curser; pair res; res=d_suckdomains.push_back(sr); @@ -66,7 +65,22 @@ void CommunicatorClass::addSuckRequest(const DNSName &domain, const string &mast } } -void CommunicatorClass::ixfrSuck(const DNSName &domain, const string &remote, uint32_t curser) +struct ZoneStatus +{ + bool isDnssecZone{false}; + bool isPresigned{false}; + bool isNSEC3 {false}; + bool optOutFlag {false}; + NSEC3PARAMRecordContent ns3pr; + + bool isNarrow{false}; + unsigned int soa_serial{0}; + set nsset, qnames, secured; + uint32_t domain_id; +}; + + +void CommunicatorClass::ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote) { UeberBackend B; // fresh UeberBackend @@ -80,31 +94,15 @@ void CommunicatorClass::ixfrSuck(const DNSName &domain, const string &remote, ui L<(DNSName("."), DNSName("."), st); - auto deltas = getIXFRDeltas(ComboAddress(remote, 53), domain, dr, tt); - cout<<"Got "<startTransaction(domain, -1); for(const auto& gone : diff) { - cerr<<"Removing "<replaceRRSet(di.id, gone.first+domain, QType(gone.second), vector()); } + cout<<"Removed "<, vector> replacement; @@ -136,18 +135,18 @@ void CommunicatorClass::ixfrSuck(const DNSName &domain, const string &remote, ui DNSResourceRecord dr(add); dr.qname += domain; dr.domain_id=di.id; + if(add.d_type == QType::SOA) + cout<<"New SOA: "<getZoneRepresentation()<content<content<replaceRRSet(di.id, rep.first.first+domain, QType(rep.first.second), rep.second); } - cerr<<"And commit!"<commitTransaction(); } - - exit(1); - } catch(std::exception& p) { cerr<<"Got exception: "< doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr, scoped_ptr& pdl, ZoneStatus& zs) +{ + vector rrs; + AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr); + Resolver::res_t recs; + bool first=true; + bool firstNSEC3{true}; + bool soa_received {false}; + while(retriever.getChunk(recs)) { + if(first) { + L<qtype.getCode() == QType::OPT || i->qtype.getCode() == QType::TSIG) // ignore EDNS0 & TSIG + continue; + + if(!i->qname.isPartOf(domain)) { + L<qname<<"'|"<qtype.getName()<<" during AXFR of zone '"< out; + if(!pdl || !pdl->axfrfilter(raddr, domain, *i, out)) { + out.push_back(*i); + } + + for(DNSResourceRecord& rr : out) { + switch(rr.qtype.getCode()) { + case QType::NSEC3PARAM: { + zs.ns3pr = NSEC3PARAMRecordContent(rr.content); + zs.isDnssecZone = zs.isNSEC3 = true; + zs.isNarrow = false; + continue; + } + case QType::NSEC3: { + NSEC3RecordContent ns3rc(rr.content); + if (firstNSEC3) { + zs.isDnssecZone = zs.isPresigned = true; + firstNSEC3 = false; + } else if (zs.optOutFlag != (ns3rc.d_flags & 1)) + throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported."); + zs.optOutFlag = ns3rc.d_flags & 1; + if (ns3rc.d_set.count(QType::NS) && !(rr.qname==domain)) { + DNSName hashPart = DNSName(toLower(rr.qname.makeRelative(domain).toString())); + zs.secured.insert(hashPart); + } + continue; + } + case QType::NSEC: { + zs.isDnssecZone = zs.isPresigned = true; + continue; + } + case QType::SOA: { + if(soa_received) + continue; //skip the last SOA + SOAData sd; + fillSOAData(rr.content,sd); + zs.soa_serial = sd.serial; + soa_received = true; + break; + } + case QType::NS: { + if(rr.qname!=domain) + zs.nsset.insert(rr.qname); + break; + } + default: + break; + } + + zs.qnames.insert(rr.qname); + + rr.domain_id=zs.domain_id; + rrs.push_back(rr); + } + } + } + return rrs; +} + +void CommunicatorClass::suck(const DNSName &domain, const string &remote) { - if(curser) - return ixfrSuck(domain, remote, *curser); L< nsset, qnames, secured; - vector rrs; - - ComboAddress raddr(remote, 53); - AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr); - Resolver::res_t recs; - while(retriever.getChunk(recs)) { - if(first) { - L<qtype.getCode() == QType::OPT || i->qtype.getCode() == QType::TSIG) // ignore EDNS0 & TSIG - continue; - - if(!i->qname.isPartOf(domain)) { - L<qname<<"'|"<qtype.getName()<<" during AXFR of zone '"< out; - if(!pdl || !pdl->axfrfilter(raddr, domain, *i, out)) { - out.push_back(*i); - } - - for(DNSResourceRecord& rr : out) { - switch(rr.qtype.getCode()) { - case QType::NSEC3PARAM: { - ns3pr = NSEC3PARAMRecordContent(rr.content); - isDnssecZone = isNSEC3 = true; - isNarrow = false; - continue; - } - case QType::NSEC3: { - NSEC3RecordContent ns3rc(rr.content); - if (firstNSEC3) { - isDnssecZone = isPresigned = true; - firstNSEC3 = false; - } else if (optOutFlag != (ns3rc.d_flags & 1)) - throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported."); - optOutFlag = ns3rc.d_flags & 1; - if (ns3rc.d_set.count(QType::NS) && !(rr.qname==domain)) { - DNSName hashPart = DNSName(toLower(rr.qname.makeRelative(domain).toString())); - secured.insert(hashPart); - } - continue; - } - case QType::NSEC: { - isDnssecZone = isPresigned = true; - continue; - } - case QType::SOA: { - if(soa_received) - continue; //skip the last SOA - SOAData sd; - fillSOAData(rr.content,sd); - soa_serial = sd.serial; - soa_received = true; - break; - } - case QType::NS: { - if(rr.qname!=domain) - nsset.insert(rr.qname); - break; - } - default: - break; - } - - qnames.insert(rr.qname); - - rr.domain_id=domain_id; - rrs.push_back(rr); - } - } + else if(di.serial) { + vector meta; + B.getDomainMetadata(domain, "IXFR", meta); + if(!meta.empty() && meta[0]=="1") + return ixfrSuck(domain, tt, laddr, raddr); } - if(isNSEC3) { - ns3pr.d_flags = optOutFlag ? 1 : 0; + vector rrs = doAxfr(raddr, domain, tt, laddr, pdl, zs); + + if(zs.isNSEC3) { + zs.ns3pr.d_flags = zs.optOutFlag ? 1 : 0; } - - if(!isPresigned) { + if(!zs.isPresigned) { DNSSECKeeper::keyset_t keys = dk.getKeys(domain); if(!keys.empty()) { - isDnssecZone = true; - isNSEC3 = hadNSEC3; - ns3pr = hadNs3pr; - optOutFlag = (hadNs3pr.d_flags & 1); - isNarrow = hadNarrow; + zs.isDnssecZone = true; + zs.isNSEC3 = hadNSEC3; + zs.ns3pr = hadNs3pr; + zs.optOutFlag = (hadNs3pr.d_flags & 1); + zs.isNarrow = hadNarrow; } } - - if(isDnssecZone) { - if(!isNSEC3) + if(zs.isDnssecZone) { + if(!zs.isNSEC3) L<startTransaction(domain, domain_id); + transaction=di.backend->startTransaction(domain, zs.domain_id); L<feedRecord(rr, &ordername); } else di.backend->feedRecord(rr); @@ -477,19 +487,19 @@ void CommunicatorClass::suck(const DNSName &domain, const string &remote, uint32 // Insert empty non-terminals if(doent && !nonterm.empty()) { - if (isNSEC3) { - di.backend->feedEnts3(domain_id, domain, nonterm, ns3pr, isNarrow); + if (zs.isNSEC3) { + di.backend->feedEnts3(zs.domain_id, domain, nonterm, zs.ns3pr, zs.isNarrow); } else - di.backend->feedEnts(domain_id, nonterm); + di.backend->feedEnts(zs.domain_id, nonterm); } di.backend->commitTransaction(); transaction = false; - di.backend->setFresh(domain_id); + di.backend->setFresh(zs.domain_id); PC.purge(domain.toString()+"$"); - L< localaddr; SuckRequest sr; sr.domain=di.zone; - sr.currentSerial = di.serial; if(di.masters.empty()) // slave domains w/o masters are ignored continue; // remove unfresh domains already queued for AXFR, no sense polling them again @@ -785,13 +794,13 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) } else { L<setSuccessResult("Added retrieval request for '"+zonename.toString()+"' from master "+di.masters.front()); } -- 2.40.0