]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/notify.cc
auth: switch circleci mssql image
[thirdparty/pdns.git] / pdns / notify.cc
index b421fa2043370bb7a3c74ad2e5cc48497ea2773f..1ec0c11d64ee7baed789f5b747c5eca93f69fce6 100644 (file)
@@ -24,8 +24,8 @@
 #endif
 #include <bitset>
 #include "dnsparser.hh"
+#include "dns_random.hh"
 #include "iputils.hh"
-#undef L
 #include <boost/program_options.hpp>
 
 #include <boost/format.hpp>
@@ -37,7 +37,7 @@
 #include "mplexer.hh"
 #include "statbag.hh"
 #include "arguments.hh"
-
+#include "version.hh"
 #include "namespaces.hh"
 using namespace ::boost::multi_index;
 #include "namespaces.hh"
@@ -53,12 +53,15 @@ ArgvMap &arg()
 }
 
 void usage() {
-  cerr<<"Syntax: pdns_notify IP_ADDRESS[:PORT] DOMAIN"<<endl;
+  cerr<<"Syntax: pdns_notify IP_ADDRESS/HOSTNAME[:PORT] DOMAIN"<<endl;
 }
 
 int main(int argc, char** argv)
 try
 {
+  set<ComboAddress> addrs;
+  ::arg().set("rng")="auto";
+  ::arg().set("entropy-source")="/dev/urandom";
 
   for(int n=1 ; n < argc; ++n) {
     if ((string) argv[n] == "--help") {
@@ -77,39 +80,89 @@ try
     exit(1);
   }
 
-  int sock = socket(AF_INET, SOCK_DGRAM, 0);
-  if(sock < 0)
-    throw runtime_error("Creating socket for incoming packets: "+stringerror());
-
+  int sock = -1;
 
  // ComboAddress local("127.0.0.1", (int)0);
 //  if(::bind(sock, (struct sockaddr*) &local, local.getSocklen()) < 0) 
 //    throw runtime_error("Failed to bind local socket to address "+local.toString()+": "+stringerror());
 
-  ComboAddress pdns(argv[1], 53);
-  if(connect(sock, (struct sockaddr*) &pdns, pdns.getSocklen()) < 0) 
-    throw runtime_error("Failed to connect PowerDNS socket to address "+pdns.toString()+": "+stringerror());
-  
-  vector<uint8_t> outpacket;
-  DNSPacketWriter pw(outpacket, DNSName(argv[2]), QType::SOA, 1, Opcode::Notify);
-  pw.getHeader()->id = random();
+  try {
+     addrs.emplace(ComboAddress{argv[1], 53});
+  } catch (PDNSException &ex) {
+     /* needs resolving, maybe */
+     struct addrinfo *info;
+     vector<string> parts;
+     boost::split(parts, argv[1], [](char c){return c == ':';});
+     if (parts.size() == 1)
+       parts.push_back("domain");
+     else if (parts.size() != 2)
+       throw runtime_error("Invalid hostname:port syntax");
+     if (getaddrinfo(parts[0].c_str(), parts[1].c_str(), NULL, &info) < 0)
+       throw runtime_error("Cannot resolve '" + string(argv[1]) +"'");
+     for(auto ptr = info; ptr != NULL; ptr = ptr->ai_next)
+       addrs.emplace(ComboAddress{ptr->ai_addr, ptr->ai_addrlen});
+  }
 
+  for(const auto &addr: addrs) {
+    if (sock > -1)
+      (void)close(sock);
+    sock = socket(addr.sin4.sin_family, SOCK_DGRAM, 0);
+    if(sock < 0)
+      throw runtime_error("Creating socket for incoming packets: "+stringerror());
+    if(connect(sock, (struct sockaddr*)&addr, addr.getSocklen()) < 0) {
+      cerr<<"Failed to connect to address "+addr.toStringWithPort()+": "+stringerror()<<endl;
+      continue;
+    }
+    vector<uint8_t> outpacket;
+    DNSPacketWriter pw(outpacket, DNSName(argv[2]), QType::SOA, 1, Opcode::Notify);
+    pw.getHeader()->id = dns_random(UINT16_MAX);
 
-  if(send(sock, &outpacket[0], outpacket.size(), 0) < 0) {
-    throw runtime_error("Unable to send notify to PowerDNS: "+stringerror());
-  }
-  
-  char buffer[1500];
+    if(send(sock, &outpacket[0], outpacket.size(), 0) < 0) {
+      cerr<<"Unable to send notify to "<<addr.toStringWithPort()<<": "+stringerror()<<endl;
+      continue;
+    }
 
-  int len=recv(sock, buffer, sizeof(buffer),0);
-  if(len < 0)
-    throw runtime_error("Unable to receive notification response from PowerDNS: "+stringerror());
+    char buffer[1500];
+    fd_set rfds;
+    FD_ZERO(&rfds);
+    FD_SET(sock, &rfds);
+    fd_set errfds;
+    FD_ZERO(&errfds);
+    FD_SET(sock, &errfds);
+    int len;
+    struct timeval tv;
+    bool timeout = true;
+
+    for(int tries=0; tries<60; tries++) {
+      tv.tv_sec = 1;
+      tv.tv_usec = 0;
+      if ((len = select(sock+1, &rfds, nullptr, &errfds, &tv)) > 0) {
+        len = recv(sock, buffer, sizeof(buffer), 0);
+        timeout = false;
+        break;
+      }
+    }
 
-  string packet(buffer, len);
-  MOADNSParser mdp(false, packet);
+    if(len < 0) {
+      cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": "+stringerror()<<endl;
+      continue;
+    } else if (timeout) {
+      cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": Timed out"<<endl;
+      continue;
+    } else if (len == 0) {
+      cerr<<"Unable to receive notification response from "<<addr.toStringWithPort()<<": EOF"<<endl;
+      continue;
+    }
 
-  cerr<<"Received notification response with error: "<<RCode::to_s(mdp.d_header.rcode)<<endl;
-  cerr<<"For: '"<<mdp.d_qname<<"'"<<endl;
+    string packet(buffer, len);
+    MOADNSParser mdp(false, packet);
+
+    if (mdp.d_header.rcode == 0)
+      cerr<<"Successfully notified "<<addr.toStringWithPort()<<endl;
+    else
+      cerr<<"Received notification response with error from "<<addr.toStringWithPort()<<": "<<RCode::to_s(mdp.d_header.rcode)<<endl;
+    cerr<<"For: '"<<mdp.d_qname<<"'"<<endl;
+  }
 }
 catch(std::exception& e)
 {