]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Refactor XFR parameters of RPZParams out
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Fri, 27 Sep 2024 12:11:44 +0000 (14:11 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 4 Nov 2024 14:17:46 +0000 (15:17 +0100)
pdns/recursordist/Makefile.am
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-lua-conf.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-xfr.cc [new file with mode: 0644]
pdns/recursordist/rec-xfr.hh [new file with mode: 0644]
pdns/recursordist/rpzloader.cc
pdns/recursordist/rpzloader.hh
pdns/recursordist/settings/cxxsupport.cc

index fe71369ee729e4c4fb1a9ccec6001c1dd581bde3..6f90adc1d58ee8d066ab68edd83dfb2e31c99e97 100644 (file)
@@ -198,6 +198,7 @@ pdns_recursor_SOURCES = \
        rec-tcounters.cc rec-tcounters.hh \
        rec-tcp.cc \
        rec-tcpout.cc rec-tcpout.hh \
+       rec-xfr.cc rec-xfr.hh \
        rec-zonetocache.cc rec-zonetocache.hh \
        rec_channel.cc rec_channel.hh rec_metrics.hh \
        rec_channel_rec.cc \
@@ -330,6 +331,7 @@ testrunner_SOURCES = \
        rec-system-resolve.hh rec-system-resolve.cc \
        rec-taskqueue.cc rec-taskqueue.hh \
        rec-tcounters.cc rec-tcounters.hh \
+       rec-xfr.cc rec-xfr.hh \
        rec-zonetocache.cc rec-zonetocache.hh \
        recpacketcache.cc recpacketcache.hh \
        recursor_cache.cc recursor_cache.hh \
index 9bd39a7f540cebb3259654f6614e5552a9009544..251b06c87e08d37fdca4cad4ea0be5b76500bcf2 100644 (file)
@@ -2393,7 +2393,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
       SLOG(g_log << Logger::Notice << RecThreadInfo::id() << " got NOTIFY for " << qname.toLogString() << " from " << source.toStringWithPort() << (source != fromaddr ? " (via " + fromaddr.toStringWithPort() + ")" : "") << endl,
            g_slogudpin->info(Logr::Notice, "Got NOTIFY", "source", Logging::Loggable(source), "remote", Logging::Loggable(fromaddr), "qname", Logging::Loggable(qname)));
     }
