]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/mastercommunicator.cc
Merge pull request #8223 from PowerDNS/omoerbeek-patch-1
[thirdparty/pdns.git] / pdns / mastercommunicator.cc
index 667cb76486be5f628674ddfb4d8a10545c24e83c..bdd13fb38bdf1f81a2fd964c0738dc568c9d66a8 100644 (file)
@@ -50,6 +50,7 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
   FindNS fns;
 
 
+  try {
   if (d_onlyNotify.size()) {
     B->lookup(QType(QType::NS), di.zone);
     while(B->get(rr))
@@ -58,13 +59,13 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
     for(set<string>::const_iterator j=nsset.begin();j!=nsset.end();++j) {
       vector<string> nsips=fns.lookup(DNSName(*j), B);
       if(nsips.empty())
-        L<<Logger::Warning<<"Unable to queue notification of domain '"<<di.zone<<"': nameservers do not resolve!"<<endl;
+        g_log<<Logger::Warning<<"Unable to queue notification of domain '"<<di.zone<<"': nameservers do not resolve!"<<endl;
       else
         for(vector<string>::const_iterator k=nsips.begin();k!=nsips.end();++k) {
           const ComboAddress caIp(*k, 53);
           if(!d_preventSelfNotification || !AddressIsUs(caIp)) {
             if(!d_onlyNotify.match(&caIp))
-              L<<Logger::Info<<"Skipped notification of domain '"<<di.zone<<"' to "<<*j<<" because it does not match only-notify."<<endl;
+              g_log<<Logger::Info<<"Skipped notification of domain '"<<di.zone<<"' to "<<*j<<" because it does not match only-notify."<<endl;
             else
               ips.insert(caIp.toStringWithPort());
           }
@@ -72,11 +73,21 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
     }
 
     for(set<string>::const_iterator j=ips.begin();j!=ips.end();++j) {
-      L<<Logger::Warning<<"Queued notification of domain '"<<di.zone<<"' to "<<*j<<endl;
+      g_log<<Logger::Warning<<"Queued notification of domain '"<<di.zone<<"' to "<<*j<<endl;
       d_nq.add(di.zone,*j);
       hasQueuedItem=true;
     }
   }
+  }
+  catch (PDNSException &ae) {
+    g_log << Logger::Error << "Error looking up name servers for " << di.zone << ", cannot notify: " << ae.reason << endl;
+    return;
+  }
+  catch (std::exception &e) {
+    g_log << Logger::Error << "Error looking up name servers for " << di.zone << ", cannot notify: " << e.what() << endl;
+    return;
+  }
+
 
   set<string> alsoNotify(d_alsoNotify);
   B->alsoNotifies(di.zone, &alsoNotify);
@@ -84,7 +95,7 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
   for(set<string>::const_iterator j=alsoNotify.begin();j!=alsoNotify.end();++j) {
     try {
       const ComboAddress caIp(*j, 53);
-      L<<Logger::Warning<<"Queued also-notification of domain '"<<di.zone<<"' to "<<caIp.toStringWithPort()<<endl;
+      g_log<<Logger::Warning<<"Queued also-notification of domain '"<<di.zone<<"' to "<<caIp.toStringWithPort()<<endl;
       if (!ips.count(caIp.toStringWithPort())) {
         ips.insert(caIp.toStringWithPort());
         d_nq.add(di.zone, caIp.toStringWithPort());
@@ -92,12 +103,12 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
       hasQueuedItem=true;
     }
     catch(PDNSException &e) {
-      L<<Logger::Warning<<"Unparseable IP in ALSO-NOTIFY metadata of domain '"<<di.zone<<"'. Warning: "<<e.reason<<endl;
+      g_log<<Logger::Warning<<"Unparseable IP in ALSO-NOTIFY metadata of domain '"<<di.zone<<"'. Warning: "<<e.reason<<endl;
     }
   }
 
   if (!hasQueuedItem)
-    L<<Logger::Warning<<"Request to queue notification for domain '"<<di.zone<<"' was processed, but no valid nameservers or ALSO-NOTIFYs found. Not notifying!"<<endl;
+    g_log<<Logger::Warning<<"Request to queue notification for domain '"<<di.zone<<"' was processed, but no valid nameservers or ALSO-NOTIFYs found. Not notifying!"<<endl;
 }
 
 
@@ -106,7 +117,7 @@ bool CommunicatorClass::notifyDomain(const DNSName &domain)
   DomainInfo di;
   UeberBackend B;
   if(!B.getDomainInfo(domain, di)) {
-    L<<Logger::Error<<"No such domain '"<<domain<<"' in our database"<<endl;
+    g_log<<Logger::Error<<"No such domain '"<<domain<<"' in our database"<<endl;
     return false;
   }
   queueNotifyDomain(di, &B);
@@ -135,12 +146,12 @@ void CommunicatorClass::masterUpdateCheck(PacketHandler *P)
   
   if(cmdomains.empty()) {
     if(d_masterschanged)
-      L<<Logger::Warning<<"No master domains need notifications"<<endl;
+      g_log<<Logger::Warning<<"No master domains need notifications"<<endl;
     d_masterschanged=false;
   }
   else {
     d_masterschanged=true;
-    L<<Logger::Error<<cmdomains.size()<<" domain"<<(cmdomains.size()>1 ? "s" : "")<<" for which we are master need"<<
+    g_log<<Logger::Error<<cmdomains.size()<<" domain"<<(cmdomains.size()>1 ? "s" : "")<<" for which we are master need"<<
       (cmdomains.size()>1 ? "" : "s")<<
       " notifications"<<endl;
   }
@@ -162,9 +173,10 @@ time_t CommunicatorClass::doNotifications()
   char buffer[1500];
   int sock;
   ssize_t size;
+  set<int> fds = {d_nsock4, d_nsock6};
 
   // receive incoming notifications on the nonblocking socket and take them off the list
-  while(waitFor2Data(d_nsock4, d_nsock6, 0, 0, &sock) > 0) {
+  while(waitForMultiData(fds, 0, 0, &sock) > 0) {
     fromlen=sizeof(from);
     size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen);
     if(size < 0)
@@ -174,17 +186,17 @@ time_t CommunicatorClass::doNotifications()
     p.setRemote(&from);
 
     if(p.parse(buffer,(size_t)size)<0) {
-      L<<Logger::Warning<<"Unable to parse SOA notification answer from "<<p.getRemote()<<endl;
+      g_log<<Logger::Warning<<"Unable to parse SOA notification answer from "<<p.getRemote()<<endl;
       continue;
     }
 
     if(p.d.rcode)
-      L<<Logger::Warning<<"Received unsuccessful notification report for '"<<p.qdomain<<"' from "<<from.toStringWithPort()<<", error: "<<RCode::to_s(p.d.rcode)<<endl;      
+      g_log<<Logger::Warning<<"Received unsuccessful notification report for '"<<p.qdomain<<"' from "<<from.toStringWithPort()<<", error: "<<RCode::to_s(p.d.rcode)<<endl;      
 
     if(d_nq.removeIf(from.toStringWithPort(), p.d.id, p.qdomain))
-      L<<Logger::Warning<<"Removed from notification list: '"<<p.qdomain<<"' to "<<from.toStringWithPort()<<" "<< (p.d.rcode ? RCode::to_s(p.d.rcode) : "(was acknowledged)")<<endl;      
+      g_log<<Logger::Warning<<"Removed from notification list: '"<<p.qdomain<<"' to "<<from.toStringWithPort()<<" "<< (p.d.rcode ? RCode::to_s(p.d.rcode) : "(was acknowledged)")<<endl;      
     else {
-      L<<Logger::Warning<<"Received spurious notify answer for '"<<p.qdomain<<"' from "<< from.toStringWithPort()<<endl;
+      g_log<<Logger::Warning<<"Received spurious notify answer for '"<<p.qdomain<<"' from "<< from.toStringWithPort()<<endl;
       //d_nq.dump();
     }
   }
@@ -200,20 +212,23 @@ time_t CommunicatorClass::doNotifications()
       try {
         ComboAddress remote(ip, 53); // default to 53
         if((d_nsock6 < 0 && remote.sin4.sin_family == AF_INET6) ||
-           (d_nsock4 < 0 && remote.sin4.sin_family == AF_INET))
+           (d_nsock4 < 0 && remote.sin4.sin_family == AF_INET)) {
+             g_log<<Logger::Warning<<"Unable to notify "<<remote.toStringWithPort()<<" for domain '"<<domain<<"', address family is disabled. Is query-local-address"<<(remote.sin4.sin_family == AF_INET ? "" : "6")<<" unset?"<<endl;
+             d_nq.removeIf(remote.toStringWithPort(), id, domain); // Remove, we'll never be able to notify
              continue; // don't try to notify what we can't!
+        }
         if(d_preventSelfNotification && AddressIsUs(remote))
           continue;
 
-        sendNotification(remote.sin4.sin_family == AF_INET ? d_nsock4 : d_nsock6, domain, remote, id); 
+        sendNotification(remote.sin4.sin_family == AF_INET ? d_nsock4 : d_nsock6, domain, remote, id);
         drillHole(domain, ip);
       }
       catch(ResolverException &re) {
-        L<<Logger::Error<<"Error trying to resolve '"<<ip<<"' for notifying '"<<domain<<"' to server: "<<re.reason<<endl;
+        g_log<<Logger::Error<<"Error trying to resolve '"<<ip<<"' for notifying '"<<domain<<"' to server: "<<re.reason<<endl;
       }
     }
     else
