]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge pull request #7704 from ahupowerdns/boost-stringref-cutoff
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 12 Apr 2019 09:27:47 +0000 (11:27 +0200)
committerGitHub <noreply@github.com>
Fri, 12 Apr 2019 09:27:47 +0000 (11:27 +0200)
Boost string_view only appeared in Boost 1.61, not 1.54 as we were assuming

45 files changed:
docs/secpoll.zone
modules/lmdbbackend/lmdbbackend.cc
pdns/backends/gsql/gsqlbackend.cc
pdns/dnscrypt.cc
pdns/dnscrypt.hh
pdns/dnsdist-console.cc
pdns/dnsdist-lua-actions.cc
pdns/dnsdist-lua-vars.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist-web.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/docs/advanced/axfr.rst
pdns/dnsdistdist/docs/changelog.rst
pdns/dnsdistdist/docs/guides/cache.rst
pdns/dnsdistdist/docs/guides/serverselection.rst
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/docs/reference/constants.rst
pdns/dnsdistdist/docs/reference/dq.rst
pdns/dnsdistdist/docs/rules-actions.rst
pdns/dnsdistdist/docs/upgrade_guide.rst
pdns/dnsdistdist/tcpiohandler.cc
pdns/iputils.hh
pdns/misc.cc
pdns/recursordist/README.md
pdns/recursordist/test-ednsoptions_cc.cc
pdns/tcpiohandler.hh
pdns/test-dnsdist_cc.cc
regression-tests.dnsdist/runtests
regression-tests.dnsdist/test-include-dir/test.conf
regression-tests.dnsdist/test_Advanced.py
regression-tests.dnsdist/test_Basics.py
regression-tests.dnsdist/test_Caching.py
regression-tests.dnsdist/test_CheckConfig.py
regression-tests.dnsdist/test_Dnstap.py
regression-tests.dnsdist/test_DynBlocks.py
regression-tests.dnsdist/test_EDNSSelfGenerated.py
regression-tests.dnsdist/test_HealthChecks.py
regression-tests.dnsdist/test_Protobuf.py
regression-tests.dnsdist/test_RecordsCount.py
regression-tests.dnsdist/test_Responses.py
regression-tests.dnsdist/test_Routing.py
regression-tests.dnsdist/test_TCPKeepAlive.py
regression-tests.dnsdist/test_TeeAction.py

index 83c2a0ef8f86e5f30035d2fa6188fe23bda1f195..21c25746b9623d971bfb9ac5e44616ae2d37d3a9 100644 (file)
@@ -1,4 +1,4 @@
-@       86400   IN  SOA pdns-public-ns1.powerdns.com. pieter\.lexis.powerdns.com. 2019040201 10800 3600 604800 10800
+@       86400   IN  SOA pdns-public-ns1.powerdns.com. pieter\.lexis.powerdns.com. 2019041201 10800 3600 604800 10800
 @       3600    IN  NS  pdns-public-ns1.powerdns.com.
 @       3600    IN  NS  pdns-public-ns2.powerdns.com.
 ; Auth
@@ -300,3 +300,4 @@ recursor-4.0.0_beta1-1pdns.jessie.raspbian.security-status 60 IN TXT "3 Upgrade
 
 ; dnsdist
 dnsdist-1.3.3.security-status                              60 IN TXT "1 OK"
+dnsdist-1.4.0-alpha1.security-status                       60 IN TXT "1 OK"
index ea152739caa20124aeb871fb2364483a7a9f26b1..43b07a909184e067685a10baa81e37adb66a1207 100644 (file)
@@ -808,7 +808,7 @@ bool LMDBBackend::setMaster(const DNSName &domain, const std::string& ips)
   vector<string> parts;
   stringtok(parts, ips, " \t;,");
   for(const auto& ip : parts) 
-    masters.push_back(ComboAddress(ip)); 
+    masters.push_back(ComboAddress(ip, 53));
   
   return genChangeDomain(domain, [&masters](DomainInfo& di) {
       di.masters = masters;
index 95f850c8116dc2b0d9c164a33fd7950558859876..64f8c758e550e7d7411f32c10f2049e638f92581 100644 (file)
@@ -930,7 +930,7 @@ bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string
       d_GetAllDomainMetadataQuery_stmt->nextRow(row);
       ASSERT_ROW_COLUMNS("get-all-domain-metadata-query", row, 2);
 
-      if (!isDnssecDomainMetadata(row[0]))
+      if (d_dnssecQueries || !isDnssecDomainMetadata(row[0]))
         meta[row[0]].push_back(row[1]);
     }
 
index f81263c09fcbbb2d5445a5f582eec1b566b98aa7..4cf126ce389d6afc7f8bb979670e34c461e458e9 100644 (file)
@@ -283,13 +283,19 @@ std::string DNSCryptContext::certificateDateToStr(uint32_t date)
   return string(buf);
 }
 
-void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active)
+void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active, bool reload)
 {
   WriteLock w(&d_lock);
 
   for (auto pair : certs) {
     if (pair->cert.getSerial() == newCert.getSerial()) {
-      throw std::runtime_error("Error adding a new certificate: we already have a certificate with the same serial");
+      if (reload) {
+        /* on reload we just assume that this is the same certificate */
+        return;
+      }
+      else {
+        throw std::runtime_error("Error adding a new certificate: we already have a certificate with the same serial");
+      }
     }
   }
 
@@ -301,7 +307,7 @@ void DNSCryptContext::addNewCertificate(const DNSCryptCert& newCert, const DNSCr
   certs.push_back(pair);
 }
 
-void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active)
+void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active, bool reload)
 {
   DNSCryptCert newCert;
   DNSCryptPrivateKey newPrivateKey;
@@ -309,7 +315,14 @@ void DNSCryptContext::loadNewCertificate(const std::string& certFile, const std:
   loadCertFromFile(certFile, newCert);
   newPrivateKey.loadFromFile(keyFile);
 
-  addNewCertificate(newCert, newPrivateKey, active);
+  addNewCertificate(newCert, newPrivateKey, active, reload);
+  certificatePath = certFile;
+  keyPath = keyFile;
+}
+
+void DNSCryptContext::reloadCertificate()
+{
+  loadNewCertificate(certificatePath, keyPath, true, true);
 }
 
 void DNSCryptContext::markActive(uint32_t serial)
index 307784cb8092ee5fcaa3ca3c42d003cbba0cb382..86ddcd20159fdad28b485fd3b97bafa7dab323bc 100644 (file)
@@ -257,8 +257,9 @@ public:
   DNSCryptContext(const std::string& pName, const std::string& certFile, const std::string& keyFile);
   DNSCryptContext(const std::string& pName, const DNSCryptCert& certificate, const DNSCryptPrivateKey& pKey);
 
-  void loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active=true);
-  void addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active=true);
+  void reloadCertificate();
+  void loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active=true, bool reload=false);
+  void addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active=true, bool reload=false);
   void markActive(uint32_t serial);
   void markInactive(uint32_t serial);
   void removeInactiveCertificate(uint32_t serial);
@@ -276,6 +277,8 @@ private:
   pthread_rwlock_t d_lock;
   std::vector<std::shared_ptr<DNSCryptCertificatePair>> certs;
   DNSName providerName;
+  std::string certificatePath;
+  std::string keyPath;
 };
 
 bool generateDNSCryptCertificate(const std::string& providerPrivateKeyFile, uint32_t serial, time_t begin, time_t end, DNSCryptExchangeVersion version, DNSCryptCert& certOut, DNSCryptPrivateKey& keyOut);
index 3d0dd4d039f02ff307296a819116b7bf63f5a9c8..8fde18cb5d0b58c193f451bd7d9adbf9b040c99e 100644 (file)
@@ -428,6 +428,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "RCodeRule", true, "rcode", "matches responses with the specified rcode" },
   { "RegexRule", true, "regex", "matches the query name against the supplied regex" },
   { "registerDynBPFFilter", true, "DynBPFFilter", "register this dynamic BPF filter into the web interface so that its counters are displayed" },
+  { "reloadAllCertificates", true, "", "reload all DNSCrypt and TLS certificates, along with their associated keys" },
   { "RemoteLogAction", true, "RemoteLogger [, alterFunction [, serverID]]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes. `serverID` is the server identifier." },
   { "RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME [, serverID]]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records. `serverID` is the server identifier." },
   { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string" },
index 4f255b6e8c0766ec2f8338cfcac9b657af856d7b..c9cadfc5ee01ea23fc2c3e8b77e8ce683c3a2f90 100644 (file)
@@ -745,7 +745,7 @@ private:
 class DnstapLogAction : public DNSAction, public boost::noncopyable
 {
 public:
-  DnstapLogAction(const std::string& identity, std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(const DNSQuestion&, DnstapMessage*)> > alterFunc): d_identity(identity), d_logger(logger), d_alterFunc(alterFunc)
+  DnstapLogAction(const std::string& identity, std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(DNSQuestion*, DnstapMessage*)> > alterFunc): d_identity(identity), d_logger(logger), d_alterFunc(alterFunc)
   {
   }
   DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
@@ -755,7 +755,7 @@ public:
     {
       if (d_alterFunc) {
         std::lock_guard<std::mutex> lock(g_luamutex);
-        (*d_alterFunc)(*dq, &message);
+        (*d_alterFunc)(dq, &message);
       }
     }
     std::string data;
@@ -771,13 +771,13 @@ public:
 private:
   std::string d_identity;
   std::shared_ptr<RemoteLoggerInterface> d_logger;
-  boost::optional<std::function<void(const DNSQuestion&, DnstapMessage*)> > d_alterFunc;
+  boost::optional<std::function<void(DNSQuestion*, DnstapMessage*)> > d_alterFunc;
 };
 
 class RemoteLogAction : public DNSAction, public boost::noncopyable
 {
 public:
-  RemoteLogAction(std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(const DNSQuestion&, DNSDistProtoBufMessage*)> > alterFunc, const std::string& serverID, const std::string& ipEncryptKey): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey)
+  RemoteLogAction(std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(DNSQuestion*, DNSDistProtoBufMessage*)> > alterFunc, const std::string& serverID, const std::string& ipEncryptKey): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey)
   {
   }
   DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
@@ -801,7 +801,7 @@ public:
 
     if (d_alterFunc) {
       std::lock_guard<std::mutex> lock(g_luamutex);
-      (*d_alterFunc)(*dq, &message);
+      (*d_alterFunc)(dq, &message);
     }
 
     std::string data;
@@ -816,7 +816,7 @@ public:
   }
 private:
   std::shared_ptr<RemoteLoggerInterface> d_logger;
-  boost::optional<std::function<void(const DNSQuestion&, DNSDistProtoBufMessage*)> > d_alterFunc;
+  boost::optional<std::function<void(DNSQuestion*, DNSDistProtoBufMessage*)> > d_alterFunc;
   std::string d_serverID;
   std::string d_ipEncryptKey;
 };
