summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/zone.c
diff options
context:
space:
mode:
authorerwin <erwin@FreeBSD.org>2013-08-06 06:22:54 +0000
committererwin <erwin@FreeBSD.org>2013-08-06 06:22:54 +0000
commitef27886236495d424b7f096da332d093109780a6 (patch)
treeb4ab3fc36f81b1377b903cb2fe0ca445c0304cbd /contrib/bind9/lib/dns/zone.c
parentc116c25dd59e2f090a93b32234e356ae28d96a02 (diff)
parent414d5ed7dd8cad7ef2738c53f9b9ecfe246ed91c (diff)
downloadFreeBSD-src-ef27886236495d424b7f096da332d093109780a6.zip
FreeBSD-src-ef27886236495d424b7f096da332d093109780a6.tar.gz
Update Bind to 9.8.5-P2
New Features Adds a new configuration option, "check-spf"; valid values are "warn" (default) and "ignore". When set to "warn", checks SPF and TXT records in spf format, warning if either resource record type occurs without a corresponding record of the other resource record type. [RT #33355] Adds support for Uniform Resource Identifier (URI) resource records. [RT #23386] Adds support for the EUI48 and EUI64 RR types. [RT #33082] Adds support for the RFC 6742 ILNP record types (NID, LP, L32, and L64). [RT #31836] Feature Changes Changes timing of when slave zones send NOTIFY messages after loading a new copy of the zone. They now send the NOTIFY before writing the zone data to disk. This will result in quicker propagation of updates in multi-level server structures. [RT #27242] "named -V" can now report a source ID string. (This is will be of most interest to developers and troubleshooters). The source ID for ISC's production versions of BIND is defined in the "srcid" file in the build tree and is normally set to the most recent git hash. [RT #31494] Response Policy Zone performance enhancements. New "response-policy" option "min-ns-dots". "nsip" and "nsdname" now enabled by default with RPZ. [RT #32251] Approved by: delphij (mentor) Sponsored by: DK Hostmaster A/S
Diffstat (limited to 'contrib/bind9/lib/dns/zone.c')
-rw-r--r--contrib/bind9/lib/dns/zone.c468
1 files changed, 344 insertions, 124 deletions
diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c
index 22db239..c212bf6 100644
--- a/contrib/bind9/lib/dns/zone.c
+++ b/contrib/bind9/lib/dns/zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -335,9 +335,9 @@ struct dns_zone {
isc_boolean_t added;
/*%
- * whether a rpz radix was needed when last loaded
+ * whether this is a response policy zone
*/
- isc_boolean_t rpz_zone;
+ isc_boolean_t is_rpz;
/*%
* Outstanding forwarded UPDATE requests.
@@ -345,6 +345,18 @@ struct dns_zone {
dns_forwardlist_t forwards;
};
+typedef struct {
+ dns_diff_t *diff;
+ isc_boolean_t offline;
+} zonediff_t;
+
+#define zonediff_init(z, d) \
+ do { \
+ zonediff_t *_z = (z); \
+ (_z)->diff = (d); \
+ (_z)->offline = ISC_FALSE; \
+ } while (0)
+
#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
#define DNS_ZONE_SETFLAG(z,f) do { \
INSIST(LOCKED_ZONE(z)); \
@@ -855,7 +867,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->nodes = 100;
zone->privatetype = (dns_rdatatype_t)0xffffU;
zone->added = ISC_FALSE;
- zone->rpz_zone = ISC_FALSE;
+ zone->is_rpz = ISC_FALSE;
ISC_LIST_INIT(zone->forwards);
zone->magic = ZONE_MAGIC;
@@ -1042,6 +1054,7 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
isc_result_t
dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
isc_result_t result;
+ unsigned int soacount;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(serialp != NULL);
@@ -1049,8 +1062,11 @@ dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
LOCK_ZONE(zone);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
- result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
- NULL, NULL, NULL, NULL, NULL);
+ result = zone_get_from_db(zone, zone->db, NULL, &soacount,
+ serialp, NULL, NULL, NULL, NULL,
+ NULL);
+ if (result == ISC_R_SUCCESS && soacount == 0)
+ result = ISC_R_FAILURE;
} else
result = DNS_R_NOTLOADED;
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
@@ -1390,6 +1406,30 @@ zone_isdynamic(dns_zone_t *zone) {
!dns_acl_isnone(zone->update_acl))));
}
+/*
+ * Set the response policy index and information for a zone.
+ */
+isc_result_t
+dns_zone_rpz_enable(dns_zone_t *zone) {
+ /*
+ * Only RBTDB zones can be used for response policy zones,
+ * because only they have the code to load the create the summary data.
+ * Only zones that are loaded instead of mmap()ed create the
+ * summary data and so can be policy zones.
+ */
+ if (strcmp(zone->db_argv[0], "rbt") != 0 &&
+ strcmp(zone->db_argv[0], "rbt64") != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ zone->is_rpz = ISC_TRUE;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+dns_zone_get_rpz(dns_zone_t *zone) {
+ return (zone->is_rpz);
+}
static isc_result_t
zone_load(dns_zone_t *zone, unsigned int flags) {
@@ -1459,8 +1499,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
* "rndc reconfig", we are done.
*/
if (!isc_time_isepoch(&zone->loadtime) &&
- (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
- zone->rpz_zone == dns_rpz_needed()) {
+ (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
result = ISC_R_SUCCESS;
goto cleanup;
}
@@ -1469,8 +1508,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
if (result == ISC_R_SUCCESS) {
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
- isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
- zone->rpz_zone == dns_rpz_needed()) {
+ isc_time_compare(&filetime, &zone->loadtime) <= 0) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"skipping load: master file "
"older than last load");
@@ -1478,7 +1516,6 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
goto cleanup;
}
loadtime = filetime;
- zone->rpz_zone = dns_rpz_needed();
}
}
@@ -1704,8 +1741,15 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
isc_result_t tresult;
unsigned int options;
- options = get_master_options(zone);
+#ifdef BIND9
+ if (zone->is_rpz) {
+ result = dns_db_rpz_enabled(db, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+#endif
+ options = get_master_options(zone);
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
options |= DNS_MASTER_MANYERRORS;
@@ -2174,6 +2218,34 @@ zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
}
static isc_boolean_t
+isspf(const dns_rdata_t *rdata) {
+ char buf[1024];
+ const unsigned char *data = rdata->data;
+ unsigned int rdl = rdata->length, i = 0, tl, len;
+
+ while (rdl > 0U) {
+ len = tl = *data;
+ ++data;
+ --rdl;
+ INSIST(tl <= rdl);
+ if (len > sizeof(buf) - i - 1)
+ len = sizeof(buf) - i - 1;
+ memcpy(buf + i, data, len);
+ i += len;
+ data += tl;
+ rdl -= tl;
+ }
+
+ if (i < 6U)
+ return(ISC_FALSE);
+
+ buf[i] = 0;
+ if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static isc_boolean_t
integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_dbiterator_t *dbiterator = NULL;
dns_dbnode_t *node = NULL;
@@ -2187,7 +2259,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_name_t *name;
dns_name_t *bottom;
isc_result_t result;
- isc_boolean_t ok = ISC_TRUE;
+ isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
@@ -2265,7 +2337,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
- goto next;
+ goto checkspf;
result = dns_rdataset_first(&rdataset);
while (result == ISC_R_SUCCESS) {
dns_rdataset_current(&rdataset, &rdata);
@@ -2278,6 +2350,50 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
}
dns_rdataset_disassociate(&rdataset);
+ checkspf:
+ /*
+ * Check if there is a type TXT spf record without a type SPF
+ * RRset being present.
+ */
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
+ goto next;
+ if (zone->rdclass != dns_rdataclass_in)
+ goto next;
+ have_spf = have_txt = ISC_FALSE;
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&rdataset);
+ have_spf = ISC_TRUE;
+ }
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto notxt;
+ result = dns_rdataset_first(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ have_txt = isspf(&rdata);
+ dns_rdata_reset(&rdata);
+ if (have_txt)
+ break;
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ notxt:
+ if (have_spf != have_txt) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *found = have_txt ? "TXT" : "SPF";
+ const char *need = have_txt ? "SPF" : "TXT";
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
+ "record but no SPF/%s record found, add "
+ "matching type %s record", namebuf, found,
+ need, need);
+ }
+
next:
dns_db_detachnode(db, &node);
result = dns_dbiterator_next(dbiterator);
@@ -2788,6 +2904,8 @@ 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);
skip:
result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
@@ -2797,10 +2915,6 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
}
}
- /* Refresh new keys from the zone apex as soon as possible. */
- if (*changed)
- set_refreshkeytimer(zone, &keydata, now);
-
if (keynode != NULL)
dns_keytable_detachkeynode(keytable, &keynode);
*keynodep = NULL;
@@ -2942,7 +3056,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
dns_rdataset_current(rdataset, &rdata);
/* Convert rdata to keydata. */
- dns_rdata_tostruct(&rdata, &keydata, NULL);
+ result = dns_rdata_tostruct(&rdata, &keydata, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
/* Set the key refresh timer. */
set_refreshkeytimer(zone, &keydata, now);
@@ -3285,6 +3400,13 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
}
failure:
+ if (result != ISC_R_SUCCESS &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "unable to synchronize managed keys: %s",
+ dns_result_totext(result));
+ isc_time_settoepoch(&zone->refreshkeytime);
+ }
if (keynode != NULL)
dns_keytable_detachkeynode(sr, &keynode);
if (sr != NULL)
@@ -3462,14 +3584,18 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
}
if (zone->db != NULL) {
+ unsigned int oldsoacount;
+
/*
* This is checked in zone_replacedb() for slave zones
* as they don't reload from disk.
*/
- result = zone_get_from_db(zone, zone->db, NULL, NULL,
- &oldserial, NULL, NULL, NULL,
- NULL, NULL);
+ result = zone_get_from_db(zone, zone->db, NULL,
+ &oldsoacount, &oldserial,
+ NULL, NULL, NULL, NULL,
+ NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(soacount > 0U);
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
!isc_serial_gt(serial, oldserial)) {
isc_uint32_t serialmin, serialmax;
@@ -3877,6 +4003,19 @@ zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
*expire = soa.expire;
if (minimum != NULL)
*minimum = soa.minimum;
+ } else {
+ if (soacount != NULL)
+ *soacount = 0;
+ if (serial != NULL)
+ *serial = 0;
+ if (refresh != NULL)
+ *refresh = 0;
+ if (retry != NULL)
+ *retry = 0;
+ if (expire != NULL)
+ *expire = 0;
+ if (minimum != NULL)
+ *minimum = 0;
}
result = ISC_R_SUCCESS;
@@ -4543,20 +4682,21 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
}
static isc_result_t
-offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
- dns_ttl_t ttl, dns_rdata_t *rdata)
+offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
+ dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
{
isc_result_t result;
if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
return (ISC_R_SUCCESS);
- result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
+ result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
name, ttl, rdata);
if (result != ISC_R_SUCCESS)
return (result);
rdata->flags |= DNS_RDATA_OFFLINE;
- result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
+ result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
name, ttl, rdata);
+ zonediff->offline = ISC_TRUE;
return (result);
}
@@ -4631,7 +4771,7 @@ delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
*/
static isc_result_t
del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
- dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
+ dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
{
isc_result_t result;
@@ -4677,7 +4817,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
if (type != dns_rdatatype_dnskey) {
if (delsig_ok(&rrsig, keys, nkeys)) {
- result = update_one_rr(db, ver, diff,
+ result = update_one_rr(db, ver, zonediff->diff,
DNS_DIFFOP_DELRESIGN, name,
rdataset.ttl, &rdata);
if (incremental)
@@ -4695,8 +4835,9 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* for the private part.
*/
if (incremental) {
- result = offline(db, ver, diff, name,
- rdataset.ttl, &rdata);
+ result = offline(db, ver, zonediff,
+ name, rdataset.ttl,
+ &rdata);
changed = ISC_TRUE;
if (result != ISC_R_SUCCESS)
break;
@@ -4756,11 +4897,12 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
warn = maybe;
if (warn == 0 || warn > timeexpire)
warn = timeexpire;
- result = offline(db, ver, diff, name,
- rdataset.ttl, &rdata);
+ result = offline(db, ver, zonediff,
+ name, rdataset.ttl,
+ &rdata);
break;
}
- result = update_one_rr(db, ver, diff,
+ result = update_one_rr(db, ver, zonediff->diff,
DNS_DIFFOP_DELRESIGN,
name, rdataset.ttl,
&rdata);
@@ -4773,7 +4915,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* delete the RRSIG.
*/
if (!found)
- result = update_one_rr(db, ver, diff,
+ result = update_one_rr(db, ver, zonediff->diff,
DNS_DIFFOP_DELRESIGN, name,
rdataset.ttl, &rdata);
if (result != ISC_R_SUCCESS)
@@ -4903,9 +5045,11 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
static void
zone_resigninc(dns_zone_t *zone) {
+ const char *me = "zone_resigninc";
dns_db_t *db = NULL;
dns_dbversion_t *version = NULL;
- dns_diff_t sig_diff;
+ dns_diff_t _sig_diff;
+ zonediff_t zonediff;
dns_fixedname_t fixed;
dns_name_t *name;
dns_rdataset_t rdataset;
@@ -4919,10 +5063,13 @@ zone_resigninc(dns_zone_t *zone) {
unsigned int nkeys = 0;
unsigned int resign;
+ ENTER;
+
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
- dns_diff_init(zone->mctx, &sig_diff);
- sig_diff.resign = zone->sigresigninginterval;
+ dns_diff_init(zone->mctx, &_sig_diff);
+ _sig_diff.resign = zone->sigresigninginterval;
+ zonediff_init(&zonediff, &_sig_diff);
/*
* Updates are disabled. Pause for 5 minutes.
@@ -4992,7 +5139,7 @@ zone_resigninc(dns_zone_t *zone) {
resign > stop)
break;
- result = del_sigs(zone, db, version, name, covers, &sig_diff,
+ result = del_sigs(zone, db, version, name, covers, &zonediff,
zone_keys, nkeys, now, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -5001,7 +5148,7 @@ zone_resigninc(dns_zone_t *zone) {
break;
}
- result = add_sigs(db, version, name, covers, &sig_diff,
+ result = add_sigs(db, version, name, covers, zonediff.diff,
zone_keys, nkeys, zone->mctx, inception,
expire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
@@ -5026,7 +5173,7 @@ zone_resigninc(dns_zone_t *zone) {
goto failure;
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
+ &zonediff, zone_keys, nkeys, now, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:del_sigs -> %s",
@@ -5037,11 +5184,17 @@ zone_resigninc(dns_zone_t *zone) {
/*
* Did we change anything in the zone?
*/
- if (ISC_LIST_EMPTY(sig_diff.tuples))
+ if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
+ /*
+ * Commit the changes if any key has been marked as offline.
+ */
+ if (zonediff.offline)
+ dns_db_closeversion(db, &version, ISC_TRUE);
goto failure;
+ }
/* Increment SOA serial if we have made changes */
- result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:increment_soa_serial -> %s",
@@ -5054,8 +5207,8 @@ zone_resigninc(dns_zone_t *zone) {
* termination is sensible.
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk, keyset_kskonly);
+ zonediff.diff, zone_keys, nkeys, zone->mctx,
+ inception, soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:add_sigs -> %s",
@@ -5064,13 +5217,13 @@ zone_resigninc(dns_zone_t *zone) {
}
/* Write changes to journal file. */
- CHECK(zone_journal(zone, &sig_diff, "zone_resigninc"));
+ CHECK(zone_journal(zone, zonediff.diff, "zone_resigninc"));
/* Everything has succeeded. Commit the changes. */
dns_db_closeversion(db, &version, ISC_TRUE);
failure:
- dns_diff_clear(&sig_diff);
+ dns_diff_clear(&_sig_diff);
for (i = 0; i < nkeys; i++)
dst_key_free(&zone_keys[i]);
if (version != NULL) {
@@ -5740,7 +5893,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
- dns_diff_t *sig_diff)
+ zonediff_t *zonediff)
{
dns_difftuple_t *tuple;
isc_result_t result;
@@ -5749,7 +5902,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
tuple != NULL;
tuple = ISC_LIST_HEAD(diff->tuples)) {
result = del_sigs(zone, db, version, &tuple->name,
- tuple->rdata.type, sig_diff,
+ tuple->rdata.type, zonediff,
zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -5758,7 +5911,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
return (result);
}
result = add_sigs(db, version, &tuple->name,
- tuple->rdata.type, sig_diff,
+ tuple->rdata.type, zonediff->diff,
zone_keys, nkeys, zone->mctx, inception,
expire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
@@ -5775,7 +5928,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
!dns_name_equal(&tuple->name, &next->name)))
next = ISC_LIST_NEXT(next, link);
ISC_LIST_UNLINK(diff->tuples, tuple, link);
- dns_diff_appendminimal(sig_diff, &tuple);
+ dns_diff_appendminimal(zonediff->diff, &tuple);
INSIST(tuple == NULL);
tuple = next;
} while (tuple != NULL);
@@ -5789,13 +5942,15 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
*/
static void
zone_nsec3chain(dns_zone_t *zone) {
+ const char *me = "zone_nsec3chain";
dns_db_t *db = NULL;
dns_dbnode_t *node = NULL;
dns_dbversion_t *version = NULL;
- dns_diff_t sig_diff;
+ dns_diff_t _sig_diff;
dns_diff_t nsec_diff;
dns_diff_t nsec3_diff;
dns_diff_t param_diff;
+ zonediff_t zonediff;
dns_fixedname_t fixed;
dns_fixedname_t nextfixed;
dns_name_t *name, *nextname;
@@ -5821,6 +5976,8 @@ zone_nsec3chain(dns_zone_t *zone) {
isc_boolean_t updatensec = ISC_FALSE;
dns_rdatatype_t privatetype = zone->privatetype;
+ ENTER;
+
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
@@ -5829,8 +5986,9 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_diff_init(zone->mctx, &param_diff);
dns_diff_init(zone->mctx, &nsec3_diff);
dns_diff_init(zone->mctx, &nsec_diff);
- dns_diff_init(zone->mctx, &sig_diff);
- sig_diff.resign = zone->sigresigninginterval;
+ dns_diff_init(zone->mctx, &_sig_diff);
+ _sig_diff.resign = zone->sigresigninginterval;
+ zonediff_init(&zonediff, &_sig_diff);
ISC_LIST_INIT(cleanup);
/*
@@ -6028,6 +6186,7 @@ zone_nsec3chain(dns_zone_t *zone) {
result = dns_dbiterator_next(nsec3chain->dbiterator);
if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
CHECK(fixup_nsec3param(db, version, nsec3chain,
ISC_FALSE, privatetype,
&param_diff));
@@ -6325,6 +6484,7 @@ zone_nsec3chain(dns_zone_t *zone) {
if (rebuild_nsec) {
if (nsec3chain != NULL)
dns_dbiterator_pause(nsec3chain->dbiterator);
+
result = updatesecure(db, version, &zone->origin,
zone->minimum, ISC_TRUE,
&nsec_diff);
@@ -6336,7 +6496,11 @@ zone_nsec3chain(dns_zone_t *zone) {
goto failure;
}
}
+
if (rebuild_nsec3) {
+ if (nsec3chain != NULL)
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+
result = dns_nsec3_addnsec3s(db, version,
dns_db_origin(db),
zone->minimum, ISC_FALSE,
@@ -6351,12 +6515,17 @@ zone_nsec3chain(dns_zone_t *zone) {
}
}
+ if (nsec3chain != NULL)
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+
/*
* Add / update signatures for the NSEC3 records.
*/
+ if (nsec3chain != NULL)
+ dns_dbiterator_pause(nsec3chain->dbiterator);
result = update_sigs(&nsec3_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, keyset_kskonly, &sig_diff);
+ check_ksk, keyset_kskonly, &zonediff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s", dns_result_totext(result));
@@ -6369,7 +6538,7 @@ zone_nsec3chain(dns_zone_t *zone) {
*/
result = update_sigs(&param_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, keyset_kskonly, &sig_diff);
+ check_ksk, keyset_kskonly, &zonediff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s", dns_result_totext(result));
@@ -6377,8 +6546,6 @@ zone_nsec3chain(dns_zone_t *zone) {
}
if (updatensec) {
- if (nsec3chain != NULL)
- dns_dbiterator_pause(nsec3chain->dbiterator);
result = updatesecure(db, version, &zone->origin,
zone->minimum, ISC_FALSE, &nsec_diff);
if (result != ISC_R_SUCCESS) {
@@ -6391,7 +6558,7 @@ zone_nsec3chain(dns_zone_t *zone) {
result = update_sigs(&nsec_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, keyset_kskonly, &sig_diff);
+ check_ksk, keyset_kskonly, &zonediff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s", dns_result_totext(result));
@@ -6402,18 +6569,23 @@ zone_nsec3chain(dns_zone_t *zone) {
* If we made no effective changes to the zone then we can just
* cleanup otherwise we need to increment the serial.
*/
- if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
+ if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
+ /*
+ * No need to call dns_db_closeversion() here as it is
+ * called with commit = ISC_TRUE below.
+ */
goto done;
+ }
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
+ &zonediff, zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"del_sigs -> %s", dns_result_totext(result));
goto failure;
}
- result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"increment_soa_serial -> %s",
@@ -6422,8 +6594,8 @@ zone_nsec3chain(dns_zone_t *zone) {
}
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk, keyset_kskonly);
+ zonediff.diff, zone_keys, nkeys, zone->mctx,
+ inception, soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"add_sigs -> %s", dns_result_totext(result));
@@ -6431,7 +6603,7 @@ zone_nsec3chain(dns_zone_t *zone) {
}
/* Write changes to journal file. */
- CHECK(zone_journal(zone, &sig_diff, "zone_nsec3chain"));
+ CHECK(zone_journal(zone, zonediff.diff, "zone_nsec3chain"));
LOCK_ZONE(zone);
zone_needdump(zone, DNS_DUMP_DELAY);
@@ -6451,6 +6623,7 @@ zone_nsec3chain(dns_zone_t *zone) {
/*
* Everything has succeeded. Commit the changes.
+ * Unconditionally commit as zonediff.offline not checked above.
*/
dns_db_closeversion(db, &version, ISC_TRUE);
@@ -6520,7 +6693,7 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_diff_clear(&param_diff);
dns_diff_clear(&nsec3_diff);
dns_diff_clear(&nsec_diff);
- dns_diff_clear(&sig_diff);
+ dns_diff_clear(&_sig_diff);
if (iterator != NULL)
dns_rdatasetiter_destroy(&iterator);
@@ -6622,11 +6795,13 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
*/
static void
zone_sign(dns_zone_t *zone) {
+ const char *me = "zone_sign";
dns_db_t *db = NULL;
dns_dbnode_t *node = NULL;
dns_dbversion_t *version = NULL;
- dns_diff_t sig_diff;
+ dns_diff_t _sig_diff;
dns_diff_t post_diff;
+ zonediff_t zonediff;
dns_fixedname_t fixed;
dns_fixedname_t nextfixed;
dns_name_t *name, *nextname;
@@ -6648,14 +6823,17 @@ zone_sign(dns_zone_t *zone) {
unsigned int nkeys = 0;
isc_uint32_t nodes;
+ ENTER;
+
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
dns_fixedname_init(&nextfixed);
nextname = dns_fixedname_name(&nextfixed);
- dns_diff_init(zone->mctx, &sig_diff);
- sig_diff.resign = zone->sigresigninginterval;
+ dns_diff_init(zone->mctx, &_sig_diff);
+ _sig_diff.resign = zone->sigresigninginterval;
dns_diff_init(zone->mctx, &post_diff);
+ zonediff_init(&zonediff, &_sig_diff);
ISC_LIST_INIT(cleanup);
/*
@@ -6769,7 +6947,7 @@ zone_sign(dns_zone_t *zone) {
dns_dbiterator_pause(signing->dbiterator);
CHECK(del_sig(db, version, name, node, nkeys,
signing->algorithm, signing->keyid,
- &sig_diff));
+ zonediff.diff));
}
/*
@@ -6864,7 +7042,7 @@ zone_sign(dns_zone_t *zone) {
build_nsec, zone_keys[i], inception,
expire, zone->minimum, is_ksk,
ISC_TF(both && keyset_kskonly),
- &delegation, &sig_diff,
+ &delegation, zonediff.diff,
&signatures, zone->mctx));
/*
* If we are adding we are done. Look for other keys
@@ -6946,7 +7124,7 @@ zone_sign(dns_zone_t *zone) {
if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
result = update_sigs(&post_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, keyset_kskonly, &sig_diff);
+ check_ksk, keyset_kskonly, &zonediff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
"update_sigs -> %s",
@@ -6958,7 +7136,9 @@ zone_sign(dns_zone_t *zone) {
/*
* Have we changed anything?
*/
- if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
+ if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
+ if (zonediff.offline)
+ commit = ISC_TRUE;
result = ISC_R_SUCCESS;
goto pauseall;
}
@@ -6966,7 +7146,7 @@ zone_sign(dns_zone_t *zone) {
commit = ISC_TRUE;
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
+ &zonediff, zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:del_sigs -> %s",
@@ -6974,7 +7154,7 @@ zone_sign(dns_zone_t *zone) {
goto failure;
}
- result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:increment_soa_serial -> %s",
@@ -6987,8 +7167,8 @@ zone_sign(dns_zone_t *zone) {
* termination is sensible.
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk, keyset_kskonly);
+ zonediff.diff, zone_keys, nkeys, zone->mctx,
+ inception, soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:add_sigs -> %s",
@@ -6999,7 +7179,7 @@ zone_sign(dns_zone_t *zone) {
/*
* Write changes to journal file.
*/
- CHECK(zone_journal(zone, &sig_diff, "zone_sign"));
+ CHECK(zone_journal(zone, zonediff.diff, "zone_sign"));
pauseall:
/*
@@ -7059,7 +7239,7 @@ zone_sign(dns_zone_t *zone) {
signing = ISC_LIST_NEXT(signing, link))
dns_dbiterator_pause(signing->dbiterator);
- dns_diff_clear(&sig_diff);
+ dns_diff_clear(&_sig_diff);
for (i = 0; i < nkeys; i++)
dst_key_free(&zone_keys[i]);
@@ -7090,19 +7270,22 @@ normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
dns_rdata_dnskey_t dnskey;
dns_rdata_keydata_t keydata;
isc_buffer_t buf;
+ isc_result_t result;
dns_rdata_reset(target);
isc_buffer_init(&buf, data, size);
switch (rr->type) {
case dns_rdatatype_dnskey:
- dns_rdata_tostruct(rr, &dnskey, NULL);
+ result = dns_rdata_tostruct(rr, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
&dnskey, &buf);
break;
case dns_rdatatype_keydata:
- dns_rdata_tostruct(rr, &keydata, NULL);
+ result = dns_rdata_tostruct(rr, &keydata, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_keydata_todnskey(&keydata, &dnskey, NULL);
dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
&dnskey, &buf);
@@ -7509,7 +7692,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
result = dns_rdataset_next(&kfetch->keydataset)) {
dns_rdata_reset(&keydatarr);
dns_rdataset_current(&kfetch->keydataset, &keydatarr);
- dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+ result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
/*
* If any keydata record has a nonzero add holddown, then
@@ -7599,7 +7783,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
dns_rdata_reset(&dnskeyrr);
dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
- dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
/* Skip ZSK's */
if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
@@ -7610,7 +7795,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
dns_rdata_reset(&keydatarr);
dns_rdataset_current(&kfetch->keydataset, &keydatarr);
- dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+ result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (revoked && revocable(kfetch, &keydata)) {
if (keydata.addhd > now) {
@@ -7710,7 +7896,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
&keydatarr));
} else if (newkey) {
/* Convert DNSKEY to KEYDATA */
- dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
NULL);
keydata.addhd = initializing ? now : now + MONTH;
@@ -7729,7 +7916,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
if (trustkey) {
/* Trust this key. */
- dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
trust_key(zone, keyname, &dnskey, mctx);
}
@@ -8020,6 +8208,14 @@ 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) &&
+ isc_time_compare(&now, &zone->notifytime) >= 0)
+ zone_notify(zone, &now);
+
+ /*
* Do we need to consolidate the backing store?
*/
switch (zone->type) {
@@ -8049,14 +8245,28 @@ zone_maintenance(dns_zone_t *zone) {
}
/*
+ * Master/redirect zones send notifies now, if needed
+ */
+ switch (zone->type) {
+ case dns_zone_master:
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
+ isc_time_compare(&now, &zone->notifytime) >= 0)
+ zone_notify(zone, &now);
+ default:
+ break;
+ }
+
+ /*
* Do we need to refresh keys?
*/
switch (zone->type) {
case dns_zone_key:
- if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
- DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
- !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
- zone_refreshkeys(zone);
+ if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
+ zone_refreshkeys(zone);
+ }
+ }
break;
case dns_zone_master:
if (!isc_time_isepoch(&zone->refreshkeytime) &&
@@ -8070,12 +8280,6 @@ zone_maintenance(dns_zone_t *zone) {
case dns_zone_master:
case dns_zone_slave:
/*
- * Do we need to send out notify messages?
- */
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
- isc_time_compare(&now, &zone->notifytime) >= 0)
- zone_notify(zone, &now);
- /*
* Do we need to sign/resign some RRsets?
*/
if (!isc_time_isepoch(&zone->signingtime) &&
@@ -8088,7 +8292,7 @@ zone_maintenance(dns_zone_t *zone) {
isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
zone_nsec3chain(zone);
/*
- * Do we need to issue a key expiry warning.
+ * Do we need to issue a key expiry warning?
*/
if (!isc_time_isepoch(&zone->keywarntime) &&
isc_time_compare(&now, &zone->keywarntime) >= 0)
@@ -8237,6 +8441,7 @@ dns_zone_dump(dns_zone_t *zone) {
static void
zone_needdump(dns_zone_t *zone, unsigned int delay) {
+ const char me[] = "zone_needdump";
isc_time_t dumptime;
isc_time_t now;
@@ -8246,6 +8451,7 @@ zone_needdump(dns_zone_t *zone, unsigned int delay) {
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(LOCKED_ZONE(zone));
+ ENTER;
/*
* Do we have a place to dump to and are we loaded?
@@ -8898,9 +9104,9 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
dns_message_destroy(&message);
cleanup:
UNLOCK_ZONE(notify->zone);
+ isc_event_free(&event);
if (result != ISC_R_SUCCESS)
notify_destroy(notify, ISC_FALSE);
- isc_event_free(&event);
}
static void
@@ -9247,7 +9453,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
isc_time_t now;
isc_boolean_t exiting = ISC_FALSE;
isc_interval_t i;
- unsigned int j;
+ unsigned int j, soacount;
stub = revent->ev_arg;
INSIST(DNS_STUB_VALID(stub));
@@ -9390,9 +9596,9 @@ 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) {
+ result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
+ &refresh, &retry, &expire, NULL, NULL);
+ if (result == ISC_R_SUCCESS && soacount > 0U) {
zone->refresh = RANGE(refresh, zone->minrefresh,
zone->maxrefresh);
zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
@@ -9728,10 +9934,12 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
serial = soa.serial;
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
- result = zone_get_from_db(zone, zone->db, NULL, NULL,
+ unsigned int soacount;
+ result = zone_get_from_db(zone, zone->db, NULL, &soacount,
&oldserial, NULL, NULL, NULL, NULL,
NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(soacount > 0U);
zone_debuglog(zone, me, 1, "serial: new %u, old %u",
serial, oldserial);
} else
@@ -10953,6 +11161,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
result = dns_rdataset_first(rdataset);
if (result == ISC_R_SUCCESS) {
isc_uint32_t serial = 0, oldserial;
+ unsigned int soacount;
dns_rdataset_current(rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &soa, NULL);
@@ -10962,10 +11171,11 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
* The following should safely be performed without DB
* lock and succeed in this context.
*/
- result = zone_get_from_db(zone, zone->db, NULL, NULL,
- &oldserial, NULL, NULL, NULL,
- NULL, NULL);
+ result = zone_get_from_db(zone, zone->db, NULL,
+ &soacount, &oldserial, NULL,
+ NULL, NULL, NULL, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(soacount > 0U);
if (isc_serial_le(serial, oldserial)) {
dns_zone_log(zone,
ISC_LOG_INFO,
@@ -11652,6 +11862,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
isc_uint32_t serial, oldserial;
+ unsigned int soacount;
dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
@@ -11666,10 +11877,11 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
/*
* This is checked in zone_postload() for master zones.
*/
- result = zone_get_from_db(zone, zone->db, NULL, NULL,
+ result = zone_get_from_db(zone, zone->db, NULL, &soacount,
&oldserial, NULL, NULL, NULL, NULL,
NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(soacount > 0U);
if (zone->type == dns_zone_slave &&
!isc_serial_gt(serial, oldserial)) {
isc_uint32_t serialmin, serialmax;
@@ -11916,6 +12128,8 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
* won't hurt with an AXFR.
*/
if (zone->masterfile != NULL || zone->journal != NULL) {
+ unsigned int delay = DNS_DUMP_DELAY;
+
result = ISC_R_FAILURE;
if (zone->journal != NULL)
result = isc_file_settime(zone->journal, &now);
@@ -11923,14 +12137,16 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
zone->masterfile != NULL)
result = isc_file_settime(zone->masterfile,
&now);
- /* Someone removed the file from underneath us! */
- if (result == ISC_R_FILENOTFOUND &&
- zone->masterfile != NULL) {
- unsigned int delay = DNS_DUMP_DELAY;
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
- delay = 0;
+
+ if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
+ result == ISC_R_FILENOTFOUND)
+ delay = 0;
+
+ if ((result == ISC_R_SUCCESS ||
+ result == ISC_R_FILENOTFOUND) &&
+ zone->masterfile != NULL)
zone_needdump(zone, delay);
- } else if (result != ISC_R_SUCCESS)
+ else if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_ERROR,
"transfer: could not set file "
"modification time of '%s': %s",
@@ -13323,6 +13539,8 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
+ if (zmgr->unreachable[i].expire == 0)
+ break;
result = isc_rwlock_tryupgrade(&zmgr->urlock);
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
@@ -13994,7 +14212,7 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
static isc_result_t
sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
- dns_diff_t *diff, dns_diff_t *sig_diff)
+ dns_diff_t *diff, zonediff_t *zonediff)
{
isc_result_t result;
isc_stdtime_t now, inception, soaexpire;
@@ -14034,7 +14252,7 @@ sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
if (tuple == NULL) {
result = del_sigs(zone, db, ver, &zone->origin,
- dns_rdatatype_dnskey, sig_diff,
+ dns_rdatatype_dnskey, zonediff,
zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -14043,7 +14261,7 @@ sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
goto failure;
}
result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
- sig_diff, zone_keys, nkeys, zone->mctx,
+ zonediff->diff, zone_keys, nkeys, zone->mctx,
inception, soaexpire, check_ksk,
keyset_kskonly);
if (result != ISC_R_SUCCESS) {
@@ -14056,7 +14274,7 @@ sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
inception, soaexpire, now, check_ksk,
- keyset_kskonly, sig_diff);
+ keyset_kskonly, zonediff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -14209,7 +14427,8 @@ zone_rekey(dns_zone_t *zone) {
dns_rdataset_t soaset, soasigs, keyset, keysigs;
dns_dnsseckeylist_t dnskeys, keys, rmkeys;
dns_dnsseckey_t *key;
- dns_diff_t diff, sig_diff;
+ dns_diff_t diff, _sig_diff;
+ zonediff_t zonediff;
isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
isc_boolean_t newalg = ISC_FALSE;
isc_boolean_t fullsign;
@@ -14233,8 +14452,9 @@ zone_rekey(dns_zone_t *zone) {
dir = dns_zone_getkeydirectory(zone);
mctx = zone->mctx;
dns_diff_init(mctx, &diff);
- dns_diff_init(mctx, &sig_diff);
- sig_diff.resign = zone->sigresigninginterval;
+ dns_diff_init(mctx, &_sig_diff);
+ _sig_diff.resign = zone->sigresigninginterval;
+ zonediff_init(&zonediff, &_sig_diff);
CHECK(dns_zone_getdb(zone, &db));
CHECK(dns_db_newversion(db, &ver));
@@ -14334,8 +14554,8 @@ zone_rekey(dns_zone_t *zone) {
ISC_TF(newalg || fullsign)));
CHECK(increment_soa_serial(db, ver, &diff, mctx));
CHECK(add_chains(zone, db, ver, &diff));
- CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
- CHECK(zone_journal(zone, &sig_diff, "zone_rekey"));
+ CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
+ CHECK(zone_journal(zone, zonediff.diff, "zone_rekey"));
commit = ISC_TRUE;
}
}
@@ -14425,7 +14645,7 @@ zone_rekey(dns_zone_t *zone) {
* Cause the zone to add/delete NSEC3 chains for the
* deferred NSEC3PARAM changes.
*/
- for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
+ for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link)) {
unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
@@ -14500,7 +14720,7 @@ zone_rekey(dns_zone_t *zone) {
failure:
dns_diff_clear(&diff);
- dns_diff_clear(&sig_diff);
+ dns_diff_clear(&_sig_diff);
clear_keylist(&dnskeys, mctx);
clear_keylist(&keys, mctx);
OpenPOWER on IntegriCloud