From: Otto Moerbeek Date: Wed, 6 Nov 2024 08:46:56 +0000 (+0100) Subject: rec: be able to specify names for primaries for catalog zones and RPZs X-Git-Tag: rec-5.2.0-beta1~19^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f4724f93734001d372737d2001ecdb6b6fcae79d;p=thirdparty%2Fpdns.git rec: be able to specify names for primaries for catalog zones and RPZs --- diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 482879ea2e..6607b95cb8 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -548,9 +548,11 @@ rec_control_SOURCES = \ qtype.cc \ rcpgenerator.cc rcpgenerator.hh \ rec-lua-conf.cc rec-lua-conf.hh \ + rec-system-resolve.cc rec-system-resolve.hh \ rec_channel.cc rec_channel.hh \ rec_control.cc \ settings/cxxsupport.cc \ + threadname.cc threadname.hh \ sillyrecords.cc \ sortlist.cc sortlist.hh \ svc-records.cc svc-records.hh \ diff --git a/pdns/recursordist/rec-lua-conf.cc b/pdns/recursordist/rec-lua-conf.cc index e398909e75..d25c528f66 100644 --- a/pdns/recursordist/rec-lua-conf.cc +++ b/pdns/recursordist/rec-lua-conf.cc @@ -16,6 +16,7 @@ #include "validate.hh" #include "validate-recursor.hh" #include "root-dnssec.hh" +#include "rec-system-resolve.hh" GlobalStateHolder g_luaconfs; @@ -278,11 +279,11 @@ static void rpzPrimary(LuaConfigItems& lci, const boost::variant zone = std::make_shared(); if (primaries_.type() == typeid(string)) { - params.zoneXFRParams.primaries.emplace_back(boost::get(primaries_), 53); + params.zoneXFRParams.primaries.emplace_back(boost::get(primaries_)); } else { for (const auto& primary : boost::get>>(primaries_)) { - params.zoneXFRParams.primaries.emplace_back(primary.second, 53); + params.zoneXFRParams.primaries.emplace_back(primary.second); } } @@ -329,7 +330,8 @@ static void rpzPrimary(LuaConfigItems& lci, const boost::variant(str.substr(pos + 1)); + } + auto& res = pdns::RecResolve::getInstance(); + ComboAddress address = res.lookupAndRegister(str.substr(0, pos), time(nullptr)); + if (address != ComboAddress()) { + address.setPort(port); + return address; + } + log->error(Logr::Error, "Could not resolve name", "name", Logging::Loggable(str)); + throw PDNSException("Could not resolve " + str); + } +} diff --git a/pdns/recursordist/rec-system-resolve.hh b/pdns/recursordist/rec-system-resolve.hh index b3e199a46b..3491598b71 100644 --- a/pdns/recursordist/rec-system-resolve.hh +++ b/pdns/recursordist/rec-system-resolve.hh @@ -31,6 +31,7 @@ #include "namespaces.hh" #include "iputils.hh" #include "lock.hh" +#include "logr.hh" /************************************************************************************************ The pdns::RecResolve class implements a facility to use the system configured resolver. At the moment @@ -146,4 +147,5 @@ private: static bool s_selfResolveCheck; }; + ComboAddress fromNameOrIP(const string& str, uint16_t defPort, Logr::log_t log); } diff --git a/pdns/recursordist/rec-xfr.cc b/pdns/recursordist/rec-xfr.cc index 097a1930af..6a5ecfbf7b 100644 --- a/pdns/recursordist/rec-xfr.cc +++ b/pdns/recursordist/rec-xfr.cc @@ -29,6 +29,7 @@ #include "axfr-retriever.hh" #include "ixfr.hh" #include "dnsrecords.hh" +#include "rec-system-resolve.hh" static const DNSName cZones("zones"); static const DNSName cVersion("version"); @@ -85,6 +86,7 @@ void CatalogZone::registerForwarders(const FWCatalogZone& params, Logr::log_t lo if (const auto ptr = getRR(record.second)) { auto defsIter = params.d_defaults.find(""); const auto& name = record.first.first; + const auto& target = ptr->getContent(); auto groupKey = name; groupKey.prependRawLabel("group"); // Look for group records matching the member @@ -95,19 +97,18 @@ void CatalogZone::registerForwarders(const FWCatalogZone& params, Logr::log_t lo groupName = unquotify(groupName); auto iter = params.d_defaults.find(groupName); if (iter == params.d_defaults.end()) { - logger->info(Logr::Debug, "No match for group in YAML config", "name", Logging::Loggable(name), "groupName", Logging::Loggable(groupName)); + logger->info(Logr::Error, "No match for group in YAML config", "name", Logging::Loggable(name), "groupName", Logging::Loggable(groupName), "target", Logging::Loggable(target)); continue; } - logger->info(Logr::Debug, "Match for group in YAML config", "name", Logging::Loggable(name), "groupName", Logging::Loggable(groupName)); + logger->info(Logr::Debug, "Match for group in YAML config", "name", Logging::Loggable(name), "groupName", Logging::Loggable(groupName), "target", Logging::Loggable(target)); defsIter = iter; break; } } if (defsIter == params.d_defaults.end()) { - logger->info(Logr::Error, "No match for group in YAML config", "name", Logging::Loggable(name)); + logger->info(Logr::Error, "No match for default group in YAML config", "name", Logging::Loggable(name), "target", Logging::Loggable(target)); continue; } - auto target = ptr->getContent(); pdns::rust::settings::rec::ForwardZone forward; forward.zone = target.toString(); forward.recurse = defsIter->second.recurse; @@ -236,8 +237,9 @@ void FWCatZoneXFR::preloadZoneFile(const DNSName& zoneName, const std::shared_pt /* full copy, as promised */ auto newZone = std::make_shared(*oldZone); - for (const auto& primary : d_params.primaries) { + for (const auto& nameOrIp : d_params.primaries) { try { + auto primary = pdns::fromNameOrIP(nameOrIp, 53, logger); d_params.soaRecordContent = loadZoneFromServer(logger, primary, zoneName, newZone, d_params.tsigtriplet, d_params.maxReceivedMBytes, d_params.localAddress, d_params.xfrTimeout); newZone->setSerial(d_params.soaRecordContent->d_st.serial); newZone->setRefresh(d_params.soaRecordContent->d_st.refresh); @@ -254,11 +256,11 @@ void FWCatZoneXFR::preloadZoneFile(const DNSName& zoneName, const std::shared_pt break; } catch (const std::exception& e) { - logger->error(Logr::Warning, e.what(), "Unable to load zone, will retry", "from", Logging::Loggable(primary), "exception", Logging::Loggable("std::exception"), "refresh", Logging::Loggable(refresh)); + logger->error(Logr::Warning, e.what(), "Unable to load zone, will retry", "from", Logging::Loggable(nameOrIp), "exception", Logging::Loggable("std::exception"), "refresh", Logging::Loggable(refresh)); // XXX Stats } catch (const PDNSException& e) { - logger->error(Logr::Warning, e.reason, "Unable to load zone, will retry", "from", Logging::Loggable(primary), "exception", Logging::Loggable("PDNSException"), "refresh", Logging::Loggable(refresh)); + logger->error(Logr::Warning, e.reason, "Unable to load zone, will retry", "from", Logging::Loggable(nameOrIp), "exception", Logging::Loggable("PDNSException"), "refresh", Logging::Loggable(refresh)); // XXX Stats } } @@ -318,7 +320,8 @@ bool FWCatZoneXFR::zoneTrackerIteration(const DNSName& zoneName, std::shared_ptr } vector, vector>> deltas; - for (const auto& primary : d_params.primaries) { + for (const auto& nameOrIp : d_params.primaries) { + auto primary = pdns::fromNameOrIP(nameOrIp, 53, logger); auto soa = getRR(soaRecord); auto serial = soa ? soa->d_st.serial : 0; logger->info(Logr::Info, "Getting IXFR deltas", "address", Logging::Loggable(primary), "ourserial", Logging::Loggable(serial)); diff --git a/pdns/recursordist/rec-xfr.hh b/pdns/recursordist/rec-xfr.hh index 541255c7ec..769053d3a5 100644 --- a/pdns/recursordist/rec-xfr.hh +++ b/pdns/recursordist/rec-xfr.hh @@ -42,7 +42,7 @@ struct FWCatalogZone; struct ZoneXFRParams { std::string name; - std::vector primaries; + std::vector primaries; ComboAddress localAddress; std::shared_ptr soaRecordContent; TSIGTriplet tsigtriplet; diff --git a/pdns/recursordist/reczones.cc b/pdns/recursordist/reczones.cc index 7831b1afd6..ae48402db4 100644 --- a/pdns/recursordist/reczones.cc +++ b/pdns/recursordist/reczones.cc @@ -65,29 +65,6 @@ bool primeHints(time_t now) return ret; } -static ComboAddress fromNameOrIP(const string& str, uint16_t defPort, Logr::log_t log) -{ - try { - ComboAddress addr = parseIPAndPort(str, defPort); - return addr; - } - catch (const PDNSException&) { - uint16_t port = defPort; - string::size_type pos = str.rfind(':'); - if (pos != string::npos) { - port = pdns::checked_stoi(str.substr(pos + 1)); - } - auto& res = pdns::RecResolve::getInstance(); - ComboAddress address = res.lookupAndRegister(str.substr(0, pos), time(nullptr)); - if (address != ComboAddress()) { - address.setPort(port); - return address; - } - log->error(Logr::Error, "Could not resolve name", "name", Logging::Loggable(str)); - throw PDNSException("Could not resolve " + str); - } -} - static void convertServersForAD(const std::string& zone, const std::string& input, SyncRes::AuthDomain& authDomain, const char* sepa, Logr::log_t log, bool verbose = true) { vector servers; @@ -96,7 +73,7 @@ static void convertServersForAD(const std::string& zone, const std::string& inpu vector addresses; for (auto& server : servers) { - ComboAddress addr = fromNameOrIP(server, 53, log); + ComboAddress addr = pdns::fromNameOrIP(server, 53, log); authDomain.d_servers.push_back(addr); if (verbose) { addresses.push_back(addr.toStringWithPort()); @@ -340,7 +317,7 @@ static void processApiZonesFile(const string& file, shared_ptr& newMap, sh authDomain.d_name = DNSName(string(forward.zone)); authDomain.d_rdForward = forward.recurse; for (const auto& forwarder : forward.forwarders) { - ComboAddress addr = parseIPAndPort(string(forwarder), 53); + ComboAddress addr = pdns::fromNameOrIP(string(forwarder), 53, log); authDomain.d_servers.emplace_back(addr); } (*newMap)[authDomain.d_name] = authDomain; diff --git a/pdns/recursordist/rpzloader.cc b/pdns/recursordist/rpzloader.cc index db554df57f..09792e92ee 100644 --- a/pdns/recursordist/rpzloader.cc +++ b/pdns/recursordist/rpzloader.cc @@ -32,6 +32,7 @@ #include "zoneparser-tng.hh" #include "threadname.hh" #include "query-local-address.hh" +#include "rec-system-resolve.hh" Netmask makeNetmaskFromRPZ(const DNSName& name) { @@ -443,7 +444,8 @@ static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, st std::shared_ptr newZone = std::make_shared(*oldZone); for (const auto& primary : params.zoneXFRParams.primaries) { try { - params.zoneXFRParams.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.zoneXFRParams.tsigtriplet, params.zoneXFRParams.maxReceivedMBytes, params.zoneXFRParams.localAddress, params.zoneXFRParams.xfrTimeout); + auto combo = pdns::fromNameOrIP(primary, 53, logger); + params.zoneXFRParams.soaRecordContent = loadRPZFromServer(logger, combo, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.zoneXFRParams.tsigtriplet, params.zoneXFRParams.maxReceivedMBytes, params.zoneXFRParams.localAddress, params.zoneXFRParams.xfrTimeout); newZone->setSerial(params.zoneXFRParams.soaRecordContent->d_st.serial); newZone->setRefresh(params.zoneXFRParams.soaRecordContent->d_st.refresh); refresh = std::max(params.zoneXFRParams.refreshFromConf != 0 ? params.zoneXFRParams.refreshFromConf : newZone->getRefresh(), 1U); @@ -528,7 +530,8 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam } vector, vector>> deltas; - for (const auto& primary : params.zoneXFRParams.primaries) { + for (const auto& ipOrName : params.zoneXFRParams.primaries) { + auto primary = pdns::fromNameOrIP(ipOrName, 53, logger); auto soa = getRR(dnsRecord); auto serial = soa ? soa->d_st.serial : 0; SLOG(g_log << Logger::Info << "Getting IXFR deltas for " << zoneName << " from " << primary.toStringWithPort() << ", our serial: " << serial << endl, diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index f27b3e9f0b..4c4fd13c1a 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -879,7 +879,7 @@ void fromLuaToRust(const vector& rpzs, pdns::rust::settings::r }; for (const auto& address : rpz.zoneXFRParams.primaries) { - rustrpz.addresses.emplace_back(address.toStringWithPort()); + rustrpz.addresses.emplace_back(address); } rustrpz.name = rpz.zoneXFRParams.name; rustrpz.defcontent = rpz.defcontent; @@ -1188,8 +1188,7 @@ void fromRustToLuaConfig(const rust::Vec& rpzs, for (const auto& rpz : rpzs) { RPZTrackerParams params; for (const auto& address : rpz.addresses) { - ComboAddress combo = ComboAddress(std::string(address), 53); - params.zoneXFRParams.primaries.emplace_back(combo.toStringWithPort()); + params.zoneXFRParams.primaries.emplace_back(address); } params.zoneXFRParams.name = std::string(rpz.name); params.polName = std::string(rpz.policyName); @@ -1316,8 +1315,7 @@ void fromRustToLuaConfig(const rust::Vec(); for (const auto& address : catz.xfr.addresses) { - ComboAddress combo = ComboAddress(std::string(address), 53); - fwcatz.d_params.primaries.emplace_back(combo.toStringWithPort()); + fwcatz.d_params.primaries.emplace_back(address); } fwcatz.d_params.name = std::string(catz.zone); fwcatz.d_params.zoneSizeHint = catz.xfr.zoneSizeHint; diff --git a/pdns/recursordist/settings/rust/src/bridge.rs b/pdns/recursordist/settings/rust/src/bridge.rs index e076410979..05872b9bea 100644 --- a/pdns/recursordist/settings/rust/src/bridge.rs +++ b/pdns/recursordist/settings/rust/src/bridge.rs @@ -186,7 +186,7 @@ fn validate_address_family(addrfield: &str, localfield: &str, vec: &[String], lo let msg = format!("{}: cannot be empty", addrfield); return Err(ValidationError { msg }); } - validate_vec(addrfield, vec, validate_socket_address)?; + validate_vec(addrfield, vec, validate_socket_address_or_name)?; if local_address.is_empty() { return Ok(()); } @@ -200,7 +200,11 @@ fn validate_address_family(addrfield: &str, localfield: &str, vec: &[String], lo let mut wrong = false; let sa = SocketAddr::from_str(addr_str); if sa.is_err() { - let ip = IpAddr::from_str(addr_str).unwrap(); + let ip = IpAddr::from_str(addr_str); + if ip.is_err() { // It is likely a name + continue; + } + let ip = ip.unwrap(); if local.is_ipv4() != ip.is_ipv4() || local.is_ipv6() != ip.is_ipv6() { wrong = true; } @@ -656,7 +660,11 @@ impl TSIGTriplet { } impl ForwardingCatalogZone { - pub fn validate(&self, _field: &str) -> Result<(), ValidationError> { + pub fn validate(&self, field: &str) -> Result<(), ValidationError> { + self.xfr.tsig.validate(&(field.to_owned() + ".xfr.tsig"))?; + if !self.xfr.addresses.is_empty() { + validate_address_family(&(field.to_owned() + ".xfr.addresses"), &(field.to_owned() + ".xfr.localAddress"), &self.xfr.addresses, &self.xfr.localAddress)?; + } Ok(()) }