From 5e3affc6a0b155ee1cadac735c1a71f4d418ad69 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Fri, 10 Jun 2011 01:32:38 +0000 Subject: [PATCH] 3127. [bug] 'rndc thaw' will now remove a zone's journal file if the zone serial number has been changed and ixfr-from-differences is not in use. [RT #24687] --- CHANGES | 4 ++ bin/tests/system/autosign/tests.sh | 13 ++++- bin/tests/system/rndc/ns2/named.conf | 3 +- bin/tests/system/rndc/tests.sh | 63 ++++++++++++++++++++++- doc/arm/Bv9ARM-book.xml | 10 +++- lib/dns/zone.c | 76 +++++++++++++++++++++------- 6 files changed, 145 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index fb6f5e2fc2..fc473a51ab 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3127. [bug] 'rndc thaw' will now remove a zone's journal file + if the zone serial number has been changed and + ixfr-from-differences is not in use. [RT #24687] + 3126. [security] Using DNAME record to generate replacements caused RPZ to exit with a assertion failure. [RT #23766] diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index e70f69e7c4..422f47de4d 100644 --- a/bin/tests/system/autosign/tests.sh +++ b/bin/tests/system/autosign/tests.sh @@ -14,7 +14,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.29 2011/05/30 22:32:06 marka Exp $ +# $Id: tests.sh,v 1.30 2011/06/10 01:32:37 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -994,6 +994,15 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` -echo "I:exit status: $status" +echo "I:checking for key reloading loops ($n)" +ret=0 +# every key event should schedule a successor, so these should be equal +rekey_calls=`grep "reconfiguring zone keys" ns*/named.run | wc -l` +rekey_events=`grep "next key event" ns*/named.run | wc -l` +[ "$rekey_calls" = "$rekey_events" ] || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` +echo "I:exit status: $status" exit $status diff --git a/bin/tests/system/rndc/ns2/named.conf b/bin/tests/system/rndc/ns2/named.conf index 6ca9f6da7e..fa2000aa43 100644 --- a/bin/tests/system/rndc/ns2/named.conf +++ b/bin/tests/system/rndc/ns2/named.conf @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.3 2011/03/21 23:47:21 tbox Exp $ */ +/* $Id: named.conf,v 1.4 2011/06/10 01:32:37 each Exp $ */ controls { /* empty */ }; @@ -46,6 +46,7 @@ zone "nil" { type master; update-policy local; file "nil.db"; + ixfr-from-differences yes; }; zone "other" { diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh index 68a7f4c3d5..cfdce0ae3e 100644 --- a/bin/tests/system/rndc/tests.sh +++ b/bin/tests/system/rndc/tests.sh @@ -14,7 +14,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.3 2011/03/21 18:38:40 each Exp $ +# $Id: tests.sh,v 1.4 2011/06/10 01:32:37 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -164,5 +164,66 @@ $RNDCCMD freeze static 2>&1 | grep 'not dynamic' > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking that journal is removed when serial is changed before thaw" +ret=0 +sleep 1 +$NSUPDATE -p 5300 -k ns2/session.key > /dev/null 2>&1 <&1 | sed 's/^/I:ns2 /' +serial=`awk '$3 == "serial" {print $1}' ns2/other.db` +newserial=`expr $serial + 1` +sed s/$serial/$newserial/ ns2/other.db > ns2/other.db.new +echo 'frozen TXT "frozen addition"' >> ns2/other.db.new +mv -f ns2/other.db.new ns2/other.db +$RNDCCMD thaw 2>&1 | sed 's/^/I:ns2 /' +sleep 1 +[ -f ns2/other.db.jnl ] && ret=1 +$NSUPDATE -p 5300 -k ns2/session.key > /dev/null 2>&1 </dev/null || ret=1 +$DIGCMD text7.other. TXT | grep 'addition 7' >/dev/null || ret=1 +$DIGCMD frozen.other. TXT | grep 'frozen addition' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking that journal is kept when ixfr-from-differences is in use" +ret=0 +$NSUPDATE -p 5300 -k ns2/session.key > /dev/null 2>&1 <&1 | sed 's/^/I:ns2 /' +serial=`awk '$3 == "serial" {print $1}' ns2/nil.db` +newserial=`expr $serial + 1` +sed s/$serial/$newserial/ ns2/nil.db > ns2/nil.db.new +echo 'frozen TXT "frozen addition"' >> ns2/nil.db.new +mv -f ns2/nil.db.new ns2/nil.db +$RNDCCMD thaw 2>&1 | sed 's/^/I:ns2 /' +sleep 1 +[ -s ns2/nil.db.jnl ] || ret=1 +$NSUPDATE -p 5300 -k ns2/session.key > /dev/null 2>&1 </dev/null || ret=1 +$DIGCMD text7.nil. TXT | grep 'addition 7' >/dev/null || ret=1 +$DIGCMD frozen.nil. TXT | grep 'frozen addition' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:exit status: $status" exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 77ce23fde5..3dedd59e88 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -1257,7 +1257,13 @@ zone "eng.example.com" { enabled. This causes the server to reload the zone from disk, and re-enables dynamic updates after the load has completed. After a zone is thawed, - dynamic updates will no longer be refused. + dynamic updates will no longer be refused. If + the zone has changed and the + ixfr-from-differences option is + in use, then the journal file will be updated to + reflect changes in the zone. Otherwise, if the + zone has changed, any existing journal file will be + removed. diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 88c0ebfa84..941b98dcf8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.612 2011/05/26 04:25:47 each Exp $ */ +/* $Id: zone.c,v 1.613 2011/06/10 01:32:38 each Exp $ */ /*! \file */ @@ -1594,8 +1594,8 @@ dns_zone_loadandthaw(dns_zone_t *zone) { case DNS_R_CONTINUE: /* Deferred thaw. */ break; - case ISC_R_SUCCESS: case DNS_R_UPTODATE: + case ISC_R_SUCCESS: case DNS_R_SEENINCLUDE: zone->update_disabled = ISC_FALSE; break; @@ -3413,9 +3413,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, needdump = ISC_TRUE; } - zone->loadtime = loadtime; - - dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded"); /* * Obtain ns, soa and cname counts for top of zone. */ @@ -3428,6 +3425,48 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "could not find NS and/or SOA records"); } + /* + * Check to make sure the journal is up to date, and remove the + * journal file if it isn't, as we wouldn't be able to apply + * updates otherwise. + */ + if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) && + ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { + isc_uint32_t jserial; + dns_journal_t *journal = NULL; + + result = dns_journal_open(zone->mctx, zone->journal, + ISC_FALSE, &journal); + if (result == ISC_R_SUCCESS) { + jserial = dns_journal_last_serial(journal); + dns_journal_destroy(&journal); + } else { + jserial = serial; + result = ISC_R_SUCCESS; + } + + if (jserial != serial) { + dns_zone_log(zone, ISC_LOG_INFO, + "journal file is out of date: " + "removing journal file"); + if (remove(zone->journal) < 0 && errno != ENOENT) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, + ISC_LOG_WARNING, + "unable to remove journal " + "'%s': '%s'", + zone->journal, strbuf); + } + } + } + + zone->loadtime = loadtime; + + dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded"); + /* * Master / Slave / Stub zones require both NS and SOA records at * the top of the zone. @@ -14159,14 +14198,11 @@ zone_rekey(dns_zone_t *zone) { dns_rdatatype_none, 0, &keyset, &keysigs); if (result == ISC_R_SUCCESS) { ttl = keyset.ttl; - result = dns_dnssec_keylistfromrdataset(&zone->origin, dir, - mctx, &keyset, - &keysigs, &soasigs, - ISC_FALSE, ISC_FALSE, - &dnskeys); - /* Can't get keys for some reason; try again later. */ - if (result != ISC_R_SUCCESS) - goto trylater; + CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir, + mctx, &keyset, + &keysigs, &soasigs, + ISC_FALSE, ISC_FALSE, + &dnskeys)); } else if (result != ISC_R_NOTFOUND) goto failure; @@ -14192,7 +14228,7 @@ zone_rekey(dns_zone_t *zone) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:" "couldn't update zone keys: %s", isc_result_totext(result)); - goto trylater; + goto failure; } /* See if any pre-existing keys have newly become active; @@ -14410,7 +14446,7 @@ zone_rekey(dns_zone_t *zone) { dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf); } - failure: + done: dns_diff_clear(&diff); dns_diff_clear(&sig_diff); @@ -14432,10 +14468,14 @@ zone_rekey(dns_zone_t *zone) { dns_db_detach(&db); return; - trylater: - isc_interval_set(&ival, HOUR, 0); + failure: + /* + * Something went wrong; try again in ten minutes or + * after a key refresh interval, whichever is shorter. + */ + isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0); isc_time_nowplusinterval(&zone->refreshkeytime, &ival); - goto failure; + goto done; } void