]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
import axfr-lock patch by Ruben d'Arco. This patch aims to prevent slaving zones...
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Fri, 12 Oct 2012 09:14:49 +0000 (09:14 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Fri, 12 Oct 2012 09:14:49 +0000 (09:14 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2807 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/communicator.cc
pdns/communicator.hh
pdns/mastercommunicator.cc
pdns/misc.cc
pdns/resolver.cc
pdns/resolver.hh
pdns/slavecommunicator.cc

index a5209c5ee3756c8956b2ed04306c2179b9a991e0..28aa63c2badc0dc26c70a0a889d5259432a5db45 100644 (file)
@@ -45,7 +45,6 @@ void CommunicatorClass::retrievalLoopThread(void)
         continue;
        
       sr=d_suckdomains.front();
-      d_suckdomains.pop_front();
     }
     try {
       suck(sr.domain,sr.master);
@@ -53,16 +52,23 @@ void CommunicatorClass::retrievalLoopThread(void)
     catch(AhuException& ae) {
       cerr<<"Error: "<<ae.reason<<endl;
     }
+
+    {
+      Lock l(&d_lock);
+      domains_by_name_t& uqIndex = d_suckdomains.get<IDTag>();
+      uqIndex.erase(sr);
+    }
   }
+
 }
 
 
 void CommunicatorClass::go()
 {
   pthread_t tid;
-  pthread_create(&tid,0,&launchhelper,this);
+  pthread_create(&tid,0,&launchhelper,this); // Starts CommunicatorClass::mainloop()
   for(int n=0; n < ::arg().asNum("retrieval-threads"); ++n)
-    pthread_create(&tid, 0, &retrieveLaunchhelper, this);
+    pthread_create(&tid, 0, &retrieveLaunchhelper, this); // Starts CommunicatorClass::retrievalLoopThread()
 
 }
 
index 2d322c79e30b48b9cdb8ac100856221bc90c4fd0..d2e15a6d6b117e60e952e703121be82cc466984b 100644 (file)
@@ -60,6 +60,7 @@ typedef multi_index_container<
     ordered_unique<tag<IDTag>, identity<SuckRequest> >
   >
 > UniQueue;
+typedef UniQueue::index<IDTag>::type domains_by_name_t;
 
 class NotificationQueue
 {
@@ -78,13 +79,13 @@ public:
   
   bool removeIf(const string &remote, uint16_t id, const string &domain)
   {
-    for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i) {
+    for(d_nqueue_t::iterator i=d_nqueue.begin(); i!=d_nqueue.end(); ++i) {
       //      cout<<i->id<<" "<<id<<endl;
       //cout<<i->ip<<" "<<remote<<endl;
       //cout<<i->domain<<" "<<domain<<endl;
       string remoteIP, ourIP, port;
-      tie(remoteIP, port)=splitField(remote,':');
-      tie(ourIP, port)=splitField(i->ip,':');
+      tie(remoteIP, port)=splitField(remote, ':');
+      tie(ourIP, port)=splitField(i->ip, ':');
       if(i->id==id && ourIP == remoteIP && i->domain==domain) {
         d_nqueue.erase(i);
         return true;
@@ -131,7 +132,7 @@ private:
     time_t next;
   };
 
-  typedef std::list<NotificationRequest>d_nqueue_t;
+  typedef std::list<NotificationRequest> d_nqueue_t;
   d_nqueue_t d_nqueue;
 
 };
@@ -156,12 +157,14 @@ public:
   
   void drillHole(const string &domain, const string &ip);
   bool justNotified(const string &domain, const string &ip);
-  void addSuckRequest(const string &domain, const string &master, bool priority=false);
+  void addSuckRequest(const string &domain, const string &master);
   void addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote);
   void addTrySuperMasterRequest(DNSPacket *p);
   void notify(const string &domain, const string &ip);
   void mainloop();
   void retrievalLoopThread();
+  void sendNotification(int sock, const string &domain, const ComboAddress& remote, uint16_t id);
+
   static void *launchhelper(void *p)
   {
     static_cast<CommunicatorClass *>(p)->mainloop();
index 3ac1fc8462b08a6493bfc2fd0f719084002a100f..8a72e31a21956306f1733724b4e8c3aaa20e3f34 100644 (file)
@@ -129,10 +129,9 @@ time_t CommunicatorClass::doNotifications()
   ComboAddress from;
   Utility::socklen_t fromlen=sizeof(from);
   char buffer[1500];
-  int size;
-  // receive incoming notifications on the nonblocking socket and take them off the list
-  int sock;
+  int size, sock;
 
+  // receive incoming notifications on the nonblocking socket and take them off the list
   while(waitFor2Data(d_nsock4, d_nsock6, 0, 0, &sock) > 0) {
     size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen);
     if(size < 0)
@@ -183,6 +182,18 @@ time_t CommunicatorClass::doNotifications()
   return d_nq.earliest();
 }
 
+void CommunicatorClass::sendNotification(int sock, const string& domain, const ComboAddress& remote, uint16_t id)
+{
+  vector<uint8_t> packet;
+  DNSPacketWriter pw(packet, domain, QType::SOA, 1, Opcode::Notify);
+  pw.getHeader()->id = id;
+  pw.getHeader()->aa = true; 
+
+  if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) {
+    throw ResolverException("Unable to send notify to "+remote.toStringWithPort()+": "+stringerror());
+  }
+}
+
 void CommunicatorClass::drillHole(const string &domain, const string &ip)
 {
   Lock l(&d_holelock);
index f822673e146541d936caefe8a8f73ea3a0e68f7f..42b73b3c2e3afe016cabe744a615cdc61c2703f2 100644 (file)
@@ -322,7 +322,7 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds)
   return ret;
 }
 