@@ -871,7 +871,7 @@ private:
 class DnstapLogResponseAction : public DNSResponseAction, public boost::noncopyable
 {
 public:
-  DnstapLogResponseAction(const std::string& identity, std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(const DNSResponse&, DnstapMessage*)> > alterFunc): d_identity(identity), d_logger(logger), d_alterFunc(alterFunc)
+  DnstapLogResponseAction(const std::string& identity, std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(DNSResponse*, DnstapMessage*)> > alterFunc): d_identity(identity), d_logger(logger), d_alterFunc(alterFunc)
   {
   }
   DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
@@ -883,7 +883,7 @@ public:
     {
       if (d_alterFunc) {
         std::lock_guard<std::mutex> lock(g_luamutex);
-        (*d_alterFunc)(*dr, &message);
+        (*d_alterFunc)(dr, &message);
       }
     }
     std::string data;
@@ -899,13 +899,13 @@ public:
 private:
   std::string d_identity;
   std::shared_ptr<RemoteLoggerInterface> d_logger;
-  boost::optional<std::function<void(const DNSResponse&, DnstapMessage*)> > d_alterFunc;
+  boost::optional<std::function<void(DNSResponse*, DnstapMessage*)> > d_alterFunc;
 };
 
 class RemoteLogResponseAction : public DNSResponseAction, public boost::noncopyable
 {
 public:
-  RemoteLogResponseAction(std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(const DNSResponse&, DNSDistProtoBufMessage*)> > alterFunc, const std::string& serverID, const std::string& ipEncryptKey, bool includeCNAME): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey), d_includeCNAME(includeCNAME)
+  RemoteLogResponseAction(std::shared_ptr<RemoteLoggerInterface>& logger, boost::optional<std::function<void(DNSResponse*, DNSDistProtoBufMessage*)> > alterFunc, const std::string& serverID, const std::string& ipEncryptKey, bool includeCNAME): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey), d_includeCNAME(includeCNAME)
   {
   }
   DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
@@ -929,7 +929,7 @@ public:
 
     if (d_alterFunc) {
       std::lock_guard<std::mutex> lock(g_luamutex);
-      (*d_alterFunc)(*dr, &message);
+      (*d_alterFunc)(dr, &message);
     }
 
     std::string data;
@@ -944,7 +944,7 @@ public:
   }
 private:
   std::shared_ptr<RemoteLoggerInterface> d_logger;
-  boost::optional<std::function<void(const DNSResponse&, DNSDistProtoBufMessage*)> > d_alterFunc;
+  boost::optional<std::function<void(DNSResponse*, DNSDistProtoBufMessage*)> > d_alterFunc;
   std::string d_serverID;
   std::string d_ipEncryptKey;
   bool d_includeCNAME;
@@ -1226,7 +1226,7 @@ void setupLuaActions()
       return std::shared_ptr<DNSResponseAction>(new LuaResponseAction(func));
     });
 
