From f58f871b72e928c0aa26ba212b4d7e035077291f Mon Sep 17 00:00:00 2001 From: Charles-Henri Bruyand Date: Mon, 24 Apr 2023 16:13:35 +0200 Subject: [PATCH] ixfrdist: add a per domain max-soa-refresh option to optionaly cap the refresh interval --- docs/manpages/ixfrdist.yml.5.rst | 3 +++ pdns/ixfrdist.cc | 23 +++++++++++++++++++++-- pdns/ixfrdist.example.yml | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/manpages/ixfrdist.yml.5.rst b/docs/manpages/ixfrdist.yml.5.rst index 2770844328..387d451507 100644 --- a/docs/manpages/ixfrdist.yml.5.rst +++ b/docs/manpages/ixfrdist.yml.5.rst @@ -37,6 +37,7 @@ Example domains: - domain: example.com master: 192.0.2.18:5301 + max-soa-refresh: 1800 - domain: example.net master: 2001:DB8:ABCD::2 @@ -103,6 +104,8 @@ Options Mandatory. :master: IP address of the server to transfer this domain from. Mandatory. + :max-soa-refresh: Cap the refresh time to the given maximum (in seconds). + Optional. :webserver-address: IP address to listen on for the built-in webserver. diff --git a/pdns/ixfrdist.cc b/pdns/ixfrdist.cc index 9207a34624..6c1193f5fc 100644 --- a/pdns/ixfrdist.cc +++ b/pdns/ixfrdist.cc @@ -142,6 +142,7 @@ struct ixfrinfo_t { // Why a struct? This way we can add more options to a domain in the future struct ixfrdistdomain_t { set masters; // A set so we can do multiple master addresses in the future + uint32_t maxSOARefresh{0}; // Cap SOA refresh value to the given value in seconds }; // This contains the configuration for each domain @@ -337,8 +338,16 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint } auto& zoneLastCheck = lastCheck[domain]; - if ((current_soa != nullptr && now - zoneLastCheck < current_soa->d_st.refresh) || // Only check if we have waited `refresh` seconds - (current_soa == nullptr && now - zoneLastCheck < soaRetry)) { // Or if we could not get an update at all still, every 30 seconds + uint32_t refresh = soaRetry; // default if we don't get an update at all + if (current_soa != nullptr) { + // Check every `refresh` seconds as advertised in the SOA record + refresh = current_soa->d_st.refresh; + if (domainConfig.second.maxSOARefresh > 0) { + // Cap refresh value to the configured one if any + refresh = std::min(refresh, domainConfig.second.maxSOARefresh); + } + } + if (now - zoneLastCheck < refresh) { continue; } @@ -1111,6 +1120,13 @@ static bool parseAndCheckConfig(const string& configpath, YAML::Node& config) { g_log<()<<"' master address: "<(); + } catch (const runtime_error &e) { + g_log<()<<"': "< s; s.insert(domain["master"].as()); g_domainConfigs[domain["domain"].as()].masters = s; + if (domain["max-soa-refresh"]) { + g_domainConfigs[domain["domain"].as()].maxSOARefresh = domain["max-soa-refresh"].as(); + } g_stats.registerDomain(domain["domain"].as()); } diff --git a/pdns/ixfrdist.example.yml b/pdns/ixfrdist.example.yml index 976b7f23c6..08bf96bd69 100644 --- a/pdns/ixfrdist.example.yml +++ b/pdns/ixfrdist.example.yml @@ -98,9 +98,13 @@ webserver-loglevel: normal # When no port is specified, 53 is used. When specifying ports for IPv6, use the # "bracket" notation: # +# You can optionally cap the refresh time of the SOA using 'max-soa-refresh' (seconds) +# Otherwise, or if set to 0, the retreived SOA refresh time will be used +# # domains: # - domain: example.com # master: 192.0.2.15 +# max-soa-refresh: 180 # - domain: rpz.example # master: [2001:DB8:a34:543::53]:5353 # -- 2.47.2