summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/zone.c')
-rw-r--r--contrib/bind9/lib/dns/zone.c343
1 files changed, 260 insertions, 83 deletions
diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c
index 9e05684..61a8170 100644
--- a/contrib/bind9/lib/dns/zone.c
+++ b/contrib/bind9/lib/dns/zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012 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,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.582.8.26 2011-08-09 02:34:24 marka Exp $ */
+/* $Id$ */
/*! \file */
@@ -74,6 +74,7 @@
#include <dns/soa.h>
#include <dns/ssu.h>
#include <dns/stats.h>
+#include <dns/time.h>
#include <dns/tsig.h>
#include <dns/xfrin.h>
#include <dns/zone.h>
@@ -136,6 +137,7 @@ typedef struct dns_notify dns_notify_t;
typedef struct dns_stub dns_stub_t;
typedef struct dns_load dns_load_t;
typedef struct dns_forward dns_forward_t;
+typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
typedef struct dns_io dns_io_t;
typedef ISC_LIST(dns_io_t) dns_iolist_t;
typedef struct dns_signing dns_signing_t;
@@ -336,6 +338,11 @@ struct dns_zone {
* whether a rpz radix was needed when last loaded
*/
isc_boolean_t rpz_zone;
+
+ /*%
+ * Outstanding forwarded UPDATE requests.
+ */
+ dns_forwardlist_t forwards;
};
#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
@@ -500,6 +507,7 @@ struct dns_forward {
isc_sockaddr_t addr;
dns_updatecallback_t callback;
void *callback_arg;
+ ISC_LINK(dns_forward_t) link;
};
/*%
@@ -659,10 +667,6 @@ static void zone_saveunique(dns_zone_t *zone, const char *path,
static void zone_maintenance(dns_zone_t *zone);
static void zone_notify(dns_zone_t *zone, isc_time_t *now);
static void dump_done(void *arg, isc_result_t result);
-static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
- isc_sockaddr_t *remote,
- isc_sockaddr_t *local,
- isc_time_t *now);
static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
isc_uint16_t keyid, isc_boolean_t delete);
static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
@@ -851,6 +855,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->privatetype = (dns_rdatatype_t)0xffffU;
zone->added = ISC_FALSE;
zone->rpz_zone = ISC_FALSE;
+ ISC_LIST_INIT(zone->forwards);
zone->magic = ZONE_MAGIC;
@@ -3183,7 +3188,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
for (result = dns_rriterator_first(&rrit);
result == ISC_R_SUCCESS;
result = dns_rriterator_nextrrset(&rrit)) {
- dns_rdataset_t *rdataset;
+ dns_rdataset_t *rdataset = NULL;
dns_name_t *rrname = NULL;
isc_uint32_t ttl;
@@ -3319,7 +3324,11 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
zone->masterfile,
dns_result_totext(result));
} else {
- dns_zone_log(zone, ISC_LOG_ERROR,
+ int level = ISC_LOG_ERROR;
+ if (zone->type == dns_zone_key &&
+ result == ISC_R_FILENOTFOUND)
+ level = ISC_LOG_DEBUG(1);
+ dns_zone_log(zone, level,
"loading from master file %s failed: %s",
zone->masterfile,
dns_result_totext(result));
@@ -3388,9 +3397,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
needdump = ISC_TRUE;
}
- zone->loadtime = loadtime;
-
- dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
/*
* Obtain ns, soa and cname counts for top of zone.
*/
@@ -3635,6 +3642,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
dns_db_issecure(db) ? " (DNSSEC signed)" : "");
+ zone->loadtime = loadtime;
return (result);
cleanup:
@@ -3988,6 +3996,26 @@ dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
UNLOCK_ZONE(source);
}
+isc_result_t
+dns_zone_synckeyzone(dns_zone_t *zone) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+
+ if (zone->type != dns_zone_key)
+ return (DNS_R_BADZONE);
+
+ CHECK(dns_zone_getdb(zone, &db));
+
+ LOCK_ZONE(zone);
+ result = sync_keyzone(zone, db);
+ UNLOCK_ZONE(zone);
+
+ failure:
+ if (db != NULL)
+ dns_db_detach(&db);
+ return (result);
+}
+
static void
zone_iattach(dns_zone_t *source, dns_zone_t **target) {
@@ -4486,8 +4514,6 @@ was_dumping(dns_zone_t *zone) {
return (dumping);
}
-#define MAXZONEKEYS 10
-
static isc_result_t
find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
isc_mem_t *mctx, unsigned int maxkeys,
@@ -4604,11 +4630,10 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned int i;
dns_rdata_rrsig_t rrsig;
isc_boolean_t found, changed;
- isc_stdtime_t warn = 0, maybe = 0;
+ isc_int64_t warn = 0, maybe = 0;
dns_rdataset_init(&rdataset);
@@ -4637,6 +4662,8 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -4648,7 +4675,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
rdataset.ttl, &rdata);
if (incremental)
changed = ISC_TRUE;
- dns_rdata_reset(&rdata);
if (result != ISC_R_SUCCESS)
break;
} else {
@@ -4709,21 +4735,20 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* iff there is a new offline signature.
*/
if (!dst_key_isprivate(keys[i])) {
- if (warn != 0 &&
- warn > rrsig.timeexpire)
- warn = rrsig.timeexpire;
+ isc_int64_t timeexpire =
+ dns_time64_from32(rrsig.timeexpire);
+ if (warn != 0 && warn > timeexpire)
+ warn = timeexpire;
if (rdata.flags & DNS_RDATA_OFFLINE) {
if (maybe == 0 ||
- maybe > rrsig.timeexpire)
- maybe =
- rrsig.timeexpire;
+ maybe > timeexpire)
+ maybe = timeexpire;
break;
}
if (warn == 0)
warn = maybe;
- if (warn == 0 ||
- warn > rrsig.timeexpire)
- warn = rrsig.timeexpire;
+ if (warn == 0 || warn > timeexpire)
+ warn = timeexpire;
result = offline(db, ver, diff, name,
rdataset.ttl, &rdata);
break;
@@ -4744,7 +4769,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, diff,
DNS_DIFFOP_DELRESIGN, name,
rdataset.ttl, &rdata);
- dns_rdata_reset(&rdata);
if (result != ISC_R_SUCCESS)
break;
}
@@ -4755,8 +4779,18 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdataset_disassociate(&rdataset);
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
- if (warn != 0)
- set_key_expiry_warning(zone, warn, now);
+ if (warn > 0) {
+#if defined(STDTIME_ON_32BITS)
+ isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
+ if (warn == stdwarn)
+#endif
+ set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
+#if defined(STDTIME_ON_32BITS)
+ else
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "key expiry warning time out of range");
+#endif
+ }
failure:
if (node != NULL)
dns_db_detachnode(db, &node);
@@ -4869,7 +4903,7 @@ zone_resigninc(dns_zone_t *zone) {
dns_name_t *name;
dns_rdataset_t rdataset;
dns_rdatatype_t covers;
- dst_key_t *zone_keys[MAXZONEKEYS];
+ dst_key_t *zone_keys[DNS_MAXZONEKEYS];
isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
isc_result_t result;
isc_stdtime_t now, inception, soaexpire, expire, stop;
@@ -4903,7 +4937,7 @@ zone_resigninc(dns_zone_t *zone) {
goto failure;
}
- result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
+ result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
zone_keys, &nkeys);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -5761,7 +5795,7 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_rdataset_t rdataset;
dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
dns_nsec3chainlist_t cleanup;
- dst_key_t *zone_keys[MAXZONEKEYS];
+ dst_key_t *zone_keys[DNS_MAXZONEKEYS];
isc_int32_t signatures;
isc_boolean_t check_ksk, keyset_kskonly;
isc_boolean_t delegation;
@@ -5813,7 +5847,7 @@ zone_nsec3chain(dns_zone_t *zone) {
}
result = find_zone_keys(zone, db, version, zone->mctx,
- MAXZONEKEYS, zone_keys, &nkeys);
+ DNS_MAXZONEKEYS, zone_keys, &nkeys);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_nsec3chain:find_zone_keys -> %s\n",
@@ -6592,7 +6626,7 @@ zone_sign(dns_zone_t *zone) {
dns_rdataset_t rdataset;
dns_signing_t *signing, *nextsigning;
dns_signinglist_t cleanup;
- dst_key_t *zone_keys[MAXZONEKEYS];
+ dst_key_t *zone_keys[DNS_MAXZONEKEYS];
isc_int32_t signatures;
isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
isc_boolean_t commit = ISC_FALSE;
@@ -6638,7 +6672,7 @@ zone_sign(dns_zone_t *zone) {
}
result = find_zone_keys(zone, db, version, zone->mctx,
- MAXZONEKEYS, zone_keys, &nkeys);
+ DNS_MAXZONEKEYS, zone_keys, &nkeys);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:find_zone_keys -> %s\n",
@@ -7272,8 +7306,7 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
if (dst_key_alg(dstkey) == sig.algorithm &&
(dst_key_id(dstkey) == sig.keyid ||
- (sig.algorithm != 1 && sig.keyid ==
- ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+ dst_key_rid(dstkey) == sig.keyid)) {
result = dns_dnssec_verify2(keyname,
&kfetch->dnskeyset,
dstkey, ISC_FALSE, mctx, &sigrr,
@@ -7771,6 +7804,7 @@ zone_refreshkeys(dns_zone_t *zone) {
dns_rdata_keydata_t kd;
isc_stdtime_t now;
isc_boolean_t commit = ISC_FALSE;
+ isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
ENTER;
REQUIRE(zone->db != NULL);
@@ -7799,16 +7833,14 @@ zone_refreshkeys(dns_zone_t *zone) {
result == ISC_R_SUCCESS;
result = dns_rriterator_nextrrset(&rrit)) {
isc_stdtime_t timer = 0xffffffff;
+ dns_name_t *name = NULL, *kname = NULL;
+ dns_rdataset_t *kdset = NULL;
dns_keyfetch_t *kfetch;
- dns_rdataset_t *kdset;
- dns_name_t *name = NULL;
isc_uint32_t ttl;
dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
- if (!dns_rdataset_isassociated(kdset))
- continue;
-
- if (kdset->type != dns_rdatatype_keydata)
+ if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
+ !dns_rdataset_isassociated(kdset))
continue;
/*
@@ -7843,15 +7875,19 @@ zone_refreshkeys(dns_zone_t *zone) {
if (timer > now)
continue;
- zone->refreshkeycount++;
-
kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
+ if (kfetch == NULL) {
+ fetch_err = ISC_TRUE;
+ goto failure;
+ }
+
+ zone->refreshkeycount++;
kfetch->zone = zone;
zone->irefs++;
INSIST(zone->irefs != 0);
dns_fixedname_init(&kfetch->name);
- dns_name_dup(name, zone->mctx,
- dns_fixedname_name(&kfetch->name));
+ kname = dns_fixedname_name(&kfetch->name);
+ dns_name_dup(name, zone->mctx, kname);
dns_rdataset_init(&kfetch->dnskeyset);
dns_rdataset_init(&kfetch->dnskeysigset);
dns_rdataset_init(&kfetch->keydataset);
@@ -7860,25 +7896,59 @@ zone_refreshkeys(dns_zone_t *zone) {
dns_db_attach(db, &kfetch->db);
kfetch->fetch = NULL;
- dns_resolver_createfetch(zone->view->resolver,
- dns_fixedname_name(&kfetch->name),
- dns_rdatatype_dnskey,
- NULL, NULL, NULL,
- DNS_FETCHOPT_NOVALIDATE,
- zone->task, keyfetch_done, kfetch,
- &kfetch->dnskeyset,
- &kfetch->dnskeysigset,
- &kfetch->fetch);
+ result = dns_resolver_createfetch(zone->view->resolver,
+ kname, dns_rdatatype_dnskey,
+ NULL, NULL, NULL,
+ DNS_FETCHOPT_NOVALIDATE,
+ zone->task,
+ keyfetch_done, kfetch,
+ &kfetch->dnskeyset,
+ &kfetch->dnskeysigset,
+ &kfetch->fetch);
+ if (result == ISC_R_SUCCESS)
+ fetching = ISC_TRUE;
+ else {
+ zone->refreshkeycount--;
+ zone->irefs--;
+ dns_db_detach(&kfetch->db);
+ dns_rdataset_disassociate(&kfetch->keydataset);
+ dns_name_free(kname, zone->mctx);
+ isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Failed to create fetch for "
+ "DNSKEY update");
+ fetch_err = ISC_TRUE;
+ }
}
if (!ISC_LIST_EMPTY(diff.tuples)) {
CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
- CHECK(zone_journal(zone, &diff, "sync_keyzone"));
+ CHECK(zone_journal(zone, &diff, "zone_refreshkeys"));
commit = ISC_TRUE;
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
zone_needdump(zone, 30);
}
failure:
+ if (fetch_err) {
+ /*
+ * Error during a key fetch; retry in an hour.
+ */
+ isc_time_t timenow, timethen;
+ char timebuf[80];
+
+ TIME_NOW(&timenow);
+ DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
+ zone->refreshkeytime = timethen;
+ zone_settimer(zone, &timenow);
+
+ isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
+ timebuf);
+
+ if (!fetching)
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
+ }
+
UNLOCK_ZONE(zone);
dns_diff_clear(&diff);
@@ -7903,7 +7973,7 @@ zone_maintenance(dns_zone_t *zone) {
* Configuring the view of this zone may have
* failed, for example because the config file
* had a syntax error. In that case, the view
- * adb or resolver, and we had better not try
+ * db or resolver will be NULL, and we had better not try
* to do maintenance on it.
*/
if (zone->view == NULL || zone->view->adb == NULL)
@@ -8435,6 +8505,24 @@ notify_cancel(dns_zone_t *zone) {
}
static void
+forward_cancel(dns_zone_t *zone) {
+ dns_forward_t *forward;
+
+ /*
+ * 'zone' locked by caller.
+ */
+
+ REQUIRE(LOCKED_ZONE(zone));
+
+ for (forward = ISC_LIST_HEAD(zone->forwards);
+ forward != NULL;
+ forward = ISC_LIST_NEXT(forward, link)) {
+ if (forward->request != NULL)
+ dns_request_cancel(forward->request);
+ }
+}
+
+static void
zone_unload(dns_zone_t *zone) {
/*
@@ -9404,7 +9492,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_soa_t soa;
isc_result_t result;
- isc_uint32_t serial, oldserial;
+ isc_uint32_t serial, oldserial = 0;
unsigned int j;
zone = revent->ev_arg;
@@ -9446,7 +9534,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
if (!dns_zonemgr_unreachable(zone->zmgr,
&zone->masteraddr,
&zone->sourceaddr,
- &now)) {
+ &now))
+ {
LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone,
DNS_ZONEFLG_SOABEFOREAXFR);
@@ -9640,7 +9729,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
isc_serial_gt(serial, oldserial)) {
if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
- &zone->sourceaddr, &now)) {
+ &zone->sourceaddr, &now))
+ {
dns_zone_log(zone, ISC_LOG_INFO,
"refresh: skipping %s as master %s "
"(source %s) is unreachable (cached)",
@@ -10344,6 +10434,7 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
REQUIRE(DNS_ZONE_VALID(zone));
INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
INSIST(isc_refcount_current(&zone->erefs) == 0);
+
zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
/*
@@ -10402,6 +10493,8 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
notify_cancel(zone);
+ forward_cancel(zone);
+
if (zone->timer != NULL) {
isc_timer_detach(&zone->timer);
INSIST(zone->irefs > 0);
@@ -10744,6 +10837,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
char fromtext[ISC_SOCKADDR_FORMATSIZE];
int match = 0;
isc_netaddr_t netaddr;
+ isc_sockaddr_t local, remote;
REQUIRE(DNS_ZONE_VALID(zone));
@@ -10894,7 +10988,10 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
return (ISC_R_SUCCESS);
}
zone->notifyfrom = *from;
+ local = zone->masteraddr;
+ remote = zone->sourceaddr;
UNLOCK_ZONE(zone);
+ dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
dns_zone_refresh(zone);
return (ISC_R_SUCCESS);
}
@@ -11916,11 +12013,13 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
* This transfer finishing freed up a transfer quota slot.
* Let any other zones waiting for quota have it.
*/
+ UNLOCK_ZONE(zone);
RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
zone->statelist = NULL;
zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
+ LOCK_ZONE(zone);
/*
* Retry with a different server if necessary.
@@ -12087,7 +12186,8 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
- &zone->sourceaddr, &now)) {
+ &zone->sourceaddr, &now))
+ {
isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
dns_zone_log(zone, ISC_LOG_INFO,
"got_transfer_quota: skipping zone transfer as "
@@ -12227,8 +12327,13 @@ forward_destroy(dns_forward_t *forward) {
dns_request_destroy(&forward->request);
if (forward->msgbuf != NULL)
isc_buffer_free(&forward->msgbuf);
- if (forward->zone != NULL)
+ if (forward->zone != NULL) {
+ LOCK(&forward->zone->lock);
+ if (ISC_LINK_LINKED(forward, link))
+ ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
+ UNLOCK(&forward->zone->lock);
dns_zone_idetach(&forward->zone);
+ }
isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
}
@@ -12238,6 +12343,12 @@ sendtomaster(dns_forward_t *forward) {
isc_sockaddr_t src;
LOCK_ZONE(forward->zone);
+
+ if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
+ UNLOCK_ZONE(forward->zone);
+ return (ISC_R_CANCELED);
+ }
+
if (forward->which >= forward->zone->masterscnt) {
UNLOCK_ZONE(forward->zone);
return (ISC_R_NOMORE);
@@ -12268,6 +12379,11 @@ sendtomaster(dns_forward_t *forward) {
forward->zone->task,
forward_callback, forward,
&forward->request);
+ if (result == ISC_R_SUCCESS) {
+ if (!ISC_LINK_LINKED(forward, link))
+ ISC_LIST_APPEND(forward->zone->forwards, forward, link);
+ }
+
unlock:
UNLOCK_ZONE(forward->zone);
return (result);
@@ -12394,6 +12510,7 @@ dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
forward->mctx = 0;
forward->callback = callback;
forward->callback_arg = callback_arg;
+ ISC_LINK_INIT(forward, link);
forward->magic = FORWARD_MAGIC;
mr = dns_message_getrawmessage(msg);
@@ -12676,6 +12793,8 @@ dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
void
dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
+ dns_zone_t *zone;
+
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
isc_ratelimiter_shutdown(zmgr->rl);
@@ -12684,6 +12803,18 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
isc_task_destroy(&zmgr->task);
if (zmgr->zonetasks != NULL)
isc_taskpool_destroy(&zmgr->zonetasks);
+
+ RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
+ for (zone = ISC_LIST_HEAD(zmgr->zones);
+ zone != NULL;
+ zone = ISC_LIST_NEXT(zone, link))
+ {
+ LOCK_ZONE(zone);
+ forward_cancel(zone);
+ UNLOCK_ZONE(zone);
+ }
+ RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
+
}
isc_result_t
@@ -12827,12 +12958,22 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
isc_event_t *e;
/*
+ * If we are exiting just pretend we got quota so the zone will
+ * be cleaned up in the zone's task context.
+ */
+ LOCK_ZONE(zone);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
+ UNLOCK_ZONE(zone);
+ goto gotquota;
+ }
+
+ /*
* Find any configured information about the server we'd
* like to transfer this zone from.
*/
isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
- (void)dns_peerlist_peerbyaddr(zone->view->peers,
- &masterip, &peer);
+ (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
+ UNLOCK_ZONE(zone);
/*
* Determine the total maximum number of simultaneous
@@ -12856,7 +12997,11 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
x = ISC_LIST_NEXT(x, statelink))
{
isc_netaddr_t xip;
+
+ LOCK_ZONE(x);
isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
+ UNLOCK_ZONE(x);
+
nxfrsin++;
if (isc_netaddr_equal(&xip, &masterip))
nxfrsperns++;
@@ -12869,15 +13014,14 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
if (nxfrsperns >= maxtransfersperns)
return (ISC_R_QUOTA);
+ gotquota:
/*
* We have sufficient quota. Move the zone to the "xfrin_in_progress"
* list and send it an event to let it start the actual transfer in the
* context of its own task.
*/
- e = isc_event_allocate(zmgr->mctx, zmgr,
- DNS_EVENT_ZONESTARTXFRIN,
- got_transfer_quota, zone,
- sizeof(isc_event_t));
+ e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
+ got_transfer_quota, zone, sizeof(isc_event_t));
if (e == NULL)
return (ISC_R_NOMEMORY);
@@ -13049,8 +13193,9 @@ zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
if (result != ISC_R_SUCCESS)
goto cleanup;
- dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
- path, buf);
+ dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
+ "renaming file to '%s' for failure analysis and "
+ "retransferring.", path, buf);
cleanup:
isc_mem_put(zone->mctx, buf, buflen);
@@ -13113,7 +13258,7 @@ dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
return (zmgr->serialqueryrate);
}
-static isc_boolean_t
+isc_boolean_t
dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
isc_sockaddr_t *local, isc_time_t *now)
{
@@ -13143,6 +13288,43 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
}
void
+dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
+ isc_sockaddr_t *local)
+{
+ unsigned int i;
+ isc_rwlocktype_t locktype;
+ isc_result_t result;
+
+ char master[ISC_SOCKADDR_FORMATSIZE];
+ char source[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(remote, master, sizeof(master));
+ isc_sockaddr_format(local, source, sizeof(source));
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ locktype = isc_rwlocktype_read;
+ RWLOCK(&zmgr->rwlock, locktype);
+ 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)) {
+ result = isc_rwlock_tryupgrade(&zmgr->rwlock);
+ if (result == ISC_R_SUCCESS) {
+ locktype = isc_rwlocktype_write;
+ zmgr->unreachable[i].expire = 0;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
+ "master %s (source %s) deleted "
+ "from unreachable cache",
+ master, source);
+ }
+ break;
+ }
+ }
+ RWUNLOCK(&zmgr->rwlock, locktype);
+}
+
+void
dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
isc_sockaddr_t *local, isc_time_t *now)
{
@@ -13802,11 +13984,11 @@ sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
isc_result_t result;
isc_stdtime_t now, inception, soaexpire;
isc_boolean_t check_ksk, keyset_kskonly;
- dst_key_t *zone_keys[MAXZONEKEYS];
+ dst_key_t *zone_keys[DNS_MAXZONEKEYS];
unsigned int nkeys = 0, i;
dns_difftuple_t *tuple;
- result = find_zone_keys(zone, db, ver, zone->mctx, MAXZONEKEYS,
+ result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
zone_keys, &nkeys);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -14043,6 +14225,9 @@ zone_rekey(dns_zone_t *zone) {
CHECK(dns_db_newversion(db, &ver));
CHECK(dns_db_getoriginnode(db, &node));
+ TIME_NOW(&timenow);
+ now = isc_time_seconds(&timenow);
+
dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
/* Get the SOA record's TTL */
@@ -14092,7 +14277,8 @@ zone_rekey(dns_zone_t *zone) {
goto trylater;
}
- /* See if any pre-existing keys have newly become active;
+ /*
+ * See if any pre-existing keys have newly become active;
* also, see if any new key is for a new algorithm, as in that
* event, we need to sign the zone fully. (If there's a new
* key, but it's for an already-existing algorithm, then
@@ -14142,7 +14328,6 @@ zone_rekey(dns_zone_t *zone) {
dns_db_closeversion(db, &ver, commit);
if (commit) {
- isc_time_t timenow;
dns_difftuple_t *tuple;
LOCK_ZONE(zone);
@@ -14150,7 +14335,6 @@ zone_rekey(dns_zone_t *zone) {
zone_needdump(zone, DNS_DUMP_DELAY);
- TIME_NOW(&timenow);
zone_settimer(zone, &timenow);
/* Remove any signatures from removed keys. */
@@ -14260,13 +14444,6 @@ zone_rekey(dns_zone_t *zone) {
UNLOCK_ZONE(zone);
}
- /*
- * If we are doing automatic key maintenance and the key metadata
- * indicates there is a key change event scheduled in the future,
- * set the key refresh timer.
- */
- isc_stdtime_get(&now);
- TIME_NOW(&timenow);
isc_time_settoepoch(&zone->refreshkeytime);
/*
OpenPOWER on IntegriCloud