From e20008739f250ee9799a95ced45eae202ae3db44 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Thu, 1 Feb 2024 12:45:34 +0100 Subject: [PATCH] (re)load Lua config from either Lua or YAML --- pdns/recursordist/Makefile.am | 2 +- pdns/recursordist/rec-main.cc | 106 +++++++------ pdns/recursordist/rec-main.hh | 2 + pdns/recursordist/rec_channel.hh | 1 + pdns/recursordist/rec_channel_rec.cc | 85 +++++++++-- pdns/recursordist/rec_control.cc | 2 +- pdns/recursordist/rpzloader.hh | 2 +- pdns/recursordist/settings/cxxsettings.hh | 2 + pdns/recursordist/settings/cxxsupport.cc | 143 ++++++++++++++---- pdns/recursordist/settings/rust/src/bridge.rs | 1 + pdns/recursordist/test-settings.cc | 14 +- .../test_Carbon.py | 10 +- regression-tests.recursor-dnssec/test_ECS.py | 2 +- .../test_Protobuf.py | 4 +- .../test_RPZIncomplete.py | 4 +- .../test_RecDnstap.py | 4 +- 16 files changed, 262 insertions(+), 122 deletions(-) diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index afc41e9a46..fbec4c82b1 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -516,10 +516,10 @@ rec_control_SOURCES = \ dnsrecords.cc dnsrecords.hh \ dnswriter.cc dnswriter.hh \ filterpo.cc filterpo.hh \ - lua-base4.cc lua-base4.hh \ iputils.cc iputils.hh \ logger.cc \ logging.cc \ + lua-base4.cc lua-base4.hh \ misc.cc \ nsecrecords.cc \ qtype.cc \ diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 5ff54beb9b..bf22554044 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -72,6 +72,7 @@ string g_pidfname; RecursorControlChannel g_rcc; // only active in the handler thread bool g_regressionTestMode; bool g_yamlSettings; +bool g_luaSettingsInYAML; #ifdef NOD_ENABLED bool g_nodEnabled; @@ -2081,19 +2082,20 @@ static int serviceMain(Logr::log_t log) } g_maxCacheEntries = ::arg().asNum("max-cache-entries"); - try { - ProxyMapping 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, - log->error(Logr::Error, e.reason, "Cannot load Lua configuration")); - return 1; - } + luaconfig(false); + // try { + // ProxyMapping 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, + // log->error(Logr::Error, e.reason, "Cannot load Lua configuration")); + // return 1; + // } parseACLs(); initPublicSuffixList(::arg()["public-suffix-list-file"]); @@ -2260,8 +2262,10 @@ static int serviceMain(Logr::log_t log) return ret; } - auto lci = g_luaconfs.getCopy(); - activateLuaConfig(lci); + { + auto lci = g_luaconfs.getCopy(); + startLuaConfigDelayedThreads(lci.rpzs, lci.generation); + } RecThreadInfo::makeThreadPipes(log); @@ -2973,6 +2977,8 @@ static pair doConfig(Logr::log_t startupLog, const string& configname return {0, false}; } +LockGuarded g_yamlStruct; + static void handleRuntimeDefaults(Logr::log_t log) { #ifdef HAVE_FIBER_SANITIZER @@ -3138,28 +3144,10 @@ int main(int argc, char** argv) ::arg().setSLog(startupLog); const string yamlconfigname = configname + ".yml"; - string msg; pdns::rust::settings::rec::Recursorsettings settings; - // TODO: handle include-dir on command line - auto yamlstatus = pdns::settings::rec::readYamlSettings(yamlconfigname, ::arg()["include-dir"], settings, msg, startupLog); - - switch (yamlstatus) { - case pdns::settings::rec::YamlSettingsStatus::CannotOpen: - SLOG(g_log << Logger::Debug << "No YAML config found for configname '" << yamlconfigname << "': " << msg << endl, - startupLog->error(Logr::Debug, msg, "No YAML config found", "configname", Logging::Loggable(yamlconfigname))); - break; - case pdns::settings::rec::YamlSettingsStatus::PresentButFailed: - SLOG(g_log << Logger::Error << "YAML config found for configname '" << yamlconfigname << "' but error ocurred processing it" << endl, - startupLog->error(Logr::Error, msg, "YAML config found, but error occurred processsing it", "configname", Logging::Loggable(yamlconfigname))); + auto yamlstatus = pdns::settings::rec::tryReadYAML(yamlconfigname, true, g_yamlSettings, g_luaSettingsInYAML, settings, startupLog); + if (yamlstatus == pdns::settings::rec::PresentButFailed) { return 1; - break; - case pdns::settings::rec::YamlSettingsStatus::OK: - g_yamlSettings = true; - SLOG(g_log << Logger::Notice << "YAML config found and processed for configname '" << yamlconfigname << "'" << endl, - startupLog->info(Logr::Notice, "YAML config found and processed", "configname", Logging::Loggable(yamlconfigname))); - pdns::settings::rec::processAPIDir(arg()["include-dir"], settings, startupLog); - pdns::settings::rec::bridgeStructToOldStyleSettings(settings); - break; } if (g_yamlSettings) { @@ -3169,7 +3157,10 @@ int main(int argc, char** argv) return ret; } } - + if (yamlstatus == pdns::settings::rec::YamlSettingsStatus::OK) { + auto lock = g_yamlStruct.lock(); + *lock = settings; + } if (yamlstatus == pdns::settings::rec::YamlSettingsStatus::CannotOpen) { configname += ".conf"; bool mustExit = false; @@ -3338,13 +3329,15 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q return res; } -static void startLuaConfigDelayedThreads(const vector& rpzs, uint64_t generation) +void startLuaConfigDelayedThreads(const vector& rpzs, uint64_t generation) { + cerr << "slcdt: " << rpzs.size() << endl; for (const auto& rpzPrimary : rpzs) { if (rpzPrimary.primaries.empty()) { continue; } try { + cerr << "STARTING" << endl; // 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); @@ -3373,7 +3366,7 @@ static void activateRPZFile(const RPZTrackerParams& params, LuaConfigItems& lci, 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")); + 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, @@ -3397,19 +3390,19 @@ static void activateRPZPrimary(RPZTrackerParams& params, LuaConfigItems& lci, sh 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(); } } + 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) @@ -3420,7 +3413,11 @@ static void activateRPZs(LuaConfigItems& lci) zone->reserve(params.zoneSizeHint); } if (!params.tags.empty()) { - zone->setTags(params.tags); + std::unordered_set tags; + for (const auto& tag : params.tags) { + tags.emplace(tag); + } + zone->setTags(tags); } zone->setPolicyOverridesGettag(params.defpolOverrideLocal); if (params.extendedErrorCode != std::numeric_limits::max()) { @@ -3435,7 +3432,7 @@ static void activateRPZs(LuaConfigItems& lci) if (params.primaries.empty()) { activateRPZFile(params, lci, zone); lci.dfe.addZone(std::move(zone)); - } + } else { DNSName domain(params.name); zone->setDomain(domain); @@ -3444,7 +3441,6 @@ static void activateRPZs(LuaConfigItems& lci) activateRPZPrimary(params, lci, zone, domain); } } - startLuaConfigDelayedThreads(lci.rpzs, lci.generation); } void activateLuaConfig(LuaConfigItems& lci) @@ -3454,11 +3450,11 @@ void activateLuaConfig(LuaConfigItems& lci) 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'!"); + 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'!"); + warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC, but dnssec is set to 'off'!"); } activateRPZs(lci); - g_luaconfs.setState(std::move(lci)); + g_luaconfs.setState(lci); } diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index fd51919d41..74168567a3 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -620,6 +620,8 @@ 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); +extern bool g_luaSettingsInYAML; +void startLuaConfigDelayedThreads(const vector& rpzs, uint64_t generation); 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" diff --git a/pdns/recursordist/rec_channel.hh b/pdns/recursordist/rec_channel.hh index 784539fb2f..f9977e5892 100644 --- a/pdns/recursordist/rec_channel.hh +++ b/pdns/recursordist/rec_channel.hh @@ -143,3 +143,4 @@ void doExitGeneric(bool nicely); void doExit(); void doExitNicely(); RecursorControlChannel::Answer doQueueReloadLuaScript(vector::const_iterator begin, vector::const_iterator end); +RecursorControlChannel::Answer luaconfig(bool broadcast); diff --git a/pdns/recursordist/rec_channel_rec.cc b/pdns/recursordist/rec_channel_rec.cc index fe95ee0558..dd45c5e5f8 100644 --- a/pdns/recursordist/rec_channel_rec.cc +++ b/pdns/recursordist/rec_channel_rec.cc @@ -2131,27 +2131,82 @@ static RecursorControlChannel::Answer help() "wipe-cache-typed type domain0 [domain1] .. wipe domain data with qtype from cache\n"}; } +RecursorControlChannel::Answer luaconfig(bool broadcast) +{ + ProxyMapping proxyMapping; + LuaConfigItems lci; + lci.d_slog = g_slog; + extern std::unique_ptr g_proxyMapping; + if (!g_luaSettingsInYAML) { + try { + loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci); + activateLuaConfig(lci); + lci = g_luaconfs.getCopy(); + if (broadcast) { + startLuaConfigDelayedThreads(lci.rpzs, lci.generation); + broadcastFunction([=] { return pleaseSupplantProxyMapping(proxyMapping); }); + } + else { + // Initial proxy mapping + g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique(proxyMapping); + } + SLOG(g_log << Logger::Notice << "Reloaded Lua configuration file '" << ::arg()["lua-config-file"] << "', requested via control channel" << endl, + g_slog->withName("config")->info(Logr::Info, "Reloaded")); + return {0, "Reloaded Lua configuration file '" + ::arg()["lua-config-file"] + "'\n"}; + } + catch (std::exception& e) { + return {1, "Unable to load Lua script from '" + ::arg()["lua-config-file"] + "': " + e.what() + "\n"}; + } + catch (const PDNSException& e) { + return {1, "Unable to load Lua script from '" + ::arg()["lua-config-file"] + "': " + e.reason + "\n"}; + } + } + try { + string configname = ::arg()["config-dir"] + "/recursor"; + if (!::arg()["config-name"].empty()) { + configname = ::arg()["config-dir"] + "/recursor-" + ::arg()["config-name"]; + } + bool dummy1{}; + bool dummy2{}; + pdns::rust::settings::rec::Recursorsettings settings; + auto yamlstat = pdns::settings::rec::tryReadYAML(configname + ".yml", false, dummy1, dummy2, settings, g_slog); + if (yamlstat != pdns::settings::rec::YamlSettingsStatus::OK) { + // HANDLE + } + auto generation = g_luaconfs.getLocal()->generation; + lci.generation = generation + 1; + pdns::settings::rec::fromBridgeStructToLuaConfig(settings, lci, proxyMapping); + activateLuaConfig(lci); + lci = g_luaconfs.getCopy(); + if (broadcast) { + startLuaConfigDelayedThreads(lci.rpzs, lci.generation); + broadcastFunction([=] { return pleaseSupplantProxyMapping(proxyMapping); }); + } + else { + // Initial proxy mapping + g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique(proxyMapping); + } + + return {0, "Reloaded dynamic part of YAML configuration\n"}; + } + catch (std::exception& e) { + return {1, "Unable to reload dynamic YAML changes: " + std::string(e.what()) + "\n"}; + } + catch (const PDNSException& e) { + return {1, "Unable to reload dynamic YAML changes: " + e.reason + "\n"}; + } +} + template static RecursorControlChannel::Answer luaconfig(T begin, T end) { if (begin != end) { + if (g_luaSettingsInYAML) { + return {1, "Unable to reload Lua script from '" + ::arg()["lua-config-file"] + " as there is not active Lua configuration\n"}; + } ::arg().set("lua-config-file") = *begin; } - try { - ProxyMapping proxyMapping; - 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"}; - } - catch (std::exception& e) { - return {1, "Unable to load Lua script from '" + ::arg()["lua-config-file"] + "': " + e.what() + "\n"}; - } - catch (const PDNSException& e) { - return {1, "Unable to load Lua script from '" + ::arg()["lua-config-file"] + "': " + e.reason + "\n"}; - } + return luaconfig(true); } static RecursorControlChannel::Answer reloadACLs() diff --git a/pdns/recursordist/rec_control.cc b/pdns/recursordist/rec_control.cc index 4ad16e440f..0561b5ac14 100644 --- a/pdns/recursordist/rec_control.cc +++ b/pdns/recursordist/rec_control.cc @@ -141,7 +141,7 @@ static std::string showLuaYAML(const ::rust::string rfile) msg += "\n# End of converted " + file + "\n#\n"; } catch (PDNSException& e) { - cerr << "Cannot load Lua configuration: " << e.reason << endl; + cerr << "Cannot load Lua configuration: " << e.reason << endl; } return msg; } diff --git a/pdns/recursordist/rpzloader.hh b/pdns/recursordist/rpzloader.hh index 3e94acde49..8b2252f14c 100644 --- a/pdns/recursordist/rpzloader.hh +++ b/pdns/recursordist/rpzloader.hh @@ -46,7 +46,7 @@ struct RPZTrackerParams std::string dumpZoneFileName; std::string polName; size_t zoneSizeHint{0}; - std::unordered_set tags; + std::set tags; uint32_t extendedErrorCode{std::numeric_limits::max()}; std::string extendedErrorExtra; bool includeSOA{false}; diff --git a/pdns/recursordist/settings/cxxsettings.hh b/pdns/recursordist/settings/cxxsettings.hh index d327820f5b..0d65b121de 100644 --- a/pdns/recursordist/settings/cxxsettings.hh +++ b/pdns/recursordist/settings/cxxsettings.hh @@ -54,4 +54,6 @@ void setArgsForZoneRelatedSettings(pdns::rust::settings::rec::Recursorsettings& void setArgsForACLRelatedSettings(pdns::rust::settings::rec::Recursorsettings& settings); 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); +bool luaItemSet(const pdns::rust::settings::rec::Recursorsettings& settings); +YamlSettingsStatus tryReadYAML(const string& yamlconfigname, bool setGlobals, bool& yamlSettings, bool& luaSettingsInYAML, rust::settings::rec::Recursorsettings& settings, Logr::log_t startupLog); } diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index 8a12eeffd3..feaeafa5d6 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -623,7 +623,7 @@ std::string pdns::settings::rec::defaultsToYaml() ::rust::String section; ::rust::String fieldname; ::rust::String type_name; - pdns::rust::settings::rec::Value rustvalue{false, 0, 0.0, "", {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}; + pdns::rust::settings::rec::Value rustvalue{}; string name = var; string val = arg().getDefault(var); if (pdns::settings::rec::oldKVToBridgeStruct(name, val, section, fieldname, type_name, rustvalue)) { @@ -633,7 +633,8 @@ std::string pdns::settings::rec::defaultsToYaml() // Should be generated auto def = [&](const string& section, const string& name, const string& type) { - pdns::rust::settings::rec::Value rustvalue{.vec_trustanchor_val = {}, .vec_negativetrustanchor_val = {}, .string_val = "", .u64_val = 24, .vec_protobufserver_val = {}}; + pdns::rust::settings::rec::Value rustvalue{}; + rustvalue.u64_val = 24; // XXX map.emplace(std::pair{std::pair{section, name}, pdns::rust::settings::rec::OldStyle{section, name, name, type, rustvalue, false}}); }; def("dnssec", "trustanchors", "Vec"); @@ -719,12 +720,14 @@ void fromLuaToRust(const LuaConfigItems& luaConfig, pdns::rust::settings::rec::D ::rust::Vec<::rust::String> dsRecords; for (const auto& dsRecord : anchors.second) { const auto dsString = dsRecord.getZoneRepresentation(); - if (std::find(rootDSs.begin(), rootDSs.end(), dsString) == rootDSs.end()) { + if (anchors.first != g_rootdnsname || std::find(rootDSs.begin(), rootDSs.end(), dsString) == rootDSs.end()) { dsRecords.emplace_back(dsRecord.getZoneRepresentation()); } } - pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords}; - dnssec.trustanchors.emplace_back(trustAnchor); + if (!dsRecords.empty()) { + pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords}; + dnssec.trustanchors.emplace_back(trustAnchor); + } } for (const auto& anchors : luaConfig.negAnchors) { pdns::rust::settings::rec::NegativeTrustAnchor negtrustAnchor{anchors.first.toString(), anchors.second}; @@ -757,7 +760,7 @@ void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec } dnstap.logQueries = fsc.logQueries; dnstap.logResponses = fsc.logQueries; - dnstap.bufferHint= fsc.bufferHint; + dnstap.bufferHint = fsc.bufferHint; dnstap.flushTimeout = fsc.flushTimeout; dnstap.inputQueueSize = fsc.inputQueueSize; dnstap.outputQueueSize = fsc.outputQueueSize; @@ -772,7 +775,7 @@ void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec } dnstap.logNODs = fsc.logNODs; dnstap.logUDRs = fsc.logUDRs; - dnstap.bufferHint= fsc.bufferHint; + dnstap.bufferHint = fsc.bufferHint; dnstap.flushTimeout = fsc.flushTimeout; dnstap.inputQueueSize = fsc.inputQueueSize; dnstap.outputQueueSize = fsc.outputQueueSize; @@ -789,8 +792,12 @@ void assign(pdns::rust::settings::rec::TSIGTriplet& var, const TSIGTriplet& tsig void assign(TSIGTriplet& var, const pdns::rust::settings::rec::TSIGTriplet& tsig) { - var.name = DNSName(std::string(tsig.name)); - var.algo = DNSName(std::string(tsig.algo)); + if (!tsig.name.empty()) { + var.name = DNSName(std::string(tsig.name)); + } + if (!tsig.algo.empty()) { + var.algo = DNSName(std::string(tsig.algo)); + } B64Decode(std::string(tsig.secret), var.secret); } @@ -810,23 +817,36 @@ std::string cvt(DNSFilterEngine::PolicyKind kind) case DNSFilterEngine::PolicyKind::Custom: return "Custom"; } + return "UnknownPolicyKind"; } void fromLuaToRust(const vector& rpzs, pdns::rust::settings::rec::Recursor& rec) { for (const auto& rpz : rpzs) { pdns::rust::settings::rec::RPZ rustrpz{ + .name = "", + .addresses = {}, + .defcontent = "", + .defpol = "", .defpolOverrideLocalData = true, .defttl = std::numeric_limits::max(), .extendedErrorCode = std::numeric_limits::max(), + .extendedErrorExtra = "", .includeSOA = false, .ignoreDuplicates = false, .maxTTL = std::numeric_limits::max(), + .policyName = "", + .tags = {}, .overridesGettag = true, .zoneSizeHint = 0, + .tsig = {}, .refresh = 0, .maxReceivedMBytes = 0, - .axfrTimeout = 20}; + .localAddress = "", + .axfrTimeout = 20, + .dumpFile = "", + .seedFile = "", + }; for (const auto& address : rpz.primaries) { rustrpz.addresses.emplace_back(address.toStringWithPort()); @@ -873,6 +893,7 @@ string cvt(pdns::ZoneMD::Config cfg) case pdns::ZoneMD::Config::Require: return "require"; } + return "UnknownZoneMDConfig"; } void fromLuaToRust(const map& ztcConfigs, pdns::rust::settings::rec::Recordcache& recordcache) @@ -916,17 +937,17 @@ std::string cvt(AdditionalMode mode) case AdditionalMode::ResolveDeferred: return "ResolveDeferred"; } + return "UnknownAdditionalMode"; } AdditionalMode cvtAdditional(const std::string& mode) { static const std::map map = { - { "Ignore", AdditionalMode::Ignore }, - { "CacheOnly", AdditionalMode::CacheOnly }, - { "CacheOnlyRequireAuth", AdditionalMode::CacheOnlyRequireAuth }, - { "ResolveImmediately", AdditionalMode::ResolveImmediately }, - { "ResolveDeferred", AdditionalMode::ResolveDeferred} - }; + {"Ignore", AdditionalMode::Ignore}, + {"CacheOnly", AdditionalMode::CacheOnly}, + {"CacheOnlyRequireAuth", AdditionalMode::CacheOnlyRequireAuth}, + {"ResolveImmediately", AdditionalMode::ResolveImmediately}, + {"ResolveDeferred", AdditionalMode::ResolveDeferred}}; if (auto iter = map.find(mode); iter != map.end()) { return iter->second; } @@ -936,9 +957,9 @@ AdditionalMode cvtAdditional(const std::string& mode) pdns::ZoneMD::Config cvtZoneMDConfig(const std::string& mode) { static const std::map map = { - { "ignore", pdns::ZoneMD::Config::Ignore }, - { "validate", pdns::ZoneMD::Config::Validate }, - { "require", pdns::ZoneMD::Config::Require }, + {"ignore", pdns::ZoneMD::Config::Ignore}, + {"validate", pdns::ZoneMD::Config::Validate}, + {"require", pdns::ZoneMD::Config::Require}, }; if (auto iter = map.find(mode); iter != map.end()) { return iter->second; @@ -1036,13 +1057,14 @@ void pdns::settings::rec::fromLuaConfigToBridgeStruct(LuaConfigItems& luaConfig, fromLuaToRust(proxyMapping, settings.incoming); } -namespace { +namespace +{ void fromRustToLuaConfig(const pdns::rust::settings::rec::Dnssec& dnssec, LuaConfigItems& luaConfig) { for (const auto& trustAnchor : dnssec.trustanchors) { // Do not inser the default root DS records if (trustAnchor.name == ".") { - for (const auto &dsRecord : trustAnchor.dsrecords) { + for (const auto& dsRecord : trustAnchor.dsrecords) { const std::string dsString = std::string(dsRecord); if (std::find(rootDSs.begin(), rootDSs.end(), dsString) == rootDSs.end()) { auto dsRecContent = std::dynamic_pointer_cast(DSRecordContent::make(dsString)); @@ -1051,7 +1073,7 @@ void fromRustToLuaConfig(const pdns::rust::settings::rec::Dnssec& dnssec, LuaCon } } else { - for (const auto &dsRecord : trustAnchor.dsrecords) { + for (const auto& dsRecord : trustAnchor.dsrecords) { auto dsRecContent = std::dynamic_pointer_cast(DSRecordContent::make(std::string(dsRecord))); luaConfig.dsAnchors[DNSName(std::string(trustAnchor.name))].emplace(*dsRecContent); } @@ -1119,20 +1141,18 @@ void fromRustToLuaConfig(const pdns::rust::settings::rec::DNSTapNODFrameStreamSe 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 } - }; + {"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) { @@ -1188,14 +1208,14 @@ void fromRustToLuaConfig(const rust::Vec& rpzs, } } - void fromRustToLuaConfig(const rust::Vec& ztcs, map& lua) +void fromRustToLuaConfig(const rust::Vec& ztcs, map& lua) { for (const auto& ztc : ztcs) { DNSName zone = DNSName(std::string(ztc.zone)); RecZoneToCache::Config lztc; for (const auto& source : ztc.sources) { lztc.d_sources.emplace_back(std::string(source)); - } + } lztc.d_zone = std::string(ztc.zone); lztc.d_method = std::string(ztc.method); if (!ztc.localAddress.empty()) { @@ -1280,3 +1300,62 @@ void pdns::settings::rec::fromBridgeStructToLuaConfig(const pdns::rust::settings fromRustToLuaConfig(settings.incoming.proxymappings, proxyMapping); } +// Return true if an item that's (also) a Lua config ite is set +bool pdns::settings::rec::luaItemSet(const pdns::rust::settings::rec::Recursorsettings& settings) +{ + bool alldefault = true; + alldefault = alldefault && settings.dnssec.trustanchors.empty(); + alldefault = alldefault && settings.dnssec.negative_trustanchors.empty(); + alldefault = alldefault && settings.dnssec.trustanchorfile.empty(); + alldefault = alldefault && settings.dnssec.trustanchorfile_interval == 24; + alldefault = alldefault && settings.logging.protobuf_mask_v4 == 32; + alldefault = alldefault && settings.logging.protobuf_mask_v6 == 128; + alldefault = alldefault && settings.logging.protobuf_servers.empty(); + alldefault = alldefault && settings.logging.outgoing_protobuf_servers.empty(); + alldefault = alldefault && settings.logging.dnstap_framestream_servers.empty(); + alldefault = alldefault && settings.logging.dnstap_nod_framestream_servers.empty(); + alldefault = alldefault && settings.recursor.sortlists.empty(); + alldefault = alldefault && settings.recursor.rpzs.empty(); + alldefault = alldefault && settings.recordcache.zonetocaches.empty(); + alldefault = alldefault && settings.recursor.allowed_additional_qtypes.empty(); + alldefault = alldefault && settings.incoming.proxymappings.empty(); + return !alldefault; +} + +pdns::settings::rec::YamlSettingsStatus pdns::settings::rec::tryReadYAML(const string& yamlconfigname, bool setGlobals, bool& yamlSettings, bool& luaSettingsInYAML, rust::settings::rec::Recursorsettings& settings, Logr::log_t startupLog) +{ + string msg; + // TODO: handle include-dir on command line + auto yamlstatus = pdns::settings::rec::readYamlSettings(yamlconfigname, ::arg()["include-dir"], settings, msg, startupLog); + + switch (yamlstatus) { + case pdns::settings::rec::YamlSettingsStatus::CannotOpen: + SLOG(g_log << Logger::Debug << "No YAML config found for configname '" << yamlconfigname << "': " << msg << endl, + startupLog->error(Logr::Debug, msg, "No YAML config found", "configname", Logging::Loggable(yamlconfigname))); + break; + + case pdns::settings::rec::YamlSettingsStatus::PresentButFailed: + SLOG(g_log << Logger::Error << "YAML config found for configname '" << yamlconfigname << "' but error ocurred processing it" << endl, + startupLog->error(Logr::Error, msg, "YAML config found, but error occurred processsing it", "configname", Logging::Loggable(yamlconfigname))); + break; + + case pdns::settings::rec::YamlSettingsStatus::OK: + yamlSettings = true; + SLOG(g_log << Logger::Notice << "YAML config found and processed for configname '" << yamlconfigname << "'" << endl, + startupLog->info(Logr::Notice, "YAML config found and processed", "configname", Logging::Loggable(yamlconfigname))); + pdns::settings::rec::processAPIDir(arg()["include-dir"], settings, startupLog); + luaSettingsInYAML = pdns::settings::rec::luaItemSet(settings); + cerr << "XXXX " << luaSettingsInYAML << ' ' << settings.recursor.lua_config_file.empty() << endl; + if (luaSettingsInYAML && !settings.recursor.lua_config_file.empty()) { + const std::string err = "YAML settings include values originally in Lua but also sets `recursor.lua_config_file`. This is unsupported"; + SLOG(g_log << Logger::Error << err << endl, + startupLog->info(Logr::Error, err, "configname", Logging::Loggable(yamlconfigname))); + yamlstatus = pdns::settings::rec::PresentButFailed; + } + else if (setGlobals) { + pdns::settings::rec::bridgeStructToOldStyleSettings(settings); + } + break; + } + return yamlstatus; +} diff --git a/pdns/recursordist/settings/rust/src/bridge.rs b/pdns/recursordist/settings/rust/src/bridge.rs index dfb5ed6922..fd8d04107e 100644 --- a/pdns/recursordist/settings/rust/src/bridge.rs +++ b/pdns/recursordist/settings/rust/src/bridge.rs @@ -323,6 +323,7 @@ impl ProtobufServer { seq2.push(serde_yaml::Value::String(entry.to_owned())); } insertseq(&mut map, "exportTypes", &seq2); + insertb(&mut map, "logMappedFrom", self.logMappedFrom); serde_yaml::Value::Mapping(map) } } diff --git a/pdns/recursordist/test-settings.cc b/pdns/recursordist/test-settings.cc index 2470fae8fb..6fbdde7ec8 100644 --- a/pdns/recursordist/test-settings.cc +++ b/pdns/recursordist/test-settings.cc @@ -965,9 +965,9 @@ recordcache: // Create YAML, given a Lua config auto newsettings = pdns::rust::settings::rec::parse_yaml_string(""); - //GlobalStateHolder gsluaConfig; - //gsluaConfig.setState(luaConfig); - //LuaConfigItems local; // = gsluaConfig.getCopy(); + // GlobalStateHolder gsluaConfig; + // gsluaConfig.setState(luaConfig); + // LuaConfigItems local; // = gsluaConfig.getCopy(); try { pdns::settings::rec::fromLuaConfigToBridgeStruct(luaConfig, proxyMapping, newsettings); } @@ -980,8 +980,12 @@ recordcache: std::ofstream aaa("a"); std::ofstream bbb("b"); - aaa << "===" << endl << yaml << endl << "===" << endl; - bbb << "===" << endl << newyaml << endl << "===" << endl; + aaa << "===" << endl + << yaml << endl + << "===" << endl; + bbb << "===" << endl + << newyaml << endl + << "===" << endl; BOOST_CHECK_EQUAL(yaml, std::string(newyaml)); } diff --git a/regression-tests.recursor-dnssec/test_Carbon.py b/regression-tests.recursor-dnssec/test_Carbon.py index 83a70d7acf..f9ed9450cd 100644 --- a/regression-tests.recursor-dnssec/test_Carbon.py +++ b/regression-tests.recursor-dnssec/test_Carbon.py @@ -68,10 +68,10 @@ class TestCarbon(RecursorTest): cls._carbonQueue1.put(lines, True, timeout=2.0) else: cls._carbonQueue2.put(lines, True, timeout=2.0) - if threading.currentThread().name in cls._carbonCounters: - cls._carbonCounters[threading.currentThread().name] += 1 + if threading.current_thread().name in cls._carbonCounters: + cls._carbonCounters[threading.current_thread().name] += 1 else: - cls._carbonCounters[threading.currentThread().name] = 1 + cls._carbonCounters[threading.current_thread().name] = 1 conn.close() sock.close() @@ -79,11 +79,11 @@ class TestCarbon(RecursorTest): @classmethod def startResponders(cls): cls._CarbonResponder1 = threading.Thread(name='Carbon Responder 1', target=cls.CarbonResponder, args=[cls._carbonServer1Port]) - cls._CarbonResponder1.setDaemon(True) + cls._CarbonResponder1.daemon = True cls._CarbonResponder1.start() cls._CarbonResponder2 = threading.Thread(name='Carbon Responder 2', target=cls.CarbonResponder, args=[cls._carbonServer2Port]) - cls._CarbonResponder2.setDaemon(True) + cls._CarbonResponder2.daemon = True cls._CarbonResponder2.start() def testCarbon(self): diff --git a/regression-tests.recursor-dnssec/test_ECS.py b/regression-tests.recursor-dnssec/test_ECS.py index d4e5e9d72b..29a75cf1e2 100644 --- a/regression-tests.recursor-dnssec/test_ECS.py +++ b/regression-tests.recursor-dnssec/test_ECS.py @@ -95,7 +95,7 @@ ecs-add-for=0.0.0.0/0 if not reactor.running: cls._UDPResponder = threading.Thread(name='UDP Responder', target=reactor.run, args=(False,)) - cls._UDPResponder.setDaemon(True) + cls._UDPResponder.daemon = True cls._UDPResponder.start() @classmethod diff --git a/regression-tests.recursor-dnssec/test_Protobuf.py b/regression-tests.recursor-dnssec/test_Protobuf.py index 953a9ce20e..4a5007488b 100644 --- a/regression-tests.recursor-dnssec/test_Protobuf.py +++ b/regression-tests.recursor-dnssec/test_Protobuf.py @@ -52,7 +52,7 @@ def ProtobufListener(queue, port): thread = threading.Thread(name='Connection Handler', target=ProtobufConnectionHandler, args=[queue, conn]) - thread.setDaemon(True) + thread.daemon = True thread.start() except socket.error as e: @@ -70,7 +70,7 @@ protobufServersParameters = [ProtobufServerParams(4243), ProtobufServerParams(42 protobufListeners = [] for param in protobufServersParameters: listener = threading.Thread(name='Protobuf Listener', target=ProtobufListener, args=[param.queue, param.port]) - listener.setDaemon(True) + listener.daemon = True listener.start() protobufListeners.append(listener) diff --git a/regression-tests.recursor-dnssec/test_RPZIncomplete.py b/regression-tests.recursor-dnssec/test_RPZIncomplete.py index b5a0e8a985..baeb2db053 100644 --- a/regression-tests.recursor-dnssec/test_RPZIncomplete.py +++ b/regression-tests.recursor-dnssec/test_RPZIncomplete.py @@ -17,7 +17,7 @@ class BadRPZServer(object): self._targetSerial = 1 self._serverPort = port listener = threading.Thread(name='RPZ Listener', target=self._listener, args=[]) - listener.setDaemon(True) + listener.daemon = True listener.start() def getCurrentSerial(self): @@ -117,7 +117,7 @@ class BadRPZServer(object): thread = threading.Thread(name='RPZ Connection Handler', target=self._connectionHandler, args=[conn]) - thread.setDaemon(True) + thread.daemon = True thread.start() except socket.error as e: diff --git a/regression-tests.recursor-dnssec/test_RecDnstap.py b/regression-tests.recursor-dnssec/test_RecDnstap.py index 5856a1bb00..b975483d7d 100644 --- a/regression-tests.recursor-dnssec/test_RecDnstap.py +++ b/regression-tests.recursor-dnssec/test_RecDnstap.py @@ -214,7 +214,7 @@ class TestRecursorDNSTap(RecursorTest): try: (conn, addr) = sock.accept() listener = threading.Thread(name='DNSTap Worker', target=cls.FrameStreamUnixListener, args=[conn, param]) - listener.setDaemon(True) + listener.daemon = True listener.start() except socket.error as e: if e.errno != errno.EBADF: @@ -233,7 +233,7 @@ class TestRecursorDNSTap(RecursorTest): cls.startResponders() listener = threading.Thread(name='DNSTap Listener', target=cls.FrameStreamUnixListenerMain, args=[DNSTapServerParameters]) - listener.setDaemon(True) + listener.daemon = True listener.start() confdir = os.path.join('configs', cls._confdir) -- 2.47.2