aboutsummaryrefslogtreecommitdiff
path: root/lib/dns/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/zone.c')
-rw-r--r--lib/dns/zone.c515
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(&notify->ns) &&
dns_name_equal(name, &notify->ns))
- return (ISC_TRUE);
- if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
- return (ISC_TRUE);
+ goto requeue;
+ if (addr != NULL && isc_sockaddr_equal(addr, &notify->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,
+ &notify->event);
+ if (result != ISC_R_SUCCESS) {
+ isc_event_free(&notify->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(&notify->dst);
dns_name_init(&notify->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, &notify);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ if (key != NULL)
+ dns_tsigkey_detach(&key);
continue;
+ }
zone_iattach(zone, &notify->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(&notify->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