chg: usr: 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.

Closes #4928

Merge branch 'fallback-ixfr-to-axfr-on-toomanyrecords' into 'main'

See merge request isc-projects/bind9!9333
This commit is contained in:
Nicki Křížek 2024-09-10 12:38:45 +00:00
commit b343484ddb
2 changed files with 40 additions and 2 deletions

View file

@ -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 <<EOF
/SOA/
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
/IXFR/
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
nil. 300 TXT "text 1"
nil. 300 TXT "text 2"
nil. 300 TXT "text 3"
nil. 300 TXT "text 4"
nil. 300 TXT "text 5"
nil. 300 TXT "text 6: causing too many records"
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
/AXFR/
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
nil. 300 NS ns.nil.
nil. 300 TXT "fallback AXFR on too many records"
/AXFR/
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
EOF
sleep 1
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
sleep 2
$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'AXFR on too many records' >/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

View file

@ -1125,8 +1125,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) &&