From: Otto Moerbeek Date: Wed, 24 Jan 2024 08:46:44 +0000 (+0100) Subject: Build active Lua config from data structure that can be supplied by either Lua or... X-Git-Tag: rec-5.1.0-alpha1~9^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69da77c2872b551e5e89ea0bb6f725aa4d506044;p=thirdparty%2Fpdns.git Build active Lua config from data structure that can be supplied by either Lua or YAML --- diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 6f4d35e56e..43ac680342 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -514,6 +514,7 @@ rec_control_SOURCES = \ dnsparser.cc dnsparser.hh \ dnsrecords.cc dnsrecords.hh \ dnswriter.cc dnswriter.hh \ + filterpo.cc filterpo.hh \ logger.cc \ logging.cc \ misc.cc \ diff --git a/pdns/recursordist/filterpo.hh b/pdns/recursordist/filterpo.hh index d69b799e5d..2fec80813b 100644 --- a/pdns/recursordist/filterpo.hh +++ b/pdns/recursordist/filterpo.hh @@ -335,6 +335,10 @@ public: { d_zoneData->d_tags = std::move(tags); } + void setTags(const std::unordered_set& tags) + { + d_zoneData->d_tags = tags; + } void setPolicyOverridesGettag(bool flag) { d_zoneData->d_policyOverridesGettag = flag; diff --git a/pdns/recursordist/rec-lua-conf.cc b/pdns/recursordist/rec-lua-conf.cc index b57bec3f2b..2ac2026a3e 100644 --- a/pdns/recursordist/rec-lua-conf.cc +++ b/pdns/recursordist/rec-lua-conf.cc @@ -99,70 +99,67 @@ typename C::value_type::second_type constGet(const C& c, const std::string& name typedef std::unordered_map>>> rpzOptions_t; -static void parseRPZParameters(rpzOptions_t& have, std::shared_ptr& zone, std::string& polName, boost::optional& defpol, bool& defpolOverrideLocal, uint32_t& maxTTL) +static void parseRPZParameters(rpzOptions_t& have, RPZTrackerParams& params) { if (have.count("policyName") != 0) { - polName = boost::get(have["policyName"]); + params.polName = boost::get(have["policyName"]); } if (have.count("defpol") != 0) { - defpol = DNSFilterEngine::Policy(); - defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get(have["defpol"]); - defpol->setName(polName); - if (defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) { - if (!defpol->d_custom) { - defpol->d_custom = make_unique(); + params.defpol = DNSFilterEngine::Policy(); + params.defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get(have["defpol"]); + params.defpol->setName(params.polName); + if (params.defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) { + params.defcontent = boost::get(have["defcontent"]); + if (!params.defpol->d_custom) { + params.defpol->d_custom = make_unique(); } - defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN, - boost::get(have["defcontent"]))); + params.defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN, + params.defcontent)); if (have.count("defttl") != 0) { - defpol->d_ttl = static_cast(boost::get(have["defttl"])); + params.defpol->d_ttl = static_cast(boost::get(have["defttl"])); } else { - defpol->d_ttl = -1; // get it from the zone + params.defpol->d_ttl = -1; // get it from the zone } } if (have.count("defpolOverrideLocalData") != 0) { - defpolOverrideLocal = boost::get(have["defpolOverrideLocalData"]); + params.defpolOverrideLocal = boost::get(have["defpolOverrideLocalData"]); } } if (have.count("maxTTL") != 0) { - maxTTL = boost::get(have["maxTTL"]); + params.maxTTL = boost::get(have["maxTTL"]); } if (have.count("zoneSizeHint") != 0) { - auto zoneSizeHint = static_cast(boost::get(have["zoneSizeHint"])); - if (zoneSizeHint > 0) { - zone->reserve(zoneSizeHint); - } + params.zoneSizeHint = static_cast(boost::get(have["zoneSizeHint"])); } if (have.count("tags") != 0) { const auto& tagsTable = boost::get>>(have["tags"]); std::unordered_set tags; for (const auto& tag : tagsTable) { tags.insert(tag.second); + params.tags.insert(tag.second); } - zone->setTags(std::move(tags)); } if (have.count("overridesGettag") != 0) { - zone->setPolicyOverridesGettag(boost::get(have["overridesGettag"])); + params.defpolOverrideLocal = boost::get(have["overridesGettag"]); } if (have.count("extendedErrorCode") != 0) { auto code = boost::get(have["extendedErrorCode"]); if (code > std::numeric_limits::max()) { throw std::runtime_error("Invalid extendedErrorCode value " + std::to_string(code) + " in RPZ configuration"); } - - zone->setExtendedErrorCode(static_cast(code)); + params.extendedErrorCode = code; if (have.count("extendedErrorExtra") != 0) { - zone->setExtendedErrorExtra(boost::get(have["extendedErrorExtra"])); + params.extendedErrorExtra = boost::get(have["extendedErrorExtra"]); } } if (have.count("includeSOA") != 0) { - zone->setIncludeSOA(boost::get(have["includeSOA"])); + params.includeSOA = boost::get(have["includeSOA"]); } if (have.count("ignoreDuplicates") != 0) { - zone->setIgnoreDuplicates(boost::get(have["ignoreDuplicates"])); + params.ignoreDuplicates = boost::get(have["ignoreDuplicates"]); } } @@ -271,116 +268,72 @@ static void parseFrameStreamOptions(boost::optional vars, } #endif /* HAVE_FSTRM */ -static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThreads, const boost::variant>>& primaries_, const string& zoneName, boost::optional options) +static void rpzPrimary(LuaConfigItems& lci, const boost::variant>>& primaries_, const string& zoneName, boost::optional options) { - boost::optional defpol; - bool defpolOverrideLocal = true; + RPZTrackerParams params; + params.name = zoneName; + params.polName = zoneName; + std::shared_ptr zone = std::make_shared(); - TSIGTriplet tt; - uint32_t refresh = 0; - size_t maxReceivedXFRMBytes = 0; - uint16_t axfrTimeout = 20; - uint32_t maxTTL = std::numeric_limits::max(); - ComboAddress localAddress; - std::vector primaries; if (primaries_.type() == typeid(string)) { - primaries.push_back(ComboAddress(boost::get(primaries_), 53)); + params.primaries.emplace_back(boost::get(primaries_), 53); } else { for (const auto& primary : boost::get>>(primaries_)) { - primaries.push_back(ComboAddress(primary.second, 53)); + params.primaries.emplace_back(primary.second, 53); } } - size_t zoneIdx; - std::string dumpFile; - std::shared_ptr sr = nullptr; - try { - std::string seedFile; - std::string polName(zoneName); - if (options) { auto& have = *options; - parseRPZParameters(have, zone, polName, defpol, defpolOverrideLocal, maxTTL); + parseRPZParameters(have, params); - if (have.count("tsigname")) { - tt.name = DNSName(toLower(boost::get(have["tsigname"]))); - tt.algo = DNSName(toLower(boost::get(have["tsigalgo"]))); - if (B64Decode(boost::get(have["tsigsecret"]), tt.secret)) + if (have.count("tsigname") != 0) { + params.tsigtriplet.name = DNSName(toLower(boost::get(have["tsigname"]))); + params.tsigtriplet.algo = DNSName(toLower(boost::get(have["tsigalgo"]))); + if (B64Decode(boost::get(have["tsigsecret"]), params.tsigtriplet.secret)) { throw std::runtime_error("TSIG secret is not valid Base-64 encoded"); + } } - - if (have.count("refresh")) { - refresh = boost::get(have["refresh"]); - if (refresh == 0) { + if (have.count("refresh") != 0) { + params.refreshFromConf = boost::get(have["refresh"]); + if (params.refreshFromConf == 0) { SLOG(g_log << Logger::Warning << "rpzPrimary refresh value of 0 ignored" << endl, lci.d_slog->info(Logr::Warning, "rpzPrimary refresh value of 0 ignored")); } } - if (have.count("maxReceivedMBytes")) { - maxReceivedXFRMBytes = static_cast(boost::get(have["maxReceivedMBytes"])); + if (have.count("maxReceivedMBytes") != 0) { + params.maxReceivedMBytes = static_cast(boost::get(have["maxReceivedMBytes"])); } - if (have.count("localAddress")) { - localAddress = ComboAddress(boost::get(have["localAddress"])); + if (have.count("localAddress") != 0) { + params.localAddress = ComboAddress(boost::get(have["localAddress"])); } - if (have.count("axfrTimeout")) { - axfrTimeout = static_cast(boost::get(have["axfrTimeout"])); + if (have.count("axfrTimeout") != 0) { + params.xfrTimeout = static_cast(boost::get(have["axfrTimeout"])); } - if (have.count("seedFile")) { - seedFile = boost::get(have["seedFile"]); + if (have.count("seedFile") != 0) { + params.seedFileName = boost::get(have["seedFile"]); } - if (have.count("dumpFile")) { - dumpFile = boost::get(have["dumpFile"]); + if (have.count("dumpFile") != 0) { + params.dumpZoneFileName = boost::get(have["dumpFile"]); } } - if (localAddress != ComboAddress()) { + if (params.localAddress != ComboAddress()) { // We were passed a localAddress, check if its AF matches the primaries' - for (const auto& primary : primaries) { - if (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 (" + localAddress.toString() + ")."); + 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() + ")."); } } } - - DNSName domain(zoneName); - zone->setDomain(domain); - zone->setName(polName); - zoneIdx = lci.dfe.addZone(zone); - - auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(seedFile), "zone", Logging::Loggable(zoneName)); - if (!seedFile.empty()) { - SLOG(g_log << Logger::Info << "Pre-loading RPZ zone " << zoneName << " from seed file '" << seedFile << "'" << endl, - log->info(Logr::Info, "Pre-loading RPZ zone from seed file")); - try { - sr = loadRPZFromFile(seedFile, zone, defpol, defpolOverrideLocal, maxTTL); - - if (zone->getDomain() != domain) { - throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")"); - } - - if (sr == nullptr) { - throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record"); - } - } - catch (const PDNSException& e) { - SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << zoneName << " from seed file '" << seedFile << "': " << e.reason << endl, - log->error(Logr::Warning, e.reason, "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("PDNSException"))); - zone->clear(); - } - catch (const std::exception& e) { - SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << zoneName << " from seed file '" << seedFile << "': " << e.what() << endl, - log->error(Logr::Warning, e.what(), "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("std::exception"))); - zone->clear(); - } - } - lci.rpzRaw.emplace_back(RPZRaw{primaries, zoneName, options}); + lci.rpzs.emplace_back(params); } catch (const std::exception& e) { SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.what() << endl, @@ -390,8 +343,6 @@ static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThre SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.reason << endl, lci.d_slog->error(Logr::Error, e.reason, "Exception configuring 'rpzPrimary'", Logging::Loggable("PDNSException"))); } - - delayedThreads.rpzPrimaryThreads.emplace_back(RPZTrackerParams{std::move(primaries), std::move(defpol), defpolOverrideLocal, maxTTL, zoneIdx, std::move(tt), maxReceivedXFRMBytes, localAddress, axfrTimeout, refresh, std::move(sr), std::move(dumpFile)}); } // A wrapper class that loads the standard Lua defintions into the context, so that we can use things like pdns.A @@ -422,7 +373,7 @@ public: } }; -void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping& proxyMapping) +void loadRecursorLuaConfig(const std::string& fname, ProxyMapping& proxyMapping, LuaConfigItems& newLuaConfig) { LuaConfigItems lci; lci.d_slog = g_slog->withName("luaconfig"); @@ -455,39 +406,22 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de Lua->writeVariable("Policy", pmap); Lua->writeFunction("rpzFile", [&lci](const string& filename, boost::optional options) { - auto log = lci.d_slog->withValues("file", Logging::Loggable(filename)); - try { - boost::optional defpol; - bool defpolOverrideLocal = true; - std::string polName("rpzFile"); - std::shared_ptr zone = std::make_shared(); - uint32_t maxTTL = std::numeric_limits::max(); - if (options) { - auto& have = *options; - parseRPZParameters(have, zone, polName, defpol, defpolOverrideLocal, maxTTL); - } - SLOG(g_log << Logger::Warning << "Loading RPZ from file '" << filename << "'" << endl, - log->info(Logr::Info, "Loading RPZ from file")); - zone->setName(polName); - loadRPZFromFile(filename, zone, defpol, defpolOverrideLocal, maxTTL); - lci.dfe.addZone(std::move(zone)); - SLOG(g_log << Logger::Warning << "Done loading RPZ from file '" << filename << "'" << endl, - log->info(Logr::Info, "Done loading RPZ from file")); - lci.rpzRaw.emplace_back(RPZRaw{{}, filename, options}); - } - catch (const std::exception& e) { - SLOG(g_log << Logger::Error << "Unable to load RPZ zone from '" << filename << "': " << e.what() << endl, - log->error(Logr::Error, e.what(), "Exception while loading RPZ zone from file")); + RPZTrackerParams params; + params.name = filename; + params.polName = "rpzFile"; + if (options) { + parseRPZParameters(*options, params); } + lci.rpzs.emplace_back(params); }); - Lua->writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant>>& primaries_, const string& zoneName, boost::optional options) { + Lua->writeFunction("rpzMaster", [&lci](const boost::variant>>& primaries_, const string& zoneName, boost::optional options) { SLOG(g_log << Logger::Warning << "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead" << endl, lci.d_slog->info(Logr::Warning, "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead")); - rpzPrimary(lci, delayedThreads, primaries_, zoneName, options); + rpzPrimary(lci, primaries_, zoneName, options); }); - Lua->writeFunction("rpzPrimary", [&lci, &delayedThreads](const boost::variant>>& primaries_, const string& zoneName, boost::optional options) { - rpzPrimary(lci, delayedThreads, primaries_, zoneName, options); + Lua->writeFunction("rpzPrimary", [&lci](const boost::variant>>& primaries_, const string& zoneName, boost::optional options) { + rpzPrimary(lci, primaries_, zoneName, options); }); typedef std::unordered_map> zoneToCacheOptions_t; @@ -607,14 +541,12 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de }); Lua->writeFunction("addTA", [&lci](const std::string& who, const std::string& what) { - warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addTA), but dnssec is set to 'off'!"); DNSName zone(who); auto ds = std::dynamic_pointer_cast(DSRecordContent::make(what)); lci.dsAnchors[zone].insert(*ds); }); Lua->writeFunction("clearTA", [&lci](boost::optional who) { - warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearTA), but dnssec is set to 'off'!"); if (who) lci.dsAnchors.erase(DNSName(*who)); else @@ -623,7 +555,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de /* Remove in 4.3 */ Lua->writeFunction("addDS", [&lci](const std::string& who, const std::string& what) { - warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!"); SLOG(g_log << Logger::Warning << "addDS is deprecated and will be removed in the future, switch to addTA" << endl, lci.d_slog->info(Logr::Warning, "addDS is deprecated and will be removed in the future, switch to addTA")); DNSName zone(who); @@ -635,7 +566,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de Lua->writeFunction("clearDS", [&lci](boost::optional who) { SLOG(g_log << Logger::Warning << "clearDS is deprecated and will be removed in the future, switch to clearTA" << endl, lci.d_slog->info(Logr::Warning, "clearDS is deprecated and will be removed in the future, switch to clearTA")); - warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!"); if (who) lci.dsAnchors.erase(DNSName(*who)); else @@ -643,7 +573,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de }); Lua->writeFunction("addNTA", [&lci](const std::string& who, const boost::optional why) { - warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!"); if (why) lci.negAnchors[DNSName(who)] = static_cast(*why); else @@ -651,7 +580,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de }); Lua->writeFunction("clearNTA", [&lci](boost::optional who) { - warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!"); if (who) lci.negAnchors.erase(DNSName(*who)); else @@ -663,10 +591,8 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de if (interval) { realInterval = static_cast(*interval); } - warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!"); lci.trustAnchorFileInfo.fname = fnamearg; lci.trustAnchorFileInfo.interval = realInterval; - updateTrustAnchorsFromFile(fnamearg, lci.dsAnchors, lci.d_slog); }); Lua->writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) { @@ -876,7 +802,7 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de try { Lua->executeCode(ifs); - g_luaconfs.setState(std::move(lci)); + newLuaConfig = lci; } catch (const LuaContext::ExecutionErrorException& e) { SLOG(g_log << Logger::Error << "Unable to load Lua script from '" + fname + "': ", @@ -902,25 +828,3 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de throw; } } - -void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation) -{ - for (const auto& rpzPrimary : delayedThreads.rpzPrimaryThreads) { - 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 theThread(RPZIXFRTracker, rpzPrimary, generation); - theThread.detach(); - } - catch (const std::exception& e) { - SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.what() << endl, - g_slog->withName("rpz")->error(Logr::Error, e.what(), "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("std::exception"))); - exit(1); - } - catch (const PDNSException& e) { - SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.reason << endl, - g_slog->withName("rpz")->error(Logr::Error, e.reason, "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("PDNSException"))); - exit(1); - } - } -} diff --git a/pdns/recursordist/rec-lua-conf.hh b/pdns/recursordist/rec-lua-conf.hh index abed5c4196..7e595715b0 100644 --- a/pdns/recursordist/rec-lua-conf.hh +++ b/pdns/recursordist/rec-lua-conf.hh @@ -101,20 +101,13 @@ using ProxyMapping = NetmaskTree; using rpzOptions_t = std::unordered_map>>>; -struct RPZRaw -{ - std::vector addresses; - std::string name; - boost::optional options; -}; - class LuaConfigItems { public: LuaConfigItems(); SortList sortlist; DNSFilterEngine dfe; - vector rpzRaw; + vector rpzs; TrustAnchorFileInfo trustAnchorFileInfo; // Used to update the Trust Anchors from file periodically map dsAnchors; map negAnchors; @@ -135,10 +128,4 @@ public: extern GlobalStateHolder g_luaconfs; -struct luaConfigDelayedThreads -{ - std::vector rpzPrimaryThreads; -}; - -void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping&); -void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation); +void loadRecursorLuaConfig(const std::string& fname, ProxyMapping&, LuaConfigItems& newConfig); diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 2bfc587aa8..5ff54beb9b 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -42,6 +42,8 @@ #include "settings/cxxsettings.hh" #include "json.hh" #include "rec-system-resolve.hh" +#include "root-dnssec.hh" + #ifdef NOD_ENABLED #include "nod.hh" #endif /* NOD_ENABLED */ @@ -2079,12 +2081,13 @@ static int serviceMain(Logr::log_t log) } g_maxCacheEntries = ::arg().asNum("max-cache-entries"); - luaConfigDelayedThreads delayedLuaThreads; try { ProxyMapping proxyMapping; - loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping); + LuaConfigItems lci; + loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci); // Initial proxy mapping g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique(proxyMapping); + activateLuaConfig(lci); } catch (PDNSException& e) { SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl, @@ -2257,8 +2260,8 @@ static int serviceMain(Logr::log_t log) return ret; } - startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation); - delayedLuaThreads.rpzPrimaryThreads.clear(); // no longer needed + auto lci = g_luaconfs.getCopy(); + activateLuaConfig(lci); RecThreadInfo::makeThreadPipes(log); @@ -2904,17 +2907,16 @@ static pair doYamlConfig(Logr::log_t startupLog, int argc, char* argv ::arg().parse(argc, argv); pdns::rust::settings::rec::Recursorsettings settings; pdns::settings::rec::oldStyleSettingsToBridgeStruct(settings); - luaConfigDelayedThreads delayedLuaThreads; ProxyMapping proxyMapping; + LuaConfigItems lci; try { - loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping); + loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci); } catch (PDNSException& e) { SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl, startupLog->error(Logr::Error, e.reason, "Cannot load Lua configuration")); } - auto luaConfig = g_luaconfs.getLocal(); - pdns::settings::rec::fromLuaConfigToBridgeStruct(luaConfig, proxyMapping, settings); + pdns::settings::rec::fromLuaConfigToBridgeStruct(lci, proxyMapping, settings); auto yaml = settings.to_yaml_string(); cout << yaml << endl; } @@ -3335,3 +3337,128 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q return res; } + +static void startLuaConfigDelayedThreads(const vector& rpzs, uint64_t generation) +{ + for (const auto& rpzPrimary : rpzs) { + if (rpzPrimary.primaries.empty()) { + continue; + } + 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 theThread(RPZIXFRTracker, rpzPrimary, generation); + theThread.detach(); + } + catch (const std::exception& e) { + SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.what() << endl, + g_slog->withName("rpz")->error(Logr::Error, e.what(), "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("std::exception"))); + exit(1); + } + catch (const PDNSException& e) { + SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.reason << endl, + g_slog->withName("rpz")->error(Logr::Error, e.reason, "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("PDNSException"))); + exit(1); + } + } +} + +static void activateRPZFile(const RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr& zone) +{ + auto log = lci.d_slog->withValues("file", Logging::Loggable(params.name)); + + zone->setName(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); + SLOG(g_log << Logger::Warning << "Done loading RPZ from file '" << params.name << "'" << endl, + log->info(Logr::Info, "Done loading RPZ from file")); + } + catch (const std::exception& e) { + SLOG(g_log << Logger::Error << "Unable to load RPZ zone from '" << params.name << "': " << e.what() << endl, + log->error(Logr::Error, e.what(), "Exception while loading RPZ zone from file")); + } +} + +static void activateRPZPrimary(RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr& zone, const DNSName& domain) +{ + auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(params.seedFileName), "zone", Logging::Loggable(params.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); + + 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() + ")"); + } + + if (params.soaRecordContent == nullptr) { + throw PDNSException("The RPZ zone " + params.name + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record"); + } + } + catch (const PDNSException& e) { + SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << params.name << " from seed file '" << params.seedFileName << "': " << e.reason << endl, + log->error(Logr::Warning, e.reason, "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("PDNSException"))); + zone->clear(); + } + catch (const std::exception& e) { + SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << params.name << " from seed file '" << params.seedFileName << "': " << e.what() << endl, + log->error(Logr::Warning, e.what(), "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("std::exception"))); + zone->clear(); + } + } +} + +static void activateRPZs(LuaConfigItems& lci) +{ + for (auto& params : lci.rpzs) { + auto zone = std::make_shared(); + if (params.zoneSizeHint != 0) { + zone->reserve(params.zoneSizeHint); + } + if (!params.tags.empty()) { + zone->setTags(params.tags); + } + zone->setPolicyOverridesGettag(params.defpolOverrideLocal); + if (params.extendedErrorCode != std::numeric_limits::max()) { + zone->setExtendedErrorCode(params.extendedErrorCode); + if (!params.extendedErrorExtra.empty()) { + zone->setExtendedErrorExtra(params.extendedErrorExtra); + } + } + zone->setIncludeSOA(params.includeSOA); + zone->setIgnoreDuplicates(params.ignoreDuplicates); + + if (params.primaries.empty()) { + activateRPZFile(params, lci, zone); + lci.dfe.addZone(std::move(zone)); + } + else { + DNSName domain(params.name); + zone->setDomain(domain); + zone->setName(params.polName); + params.zoneIdx = lci.dfe.addZone(zone); + activateRPZPrimary(params, lci, zone, domain); + } + } + startLuaConfigDelayedThreads(lci.rpzs, lci.generation); +} + +void activateLuaConfig(LuaConfigItems& lci) +{ + if (!lci.trustAnchorFileInfo.fname.empty()) { + warnIfDNSSECDisabled("Warning: reading Trust Anchors from file, but dnssec is set to 'off'!"); + updateTrustAnchorsFromFile(lci.trustAnchorFileInfo.fname, lci.dsAnchors, lci.d_slog); + } + if (lci.dsAnchors.size() > rootDSs.size()) { + warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC, but dnssec is set to 'off'!"); + } + if (!lci.negAnchors.empty()) { + warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC, but dnssec is set to 'off'!"); + } + activateRPZs(lci); + g_luaconfs.setState(std::move(lci)); +} diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index 98c6898696..fd51919d41 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -620,6 +620,7 @@ void handleNewTCPQuestion(int fileDesc, FDMultiplexer::funcparam_t&); void makeUDPServerSockets(deferredAdd_t& deferredAdds, Logr::log_t); string doTraceRegex(FDWrapper file, vector::const_iterator begin, vector::const_iterator end); +void activateLuaConfig(LuaConfigItems& lci); #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10" #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10" diff --git a/pdns/recursordist/rec_channel_rec.cc b/pdns/recursordist/rec_channel_rec.cc index 8a3af52076..fe95ee0558 100644 --- a/pdns/recursordist/rec_channel_rec.cc +++ b/pdns/recursordist/rec_channel_rec.cc @@ -2138,10 +2138,10 @@ static RecursorControlChannel::Answer luaconfig(T begin, T end) ::arg().set("lua-config-file") = *begin; } try { - luaConfigDelayedThreads delayedLuaThreads; ProxyMapping proxyMapping; - loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping); - startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation); + LuaConfigItems lci; + loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci); + activateLuaConfig(lci); broadcastFunction([=] { return pleaseSupplantProxyMapping(proxyMapping); }); g_log << Logger::Warning << "Reloaded Lua configuration file '" << ::arg()["lua-config-file"] << "', requested via control channel" << endl; return {0, "Reloaded Lua configuration file '" + ::arg()["lua-config-file"] + "'\n"}; diff --git a/pdns/recursordist/rpzloader.cc b/pdns/recursordist/rpzloader.cc index 4b28464edb..1870a4f494 100644 --- a/pdns/recursordist/rpzloader.cc +++ b/pdns/recursordist/rpzloader.cc @@ -454,7 +454,7 @@ static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, st std::shared_ptr newZone = std::make_shared(*oldZone); for (const auto& primary : params.primaries) { try { - params.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.tsigtriplet, params.maxReceivedBytes, params.localAddress, params.xfrTimeout); + 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); refresh = std::max(params.refreshFromConf != 0 ? params.refreshFromConf : newZone->getRefresh(), 1U); @@ -543,7 +543,7 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam } try { - deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedBytes); + deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedMBytes); /* no need to try another primary */ break; diff --git a/pdns/recursordist/rpzloader.hh b/pdns/recursordist/rpzloader.hh index 57fddce8af..3e94acde49 100644 --- a/pdns/recursordist/rpzloader.hh +++ b/pdns/recursordist/rpzloader.hh @@ -29,18 +29,28 @@ 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 primaries; boost::optional defpol; - bool defpolOverrideLocal; - uint32_t maxTTL; - size_t zoneIdx; + std::string defcontent; + bool defpolOverrideLocal{true}; + uint32_t maxTTL = std::numeric_limits::max(); + size_t zoneIdx{0}; TSIGTriplet tsigtriplet; - size_t maxReceivedBytes; + size_t maxReceivedMBytes{0}; ComboAddress localAddress; - uint16_t xfrTimeout; - uint32_t refreshFromConf; + uint16_t xfrTimeout{20}; + uint32_t refreshFromConf{0}; std::shared_ptr soaRecordContent; + std::string seedFileName; std::string dumpZoneFileName; + std::string polName; + size_t zoneSizeHint{0}; + std::unordered_set tags; + uint32_t extendedErrorCode{std::numeric_limits::max()}; + std::string extendedErrorExtra; + bool includeSOA{false}; + bool ignoreDuplicates{false}; }; std::shared_ptr loadRPZFromFile(const std::string& fname, const std::shared_ptr& zone, const boost::optional& defpol, bool defpolOverrideLocal, uint32_t maxTTL); diff --git a/pdns/recursordist/settings/cxxsettings.hh b/pdns/recursordist/settings/cxxsettings.hh index cb0f9a086b..d327820f5b 100644 --- a/pdns/recursordist/settings/cxxsettings.hh +++ b/pdns/recursordist/settings/cxxsettings.hh @@ -52,6 +52,6 @@ void readYamlAllowFromFile(const std::string& filename, ::rust::Vec<::rust::Stri void readYamlAllowNotifyForFile(const std::string& filename, ::rust::Vec<::rust::String>& vec, Logr::log_t log); void setArgsForZoneRelatedSettings(pdns::rust::settings::rec::Recursorsettings& settings); void setArgsForACLRelatedSettings(pdns::rust::settings::rec::Recursorsettings& settings); -void fromLuaConfigToBridgeStruct(LocalStateHolder& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings); - void fromBridgeStructToLuaConfig(const pdns::rust::settings::rec::Recursorsettings& settings, LuaConfigItems& luaConfig, ProxyMapping& proxyMapping); +void fromLuaConfigToBridgeStruct(LuaConfigItems& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings); +void fromBridgeStructToLuaConfig(const pdns::rust::settings::rec::Recursorsettings& settings, LuaConfigItems& luaConfig, ProxyMapping& proxyMapping); } diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index e2b49b992b..8a12eeffd3 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -37,6 +37,7 @@ #include "root-dnssec.hh" #include "dnsrecords.hh" #include "base64.hh" +#include "validate-recursor.hh" ::rust::Vec<::rust::String> pdns::settings::rec::getStrings(const std::string& name) { @@ -710,11 +711,11 @@ std::string pdns::settings::rec::defaultsToYaml() namespace { -void fromLuaToRust(LocalStateHolder& luaConfig, pdns::rust::settings::rec::Dnssec& dnssec) +void fromLuaToRust(const LuaConfigItems& luaConfig, pdns::rust::settings::rec::Dnssec& dnssec) { - dnssec.trustanchorfile = luaConfig->trustAnchorFileInfo.fname; - dnssec.trustanchorfile_interval = luaConfig->trustAnchorFileInfo.interval; - for (const auto& anchors : luaConfig->dsAnchors) { + dnssec.trustanchorfile = luaConfig.trustAnchorFileInfo.fname; + dnssec.trustanchorfile_interval = luaConfig.trustAnchorFileInfo.interval; + for (const auto& anchors : luaConfig.dsAnchors) { ::rust::Vec<::rust::String> dsRecords; for (const auto& dsRecord : anchors.second) { const auto dsString = dsRecord.getZoneRepresentation(); @@ -725,7 +726,7 @@ void fromLuaToRust(LocalStateHolder& luaConfig, pdns::rust::sett pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords}; dnssec.trustanchors.emplace_back(trustAnchor); } - for (const auto& anchors : luaConfig->negAnchors) { + for (const auto& anchors : luaConfig.negAnchors) { pdns::rust::settings::rec::NegativeTrustAnchor negtrustAnchor{anchors.first.toString(), anchors.second}; dnssec.negative_trustanchors.emplace_back(negtrustAnchor); } @@ -779,37 +780,45 @@ void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec dnstap.reopenInterval = fsc.reopenInterval; } - -template -void setIfAvailable(const rpzOptions_t& table, T& var, const std::string& name) +void assign(pdns::rust::settings::rec::TSIGTriplet& var, const TSIGTriplet& tsig) { - if (table.count(name) != 0) { - var = boost::get(table.at(name)); - } + var.name = tsig.name.empty() ? "" : tsig.name.toStringNoDot(); + var.algo = tsig.algo.empty() ? "" : tsig.algo.toStringNoDot(); + var.secret = Base64Encode(tsig.secret); } -void setIfAvailable(const rpzOptions_t& table, rust::string& var, const std::string& name) +void assign(TSIGTriplet& var, const pdns::rust::settings::rec::TSIGTriplet& tsig) { - if (table.count(name) != 0) { - var = boost::get(table.at(name)); - } + var.name = DNSName(std::string(tsig.name)); + var.algo = DNSName(std::string(tsig.algo)); + B64Decode(std::string(tsig.secret), var.secret); } -void setIfAvailable(const rpzOptions_t& table, pdns::rust::settings::rec::TSIGTriplet& var, const std::string& name) +std::string cvt(DNSFilterEngine::PolicyKind kind) { - if (table.count(name) != 0) { - var.name = boost::get(table.at("tsigname")); - var.algo = boost::get(table.at("tsigalgo")); - var.secret = boost::get(table.at("tsigsecret")); + switch (kind) { + case DNSFilterEngine::PolicyKind::NoAction: + return "NoAction"; + case DNSFilterEngine::PolicyKind::Drop: + return "Drop"; + case DNSFilterEngine::PolicyKind::NXDOMAIN: + return "NXDOMAIN"; + case DNSFilterEngine::PolicyKind::NODATA: + return "NODATA"; + case DNSFilterEngine::PolicyKind::Truncate: + return "Truncate"; + case DNSFilterEngine::PolicyKind::Custom: + return "Custom"; } } -void fromLuaToRust(const vector& rpzs, pdns::rust::settings::rec::Recursor& rec) + +void fromLuaToRust(const vector& rpzs, pdns::rust::settings::rec::Recursor& rec) { for (const auto& rpz : rpzs) { pdns::rust::settings::rec::RPZ rustrpz{ .defpolOverrideLocalData = true, .defttl = std::numeric_limits::max(), - .extendedErrorCode = 0, + .extendedErrorCode = std::numeric_limits::max(), .includeSOA = false, .ignoreDuplicates = false, .maxTTL = std::numeric_limits::max(), @@ -819,37 +828,37 @@ void fromLuaToRust(const vector& rpzs, pdns::rust::settings::rec::Recurs .maxReceivedMBytes = 0, .axfrTimeout = 20}; - for (const auto& address : rpz.addresses) { + for (const auto& address : rpz.primaries) { rustrpz.addresses.emplace_back(address.toStringWithPort()); } rustrpz.name = rpz.name; - if (rpz.options) { - setIfAvailable(*rpz.options, rustrpz.defcontent, "defcontent"); - setIfAvailable(*rpz.options, rustrpz.defpol, "defpol"); - setIfAvailable(*rpz.options, rustrpz.defpolOverrideLocalData, "defpolOverrideLocalData"); - setIfAvailable(*rpz.options, rustrpz.defttl, "defttl"); - setIfAvailable(*rpz.options, rustrpz.extendedErrorCode, "extendedErrorCode"); - setIfAvailable(*rpz.options, rustrpz.extendedErrorExtra, "extendedErrorExtra"); - setIfAvailable(*rpz.options, rustrpz.includeSOA, "includeSOA"); - setIfAvailable(*rpz.options, rustrpz.ignoreDuplicates, "ignoreDuplicates"); - setIfAvailable(*rpz.options, rustrpz.maxTTL, "maxTTL"); - setIfAvailable(*rpz.options, rustrpz.policyName, "policyName"); - if (rpz.options->count("tags") != 0) { - const auto& tags = boost::get>>(rpz.options->at("tags")); - for (const auto& tag : tags) { - rustrpz.tags.emplace_back(tag.second); - } - } - setIfAvailable(*rpz.options, rustrpz.overridesGettag, "overridesGettag"); - setIfAvailable(*rpz.options, rustrpz.zoneSizeHint, "zoneSizeHint"); - setIfAvailable(*rpz.options, rustrpz.tsig, "tsig"); - setIfAvailable(*rpz.options, rustrpz.refresh, "refresh"); - setIfAvailable(*rpz.options, rustrpz.maxReceivedMBytes, "maxReceivedMBytes"); - setIfAvailable(*rpz.options, rustrpz.localAddress, "localAddress"); - setIfAvailable(*rpz.options, rustrpz.axfrTimeout, "axfrTimeout"); - setIfAvailable(*rpz.options, rustrpz.dumpFile, "dumpFile"); - setIfAvailable(*rpz.options, rustrpz.seedFile, "seedFile"); + rustrpz.defcontent = rpz.defcontent; + if (rpz.defpol) { + rustrpz.defpol = cvt(rpz.defpol->d_kind); + rustrpz.defttl = rpz.defpol->d_ttl; + } + rustrpz.defpolOverrideLocalData = rpz.defpolOverrideLocal; + rustrpz.extendedErrorCode = rpz.extendedErrorCode; + rustrpz.extendedErrorExtra = rpz.extendedErrorExtra; + rustrpz.includeSOA = rpz.includeSOA; + rustrpz.ignoreDuplicates = rpz.ignoreDuplicates; + rustrpz.maxTTL = rpz.maxTTL; + rustrpz.policyName = rpz.polName; + for (const auto& tag : rpz.tags) { + rustrpz.tags.emplace_back(tag); } + rustrpz.overridesGettag = rpz.defpolOverrideLocal; + rustrpz.zoneSizeHint = rpz.zoneSizeHint; + assign(rustrpz.tsig, rpz.tsigtriplet); + rustrpz.refresh = rpz.refreshFromConf; + rustrpz.maxReceivedMBytes = rpz.maxReceivedMBytes; + if (rpz.localAddress != ComboAddress()) { + rustrpz.localAddress = rpz.localAddress.toString(); + } + rustrpz.axfrTimeout = rpz.xfrTimeout; + rustrpz.dumpFile = rpz.dumpZoneFileName; + rustrpz.seedFile = rpz.seedFileName; + rec.rpzs.emplace_back(rustrpz); } } @@ -994,34 +1003,36 @@ void fromLuaToRust(const SortList& arg, pdns::rust::settings::rec::Recursor& rec } } // namespace -void pdns::settings::rec::fromLuaConfigToBridgeStruct(LocalStateHolder& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings) +void pdns::settings::rec::fromLuaConfigToBridgeStruct(LuaConfigItems& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings) { fromLuaToRust(luaConfig, settings.dnssec); - if (luaConfig->protobufExportConfig.enabled) { + settings.logging.protobuf_mask_v4 = luaConfig.protobufMaskV4; + settings.logging.protobuf_mask_v6 = luaConfig.protobufMaskV6; + if (luaConfig.protobufExportConfig.enabled) { pdns::rust::settings::rec::ProtobufServer pbServer; - fromLuaToRust(luaConfig->protobufExportConfig, pbServer); + fromLuaToRust(luaConfig.protobufExportConfig, pbServer); settings.logging.protobuf_servers.emplace_back(pbServer); } - if (luaConfig->outgoingProtobufExportConfig.enabled) { + if (luaConfig.outgoingProtobufExportConfig.enabled) { pdns::rust::settings::rec::ProtobufServer pbServer; - fromLuaToRust(luaConfig->outgoingProtobufExportConfig, pbServer); + fromLuaToRust(luaConfig.outgoingProtobufExportConfig, pbServer); settings.logging.outgoing_protobuf_servers.emplace_back(pbServer); } - if (luaConfig->frameStreamExportConfig.enabled) { + if (luaConfig.frameStreamExportConfig.enabled) { pdns::rust::settings::rec::DNSTapFrameStreamServer dnstap; - fromLuaToRust(luaConfig->frameStreamExportConfig, dnstap); + fromLuaToRust(luaConfig.frameStreamExportConfig, dnstap); settings.logging.dnstap_framestream_servers.emplace_back(dnstap); } - if (luaConfig->nodFrameStreamExportConfig.enabled) { + if (luaConfig.nodFrameStreamExportConfig.enabled) { pdns::rust::settings::rec::DNSTapNODFrameStreamServer dnstap; - fromLuaToRust(luaConfig->nodFrameStreamExportConfig, dnstap); + fromLuaToRust(luaConfig.nodFrameStreamExportConfig, dnstap); settings.logging.dnstap_nod_framestream_servers.emplace_back(dnstap); } - fromLuaToRust(luaConfig->rpzRaw, settings.recursor); - fromLuaToRust(luaConfig->sortlist, settings.recursor); - fromLuaToRust(luaConfig->ztcConfigs, settings.recordcache); - fromLuaToRust(luaConfig->allowAdditionalQTypes, settings.recursor); + fromLuaToRust(luaConfig.rpzs, settings.recursor); + fromLuaToRust(luaConfig.sortlist, settings.recursor); + fromLuaToRust(luaConfig.ztcConfigs, settings.recordcache); + fromLuaToRust(luaConfig.allowAdditionalQTypes, settings.recursor); fromLuaToRust(proxyMapping, settings.incoming); } @@ -1105,78 +1116,75 @@ void fromRustToLuaConfig(const pdns::rust::settings::rec::DNSTapNODFrameStreamSe exp.reopenInterval = dnstap.reopenInterval; } +DNSFilterEngine::PolicyKind cvtKind(const std::string& kind) +{ + static const std::map map = { + { "Custom", DNSFilterEngine::PolicyKind::Custom }, + { "Drop", DNSFilterEngine::PolicyKind::Drop }, + { "NoAction", DNSFilterEngine::PolicyKind::NoAction }, + { "NODATA", DNSFilterEngine::PolicyKind::NODATA }, + { "NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN }, + { "Truncate", DNSFilterEngine::PolicyKind::Truncate } + }; + if (auto iter = map.find(kind); iter != map.end()) { + return iter->second; + } + throw runtime_error("PolicyKind '" + kind + "' unknown"); +} + void fromRustToLuaConfig(const rust::Vec& rpzs, LuaConfigItems& luaConfig) { for (const auto& rpz : rpzs) { - RPZRaw rpzRaw; + RPZTrackerParams params; for (const auto& address : rpz.addresses) { - rpzRaw.addresses.emplace_back(std::string(address)); + params.primaries.emplace_back(std::string(address)); } - rpzRaw.name = std::string(rpz.name); - rpzOptions_t options; + params.name = std::string(rpz.name); + params.polName = std::string(rpz.policyName); + + if (!rpz.defpol.empty()) { + params.defpol = DNSFilterEngine::Policy(); + params.defcontent = std::string(rpz.defcontent); + params.defpol->d_kind = cvtKind(std::string(rpz.defpol)); + params.defpol->setName(params.polName); + if (params.defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) { + if (!params.defpol->d_custom) { + params.defpol->d_custom = make_unique(); + } + params.defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN, + std::string(params.defcontent))); - auto setIfNonDefault = [&options](const rust::String& value, const string& name) - { - if (!value.empty()) { - options[name] = std::string(value); + if (rpz.defttl != std::numeric_limits::max()) { + params.defpol->d_ttl = static_cast(rpz.defttl); + } + else { + params.defpol->d_ttl = -1; // get it from the zone + } } - }; - setIfNonDefault(rpz.defcontent, "defcontent"); - setIfNonDefault(rpz.defpol, "defpol"); - if (!rpz.defpolOverrideLocalData) { - options["defpolOverrideLocalData"] = false; - } - if (rpz.defttl != -1U) { - options["defttl"] = rpz.defttl; - } - if (rpz.extendedErrorCode != 0) { - options["extendedErrorCode"] = rpz.extendedErrorCode; - } - setIfNonDefault(rpz.extendedErrorExtra, "extendedErrorExtra"); - if (rpz.includeSOA) { - options["includeSOA"] = true; - } - if (rpz.ignoreDuplicates) { - options["ignoreDuplicates"] = true; - } - if (rpz.maxTTL != -1U) { - options["maxTTL"] = rpz.maxTTL; } - setIfNonDefault(rpz.policyName, "policyName"); - std::vector> tags; - int count = 0; + params.defpolOverrideLocal = rpz.defpolOverrideLocalData; + params.extendedErrorCode = rpz.extendedErrorCode; + params.extendedErrorExtra = std::string(rpz.extendedErrorExtra); + params.includeSOA = rpz.includeSOA; + params.ignoreDuplicates = rpz.ignoreDuplicates; + params.maxTTL = rpz.maxTTL; + for (const auto& tag : rpz.tags) { - tags.emplace_back(++count, tag); - } - if (!tags.empty()) { - options["tags"] = tags; - } - if (!rpz.overridesGettag) { - options["overridesGettag"] = false; - } - if (rpz.zoneSizeHint != 0) { - options["zoneSizeHint"] = rpz.zoneSizeHint; + params.tags.emplace(std::string(tag)); } - setIfNonDefault(rpz.tsig.name, "tsigname"); - setIfNonDefault(rpz.tsig.algo, "tsigalgo"); - setIfNonDefault(rpz.tsig.secret, "tsigsecret"); - if (rpz.refresh != 0) { - options["refresh"] = rpz.refresh; + params.defpolOverrideLocal = rpz.overridesGettag; + params.zoneSizeHint = rpz.zoneSizeHint; + assign(params.tsigtriplet, rpz.tsig); + params.refreshFromConf = rpz.refresh; + params.maxReceivedMBytes = rpz.maxReceivedMBytes; + if (!rpz.localAddress.empty()) { + params.localAddress = ComboAddress(std::string(rpz.localAddress)); } - if (rpz.maxReceivedMBytes != 0) { - options["maxReceivedMBytes"] = rpz.maxReceivedMBytes; - } - setIfNonDefault(rpz.localAddress, "localAddress"); - if (rpz.axfrTimeout != 0) { - options["axfrTimeout"] = rpz.axfrTimeout; - } - setIfNonDefault(rpz.dumpFile, "dumpFile"); - setIfNonDefault(rpz.seedFile, "seedFile"); - if (!options.empty()) { - rpzRaw.options = options; - } - luaConfig.rpzRaw.emplace_back(rpzRaw); + params.xfrTimeout = rpz.axfrTimeout; + params.dumpZoneFileName = std::string(rpz.dumpFile); + params.seedFileName = std::string(rpz.seedFile); + luaConfig.rpzs.emplace_back(params); } } @@ -1251,6 +1259,8 @@ void fromRustToLuaConfig(const rust::Vec gsluaConfig; - gsluaConfig.setState(luaConfig); - LocalStateHolder local = gsluaConfig.getLocal(); + //GlobalStateHolder gsluaConfig; + //gsluaConfig.setState(luaConfig); + //LuaConfigItems local; // = gsluaConfig.getCopy(); try { - pdns::settings::rec::fromLuaConfigToBridgeStruct(local, proxyMapping, newsettings); + pdns::settings::rec::fromLuaConfigToBridgeStruct(luaConfig, proxyMapping, newsettings); } catch (std::exception& e) { cerr << e.what() << endl;