]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/slavecommunicator.cc
auth: Wrap pthread_ objects
[thirdparty/pdns.git] / pdns / slavecommunicator.cc
index 53b66197c320521a7378cc98ce37bcf422c84ae5..0638c51e1c5f319cb2f06d5e5f1360a4098a726e 100644 (file)
 #include "common_startup.hh"
 
 #include "ixfr.hh"
-using boost::scoped_ptr;
-
 
 void CommunicatorClass::addSuckRequest(const DNSName &domain, const ComboAddress& master)
 {
-  Lock l(&d_lock);
+  std::lock_guard<std::mutex> l(d_lock);
   SuckRequest sr;
   sr.domain = domain;
   sr.master = master;
@@ -80,7 +78,7 @@ struct ZoneStatus
 };
 
 
-void CommunicatorClass::ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, scoped_ptr<AuthLua4>& pdl,
+void CommunicatorClass::ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, unique_ptr<AuthLua4>& pdl,
                                  ZoneStatus& zs, vector<DNSRecord>* axfr)
 {
   UeberBackend B; // fresh UeberBackend
@@ -141,8 +139,8 @@ void CommunicatorClass::ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, c
         vector<DNSRecord> rrset;
         {
           DNSZoneRecord zrr;
-          B.lookup(QType(g.first.second), g.first.first+domain, 0, di.id);
-          while(B.get(zrr)) {
+          di.backend->lookup(QType(g.first.second), g.first.first+domain, di.id);
+          while(di.backend->get(zrr)) {
             zrr.dr.d_name.makeUsRelative(domain);
             rrset.push_back(zrr.dr);
           }
@@ -239,15 +237,16 @@ static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResou
    5) It updates the Empty Non Terminals
 */
 
-static vector<DNSResourceRecord> doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr,  scoped_ptr<AuthLua4>& pdl, ZoneStatus& zs)
+static vector<DNSResourceRecord> doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr,  unique_ptr<AuthLua4>& pdl, ZoneStatus& zs)
 {
+  uint16_t axfr_timeout=::arg().asNum("axfr-fetch-timeout");
   vector<DNSResourceRecord> rrs;
-  AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024);
+  AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024, axfr_timeout);
   Resolver::res_t recs;
   bool first=true;
   bool firstNSEC3{true};
   bool soa_received {false};
