mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
[9.20] new: usr: implement rndc retransfer -force
A new optional argument '-force' has been added to the command channel command 'rndc retransfer'. When it is specified, named aborts the ongoing zone transfer (if there is one), and starts a new transfer. Closes #2299 Backport of MR !9102 Merge branch 'backport-2299-implement-rndc-force-retransfer-9.20' into 'bind-9.20' See merge request isc-projects/bind9!9219
This commit is contained in:
commit
008bfb6249
10 changed files with 152 additions and 16 deletions
|
|
@ -10763,13 +10763,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);
|
||||
}
|
||||
|
|
@ -10788,7 +10799,10 @@ named_server_retransfercommand(named_server_t *server, isc_lex_t *lex,
|
|||
(type == dns_zone_redirect &&
|
||||
dns_zone_getredirecttype(zone) == dns_zone_secondary))
|
||||
{
|
||||
dns_zone_forcereload(zone);
|
||||
if (force) {
|
||||
dns_zone_stopxfr(zone);
|
||||
}
|
||||
dns_zone_forcexfr(zone);
|
||||
} else {
|
||||
(void)putstr(text, "retransfer: inappropriate zone type: ");
|
||||
(void)putstr(text, dns_zonetype_name(type));
|
||||
|
|
|
|||
|
|
@ -444,14 +444,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
|
||||
|
||||
|
|
|
|||
15
bin/tests/system/xfer/ns1/axfr-rndc-retransfer-force.db
Normal file
15
bin/tests/system/xfer/ns1/axfr-rndc-retransfer-force.db
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 3600
|
||||
@ IN SOA . . 0 0 0 0 0
|
||||
@ IN NS .
|
||||
$GENERATE 1-5000 host$ TXT data-$
|
||||
|
|
@ -47,6 +47,7 @@ zone "edns-expire" {
|
|||
file "edns-expire.db";
|
||||
};
|
||||
|
||||
|
||||
zone "axfr-max-transfer-time" {
|
||||
type primary;
|
||||
file "axfr-max-transfer-time.db";
|
||||
|
|
@ -57,6 +58,11 @@ zone "axfr-max-idle-time" {
|
|||
file "axfr-max-idle-time.db";
|
||||
};
|
||||
|
||||
zone "axfr-rndc-retransfer-force" {
|
||||
type primary;
|
||||
file "axfr-rndc-retransfer-force.db";
|
||||
};
|
||||
|
||||
zone "axfr-too-big" {
|
||||
type primary;
|
||||
file "axfr-too-big.db";
|
||||
|
|
|
|||
|
|
@ -40,3 +40,8 @@ zone "axfr-max-transfer-time" {
|
|||
type primary;
|
||||
file "axfr-max-transfer-time.db";
|
||||
};
|
||||
|
||||
zone "axfr-rndc-retransfer-force" {
|
||||
type primary;
|
||||
file "axfr-rndc-retransfer-force.db";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ zone "axfr-max-idle-time" {
|
|||
file "axfr-max-idle-time.bk";
|
||||
};
|
||||
|
||||
zone "axfr-rndc-retransfer-force" {
|
||||
type secondary;
|
||||
primaries { 10.53.0.1; };
|
||||
file "axfr-rndc-retransfer-force.bk";
|
||||
};
|
||||
|
||||
zone "axfr-too-big" {
|
||||
type secondary;
|
||||
max-records 30;
|
||||
|
|
|
|||
|
|
@ -646,27 +646,50 @@ wait_for_message() (
|
|||
grep -F "$1" wait_for_message.$n >/dev/null
|
||||
)
|
||||
|
||||
nextpart ns6/named.run >/dev/null
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "test max-transfer-time-in with 1 second timeout ($n)"
|
||||
# Restart ns1 with -T transferslowly
|
||||
stop_server ns1
|
||||
copy_setports ns1/named2.conf.in ns1/named.conf
|
||||
start_server --noclean --restart --port ${PORT} ns1 -- "-D xfer-ns1 $NS_PARAMS -T transferinsecs -T transferslowly"
|
||||
sleep 1
|
||||
$RNDCCMD 10.53.0.6 retransfer axfr-max-transfer-time 2>&1 | sed 's/^/ns6 /' | cat_i
|
||||
|
||||
nextpart ns6/named.run >/dev/null
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "test rndc retransfer -force ($n)"
|
||||
tmp=0
|
||||
retry_quiet 10 wait_for_message "maximum transfer time exceeded: timed out" || tmp=1
|
||||
$RNDCCMD 10.53.0.6 retransfer axfr-rndc-retransfer-force 2>&1 | sed 's/^/ns6 /' | cat_i
|
||||
# Wait for at least one message
|
||||
msg="'axfr-rndc-retransfer-force/IN' from 10.53.0.1#${PORT}: received"
|
||||
retry_quiet 5 wait_for_message "$msg" || tmp=1
|
||||
# Issue a retransfer-force command which should cancel the ongoing transfer and start a new one
|
||||
$RNDCCMD 10.53.0.6 retransfer -force axfr-rndc-retransfer-force 2>&1 | sed 's/^/ns6 /' | cat_i
|
||||
msg="'axfr-rndc-retransfer-force/IN' from 10.53.0.1#${PORT}: Transfer status: operation canceled"
|
||||
retry_quiet 5 wait_for_message "$msg" || tmp=1
|
||||
# Wait for the new transfer to complete successfully
|
||||
msg="'axfr-rndc-retransfer-force/IN' from 10.53.0.1#${PORT}: Transfer status: success"
|
||||
retry_quiet 30 wait_for_message "$msg" || tmp=1
|
||||
if test $tmp != 0; then echo_i "failed"; fi
|
||||
status=$((status + tmp))
|
||||
|
||||
nextpart ns6/named.run >/dev/null
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "test max-transfer-idle-in with 50 seconds timeout ($n)"
|
||||
echo_i "test max-transfer-time-in with 1 second timeout ($n)"
|
||||
$RNDCCMD 10.53.0.6 retransfer axfr-max-transfer-time 2>&1 | sed 's/^/ns6 /' | cat_i
|
||||
tmp=0
|
||||
retry_quiet 10 wait_for_message "maximum transfer time exceeded: timed out" || tmp=1
|
||||
status=$((status + tmp))
|
||||
|
||||
# Restart ns1 with -T transferstuck
|
||||
stop_server ns1
|
||||
copy_setports ns1/named3.conf.in ns1/named.conf
|
||||
start_server --noclean --restart --port ${PORT} ns1 -- "-D xfer-ns1 $NS_PARAMS -T transferinsecs -T transferstuck"
|
||||
sleep 1
|
||||
|
||||
nextpart ns6/named.run >/dev/null
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "test max-transfer-idle-in with 50 seconds timeout ($n)"
|
||||
start=$(date +%s)
|
||||
$RNDCCMD 10.53.0.6 retransfer axfr-max-idle-time 2>&1 | sed 's/^/ns6 /' | cat_i
|
||||
tmp=0
|
||||
|
|
|
|||
|
|
@ -1998,9 +1998,18 @@ dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
|
|||
*/
|
||||
|
||||
void
|
||||
dns_zone_forcereload(dns_zone_t *zone);
|
||||
dns_zone_stopxfr(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Force a reload of specified zone.
|
||||
* If 'zone' has an ongoing active transfer, stop it.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be a valid zone.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_forcexfr(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Force a zone transfer of the specified zone.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be a valid zone.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/async.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/random.h>
|
||||
|
|
@ -1048,11 +1049,26 @@ dns_xfrin_gettsigkeyname(const dns_xfrin_t *xfr) {
|
|||
return (dst_key_name(xfr->tsigkey->key));
|
||||
}
|
||||
|
||||
static void
|
||||
xfrin_shutdown(void *arg) {
|
||||
dns_xfrin_t *xfr = arg;
|
||||
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
|
||||
dns_xfrin_detach(&xfr);
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_shutdown(dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
|
||||
if (xfr->loop != isc_loop()) {
|
||||
dns_xfrin_ref(xfr);
|
||||
isc_async_run(xfr->loop, xfrin_shutdown, xfr);
|
||||
} else {
|
||||
xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
|
||||
}
|
||||
}
|
||||
|
||||
#if DNS_XFRIN_TRACE
|
||||
|
|
@ -1110,7 +1126,10 @@ xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg) {
|
|||
{
|
||||
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
|
||||
isc_result_totext(result));
|
||||
if (atomic_load(&xfr->is_ixfr)) {
|
||||
if (atomic_load(&xfr->is_ixfr) &&
|
||||
result != ISC_R_CANCELED &&
|
||||
result != ISC_R_SHUTTINGDOWN)
|
||||
{
|
||||
/*
|
||||
* Pass special result code to force AXFR retry
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17795,6 +17795,21 @@ again:
|
|||
inc_stats(zone, dns_zonestatscounter_xfrfail);
|
||||
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, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
next_primary:
|
||||
/*
|
||||
|
|
@ -19458,7 +19473,29 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
|
|||
}
|
||||
|
||||
void
|
||||
dns_zone_forcereload(dns_zone_t *zone) {
|
||||
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_forcexfr(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
if (zone->type == dns_zone_primary ||
|
||||
|
|
|
|||
Loading…
Reference in a new issue