diff --git a/CHANGES b/CHANGES index d21d98c2dd..508038d575 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3618. [func] "rndc reload" now checks modification times of + include files as well as master files to determine + whether to skip reloading a zone. [RT #33936] + 3617. [bug] Named was failing to answer queries during "rndc reload" [RT #34098] diff --git a/bin/tests/system/rndc/clean.sh b/bin/tests/system/rndc/clean.sh index bcea515c74..326e31c568 100644 --- a/bin/tests/system/rndc/clean.sh +++ b/bin/tests/system/rndc/clean.sh @@ -16,7 +16,7 @@ # $Id: clean.sh,v 1.2 2011/03/21 18:06:06 each Exp $ -rm -f ns2/*.db ns2/*.jnl +rm -f ns2/nil.db ns2/other.db ns2/static.db ns2/*.jnl rm -f ns2/session.key rm -f ns2/named.stats rm -f ns3/named_dump.db diff --git a/bin/tests/system/rndc/ns2/named.conf b/bin/tests/system/rndc/ns2/named.conf index 2d13bc6fd1..e18b760f49 100644 --- a/bin/tests/system/rndc/ns2/named.conf +++ b/bin/tests/system/rndc/ns2/named.conf @@ -64,3 +64,8 @@ zone "static" { type master; file "static.db"; }; + +zone "incl" { + type master; + file "incl.db"; +}; diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh index 3696a9f294..6e14a470e1 100644 --- a/bin/tests/system/rndc/tests.sh +++ b/bin/tests/system/rndc/tests.sh @@ -242,7 +242,7 @@ status=`expr $status + $ret` echo "I:test 'rndc dumpdb' on a empty cache" ret=0 $RNDC -s 10.53.0.3 -p 9953 -c ../common/rndc.conf dumpdb > /dev/null || ret=1 -for i in 1 2 3 4 5 6 7 8 9 +for i in 1 2 3 4 5 6 7 8 9 do tmp=0 grep "Dump complete" ns3/named_dump.db > /dev/null || tmp=1 @@ -253,6 +253,34 @@ done if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:test 'rndc reload' on a zone with include files" +ret=0 +grep "incl/IN: skipping load" ns2/named.run > /dev/null && ret=1 +loads=`grep "incl/IN: starting load" ns2/named.run | wc -l` +[ "$loads" -eq 1 ] || ret=1 +$RNDC -s 10.53.0.2 -p 9953 -c ../common/rndc.conf reload > /dev/null || ret=1 +for i in 1 2 3 4 5 6 7 8 9 +do + tmp=0 + grep "incl/IN: skipping load" ns2/named.run > /dev/null || tmp=1 + [ $tmp -eq 0 ] && break + sleep 1 +done +[ $tmp -eq 1 ] && ret=1 +touch ns2/static.db +$RNDC -s 10.53.0.2 -p 9953 -c ../common/rndc.conf reload > /dev/null || ret=1 +for i in 1 2 3 4 5 6 7 8 9 +do + tmp=0 + loads=`grep "incl/IN: starting load" ns2/named.run | wc -l` + [ "$loads" -eq 2 ] || tmp=1 + [ $tmp -eq 0 ] && break + sleep 1 +done +[ $tmp -eq 1 ] && ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:testing rndc with hmac-md5" ret=0 $RNDC -s 10.53.0.4 -p 9951 -c ns4/key1.conf status > /dev/null 2>&1 || ret=1 diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a0bc2d0530..39c2d80337 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -653,6 +653,7 @@ struct dns_asyncload { */ struct dns_include { char *name; + isc_time_t filetime; ISC_LINK(dns_include_t) link; }; @@ -1597,11 +1598,41 @@ dns_zone_get_rpz_num(dns_zone_t *zone) { return (zone->rpz_num); } +static isc_boolean_t +zone_touched(dns_zone_t *zone) { + isc_result_t result; + isc_time_t modtime; + dns_include_t *include; + + REQUIRE(DNS_ZONE_VALID(zone)); + + result = isc_file_getmodtime(zone->masterfile, &modtime); + if (result != ISC_R_SUCCESS || + isc_time_compare(&modtime, &zone->loadtime) > 0) + { + zone->loadtime = modtime; + return (ISC_TRUE); + } + + for (include = ISC_LIST_HEAD(zone->includes); + include != NULL; + include = ISC_LIST_NEXT(include, link)) + { + result = isc_file_getmodtime(include->name, &modtime); + if (result != ISC_R_SUCCESS || + isc_time_compare(&modtime, &include->filetime) > 0) + return (ISC_TRUE); + } + + + return (ISC_FALSE); +} + static isc_result_t zone_load(dns_zone_t *zone, unsigned int flags) { isc_result_t result; isc_time_t now; - isc_time_t loadtime, filetime; + isc_time_t loadtime; dns_db_t *db = NULL; isc_boolean_t rbt, hasraw; @@ -1680,18 +1711,14 @@ zone_load(dns_zone_t *zone, unsigned int flags) { goto cleanup; } - result = isc_file_getmodtime(zone->masterfile, &filetime); - if (result == ISC_R_SUCCESS) { - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) && - isc_time_compare(&filetime, &zone->loadtime) <= 0) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "skipping load: master file " - "older than last load"); - result = DNS_R_UPTODATE; - goto cleanup; - } - loadtime = filetime; + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && + !zone_touched(zone)) + { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "skipping load: master file " + "older than last load"); + result = DNS_R_UPTODATE; + goto cleanup; } } @@ -1979,6 +2006,7 @@ get_master_options(dns_zone_t *zone) { static void zone_registerinclude(const char *filename, void *arg) { + isc_result_t result; dns_zone_t *zone = (dns_zone_t *) arg; dns_include_t *inc = NULL; @@ -1997,6 +2025,10 @@ zone_registerinclude(const char *filename, void *arg) { } ISC_LINK_INIT(inc, link); + result = isc_file_getmodtime(filename, &inc->filetime); + if (result != ISC_R_SUCCESS) + isc_time_settoepoch(&inc->filetime); + ISC_LIST_APPEND(zone->includes, inc, link); zone->nincludes++; }