-  while(retriever.getChunk(recs)) {
+  while(retriever.getChunk(recs, nullptr, axfr_timeout)) {
     if(first) {
       g_log<<Logger::Error<<"AXFR started for '"<<domain<<"'"<<endl;
       first=false;
@@ -296,7 +295,7 @@ static vector<DNSResourceRecord> doAxfr(const ComboAddress& raddr, const DNSName
 void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
 {
   {
-    Lock l(&d_lock);
+    std::lock_guard<std::mutex> l(d_lock);
     if(d_inprogress.count(domain)) {
       return; 
     }
@@ -339,7 +338,7 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
     }
 
 
-    scoped_ptr<AuthLua4> pdl;
+    unique_ptr<AuthLua4> pdl{nullptr};
     vector<string> scripts;
     string script=::arg()["lua-axfr-script"];
     if(B.getDomainMetadata(domain, "LUA-AXFR-SCRIPT", scripts) && !scripts.empty()) {
@@ -351,7 +350,7 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
     }
     if(!script.empty()){
       try {
-        pdl.reset(new AuthLua4());
+        pdl = make_unique<AuthLua4>();
         pdl->loadFile(script);
         g_log<<Logger::Info<<"Loaded Lua script '"<<script<<"' to edit the incoming AXFR of '"<<domain<<"'"<<endl;
       }
@@ -597,10 +596,20 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
     di.backend->setFresh(zs.domain_id);
     purgeAuthCaches(domain.toString()+"$");
 
-
     g_log<<Logger::Error<<"AXFR done for '"<<domain<<"', zone committed with serial number "<<zs.soa_serial<<endl;
-    if(::arg().mustDo("slave-renotify"))
-      notifyDomain(domain);
+
+    // Send slave re-notifications
+    bool doNotify;
+    vector<string> meta;
+    if(B.getDomainMetadata(domain, "SLAVE-RENOTIFY", meta ) && !meta.empty()) {
+      doNotify=(meta.front() == "1");
+    } else {
+      doNotify=(::arg().mustDo("slave-renotify"));
+    }
+    if(doNotify) {
+      notifyDomain(domain, &B);
+    }
+
   }
   catch(DBException &re) {
     g_log<<Logger::Error<<"Unable to feed record during incoming AXFR of '" << domain<<"': "<<re.reason<<endl;
@@ -625,7 +634,7 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote)
   }
   catch(ResolverException &re) {
     {
-      Lock l(&d_lock);
+      std::lock_guard<std::mutex> l(d_lock);
       // The AXFR probably failed due to a problem on the master server. If SOA-checks against this master
       // still succeed, we would constantly try to AXFR the zone. To avoid this, we add the zone to the list of
       // failed slave-checks. This will suspend slave-checks (and subsequent AXFR) for this zone for some time.
@@ -685,7 +694,7 @@ struct SlaveSenderReceiver
 
   Identifier send(DomainNotificationInfo& dni)
   {
-    random_shuffle(dni.di.masters.begin(), dni.di.masters.end());
+    shuffle(dni.di.masters.begin(), dni.di.masters.end(), pdns::dns_random_engine());
     try {
       return std::make_tuple(dni.di.zone,
                              *dni.di.masters.begin(),
@@ -720,7 +729,7 @@ struct SlaveSenderReceiver
 
 void CommunicatorClass::addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote)
 {
-  Lock l(&d_lock);
+  std::lock_guard<std::mutex> l(d_lock);
   DomainInfo ours = di;
   ours.backend = 0;
 
@@ -739,10 +748,10 @@ void CommunicatorClass::addSlaveCheckRequest(const DomainInfo& di, const ComboAd
   d_any_sem.post(); // kick the loop!
 }
 
-void CommunicatorClass::addTrySuperMasterRequest(DNSPacket *p)
+void CommunicatorClass::addTrySuperMasterRequest(const DNSPacket& p)
 {
-  Lock l(&d_lock);
-  DNSPacket ours = *p;
+  std::lock_guard<std::mutex> l(d_lock);
+  DNSPacket ours = p;
   if(d_potentialsupermasters.insert(ours).second)
     d_any_sem.post(); // kick the loop!
 }
@@ -757,8 +766,9 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
   vector<DomainNotificationInfo> sdomains;
   set<DNSPacket, cmp> trysuperdomains;
   {
-    Lock l(&d_lock);
+    std::lock_guard<std::mutex> l(d_lock);
     set<DomainInfo> requeue;
+    rdomains.reserve(d_tocheck.size());
     for(const auto& di: d_tocheck) {
       if(d_inprogress.count(di.zone)) {
         g_log<<Logger::Debug<<"Got NOTIFY for "<<di.zone<<" while AXFR in progress, requeueing SOA check"<<endl;
@@ -788,14 +798,15 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
     TSIGRecordContent trc;
     DNSName tsigkeyname;
     dp.getTSIGDetails(&trc, &tsigkeyname);
-    P->trySuperMasterSynchronous(&dp, tsigkeyname); // FIXME could use some error loging
+    P->trySuperMasterSynchronous(dp, tsigkeyname); // FIXME could use some error logging
   }
   if(rdomains.empty()) { // if we have priority domains, check them first
     B->getUnfreshSlaveInfos(&rdomains);
   }
+  sdomains.reserve(rdomains.size());
   DNSSECKeeper dk(B); // NOW HEAR THIS! This DK uses our B backend, so no interleaved access!
   {
-    Lock l(&d_lock);
+    std::lock_guard<std::mutex> l(d_lock);
     domains_by_name_t& nameindex=boost::multi_index::get<IDTag>(d_suckdomains);
     time_t now = time(0);
 
@@ -850,20 +861,20 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
         dni.localaddr.sin4.sin_family = 0;
       }
 
-      sdomains.push_back(dni);
+      sdomains.push_back(std::move(dni));
     }
   }
   if(sdomains.empty())
   {
     if(d_slaveschanged) {
-      Lock l(&d_lock);
+      std::lock_guard<std::mutex> l(d_lock);
       g_log<<Logger::Warning<<"No new unfresh slave domains, "<<d_suckdomains.size()<<" queued for AXFR already, "<<d_inprogress.size()<<" in progress"<<endl;
     }
     d_slaveschanged = !rdomains.empty();
     return;
   }
   else {
-    Lock l(&d_lock);
+    std::lock_guard<std::mutex> l(d_lock);
     g_log<<Logger::Warning<<sdomains.size()<<" slave domain"<<(sdomains.size()>1 ? "s" : "")<<" need"<<
       (sdomains.size()>1 ? "" : "s")<<
       " checking, "<<d_suckdomains.size()<<" queued for AXFR"<<endl;
@@ -908,7 +919,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
 
     if(!ssr.d_freshness.count(di.id)) { // If we don't have an answer for the domain
       uint64_t newCount = 1;
-      Lock l(&d_lock);
+      std::lock_guard<std::mutex> l(d_lock);
       const auto failedEntry = d_failedSlaveRefresh.find(di.zone);
       if (failedEntry != d_failedSlaveRefresh.end())
         newCount = d_failedSlaveRefresh[di.zone].first + 1;
@@ -925,7 +936,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
     }
 
     {
-      Lock l(&d_lock);
+      std::lock_guard<std::mutex> l(d_lock);
       const auto wasFailedDomain = d_failedSlaveRefresh.find(di.zone);
       if (wasFailedDomain != d_failedSlaveRefresh.end())
         d_failedSlaveRefresh.erase(di.zone);
@@ -947,7 +958,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
     else if(hasSOA && theirserial == ourserial) {
       uint32_t maxExpire=0, maxInception=0;
       if(dk.isPresigned(di.zone)) {
-        B->lookup(QType(QType::RRSIG), di.zone); // can't use DK before we are done with this lookup!
+        B->lookup(QType(QType::RRSIG), di.zone, di.id); // can't use DK before we are done with this lookup!
         DNSZoneRecord zr;
         while(B->get(zr)) {
           auto rrsig = getRR<RRSIGRecordContent>(zr.dr);