diff options
Diffstat (limited to 'contrib/bind9/lib/dns/zone.c')
-rw-r--r-- | contrib/bind9/lib/dns/zone.c | 343 |
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); /* |