From c41c261fc7b2ae573fab3675a03a5f1ef099a2ea Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 27 Jun 2012 09:21:09 +1000 Subject: [PATCH] 3342. [bug] Change #3314 broke saving of stub zones to disk resulting in excessive cpu usage in some cases. [RT #29952] --- CHANGES | 4 ++++ bin/tests/system/stub/tests.sh | 27 +++++++++++++++++++++++---- lib/dns/zone.c | 26 ++++++++++++++++++++------ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index decceac508..7edd1b21e2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3342. [bug] Change #3314 broke saving of stub zones to disk + resulting in excessive cpu usage in some cases. + [RT #29952] + 3341. [func] New "dnssec-verify" command checks a signed zone to ensure correctness of signatures and of NSEC/NSEC3 chains. [RT #23673] diff --git a/bin/tests/system/stub/tests.sh b/bin/tests/system/stub/tests.sh index d61a2190ab..ec589c2c0f 100644 --- a/bin/tests/system/stub/tests.sh +++ b/bin/tests/system/stub/tests.sh @@ -21,14 +21,24 @@ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh status=0 +echo "I:check that the stub zone has been saved to disk" +for i in 1 2 3 4 5 6 7 8 9 20 +do + [ -f ns3/child.example.st ] && break + sleep 1 +done +[ -f ns3/child.example.st ] || { status=1; echo "I:failed"; } -echo "I:trying an axfr that should be denied (NOTAUTH)" +for pass in 1 2 +do + +echo "I:trying an axfr that should be denied (NOTAUTH) (pass=$pass)" ret=0 -$DIG +tcp data.child.example. @10.53.0.3 axfr -p 5300 > dig.out.ns3 || ret=1 +$DIG +tcp child.example. @10.53.0.3 axfr -p 5300 > dig.out.ns3 || ret=1 grep "; Transfer failed." dig.out.ns3 > /dev/null || ret=1 [ $ret = 0 ] || { status=1; echo "I:failed"; } -echo "I:look for stub zone data without recursion (should not be found)" +echo "I:look for stub zone data without recursion (should not be found) (pass=$pass)" for i in 1 2 3 4 5 6 7 8 9 do ret=0 @@ -41,11 +51,20 @@ done $PERL ../digcomp.pl knowngood.dig.out.norec dig.out.ns3 || ret=1 [ $ret = 0 ] || { status=1; echo "I:failed"; } -echo "I:look for stub zone data with recursion (should be found)" +echo "I:look for stub zone data with recursion (should be found) (pass=$pass)" ret=0 $DIG +tcp data.child.example. @10.53.0.3 txt -p 5300 > dig.out.ns3 || ret=1 $PERL ../digcomp.pl knowngood.dig.out.rec dig.out.ns3 || ret=1 [ $ret = 0 ] || { status=1; echo "I:failed"; } +[ $pass = 1 ] && { + echo "I:stopping stub server" + $PERL $SYSTEMTESTTOP/stop.pl . ns3 + + echo "I:re-starting stub server" + $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns3 +} +done + echo "I:exit status: $status" exit $status diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 2ff4c7429e..6081dd1a96 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -8571,13 +8571,14 @@ zone_maintenance(dns_zone_t *zone) { case dns_zone_slave: case dns_zone_key: case dns_zone_redirect: + case dns_zone_stub: LOCK_ZONE(zone); if (zone->masterfile != NULL && isc_time_compare(&now, &zone->dumptime) >= 0 && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) { dumping = was_dumping(zone); - } else + } else dumping = ISC_TRUE; UNLOCK_ZONE(zone); if (!dumping) { @@ -8964,7 +8965,7 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { goto fail; } - if (compact) { + if (compact && zone->type != dns_zone_stub) { dns_zone_t *dummy = NULL; LOCK_ZONE(zone); zone_iattach(zone, &dummy); @@ -9870,7 +9871,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { dns_zone_t *zone = NULL; char master[ISC_SOCKADDR_FORMATSIZE]; char source[ISC_SOCKADDR_FORMATSIZE]; - isc_uint32_t nscnt, cnamecnt; + isc_uint32_t nscnt, cnamecnt, refresh, retry, expire; isc_result_t result; isc_time_t now; isc_boolean_t exiting = ISC_FALSE; @@ -10018,19 +10019,32 @@ stub_callback(isc_task_t *task, isc_event_t *event) { ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write); if (zone->db == NULL) zone_attachdb(zone, stub->db); + result = zone_get_from_db(zone, zone->db, NULL, NULL, NULL, &refresh, + &retry, &expire, NULL, NULL); + if (result == ISC_R_SUCCESS) { + zone->refresh = RANGE(refresh, zone->minrefresh, + zone->maxrefresh); + zone->retry = RANGE(retry, zone->minretry, zone->maxretry); + zone->expire = RANGE(expire, zone->refresh + zone->retry, + DNS_MAX_EXPIRE); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); + } ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); dns_db_detach(&stub->db); - if (zone->masterfile != NULL) - zone_needdump(zone, 0); - dns_message_destroy(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); isc_interval_set(&i, zone->expire, 0); DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); + + if (zone->masterfile != NULL) + zone_needdump(zone, 0); + zone_settimer(zone, &now); goto free_stub;