From: Otto Moerbeek Date: Tue, 9 Jan 2024 14:33:30 +0000 (+0100) Subject: Refactor RPZ download thread code X-Git-Tag: dnsdist-1.9.0-rc1~15^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4fc57a40ae1313fd328c1351097b667f9ef1db4d;p=thirdparty%2Fpdns.git Refactor RPZ download thread code --- diff --git a/pdns/recursordist/rec-lua-conf.cc b/pdns/recursordist/rec-lua-conf.cc index 071271f61a..615f8b9621 100644 --- a/pdns/recursordist/rec-lua-conf.cc +++ b/pdns/recursordist/rec-lua-conf.cc @@ -387,7 +387,7 @@ static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThre lci.d_slog->error(Logr::Error, e.reason, "Exception configuring 'rpzPrimary'", Logging::Loggable("PDNSException"))); } - delayedThreads.rpzPrimaryThreads.emplace_back(primaries, defpol, defpolOverrideLocal, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, refresh, sr, dumpFile); + delayedThreads.rpzPrimaryThreads.emplace_back(RPZTrackerParams{primaries, defpol, defpolOverrideLocal, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, refresh, sr, dumpFile}); } // A wrapper class that loads the standard Lua defintions into the context, so that we can use things like pdns.A @@ -904,8 +904,8 @@ void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, try { // The get calls all return a value object here. That is essential, since we want copies so that RPZIXFRTracker gets values // with the proper lifetime. - std::thread t(RPZIXFRTracker, std::get<0>(rpzPrimary), std::get<1>(rpzPrimary), std::get<2>(rpzPrimary), std::get<3>(rpzPrimary), std::get<4>(rpzPrimary), std::get<5>(rpzPrimary), std::get<6>(rpzPrimary) * 1024 * 1024, std::get<7>(rpzPrimary), std::get<8>(rpzPrimary), std::get<9>(rpzPrimary), std::get<10>(rpzPrimary), std::get<11>(rpzPrimary), generation); - t.detach(); + std::thread theThread(RPZIXFRTracker, rpzPrimary, generation); + theThread.detach(); } catch (const std::exception& e) { SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.what() << endl, diff --git a/pdns/recursordist/rec-lua-conf.hh b/pdns/recursordist/rec-lua-conf.hh index 29a18b00f6..440068ec6e 100644 --- a/pdns/recursordist/rec-lua-conf.hh +++ b/pdns/recursordist/rec-lua-conf.hh @@ -29,6 +29,7 @@ #include "rec-zonetocache.hh" #include "logging.hh" #include "fstrm_logger.hh" +#include "rpzloader.hh" struct ProtobufExportConfig { @@ -125,8 +126,7 @@ extern GlobalStateHolder g_luaconfs; struct luaConfigDelayedThreads { - // Please make sure that the tuple below only contains value types since they are used as parameters in a thread ct - std::vector, boost::optional, bool, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, uint32_t, std::shared_ptr, std::string>> rpzPrimaryThreads; + std::vector rpzPrimaryThreads; }; void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping&); diff --git a/pdns/recursordist/rpzloader.cc b/pdns/recursordist/rpzloader.cc index 549902c058..45c3576fae 100644 --- a/pdns/recursordist/rpzloader.cc +++ b/pdns/recursordist/rpzloader.cc @@ -386,47 +386,27 @@ static bool dumpZoneToDisk(Logr::log_t logger, const DNSName& zoneName, const st return true; } -void RPZIXFRTracker(const std::vector& primaries, const boost::optional& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t refreshFromConf, std::shared_ptr sr, const std::string& dumpZoneFileName, uint64_t configGeneration) +static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr& oldZone, uint32_t& refresh, const string& polName, Logr::log_t logger) { - setThreadName("rec/rpzixfr"); - bool isPreloaded = sr != nullptr; - auto logger = g_slog->withName("rpz"); - - /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */ - std::shared_ptr oldZone = g_luaconfs.getLocal()->dfe.getZone(zoneIdx); - if (!oldZone) { - SLOG(g_log << Logger::Error << "Unable to retrieve RPZ zone with index " << zoneIdx << " from the configuration, exiting" << endl, - logger->error(Logr::Error, "Unable to retrieve RPZ zone from configuration", "index", Logging::Loggable(zoneIdx))); - return; - } - - // If oldZone failed to load its getRefresh() returns 0, protect against that - uint32_t refresh = std::max(refreshFromConf ? refreshFromConf : oldZone->getRefresh(), 10U); - DNSName zoneName = oldZone->getDomain(); - std::string polName = !oldZone->getName().empty() ? oldZone->getName() : zoneName.toStringNoDot(); - - // Now that we know the name, set it in the logger - logger = logger->withValues("zone", Logging::Loggable(zoneName)); - - while (!sr) { + while (!params.soaRecordContent) { /* if we received an empty sr, the zone was not really preloaded */ /* full copy, as promised */ std::shared_ptr newZone = std::make_shared(*oldZone); - for (const auto& primary : primaries) { + for (const auto& primary : params.primaries) { try { - sr = loadRPZFromServer(logger, primary, zoneName, newZone, defpol, defpolOverrideLocal, maxTTL, tt, maxReceivedBytes, localAddress, xfrTimeout); - newZone->setSerial(sr->d_st.serial); - newZone->setRefresh(sr->d_st.refresh); - refresh = std::max(refreshFromConf ? refreshFromConf : newZone->getRefresh(), 1U); - setRPZZoneNewState(polName, sr->d_st.serial, newZone->size(), false, true); + params.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.tsigtriplet, params.maxReceivedBytes, params.localAddress, params.xfrTimeout); + newZone->setSerial(params.soaRecordContent->d_st.serial); + newZone->setRefresh(params.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); - g_luaconfs.modify([zoneIdx, &newZone](LuaConfigItems& lci) { + g_luaconfs.modify([zoneIdx = params.zoneIdx, &newZone](LuaConfigItems& lci) { lci.dfe.setZone(zoneIdx, newZone); }); - if (!dumpZoneFileName.empty()) { - dumpZoneToDisk(logger, zoneName, newZone, dumpZoneFileName); + if (!params.dumpZoneFileName.empty()) { + dumpZoneToDisk(logger, zoneName, newZone, params.dumpZoneFileName); } /* no need to try another primary */ @@ -445,176 +425,207 @@ void RPZIXFRTracker(const std::vector& primaries, const boost::opt } // Release newZone before (long) sleep to reduce memory usage newZone = nullptr; - if (!sr) { + if (!params.soaRecordContent) { sleep(refresh); } } +} - bool skipRefreshDelay = isPreloaded; - - for (;;) { - // Don't hold on to oldZone, it well be re-assigned after sleep in the try block - oldZone = nullptr; - DNSRecord dr; - dr.setContent(sr); +static void RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneName, std::shared_ptr& oldZone, uint32_t& refresh, const string& polName, bool skipRefreshDelay, uint64_t configGeneration, Logr::log_t logger) +{ + // Don't hold on to oldZone, it well be re-assigned after sleep in the try block + oldZone = nullptr; + DNSRecord dr; + dr.setContent(params.soaRecordContent); - if (skipRefreshDelay) { - skipRefreshDelay = false; - } - else { - sleep(refresh); - } - auto luaconfsLocal = g_luaconfs.getLocal(); + if (skipRefreshDelay) { + skipRefreshDelay = false; + } + else { + sleep(refresh); + } + auto luaconfsLocal = g_luaconfs.getLocal(); - if (luaconfsLocal->generation != configGeneration) { - /* the configuration has been reloaded, meaning that a new thread - has been started to handle that zone and we are now obsolete. - */ - SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, - logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); - return; - } + if (luaconfsLocal->generation != configGeneration) { + /* the configuration has been reloaded, meaning that a new thread + has been started to handle that zone and we are now obsolete. + */ + SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, + logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); + return; + } - vector, vector>> deltas; - for (const auto& primary : primaries) { - auto soa = getRR(dr); - 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))); + vector, vector>> deltas; + for (const auto& primary : params.primaries) { + auto soa = getRR(dr); + 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(localAddress); - if (local == ComboAddress()) { - local = pdns::getQueryLocalAddress(primary.sin4.sin_family, 0); - } + ComboAddress local(params.localAddress); + if (local == ComboAddress()) { + local = pdns::getQueryLocalAddress(primary.sin4.sin_family, 0); + } - try { - deltas = getIXFRDeltas(primary, zoneName, dr, xfrTimeout, true, tt, &local, maxReceivedBytes); + try { + deltas = getIXFRDeltas(primary, zoneName, dr, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedBytes); - /* no need to try another primary */ - break; - } - catch (const std::runtime_error& e) { - SLOG(g_log << Logger::Warning << e.what() << endl, - logger->error(Logr::Warning, e.what(), "Exception during retrieval of delta", "exception", Logging::Loggable("std::runtime_error"))); - incRPZFailedTransfers(polName); - continue; - } + /* no need to try another primary */ + break; } - - if (deltas.empty()) { + catch (const std::runtime_error& e) { + SLOG(g_log << Logger::Warning << e.what() << endl, + logger->error(Logr::Warning, e.what(), "Exception during retrieval of delta", "exception", Logging::Loggable("std::runtime_error"))); + incRPZFailedTransfers(polName); continue; } + } - try { - SLOG(g_log << Logger::Info << "Processing " << deltas.size() << " delta" << addS(deltas) << " for RPZ " << zoneName << endl, - logger->info(Logr::Info, "Processing deltas", "size", Logging::Loggable(deltas.size()))); + if (deltas.empty()) { + return; + } - if (luaconfsLocal->generation != configGeneration) { - SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, - logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); - return; - } - oldZone = luaconfsLocal->dfe.getZone(zoneIdx); - if (!oldZone || oldZone->getDomain() != zoneName) { - SLOG(g_log << Logger::Info << "This policy is no more, stopping the existing RPZ update thread for " << zoneName << endl, - logger->info(Logr::Info, "This policy is no more, stopping the existing RPZ update thread")); - return; + try { + SLOG(g_log << Logger::Info << "Processing " << deltas.size() << " delta" << addS(deltas) << " for RPZ " << zoneName << endl, + logger->info(Logr::Info, "Processing deltas", "size", Logging::Loggable(deltas.size()))); + + if (luaconfsLocal->generation != configGeneration) { + SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, + logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); + return; + } + oldZone = luaconfsLocal->dfe.getZone(params.zoneIdx); + if (!oldZone || oldZone->getDomain() != zoneName) { + SLOG(g_log << Logger::Info << "This policy is no more, stopping the existing RPZ update thread for " << zoneName << endl, + logger->info(Logr::Info, "This policy is no more, stopping the existing RPZ update thread")); + return; + } + /* we need to make a _full copy_ of the zone we are going to work on */ + std::shared_ptr newZone = std::make_shared(*oldZone); + /* initialize the current serial to the last one */ + std::shared_ptr currentSR = params.soaRecordContent; + + int totremove = 0; + int totadd = 0; + bool fullUpdate = false; + for (const auto& delta : deltas) { + const auto& remove = delta.first; + const auto& add = delta.second; + if (remove.empty()) { + SLOG(g_log << Logger::Warning << "IXFR update is a whole new zone" << endl, + logger->info(Logr::Warning, "IXFR update is a whole new zone")); + newZone->clear(); + fullUpdate = true; } - /* we need to make a _full copy_ of the zone we are going to work on */ - std::shared_ptr newZone = std::make_shared(*oldZone); - /* initialize the current serial to the last one */ - std::shared_ptr currentSR = sr; - - int totremove = 0, totadd = 0; - bool fullUpdate = false; - for (const auto& delta : deltas) { - const auto& remove = delta.first; - const auto& add = delta.second; - if (remove.empty()) { - SLOG(g_log << Logger::Warning << "IXFR update is a whole new zone" << endl, - logger->info(Logr::Warning, "IXFR update is a whole new zone")); - newZone->clear(); - fullUpdate = true; + for (const auto& resourceRecord : remove) { // should always contain the SOA + if (resourceRecord.d_type == QType::NS) { + continue; } - for (const auto& rr : remove) { // should always contain the SOA - if (rr.d_type == QType::NS) - continue; - if (rr.d_type == QType::SOA) { - auto oldsr = getRR(rr); - if (oldsr && oldsr->d_st.serial == currentSR->d_st.serial) { - // cout<<"Got good removal of SOA serial "<d_st.serial<d_st.serial) + ", expecting " + std::to_string(currentSR->d_st.serial) + ") from SOA record while processing the removal part of an update"); - } - } + if (resourceRecord.d_type == QType::SOA) { + auto oldsr = getRR(resourceRecord); + if (oldsr && oldsr->d_st.serial == currentSR->d_st.serial) { + // cout<<"Got good removal of SOA serial "<d_st.serial<info(g_logRPZChanges ? Logr::Info : Logr::Debug, "Remove from RPZ zone", "name", Logging::Loggable(rr.d_name))); - RPZRecordToPolicy(rr, newZone, false, defpol, defpolOverrideLocal, maxTTL, logger); - } - } - - for (const auto& rr : add) { // should always contain the new SOA - if (rr.d_type == QType::NS) - continue; - if (rr.d_type == QType::SOA) { - auto tempSR = getRR(rr); - // g_log<d_st.serial<info(g_logRPZChanges ? Logr::Info : Logr::Debug, "Addition to RPZ zone", "name", Logging::Loggable(rr.d_name))); - RPZRecordToPolicy(rr, newZone, true, defpol, defpolOverrideLocal, maxTTL, logger); + throw std::runtime_error("Received an unexpected serial (" + std::to_string(oldsr->d_st.serial) + ", expecting " + std::to_string(currentSR->d_st.serial) + ") from SOA record while processing the removal part of an update"); } } + else { + totremove++; + SLOG(g_log << (g_logRPZChanges ? Logger::Info : Logger::Debug) << "Had removal of " << resourceRecord.d_name << " from RPZ zone " << zoneName << endl, + logger->info(g_logRPZChanges ? Logr::Info : Logr::Debug, "Remove from RPZ zone", "name", Logging::Loggable(resourceRecord.d_name))); + RPZRecordToPolicy(resourceRecord, newZone, false, params.defpol, params.defpolOverrideLocal, params.maxTTL, logger); + } } - /* only update sr now that all changes have been converted */ - if (currentSR) { - sr = std::move(currentSR); - } - SLOG(g_log << Logger::Info << "Had " << totremove << " RPZ removal" << addS(totremove) << ", " << totadd << " addition" << addS(totadd) << " for " << zoneName << " New serial: " << sr->d_st.serial << endl, - logger->info(Logr::Info, "RPZ mutations", "removals", Logging::Loggable(totremove), "additions", Logging::Loggable(totadd), "newserial", Logging::Loggable(sr->d_st.serial))); - newZone->setSerial(sr->d_st.serial); - newZone->setRefresh(sr->d_st.refresh); - setRPZZoneNewState(polName, sr->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, - since they might have been updated by another RPZ IXFR tracker thread. - */ - if (luaconfsLocal->generation != configGeneration) { - SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, - logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); - return; + for (const auto& resourceRecord : add) { // should always contain the new SOA + if (resourceRecord.d_type == QType::NS) { + continue; + } + if (resourceRecord.d_type == QType::SOA) { + auto tempSR = getRR(resourceRecord); + // g_log<d_st.serial<info(g_logRPZChanges ? Logr::Info : Logr::Debug, "Addition to RPZ zone", "name", Logging::Loggable(resourceRecord.d_name))); + RPZRecordToPolicy(resourceRecord, newZone, true, params.defpol, params.defpolOverrideLocal, params.maxTTL, logger); + } } - g_luaconfs.modify([zoneIdx, &newZone](LuaConfigItems& lci) { - lci.dfe.setZone(zoneIdx, newZone); - }); + } - if (!dumpZoneFileName.empty()) { - dumpZoneToDisk(logger, zoneName, newZone, dumpZoneFileName); - } - refresh = std::max(refreshFromConf ? refreshFromConf : newZone->getRefresh(), 1U); + /* only update sr now that all changes have been converted */ + if (currentSR) { + params.soaRecordContent = std::move(currentSR); } - catch (const std::exception& e) { - SLOG(g_log << Logger::Error << "Error while applying the update received over XFR for " << zoneName << ", skipping the update: " << e.what() << endl, - logger->error(Logr::Error, e.what(), "Exception while applying the update received over XFR, skipping", "exception", Logging::Loggable("std::exception"))); + 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); + + /* we need to replace the existing zone with the new one, + but we don't want to touch anything else, especially other zones, + since they might have been updated by another RPZ IXFR tracker thread. + */ + if (luaconfsLocal->generation != configGeneration) { + SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl, + logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread")); + return; } - catch (const PDNSException& e) { - SLOG(g_log << Logger::Error << "Error while applying the update received over XFR for " << zoneName << ", skipping the update: " << e.reason << endl, - logger->error(Logr::Error, e.reason, "Exception while applying the update received over XFR, skipping", "exception", Logging::Loggable("PDNSException"))); + g_luaconfs.modify([zoneIdx = params.zoneIdx, &newZone](LuaConfigItems& lci) { + lci.dfe.setZone(zoneIdx, newZone); + }); + + if (!params.dumpZoneFileName.empty()) { + dumpZoneToDisk(logger, zoneName, newZone, params.dumpZoneFileName); } + refresh = std::max(params.refreshFromConf != 0 ? params.refreshFromConf : newZone->getRefresh(), 1U); + } + catch (const std::exception& e) { + SLOG(g_log << Logger::Error << "Error while applying the update received over XFR for " << zoneName << ", skipping the update: " << e.what() << endl, + logger->error(Logr::Error, e.what(), "Exception while applying the update received over XFR, skipping", "exception", Logging::Loggable("std::exception"))); + } + catch (const PDNSException& e) { + SLOG(g_log << Logger::Error << "Error while applying the update received over XFR for " << zoneName << ", skipping the update: " << e.reason << endl, + logger->error(Logr::Error, e.reason, "Exception while applying the update received over XFR, skipping", "exception", Logging::Loggable("PDNSException"))); + } +} + +void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration) +{ + setThreadName("rec/rpzixfr"); + bool isPreloaded = params.soaRecordContent != nullptr; + auto logger = g_slog->withName("rpz"); + + /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */ + std::shared_ptr oldZone = g_luaconfs.getLocal()->dfe.getZone(params.zoneIdx); + if (!oldZone) { + SLOG(g_log << Logger::Error << "Unable to retrieve RPZ zone with index " << params.zoneIdx << " from the configuration, exiting" << endl, + logger->error(Logr::Error, "Unable to retrieve RPZ zone from configuration", "index", Logging::Loggable(params.zoneIdx))); + return; + } + + // If oldZone failed to load its getRefresh() returns 0, protect against that + uint32_t refresh = std::max(params.refreshFromConf != 0 ? params.refreshFromConf : oldZone->getRefresh(), 10U); + DNSName zoneName = oldZone->getDomain(); + std::string polName = !oldZone->getName().empty() ? oldZone->getName() : zoneName.toStringNoDot(); + + // Now that we know the name, set it in the logger + logger = logger->withValues("zone", Logging::Loggable(zoneName)); + + preloadRPZFIle(params, zoneName, oldZone, refresh, polName, logger); + + bool skipRefreshDelay = isPreloaded; + + for (;;) { + RPZTrackerIteration(params, zoneName, oldZone, refresh, polName, skipRefreshDelay, configGeneration, logger); } } diff --git a/pdns/recursordist/rpzloader.hh b/pdns/recursordist/rpzloader.hh index 8f37a0b4c0..c8811ee0b3 100644 --- a/pdns/recursordist/rpzloader.hh +++ b/pdns/recursordist/rpzloader.hh @@ -26,8 +26,24 @@ 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::vector primaries; + boost::optional defpol; + bool defpolOverrideLocal; + uint32_t maxTTL; + size_t zoneIdx; + TSIGTriplet tsigtriplet; + size_t maxReceivedBytes; + ComboAddress localAddress; + uint16_t xfrTimeout; + uint32_t refreshFromConf; + std::shared_ptr soaRecordContent; + std::string dumpZoneFileName; +}; + std::shared_ptr loadRPZFromFile(const std::string& fname, std::shared_ptr zone, const boost::optional& defpol, bool defpolOverrideLocal, uint32_t maxTTL); -void RPZIXFRTracker(const std::vector& primaries, const boost::optional& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t reloadFromConf, shared_ptr sr, const std::string& dumpZoneFileName, uint64_t configGeneration); +void RPZIXFRTracker(RPZTrackerParams params, uint64_t configGeneration); struct rpzStats {