-  g_lua.writeFunction("RemoteLogAction", [](std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(const DNSQuestion&, DNSDistProtoBufMessage*)> > alterFunc, boost::optional<std::unordered_map<std::string, std::string>> vars) {
+  g_lua.writeFunction("RemoteLogAction", [](std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(DNSQuestion*, DNSDistProtoBufMessage*)> > alterFunc, boost::optional<std::unordered_map<std::string, std::string>> vars) {
       // avoids potentially-evaluated-expression warning with clang.
       RemoteLoggerInterface& rl = *logger.get();
       if (typeid(rl) != typeid(RemoteLogger)) {
@@ -1252,7 +1252,7 @@ void setupLuaActions()
 #endif
     });
 
-  g_lua.writeFunction("RemoteLogResponseAction", [](std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(const DNSResponse&, DNSDistProtoBufMessage*)> > alterFunc, boost::optional<bool> includeCNAME, boost::optional<std::unordered_map<std::string, std::string>> vars) {
+  g_lua.writeFunction("RemoteLogResponseAction", [](std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(DNSResponse*, DNSDistProtoBufMessage*)> > alterFunc, boost::optional<bool> includeCNAME, boost::optional<std::unordered_map<std::string, std::string>> vars) {
       // avoids potentially-evaluated-expression warning with clang.
       RemoteLoggerInterface& rl = *logger.get();
       if (typeid(rl) != typeid(RemoteLogger)) {
@@ -1278,7 +1278,7 @@ void setupLuaActions()
 #endif
     });
 
-  g_lua.writeFunction("DnstapLogAction", [](const std::string& identity, std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(const DNSQuestion&, DnstapMessage*)> > alterFunc) {
+  g_lua.writeFunction("DnstapLogAction", [](const std::string& identity, std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(DNSQuestion*, DnstapMessage*)> > alterFunc) {
 #ifdef HAVE_PROTOBUF
       return std::shared_ptr<DNSAction>(new DnstapLogAction(identity, logger, alterFunc));
 #else
@@ -1286,7 +1286,7 @@ void setupLuaActions()
 #endif
     });
 
-  g_lua.writeFunction("DnstapLogResponseAction", [](const std::string& identity, std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(const DNSResponse&, DnstapMessage*)> > alterFunc) {
+  g_lua.writeFunction("DnstapLogResponseAction", [](const std::string& identity, std::shared_ptr<RemoteLoggerInterface> logger, boost::optional<std::function<void(DNSResponse*, DnstapMessage*)> > alterFunc) {
 #ifdef HAVE_PROTOBUF
       return std::shared_ptr<DNSResponseAction>(new DnstapLogResponseAction(identity, logger, alterFunc));
 #else
index 9cf840093155c51915a6904ab8d83c8cbd881bcf..b912cda51b4ef6028a3e3cd8cd02e479841035eb 100644 (file)
@@ -87,33 +87,54 @@ void setupLuaVars()
       {"KEYTAG",       EDNSOptionCode::KEYTAG }
     });
 
-  vector<pair<string, int> > rcodes = {{"NOERROR",  RCode::NoError  },
-                                       {"FORMERR",  RCode::FormErr  },
-                                       {"SERVFAIL", RCode::ServFail },
-                                       {"NXDOMAIN", RCode::NXDomain },
-                                       {"NOTIMP",   RCode::NotImp   },
-                                       {"REFUSED",  RCode::Refused  },
-                                       {"YXDOMAIN", RCode::YXDomain },
-                                       {"YXRRSET",  RCode::YXRRSet  },
-                                       {"NXRRSET",  RCode::NXRRSet  },
-                                       {"NOTAUTH",  RCode::NotAuth  },
-                                       {"NOTZONE",  RCode::NotZone  },
-                                       {"BADVERS",  ERCode::BADVERS },
-                                       {"BADSIG",   ERCode::BADSIG  },
-                                       {"BADKEY",   ERCode::BADKEY  },
-                                       {"BADTIME",  ERCode::BADTIME   },
-                                       {"BADMODE",  ERCode::BADMODE   },
-                                       {"BADNAME",  ERCode::BADNAME   },
-                                       {"BADALG",   ERCode::BADALG    },
-                                       {"BADTRUNC", ERCode::BADTRUNC  },
-                                       {"BADCOOKIE",ERCode::BADCOOKIE },
-  };
+  g_lua.writeVariable("DNSRCode", std::unordered_map<string, int>{
+      {"NOERROR",  RCode::NoError  },
+      {"FORMERR",  RCode::FormErr  },
+      {"SERVFAIL", RCode::ServFail },
+      {"NXDOMAIN", RCode::NXDomain },
+      {"NOTIMP",   RCode::NotImp   },
+      {"REFUSED",  RCode::Refused  },
+      {"YXDOMAIN", RCode::YXDomain },
+      {"YXRRSET",  RCode::YXRRSet  },
+      {"NXRRSET",  RCode::NXRRSet  },
+      {"NOTAUTH",  RCode::NotAuth  },
+      {"NOTZONE",  RCode::NotZone  },
+      {"BADVERS",  ERCode::BADVERS },
+      {"BADSIG",   ERCode::BADSIG  },
+      {"BADKEY",   ERCode::BADKEY  },
+      {"BADTIME",  ERCode::BADTIME   },
+      {"BADMODE",  ERCode::BADMODE   },
+      {"BADNAME",  ERCode::BADNAME   },
+      {"BADALG",   ERCode::BADALG    },
+      {"BADTRUNC", ERCode::BADTRUNC  },
+      {"BADCOOKIE",ERCode::BADCOOKIE }
+  });
+
   vector<pair<string, int> > dd;
   for(const auto& n : QType::names)
     dd.push_back({n.first, n.second});
-  for(const auto& n : rcodes)
-    dd.push_back({n.first, n.second});
-  g_lua.writeVariable("dnsdist", dd);
+  g_lua.writeVariable("DNSQType", dd);
+
+  g_lua.executeCode(R"LUA(
+    local tables = {
+      DNSQType = DNSQType,
+      DNSRCode = DNSRCode
+    }
+    local function index (table, key)
+      for tname,t in pairs(tables)
+      do
+        local val = t[key]
+        if val then
+          warnlog(string.format("access to dnsdist.%s is deprecated, please use %s.%s", key, tname, key))
+          return val
+        end
+      end
+    end
+
+    dnsdist = {}
+    setmetatable(dnsdist, { __index = index })
+    )LUA"
+  );
 
 #ifdef HAVE_DNSCRYPT
     g_lua.writeVariable("DNSCryptExchangeVersion", std::unordered_map<string,int>{
index 69e5c571f67178cb8e6242c0d19a180e517382b9..ad4c55472354e2a6f47df8652d8bf0027a534fc3 100644 (file)
@@ -497,10 +497,23 @@ void setupLuaConfig(bool client)
 
       try {
        ComboAddress loc(addr, 53);
-       g_locals.clear();
-       g_locals.push_back(std::make_tuple(loc, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus)); /// only works pre-startup, so no sync necessary
+        for (auto it = g_frontends.begin(); it != g_frontends.end(); ) {
+          /* TLS and DNSCrypt frontends are separate */
+          if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr) {
+            it = g_frontends.erase(it);
+          }
+          else {
+            ++it;
+          }
+        }
+
+        // only works pre-startup, so no sync necessary
+        g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        if (doTCP) {
+          g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        }
       }
-      catch(std::exception& e) {
+      catch(const std::exception& e) {
        g_outputBuffer="Error: "+string(e.what())+"\n";
       }
     });
@@ -523,7 +536,11 @@ void setupLuaConfig(bool client)
 
       try {
        ComboAddress loc(addr, 53);
-       g_locals.push_back(std::make_tuple(loc, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus)); /// only works pre-startup, so no sync necessary
+        // only works pre-startup, so no sync necessary
+        g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        if (doTCP) {
+          g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        }
       }
       catch(std::exception& e) {
        g_outputBuffer="Error: "+string(e.what())+"\n";
@@ -1095,7 +1112,17 @@ void setupLuaConfig(bool client)
 
       try {
         auto ctx = std::make_shared<DNSCryptContext>(providerName, certFile, keyFile);
-        g_dnsCryptLocals.push_back(std::make_tuple(ComboAddress(addr, 443), ctx, reusePort, tcpFastOpenQueueSize, interface, cpus));
+
+        /* UDP */
+        auto cs = std::unique_ptr<ClientState>(new ClientState(ComboAddress(addr, 443), false, reusePort, tcpFastOpenQueueSize, interface, cpus));
+        cs->dnscryptCtx = ctx;
+        g_dnsCryptLocals.push_back(ctx);
+        g_frontends.push_back(std::move(cs));
+
+        /* TCP */
+        cs = std::unique_ptr<ClientState>(new ClientState(ComboAddress(addr, 443), true, reusePort, tcpFastOpenQueueSize, interface, cpus));
+        cs->dnscryptCtx = ctx;
+        g_frontends.push_back(std::move(cs));
       }
       catch(std::exception& e) {
         errlog(e.what());
@@ -1115,9 +1142,9 @@ void setupLuaConfig(bool client)
       ret << (fmt % "#" % "Address" % "Provider Name") << endl;
       size_t idx = 0;
 
-      for (const auto& local : g_dnsCryptLocals) {
-        const std::shared_ptr<DNSCryptContext> ctx = std::get<1>(local);
-        ret<< (fmt % idx % std::get<0>(local).toStringWithPort() % ctx->getProviderName()) << endl;
+      for (const auto& frontend : g_frontends) {
+        const std::shared_ptr<DNSCryptContext> ctx = frontend->dnscryptCtx;
+        ret<< (fmt % idx % frontend->local.toStringWithPort() % ctx->getProviderName()) << endl;
         idx++;
       }
 
@@ -1132,7 +1159,7 @@ void setupLuaConfig(bool client)
 #ifdef HAVE_DNSCRYPT
       std::shared_ptr<DNSCryptContext> ret = nullptr;
       if (idx < g_dnsCryptLocals.size()) {
-        ret = std::get<1>(g_dnsCryptLocals.at(idx));
+        ret = g_dnsCryptLocals.at(idx);
       }
       return ret;
 #else
@@ -1285,7 +1312,7 @@ void setupLuaConfig(bool client)
       setLuaNoSideEffect();
       ClientState* ret = nullptr;
       if(num < g_frontends.size()) {
-        ret=g_frontends[num];
+        ret=g_frontends[num].get();
       }
       return ret;
       });
@@ -1458,6 +1485,11 @@ void setupLuaConfig(bool client)
       g_servFailOnNoPolicy = servfail;
     });
 
+  g_lua.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) {
+      setLuaSideEffect();
+      g_roundrobinFailOnNoServer = fail;
+    });
+
   g_lua.writeFunction("setRingBuffersSize", [](size_t capacity, boost::optional<size_t> numberOfShards) {
       setLuaSideEffect();
       if (g_configurationDone) {
@@ -1633,9 +1665,16 @@ void setupLuaConfig(bool client)
           return;
         }
 
+        bool doTCP = true;
+        bool reusePort = false;
+        int tcpFastOpenQueueSize = 0;
+        std::string interface;
+        std::set<int> cpus;
+        (void) doTCP;
+
         if (vars) {
           bool doTCP = true;
-          parseLocalBindVars(vars, doTCP, frontend->d_reusePort, frontend->d_tcpFastOpenQueueSize, frontend->d_interface, frontend->d_cpus);
+          parseLocalBindVars(vars, doTCP, reusePort, tcpFastOpenQueueSize, interface, cpus);
 
           if (vars->count("provider")) {
             frontend->d_provider = boost::get<const string>((*vars)["provider"]);
@@ -1675,7 +1714,11 @@ void setupLuaConfig(bool client)
         try {
           frontend->d_addr = ComboAddress(addr, 853);
           vinfolog("Loading TLS provider %s", frontend->d_provider);
-          g_tlslocals.push_back(frontend); /// only works pre-startup, so no sync necessary
+          // only works pre-startup, so no sync necessary
+          auto cs = std::unique_ptr<ClientState>(new ClientState(frontend->d_addr, true, reusePort, tcpFastOpenQueueSize, interface, cpus));
+          cs->tlsFrontend = frontend;
+          g_tlslocals.push_back(cs->tlsFrontend);
+          g_frontends.push_back(std::move(cs));
         }
         catch(const std::exception& e) {
           g_outputBuffer="Error: "+string(e.what())+"\n";
@@ -1775,7 +1818,30 @@ void setupLuaConfig(bool client)
 #endif
       });
 
-  g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; });
+    g_lua.writeFunction("reloadAllCertificates", []() {
+        for (auto& frontend : g_frontends) {
+          if (!frontend) {
+            continue;
+          }
+          try {
+#ifdef HAVE_DNSCRYPT
+            if (frontend->dnscryptCtx) {
+              frontend->dnscryptCtx->reloadCertificate();
+            }
+#endif /* HAVE_DNSCRYPT */
+#ifdef HAVE_DNS_OVER_TLS
+            if (frontend->tlsFrontend) {
+              frontend->tlsFrontend->setupTLS();
+            }
+#endif /* HAVE_DNS_OVER_TLS */
+          }
+          catch(const std::exception& e) {
+            errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what());
+          }
+        }
+      });
+
+    g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; });
 }
 
 vector<std::function<void(void)>> setupLua(bool client, const std::string& config)
index 878f056a02ec68844874abe230a466a4ab65eb43..1c51cdc16cab584b5df2f00c31c1262a877c61d0 100644 (file)
@@ -209,12 +209,9 @@ struct ConnectionInfo
   ConnectionInfo(ClientState* cs_): cs(cs_), fd(-1)
   {
   }
-  ConnectionInfo(ConnectionInfo&& rhs)
+  ConnectionInfo(ConnectionInfo&& rhs): remote(rhs.remote), cs(rhs.cs), fd(rhs.fd)
   {
-    remote = rhs.remote;
-    cs = rhs.cs;
     rhs.cs = nullptr;
-    fd = rhs.fd;
     rhs.fd = -1;
   }
 
index 291e16661d7cb1b7af40c158ca8fe53dc7f42552..704c575172a0533690e185b4ea777bc56f7c635d 100644 (file)
@@ -681,9 +681,14 @@ static void connectionThread(int sock, ComboAddress remote)
         acl+=s;
       }
       string localaddresses;
-      for(const auto& loc : g_locals) {
-        if(!localaddresses.empty()) localaddresses += ", ";
-        localaddresses += std::get<0>(loc).toStringWithPort();
+      for(const auto& front : g_frontends) {
+        if (front->tcp) {
+          continue;
+        }
+        if (!localaddresses.empty()) {
+          localaddresses += ", ";
+        }
+        localaddresses += front->local.toStringWithPort();
       }
 
       Json my_json = Json::object {
index 461c5f389649257d2ca3a08b69294b1b3bfcfd58..f7bfc1dee545f193182f8a758dbdfe520783a99c 100644 (file)
@@ -92,14 +92,13 @@ bool g_allowEmptyResponse{false};
 GlobalStateHolder<NetmaskGroup> g_ACL;
 string g_outputBuffer;
 
-vector<std::tuple<ComboAddress, bool, bool, int, string, std::set<int>>> g_locals;
 std::vector<std::shared_ptr<TLSFrontend>> g_tlslocals;
-std::vector<std::tuple<ComboAddress,std::shared_ptr<DNSCryptContext>,bool, int, string, std::set<int> >> g_dnsCryptLocals;
+std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
 #ifdef HAVE_EBPF
 shared_ptr<BPFFilter> g_defaultBPFFilter;
 std::vector<std::shared_ptr<DynBPFFilter> > g_dynBPFFilters;
 #endif /* HAVE_EBPF */
-vector<ClientState *> g_frontends;
+std::vector<std::unique_ptr<ClientState>> g_frontends;
 GlobalStateHolder<pools_t> g_pools;
 size_t g_udpVectorSize{1};
 
@@ -142,6 +141,7 @@ bool g_servFailOnNoPolicy{false};
 bool g_truncateTC{false};
 bool g_fixupCase{false};
 bool g_preserveTrailingData{false};
+bool g_roundrobinFailOnNoServer{false};
 
 static void truncateTC(char* packet, uint16_t* len, size_t responseSize, unsigned int consumed)
 try
@@ -884,7 +884,7 @@ shared_ptr<DownstreamState> roundrobin(const NumberedServerVector& servers, cons
   }
 
   const auto *res=&poss;
-  if(poss.empty())
+  if(poss.empty() && !g_roundrobinFailOnNoServer)
     res = &servers;
 
   if(res->empty())
@@ -1006,7 +1006,7 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, string& po
     bool countQuery{true};
     if(g_qcount.filter) {
       std::lock_guard<std::mutex> lock(g_luamutex);
-      std::tie (countQuery, qname) = g_qcount.filter(dq);
+      std::tie (countQuery, qname) = g_qcount.filter(&dq);
     }
 
     if(countQuery) {
@@ -2168,6 +2168,102 @@ static void checkFileDescriptorsLimits(size_t udpBindsCount, size_t tcpBindsCoun
   }
 }
 
+static void setUpLocalBind(std::unique_ptr<ClientState>& cs)
+{
+  /* skip some warnings if there is an identical UDP context */
+  bool warn = cs->tcp == false || cs->tlsFrontend != nullptr;
+  int& fd = cs->tcp == false ? cs->udpFD : cs->tcpFD;
+  (void) warn;
+
+  fd = SSocket(cs->local.sin4.sin_family, cs->tcp == false ? SOCK_DGRAM : SOCK_STREAM, 0);
+
+  if (cs->tcp) {
+    SSetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 1);
+#ifdef TCP_DEFER_ACCEPT
+    SSetsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1);
+#endif
+    if (cs->fastOpenQueueSize > 0) {
+#ifdef TCP_FASTOPEN
+      SSetsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, cs->fastOpenQueueSize);
+#else
+      if (warn) {
+        warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", cs->local.toStringWithPort());
+      }
+#endif
+    }
+  }
+
+  if(cs->local.sin4.sin_family == AF_INET6) {
+    SSetsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
+  }
+
+  bindAny(cs->local.sin4.sin_family, fd);
+
+  if(!cs->tcp && IsAnyAddress(cs->local)) {
+    int one=1;
+    setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));     // linux supports this, so why not - might fail on other systems
+#ifdef IPV6_RECVPKTINFO
+    setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+#endif
+  }
+
+  if (cs->reuseport) {
+#ifdef SO_REUSEPORT
+    SSetsockopt(fd, SOL_SOCKET, SO_REUSEPORT, 1);
+#else
+    if (warn) {
+      /* no need to warn again if configured but support is not available, we already did for UDP */
+      warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", cs->local.toStringWithPort());
+    }
+#endif
+  }
+
+  const std::string& itf = cs->interface;
+  if (!itf.empty()) {
+#ifdef SO_BINDTODEVICE
+    int res = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length());
+    if (res != 0) {
+      warnlog("Error setting up the interface on local address '%s': %s", cs->local.toStringWithPort(), strerror(errno));
+    }
+#else
+    if (warn) {
+      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", cs->local.toStringWithPort());
+    }
+#endif
+  }
+
+#ifdef HAVE_EBPF
+  if (g_defaultBPFFilter) {
+    cs->attachFilter(g_defaultBPFFilter);
+    vinfolog("Attaching default BPF Filter to %s frontend %s", (!cs->tcp ? "UDP" : "TCP"), cs->local.toStringWithPort());
+  }
+#endif /* HAVE_EBPF */
+
+  if (cs->tlsFrontend != nullptr) {
+    if (!cs->tlsFrontend->setupTLS()) {
+      errlog("Error while setting up TLS on local address '%s', exiting", cs->local.toStringWithPort());
+      _exit(EXIT_FAILURE);
+    }
+  }
+
+  SBind(fd, cs->local);
+
+  if (cs->tcp) {
+    SListen(cs->tcpFD, 64);
+    if (cs->tlsFrontend != nullptr) {
+      warnlog("Listening on %s for TLS", cs->local.toStringWithPort());
+    }
+    else if (cs->dnscryptCtx != nullptr) {
+      warnlog("Listening on %s for DNSCrypt", cs->local.toStringWithPort());
+    }
+    else {
+      warnlog("Listening on %s", cs->local.toStringWithPort());
+    }
+  }
+
+  cs->ready = true;
+}
+
 struct 
 {
   vector<string> locals;
@@ -2449,291 +2545,42 @@ try
     }
   }
 