-// returns -1 in case if error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
+// returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
 int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
 {
   int ret;
index 7689c5b313afb73c641064d74af4190fee19bf8b..9cc3b8487c80a8dcfe8e744a8d45441b6345602a 100644 (file)
 
 #include "namespaces.hh"
 
-int sendNotification(int sock, const string& domain, const ComboAddress& remote, uint16_t id)
-{
-  vector<uint8_t> packet;
-  DNSPacketWriter pw(packet, domain, QType::SOA, 1, Opcode::Notify);
-  pw.getHeader()->id = id;
-  pw.getHeader()->aa = true; 
-
-  if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen())<0) {
-    throw ResolverException("Unable to send notify to "+remote.toStringWithPort()+": "+stringerror());
-  }
-  return true;
-}
-
 int makeQuerySocket(const ComboAddress& local, bool udpOrTCP)
 {
   ComboAddress ourLocal(local);
index 391de613be43e4073734b35002658ec9951ce70c..3633bf2ddc12e40a00be966b9ed376135cb89c50 100644 (file)
@@ -44,9 +44,6 @@ public:
   ResolverException(const string &reason) : AhuException(reason){}
 };
 
-// send out an update notification for a domain to an IPv4/v6 address
-int sendNotification(int sock, const string &domain, const ComboAddress& remote, uint16_t id);
-
 // make an IPv4 or IPv6 query socket 
 int makeQuerySocket(const ComboAddress& local, bool udpOrTCP);
 //! Resolver class. Can be used synchronously and asynchronously, over IPv4 and over IPv6 (simultaneously)
index 368433a4cbd48995e85b4e7e479b63c784388d14..04bf34d56bce4d4eea03f3baf693ed2a7e5827c8 100644 (file)
@@ -48,20 +48,15 @@ template<typename T> bool rfc1982LessThan(T a, T b)
   return ((signed)(a - b)) < 0;
 }
 
-void CommunicatorClass::addSuckRequest(const string &domain, const string &master, bool priority)
+void CommunicatorClass::addSuckRequest(const string &domain, const string &master)
 {
   Lock l(&d_lock);
-  
   SuckRequest sr;
   sr.domain = domain;
   sr.master = master;
   pair<UniQueue::iterator, bool>  res;
-  if(priority) {
-    res=d_suckdomains.push_front(sr);
-  }
-  else {
-    res=d_suckdomains.push_back(sr);
-  }
+
+  res=d_suckdomains.push_back(sr);
   
   if(res.second) {
     d_suck_sem.post();
@@ -484,7 +479,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
 {
   UeberBackend *B=dynamic_cast<UeberBackend *>(P->getBackend());
   vector<DomainInfo> rdomains;
-  vector<DomainNotificationInfo > sdomains; // the bool is for 'presigned'
+  vector<DomainNotificationInfo> sdomains; // the bool is for 'presigned'
   vector<DNSPacket> trysuperdomains;
   
   {
@@ -513,7 +508,6 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
   DNSSECKeeper dk(B); // NOW HEAR THIS! This DK uses our B backend, so no interleaved access!
   {
     Lock l(&d_lock);
-    typedef UniQueue::index<IDTag>::type domains_by_name_t;
     domains_by_name_t& nameindex=boost::multi_index::get<IDTag>(d_suckdomains);
 
     BOOST_FOREACH(DomainInfo& di, rdomains) {
@@ -523,8 +517,10 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
         continue;
       // remove unfresh domains already queued for AXFR, no sense polling them again
       sr.master=*di.masters.begin();
-      if(nameindex.count(sr))
+      if(nameindex.count(sr)) {
+        L<<Logger::Warning<<"Domain "<<sr.domain<<" already queued for AXFR."<<endl;
         continue;
+      }
       DomainNotificationInfo dni;
       dni.di=di;
       dni.dnssecOk = dk.isPresigned(di.zone);