-    if (!notifyRPZTracker(qname)) {
+    if (!notifyZoneTracker(qname)) {
       // It wasn't an RPZ
       requestWipeCaches(qname);
     }
index bd838f846fbf2e4430c48690bac4ce7d67cd3c1e..ba915adeb926281c61a8b303163bf95c412e5d56 100644 (file)
@@ -132,7 +132,7 @@ static void parseRPZParameters(const rpzOptions_t& have, RPZTrackerParams& param
     params.maxTTL = boost::get<uint32_t>(have.at("maxTTL"));
   }
   if (have.count("zoneSizeHint") != 0) {
-    params.zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have.at("zoneSizeHint")));
+    params.zoneXFRParams.zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have.at("zoneSizeHint")));
   }
   if (have.count("tags") != 0) {
     const auto& tagsTable = boost::get<std::vector<std::pair<int, std::string>>>(have.at("tags"));
@@ -273,16 +273,16 @@ static void parseFrameStreamOptions(const boost::optional<frameStreamOptions_t>&
 static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, const boost::optional<rpzOptions_t>& options)
 {
   RPZTrackerParams params;
-  params.name = zoneName;
+  params.zoneXFRParams.name = zoneName;
   params.polName = zoneName;
 
   std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
   if (primaries_.type() == typeid(string)) {
-    params.primaries.emplace_back(boost::get<std::string>(primaries_), 53);
+    params.zoneXFRParams.primaries.emplace_back(boost::get<std::string>(primaries_), 53);
   }
   else {
     for (const auto& primary : boost::get<std::vector<std::pair<int, std::string>>>(primaries_)) {
-      params.primaries.emplace_back(primary.second, 53);
+      params.zoneXFRParams.primaries.emplace_back(primary.second, 53);
     }
   }
 
@@ -292,9 +292,9 @@ static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::ve
       parseRPZParameters(have, params);
 
       if (have.count("tsigname") != 0) {
-        params.tsigtriplet.name = DNSName(toLower(boost::get<string>(have.at("tsigname"))));
-        params.tsigtriplet.algo = DNSName(toLower(boost::get<string>(have.at("tsigalgo"))));
-        if (B64Decode(boost::get<string>(have.at("tsigsecret")), params.tsigtriplet.secret) != 0) {
+        params.zoneXFRParams.tsigtriplet.name = DNSName(toLower(boost::get<string>(have.at("tsigname"))));
+        params.zoneXFRParams.tsigtriplet.algo = DNSName(toLower(boost::get<string>(have.at("tsigalgo"))));
+        if (B64Decode(boost::get<string>(have.at("tsigsecret")), params.zoneXFRParams.tsigtriplet.secret) != 0) {
           throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
         }
       }
@@ -307,15 +307,15 @@ static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::ve
       }
 
       if (have.count("maxReceivedMBytes") != 0) {
-        params.maxReceivedMBytes = static_cast<size_t>(boost::get<uint32_t>(have.at("maxReceivedMBytes")));
+        params.zoneXFRParams.maxReceivedMBytes = static_cast<size_t>(boost::get<uint32_t>(have.at("maxReceivedMBytes")));
       }
 
       if (have.count("localAddress") != 0) {
-        params.localAddress = ComboAddress(boost::get<string>(have.at("localAddress")));
+        params.zoneXFRParams.localAddress = ComboAddress(boost::get<string>(have.at("localAddress")));
       }
 
       if (have.count("axfrTimeout") != 0) {
-        params.xfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have.at("axfrTimeout")));
+        params.zoneXFRParams.xfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have.at("axfrTimeout")));
       }
 
       if (have.count("seedFile") != 0) {
@@ -327,11 +327,11 @@ static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::ve
       }
     }
 
