]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement rndc retransfer -force
authorAram Sargsyan <aram@isc.org>
Tue, 11 Jun 2024 10:55:18 +0000 (10:55 +0000)
committerAram Sargsyan <aram@isc.org>
Thu, 1 Aug 2024 10:43:47 +0000 (10:43 +0000)
With this new optional argument if there is an ongoing zone
transfer it will be aborted before a new zone transfer is scheduled.

bin/named/server.c
bin/rndc/rndc.rst
lib/dns/include/dns/zone.h
lib/dns/zone.c

index 3c5ba6d5e93db671226da1ce6e741b33929d397f..acba8704730000a6f3bfafe3038a11cc65eefd01 100644 (file)
@@ -10795,13 +10795,24 @@ isc_result_t
 named_server_retransfercommand(named_server_t *server, isc_lex_t *lex,
                               isc_buffer_t **text) {
        isc_result_t result;
+       const char *arg = NULL;
        dns_zone_t *zone = NULL;
        dns_zone_t *raw = NULL;
        dns_zonetype_t type;
+       bool force = false;
 
        REQUIRE(text != NULL);
 
-       result = zone_from_args(server, lex, NULL, &zone, NULL, text, true);
+       /* Skip the command name. */
+       (void)next_token(lex, text);
+
+       arg = next_token(lex, text);
+       if (arg != NULL && (strcmp(arg, "-force") == 0)) {
+               force = true;
+               arg = next_token(lex, text);
+       }
+
+       result = zone_from_args(server, lex, arg, &zone, NULL, text, false);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
@@ -10820,6 +10831,9 @@ named_server_retransfercommand(named_server_t *server, isc_lex_t *lex,
            (type == dns_zone_redirect &&
             dns_zone_getredirecttype(zone) == dns_zone_secondary))
        {
+               if (force) {
+                       dns_zone_stopxfr(zone);
+               }
                dns_zone_forcereload(zone);
        } else {
                (void)putstr(text, "retransfer: inappropriate zone type: ");
index 62603d1da8b16e46aca26e57c80c1be16fd199e8..531a56430e47cc29573a66e58e34a33cc5bf4109 100644 (file)
@@ -453,14 +453,16 @@ Currently supported commands are:
 
 .. program:: rndc
 
-.. option:: retransfer zone [class [view]]
+.. option:: retransfer [-force] zone [class [view]]
 
    This command retransfers the given secondary zone from the primary server.
 
    If the zone is configured to use ``inline-signing``, the signed
    version of the zone is discarded; after the retransfer of the
    unsigned version is complete, the signed version is regenerated
-   with new signatures.
+   with new signatures. With the optional ``-force`` argument provided
+   if there is an ongoing zone transfer it will be aborted before a new zone
+   transfer is scheduled.
 
 .. option:: scan
 
index 623edf162b79065700cecd9064b9405d1faae2ff..d6d9a0e6914672d7262ce4c7757988af7af7263e 100644 (file)
@@ -1997,6 +1997,15 @@ dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t       *zmgr,
  *\li  'tlsctx_cache' is a valid TLS context cache.
  */
 
+void
+dns_zone_stopxfr(dns_zone_t *zone);
+/*%<
+ *      If 'zone' has an ongoing active transfer, stop it.
+ *
+ * Requires:
+ *\li      'zone' to be a valid zone.
+ */
+
 void
 dns_zone_forcereload(dns_zone_t *zone);
 /*%<
index 24c63aa720c29f3a48707860df4482dff023b4d3..037040054800f992759a77a6c769bcc9a743b002 100644 (file)
@@ -17796,8 +17796,18 @@ again:
                break;
 
        case ISC_R_CANCELED:
+               /*
+                * A new "retransfer" command with a "-force" argument could
+                * have canceled the current transfer in which case we should
+                * make sure to try again from the beginning.
+                */
+               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
+                       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
+                       again = true;
+               }
+               FALLTHROUGH;
        case ISC_R_SHUTTINGDOWN:
-               dns_remote_reset(&zone->primaries, false);
+               dns_remote_reset(&zone->primaries, true);
                break;
 
        default:
@@ -19462,6 +19472,28 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
        RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
 }
 
+void
+dns_zone_stopxfr(dns_zone_t *zone) {
+       dns_xfrin_t *xfr = NULL;
+
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+       LOCK_ZONE(zone);
+       if (zone->statelist == &zone->zmgr->xfrin_in_progress &&
+           zone->xfr != NULL)
+       {
+               dns_xfrin_attach(zone->xfr, &xfr);
+       }
+       UNLOCK_ZONE(zone);
+       RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+
+       if (xfr != NULL) {
+               dns_xfrin_shutdown(xfr);
+               dns_xfrin_detach(&xfr);
+       }
+}
+
 void
 dns_zone_forcereload(dns_zone_t *zone) {
        REQUIRE(DNS_ZONE_VALID(zone));