]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Split the AXFRRetriever from resolver.cc
authorPieter Lexis <pieter.lexis@powerdns.com>
Mon, 16 Mar 2020 15:53:56 +0000 (16:53 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Wed, 1 Apr 2020 09:10:22 +0000 (11:10 +0200)
ALso, this moves the `parseResult` function into the pdns::resolver
namespace

15 files changed:
pdns/Makefile.am
pdns/axfr-retriever.cc [new file with mode: 0644]
pdns/axfr-retriever.hh [new file with mode: 0644]
pdns/communicator.cc
pdns/ixfrdist.cc
pdns/ixplore.cc
pdns/recursordist/Makefile.am
pdns/recursordist/axfr-retriever.cc [new symlink]
pdns/recursordist/axfr-retriever.hh [new symlink]
pdns/resolver.cc
pdns/resolver.hh
pdns/rpzloader.cc
pdns/slavecommunicator.cc
pdns/tcpreceiver.cc
pdns/tsig-tests.cc

index 524110a07be8a0035da66cc314e16456fd9b19b5..f6a5510bd24ca65528ab6bde0b6a0e74e676c92b 100644 (file)
@@ -207,6 +207,7 @@ pdns_server_SOURCES = \
        rcpgenerator.cc \
        receiver.cc \
        resolver.cc resolver.hh \
+       axfr-retriever.cc axfr-retriever.hh \
        responsestats.cc responsestats.hh responsestats-auth.cc \
        rfc2136handler.cc \
        secpoll.cc secpoll.hh \
@@ -636,6 +637,7 @@ ixfrdist_SOURCES = \
        qtype.cc \
        rcpgenerator.cc rcpgenerator.hh \
        resolver.cc \
+       axfr-retriever.cc \
        pollmplexer.cc \
        sillyrecords.cc \
        sstuff.hh \
@@ -690,6 +692,7 @@ ixplore_SOURCES = \
        qtype.cc \
        rcpgenerator.cc rcpgenerator.hh \
        resolver.cc \
+       axfr-retriever.cc \
        ixfr.cc ixfr.hh \
        ixfrutils.cc ixfrutils.hh \
        ixplore.cc \
@@ -823,6 +826,7 @@ toysdig_LDADD += $(P11KIT1_LIBS)
 endif
 
 tsig_tests_SOURCES = \
+       axfr-retriever.cc \
        arguments.cc \
        base32.cc \
        base64.cc base64.hh \
diff --git a/pdns/axfr-retriever.cc b/pdns/axfr-retriever.cc
new file mode 100644 (file)
index 0000000..cfac004
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "axfr-retriever.hh"
+#include "arguments.hh"
+#include "dns_random.hh"
+#include "utility.hh"
+#include "resolver.hh"
+
+using pdns::resolver::parseResult;
+
+AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
+                             const DNSName& domain,
+                             const TSIGTriplet& tt, 
+                             const ComboAddress* laddr,
+                             size_t maxReceivedBytes,
+                             uint16_t timeout)
+  : d_tsigVerifier(tt, remote, d_trc), d_receivedBytes(0), d_maxReceivedBytes(maxReceivedBytes)
+{
+  ComboAddress local;
+  if (laddr != nullptr) {
+    local = ComboAddress(*laddr);
+  } else {
+    string qlas = remote.sin4.sin_family == AF_INET ? "query-local-address" : "query-local-address6";
+    if (::arg()[qlas].empty()) {
+      throw ResolverException("Unable to determine source address for AXFR request to " + remote.toStringWithPort() + " for " + domain.toLogString() + ". " + qlas + " is unset");
+    }
+    local=ComboAddress(::arg()[qlas]);
+  }
+  d_sock = -1;
+  try {
+    d_sock = makeQuerySocket(local, false); // make a TCP socket
+    if (d_sock < 0)
+      throw ResolverException("Error creating socket for AXFR request to "+d_remote.toStringWithPort());
+    d_buf = shared_array<char>(new char[65536]);
+    d_remote = remote; // mostly for error reporting
+    this->connect(timeout);
+    d_soacount = 0;
+  
+    vector<uint8_t> packet;
+    DNSPacketWriter pw(packet, domain, QType::AXFR);
+    pw.getHeader()->id = dns_random_uint16();
+  
+    if(!tt.name.empty()) {
+      if (tt.algo == DNSName("hmac-md5"))
+        d_trc.d_algoName = tt.algo + DNSName("sig-alg.reg.int");
+      else
+        d_trc.d_algoName = tt.algo;
+      d_trc.d_time = time(0);
+      d_trc.d_fudge = 300;
+      d_trc.d_origID=ntohs(pw.getHeader()->id);
+      d_trc.d_eRcode=0;
+      addTSIG(pw, d_trc, tt.name, tt.secret, "", false);
+    }
+  
+    uint16_t replen=htons(packet.size());
+    Utility::iovec iov[2];
+    iov[0].iov_base=reinterpret_cast<char*>(&replen);
+    iov[0].iov_len=2;
+    iov[1].iov_base=packet.data();
+    iov[1].iov_len=packet.size();
+  
+    int ret=Utility::writev(d_sock, iov, 2);
+    if(ret < 0)
+      throw ResolverException("Error sending question to "+d_remote.toStringWithPort()+": "+stringerror());
+    if(ret != (int)(2+packet.size())) {
+      throw ResolverException("Partial write on AXFR request to "+d_remote.toStringWithPort());
+    }
+  
+    int res = waitForData(d_sock, timeout, 0);
+    
+    if(!res)
+      throw ResolverException("Timeout waiting for answer from "+d_remote.toStringWithPort()+" during AXFR");
+    if(res<0)
+      throw ResolverException("Error waiting for answer from "+d_remote.toStringWithPort()+": "+stringerror());
+  }
+  catch(...) {
+    if(d_sock >= 0)
+      close(d_sock);
+    d_sock = -1;
+    throw;
+  }
+}
+
+AXFRRetriever::~AXFRRetriever()
+{
+  close(d_sock);
+}
+
+
+
+int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records, uint16_t timeout) // Implementation is making sure RFC2845 4.4 is followed.
+{
+  if(d_soacount > 1)
+    return false;
+
+  // d_sock is connected and is about to spit out a packet
+  int len=getLength(timeout);
+  if(len<0)
+    throw ResolverException("EOF trying to read axfr chunk from remote TCP client");
+
+  if (d_maxReceivedBytes > 0 && (d_maxReceivedBytes - d_receivedBytes) < (size_t) len)
+    throw ResolverException("Reached the maximum number of received bytes during AXFR");
+
+  timeoutReadn(len, timeout);
+
+  d_receivedBytes += (uint16_t) len;
+
+  MOADNSParser mdp(false, d_buf.get(), len);
+
+  int err = mdp.d_header.rcode;
+
+  if(err) {
+    throw ResolverException("AXFR chunk error: " + RCode::to_s(err));
+  }
+
+  try {
+    d_tsigVerifier.check(std::string(d_buf.get(), len), mdp);
+  }
+  catch(const std::runtime_error& re) {
+    throw ResolverException(re.what());
+  }
+
+  if(!records) {
+    err = parseResult(mdp, DNSName(), 0, 0, &res);
+
+    if (!err) {
+      for(const auto& answer :  mdp.d_answers)
+        if (answer.first.d_type == QType::SOA)
+          d_soacount++;
+    }
+  }
+  else {
+    records->clear();
+    records->reserve(mdp.d_answers.size());
+
+    for(auto& r: mdp.d_answers) {
+      if (r.first.d_type == QType::SOA) {
+        d_soacount++;
+      }
+
+      records->push_back(std::move(r.first));
+    }
+  }
+
+  return true;
+}
+
+void AXFRRetriever::timeoutReadn(uint16_t bytes, uint16_t timeoutsec)
+{
+  time_t start=time(nullptr);
+  int n=0;
+  int numread;
+  while(n<bytes) {
+    int res=waitForData(d_sock, timeoutsec-(time(nullptr)-start));
+    if(res<0)
+      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
+    if(!res)
+      throw ResolverException("Timeout while reading data from remote nameserver over TCP");
+
+    numread=recv(d_sock, d_buf.get()+n, bytes-n, 0);
+    if(numread<0)
+      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
+    if(numread==0)
+      throw ResolverException("Remote nameserver closed TCP connection");
+    n+=numread;
+  }
+}
+
+void AXFRRetriever::connect(uint16_t timeout)
+{
+  setNonBlocking( d_sock );
+
+  int err;
+
+  if((err=::connect(d_sock,(struct sockaddr*)&d_remote, d_remote.getSocklen()))<0 && errno!=EINPROGRESS) {
+    try {
+      closesocket(d_sock);
+    }
+    catch(const PDNSException& e) {
+      d_sock=-1;
+      throw ResolverException("Error closing AXFR socket after connect() failed: "+e.reason);
+    }
+
+    throw ResolverException("connect: "+stringerror());
+  }
+
+  if(!err)
+    goto done;
+
+  err=waitForRWData(d_sock, false, timeout, 0); // wait for writeability
+  
+  if(!err) {
+    try {
+      closesocket(d_sock); // timeout
+    }
+    catch(const PDNSException& e) {
+      d_sock=-1;
+      throw ResolverException("Error closing AXFR socket after timeout: "+e.reason);
+    }
+
+    d_sock=-1;
+    errno=ETIMEDOUT;
+    
+    throw ResolverException("Timeout connecting to server");
+  }
+  else if(err < 0) {
+    throw ResolverException("Error connecting: "+stringerror());
+  }
+  else {
+    Utility::socklen_t len=sizeof(err);
+    if(getsockopt(d_sock, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
+      throw ResolverException("Error connecting: "+stringerror()); // Solaris
+
+    if(err)
+      throw ResolverException("Error connecting: "+string(strerror(err)));
+  }
+  
+ done:
+  setBlocking( d_sock );
+  // d_sock now connected
+}
+
+int AXFRRetriever::getLength(uint16_t timeout)
+{
+  timeoutReadn(2, timeout);
+  return (unsigned char)d_buf[0]*256+(unsigned char)d_buf[1];
+}
+
diff --git a/pdns/axfr-retriever.hh b/pdns/axfr-retriever.hh
new file mode 100644 (file)
index 0000000..63f3324
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+#include <boost/utility.hpp>
+
+#include "iputils.hh"
+#include "dnsname.hh"
+#include "resolver.hh"
+
+class AXFRRetriever : public boost::noncopyable
+{
+  public:
+    AXFRRetriever(const ComboAddress& remote,
+                  const DNSName& zone,
+                  const TSIGTriplet& tt = TSIGTriplet(),
+                  const ComboAddress* laddr = NULL,
+                  size_t maxReceivedBytes=0,
+                  uint16_t timeout=10);
+    ~AXFRRetriever();
+    int getChunk(Resolver::res_t &res, vector<DNSRecord>* records=0, uint16_t timeout=10);
+
+  private:
+    void connect(uint16_t timeout);
+    int getLength(uint16_t timeout);
+    void timeoutReadn(uint16_t bytes, uint16_t timeoutsec=10);
+
+    shared_array<char> d_buf;
+    string d_domain;
+    int d_sock;
+    int d_soacount;
+    ComboAddress d_remote;
+    TSIGTCPVerifier d_tsigVerifier;
+
+    size_t d_receivedBytes;
+    size_t d_maxReceivedBytes;
+    TSIGRecordContent d_trc;
+};
index 816b489673ddd05228c8fd71d22e22fc5a03b4ff..f0154995213f37129305afb198946d5262476827 100644 (file)
@@ -30,7 +30,6 @@
 #include "dnsbackend.hh"
 #include "ueberbackend.hh"
 #include "packethandler.hh"
-#include "resolver.hh"
 #include "logger.hh"
 #include "dns.hh"
 #include "arguments.hh"
index 7d9a0eb0274c6c14cddc0c04c243cbf24fa8c254..25e3470e4d44e4e6fd45001708a153752c22cc25 100644 (file)
@@ -36,7 +36,7 @@
 #include <condition_variable>
 #include "ixfr.hh"
 #include "ixfrutils.hh"
-#include "resolver.hh"
+#include "axfr-retriever.hh"
 #include "dns_random.hh"
 #include "sstuff.hh"
 #include "mplexer.hh"
index 9b525de1b00f925387376265a529d04865e6a2ef..2f010d77c3a3b1b0666fcd97eca634edc794b5fc 100644 (file)
@@ -34,7 +34,7 @@
 #include "dns_random.hh"
 #include "gss_context.hh"
 #include <boost/multi_index_container.hpp>
-#include "resolver.hh"
+#include "axfr-retriever.hh"
 #include <fstream>
 #include "ixfr.hh"
 #include "ixfrutils.hh"
index 657ea7eec6bcb4f35d98d99d675195018d60e2a5..6e13a653b7f558cfd0af87fab2f172a68e51bc63 100644 (file)
@@ -160,6 +160,7 @@ pdns_recursor_SOURCES = \
        reczones.cc \
        remote_logger.cc remote_logger.hh \
        resolver.hh resolver.cc \
+       axfr-retriever.hh axfr-retriever.cc \
        resolve-context.hh \
        responsestats.hh responsestats.cc \
        root-addresses.hh \
@@ -259,6 +260,7 @@ testrunner_SOURCES = \
        responsestats.cc \
        rpzloader.cc rpzloader.hh \
        resolver.hh resolver.cc \
+       axfr-retriever.hh axfr-retriever.cc \
        root-dnssec.hh \
        secpoll.cc \
        sillyrecords.cc \
diff --git a/pdns/recursordist/axfr-retriever.cc b/pdns/recursordist/axfr-retriever.cc
new file mode 120000 (symlink)
index 0000000..e3e1df8
--- /dev/null
@@ -0,0 +1 @@
+../axfr-retriever.cc
\ No newline at end of file
diff --git a/pdns/recursordist/axfr-retriever.hh b/pdns/recursordist/axfr-retriever.hh
new file mode 120000 (symlink)
index 0000000..7e99348
--- /dev/null
@@ -0,0 +1 @@
+../axfr-retriever.hh
\ No newline at end of file
index 774fa7e56402378524de46135cc6535cedf0cb1b..d8977b8db5188b4f7efe09ed776e9b5888233af5 100644 (file)
@@ -51,6 +51,8 @@
 #include "gss_context.hh"
 #include "namespaces.hh"
 
+using pdns::resolver::parseResult;
+
 int makeQuerySocket(const ComboAddress& local, bool udpOrTCP, bool nonLocalBind)
 {
   ComboAddress ourLocal(local);
@@ -188,36 +190,41 @@ uint16_t Resolver::sendResolve(const ComboAddress& remote, const ComboAddress& l
   return randomid;
 }
 
-static int parseResult(MOADNSParser& mdp, const DNSName& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result)
-{
-  result->clear();
-
-  if(mdp.d_header.rcode)
-    return mdp.d_header.rcode;
-
-  if(origQname.countLabels()) {  // not AXFR
-    if(mdp.d_header.id != id) 
-      throw ResolverException("Remote nameserver replied with wrong id");
-    if(mdp.d_header.qdcount != 1)
-      throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp.d_header.qdcount)+")");
-    if(mdp.d_qname != origQname)
-      throw ResolverException(string("resolver: received an answer to another question (")+mdp.d_qname.toLogString()+"!="+ origQname.toLogString()+".)");
-  }
+namespace pdns {
+  namespace resolver {
+    int parseResult(MOADNSParser& mdp, const DNSName& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result)
+    {
+      result->clear();
+
+      if(mdp.d_header.rcode)
+        return mdp.d_header.rcode;
+
+      if(origQname.countLabels()) {  // not AXFR
+        if(mdp.d_header.id != id) 
+          throw ResolverException("Remote nameserver replied with wrong id");
+        if(mdp.d_header.qdcount != 1)
+          throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp.d_header.qdcount)+")");
+        if(mdp.d_qname != origQname)
+          throw ResolverException(string("resolver: received an answer to another question (")+mdp.d_qname.toLogString()+"!="+ origQname.toLogString()+".)");
+      }
 
-  vector<DNSResourceRecord> ret;
-  DNSResourceRecord rr;
-  result->reserve(mdp.d_answers.size());
+      vector<DNSResourceRecord> ret;
+      DNSResourceRecord rr;
+      result->reserve(mdp.d_answers.size());
 
-  for (const auto& i: mdp.d_answers) {
-    rr.qname = i.first.d_name;
-    rr.qtype = i.first.d_type;
-    rr.ttl = i.first.d_ttl;
-    rr.content = i.first.d_content->getZoneRepresentation(true);
-    result->push_back(rr);
-  }
+      for (const auto& i: mdp.d_answers) {
+        rr.qname = i.first.d_name;
+        rr.qtype = i.first.d_type;
+        rr.ttl = i.first.d_ttl;
+        rr.content = i.first.d_content->getZoneRepresentation(true);
+        result->push_back(rr);
+      }
 
-  return 0;
-}
+      return 0;
+    }
+
+  } // namespace resolver
+} // namespace pdns
 
 bool Resolver::tryGetSOASerial(DNSName *domain, ComboAddress* remote, uint32_t *theirSerial, uint32_t *theirInception, uint32_t *theirExpire, uint16_t* id)
 {
@@ -362,221 +369,3 @@ void Resolver::getSoaSerial(const ComboAddress& ipport, const DNSName &domain, u
   }
 }
 
-AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
-                             const DNSName& domain,
-                             const TSIGTriplet& tt, 
-                             const ComboAddress* laddr,
-                             size_t maxReceivedBytes,
-                             uint16_t timeout)
-  : d_tsigVerifier(tt, remote, d_trc), d_receivedBytes(0), d_maxReceivedBytes(maxReceivedBytes)
-{
-  ComboAddress local;
-  if (laddr != nullptr) {
-    local = ComboAddress(*laddr);
-  } else {
-    string qlas = remote.sin4.sin_family == AF_INET ? "query-local-address" : "query-local-address6";
-    if (::arg()[qlas].empty()) {
-      throw ResolverException("Unable to determine source address for AXFR request to " + remote.toStringWithPort() + " for " + domain.toLogString() + ". " + qlas + " is unset");
-    }
-    local=ComboAddress(::arg()[qlas]);
-  }
-  d_sock = -1;
-  try {
-    d_sock = makeQuerySocket(local, false); // make a TCP socket
-    if (d_sock < 0)
-      throw ResolverException("Error creating socket for AXFR request to "+d_remote.toStringWithPort());
-    d_buf = shared_array<char>(new char[65536]);
-    d_remote = remote; // mostly for error reporting
-    this->connect(timeout);
-    d_soacount = 0;
-  
-    vector<uint8_t> packet;
-    DNSPacketWriter pw(packet, domain, QType::AXFR);
-    pw.getHeader()->id = dns_random_uint16();
-  
-    if(!tt.name.empty()) {
-      if (tt.algo == DNSName("hmac-md5"))
-        d_trc.d_algoName = tt.algo + DNSName("sig-alg.reg.int");
-      else
-        d_trc.d_algoName = tt.algo;
-      d_trc.d_time = time(0);
-      d_trc.d_fudge = 300;
-      d_trc.d_origID=ntohs(pw.getHeader()->id);
-      d_trc.d_eRcode=0;
-      addTSIG(pw, d_trc, tt.name, tt.secret, "", false);
-    }
-  
-    uint16_t replen=htons(packet.size());
-    Utility::iovec iov[2];
-    iov[0].iov_base=reinterpret_cast<char*>(&replen);
-    iov[0].iov_len=2;
-    iov[1].iov_base=packet.data();
-    iov[1].iov_len=packet.size();
-  
-    int ret=Utility::writev(d_sock, iov, 2);
-    if(ret < 0)
-      throw ResolverException("Error sending question to "+d_remote.toStringWithPort()+": "+stringerror());
-    if(ret != (int)(2+packet.size())) {
-      throw ResolverException("Partial write on AXFR request to "+d_remote.toStringWithPort());
-    }
-  
-    int res = waitForData(d_sock, timeout, 0);
-    
-    if(!res)
-      throw ResolverException("Timeout waiting for answer from "+d_remote.toStringWithPort()+" during AXFR");
-    if(res<0)
-      throw ResolverException("Error waiting for answer from "+d_remote.toStringWithPort()+": "+stringerror());
-  }
-  catch(...) {
-    if(d_sock >= 0)
-      close(d_sock);
-    d_sock = -1;
-    throw;
-  }
-}
-
-AXFRRetriever::~AXFRRetriever()
-{
-  close(d_sock);
-}
-
-
-
-int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records, uint16_t timeout) // Implementation is making sure RFC2845 4.4 is followed.
-{
-  if(d_soacount > 1)
-    return false;
-
-  // d_sock is connected and is about to spit out a packet
-  int len=getLength(timeout);
-  if(len<0)
-    throw ResolverException("EOF trying to read axfr chunk from remote TCP client");
-
-  if (d_maxReceivedBytes > 0 && (d_maxReceivedBytes - d_receivedBytes) < (size_t) len)
-    throw ResolverException("Reached the maximum number of received bytes during AXFR");
-
-  timeoutReadn(len, timeout);
-
-  d_receivedBytes += (uint16_t) len;
-
-  MOADNSParser mdp(false, d_buf.get(), len);
-
-  int err = mdp.d_header.rcode;
-
-  if(err) {
-    throw ResolverException("AXFR chunk error: " + RCode::to_s(err));
-  }
-
-  try {
-    d_tsigVerifier.check(std::string(d_buf.get(), len), mdp);
-  }
-  catch(const std::runtime_error& re) {
-    throw ResolverException(re.what());
-  }
-
-  if(!records) {
-    err = parseResult(mdp, DNSName(), 0, 0, &res);
-
-    if (!err) {
-      for(const auto& answer :  mdp.d_answers)
-        if (answer.first.d_type == QType::SOA)
-          d_soacount++;
-    }
-  }
-  else {
-    records->clear();
-    records->reserve(mdp.d_answers.size());
-
-    for(auto& r: mdp.d_answers) {
-      if (r.first.d_type == QType::SOA) {
-        d_soacount++;
-      }
-
-      records->push_back(std::move(r.first));
-    }
-  }
-
-  return true;
-}
-
-void AXFRRetriever::timeoutReadn(uint16_t bytes, uint16_t timeoutsec)
-{
-  time_t start=time(nullptr);
-  int n=0;
-  int numread;
-  while(n<bytes) {
-    int res=waitForData(d_sock, timeoutsec-(time(nullptr)-start));
-    if(res<0)
-      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
-    if(!res)
-      throw ResolverException("Timeout while reading data from remote nameserver over TCP");
-
-    numread=recv(d_sock, d_buf.get()+n, bytes-n, 0);
-    if(numread<0)
-      throw ResolverException("Reading data from remote nameserver over TCP: "+stringerror());
-    if(numread==0)
-      throw ResolverException("Remote nameserver closed TCP connection");
-    n+=numread;
-  }
-}
-
-void AXFRRetriever::connect(uint16_t timeout)
-{
-  setNonBlocking( d_sock );
-
-  int err;
-
-  if((err=::connect(d_sock,(struct sockaddr*)&d_remote, d_remote.getSocklen()))<0 && errno!=EINPROGRESS) {
-    try {
-      closesocket(d_sock);
-    }
-    catch(const PDNSException& e) {
-      d_sock=-1;
-      throw ResolverException("Error closing AXFR socket after connect() failed: "+e.reason);
-    }
-
-    throw ResolverException("connect: "+stringerror());
-  }
-
-  if(!err)
-    goto done;
-
-  err=waitForRWData(d_sock, false, timeout, 0); // wait for writeability
-  
-  if(!err) {
-    try {
-      closesocket(d_sock); // timeout
-    }
-    catch(const PDNSException& e) {
-      d_sock=-1;
-      throw ResolverException("Error closing AXFR socket after timeout: "+e.reason);
-    }
-
-    d_sock=-1;
-    errno=ETIMEDOUT;
-    
-    throw ResolverException("Timeout connecting to server");
-  }
-  else if(err < 0) {
-    throw ResolverException("Error connecting: "+stringerror());
-  }
-  else {
-    Utility::socklen_t len=sizeof(err);
-    if(getsockopt(d_sock, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
-      throw ResolverException("Error connecting: "+stringerror()); // Solaris
-
-    if(err)
-      throw ResolverException("Error connecting: "+string(strerror(err)));
-  }
-  
- done:
-  setBlocking( d_sock );
-  // d_sock now connected
-}
-
-int AXFRRetriever::getLength(uint16_t timeout)
-{
-  timeoutReadn(2, timeout);
-  return (unsigned char)d_buf[0]*256+(unsigned char)d_buf[1];
-}
-
index 17b4b7ccdd4fc876b879ef09243b78ace0f1c46f..c78ef139f20a0a923104178acf0578c6ec852e55 100644 (file)
@@ -76,31 +76,8 @@ private:
   std::map<std::string, int> locals;
 };
 
-class AXFRRetriever : public boost::noncopyable
-{
-  public:
-    AXFRRetriever(const ComboAddress& remote,
-                  const DNSName& zone,
-                  const TSIGTriplet& tt = TSIGTriplet(),
-                  const ComboAddress* laddr = NULL,
-                  size_t maxReceivedBytes=0,
-                  uint16_t timeout=10);
-    ~AXFRRetriever();
-    int getChunk(Resolver::res_t &res, vector<DNSRecord>* records=0, uint16_t timeout=10);
-  
-  private:
-    void connect(uint16_t timeout);
-    int getLength(uint16_t timeout);
-    void timeoutReadn(uint16_t bytes, uint16_t timeoutsec=10);
-
-    shared_array<char> d_buf;
-    string d_domain;
-    int d_sock;
-    int d_soacount;
-    ComboAddress d_remote;
-    TSIGTCPVerifier d_tsigVerifier;
-
-    size_t d_receivedBytes;
-    size_t d_maxReceivedBytes;
-    TSIGRecordContent d_trc;
-};
+namespace pdns {
+  namespace resolver {
+    int parseResult(MOADNSParser& mdp, const DNSName& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result);
+  } // namespace resolver
+} // namespace pdns
index 908c3a4384b9f493f3a236bf155fa2017a1f9372..1562c5f94eaad392b25caa3649ec90e13d9fce23 100644 (file)
@@ -3,7 +3,7 @@
 #include "dnsrecords.hh"
 #include "ixfr.hh"
 #include "syncres.hh"
-#include "resolver.hh"
+#include "axfr-retriever.hh"
 #include "logger.hh"
 #include "rec-lua-conf.hh"
 #include "rpzloader.hh"
index 8a55e4125ba34e8ebe082c634b982cbfc7b835f7..7e548ff08f51e7d85e63d6ac3bca5d28e0060f67 100644 (file)
@@ -34,7 +34,7 @@
 #include "dnsbackend.hh"
 #include "ueberbackend.hh"
 #include "packethandler.hh"
-#include "resolver.hh"
+#include "axfr-retriever.hh"
 #include "logger.hh"
 #include "dns.hh"
 #include "arguments.hh"
index 80cf3f9f4ca9ad0f9c7db036cf3042a38a71b449..8ee6102c5c8f2a43a3ae03d1a577889ce1555f41 100644 (file)
@@ -53,7 +53,6 @@
 #include "common_startup.hh"
 #include "packethandler.hh"
 #include "statbag.hh"
-#include "resolver.hh"
 #include "communicator.hh"
 #include "namespaces.hh"
 #include "signingpipe.hh"
index 3a705096cd5369949b86a083677d973daccbf5f6..d65bd563ab420890bff2720a23cfd3f8d50cd856 100644 (file)
@@ -11,7 +11,7 @@
 #include "digests.hh"
 #include "base64.hh"
 #include "dnssecinfra.hh"
-#include "resolver.hh"
+#include "axfr-retriever.hh"
 #include "arguments.hh"
 #include "dns_random.hh"