-    if (params.localAddress != ComboAddress()) {
+    if (params.zoneXFRParams.localAddress != ComboAddress()) {
       // We were passed a localAddress, check if its AF matches the primaries'
-      for (const auto& primary : params.primaries) {
-        if (params.localAddress.sin4.sin_family != primary.sin4.sin_family) {
-          throw PDNSException("Primary address(" + primary.toString() + ") is not of the same Address Family as the local address (" + params.localAddress.toString() + ").");
+      for (const auto& primary : params.zoneXFRParams.primaries) {
+        if (params.zoneXFRParams.localAddress.sin4.sin_family != primary.sin4.sin_family) {
+          throw PDNSException("Primary address(" + primary.toString() + ") is not of the same Address Family as the local address (" + params.zoneXFRParams.localAddress.toString() + ").");
         }
       }
     }
@@ -412,7 +412,7 @@ void loadRecursorLuaConfig(const std::string& fname, ProxyMapping& proxyMapping,
 
   Lua->writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
     RPZTrackerParams params;
-    params.name = filename;
+    params.zoneXFRParams.name = filename;
     params.polName = "rpzFile";
     if (options) {
       parseRPZParameters(*options, params);
index ab33fbc4470e5e30e556f9f955bf1ed5038ede24..f20c17736e004eac4f69c3d348690a6c3360145f 100644 (file)
@@ -2875,7 +2875,7 @@ static void recursorThread()
       checkFrameStreamExport(luaconfsLocal, luaconfsLocal->nodFrameStreamExportConfig, t_nodFrameStreamServersInfo);
 #endif
       for (const auto& rpz : luaconfsLocal->rpzs) {
-        string name = rpz.polName.empty() ? (rpz.primaries.empty() ? "rpzFile" : rpz.name) : rpz.polName;
+        string name = rpz.polName.empty() ? (rpz.zoneXFRParams.primaries.empty() ? "rpzFile" : rpz.zoneXFRParams.name) : rpz.polName;
         t_Counters.at(rec::PolicyNameHits::policyName).counts[name] = 0;
       }
     }
@@ -3405,7 +3405,7 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q
 void startLuaConfigDelayedThreads(const vector<RPZTrackerParams>& rpzs, uint64_t generation)
 {
   for (const auto& rpzPrimary : rpzs) {
-    if (rpzPrimary.primaries.empty()) {
+    if (rpzPrimary.zoneXFRParams.primaries.empty()) {
       continue;
     }
     try {
@@ -3437,13 +3437,13 @@ static void* pleaseInitPolCounts(const string& name)
 
 static bool activateRPZFile(const RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr<DNSFilterEngine::Zone>& zone)
 {
-  auto log = lci.d_slog->withValues("file", Logging::Loggable(params.name));
+  auto log = lci.d_slog->withValues("file", Logging::Loggable(params.zoneXFRParams.name));
 
   zone->setName(params.polName.empty() ? "rpzFile" : params.polName);
   try {
     SLOG(g_log << Logger::Warning << "Loading RPZ from file '" << params.name << "'" << endl,
          log->info(Logr::Info, "Loading RPZ from file"));
-    loadRPZFromFile(params.name, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
+    loadRPZFromFile(params.zoneXFRParams.name, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
     SLOG(g_log << Logger::Warning << "Done loading RPZ from file '" << params.name << "'" << endl,
          log->info(Logr::Info, "Done loading RPZ from file"));
   }
@@ -3458,20 +3458,20 @@ static bool activateRPZFile(const RPZTrackerParams& params, LuaConfigItems& lci,
 
 static void activateRPZPrimary(RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr<DNSFilterEngine::Zone>& zone, const DNSName& domain)
 {
-  auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(params.seedFileName), "zone", Logging::Loggable(params.name));
+  auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(params.seedFileName), "zone", Logging::Loggable(params.zoneXFRParams.name));
 
   if (!params.seedFileName.empty()) {
     SLOG(g_log << Logger::Info << "Pre-loading RPZ zone " << params.name << " from seed file '" << params.seedFileName << "'" << endl,
          log->info(Logr::Info, "Pre-loading RPZ zone from seed file"));
     try {
-      params.soaRecordContent = loadRPZFromFile(params.seedFileName, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
+      params.zoneXFRParams.soaRecordContent = loadRPZFromFile(params.seedFileName, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
 
       if (zone->getDomain() != domain) {
-        throw PDNSException("The RPZ zone " + params.name + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
+        throw PDNSException("The RPZ zone " + params.zoneXFRParams.name + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
       }
 
-      if (params.soaRecordContent == nullptr) {
-        throw PDNSException("The RPZ zone " + params.name + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
+      if (params.zoneXFRParams.soaRecordContent == nullptr) {
+        throw PDNSException("The RPZ zone " + params.zoneXFRParams.name + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
       }
     }
     catch (const PDNSException& e) {
@@ -3491,8 +3491,8 @@ static void activateRPZs(LuaConfigItems& lci)
 {
   for (auto& params : lci.rpzs) {
     auto zone = std::make_shared<DNSFilterEngine::Zone>();
-    if (params.zoneSizeHint != 0) {
-      zone->reserve(params.zoneSizeHint);
+    if (params.zoneXFRParams.zoneSizeHint != 0) {
+      zone->reserve(params.zoneXFRParams.zoneSizeHint);
     }
     if (!params.tags.empty()) {
       std::unordered_set<std::string> tags;
@@ -3511,15 +3511,15 @@ static void activateRPZs(LuaConfigItems& lci)
     zone->setIncludeSOA(params.includeSOA);
     zone->setIgnoreDuplicates(params.ignoreDuplicates);
 
-    if (params.primaries.empty()) {
+    if (params.zoneXFRParams.primaries.empty()) {
       if (activateRPZFile(params, lci, zone)) {
         lci.dfe.addZone(zone);
       }
     }
     else {
-      DNSName domain(params.name);
+      DNSName domain(params.zoneXFRParams.name);
       zone->setDomain(domain);
-      zone->setName(params.polName.empty() ? params.name : params.polName);
+      zone->setName(params.polName.empty() ? params.zoneXFRParams.name : params.polName);
       params.zoneIdx = lci.dfe.addZone(zone);
       activateRPZPrimary(params, lci, zone, domain);
     }
diff --git a/pdns/recursordist/rec-xfr.cc b/pdns/recursordist/rec-xfr.cc
new file mode 100644 (file)
index 0000000..6ef1435
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 "rec-xfr.hh"
+#include "lock.hh"
+
+// As there can be multiple threads doing updates (due to config reloads), we use a multimap.
+// The value contains the actual thread id that owns the struct.
+
+static LockGuarded<std::multimap<DNSName, ZoneWaiter&>> condVars;
+
+// Notify all threads tracking the RPZ name
+bool notifyZoneTracker(const DNSName& name)
+{
+  auto lock = condVars.lock();
+  auto [start, end] = lock->equal_range(name);
+  if (start == end) {
+    // Did not find any thread tracking that name
+    return false;
+  }
+  while (start != end) {
+    start->second.stop = true;
+    start->second.condVar.notify_one();
+    ++start;
+  }
+  return true;
+}
+
+void insertZoneTracker(const DNSName& zoneName, ZoneWaiter& waiter)
+{
+  auto lock = condVars.lock();
+  lock->emplace(zoneName, waiter);
+}
+
+void clearZoneTracker(const DNSName& zoneName)
+{
+  // Zap our (and only our) ZoneWaiter struct out of the multimap
+  auto lock = condVars.lock();
+  auto [start, end] = lock->equal_range(zoneName);
+  while (start != end) {
+    if (start->second.id == std::this_thread::get_id()) {
+      lock->erase(start);
+      break;
+    }
+    ++start;
+  }
+}
diff --git a/pdns/recursordist/rec-xfr.hh b/pdns/recursordist/rec-xfr.hh
new file mode 100644 (file)
index 0000000..739ef96
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 "config.h"
+
+#include <string>
+#include <thread>
+
+#include "iputils.hh"
+
+class DNSName;
+class SOARecordContent;
+
+// Please make sure that the struct below only contains value types since they are used as parameters in a thread ct
+struct ZoneXFRParams
+{
+  std::string name;
+  std::vector<ComboAddress> primaries;
+  ComboAddress localAddress;
+  std::shared_ptr<const SOARecordContent> soaRecordContent;
+  TSIGTriplet tsigtriplet;
+  size_t maxReceivedMBytes{0};
+  size_t zoneSizeHint{0};
+  uint16_t xfrTimeout{20};
+};
+
+// A struct that holds the condition var and related stuff to allow notifies to be sent to the tread owning
+// the struct.
+struct ZoneWaiter
+{
+  ZoneWaiter(std::thread::id arg) :
+    id(arg) {}
+  std::thread::id id;
+  std::mutex mutex;
+  std::condition_variable condVar;
+  std::atomic<bool> stop{false};
+};
+
+bool notifyZoneTracker(const DNSName& name);
+void insertZoneTracker(const DNSName& zoneName, ZoneWaiter& waiter);
+void clearZoneTracker(const DNSName& zoneName);
index a7471d64cabf4176939241837cdb1fdc626b381b..42d38a9de1ddd25f80f843112995bdcaa1fbca58 100644 (file)
 #include "dnsparser.hh"
 #include "dnsrecords.hh"
 #include "ixfr.hh"
-#include "syncres.hh"
 #include "axfr-retriever.hh"
 #include "lock.hh"
-#include "logger.hh"
 #include "logging.hh"
 #include "rec-lua-conf.hh"
 #include "rpzloader.hh"
@@ -436,32 +434,21 @@ static bool dumpZoneToDisk(Logr::log_t logger, const std::shared_ptr<DNSFilterEn
   return true;
 }
 
-// A struct that holds the condition var and related stuff to allow notifies to be sent to the tread owning
-// the struct.
-struct RPZWaiter
-{
-  RPZWaiter(std::thread::id arg) :
-    id(arg) {}
-  std::thread::id id;
-  std::mutex mutex;
-  std::condition_variable condVar;
-  std::atomic<bool> stop{false};
-};
-
-static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone>& oldZone, uint32_t& refresh, const string& polName, uint64_t configGeneration, RPZWaiter& rpzwaiter, Logr::log_t logger)
+
+static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone>& oldZone, uint32_t& refresh, const string& polName, uint64_t configGeneration, ZoneWaiter& rpzwaiter, Logr::log_t logger)
 {
-  while (!params.soaRecordContent) {
+  while (!params.zoneXFRParams.soaRecordContent) {
     /* if we received an empty sr, the zone was not really preloaded */
 
     /* full copy, as promised */
     std::shared_ptr<DNSFilterEngine::Zone> newZone = std::make_shared<DNSFilterEngine::Zone>(*oldZone);
-    for (const auto& primary : params.primaries) {
+    for (const auto& primary : params.zoneXFRParams.primaries) {
       try {
-        params.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.tsigtriplet, params.maxReceivedMBytes, params.localAddress, params.xfrTimeout);
-        newZone->setSerial(params.soaRecordContent->d_st.serial);
-        newZone->setRefresh(params.soaRecordContent->d_st.refresh);
+        params.zoneXFRParams.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.zoneXFRParams.tsigtriplet, params.zoneXFRParams.maxReceivedMBytes, params.zoneXFRParams.localAddress, params.zoneXFRParams.xfrTimeout);
+        newZone->setSerial(params.zoneXFRParams.soaRecordContent->d_st.serial);
+        newZone->setRefresh(params.zoneXFRParams.soaRecordContent->d_st.refresh);
         refresh = std::max(params.refreshFromConf != 0 ? params.refreshFromConf : newZone->getRefresh(), 1U);
-        setRPZZoneNewState(polName, params.soaRecordContent->d_st.serial, newZone->size(), false, true);
+        setRPZZoneNewState(polName, params.zoneXFRParams.soaRecordContent->d_st.serial, newZone->size(), false, true);
 
         g_luaconfs.modify([zoneIdx = params.zoneIdx, &newZone](LuaConfigItems& lci) {
           lci.dfe.setZone(zoneIdx, newZone);
@@ -487,7 +474,7 @@ static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, st
     }
     // Release newZone before (long) sleep to reduce memory usage
     newZone = nullptr;
-    if (!params.soaRecordContent) {
+    if (!params.zoneXFRParams.soaRecordContent) {
       std::unique_lock lock(rpzwaiter.mutex);
       rpzwaiter.condVar.wait_for(lock, std::chrono::seconds(refresh),
                                  [&stop = rpzwaiter.stop] { return stop.load(); });
@@ -504,12 +491,12 @@ static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, st
   }
 }
 
-static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone>& oldZone, uint32_t& refresh, const string& polName, bool& skipRefreshDelay, uint64_t configGeneration, RPZWaiter& rpzwaiter, Logr::log_t logger)
+static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone>& oldZone, uint32_t& refresh, const string& polName, bool& skipRefreshDelay, uint64_t configGeneration, ZoneWaiter& rpzwaiter, Logr::log_t logger)
 {
   // Don't hold on to oldZone, it well be re-assigned after sleep in the try block
   oldZone = nullptr;
   DNSRecord dnsRecord;
-  dnsRecord.setContent(params.soaRecordContent);
+  dnsRecord.setContent(params.zoneXFRParams.soaRecordContent);
 
   if (skipRefreshDelay) {
     skipRefreshDelay = false;
@@ -542,19 +529,19 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam
   }
 
   vector<pair<vector<DNSRecord>, vector<DNSRecord>>> deltas;
-  for (const auto& primary : params.primaries) {
+  for (const auto& primary : params.zoneXFRParams.primaries) {
     auto soa = getRR<SOARecordContent>(dnsRecord);
     auto serial = soa ? soa->d_st.serial : 0;
     SLOG(g_log << Logger::Info << "Getting IXFR deltas for " << zoneName << " from " << primary.toStringWithPort() << ", our serial: " << serial << endl,
          logger->info(Logr::Info, "Getting IXFR deltas", "address", Logging::Loggable(primary), "ourserial", Logging::Loggable(serial)));
 
-    ComboAddress local(params.localAddress);
+    ComboAddress local(params.zoneXFRParams.localAddress);
     if (local == ComboAddress()) {
       local = pdns::getQueryLocalAddress(primary.sin4.sin_family, 0);
     }
 
     try {
-      deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedMBytes);
+      deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.zoneXFRParams.xfrTimeout, true, params.zoneXFRParams.tsigtriplet, &local, params.zoneXFRParams.maxReceivedMBytes);
 
       /* no need to try another primary */
       break;
@@ -589,7 +576,7 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam
     /* we need to make a _full copy_ of the zone we are going to work on */
     std::shared_ptr<DNSFilterEngine::Zone> newZone = std::make_shared<DNSFilterEngine::Zone>(*oldZone);
     /* initialize the current serial to the last one */
-    std::shared_ptr<const SOARecordContent> currentSR = params.soaRecordContent;
+    std::shared_ptr<const SOARecordContent> currentSR = params.zoneXFRParams.soaRecordContent;
 
     int totremove = 0;
     int totadd = 0;
@@ -648,13 +635,13 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam
 
     /* only update sr now that all changes have been converted */
     if (currentSR) {
-      params.soaRecordContent = std::move(currentSR);
+      params.zoneXFRParams.soaRecordContent = std::move(currentSR);
     }
     SLOG(g_log << Logger::Info << "Had " << totremove << " RPZ removal" << addS(totremove) << ", " << totadd << " addition" << addS(totadd) << " for " << zoneName << " New serial: " << params.soaRecordContent->d_st.serial << endl,
-         logger->info(Logr::Info, "RPZ mutations", "removals", Logging::Loggable(totremove), "additions", Logging::Loggable(totadd), "newserial", Logging::Loggable(params.soaRecordContent->d_st.serial)));
-    newZone->setSerial(params.soaRecordContent->d_st.serial);
-    newZone->setRefresh(params.soaRecordContent->d_st.refresh);
-    setRPZZoneNewState(polName, params.soaRecordContent->d_st.serial, newZone->size(), false, fullUpdate);
+         logger->info(Logr::Info, "RPZ mutations", "removals", Logging::Loggable(totremove), "additions", Logging::Loggable(totadd), "newserial", Logging::Loggable(params.zoneXFRParams.soaRecordContent->d_st.serial)));
+    newZone->setSerial(params.zoneXFRParams.soaRecordContent->d_st.serial);
+    newZone->setRefresh(params.zoneXFRParams.soaRecordContent->d_st.refresh);
+    setRPZZoneNewState(polName, params.zoneXFRParams.soaRecordContent->d_st.serial, newZone->size(), false, fullUpdate);
 
     /* we need to replace the existing zone with the new one,
        but we don't want to touch anything else, especially other zones,
@@ -685,35 +672,13 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam
   return true;
 }
 
-// As there can be multiple threads doing updates (due to config reloads), we use a multimap.
-// The value contains the actual thread id that owns the struct.
-
-static LockGuarded<std::multimap<DNSName, RPZWaiter&>> condVars;
-
-// Notify all threads tracking the RPZ name
-bool notifyRPZTracker(const DNSName& name)
-{
-  auto lock = condVars.lock();
-  auto [start, end] = lock->equal_range(name);
-  if (start == end) {
-    // Did not find any thread tracking that RPZ name
-    return false;
-  }
-  while (start != end) {
-    start->second.stop = true;
-    start->second.condVar.notify_one();
-    ++start;
-  }
-  return true;
-}
-
 // coverity[pass_by_value] params is intended to be a copy, as this is the main function of a thread
 void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration)
 {
   setThreadName("rec/rpzixfr");
-  bool isPreloaded = params.soaRecordContent != nullptr;
+  bool isPreloaded = params.zoneXFRParams.soaRecordContent != nullptr;
   auto logger = g_slog->withName("rpz");
-  RPZWaiter waiter(std::this_thread::get_id());
+  ZoneWaiter waiter(std::this_thread::get_id());
 
   /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */
   std::shared_ptr<DNSFilterEngine::Zone> oldZone = g_luaconfs.getLocal()->dfe.getZone(params.zoneIdx);
@@ -731,10 +696,8 @@ void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration)
   // Now that we know the name, set it in the logger
   logger = logger->withValues("zone", Logging::Loggable(zoneName));
 
-  {
-    auto lock = condVars.lock();
-    lock->emplace(zoneName, waiter);
-  }
+  insertZoneTracker(zoneName, waiter);
+
   preloadRPZFIle(params, zoneName, oldZone, refresh, polName, configGeneration, waiter, logger);
 
   bool skipRefreshDelay = isPreloaded;
@@ -743,14 +706,5 @@ void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration)
     // empty
   }
 
-  // Zap our (and only our) RPZWaiter struct out of the multimap
-  auto lock = condVars.lock();
-  auto [start, end] = lock->equal_range(zoneName);
-  while (start != end) {
-    if (start->second.id == std::this_thread::get_id()) {
-      lock->erase(start);
-      break;
-    }
-    ++start;
-  }
+  clearZoneTracker(zoneName);
 }
index 8b2252f14cce90fe15ad47b5f2c3e0afbbdd81f3..0872ff6a27f7897116f57e57774701514a4ab3c8 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 #pragma once
+#include "rec-xfr.hh"
 #include "filterpo.hh"
 #include <string>
 #include "dnsrecords.hh"
@@ -29,23 +30,16 @@ extern bool g_logRPZChanges;
 // Please make sure that the struct below only contains value types since they are used as parameters in a thread ct
 struct RPZTrackerParams
 {
-  std::string name;
-  std::vector<ComboAddress> primaries;
+  ZoneXFRParams zoneXFRParams;
   boost::optional<DNSFilterEngine::Policy> defpol;
   std::string defcontent;
   bool defpolOverrideLocal{true};
   uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
   size_t zoneIdx{0};
-  TSIGTriplet tsigtriplet;
-  size_t maxReceivedMBytes{0};
-  ComboAddress localAddress;
-  uint16_t xfrTimeout{20};
   uint32_t refreshFromConf{0};
-  std::shared_ptr<const SOARecordContent> soaRecordContent;
   std::string seedFileName;
   std::string dumpZoneFileName;
   std::string polName;
-  size_t zoneSizeHint{0};
   std::set<std::string> tags;
   uint32_t extendedErrorCode{std::numeric_limits<uint32_t>::max()};
   std::string extendedErrorExtra;
@@ -55,7 +49,6 @@ struct RPZTrackerParams
 
 std::shared_ptr<const SOARecordContent> loadRPZFromFile(const std::string& fname, const std::shared_ptr<DNSFilterEngine::Zone>& zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL);
 void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration);
-bool notifyRPZTracker(const DNSName& name);
 
 struct rpzStats
 {
index f8345b4918975e53c1b043e5aea54fc271e08238..fcaf9f6ec1d08d377b3ccb7411dede89ce2dd174 100644 (file)
@@ -870,10 +870,10 @@ void fromLuaToRust(const vector<RPZTrackerParams>& rpzs, pdns::rust::settings::r
       .seedFile = "",
     };
 
-    for (const auto& address : rpz.primaries) {
+    for (const auto& address : rpz.zoneXFRParams.primaries) {
       rustrpz.addresses.emplace_back(address.toStringWithPort());
     }
-    rustrpz.name = rpz.name;
+    rustrpz.name = rpz.zoneXFRParams.name;
     rustrpz.defcontent = rpz.defcontent;
     if (rpz.defpol) {
       rustrpz.defpol = cvt(rpz.defpol->d_kind);
@@ -890,14 +890,14 @@ void fromLuaToRust(const vector<RPZTrackerParams>& rpzs, pdns::rust::settings::r
       rustrpz.tags.emplace_back(tag);
     }
     rustrpz.overridesGettag = rpz.defpolOverrideLocal;
-    rustrpz.zoneSizeHint = rpz.zoneSizeHint;
-    assign(rustrpz.tsig, rpz.tsigtriplet);
+    rustrpz.zoneSizeHint = rpz.zoneXFRParams.zoneSizeHint;
+    assign(rustrpz.tsig, rpz.zoneXFRParams.tsigtriplet);
     rustrpz.refresh = rpz.refreshFromConf;
-    rustrpz.maxReceivedMBytes = rpz.maxReceivedMBytes;
-    if (rpz.localAddress != ComboAddress()) {
-      rustrpz.localAddress = rpz.localAddress.toString();
+    rustrpz.maxReceivedMBytes = rpz.zoneXFRParams.maxReceivedMBytes;
+    if (rpz.zoneXFRParams.localAddress != ComboAddress()) {
+      rustrpz.localAddress = rpz.zoneXFRParams.localAddress.toString();
     }
-    rustrpz.axfrTimeout = rpz.xfrTimeout;
+    rustrpz.axfrTimeout = rpz.zoneXFRParams.xfrTimeout;
     rustrpz.dumpFile = rpz.dumpZoneFileName;
     rustrpz.seedFile = rpz.seedFileName;
 
@@ -1181,9 +1181,9 @@ void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::RPZ>& rpzs,
     RPZTrackerParams params;
     for (const auto& address : rpz.addresses) {
       ComboAddress combo = ComboAddress(std::string(address), 53);
-      params.primaries.emplace_back(combo.toStringWithPort());
+      params.zoneXFRParams.primaries.emplace_back(combo.toStringWithPort());
     }
-    params.name = std::string(rpz.name);
+    params.zoneXFRParams.name = std::string(rpz.name);
     params.polName = std::string(rpz.policyName);
 
     if (!rpz.defpol.empty()) {
@@ -1217,14 +1217,14 @@ void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::RPZ>& rpzs,
       params.tags.emplace(std::string(tag));
     }
     params.defpolOverrideLocal = rpz.overridesGettag;
-    params.zoneSizeHint = rpz.zoneSizeHint;
-    assign(params.tsigtriplet, rpz.tsig);
+    params.zoneXFRParams.zoneSizeHint = rpz.zoneSizeHint;
+    assign(params.zoneXFRParams.tsigtriplet, rpz.tsig);
     params.refreshFromConf = rpz.refresh;
-    params.maxReceivedMBytes = rpz.maxReceivedMBytes;
+    params.zoneXFRParams.maxReceivedMBytes = rpz.maxReceivedMBytes;
     if (!rpz.localAddress.empty()) {
-      params.localAddress = ComboAddress(std::string(rpz.localAddress));
+      params.zoneXFRParams.localAddress = ComboAddress(std::string(rpz.localAddress));
     }
-    params.xfrTimeout = rpz.axfrTimeout;
+    params.zoneXFRParams.xfrTimeout = rpz.axfrTimeout;
     params.dumpZoneFileName = std::string(rpz.dumpFile);
     params.seedFileName = std::string(rpz.seedFile);
     luaConfig.rpzs.emplace_back(params);