diff --git a/bin/named/config.c b/bin/named/config.c index fbf29cf7a8..85bad35716 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -79,6 +79,7 @@ options {\n\ listen-on-v6 {any;};\n\ # lock-file \"" NAMED_LOCALSTATEDIR "/run/named/named.lock\";\n\ match-mapped-addresses no;\n\ + max-ixfr-ratio 100%;\n\ max-rsa-exponent-size 0; /* no limit */\n\ max-udp-size 4096;\n\ memstatistics-file \"named.memstats\";\n\ diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 30ec0c430f..7d2c1fb208 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -1400,6 +1400,15 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, ixfrdiff); } + obj = NULL; + result = named_config_get(maps, "max-ixfr-ratio", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isstring(obj)) { + dns_zone_setixfrratio(zone, 0); + } else { + dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj)); + } + obj = NULL; result = named_config_get(maps, "request-expire", &obj); INSIST(result == ISC_R_SUCCESS); diff --git a/bin/tests/system/checkconf/bad-maxratio1.conf b/bin/tests/system/checkconf/bad-maxratio1.conf new file mode 100644 index 0000000000..f0d06be669 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxratio1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type master; + masterfile-format map; + file "example.db"; + max-ixfr-ratio 0.9; +}; diff --git a/bin/tests/system/checkconf/bad-maxratio2.conf b/bin/tests/system/checkconf/bad-maxratio2.conf new file mode 100644 index 0000000000..902c334423 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxratio2.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type master; + masterfile-format map; + file "example.db"; + max-ixfr-ratio 0%; +}; diff --git a/bin/tests/system/checkconf/good-maxratio1.conf b/bin/tests/system/checkconf/good-maxratio1.conf new file mode 100644 index 0000000000..80ff113f21 --- /dev/null +++ b/bin/tests/system/checkconf/good-maxratio1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type master; + masterfile-format map; + file "example.db"; + max-ixfr-ratio 50%; +}; diff --git a/bin/tests/system/checkconf/good-maxratio2.conf b/bin/tests/system/checkconf/good-maxratio2.conf new file mode 100644 index 0000000000..e057dfe6e1 --- /dev/null +++ b/bin/tests/system/checkconf/good-maxratio2.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type master; + masterfile-format map; + file "example.db"; + max-ixfr-ratio unlimited; +}; diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf index 2eb2850f10..f2dae97362 100644 --- a/bin/tests/system/checkconf/good.conf +++ b/bin/tests/system/checkconf/good.conf @@ -79,6 +79,7 @@ options { "corp"; }; dnssec-policy "test"; + max-ixfr-ratio 90%; transfer-source 0.0.0.0 dscp 63; zone-statistics none; }; @@ -90,11 +91,13 @@ view "first" { type master; file "xxx"; update-policy local; + max-ixfr-ratio 20%; notify-source 10.10.10.10 port 53 dscp 55; }; zone "clone" { type master; file "yyy"; + max-ixfr-ratio unlimited; }; dnssec-validation auto; zone-statistics terse; diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index 07fc06cd1f..ba8b314cb6 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -511,9 +511,16 @@ awk 'BEGIN { ok = 0; } /cut here/ { ok = 1; getline } ok == 1 { print }' good-ka [ -s good-kasp.conf.in ] || ret=1 $CHECKCONF -p good-kasp.conf.in | grep -v '^good-kasp.conf.in:' > good-kasp.conf.out 2>&1 || ret=1 cmp good-kasp.conf.in good-kasp.conf.out || ret=1 - if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo_i "check that max-ixfr-ratio 100% generates a warning ($n)" +ret=0 +$CHECKCONF warn-maxratio1.conf > checkconf.out$n 2>/dev/null || ret=1 +grep "exceeds 100%" < checkconf.out$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi +status=`expr $status + $ret` + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/checkconf/warn-maxratio1.conf b/bin/tests/system/checkconf/warn-maxratio1.conf new file mode 100644 index 0000000000..519dcc484c --- /dev/null +++ b/bin/tests/system/checkconf/warn-maxratio1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type master; + masterfile-format map; + file "example.db"; + max-ixfr-ratio 101%; +}; diff --git a/bin/tests/system/ixfr/ns4/named.conf.in b/bin/tests/system/ixfr/ns4/named.conf.in index d3490b18e4..086211684a 100644 --- a/bin/tests/system/ixfr/ns4/named.conf.in +++ b/bin/tests/system/ixfr/ns4/named.conf.in @@ -37,6 +37,7 @@ view "primary" { type slave; file "mytest.db"; masters { 10.53.0.3; }; + max-ixfr-ratio unlimited; }; zone "sub.test" IN { type slave; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index dbae875c87..037c9e218f 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1565,6 +1565,24 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, } } + obj = NULL; + (void)cfg_map_get(options, "max-ixfr-ratio", &obj); + if (obj != NULL && cfg_obj_ispercentage(obj)) { + uint32_t percent = cfg_obj_aspercentage(obj); + if (percent == 0) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'ixfr-max-ratio' must be a nonzero " + "percentage or 'unlimited')"); + if (result == ISC_R_SUCCESS) { + result = ISC_R_RANGE; + } + } else if (percent > 100) { + cfg_obj_log(obj, logctx, ISC_LOG_WARNING, + "'ixfr-max-ratio %d%%' exceeds 100%%", + percent); + } + } + return (result); } diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 4ca41d65e1..c5c363ab0e 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -2345,6 +2345,25 @@ dns_zone_setrequestixfr(dns_zone_t *zone, bool flag); * \li 'zone' to be valid. */ +uint32_t +dns_zone_getixfrratio(dns_zone_t *zone); +/*% + * Returns the zone's current IXFR ratio. + * + * Requires: + * \li 'zone' to be valid. + */ + +void +dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio); +/*% + * Sets the ratio of IXFR size to zone size above which we use an AXFR + * response, expressed as a percentage. Cannot exceed 100. + * + * Requires: + * \li 'zone' to be valid. + */ + void dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method); /*% diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index b5f2e57c65..3c25fec239 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -1203,6 +1203,7 @@ dns_zone_getgluecachestats dns_zone_getidlein dns_zone_getidleout dns_zone_getincludes +dns_zone_getixfrratio dns_zone_getjournal dns_zone_getjournalsize dns_zone_getkasp @@ -1305,6 +1306,7 @@ dns_zone_setforwardacl dns_zone_setidlein dns_zone_setidleout dns_zone_setisself +dns_zone_setixfrratio dns_zone_setjournal dns_zone_setjournalsize dns_zone_setkasp diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d1459c1919..e408e7ff4d 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -408,6 +408,7 @@ struct dns_zone { * whether ixfr is requested */ bool requestixfr; + uint32_t ixfr_ratio; /*% * whether EDNS EXPIRE is requested @@ -1114,6 +1115,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->sourceserial = 0; zone->sourceserialset = false; zone->requestixfr = true; + zone->ixfr_ratio = 100; zone->requestexpire = true; ISC_LIST_INIT(zone->rss_events); ISC_LIST_INIT(zone->rss_post); @@ -20083,6 +20085,18 @@ dns_zone_getrequestixfr(dns_zone_t *zone) { return (zone->requestixfr); } +void +dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->ixfr_ratio = ratio; +} + +uint32_t +dns_zone_getixfrratio(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->ixfr_ratio); +} + void dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) { REQUIRE(DNS_ZONE_VALID(zone)); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 516be5cc2b..d3b0d6a41f 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -92,6 +92,7 @@ static cfg_type_t cfg_type_dnstapoutput; static cfg_type_t cfg_type_dyndb; static cfg_type_t cfg_type_plugin; static cfg_type_t cfg_type_ixfrdifftype; +static cfg_type_t cfg_type_ixfrratio; static cfg_type_t cfg_type_key; static cfg_type_t cfg_type_logfile; static cfg_type_t cfg_type_logging; @@ -2165,6 +2166,8 @@ static cfg_clausedef_t zone_clauses[] = { CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR | CFG_ZONE_STUB | CFG_ZONE_REDIRECT }, { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT }, + { "max-ixfr-ratio", &cfg_type_ixfrratio, + CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "max-journal-size", &cfg_type_size, CFG_ZONE_MASTER | CFG_ZONE_SLAVE | CFG_ZONE_MIRROR }, { "max-records", &cfg_type_uint32, @@ -2699,6 +2702,28 @@ static cfg_type_t cfg_type_sizeorpercent = { doc_parse_size_or_percent, &cfg_rep_string, sizeorpercent_enums }; +/*% + * An IXFR size ratio: percentage, or "unlimited". + */ + +static isc_result_t +parse_ixfrratio(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + return (cfg_parse_enum_or_other(pctx, type, &cfg_type_percentage, ret)); +} + +static void +doc_ixfrratio(cfg_printer_t *pctx, const cfg_type_t *type) { + UNUSED(type); + cfg_print_cstr(pctx, "( unlimited | "); + cfg_doc_terminal(pctx, &cfg_type_percentage); + cfg_print_cstr(pctx, " )"); +} + +static const char *ixfrratio_enums[] = { "unlimited", NULL }; +static cfg_type_t cfg_type_ixfrratio = { "ixfr_ratio", parse_ixfrratio, + NULL, doc_ixfrratio, + NULL, ixfrratio_enums }; + /*% * optional_keyvalue */