-  if(g_cmdLine.locals.size()) {
-    g_locals.clear();
-    for(auto loc : g_cmdLine.locals)
-      g_locals.push_back(std::make_tuple(ComboAddress(loc, 53), true, false, 0, "", std::set<int>()));
-  }
-  
-  if(g_locals.empty())
-    g_locals.push_back(std::make_tuple(ComboAddress("127.0.0.1", 53), true, false, 0, "", std::set<int>()));
-
-  g_configurationDone = true;
-
-  vector<ClientState*> toLaunch;
-  for(const auto& local : g_locals) {
-    ClientState* cs = new ClientState;
-    cs->local= std::get<0>(local);
-    cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0);
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-    //if(g_vm.count("bind-non-local"))
-    bindAny(cs->local.sin4.sin_family, cs->udpFD);
-
-    //    if (!setSocketTimestamps(cs->udpFD))
-    //      g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
-
-
-    if(IsAnyAddress(cs->local)) {
-      int one=1;
-      setsockopt(cs->udpFD, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));     // linux supports this, so why not - might fail on other systems
-#ifdef IPV6_RECVPKTINFO
-      setsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
-#endif
-    }
-
-    if (std::get<2>(local)) {
-#ifdef SO_REUSEPORT
-      SSetsockopt(cs->udpFD, SOL_SOCKET, SO_REUSEPORT, 1);
-#else
-      warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", std::get<0>(local).toStringWithPort());
-#endif
-    }
-
-    const std::string& itf = std::get<4>(local);
-    if (!itf.empty()) {
-#ifdef SO_BINDTODEVICE
-      int res = setsockopt(cs->udpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length());
-      if (res != 0) {
-        warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(local).toStringWithPort(), strerror(errno));
+  if (!g_cmdLine.locals.empty()) {
+    for (auto it = g_frontends.begin(); it != g_frontends.end(); ) {
+      /* TLS and DNSCrypt frontends are separate */
+      if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr) {
+        it = g_frontends.erase(it);
       }
-#else
-      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(local).toStringWithPort());
-#endif
-    }
-
-#ifdef HAVE_EBPF
-    if (g_defaultBPFFilter) {
-      cs->attachFilter(g_defaultBPFFilter);
-      vinfolog("Attaching default BPF Filter to UDP frontend %s", cs->local.toStringWithPort());
-    }
-#endif /* HAVE_EBPF */
-
-    cs->cpus = std::get<5>(local);
-
-    SBind(cs->udpFD, cs->local);
-    toLaunch.push_back(cs);
-    g_frontends.push_back(cs);
-    udpBindsCount++;
-  }
-
-  for(const auto& local : g_locals) {
-    if(!std::get<1>(local)) { // no TCP/IP
-      warnlog("Not providing TCP/IP service on local address '%s'", std::get<0>(local).toStringWithPort());
-      continue;
-    }
-    ClientState* cs = new ClientState;
-    cs->local= std::get<0>(local);
-
-    cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0);
-
-    SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1);
-#ifdef TCP_DEFER_ACCEPT
-    SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1);
-#endif
-    if (std::get<3>(local) > 0) {
-#ifdef TCP_FASTOPEN
-      SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, std::get<3>(local));
-#else
-      warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", std::get<0>(local).toStringWithPort());
-#endif
-    }
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-#ifdef SO_REUSEPORT
-    /* no need to warn again if configured but support is not available, we already did for UDP */
-    if (std::get<2>(local)) {
-      SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1);
-    }
-#endif
-
-    const std::string& itf = std::get<4>(local);
-    if (!itf.empty()) {
-#ifdef SO_BINDTODEVICE
-      int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length());
-      if (res != 0) {
-        warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(local).toStringWithPort(), strerror(errno));
+      else {
+        ++it;
       }
-#else
-      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(local).toStringWithPort());
-#endif
     }
 
-#ifdef HAVE_EBPF
-    if (g_defaultBPFFilter) {
-      cs->attachFilter(g_defaultBPFFilter);
-      vinfolog("Attaching default BPF Filter to TCP frontend %s", cs->local.toStringWithPort());
+    for(const auto& loc : g_cmdLine.locals) {
+      /* UDP */
+      g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(ComboAddress(loc, 53), false, false, 0, "", {})));
+      /* TCP */
+      g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(ComboAddress(loc, 53), true, false, 0, "", {})));
     }
-#endif /* HAVE_EBPF */
-
-    //    if(g_vm.count("bind-non-local"))
-      bindAny(cs->local.sin4.sin_family, cs->tcpFD);
-    SBind(cs->tcpFD, cs->local);
-    SListen(cs->tcpFD, 64);
-    warnlog("Listening on %s", cs->local.toStringWithPort());
-
-    toLaunch.push_back(cs);
-    g_frontends.push_back(cs);
-    tcpBindsCount++;
   }
 
-  for(auto& dcLocal : g_dnsCryptLocals) {
-    ClientState* cs = new ClientState;
-    cs->local = std::get<0>(dcLocal);
-    cs->dnscryptCtx = std::get<1>(dcLocal);
-    cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0);
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-    bindAny(cs->local.sin4.sin_family, cs->udpFD);
-    if(IsAnyAddress(cs->local)) {
-      int one=1;
-      setsockopt(cs->udpFD, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));     // linux supports this, so why not - might fail on other systems
-#ifdef IPV6_RECVPKTINFO
-      setsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); 
-#endif
-    }
-    if (std::get<2>(dcLocal)) {
-#ifdef SO_REUSEPORT
-      SSetsockopt(cs->udpFD, SOL_SOCKET, SO_REUSEPORT, 1);
-#else
-      warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", std::get<0>(dcLocal).toStringWithPort());
-#endif
-    }
-
-    const std::string& itf = std::get<4>(dcLocal);
-    if (!itf.empty()) {
-#ifdef SO_BINDTODEVICE
-      int res = setsockopt(cs->udpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length());
-      if (res != 0) {
-        warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(dcLocal).toStringWithPort(), strerror(errno));
-      }
-#else
-      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(dcLocal).toStringWithPort());
-#endif
-    }
-
-#ifdef HAVE_EBPF
-    if (g_defaultBPFFilter) {
-      cs->attachFilter(g_defaultBPFFilter);
-      vinfolog("Attaching default BPF Filter to UDP DNSCrypt frontend %s", cs->local.toStringWithPort());
-    }
-#endif /* HAVE_EBPF */
-    SBind(cs->udpFD, cs->local);    
-    toLaunch.push_back(cs);
-    g_frontends.push_back(cs);
-    udpBindsCount++;
-
-    cs = new ClientState;
-    cs->local = std::get<0>(dcLocal);
-    cs->dnscryptCtx = std::get<1>(dcLocal);
-    cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0);
-    SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1);
-#ifdef TCP_DEFER_ACCEPT
-    SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1);
-#endif
-    if (std::get<3>(dcLocal) > 0) {
-#ifdef TCP_FASTOPEN
-      SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, std::get<3>(dcLocal));
-#else
-      warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", std::get<0>(dcLocal).toStringWithPort());
-#endif
-    }
-
-#ifdef SO_REUSEPORT
-    /* no need to warn again if configured but support is not available, we already did for UDP */
-    if (std::get<2>(dcLocal)) {
-      SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1);
-    }
-#endif
-
-    if (!itf.empty()) {
-#ifdef SO_BINDTODEVICE
-      int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, itf.c_str(), itf.length());
-      if (res != 0) {
-        warnlog("Error setting up the interface on local address '%s': %s", std::get<0>(dcLocal).toStringWithPort(), strerror(errno));
-      }
-#else
-      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", std::get<0>(dcLocal).toStringWithPort());
-#endif
-    }
-
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-#ifdef HAVE_EBPF
-    if (g_defaultBPFFilter) {
-      cs->attachFilter(g_defaultBPFFilter);
-      vinfolog("Attaching default BPF Filter to TCP DNSCrypt frontend %s", cs->local.toStringWithPort());
-    }
-#endif /* HAVE_EBPF */
-
-    cs->cpus = std::get<5>(dcLocal);
-
-    bindAny(cs->local.sin4.sin_family, cs->tcpFD);
-    SBind(cs->tcpFD, cs->local);
-    SListen(cs->tcpFD, 64);
-    warnlog("Listening on %s", cs->local.toStringWithPort());
-    toLaunch.push_back(cs);
-    g_frontends.push_back(cs);
-    tcpBindsCount++;
+  if (g_frontends.empty()) {
+    /* UDP */
+    g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(ComboAddress("127.0.0.1", 53), false, false, 0, "", {})));
+    /* TCP */
+    g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(ComboAddress("127.0.0.1", 53), true, false, 0, "", {})));
   }
 
-  for(auto& frontend : g_tlslocals) {
-    ClientState* cs = new ClientState;
-    cs->local = frontend->d_addr;
-    cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0);
-    SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEADDR, 1);
-#ifdef TCP_DEFER_ACCEPT
-    SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1);
-#endif
-    if (frontend->d_tcpFastOpenQueueSize > 0) {
-#ifdef TCP_FASTOPEN
-      SSetsockopt(cs->tcpFD, IPPROTO_TCP, TCP_FASTOPEN, frontend->d_tcpFastOpenQueueSize);
-#else
-      warnlog("TCP Fast Open has been configured on local address '%s' but is not supported", cs->local.toStringWithPort());
-#endif
-    }
-    if (frontend->d_reusePort) {
-#ifdef SO_REUSEPORT
-      SSetsockopt(cs->tcpFD, SOL_SOCKET, SO_REUSEPORT, 1);
-#else
-      warnlog("SO_REUSEPORT has been configured on local address '%s' but is not supported", cs->local.toStringWithPort());
-#endif
-    }
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->tcpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-
-    if (!frontend->d_interface.empty()) {
-#ifdef SO_BINDTODEVICE
-      int res = setsockopt(cs->tcpFD, SOL_SOCKET, SO_BINDTODEVICE, frontend->d_interface.c_str(), frontend->d_interface.length());
-      if (res != 0) {
-        warnlog("Error setting up the interface on local address '%s': %s", cs->local.toStringWithPort(), strerror(errno));
-      }
-#else
-      warnlog("An interface has been configured on local address '%s' but SO_BINDTODEVICE is not supported", cs->local.toStringWithPort());
-#endif
-    }
+  g_configurationDone = true;
 
-    cs->cpus = frontend->d_cpus;
+  for(auto& frontend : g_frontends) {
+    setUpLocalBind(frontend);
 
-    bindAny(cs->local.sin4.sin_family, cs->tcpFD);
-    if (frontend->setupTLS()) {
-      cs->tlsFrontend = frontend;
-      SBind(cs->tcpFD, cs->local);
-      SListen(cs->tcpFD, 64);
-      warnlog("Listening on %s for TLS", cs->local.toStringWithPort());
-      toLaunch.push_back(cs);
-      g_frontends.push_back(cs);
-      tcpBindsCount++;
+    if (frontend->tcp == false) {
+      ++udpBindsCount;
     }
     else {
-      errlog("Error while setting up TLS on local address '%s', exiting", cs->local.toStringWithPort());
-      delete cs;
-      _exit(EXIT_FAILURE);
+      ++tcpBindsCount;
     }
   }
 
@@ -2831,16 +2678,16 @@ try
     }
   }
 