-      L<<Logger::Error<<"Notification for "<<domain<<" to "<<ip<<" failed after retries"<<endl;
+      g_log<<Logger::Error<<"Notification for "<<domain<<" to "<<ip<<" failed after retries"<<endl;
   }
 
   return d_nq.earliest();
@@ -228,7 +243,7 @@ void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const
   string tsigsecret64;
   string tsigsecret;
 
-  if (B.getDomainMetadata(domain, "TSIG-ALLOW-AXFR", meta) && meta.size() > 0) {
+  if (::arg().mustDo("send-signed-notify") && B.getDomainMetadata(domain, "TSIG-ALLOW-AXFR", meta) && meta.size() > 0) {
     tsigkeyname = DNSName(meta[0]);
   }
 
@@ -238,7 +253,10 @@ void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const
   pw.getHeader()->aa = true; 
 
   if (tsigkeyname.empty() == false) {
-    B.getTSIGKey(tsigkeyname, &tsigalgorithm, &tsigsecret64);
+    if (!B.getTSIGKey(tsigkeyname, &tsigalgorithm, &tsigsecret64)) {
+      g_log<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<domain<<"' not found"<<endl;
+      return;
+    }
     TSIGRecordContent trc;
     if (tsigalgorithm.toStringNoDot() == "hmac-md5")
       trc.d_algoName = DNSName(tsigalgorithm.toStringNoDot() + ".sig-alg.reg.int.");
@@ -248,7 +266,10 @@ void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const
     trc.d_fudge = 300;
     trc.d_origID=ntohs(id);
     trc.d_eRcode=0;
-    B64Decode(tsigsecret64, tsigsecret);
+    if (B64Decode(tsigsecret64, tsigsecret) == -1) {
+      g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<domain<<"'"<<endl;
+      return;
+    }
     addTSIG(pw, trc, tsigkeyname, tsigsecret, "", false);
   }
 
@@ -278,11 +299,16 @@ bool CommunicatorClass::justNotified(const DNSName &domain, const string &ip)
 
 void CommunicatorClass::makeNotifySockets()
 {
-  d_nsock4 = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true, ::arg().mustDo("non-local-bind"));
-  if(!::arg()["query-local-address6"].empty())
+  if(!::arg()["query-local-address"].empty()) {
+    d_nsock4 = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true, ::arg().mustDo("non-local-bind"));
+  } else {
+    d_nsock4 = -1;
+  }
+  if(!::arg()["query-local-address6"].empty()) {
     d_nsock6 = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true, ::arg().mustDo("non-local-bind"));
-  else
+  } else {
     d_nsock6 = -1;
+  }
 }
 
 void CommunicatorClass::notify(const DNSName &domain, const string &ip)