From a93b6f20403dbcfc4711648f99db41bb0dc0fc71 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 ca136391ff..6122e23886 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 e5f1e0b536..72b24e15ac 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -859,8 +859,7 @@ xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) { (void)isc_timer_reset(xfr->max_idle_timer, isc_timertype_inactive, NULL, NULL, 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 (xfr->is_ixfr) {