-  for(auto& cs : toLaunch) {
+  for(auto& cs : g_frontends) {
     if (cs->udpFD >= 0) {
-      thread t1(udpClientThread, cs);
+      thread t1(udpClientThread, cs.get());
       if (!cs->cpus.empty()) {
         mapThreadToCPUList(t1.native_handle(), cs->cpus);
       }
       t1.detach();
     }
     else if (cs->tcpFD >= 0) {
-      thread t1(tcpAcceptorThread, cs);
+      thread t1(tcpAcceptorThread, cs.get());
       if (!cs->cpus.empty()) {
         mapThreadToCPUList(t1.native_handle(), cs->cpus);
       }
index 663e18061bdb115b3deaef847b91d12ef1fa5d5e..71651495fa54f218a4a2ca2c2e51927fdbf6950a 100644 (file)
@@ -65,6 +65,9 @@ struct DNSQuestion
     const uint16_t* flags = getFlagsFromDNSHeader(dh);
     origFlags = *flags;
   }
+  DNSQuestion(const DNSQuestion&) = delete;
+  DNSQuestion& operator=(const DNSQuestion&) = delete;
+  DNSQuestion(DNSQuestion&&) = default;
 
 #ifdef HAVE_PROTOBUF
   boost::optional<boost::uuids::uuid> uniqueId;
@@ -108,6 +111,9 @@ struct DNSResponse : DNSQuestion
 {
   DNSResponse(const DNSName* name, uint16_t type, uint16_t class_, unsigned int consumed, const ComboAddress* lc, const ComboAddress* rem, struct dnsheader* header, size_t bufferSize, uint16_t responseLen, bool isTcp, const struct timespec* queryTime_):
     DNSQuestion(name, type, class_, consumed, lc, rem, header, bufferSize, responseLen, isTcp, queryTime_) { }
+  DNSResponse(const DNSResponse&) = delete;
+  DNSResponse& operator=(const DNSResponse&) = delete;
+  DNSResponse(DNSResponse&&) = default;
 };
 
 /* so what could you do:
@@ -565,7 +571,7 @@ struct IDState
 };
 
 typedef std::unordered_map<string, unsigned int> QueryCountRecords;
-typedef std::function<std::tuple<bool, string>(DNSQuestion dq)> QueryCountFilter;
+typedef std::function<std::tuple<bool, string>(const DNSQuestion* dq)> QueryCountFilter;
 struct QueryCount {
   QueryCount()
   {
@@ -581,10 +587,15 @@ extern QueryCount g_qcount;
 
 struct ClientState
 {
+  ClientState(const ComboAddress& local_, bool isTCP, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set<int>& cpus_): cpus(cpus_), local(local_), interface(itfName), fastOpenQueueSize(fastOpenQueue), tcp(isTCP), reuseport(doReusePort)
+  {
+  }
+
   std::set<int> cpus;
   ComboAddress local;
   std::shared_ptr<DNSCryptContext> dnscryptCtx{nullptr};
-  shared_ptr<TLSFrontend> tlsFrontend;
+  std::shared_ptr<TLSFrontend> tlsFrontend{nullptr};
+  std::string interface;
   std::atomic<uint64_t> queries{0};
   std::atomic<uint64_t> tcpDiedReadingQuery{0};
   std::atomic<uint64_t> tcpDiedSendingResponse{0};
@@ -597,7 +608,11 @@ struct ClientState
   std::atomic<double> tcpAvgConnectionDuration{0.0};
   int udpFD{-1};
   int tcpFD{-1};
+  int fastOpenQueueSize{0};
   bool muted{false};
+  bool tcp;
+  bool reuseport;
+  bool ready{false};
 
   int getSocket() const
   {
@@ -1008,7 +1023,7 @@ extern ComboAddress g_serverControl; // not changed during runtime
 
 extern std::vector<std::tuple<ComboAddress, bool, bool, int, std::string, std::set<int>>> g_locals; // not changed at runtime (we hope XXX)
 extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals;
-extern vector<ClientState*> g_frontends;
+extern std::vector<std::unique_ptr<ClientState>> g_frontends;
 extern bool g_truncateTC;
 extern bool g_fixupCase;
 extern int g_tcpRecvTimeout;
@@ -1034,6 +1049,7 @@ extern uint16_t g_downstreamTCPCleanupInterval;
 extern size_t g_udpVectorSize;
 extern bool g_preserveTrailingData;
 extern bool g_allowEmptyResponse;
+extern bool g_roundrobinFailOnNoServer;
 
 #ifdef HAVE_EBPF
 extern shared_ptr<BPFFilter> g_defaultBPFFilter;
@@ -1098,7 +1114,7 @@ bool processResponse(char** response, uint16_t* responseLen, size_t* responseSiz
 
 bool checkQueryHeaders(const struct dnsheader* dh);
 
-extern std::vector<std::tuple<ComboAddress, std::shared_ptr<DNSCryptContext>, bool, int, std::string, std::set<int> > > g_dnsCryptLocals;
+extern std::vector<std::shared_ptr<DNSCryptContext>> g_dnsCryptLocals;
 int handleDNSCryptQuery(char* packet, uint16_t len, std::shared_ptr<DNSCryptQuery> query, uint16_t* decryptedQueryLen, bool tcp, time_t now, std::vector<uint8_t>& response);
 boost::optional<std::vector<uint8_t>> checkDNSCryptQuery(const ClientState& cs, const char* query, uint16_t& len, std::shared_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp);
 
index dcc787ea42966e464c9613d1acd878ae415d8db5..dc883b85ce640254a59e0d57349cae6470c142b8 100644 (file)
@@ -13,12 +13,16 @@ AXFR or IXFR queries destined to this master. There are two issues that can aris
 The first issue can be solved by routing SOA, AXFR and IXFR requests explicitly to the master::
 
   newServer({address="192.168.1.2", name="master", pool={"master", "otherpool"}})
-  addAction(OrRule({QTypeRule(dnsdist.SOA), QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), PoolAction("master"))
+  addAction(OrRule({QTypeRule(DNSQType.SOA), QTypeRule(DNSQType.AXFR), QTypeRule(DNSQType.IXFR)}), PoolAction("master"))
 
 The second one might require allowing AXFR/IXFR from the :program:`dnsdist` source address
 and moving the source address check to :program:`dnsdist`'s side::
 
-  addAction(AndRule({OrRule({QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
+  addAction(AndRule({OrRule({QTypeRule(DNSQType.AXFR), QTypeRule(DNSQTypeIXFR)}), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(DNSRCode.REFUSED))
+
+.. versionchanged:: 1.4.0
+  Before 1.4.0, the QTypes were in the ``dnsdist`` namespace. Use ``dnsdist.AXFR`` and ``dnsdist.IXFR`` in these versions.
+  Before 1.4.0, the RCodes were in the ``dnsdist`` namespace. Use ``dnsdist.REFUSED`` in these versions.
 
 When :program:`dnsdist` is deployed in front of slaves, however, an issue might arise with NOTIFY
 queries, because the slave will receive a notification coming from the :program:`dnsdist` address,
@@ -26,5 +30,7 @@ and not the master's one. One way to fix this issue is to allow NOTIFY from the
 address on the slave side (for example with PowerDNS's `trusted-notification-proxy`) and move the address
 check to :program:`dnsdist`'s side::
 
-  addAction(AndRule({OpcodeRule(DNSOpcode.Notify), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
+  addAction(AndRule({OpcodeRule(DNSOpcode.Notify), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(DNSRCode.REFUSED))
 
+.. versionchanged:: 1.4.0
+  Before 1.4.0, the RCodes were in the ``dnsdist`` namespace. Use ``dnsdist.REFUSED`` in these versions.
\ No newline at end of file
index 48ec0fa6356616ac2b69e3cce58aa699cc3315b7..3fea22211767cf0d592f6ec2d3191eee424cdb67 100644 (file)
@@ -1,6 +1,270 @@
 Changelog
 =========
 
+.. changelog::
+  :version: 1.4.0-alpha1
+  :released: 12th of April 2019
+
+ .. change::
+    :tags: Improvements
+    :pullreq: 7167
+
+    Fix compiler warning about returning garbage (Adam Majer)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7168
+
+    Fix warnings, mostly unused parameters, reported by -wextra
+
+  .. change::
+    :tags: New Features
+    :pullreq: 6959
+    :tickets: 6941, 2362
+
+    Add namespace and instance variable to carbon key (Gibheer)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7191
+
+    Add optional uuid column to showServers()
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7087
+
+    Allow NoRecurse for use in dynamic blocks or Lua rules (phonedph1)
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7197
+    :tickets: 7194
+
+    Expose secpoll status
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7026
+
+    Configure --enable-pdns-option --with-third-party-module (Josh Soref)
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7256
+
+    Protect GnuTLS tickets key rotation with a read-write lock
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7267
+
+    Check that ``SO_ATTACH_BPF`` is defined before enabling eBPF
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7138
+
+    Drop remaining capabilities after startup
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7323
+    :tickets: 7236
+
+    Add an optional 'checkTimeout' parameter to 'newServer()'
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7322
+    :tickets: 7237
+
+    Add a 'rise' parameter to 'newServer()'
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7310
+    :tickets: 7239
+
+    Add a 'keepStaleData' option to the packet cache
+
+  .. change::
+    :tags: New Features
+    :pullreq: 6967
+    :tickets: 6846, 6897
+
+    Expose trailing data (Richard Gibson)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 6634
+
+    More sandboxing using systemd's features
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7426
+
+    Fix off-by-one in mvRule counting
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7428
+
+    Reduce systemcall usage in Protobuf logging
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7433
+
+    Resync YaHTTP code to cmouse/yahttp@11be77a1fc4032 (Chris Hofstaedtler)
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7142
+
+    Add option to set interval between health checks (1848)
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7406
+
+    Add EDNS unknown version handling (Dmitry Alenichev)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7431
+
+    Pass empty response (Dmitry Alenichev)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7502
+
+    Change the way getRealMemusage() works on linux (using statm)
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7520
+
+    Don't convert nsec to usec if we need nsec
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7537
+
+    DNSNameSet and QNameSetRule (Andrey)
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7594
+
+    Fix setRules()
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7560
+
+    Handle EAGAIN in the GnuTLS DNS over TLS provider
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7586
+    :tickets: 7461
+
+    Gracefully handle a null latency in the webserver's js
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7585
+    :tickets: 7534
+
+     Prevent 0-ttl cache hits
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7343
+    :tickets: 7139
+
+    Add addDynBlockSMT() support to dynBlockRulesGroup
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7578
+
+    Add frontend response statistics (Matti Hiljanen)
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7652
+
+   EDNSOptionView improvements
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7481
+    :tickets: 6242
+
+    Add support for encrypting ip addresses #gdpr 
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7670
+
+    Remove addLuaAction and addLuaResponseAction
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7559
+    :tickets: 7526, 4814
+
+    Refactoring of the TCP stack
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 7674
+    :tickets: 7481
+
+    Honor libcrypto include path
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7677
+    :tickets: 5653
+
+    Add 'setSyslogFacility()'
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7692
+    :tickets: 7556
+
+    Prevent a conflict with BADSIG being clobbered
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7689
+
+    Switch to the new 'newPacketCache()' syntax for 1.4.0
+
+  .. change::
+    :tags: New Features
+    :pullreq: 7676
+
+    Add 'reloadAllCertificates()'
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7678
+
+    Move constants to proper namespace
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 7694
+
+    Unify the management of DNS/DNSCrypt/DoT frontends
+
 .. changelog::
   :version: 1.3.3
   :released: 8th of November 2018
index 1a6bdd3e3a7d7a17a8c3954a7f5de482d919f6bf..167c1503e13c42267ee8762c18740e50d3980fc2 100644 (file)
@@ -5,7 +5,7 @@ Caching Responses
 It is enabled per-pool, but the same cache can be shared between several pools.
 The first step is to define a cache with :func:`newPacketCache`, then to assign that cache to the chosen pool, the default one being represented by the empty string::
 
-  pc = newPacketCache(10000, 86400, 0, 60, 60, false)
+  pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false})
   getPool(""):setCache(pc)
 
  + The first parameter (10000) is the maximum number of entries stored in the cache, and is the only one required. All the other parameters are optional and in seconds, except the last one which is a boolean.
@@ -49,7 +49,10 @@ For example, to remove all expired entries::
 
 Specific entries can also be removed using the :meth:`PacketCache:expungeByName` method::
 
-  getPool("poolname"):getCache():expungeByName(newDNSName("powerdns.com"), dnsdist.A)
+  getPool("poolname"):getCache():expungeByName(newDNSName("powerdns.com"), DNSQType.A)
+
+.. versionchanged:: 1.4.0
+  Before 1.4.0, the QTypes were in the ``dnsdist`` namespace. Use ``dnsdist.A`` in these versions.
 
 Finally, the :meth:`PacketCache:expunge` method will remove all entries until at most n entries remain in the cache::
 
index 191b934d6983d066c3e509230477086b3fd6ac6c..7e7a4495d27b374cd6127beb847c4d90769059ba 100644 (file)
@@ -54,6 +54,7 @@ You can also set the hash perturbation value, see :func:`setWHashedPertubation`.
 ~~~~~~~~~~~~~~
 
 The last available policy is ``roundrobin``, which indiscriminately sends each query to the next server that is up.
+If all servers are down, the policy will still select one server by default. Setting :func:`setRoundRobinFailOnNoServer` to ``true`` will change this behavior.
 
 Lua server policies
 -------------------
@@ -131,7 +132,7 @@ Functions
 
   If set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query.
 
-  :param bool value:
+  :param bool value: whether to return a servfail instead of dropping the query
 
 .. function:: setPoolServerPolicy(policy, pool)
 
@@ -148,6 +149,14 @@ Functions
   :param string function: name of the function
   :param string pool: Name of the pool
 
+.. function:: setRoundRobinFailOnNoServer(value)
+
+  .. versionadded:: 1.4.0
+
+  By default the roundrobin load-balancing policy will still try to select a backend even if all backends are currently down. Setting this to true will make the policy fail and return that no server is available instead.
+
+  :param bool value: whether to fail when all servers are down
+
 .. function:: showPoolServerPolicy(pool)
 
   Print server selection policy for ``pool``.
index 1f78d14b623a38791fb9a83edec0adbeacd5e165..4252d890a2f2dee69d395064950435e755572999 100644 (file)
@@ -42,6 +42,12 @@ Global configuration
 
   :param str path: The directory to load configuration files from. Each file must end in ``.conf``.
 
+.. function:: reloadAllCertificates()
+
+  .. versionadded:: 1.4.0
+
+  Reload all DNSCrypt and TLS certificates, along with their associated keys.
+
 .. function:: setSyslogFacility(facility)
 
   .. versionadded:: 1.4.0
@@ -608,7 +614,7 @@ See :doc:`../guides/cache` for a how to.
 
     :param int n: Number of entries to keep
 
-  .. method:: PacketCache:expungeByName(name [, qtype=dnsdist.ANY[, suffixMatch=false]])
+  .. method:: PacketCache:expungeByName(name [, qtype=DNSQType.ANY[, suffixMatch=false]])
 
     .. versionchanged:: 1.2.0
       ``suffixMatch`` parameter added.
@@ -616,7 +622,7 @@ See :doc:`../guides/cache` for a how to.
     Remove entries matching ``name`` and type from the cache.
 
     :param DNSName name: The name to expunge
-    :param int qtype: The type to expunge
+    :param int qtype: The type to expunge, can be a pre-defined :ref:`DNSQType`
     :param bool suffixMatch: When set to true, remove al entries under ``name``
 
   .. method:: PacketCache:getStats()
index 248f67148ec1160cf79d618b4b3a7a0e64e63ed9..03793cfa2cb6a59eea53c15d92979a074295f1f2 100644 (file)
@@ -8,6 +8,8 @@ There are many constants in :program:`dnsdist`.
 OPCode
 ------
 
+These constants represent the `OpCode <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5>`__ of a query.
+
 - ``DNSOpcode.Query``
 - ``DNSOpcode.IQuery``
 - ``DNSOpcode.Status``
@@ -21,6 +23,8 @@ Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#
 DNSClass
 ------
 
+These constants represent the `CLASS <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2>`__ of a DNS record.
+
 - ``DNSClass.IN``
 - ``DNSClass.CHAOS``
 - ``DNSClass.NONE``
@@ -33,31 +37,34 @@ Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#
 RCode
 -----
 
-- ``dnsdist.NOERROR``
-- ``dnsdist.FORMERR``
-- ``dnsdist.SERVFAIL``
-- ``dnsdist.NXDOMAIN``
-- ``dnsdist.NOTIMP``
-- ``dnsdist.REFUSED``
-- ``dnsdist.YXDOMAIN``
-- ``dnsdist.YXRRSET``
-- ``dnsdist.NXRRSET``
-- ``dnsdist.NOTAUTH``
-- ``dnsdist.NOTZONE``
-- ``dnsdist.BADVERS``
-- ``dnsdist.BADSIG``
-- ``dnsdist.BADKEY``
-- ``dnsdist.BADTIME``
-- ``dnsdist.BADMODE``
-- ``dnsdist.BADNAME``
-- ``dnsdist.BADALG``
-- ``dnsdist.BADTRUNC``
-- ``dnsdist.BADCOOKIE``
-
-RCodes below and including ``BADVERS`` are extended RCodes that can only be matched using :func:`ERCodeRule`.
-
-Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
-
+These constants represent the different `RCODEs <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6>`__ for DNS messages.
+
+.. versionchanged:: 1.4.0
+  The prefix is changed from ``dnsdist`` to ``DNSRCode``.
+
+- ``DNSRCode.NOERROR``
+- ``DNSRCode.FORMERR``
+- ``DNSRCode.SERVFAIL``
+- ``DNSRCode.NXDOMAIN``
+- ``DNSRCode.NOTIMP``
+- ``DNSRCode.REFUSED``
+- ``DNSRCode.YXDOMAIN``
+- ``DNSRCode.YXRRSET``
+- ``DNSRCode.NXRRSET``
+- ``DNSRCode.NOTAUTH``
+- ``DNSRCode.NOTZONE``
+
+RCodes below are extended RCodes that can only be matched using :func:`ERCodeRule`.
+
+- ``DNSRCode.BADVERS``
+- ``DNSRCode.BADSIG``
+- ``DNSRCode.BADKEY``
+- ``DNSRCode.BADTIME``
+- ``DNSRCode.BADMODE``
+- ``DNSRCode.BADNAME``
+- ``DNSRCode.BADALG``
+- ``DNSRCode.BADTRUNC``
+- ``DNSRCode.BADCOOKIE``
 
 .. _EDNSOptionCode:
 
@@ -80,8 +87,10 @@ Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#
 
 .. _DNSSection:
 
-DNS Section
------------
+DNS Packet Sections
+-------------------
+
+These constants represent the section in the DNS Packet.
 
 - ``DNSSection.Question``
 - ``DNSSection.Answer``
@@ -109,6 +118,22 @@ These constants represent an Action that can be returned from :func:`LuaAction`
  * ``DNSAction.Truncate``: truncate the response
  * ``DNSAction.NoRecurse``: set rd=0 on the query
 
+.. _DNSQType:
+
+DNSQType
+--------
+
+.. versionchanged:: 1.3.0
+  The prefix is changed from ``dnsdist.`` to ``DNSQType``.
+
+All named `QTypes <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4>`__ are available as constants, prefixed with ``DNSQType.``, e.g.:
+
+ * ``DNSQType.AAAA``
+ * ``DNSQType.AXFR``
+ * ``DNSQType.A``
+ * ``DNSQType.NS``
+ * ``DNSQType.SOA``
+ * etc.
 
 .. _DNSResponseAction:
 
index 117ac18bb0b49eb806f111fc47270c33cf1b1f5f..e451eb62e06616619ff862d6cd75970def55b775 100644 (file)
@@ -47,7 +47,7 @@ This state can be modified from the various hooks.
   .. attribute:: DNSQuestion.qtype
 
     QType (as an unsigned integer) of this question.
-    Can be compared against ``dnsdist.A``, ``dnsdist.AAAA`` etc.
+    Can be compared against the pre-defined :ref:`constants <DNSQType>` like ``DNSQType.A``, DNSQType.AAAA``.
 
   .. attribute:: DNSQuestion.remoteaddr
 
@@ -170,7 +170,7 @@ DNSResponse object
 
     - ``section`` is the section in the packet and can be compared to :ref:`DNSSection`
     - ``qclass`` is the QClass of the record. Can be compared to :ref:`DNSQClass`
-    - ``qtype`` is the QType of the record. Can be e.g. compared to ``dnsdist.A``, ``dnsdist.AAAA`` and the like.
+    - ``qtype`` is the QType of the record. Can be e.g. compared to ``DNSQType.A``, ``DNSQType.AAAA`` :ref:`constants <DNSQType>` and the like.
     - ``ttl`` is the current TTL
 
     This function must return an integer with the new TTL.
index ec23c155e3b4eb7800725826f484ca7aa25fcc57..f2ad20a6d30e33652c1b39ed4f4d478f73a4a498 100644 (file)
@@ -81,7 +81,10 @@ Rule Generators
   Set the TC-bit (truncate) on ANY queries received over UDP, forcing a retry over TCP.
   This function is deprecated as of 1.2.0 and will be removed in 1.3.0. This is equivalent to doing::
 
-    addAction(AndRule({QTypeRule(dnsdist.ANY), TCPRule(false)}), TCAction())
+   addAction(AndRule({QTypeRule(DNSQType.ANY), TCPRule(false)}), TCAction())
+
+  .. versionchanged:: 1.4.0
+    Before 1.4.0, the QTypes were in the ``dnsdist`` namespace. Use ``dnsdist.ANY`` in these versions.
 
 .. function:: addDelay(DNSrule, delay)
 
@@ -718,7 +721,7 @@ These ``DNSRule``\ s be one of the following items:
 
   Matches if there is at least ``minCount`` and at most ``maxCount`` records of type ``type`` in the section ``section``.
   ``section`` can be specified as an integer or as a ref:`DNSSection`.
-  ``qtype`` may be specified as an integer or as one of the built-in QTypes, for instance ``dnsdist.A`` or ``dnsdist.TXT``.
+  ``qtype`` may be specified as an integer or as one of the :ref:`built-in QTypes <DNSQType>`, for instance ``DNSQType.A`` or ``DNSQType.TXT``.
 
   :param int section: The section to match on
   :param int qtype: The QTYPE to match on
index 756c08249b587346d9bad99fd3ff66dec11ce82c..4de4298cfb40aa3e2df15dc65ad0cf47edd1c259 100644 (file)
@@ -6,6 +6,20 @@ Upgrade Guide
 
 :func:`addLuaAction` and :func:`addLuaResponseAction` have been removed. Instead, use :func:`addAction` with a :func:`LuaAction`, or :func:`addResponseAction` with a :func:`LuaResponseAction`.
 
+:func:`newPacketCache` now takes an optional table as its second argument, instead of several optional parameters.
+
+Lua's constants for DNS response codes and QTypes have been moved from the 'dnsdist' prefix to, respectively, the 'DNSQType' and 'DNSRCode' prefix.
+
+To improve security, all ambient capabilities are now dropped after the startup phase, which might prevent launching the webserver on a privileged port at run-time, or impact some custom Lua code. In addition, systemd's sandboxing features are now determined at compile-time, resulting in more restrictions on recent distributions. See pull requests 7138 and 6634 for more information.
+
+If you are compiling dnsdist, note that several ./configure options have been renamed to provide a more consistent experience. Features that depend on an external component have been prefixed with '--with-' while internal features use '--enable-'. This lead to the following changes:
+
+- ``--enable-fstrm`` to ``--enable-dnstap``
+- ``--enable-gnutls`` to ``--with-gnutls``
+- ``--enable-libsodium`` to ``--with-libsodium``
+- ``--enable-libssl`` to ``--with-libssl``
+- ``--enable-re2`` to ``--with-re2``
+
 1.3.2 to 1.3.3
 --------------
 
index 3ee1f46c35b83d42fbb53d4633b686aad85861c6..32731c85b5a5c21dc174c819f1e0f5cca34e899d 100644 (file)
@@ -958,7 +958,7 @@ public:
 
     rc = gnutls_priority_init(&d_priorityCache, fe.d_ciphers.empty() ? "NORMAL" : fe.d_ciphers.c_str(), nullptr);
     if (rc != GNUTLS_E_SUCCESS) {
-      warnlog("Error setting up TLS cipher preferences to %s (%s), skipping.", fe.d_ciphers.c_str(), gnutls_strerror(rc));
+      throw std::runtime_error("Error setting up TLS cipher preferences to '" + fe.d_ciphers + "' (" + gnutls_strerror(rc) + ") on " + fe.d_addr.toStringWithPort());
     }
 
     pthread_rwlock_init(&d_lock, nullptr);
index 498e03c9243df8334ce40ccec24e0741320387f9..6454c342cfbf51f28e9ccf0ea6df61668d6185fe 100644 (file)
@@ -278,7 +278,7 @@ union ComboAddress {
     char host[1024];
     int retval = 0;
     if(sin4.sin_family && !(retval = getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST)))
-      return host;
+      return string(host);
     else
       return "invalid "+string(gai_strerror(retval));
   }
index 08c42251cf70df8aeb2dd10c4d6cf7ddf96048b4..9b6eea36d56b2668367ed46974fb98a7b58805e5 100644 (file)
@@ -202,7 +202,7 @@ string nowTime()
   // YYYY-mm-dd HH:MM:SS TZOFF
   strftime(buffer, sizeof(buffer), "%F %T %z", tm);
   buffer[sizeof(buffer)-1] = '\0';
-  return buffer;
+  return string(buffer);
 }
 
 uint16_t getShort(const unsigned char *p)
@@ -498,7 +498,7 @@ string getHostname()
   if(gethostname(tmp, MAXHOSTNAMELEN))
     return "UNKNOWN";
 
-  return tmp;
+  return string(tmp);
 }
 
 string itoa(int i)
@@ -571,7 +571,7 @@ string U32ToIP(uint32_t val)
            (val >> 16)&0xff,
            (val >>  8)&0xff,
            (val      )&0xff);
-  return tmp;
+  return string(tmp);
 }
 
 
index 762901a0cb8ddd67229c5734c6f2b0c512684feb..49fc8bcf50225e3525c5a4e1ef8ee7db402b0dc3 100644 (file)
@@ -57,7 +57,7 @@ Homebrew. You need to tell configure where to find OpenSSL, too.
 
 ```sh
 brew install boost lua pkg-config ragel openssl
-./configure --with-modules="" --with-lua PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig
+./configure --with-lua PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig
 make -j4
 ```
 
index d62a64c194c8cbd195db0c83d905585d048c9f2e..a49068f385fc43f02ce32239cf127d698e7d0f2f 100644 (file)
@@ -126,7 +126,9 @@ static void checkECSOptionValidity(const std::string& sourceStr, uint8_t sourceM
   uint8_t sourceBytes = ((sourceMask - 1) >> 3) + 1;
   BOOST_REQUIRE_EQUAL(ecsOptionStr.size(), (ecsHeaderSize + sourceBytes));
   /* family */
-  BOOST_REQUIRE_EQUAL(ntohs(*(reinterpret_cast<const uint16_t*>(&ecsOptionStr.at(0)))), source.isIPv4() ? 1 : 2);
+  uint16_t u;
+  memcpy(&u, ecsOptionStr.c_str(), sizeof(u));
+  BOOST_REQUIRE_EQUAL(ntohs(u), source.isIPv4() ? 1 : 2);
   /* source mask */
   BOOST_REQUIRE_EQUAL(static_cast<uint8_t>(ecsOptionStr.at(2)), sourceMask);
   BOOST_REQUIRE_EQUAL(static_cast<uint8_t>(ecsOptionStr.at(3)), scopeMask);
index e14c535d859a24d3065ec6b937bf6f599f655383..5c2c90a0532b291c1be88488a8ba8c6d2fc650c8 100644 (file)
@@ -137,19 +137,15 @@ public:
     return res;
   }
 
-  std::set<int> d_cpus;
   std::vector<std::pair<std::string, std::string>> d_certKeyPairs;
   ComboAddress d_addr;
   std::string d_ciphers;
   std::string d_provider;
-  std::string d_interface;
   std::string d_ticketKeyFile;
 
   size_t d_maxStoredSessions{20480};
   time_t d_ticketsKeyRotationDelay{43200};
-  int d_tcpFastOpenQueueSize{0};
   uint8_t d_numberOfTicketsKeys{5};
-  bool d_reusePort{false};
   bool d_enableTickets{true};
 
 private:
index f34968e7416f8a3f65739b823b08262c3bf1b79a..100dd47109fbf539896e8d769d4cd45b1a4610b2 100644 (file)
@@ -1105,8 +1105,7 @@ static DNSQuestion getDNSQuestion(const DNSName& qname, const uint16_t qtype, co
 {
   dnsheader* dh = reinterpret_cast<dnsheader*>(query.data());
 
-  DNSQuestion dq(&qname, qtype, qclass, qname.wirelength(), &lc, &rem, dh, query.size(), len, false, &realTime);
-  return dq;
+  return DNSQuestion(&qname, qtype, qclass, qname.wirelength(), &lc, &rem, dh, query.size(), len, false, &realTime);
 }
 
 static DNSQuestion turnIntoResponse(const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const ComboAddress& lc, const ComboAddress& rem, const struct timespec& queryRealTime, vector<uint8_t>&  query, bool resizeBuffer=true)
index 45e34dfbe7a8bcd9f860735e1b1f235657e4c708..e83d947c85d8148d71178a001d757e9b74b741c1 100755 (executable)
@@ -32,6 +32,9 @@ if [ "${PDNS_DEBUG}" = "YES" ]; then
   set -x
 fi
 
+rm -f ca.key ca.pem ca.srl server.csr server.key server.pem server.chain
+rm -rf configs/*
+
 # Generate a new CA
 openssl req -new -x509 -days 1 -extensions v3_ca -keyout ca.key -out ca.pem -nodes -config configCA.conf
 # Generate a new server certificate request
@@ -39,7 +42,7 @@ openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -con
 # Sign the server cert
 openssl x509 -req -days 1 -CA ca.pem -CAkey ca.key -CAcreateserial -in server.csr -out server.pem
 # Generate a chain
-cat server.pem ca.pem >> server.chain
+cat server.pem ca.pem > server.chain
 
 if ! nosetests --with-xunit $@; then
     for log in configs/*.log; do
index 0b358ca7e64bc9ba41229156c4bf1c6f614803e0..01bc901baea5eacfff5f366b4bea6a74ef22cdb2 100644 (file)
@@ -1 +1 @@
-addAction(AllRule(), RCodeAction(dnsdist.REFUSED))
+addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
index 78105512e88963f88d4a6a052003837d173f549f..4a4c7e55535a62170cc1429b3518eed36561fd46 100644 (file)
@@ -452,7 +452,7 @@ class TestAdvancedTruncateAnyAndTCP(DNSDistTest):
 class TestAdvancedAndNot(DNSDistTest):
 
     _config_template = """
-    addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))
+    addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
     newServer{address="127.0.0.1:%s"}
     """
     def testAOverUDPReturnsNotImplementedCanary(self):
@@ -519,7 +519,7 @@ class TestAdvancedAndNot(DNSDistTest):
 class TestAdvancedOr(DNSDistTest):
 
     _config_template = """
-    addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))
+    addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
     newServer{address="127.0.0.1:%s"}
     """
     def testAAAAOverUDPReturnsNotImplemented(self):
@@ -885,7 +885,7 @@ class TestAdvancedQPSNone(DNSDistTest):
 
     _config_template = """
     addAction("qpsnone.advanced.tests.powerdns.com", QPSAction(100))
-    addAction(AllRule(), RCodeAction(dnsdist.REFUSED))
+    addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -912,7 +912,7 @@ class TestAdvancedNMGRule(DNSDistTest):
     _config_template = """
     allowed = newNMG()
     allowed:addMask("192.0.2.1/32")
-    addAction(NotRule(NetmaskGroupRule(allowed)), RCodeAction(dnsdist.REFUSED))
+    addAction(NotRule(NetmaskGroupRule(allowed)), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -937,7 +937,7 @@ class TestDSTPortRule(DNSDistTest):
 
     _config_params = ['_dnsDistPort', '_testServerPort']
     _config_template = """
-    addAction(DSTPortRule(%d), RCodeAction(dnsdist.REFUSED))
+    addAction(DSTPortRule(%d), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -962,7 +962,7 @@ class TestDSTPortRule(DNSDistTest):
 class TestAdvancedLabelsCountRule(DNSDistTest):
 
     _config_template = """
-    addAction(QNameLabelsCountRule(5,6), RCodeAction(dnsdist.REFUSED))
+    addAction(QNameLabelsCountRule(5,6), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -1015,7 +1015,7 @@ class TestAdvancedLabelsCountRule(DNSDistTest):
 class TestAdvancedWireLengthRule(DNSDistTest):
 
     _config_template = """
-    addAction(QNameWireLengthRule(54,56), RCodeAction(dnsdist.REFUSED))
+    addAction(QNameWireLengthRule(54,56), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -1351,7 +1351,7 @@ com.""")
 class TestAdvancedRD(DNSDistTest):
 
     _config_template = """
-    addAction(RDRule(), RCodeAction(dnsdist.REFUSED))
+    addAction(RDRule(), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -1654,7 +1654,7 @@ class TestAdvancedEDNSVersionRule(DNSDistTest):
 
     _config_template = """
     newServer{address="127.0.0.1:%s"}
-    addAction(EDNSVersionRule(0), ERCodeAction(dnsdist.BADVERS))
+    addAction(EDNSVersionRule(0), ERCodeAction(DNSRCode.BADVERS))
     """
 
     def testDropped(self):
index 4ecdb096e0278093a4847068c4a149c82b8ab373..5dfda57d21467c8a49411f3564aeb5cc23c87b37 100644 (file)
@@ -9,15 +9,15 @@ class TestBasics(DNSDistTest):
     _config_template = """
     newServer{address="127.0.0.1:%s"}
     truncateTC(true)
-    addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction())
-    addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(dnsdist.REFUSED))
+    addAction(AndRule{QTypeRule(DNSQType.ANY), TCPRule(false)}, TCAction())
+    addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(DNSRCode.REFUSED))
     mySMN = newSuffixMatchNode()
     mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com."))
-    addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(dnsdist.NOTIMP))
+    addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(DNSRCode.NOTIMP))
     addAction(makeRule("drop.test.powerdns.com."), DropAction())
-    addAction(AndRule({QTypeRule(dnsdist.A),QNameRule("ds9a.nl")}), SpoofAction("1.2.3.4"))
-    addAction(newDNSName("dnsname.addaction.powerdns.com."), RCodeAction(dnsdist.REFUSED))
-    addAction({newDNSName("dnsname-table1.addaction.powerdns.com."), newDNSName("dnsname-table2.addaction.powerdns.com.")}, RCodeAction(dnsdist.REFUSED))
+    addAction(AndRule({QTypeRule(DNSQType.A),QNameRule("ds9a.nl")}), SpoofAction("1.2.3.4"))
+    addAction(newDNSName("dnsname.addaction.powerdns.com."), RCodeAction(DNSRCode.REFUSED))
+    addAction({newDNSName("dnsname-table1.addaction.powerdns.com."), newDNSName("dnsname-table2.addaction.powerdns.com.")}, RCodeAction(DNSRCode.REFUSED))
     """
 
     def testDropped(self):
index 60a898b65b294190f6b5a47acf9cf0321c2d9e0d..aba9d554bd98397f14bf26e49addec30422ecbb0 100644 (file)
@@ -1038,7 +1038,7 @@ class TestCacheManagement(DNSDistTest):
         self.assertEquals(receivedResponse, response2)
 
         # remove cached entries from name A
-        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"" + name + "\"), dnsdist.A)")
+        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"" + name + "\"), DNSQType.A)")
 
         # Miss for name A
         (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
@@ -1119,7 +1119,7 @@ class TestCacheManagement(DNSDistTest):
         self.assertEquals(receivedResponse, response2)
 
         # remove cached entries from name
-        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffix.cache.tests.powerdns.com.\"), dnsdist.ANY, true)")
+        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffix.cache.tests.powerdns.com.\"), DNSQType.ANY, true)")
 
         # Miss for name
         (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
@@ -1200,7 +1200,7 @@ class TestCacheManagement(DNSDistTest):
         self.assertEquals(receivedResponse, response2)
 
         # remove cached entries from name A
-        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffixtype.cache.tests.powerdns.com.\"), dnsdist.A, true)")
+        self.sendConsoleCommand("getPool(\"\"):getCache():expungeByName(newDNSName(\"suffixtype.cache.tests.powerdns.com.\"), DNSQType.A, true)")
 
         # Miss for name A
         (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
index ba3befb185721e858b7e9066075434d294849541..ce9345c05ed68d684a370432a925b3033617c0a1 100644 (file)
@@ -33,11 +33,11 @@ class TestCheckConfig(unittest.TestCase):
         configTemplate = """
             newServer{address="127.0.0.1:53"}
             truncateTC(true)
-            addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction())
-            addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(dnsdist.REFUSED))
+            addAction(AndRule{QTypeRule(DNSQType.ANY), TCPRule(false)}, TCAction())
+            addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(DNSRCode.REFUSED))
             mySMN = newSuffixMatchNode()
             mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com."))
-            addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(dnsdist.NOTIMP))
+            addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(DNSRCode.NOTIMP))
             addAction(makeRule("drop.test.powerdns.com."), DropAction())
         """
 
index 78e71bffc89556d39f3b0e66e7188567929e1642..f91647e7b7c5ec0404422a5613a0a1d18c013d55 100644 (file)
@@ -102,7 +102,7 @@ class TestDnstapOverRemoteLogger(DNSDistTest):
 
     function luaFunc(dq)
       dq.dh:setQR(true)
-      dq.dh:setRCode(dnsdist.NXDOMAIN)
+      dq.dh:setRCode(DNSRCode.NXDOMAIN)
       return DNSAction.None, ""
     end
 
index a5768b5fb835ddc96c2630296db1541497d4bedf..06260357451cb295abb7aa0b3843486b656b184d 100644 (file)
@@ -803,7 +803,7 @@ class TestDynBlockGroupServFails(DynBlocksTest):
     _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort']
     _config_template = """
     local dbr = dynBlockRulesGroup()
-    dbr:setRCodeRate(dnsdist.SERVFAIL, %d, %d, "Exceeded query rate", %d)
+    dbr:setRCodeRate(DNSRCode.SERVFAIL, %d, %d, "Exceeded query rate", %d)
 
     function maintenance()
            dbr:apply()
index c1d7c56f28ef69d9112be53ad38b782764395319..c5cb99bd7bd8a115d3d3a99dc3b25927483fe031 100644 (file)
@@ -11,7 +11,7 @@ class TestEDNSSelfGenerated(DNSDistTest):
     """
 
     _config_template = """
-    addAction("rcode.edns-self.tests.powerdns.com.", RCodeAction(dnsdist.REFUSED))
+    addAction("rcode.edns-self.tests.powerdns.com.", RCodeAction(DNSRCode.REFUSED))
     addAction("tc.edns-self.tests.powerdns.com.", TCAction())
 
     function luarule(dq)
@@ -262,7 +262,7 @@ class TestEDNSSelfGeneratedDisabled(DNSDistTest):
     _config_template = """
     setAddEDNSToSelfGeneratedResponses(false)
 
-    addAction("rcode.edns-self-disabled.tests.powerdns.com.", RCodeAction(dnsdist.REFUSED))
+    addAction("rcode.edns-self-disabled.tests.powerdns.com.", RCodeAction(DNSRCode.REFUSED))
     addAction("tc.edns-self-disabled.tests.powerdns.com.", TCAction())
 
     function luarule(dq)
index 8e25488c07ebc84b6e77d1bacc3967889368cfce..efccf206ff7af8591c91096e6ecb4a691312b1c2 100644 (file)
@@ -163,7 +163,7 @@ class TestHealthCheckCustomFunction(HealthCheckTest):
     function myHealthCheckFunction(qname, qtype, qclass, dh)
       dh:setCD(true)
 
-      return newDNSName('powerdns.com.'), dnsdist.AAAA, qclass
+      return newDNSName('powerdns.com.'), DNSQType.AAAA, qclass
     end
 
     srv = newServer{address="127.0.0.1:%d", checkName='powerdns.org.', checkFunction=myHealthCheckFunction}
index d7bacbb6323805bc2d05c795bcd50033cd03087d..f8345d2092cb70f191758823f8484767c735d41e 100644 (file)
@@ -198,7 +198,7 @@ class TestProtobuf(DNSDistProtobufTest):
         protobuf:setTagArray(tablePB)                          -- store table in protobuf
         protobuf:setTag("Query,123")                           -- add another tag entry in protobuf
 
-        protobuf:setResponseCode(dnsdist.NXDOMAIN)             -- set protobuf response code to be NXDOMAIN
+        protobuf:setResponseCode(DNSRCode.NXDOMAIN)            -- set protobuf response code to be NXDOMAIN
 
         local strReqName = dq.qname:toString()                 -- get request dns name
 
@@ -409,7 +409,7 @@ class TestProtobufIPCipher(DNSDistProtobufTest):
         """
         name = 'query.protobuf-ipcipher.tests.powerdns.com.'
 
-        target = 'target.protobuf-ipcipher.tests.powerdns.com.'
+        target = b'target.protobuf-ipcipher.tests.powerdns.com.'
         query = dns.message.make_query(name, 'A', 'IN')
         response = dns.message.make_response(query)
 
index 4b9ce8b27a9cd372ceeff18555d2f21402abbc30..1abe575fd0991168e83c3ccbcc18d26311b05d9f 100644 (file)
@@ -7,7 +7,7 @@ from dnsdisttests import DNSDistTest
 class TestRecordsCountOnlyOneAR(DNSDistTest):
 
     _config_template = """
-    addAction(NotRule(RecordsCountRule(DNSSection.Additional, 1, 1)), RCodeAction(dnsdist.REFUSED))
+    addAction(NotRule(RecordsCountRule(DNSSection.Additional, 1, 1)), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -79,7 +79,7 @@ class TestRecordsCountMoreThanOneLessThanFour(DNSDistTest):
 
     _config_template = """
     addAction(RecordsCountRule(DNSSection.Answer, 2, 3), AllowAction())
-    addAction(AllRule(), RCodeAction(dnsdist.REFUSED))
+    addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -156,7 +156,7 @@ class TestRecordsCountNothingInNS(DNSDistTest):
 
     _config_template = """
     addAction(RecordsCountRule(DNSSection.Authority, 0, 0), AllowAction())
-    addAction(AllRule(), RCodeAction(dnsdist.REFUSED))
+    addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
@@ -213,7 +213,7 @@ class TestRecordsCountNothingInNS(DNSDistTest):
 class TestRecordsCountNoOPTInAR(DNSDistTest):
 
     _config_template = """
-    addAction(NotRule(RecordsTypeCountRule(DNSSection.Additional, dnsdist.OPT, 0, 0)), RCodeAction(dnsdist.REFUSED))
+    addAction(NotRule(RecordsTypeCountRule(DNSSection.Additional, DNSQType.OPT, 0, 0)), RCodeAction(DNSRCode.REFUSED))
     newServer{address="127.0.0.1:%s"}
     """
 
index ffbdf94266543b5e99cffbf844324c3d3a5569bb..fb9276493fd647e014ae787771d059f48a05d127 100644 (file)
@@ -8,7 +8,7 @@ class TestResponseRuleNXDelayed(DNSDistTest):
 
     _config_template = """
     newServer{address="127.0.0.1:%s"}
-    addResponseAction(RCodeRule(dnsdist.NXDOMAIN), DelayResponseAction(1000))
+    addResponseAction(RCodeRule(DNSRCode.NXDOMAIN), DelayResponseAction(1000))
     """
 
     def testNXDelayed(self):
@@ -57,7 +57,7 @@ class TestResponseRuleERCode(DNSDistTest):
 
     _config_template = """
     newServer{address="127.0.0.1:%s"}
-    addResponseAction(ERCodeRule(dnsdist.BADVERS), DelayResponseAction(1000))
+    addResponseAction(ERCodeRule(DNSRCode.BADVERS), DelayResponseAction(1000))
     """
 
     def testBADVERSDelayed(self):
@@ -244,7 +244,7 @@ class TestResponseLuaActionReturnSyntax(DNSDistTest):
       return DNSResponseAction.Drop
     end
     addResponseAction("drop.responses.tests.powerdns.com.", LuaResponseAction(customDrop))
-    addResponseAction(RCodeRule(dnsdist.NXDOMAIN), LuaResponseAction(customDelay))
+    addResponseAction(RCodeRule(DNSRCode.NXDOMAIN), LuaResponseAction(customDelay))
     """
 
     def testResponseActionDelayed(self):
index e0bda09aebc4893b116377a8956efd4ab997bef3..386fba655f91ce2d8235e620cae1ac5283233e40 100644 (file)
@@ -220,6 +220,39 @@ class TestRoutingRoundRobinLBOneDown(DNSDistTest):
 
         self.assertEquals(total, numberOfQueries * 2)
 
+class TestRoutingRoundRobinLBAllDown(DNSDistTest):
+
+    _testServer2Port = 5351
+    _config_params = ['_testServerPort', '_testServer2Port']
+    _config_template = """
+    setServerPolicy(roundrobin)
+    setRoundRobinFailOnNoServer(true)
+    s1 = newServer{address="127.0.0.1:%s"}
+    s1:setDown()
+    s2 = newServer{address="127.0.0.1:%s"}
+    s2:setDown()
+    """
+
+    def testRRWithAllDown(self):
+        """
+        Routing: Round Robin with all servers down
+        """
+        numberOfQueries = 10
+        name = 'alldown.rr.routing.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '192.0.2.1')
+        response.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.assertEquals(receivedResponse, None)
+
 class TestRoutingOrder(DNSDistTest):
 
     _testServer2Port = 5351
index 87aa54bf1f5adf4d5a060ec562a9845faeab455f..f975c9f403a03d30c6d1481ba207c8d857b86567 100644 (file)
@@ -29,7 +29,7 @@ class TestTCPKeepAlive(DNSDistTest):
     pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
     getPool(""):setCache(pc)
     addAction("largernumberofconnections.tcpka.tests.powerdns.com.", SkipCacheAction())
-    addAction("refused.tcpka.tests.powerdns.com.", RCodeAction(dnsdist.REFUSED))
+    addAction("refused.tcpka.tests.powerdns.com.", RCodeAction(DNSRCode.REFUSED))
     addAction("dropped.tcpka.tests.powerdns.com.", DropAction())
     addResponseAction("dropped-response.tcpka.tests.powerdns.com.", DropResponseAction())
     -- create the pool named "nosuchpool"
index 5adb3819be470f689969204349b2200f63b5f3ca..156dcda7be2965e47e10679538af5907c624fe83 100644 (file)
@@ -16,8 +16,8 @@ class TestTeeAction(DNSDistTest):
     setKey("%s")
     controlSocket("127.0.0.1:%s")
     newServer{address="127.0.0.1:%d"}
-    addAction(QTypeRule(dnsdist.A), TeeAction("127.0.0.1:%d", true))
-    addAction(QTypeRule(dnsdist.AAAA), TeeAction("127.0.0.1:%d", false))
+    addAction(QTypeRule(DNSQType.A), TeeAction("127.0.0.1:%d", true))
+    addAction(QTypeRule(DNSQType.AAAA), TeeAction("127.0.0.1:%d", false))
     """
     _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_teeServerPort', '_teeServerPort']
     @classmethod