diff options
Diffstat (limited to 'lib/dns/zone.c')
| -rw-r--r-- | lib/dns/zone.c | 515 |
1 files changed, 349 insertions, 166 deletions
diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 5db28449b8f7..fbaeab14c699 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ #include <config.h> @@ -444,6 +442,10 @@ typedef struct { #define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */ #define DNS_ZONEFLG_NODELAY 0x20000000U #define DNS_ZONEFLG_SENDSECURE 0x40000000U +#define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify + * due to the zone just + * being loaded for the + * first time. */ #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0) @@ -482,6 +484,8 @@ struct dns_zonemgr { isc_pool_t * mctxpool; isc_ratelimiter_t * notifyrl; isc_ratelimiter_t * refreshrl; + isc_ratelimiter_t * startupnotifyrl; + isc_ratelimiter_t * startuprefreshrl; isc_rwlock_t rwlock; isc_mutex_t iolock; isc_rwlock_t urlock; @@ -494,7 +498,10 @@ struct dns_zonemgr { /* Configuration data. */ isc_uint32_t transfersin; isc_uint32_t transfersperns; + unsigned int notifyrate; + unsigned int startupnotifyrate; unsigned int serialqueryrate; + unsigned int startupserialqueryrate; /* Locked by iolock */ isc_uint32_t iolimit; @@ -521,9 +528,11 @@ struct dns_notify { isc_sockaddr_t dst; dns_tsigkey_t *key; ISC_LINK(dns_notify_t) link; + isc_event_t *event; }; #define DNS_NOTIFY_NOSOA 0x0001U +#define DNS_NOTIFY_STARTUP 0x0002U /*% * dns_stub holds state while performing a 'stub' transfer. @@ -564,6 +573,7 @@ struct dns_forward { isc_sockaddr_t addr; dns_updatecallback_t callback; void *callback_arg; + unsigned int options; ISC_LINK(dns_forward_t) link; }; @@ -651,6 +661,16 @@ struct dns_asyncload { #define DAY (24*HOUR) #define MONTH (30*DAY) +/* + * These can be overridden by the -T mkeytimers option on the command + * line, so that we can test with shorter periods than specified in + * RFC 5011. + */ +unsigned int dns_zone_mkey_hour = HOUR; +unsigned int dns_zone_mkey_day = (24 * HOUR); +unsigned int dns_zone_mkey_month = (30 * DAY); + + #define SEND_BUFFER_SIZE 2048 static void zone_settimer(dns_zone_t *, isc_time_t *); @@ -742,6 +762,8 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff); static void zone_rekey(dns_zone_t *zone); static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db); +static void setrl(isc_ratelimiter_t *rl, unsigned int *rate, + unsigned int value); #define ENTER zone_debuglog(zone, me, 1, "enter") @@ -2328,6 +2350,8 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, DNS_DBFIND_GLUEOK, 0, NULL, foundname, &aaaa, NULL); if (tresult == ISC_R_SUCCESS) { + if (dns_rdataset_isassociated(&a)) + dns_rdataset_disassociate(&a); dns_rdataset_disassociate(&aaaa); return (ISC_TRUE); } @@ -3175,7 +3199,7 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { */ static void set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, - isc_stdtime_t now) + isc_stdtime_t now, isc_boolean_t force) { const char me[] = "set_refreshkeytimer"; isc_stdtime_t then; @@ -3184,6 +3208,8 @@ set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, ENTER; then = key->refresh; + if (force) + then = now; if (key->addhd > now && key->addhd < then) then = key->addhd; if (key->removehd > now && key->removehd < then) @@ -3263,8 +3289,9 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, dst_key_name(key), 0, &rdata)); *changed = ISC_TRUE; + /* Refresh new keys from the zone apex as soon as possible. */ - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); skip: result = dns_keytable_nextkeynode(keytable, keynode, &nextnode); @@ -3420,8 +3447,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { continue; RUNTIME_CHECK(result == ISC_R_SUCCESS); - /* Set the key refresh timer. */ - set_refreshkeytimer(zone, &keydata, now); + /* Set the key refresh timer to force a fast refresh. */ + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); /* If the removal timer is nonzero, this key was revoked. */ if (keydata.removehd != 0) { @@ -3615,6 +3642,8 @@ failure: if (ver != NULL) dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS)); + INSIST(ver == NULL); + return (result); } @@ -3687,7 +3716,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { result = dns_keytable_find(sr, rrname, &keynode); if ((result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) || - dns_keynode_managed(keynode) == ISC_FALSE) { + dns_keynode_managed(keynode) == ISC_FALSE) + { CHECK(delete_keydata(db, ver, &diff, rrname, rdataset)); changed = ISC_TRUE; @@ -3777,6 +3807,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { dns_db_closeversion(db, &ver, commit); dns_diff_clear(&diff); + INSIST(ver == NULL); + return (result); } @@ -4210,7 +4242,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, zone_attachdb(zone, db); ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); DNS_ZONE_SETFLAG(zone, - DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); + DNS_ZONEFLG_LOADED| + DNS_ZONEFLG_NEEDSTARTUPNOTIFY); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) && inline_raw(zone)) { @@ -5383,8 +5416,8 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdataset_t rdataset; unsigned int i; dns_rdata_rrsig_t rrsig; - isc_boolean_t found, changed; - isc_int64_t warn = 0, maybe = 0; + isc_boolean_t found; + isc_int64_t timewarn = 0, timemaybe = 0; dns_rdataset_init(&rdataset); @@ -5409,7 +5442,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, goto failure; } - changed = ISC_FALSE; for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { @@ -5425,8 +5457,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN, name, rdataset.ttl, &rdata); - if (incremental) - changed = ISC_TRUE; if (result != ISC_R_SUCCESS) break; deleted = ISC_TRUE; @@ -5445,7 +5475,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = offline(db, ver, zonediff, name, rdataset.ttl, &rdata); - changed = ISC_TRUE; if (result != ISC_R_SUCCESS) break; } @@ -5494,22 +5523,23 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, { isc_int64_t timeexpire = dns_time64_from32(rrsig.timeexpire); - if (warn != 0 && warn > timeexpire) - warn = timeexpire; + if (timewarn != 0 && + timewarn > timeexpire) + timewarn = timeexpire; if (rdata.flags & DNS_RDATA_OFFLINE) { - if (maybe == 0 || - maybe > timeexpire) - maybe = timeexpire; + if (timemaybe == 0 || + timemaybe > timeexpire) + timemaybe = timeexpire; break; } - if (warn == 0) - warn = maybe; - if (warn == 0 || warn > timeexpire) - warn = timeexpire; + if (timewarn == 0) + timewarn = timemaybe; + if (timewarn == 0 || + timewarn > timeexpire) + timewarn = timeexpire; result = offline(db, ver, zonediff, name, rdataset.ttl, &rdata); - changed = ISC_TRUE; break; } result = update_one_rr(db, ver, zonediff->diff, @@ -5532,18 +5562,16 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, break; } - if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0) - dns_db_resigned(db, &rdataset, ver); - dns_rdataset_disassociate(&rdataset); if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; - if (warn > 0) { + if (timewarn > 0) { #if defined(STDTIME_ON_32BITS) - isc_stdtime_t stdwarn = (isc_stdtime_t)warn; - if (warn == stdwarn) + isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn; + if (timewarn == stdwarn) #endif - set_key_expiry_warning(zone, (isc_stdtime_t)warn, now); + set_key_expiry_warning(zone, (isc_stdtime_t)timewarn, + now); #if defined(STDTIME_ON_32BITS) else dns_zone_log(zone, ISC_LOG_ERROR, @@ -5769,8 +5797,7 @@ zone_resigninc(dns_zone_t *zone) { dns_result_totext(result)); break; } - result = dns_db_getsigningtime(db, &rdataset, - dns_fixedname_name(&fixed)); + result = dns_db_getsigningtime(db, &rdataset, name); if (nkeys == 0 && result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; break; @@ -5857,6 +5884,8 @@ zone_resigninc(dns_zone_t *zone) { isc_interval_set(&ival, 300, 0); isc_time_nowplusinterval(&zone->resigntime, &ival); } + + INSIST(version == NULL); } static isc_result_t @@ -7331,15 +7360,17 @@ zone_nsec3chain(dns_zone_t *zone) { LOCK_ZONE(zone); if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) { - isc_interval_t i; + isc_interval_t interval; if (zone->update_disabled || result != ISC_R_SUCCESS) - isc_interval_set(&i, 60, 0); /* 1 minute */ + isc_interval_set(&interval, 60, 0); /* 1 minute */ else - isc_interval_set(&i, 0, 10000000); /* 10 ms */ - isc_time_nowplusinterval(&zone->nsec3chaintime, &i); + isc_interval_set(&interval, 0, 10000000); /* 10 ms */ + isc_time_nowplusinterval(&zone->nsec3chaintime, &interval); } else isc_time_settoepoch(&zone->nsec3chaintime); UNLOCK_ZONE(zone); + + INSIST(version == NULL); } static isc_result_t @@ -7879,19 +7910,22 @@ zone_sign(dns_zone_t *zone) { dns_db_detach(&db); if (ISC_LIST_HEAD(zone->signing) != NULL) { - isc_interval_t i; + isc_interval_t interval; if (zone->update_disabled || result != ISC_R_SUCCESS) - isc_interval_set(&i, 60, 0); /* 1 minute */ + isc_interval_set(&interval, 60, 0); /* 1 minute */ else - isc_interval_set(&i, 0, 10000000); /* 10 ms */ - isc_time_nowplusinterval(&zone->signingtime, &i); + isc_interval_set(&interval, 0, 10000000); /* 10 ms */ + isc_time_nowplusinterval(&zone->signingtime, &interval); } else isc_time_settoepoch(&zone->signingtime); + + INSIST(version == NULL); } static isc_result_t normalize_key(dns_rdata_t *rr, dns_rdata_t *target, - unsigned char *data, int size) { + unsigned char *data, int size) +{ dns_rdata_dnskey_t dnskey; dns_rdata_keydata_t keydata; isc_buffer_t buf; @@ -7988,11 +8022,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) rdset = &kfetch->dnskeysigset; else - return (now + HOUR); + return (now + dns_zone_mkey_hour); result = dns_rdataset_first(rdset); if (result != ISC_R_SUCCESS) - return (now + HOUR); + return (now + dns_zone_mkey_hour); dns_rdataset_current(rdset, &sigrr); result = dns_rdata_tostruct(&sigrr, &sig, NULL); @@ -8007,11 +8041,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > (15*DAY)) - t = (15*DAY); + if (t > (15 * dns_zone_mkey_day)) + t = (15 * dns_zone_mkey_day); - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } else { t = sig.originalttl / 10; @@ -8021,11 +8055,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > DAY) - t = DAY; + if (t > dns_zone_mkey_day) + t = dns_zone_mkey_day; - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } return (now + t); @@ -8068,7 +8102,7 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) if (result != ISC_R_SUCCESS) goto failure; keydata.refresh = refresh_time(kfetch, ISC_TRUE); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); dns_rdata_reset(&rdata); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8111,8 +8145,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* Generate a key from keydata */ isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); dns_keydata_todnskey(keydata, &dnskey, NULL); - dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey, - &dnskey, &keyb); + dns_rdata_fromstruct(&rr, keydata->common.rdclass, + dns_rdatatype_dnskey, &dnskey, &keyb); result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (ISC_FALSE); @@ -8120,7 +8154,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* See if that key generated any of the signatures */ for (result = dns_rdataset_first(&kfetch->dnskeysigset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeysigset)) { + result = dns_rdataset_next(&kfetch->dnskeysigset)) + { dns_fixedname_t fixed; dns_fixedname_init(&fixed); @@ -8130,8 +8165,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dst_key_alg(dstkey) == sig.algorithm && - (dst_key_id(dstkey) == sig.keyid || - dst_key_rid(dstkey) == sig.keyid)) { + dst_key_rid(dstkey) == sig.keyid) + { result = dns_dnssec_verify2(keyname, &kfetch->dnskeyset, dstkey, ISC_FALSE, mctx, &sigrr, @@ -8246,6 +8281,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { } /* + * Clear any cached trust level, as we need to run validation + * over again; trusted keys might have changed. + */ + kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none; + + /* * Validate the dnskeyset against the current trusted keys. */ for (result = dns_rdataset_first(&kfetch->dnskeysigset); @@ -8278,7 +8319,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_zone_log(zone, ISC_LOG_DEBUG(3), "Verifying DNSKEY set for zone " - "'%s': %s", namebuf, + "'%s' using key %d/%d: %s", + namebuf, sig.keyid, sig.algorithm, dns_result_totext(result)); if (result == ISC_R_SUCCESS) { @@ -8286,8 +8328,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_trust_secure; kfetch->dnskeysigset.trust = dns_trust_secure; - dns_keytable_detachkeynode(secroots, - &keynode); break; } } @@ -8298,6 +8338,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { keynode = nextnode; } + if (keynode != NULL) + dns_keytable_detachkeynode(secroots, &keynode); + if (kfetch->dnskeyset.trust == dns_trust_secure) break; } @@ -8342,31 +8385,34 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { isc_boolean_t deletekey = ISC_FALSE; if (!secure) { - if (now > keydata.removehd) + if (keydata.removehd != 0 && + keydata.removehd <= now) deletekey = ISC_TRUE; - } else if (now < keydata.addhd) { + } else if (keydata.addhd == 0) { + deletekey = ISC_TRUE; + } else if (keydata.addhd > now) { dns_zone_log(zone, ISC_LOG_WARNING, "Pending key unexpectedly missing " "from %s; restarting acceptance " "timer", namebuf); - keydata.addhd = now + MONTH; + if (keydata.addhd < now + dns_zone_mkey_month) + keydata.addhd = + now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); - } else if (keydata.addhd == 0) { - keydata.addhd = now; } else if (keydata.removehd == 0) { dns_zone_log(zone, ISC_LOG_WARNING, "Active key unexpectedly missing " "from %s", namebuf); - keydata.refresh = now + HOUR; - } else if (now > keydata.removehd) { + keydata.refresh = now + dns_zone_mkey_hour; + } else if (keydata.removehd <= now) { deletekey = ISC_TRUE; } else { keydata.refresh = refresh_time(kfetch, ISC_FALSE); } - if (secure || deletekey) { + if (secure || deletekey) { /* Delete old version */ CHECK(update_one_rr(kfetch->db, ver, &diff, DNS_DIFFOP_DEL, keyname, 0, @@ -8387,7 +8433,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { DNS_DIFFOP_ADD, keyname, 0, &keydatarr)); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8409,7 +8455,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { */ for (result = dns_rdataset_first(&kfetch->dnskeyset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeyset)) { + result = dns_rdataset_next(&kfetch->dnskeyset)) + { isc_boolean_t revoked = ISC_FALSE; isc_boolean_t newkey = ISC_FALSE; isc_boolean_t updatekey = ISC_FALSE; @@ -8445,34 +8492,43 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_view_untrust(zone->view, keyname, &dnskey, mctx); + /* But ensure there's a null key */ + fail_secure(zone, keyname); + /* If initializing, delete now */ if (keydata.addhd == 0) deletekey = ISC_TRUE; - else - keydata.removehd = now + MONTH; + else { + keydata.removehd = now + + dns_zone_mkey_month; + keydata.flags |= + DNS_KEYFLAG_REVOKE; + } } else if (keydata.removehd < now) { /* Scheduled for removal */ deletekey = ISC_TRUE; } - } else if (revoked) { - if (secure && keydata.removehd == 0) { - dns_zone_log(zone, ISC_LOG_WARNING, - "Active key for zone " - "'%s' is revoked but " - "did not self-sign; " - "ignoring.", namebuf); - continue; - } + } else if (revoked && keydata.removehd == 0) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Active key for zone " + "'%s' is revoked but " + "did not self-sign; " + "ignoring.", namebuf); + continue; } else if (secure) { if (keydata.removehd != 0) { /* * Key isn't revoked--but it * seems it used to be. * Remove it now and add it - * back as if it were a fresh key. + * back as if it were a fresh key, + * with a 30 day acceptance timer. */ deletekey = ISC_TRUE; newkey = ISC_TRUE; + keydata.removehd = 0; + keydata.addhd = + now + dns_zone_mkey_month; } else if (keydata.addhd > now) pending++; else if (keydata.addhd == 0) @@ -8480,6 +8536,13 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (keydata.addhd <= now) trustkey = ISC_TRUE; + } else if (keydata.addhd > now) { + /* + * Not secure, and key is pending: + * reset the acceptance timer + */ + pending++; + keydata.addhd = now + dns_zone_mkey_month; } if (!deletekey && !newkey) @@ -8541,7 +8604,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0, NULL); - keydata.addhd = initializing ? now : now + MONTH; + keydata.addhd = initializing + ? now : now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); dns_rdata_reset(&keydatarr); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8564,7 +8628,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (secure && !deletekey) { INSIST(newkey || updatekey); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8593,7 +8657,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { zone_needdump(zone, 30); } - failure: + failure: dns_diff_clear(&diff); if (ver != NULL) @@ -8624,6 +8688,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { UNLOCK_ZONE(zone); if (free_needed) zone_free(zone); + + INSIST(ver == NULL); } /* @@ -8776,7 +8842,7 @@ zone_refreshkeys(dns_zone_t *zone) { char timebuf[80]; TIME_NOW(&timenow); - DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen); + DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen); zone->refreshkeytime = timethen; zone_settimer(zone, &timenow); @@ -8796,6 +8862,8 @@ zone_refreshkeys(dns_zone_t *zone) { dns_db_closeversion(db, &ver, commit); } dns_db_detach(&db); + + INSIST(ver == NULL); } static void @@ -8868,7 +8936,8 @@ zone_maintenance(dns_zone_t *zone) { * Slaves send notifies before backing up to disk, masters after. */ if (zone->type == dns_zone_slave && - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) && + (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) && isc_time_compare(&now, &zone->notifytime) >= 0) zone_notify(zone, &now); @@ -8908,7 +8977,8 @@ zone_maintenance(dns_zone_t *zone) { switch (zone->type) { case dns_zone_master: case dns_zone_redirect: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) && + if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&& isc_time_compare(&now, &zone->notifytime) >= 0) zone_notify(zone, &now); default: @@ -9537,21 +9607,51 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) { } static isc_boolean_t -notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) { +notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name, + isc_sockaddr_t *addr, dns_tsigkey_t *key) +{ dns_notify_t *notify; + dns_zonemgr_t *zmgr; + isc_result_t result; for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL; notify = ISC_LIST_NEXT(notify, link)) { if (notify->request != NULL) continue; + if ((flags & DNS_NOTIFY_STARTUP) == 0) + notify->flags &= ~DNS_NOTIFY_STARTUP; if (name != NULL && dns_name_dynamic(¬ify->ns) && dns_name_equal(name, ¬ify->ns)) - return (ISC_TRUE); - if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst)) - return (ISC_TRUE); + goto requeue; + if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) && + notify->key == key) + goto requeue; } return (ISC_FALSE); + +requeue: + /* + * If we are enqueued on the startup ratelimiter and this is + * not a startup notify, re-enqueue on the normal notify + * ratelimiter. + */ + if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0) { + zmgr = notify->zone->zmgr; + result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl, + notify->event); + if (result != ISC_R_SUCCESS) + return (ISC_TRUE); + result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl, + notify->zone->task, + ¬ify->event); + if (result != ISC_R_SUCCESS) { + isc_event_free(¬ify->event); + return (ISC_FALSE); + } + } + + return (ISC_TRUE); } static isc_boolean_t @@ -9649,6 +9749,7 @@ notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { notify->find = NULL; notify->request = NULL; notify->key = NULL; + notify->event = NULL; isc_sockaddr_any(¬ify->dst); dns_name_init(¬ify->ns, NULL); ISC_LINK_INIT(notify, link); @@ -9724,22 +9825,27 @@ notify_find_address(dns_notify_t *notify) { static isc_result_t -notify_send_queue(dns_notify_t *notify) { +notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) { isc_event_t *e; isc_result_t result; - e = isc_event_allocate(notify->mctx, NULL, - DNS_EVENT_NOTIFYSENDTOADDR, - notify_send_toaddr, - notify, sizeof(isc_event_t)); + INSIST(notify->event == NULL); + e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR, + notify_send_toaddr, notify, sizeof(isc_event_t)); if (e == NULL) return (ISC_R_NOMEMORY); + if (startup) + notify->event = e; e->ev_arg = notify; e->ev_sender = NULL; - result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl, + result = isc_ratelimiter_enqueue(startup + ? notify->zone->zmgr->startupnotifyrl + : notify->zone->zmgr->notifyrl, notify->zone->task, &e); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { isc_event_free(&e); + notify->event = NULL; + } return (result); } @@ -9762,6 +9868,8 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { LOCK_ZONE(notify->zone); + notify->event = NULL; + if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) { result = ISC_R_CANCELED; goto cleanup; @@ -9871,6 +9979,8 @@ notify_send(dns_notify_t *notify) { isc_sockaddr_t dst; isc_result_t result; dns_notify_t *new = NULL; + unsigned int flags; + isc_boolean_t startup; /* * Zone lock held by caller. @@ -9882,20 +9992,21 @@ notify_send(dns_notify_t *notify) { ai != NULL; ai = ISC_LIST_NEXT(ai, publink)) { dst = ai->sockaddr; - if (notify_isqueued(notify->zone, NULL, &dst)) + if (notify_isqueued(notify->zone, notify->flags, NULL, &dst, + NULL)) continue; if (notify_isself(notify->zone, &dst)) continue; new = NULL; - result = notify_create(notify->mctx, - (notify->flags & DNS_NOTIFY_NOSOA), - &new); + flags = notify->flags & DNS_NOTIFY_NOSOA; + result = notify_create(notify->mctx, flags, &new); if (result != ISC_R_SUCCESS) goto cleanup; zone_iattach(notify->zone, &new->zone); ISC_LIST_APPEND(new->zone->notifies, new, link); new->dst = dst; - result = notify_send_queue(new); + startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0); + result = notify_send_queue(new, startup); if (result != ISC_R_SUCCESS) goto cleanup; new = NULL; @@ -9934,18 +10045,20 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { dns_rdataset_t nsrdset; dns_rdataset_t soardset; isc_result_t result; - dns_notify_t *notify = NULL; unsigned int i; isc_sockaddr_t dst; isc_boolean_t isqueued; dns_notifytype_t notifytype; unsigned int flags = 0; isc_boolean_t loggednotify = ISC_FALSE; + isc_boolean_t startup; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); + startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY); notifytype = zone->notifytype; DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime); UNLOCK_ZONE(zone); @@ -9970,6 +10083,12 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { flags |= DNS_NOTIFY_NOSOA; /* + * Record that this was a notify due to starting up. + */ + if (startup) + flags |= DNS_NOTIFY_STARTUP; + + /* * Get SOA RRset. */ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); @@ -10012,31 +10131,41 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { LOCK_ZONE(zone); for (i = 0; i < zone->notifycnt; i++) { dns_tsigkey_t *key = NULL; + dns_notify_t *notify = NULL; + + if ((zone->notifykeynames != NULL) && + (zone->notifykeynames[i] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->notifykeynames[i]; + (void)dns_view_gettsig(view, keyname, &key); + } dst = zone->notify[i]; - if (notify_isqueued(zone, NULL, &dst)) + if (notify_isqueued(zone, flags, NULL, &dst, key)) { + if (key != NULL) + dns_tsigkey_detach(&key); continue; + } result = notify_create(zone->mctx, flags, ¬ify); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + if (key != NULL) + dns_tsigkey_detach(&key); continue; + } zone_iattach(zone, ¬ify->zone); notify->dst = dst; - if ((zone->notifykeynames != NULL) && - (zone->notifykeynames[i] != NULL)) { - dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->notifykeynames[i]; - result = dns_view_gettsig(view, keyname, &key); - if (result == ISC_R_SUCCESS) { - notify->key = key; - key = NULL; - } + INSIST(notify->key == NULL); + + if (key != NULL) { + notify->key = key; + key = NULL; } ISC_LIST_APPEND(zone->notifies, notify, link); - result = notify_send_queue(notify); + result = notify_send_queue(notify, startup); if (result != ISC_R_SUCCESS) notify_destroy(notify, ISC_TRUE); if (!loggednotify) { @@ -10045,7 +10174,6 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { serial); loggednotify = ISC_TRUE; } - notify = NULL; } UNLOCK_ZONE(zone); @@ -10064,6 +10192,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { result = dns_rdataset_first(&nsrdset); while (result == ISC_R_SUCCESS) { + dns_notify_t *notify = NULL; + dns_rdataset_current(&nsrdset, &rdata); result = dns_rdata_tostruct(&rdata, &ns, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -10086,7 +10216,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { } LOCK_ZONE(zone); - isqueued = notify_isqueued(zone, &ns.name, NULL); + isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL); UNLOCK_ZONE(zone); if (isqueued) { result = dns_rdataset_next(&nsrdset); @@ -10107,7 +10237,6 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { ISC_LIST_APPEND(zone->notifies, notify, link); UNLOCK_ZONE(zone); notify_find_address(notify); - notify = NULL; result = dns_rdataset_next(&nsrdset); } dns_rdataset_disassociate(&nsrdset); @@ -10715,12 +10844,12 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { serial = soa.serial; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { - unsigned int soacount; - result = zone_get_from_db(zone, zone->db, NULL, &soacount, + unsigned int dbsoacount; + result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount, &oldserial, NULL, NULL, NULL, NULL, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - RUNTIME_CHECK(soacount > 0U); + RUNTIME_CHECK(dbsoacount > 0U); zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial, oldserial); } else @@ -11004,14 +11133,11 @@ soa_query(isc_task_t *task, isc_event_t *event) { goto cleanup; } - /* - * XXX Optimisation: Create message when zone is setup and reuse. - */ + again: result = create_query(zone, dns_rdatatype_soa, &message); if (result != ISC_R_SUCCESS) goto cleanup; - again: INSIST(zone->masterscnt > 0); INSIST(zone->curmaster < zone->masterscnt); @@ -11116,9 +11242,9 @@ soa_query(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) { zone_idetach(&dummy); zone_debuglog(zone, me, 1, - "dns_request_createvia2() failed: %s", + "dns_request_createvia4() failed: %s", dns_result_totext(result)); - goto cleanup; + goto skip_master; } else { if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) inc_stats(zone, dns_zonestatscounter_soaoutv4); @@ -11144,6 +11270,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { skip_master: if (key != NULL) dns_tsigkey_detach(&key); + dns_message_destroy(&message); /* * Skip to next failed / untried master. */ @@ -11526,7 +11653,8 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { /* FALLTHROUGH */ case dns_zone_master: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) next = zone->notifytime; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { @@ -12586,9 +12714,12 @@ notify_done(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); if (message != NULL && message->rcode == dns_rcode_formerr && (notify->flags & DNS_NOTIFY_NOSOA) == 0) { + isc_boolean_t startup; + notify->flags |= DNS_NOTIFY_NOSOA; dns_request_destroy(¬ify->request); - result = notify_send_queue(notify); + startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0); + result = notify_send_queue(notify, startup); if (result != ISC_R_SUCCESS) notify_destroy(notify, ISC_FALSE); } else { @@ -12614,7 +12745,7 @@ update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { } static isc_result_t -sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, +sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal, isc_uint32_t start, isc_uint32_t end, dns_difftuple_t **soatuplep, dns_diff_t *diff) { @@ -12658,9 +12789,9 @@ sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, /* Sanity. */ if (n_soa == 0) { - dns_zone_log(zone->raw, ISC_LOG_ERROR, + dns_zone_log(raw, ISC_LOG_ERROR, "corrupt journal file: '%s'\n", - zone->raw->journal); + raw->journal); return (ISC_R_FAILURE); } @@ -12689,7 +12820,7 @@ sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, } static isc_result_t -sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, +sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_dbversion_t *secver, dns_difftuple_t **soatuple, dns_diff_t *diff) { @@ -12701,13 +12832,12 @@ sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, dns_rdata_soa_t oldsoa, newsoa; REQUIRE(DNS_ZONE_VALID(seczone)); - REQUIRE(inline_secure(seczone)); REQUIRE(soatuple != NULL && *soatuple == NULL); if (!seczone->sourceserialset) return (DNS_R_UNCHANGED); - dns_db_attach(seczone->raw->db, &rawdb); + dns_db_attach(raw->db, &rawdb); dns_db_currentversion(rawdb, &rawver); result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL); dns_db_closeversion(rawdb, &rawver, ISC_FALSE); @@ -12794,7 +12924,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { isc_result_t result; dns_journal_t *rjournal = NULL; isc_uint32_t start, end; - dns_zone_t *zone; + dns_zone_t *zone, *raw = NULL; dns_db_t *db = NULL; dns_dbversion_t *newver = NULL, *oldver = NULL; dns_diff_t diff; @@ -12819,10 +12949,14 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_db_attach(zone->db, &db); ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->raw != NULL) + dns_zone_attach(zone->raw, &raw); + UNLOCK_ZONE(zone); + /* * zone->db may be NULL if the load from disk failed. */ - if (db == NULL || !inline_secure(zone)) { + if (db == NULL || raw == NULL) { result = ISC_R_FAILURE; goto failure; } @@ -12836,7 +12970,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { * If that fails, then we'll fall back to a direct comparison * between raw and secure zones. */ - result = dns_journal_open(zone->raw->mctx, zone->raw->journal, + result = dns_journal_open(raw->mctx, raw->journal, DNS_JOURNAL_WRITE, &rjournal); if (result != ISC_R_SUCCESS) goto failure; @@ -12875,12 +13009,12 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { * zone. If that fails, we recover by syncing up the databases * directly. */ - result = sync_secure_journal(zone, rjournal, start, end, + result = sync_secure_journal(zone, raw, rjournal, start, end, &soatuple, &diff); if (result == DNS_R_UNCHANGED) goto failure; else if (result != ISC_R_SUCCESS) - CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff)); + CHECK(sync_secure_db(zone, raw, db, oldver, &soatuple, &diff)); CHECK(dns_diff_apply(&diff, db, newver)); @@ -12913,6 +13047,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_journal_set_sourceserial(rjournal, end); dns_journal_commit(rjournal); + LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); zone->sourceserial = end; @@ -12921,12 +13056,14 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { TIME_NOW(&timenow); zone_settimer(zone, &timenow); + UNLOCK_ZONE(zone); dns_db_closeversion(db, &oldver, ISC_FALSE); dns_db_closeversion(db, &newver, ISC_TRUE); failure: - UNLOCK_ZONE(zone); + if (raw != NULL) + dns_zone_detach(&raw); if (result != ISC_R_SUCCESS) dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s", dns_result_totext(result)); @@ -12945,6 +13082,9 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_journal_destroy(&rjournal); dns_diff_clear(&diff); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } static isc_result_t @@ -13380,6 +13520,8 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { if (db != NULL) { if (node != NULL) dns_db_detachnode(db, &node); + if (version != NULL) + dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); } if (rawnode != NULL) @@ -13388,6 +13530,8 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { if (dbiterator != NULL) dns_dbiterator_destroy(&dbiterator); dns_zone_idetach(&zone); + + INSIST(version == NULL); } static isc_result_t @@ -14288,7 +14432,7 @@ sendtomaster(dns_forward_t *forward) { result = dns_request_createraw(forward->zone->view->requestmgr, forward->msgbuf, &src, &forward->addr, - DNS_REQUESTOPT_TCP, 15 /* XXX */, + forward->options, 15 /* XXX */, forward->zone->task, forward_callback, forward, &forward->request); @@ -14435,6 +14579,13 @@ dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, forward->callback_arg = callback_arg; ISC_LINK_INIT(forward, link); forward->magic = FORWARD_MAGIC; + forward->options = DNS_REQUESTOPT_TCP; + /* + * If we have a SIG(0) signed message we need to preserve the + * query id as that is included in the SIG(0) computation. + */ + if (msg->sig0 != NULL) + forward->options |= DNS_REQUESTOPT_FIXEDID; mr = dns_message_getrawmessage(msg); if (mr == NULL) { @@ -14495,7 +14646,6 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, { dns_zonemgr_t *zmgr; isc_result_t result; - isc_interval_t interval; zmgr = isc_mem_get(mctx, sizeof(*zmgr)); if (zmgr == NULL) @@ -14512,6 +14662,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, zmgr->task = NULL; zmgr->notifyrl = NULL; zmgr->refreshrl = NULL; + zmgr->startupnotifyrl = NULL; + zmgr->startuprefreshrl = NULL; ISC_LIST_INIT(zmgr->zones); ISC_LIST_INIT(zmgr->waiting_for_xfrin); ISC_LIST_INIT(zmgr->xfrin_in_progress); @@ -14544,15 +14696,21 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, if (result != ISC_R_SUCCESS) goto free_notifyrl; - /* default to 20 refresh queries / notifies per second. */ - isc_interval_set(&interval, 0, 1000000000/2); - result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->notifyrl, 10); + result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, + &zmgr->startupnotifyrl); + if (result != ISC_R_SUCCESS) + goto free_refreshrl; - result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->refreshrl, 10); + result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, + &zmgr->startuprefreshrl); + if (result != ISC_R_SUCCESS) + goto free_startupnotifyrl; + + /* default to 20 refresh queries / notifies per second. */ + setrl(zmgr->notifyrl, &zmgr->notifyrate, 20); + setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20); + setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20); + setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20); zmgr->iolimit = 1; zmgr->ioactive = 0; @@ -14561,7 +14719,7 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, result = isc_mutex_init(&zmgr->iolock); if (result != ISC_R_SUCCESS) - goto free_refreshrl; + goto free_startuprefreshrl; zmgr->magic = ZONEMGR_MAGIC; @@ -14572,6 +14730,10 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, free_iolock: DESTROYLOCK(&zmgr->iolock); #endif + free_startuprefreshrl: + isc_ratelimiter_detach(&zmgr->startuprefreshrl); + free_startupnotifyrl: + isc_ratelimiter_detach(&zmgr->startupnotifyrl); free_refreshrl: isc_ratelimiter_detach(&zmgr->refreshrl); free_notifyrl: @@ -14775,6 +14937,8 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { isc_ratelimiter_shutdown(zmgr->notifyrl); isc_ratelimiter_shutdown(zmgr->refreshrl); + isc_ratelimiter_shutdown(zmgr->startupnotifyrl); + isc_ratelimiter_shutdown(zmgr->startuprefreshrl); if (zmgr->task != NULL) isc_task_destroy(&zmgr->task); @@ -14908,6 +15072,8 @@ zonemgr_free(dns_zonemgr_t *zmgr) { DESTROYLOCK(&zmgr->iolock); isc_ratelimiter_detach(&zmgr->notifyrl); isc_ratelimiter_detach(&zmgr->refreshrl); + isc_ratelimiter_detach(&zmgr->startupnotifyrl); + isc_ratelimiter_detach(&zmgr->startuprefreshrl); isc_rwlock_destroy(&zmgr->urlock); isc_rwlock_destroy(&zmgr->rwlock); @@ -15270,15 +15436,13 @@ dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) { } #endif -void -dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { +static void +setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) { isc_interval_t interval; isc_uint32_t s, ns; isc_uint32_t pertic; isc_result_t result; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - if (value == 0) value = 1; @@ -15298,15 +15462,26 @@ dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { isc_interval_set(&interval, s, ns); - result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval); + result = isc_ratelimiter_setinterval(rl, &interval); RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->notifyrl, pertic); + isc_ratelimiter_setpertic(rl, pertic); - result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->refreshrl, pertic); + *rate = value; +} - zmgr->serialqueryrate = value; +void +dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value); + + /* Seperately controlled in BIND 9.11.x */ + setrl(zmgr->notifyrl, &zmgr->notifyrate, 20); + setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20); + + /* XXXMPA seperate out once we have the code to support this. */ + setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value); } unsigned int @@ -16627,6 +16802,8 @@ zone_rekey(dns_zone_t *zone) { dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); + + INSIST(ver == NULL); return; failure: @@ -16964,6 +17141,9 @@ keydone(isc_task_t *task, isc_event_t *event) { dns_diff_clear(&diff); isc_event_free(&event); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } isc_result_t @@ -17199,6 +17379,9 @@ setnsec3param(isc_task_t *task, isc_event_t *event) { dns_diff_clear(&diff); isc_event_free(&event); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } isc_result_t |
