summaryrefslogtreecommitdiffstats
path: root/lib/dns/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/zone.c')
-rw-r--r--lib/dns/zone.c124
1 files changed, 63 insertions, 61 deletions
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 61a8170..22870dc 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -429,6 +429,7 @@ struct dns_zonemgr {
isc_ratelimiter_t * rl;
isc_rwlock_t rwlock;
isc_mutex_t iolock;
+ isc_rwlock_t urlock;
/* Locked by rwlock. */
dns_zonelist_t zones;
@@ -446,7 +447,7 @@ struct dns_zonemgr {
dns_iolist_t high;
dns_iolist_t low;
- /* Locked by rwlock. */
+ /* Locked by urlock. */
/* LRU cache */
struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
};
@@ -1676,12 +1677,16 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
LOCK_ZONE(zone);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
- dns_db_currentversion(zone->db, &version);
- result = dns_master_dumpinc2(zone->mctx, zone->db, version,
- &dns_master_style_default,
- zone->masterfile, zone->task, dump_done,
- zone, &zone->dctx, zone->masterformat);
- dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ if (zone->db != NULL) {
+ dns_db_currentversion(zone->db, &version);
+ result = dns_master_dumpinc2(zone->mctx, zone->db, version,
+ &dns_master_style_default,
+ zone->masterfile, zone->task,
+ dump_done, zone, &zone->dctx,
+ zone->masterformat);
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ } else
+ result = ISC_R_CANCELED;
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
UNLOCK_ZONE(zone);
if (result != DNS_R_CONTINUE)
@@ -2695,7 +2700,8 @@ 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)
+{
const char me[] = "set_refreshkeytimer";
isc_stdtime_t then;
isc_time_t timenow, timethen;
@@ -4443,6 +4449,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
/*
* Everything is ok so attach to the zone.
*/
+ zone->curmaster = 0;
zone->masters = new;
zone->mastersok = newok;
zone->masterkeynames = newname;
@@ -8531,6 +8538,14 @@ zone_unload(dns_zone_t *zone) {
REQUIRE(LOCKED_ZONE(zone));
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
+ if (zone->writeio != NULL)
+ zonemgr_cancelio(zone->writeio);
+
+ if (zone->dctx != NULL)
+ dns_dumpctx_cancel(zone->dctx);
+ }
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
zone_detachdb(zone);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
@@ -9245,6 +9260,8 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
TIME_NOW(&now);
+ LOCK_ZONE(zone);
+
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
zone_debuglog(zone, me, 1, "exiting");
exiting = ISC_TRUE;
@@ -9257,9 +9274,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
if (revent->result != ISC_R_SUCCESS) {
if (revent->result == ISC_R_TIMEDOUT &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"refreshing stub: timeout retrying "
" without EDNS master %s (source %s)",
@@ -9301,9 +9316,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
"refreshing stub: rcode (%.*s) retrying "
"without EDNS master %s (source %s)",
(int)rb.used, rcode, master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
goto same_master;
}
@@ -9325,9 +9338,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
master, source);
goto next_master;
}
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
- UNLOCK_ZONE(zone);
goto same_master;
}
@@ -9382,21 +9393,17 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
dns_db_detach(&stub->db);
- if (zone->masterfile != NULL) {
- dns_zone_dump(zone);
- TIME_NOW(&zone->loadtime);
- }
+ if (zone->masterfile != NULL)
+ zone_needdump(zone, 0);
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
isc_interval_set(&i, zone->expire, 0);
DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto free_stub;
next_master:
@@ -9407,7 +9414,6 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
/*
* Skip to next failed / untried master.
@@ -9445,25 +9451,23 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto free_stub;
}
}
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
goto free_stub;
same_master:
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- UNLOCK_ZONE(zone);
ns_query(zone, NULL, stub);
+ UNLOCK_ZONE(zone);
goto done;
free_stub:
+ UNLOCK_ZONE(zone);
stub->magic = 0;
dns_zone_idetach(&stub->zone);
INSIST(stub->db == NULL);
@@ -9494,6 +9498,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
isc_uint32_t serial, oldserial = 0;
unsigned int j;
+ isc_boolean_t do_queue_xfrin = ISC_FALSE;
zone = revent->ev_arg;
INSIST(DNS_ZONE_VALID(zone));
@@ -9502,6 +9507,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
ENTER;
+ TIME_NOW(&now);
+
+ LOCK_ZONE(zone);
+
/*
* if timeout log and next master;
*/
@@ -9509,14 +9518,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
- TIME_NOW(&now);
-
if (revent->result != ISC_R_SUCCESS) {
if (revent->result == ISC_R_TIMEDOUT &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"refresh: timeout retrying without EDNS "
"master %s (source %s)", master, source);
@@ -9536,10 +9541,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
&zone->sourceaddr,
&now))
{
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone,
DNS_ZONEFLG_SOABEFOREAXFR);
- UNLOCK_ZONE(zone);
goto tcp_transfer;
}
dns_zone_log(zone, ISC_LOG_DEBUG(1),
@@ -9586,9 +9589,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"refresh: rcode (%.*s) retrying without "
"EDNS master %s (source %s)",
(int)rb.used, rcode, master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
- UNLOCK_ZONE(zone);
goto same_master;
}
dns_zone_log(zone, ISC_LOG_INFO,
@@ -9614,9 +9615,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"initiating TCP zone xfer "
"for master %s (source %s)",
master, source);
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
- UNLOCK_ZONE(zone);
goto tcp_transfer;
} else {
INSIST(zone->type == dns_zone_stub);
@@ -9627,9 +9626,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
master, source);
goto next_master;
}
- LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
- UNLOCK_ZONE(zone);
goto same_master;
}
}
@@ -9690,6 +9687,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
soacnt, master, source);
goto next_master;
}
+
/*
* Extract serial
*/
@@ -9717,7 +9715,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
serial = soa.serial;
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
- result = dns_zone_getserial2(zone, &oldserial);
+ result = zone_get_from_db(zone, zone->db, NULL, NULL,
+ &oldserial, NULL, NULL, NULL, NULL,
+ NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
zone_debuglog(zone, me, 1, "serial: new %u, old %u",
serial, oldserial);
@@ -9741,11 +9741,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
}
tcp_transfer:
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- UNLOCK_ZONE(zone);
if (zone->type == dns_zone_slave) {
- queue_xfrin(zone);
+ do_queue_xfrin = ISC_TRUE;
} else {
INSIST(zone->type == dns_zone_stub);
ns_query(zone, rdataset, NULL);
@@ -9767,9 +9765,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
&now);
/* Someone removed the file from underneath us! */
if (result == ISC_R_FILENOTFOUND) {
- LOCK_ZONE(zone);
zone_needdump(zone, DNS_DUMP_DELAY);
- UNLOCK_ZONE(zone);
} else if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_ERROR,
"refresh: could not set file "
@@ -9799,7 +9795,6 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
/*
* Skip to next failed / untried master.
@@ -9841,25 +9836,24 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
}
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
zone_settimer(zone, &now);
- UNLOCK_ZONE(zone);
goto detach;
}
requeue:
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
goto detach;
same_master:
if (msg != NULL)
dns_message_destroy(&msg);
isc_event_free(&event);
- LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
queue_soa_query(zone);
- UNLOCK_ZONE(zone);
detach:
+ UNLOCK_ZONE(zone);
+ if (do_queue_xfrin)
+ queue_xfrin(zone);
dns_zone_idetach(&zone);
return;
}
@@ -10217,13 +10211,13 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(LOCKED_ZONE(zone));
REQUIRE((soardataset != NULL && stub == NULL) ||
(soardataset == NULL && stub != NULL));
REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
ENTER;
- LOCK_ZONE(zone);
if (stub == NULL) {
stub = isc_mem_get(zone->mctx, sizeof(*stub));
if (stub == NULL)
@@ -10414,10 +10408,9 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
}
if (message != NULL)
dns_message_destroy(&message);
- unlock:
+ unlock:
if (key != NULL)
dns_tsigkey_detach(&key);
- UNLOCK_ZONE(zone);
return;
}
@@ -12597,15 +12590,22 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
zmgr->transfersin = 10;
zmgr->transfersperns = 2;
+ /* Unreachable lock. */
+ result = isc_rwlock_init(&zmgr->urlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto free_rwlock;
+
/* Create a single task for queueing of SOA queries. */
result = isc_task_create(taskmgr, 1, &zmgr->task);
if (result != ISC_R_SUCCESS)
- goto free_rwlock;
+ goto free_urlock;
+
isc_task_setname(zmgr->task, "zmgr", zmgr);
result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
&zmgr->rl);
if (result != ISC_R_SUCCESS)
goto free_task;
+
/* default to 20 refresh queries / notifies per second. */
isc_interval_set(&interval, 0, 1000000000/2);
result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
@@ -12634,6 +12634,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_ratelimiter_detach(&zmgr->rl);
free_task:
isc_task_detach(&zmgr->task);
+ free_urlock:
+ isc_rwlock_destroy(&zmgr->urlock);
free_rwlock:
isc_rwlock_destroy(&zmgr->rwlock);
free_mem:
@@ -12814,7 +12816,6 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
UNLOCK_ZONE(zone);
}
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
-
}
isc_result_t
@@ -12858,6 +12859,7 @@ zonemgr_free(dns_zonemgr_t *zmgr) {
DESTROYLOCK(&zmgr->iolock);
isc_ratelimiter_detach(&zmgr->rl);
+ isc_rwlock_destroy(&zmgr->urlock);
isc_rwlock_destroy(&zmgr->rwlock);
mctx = zmgr->mctx;
isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
@@ -13270,12 +13272,12 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->rwlock, locktype);
+ RWLOCK(&zmgr->urlock, locktype);
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
if (zmgr->unreachable[i].expire >= seconds &&
isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
- result = isc_rwlock_tryupgrade(&zmgr->rwlock);
+ result = isc_rwlock_tryupgrade(&zmgr->urlock);
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
zmgr->unreachable[i].last = seconds;
@@ -13283,7 +13285,7 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
break;
}
}
- RWUNLOCK(&zmgr->rwlock, locktype);
+ RWUNLOCK(&zmgr->urlock, locktype);
return (ISC_TF(i < UNREACH_CHACHE_SIZE));
}
@@ -13304,11 +13306,11 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
locktype = isc_rwlocktype_read;
- RWLOCK(&zmgr->rwlock, locktype);
+ RWLOCK(&zmgr->urlock, 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);
+ result = isc_rwlock_tryupgrade(&zmgr->urlock);
if (result == ISC_R_SUCCESS) {
locktype = isc_rwlocktype_write;
zmgr->unreachable[i].expire = 0;
@@ -13321,7 +13323,7 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
break;
}
}
- RWUNLOCK(&zmgr->rwlock, locktype);
+ RWUNLOCK(&zmgr->urlock, locktype);
}
void
@@ -13334,7 +13336,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
/* Existing entry? */
if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
@@ -13373,7 +13375,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
zmgr->unreachable[oldest].remote = *remote;
zmgr->unreachable[oldest].local = *local;
}
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
}
void
OpenPOWER on IntegriCloud