From: Aram Sargsyan Date: Tue, 11 Jun 2024 10:55:18 +0000 (+0000) Subject: Implement rndc retransfer -force X-Git-Tag: alessio/regression/026024a6ae~12^2~3 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=402ca316ae3bd285889ecd7ac4005ada295ba421;p=thirdparty%2Fbind9.git Implement rndc retransfer -force With this new optional argument if there is an ongoing zone transfer it will be aborted before a new zone transfer is scheduled. --- diff --git a/bin/named/server.c b/bin/named/server.c index 3c5ba6d5e93..acba8704730 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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: "); diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst index 62603d1da8b..531a56430e4 100644 --- a/bin/rndc/rndc.rst +++ b/bin/rndc/rndc.rst @@ -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 diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 623edf162b7..d6d9a0e6914 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -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); /*%< diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 24c63aa720c..03704005480 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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));