]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
ixfrdist: add a per domain max-soa-refresh option to optionaly cap the refresh interval 12768/head
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Mon, 24 Apr 2023 14:13:35 +0000 (16:13 +0200)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Mon, 24 Apr 2023 14:13:35 +0000 (16:13 +0200)
docs/manpages/ixfrdist.yml.5.rst
pdns/ixfrdist.cc
pdns/ixfrdist.example.yml

index 277084432837974381cfab2c9404fdf6cf686df9..387d4515076ad054322aa97f8dfc2b7d0fc2b9a7 100644 (file)
@@ -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.
index 9207a346242aa1816761dc581ad7c2639388ad50..6c1193f5fca7601635f686f6b15868b5662bad00 100644 (file)
@@ -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<ComboAddress> 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<<Logger::Error<<"Unable to read domain '"<<domain["domain"].as<string>()<<"' master address: "<<e.what()<<endl;
         retval = false;
       }
+      if (domain["max-soa-refresh"]) {
+        try {
+          config["max-soa-refresh"].as<uint32_t>();
+        } catch (const runtime_error &e) {
+          g_log<<Logger::Error<<"Unable to read 'max-soa-refresh' value for domain '"<<domain["domain"].as<string>()<<"': "<<e.what()<<endl;
+        }
+      }
     }
   } else {
     g_log<<Logger::Error<<"No domains configured"<<endl;
@@ -1223,6 +1239,9 @@ int main(int argc, char** argv) {
     set<ComboAddress> s;
     s.insert(domain["master"].as<ComboAddress>());
     g_domainConfigs[domain["domain"].as<DNSName>()].masters = s;
+    if (domain["max-soa-refresh"]) {
+      g_domainConfigs[domain["domain"].as<DNSName>()].maxSOARefresh = domain["max-soa-refresh"].as<uint32_t>();
+    }
     g_stats.registerDomain(domain["domain"].as<DNSName>());
   }
 
index 976b7f23c6224762d428575ca972eefda90468f5..08bf96bd698fd7c99ee495b96ce9f0e7c1cde9b4 100644 (file)
@@ -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
 #