From 33dd3fbca2c4f73e81a3e4171965562d063072e5 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Fri, 16 Aug 2024 16:53:38 +0900 Subject: [PATCH] allow IXFR-to-AXFR fallback on DNS_R_TOOMANYRECORDS This change allows fallback from an IXFR failure to AXFR when the reason is DNS_R_TOOMANYRECORDS. This is because this error condition could be temporary only in an intermediate version of IXFR transactions and it's possible that the latest version of the zone doesn't have that condition. In such a case, the secondary would never be able to update the zone (even if it could) without this fallback. This fallback behavior is particularly useful with the recently introduced max-records-per-type and max-types-per-name options: the primary may not have these limitations and may temporarily introduce "too many" records, breaking IXFR. If the primary side subsequently deletes these records, this fallback will help recover the zone transfer failure automatically; without it, the secondary side would first need to increase the limit, which requires more operational overhead and has its own adverse effect. This change also fixes a minor glitch that DNS_R_TOOMANYRECORDS wasn't logged in xfrin_fail. (cherry picked from commit 7289090683b07d5c9e9843fb68fe626f8552c664) --- bin/tests/system/ixfr/tests.sh | 39 ++++++++++++++++++++++++++++++++++ lib/dns/xfrin.c | 3 +-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/bin/tests/system/ixfr/tests.sh b/bin/tests/system/ixfr/tests.sh index 2b9e085cd5..97014200f2 100644 --- a/bin/tests/system/ixfr/tests.sh +++ b/bin/tests/system/ixfr/tests.sh @@ -65,6 +65,7 @@ zone "nil" { type secondary; file "myftp.db"; primaries { 10.53.0.2; }; + max-records-per-type 5; # use a small value for fallback test }; EOF @@ -144,6 +145,44 @@ $DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'fallback AXFR' >/dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) +n=$((n + 1)) +echo_i "testing AXFR fallback after IXFR failure (too many records) ($n)" +ret=0 + +# Provide an IXFR response that would cause a "too many records" condition + +sendcmd </dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + n=$((n + 1)) echo_i "testing AXFR fallback after IXFR failure (bad SOA owner) ($n)" ret=0 diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index b0cf39458b..723e15b4e6 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1119,8 +1119,7 @@ xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg) { if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false }, true)) { - if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) - { + if (result != DNS_R_UPTODATE) { xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg, isc_result_totext(result)); if (atomic_load(&xfr->is_ixfr) &&