1999-09-15 15:11:42 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
1999-09-15 15:11:42 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
|
2019-05-20 16:56:12 +02:00
|
|
|
#include <isc/atomic.h>
|
2005-01-14 03:28:09 +00:00
|
|
|
#include <isc/file.h>
|
1999-10-13 18:19:56 +00:00
|
|
|
#include <isc/magic.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2005-01-14 03:28:09 +00:00
|
|
|
#include <isc/string.h>
|
2011-09-03 19:53:15 +00:00
|
|
|
#include <isc/task.h>
|
1999-12-16 22:24:22 +00:00
|
|
|
#include <isc/util.h>
|
1999-10-13 18:48:32 +00:00
|
|
|
|
2005-01-14 03:28:09 +00:00
|
|
|
#include <dns/log.h>
|
|
|
|
#include <dns/name.h>
|
2000-04-12 21:32:13 +00:00
|
|
|
#include <dns/rbt.h>
|
2005-01-14 03:28:09 +00:00
|
|
|
#include <dns/rdataclass.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/result.h>
|
2005-01-14 03:28:09 +00:00
|
|
|
#include <dns/view.h>
|
2000-01-20 00:45:56 +00:00
|
|
|
#include <dns/zone.h>
|
2000-04-12 21:32:13 +00:00
|
|
|
#include <dns/zt.h>
|
1999-09-15 15:11:42 +00:00
|
|
|
|
2018-07-10 18:43:55 +02:00
|
|
|
struct zt_load_params {
|
|
|
|
dns_zt_zoneloaded_t dl;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool newonly;
|
2018-07-10 18:43:55 +02:00
|
|
|
};
|
|
|
|
|
1999-09-15 15:11:42 +00:00
|
|
|
struct dns_zt {
|
1999-10-13 18:48:32 +00:00
|
|
|
/* Unlocked. */
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
dns_rdataclass_t rdclass;
|
|
|
|
isc_rwlock_t rwlock;
|
|
|
|
dns_zt_allloaded_t loaddone;
|
|
|
|
void *loaddone_arg;
|
2020-02-12 13:59:18 +01:00
|
|
|
struct zt_load_params *loadparams;
|
2019-05-20 16:56:12 +02:00
|
|
|
|
|
|
|
/* Atomic */
|
2020-02-13 14:44:37 -08:00
|
|
|
atomic_bool flush;
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_refcount_t references;
|
|
|
|
isc_refcount_t loads_pending;
|
2019-05-20 16:56:12 +02:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
/* Locked by lock. */
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_rbt_t *table;
|
1999-09-15 15:11:42 +00:00
|
|
|
};
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
|
2018-07-10 18:43:55 +02:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
auto_detach(void *, void *);
|
2000-05-08 14:38:29 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
|
|
|
load(dns_zone_t *zone, void *uap);
|
1999-09-15 15:11:42 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
|
|
|
asyncload(dns_zone_t *zone, void *callback);
|
2011-09-02 21:15:39 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
|
|
|
freezezones(dns_zone_t *zone, void *uap);
|
2005-01-14 03:28:09 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
|
|
|
doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task);
|
2011-09-02 21:15:39 +00:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
|
|
|
|
dns_zt_t *zt;
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(ztp != NULL && *ztp == NULL);
|
1999-09-15 15:11:42 +00:00
|
|
|
|
2001-11-12 19:05:39 +00:00
|
|
|
zt = isc_mem_get(mctx, sizeof(*zt));
|
1999-09-15 15:11:42 +00:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
zt->table = NULL;
|
2000-05-17 19:45:36 +00:00
|
|
|
result = dns_rbt_create(mctx, auto_detach, zt, &zt->table);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-10-13 18:48:32 +00:00
|
|
|
goto cleanup_zt;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-17 10:00:14 +00:00
|
|
|
|
2021-02-01 15:59:41 +11:00
|
|
|
isc_rwlock_init(&zt->rwlock, 0, 0);
|
2012-06-08 13:52:13 +10:00
|
|
|
zt->mctx = NULL;
|
|
|
|
isc_mem_attach(mctx, &zt->mctx);
|
2019-05-16 18:46:29 +02:00
|
|
|
isc_refcount_init(&zt->references, 1);
|
2019-05-20 16:56:12 +02:00
|
|
|
atomic_init(&zt->flush, false);
|
1999-10-13 18:48:32 +00:00
|
|
|
zt->rdclass = rdclass;
|
|
|
|
zt->magic = ZTMAGIC;
|
2011-09-02 21:15:39 +00:00
|
|
|
zt->loaddone = NULL;
|
|
|
|
zt->loaddone_arg = NULL;
|
2018-07-10 18:43:55 +02:00
|
|
|
zt->loadparams = NULL;
|
2019-05-20 16:56:12 +02:00
|
|
|
isc_refcount_init(&zt->loads_pending, 0);
|
1999-10-13 18:48:32 +00:00
|
|
|
*ztp = zt;
|
1999-09-17 10:00:14 +00:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_zt:
|
2001-11-12 19:05:39 +00:00
|
|
|
isc_mem_put(mctx, zt, sizeof(*zt));
|
1999-09-17 10:00:14 +00:00
|
|
|
|
|
|
|
return (result);
|
1999-09-15 15:11:42 +00:00
|
|
|
}
|
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone) {
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zone_t *dummy = NULL;
|
|
|
|
dns_name_t *name;
|
1999-09-15 15:11:42 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
1999-10-14 00:47:01 +00:00
|
|
|
name = dns_zone_getorigin(zone);
|
1999-10-13 18:48:32 +00:00
|
|
|
|
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
|
|
|
|
|
1999-10-14 00:47:01 +00:00
|
|
|
result = dns_rbt_addname(zt->table, name, zone);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-10-13 18:19:56 +00:00
|
|
|
dns_zone_attach(zone, &dummy);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-17 10:00:14 +00:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
|
|
|
|
|
1999-09-15 15:11:42 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *name;
|
1999-09-15 15:11:42 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
1999-10-14 00:47:01 +00:00
|
|
|
name = dns_zone_getorigin(zone);
|
1999-10-13 18:48:32 +00:00
|
|
|
|
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_write);
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_rbt_deletename(zt->table, name, false);
|
1999-10-13 18:48:32 +00:00
|
|
|
|
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
|
|
|
|
|
1999-09-15 15:11:42 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_zt_find(dns_zt_t *zt, const dns_name_t *name, unsigned int options,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *foundname, dns_zone_t **zonep) {
|
1999-10-13 18:48:32 +00:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zone_t *dummy = NULL;
|
2000-04-19 18:21:24 +00:00
|
|
|
unsigned int rbtoptions = 0;
|
1999-09-15 15:11:42 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((options & DNS_ZTFIND_NOEXACT) != 0) {
|
2000-04-19 18:21:24 +00:00
|
|
|
rbtoptions |= DNS_RBTFIND_NOEXACT;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-04-19 18:21:24 +00:00
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_read);
|
1999-09-17 10:00:14 +00:00
|
|
|
|
2000-04-19 18:21:24 +00:00
|
|
|
result = dns_rbt_findname(zt->table, name, rbtoptions, foundname,
|
2020-02-12 13:59:18 +01:00
|
|
|
(void **)(void *)&dummy);
|
2018-06-28 13:38:39 +02:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
|
|
|
/*
|
|
|
|
* If DNS_ZTFIND_MIRROR is set and the zone which was
|
|
|
|
* determined to be the deepest match for the supplied name is
|
|
|
|
* a mirror zone which is expired or not yet loaded, treat it
|
|
|
|
* as non-existent. This will trigger a fallback to recursion
|
|
|
|
* instead of returning a SERVFAIL.
|
2019-02-07 21:56:59 +01:00
|
|
|
*
|
|
|
|
* Note that currently only the deepest match in the zone table
|
|
|
|
* is checked. Consider a server configured with two mirror
|
|
|
|
* zones: "bar" and its child, "foo.bar". If zone data is
|
|
|
|
* available for "bar" but not for "foo.bar", a query with
|
|
|
|
* QNAME equal to or below "foo.bar" will cause ISC_R_NOTFOUND
|
|
|
|
* to be returned, not DNS_R_PARTIALMATCH, despite zone data
|
|
|
|
* being available for "bar". This is considered to be an edge
|
|
|
|
* case, handling which more appropriately is possible, but
|
|
|
|
* arguably not worth the added complexity.
|
2018-06-28 13:38:39 +02:00
|
|
|
*/
|
|
|
|
if ((options & DNS_ZTFIND_MIRROR) != 0 &&
|
2018-10-09 10:54:51 +02:00
|
|
|
dns_zone_gettype(dummy) == dns_zone_mirror &&
|
2020-02-13 14:44:37 -08:00
|
|
|
!dns_zone_isloaded(dummy))
|
|
|
|
{
|
2018-06-28 13:38:39 +02:00
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
} else {
|
|
|
|
dns_zone_attach(dummy, zonep);
|
|
|
|
}
|
|
|
|
}
|
1999-10-13 18:48:32 +00:00
|
|
|
|
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
|
1999-10-13 18:19:56 +00:00
|
|
|
|
1999-09-15 15:11:42 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-10-13 18:48:32 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) {
|
1999-10-13 18:48:32 +00:00
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
REQUIRE(ztp != NULL && *ztp == NULL);
|
|
|
|
|
2019-05-16 18:46:29 +02:00
|
|
|
isc_refcount_increment(&zt->references);
|
1999-10-13 18:48:32 +00:00
|
|
|
|
|
|
|
*ztp = zt;
|
|
|
|
}
|
|
|
|
|
2000-10-05 06:39:26 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
flush(dns_zone_t *zone, void *uap) {
|
2000-10-05 06:39:26 +00:00
|
|
|
UNUSED(uap);
|
2011-12-10 22:09:41 +00:00
|
|
|
return (dns_zone_flush(zone));
|
2000-10-05 06:39:26 +00:00
|
|
|
}
|
|
|
|
|
2012-06-08 13:52:13 +10:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
zt_destroy(dns_zt_t *zt) {
|
2019-05-20 16:56:12 +02:00
|
|
|
if (atomic_load_acquire(&zt->flush)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
(void)dns_zt_apply(zt, false, NULL, flush, NULL);
|
2019-05-20 16:56:12 +02:00
|
|
|
}
|
2012-06-08 13:52:13 +10:00
|
|
|
dns_rbt_destroy(&zt->table);
|
|
|
|
isc_rwlock_destroy(&zt->rwlock);
|
|
|
|
zt->magic = 0;
|
|
|
|
isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt));
|
|
|
|
}
|
|
|
|
|
2000-10-05 06:39:26 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
zt_flushanddetach(dns_zt_t **ztp, bool need_flush) {
|
1999-09-17 10:00:14 +00:00
|
|
|
dns_zt_t *zt;
|
|
|
|
|
|
|
|
REQUIRE(ztp != NULL && VALID_ZT(*ztp));
|
|
|
|
|
|
|
|
zt = *ztp;
|
2019-05-20 16:56:12 +02:00
|
|
|
*ztp = NULL;
|
|
|
|
|
2019-05-16 18:46:29 +02:00
|
|
|
if (need_flush) {
|
2019-05-20 16:56:12 +02:00
|
|
|
atomic_store_release(&zt->flush, true);
|
2019-05-16 18:46:29 +02:00
|
|
|
}
|
2019-05-20 16:56:12 +02:00
|
|
|
|
2019-05-16 18:46:29 +02:00
|
|
|
if (isc_refcount_decrement(&zt->references) == 1) {
|
2012-06-08 13:52:13 +10:00
|
|
|
zt_destroy(zt);
|
2019-05-16 18:46:29 +02:00
|
|
|
}
|
1999-09-17 10:00:14 +00:00
|
|
|
}
|
|
|
|
|
2000-10-05 06:39:26 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_flushanddetach(dns_zt_t **ztp) {
|
2018-04-17 08:29:14 -07:00
|
|
|
zt_flushanddetach(ztp, true);
|
2000-10-05 06:39:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_detach(dns_zt_t **ztp) {
|
2018-04-17 08:29:14 -07:00
|
|
|
zt_flushanddetach(ztp, false);
|
2000-10-05 06:39:26 +00:00
|
|
|
}
|
|
|
|
|
2000-01-22 01:36:34 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_load(dns_zt_t *zt, bool stop, bool newonly) {
|
|
|
|
isc_result_t result;
|
2018-07-10 18:43:55 +02:00
|
|
|
struct zt_load_params params;
|
2001-02-27 02:54:11 +00:00
|
|
|
REQUIRE(VALID_ZT(zt));
|
2018-07-10 18:43:55 +02:00
|
|
|
params.newonly = newonly;
|
2000-05-17 19:45:36 +00:00
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_read);
|
2018-07-10 18:43:55 +02:00
|
|
|
result = dns_zt_apply(zt, stop, NULL, load, ¶ms);
|
2000-05-17 19:45:36 +00:00
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
|
|
|
|
return (result);
|
1999-10-25 13:34:17 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
load(dns_zone_t *zone, void *paramsv) {
|
|
|
|
isc_result_t result;
|
2020-02-12 13:59:18 +01:00
|
|
|
struct zt_load_params *params = (struct zt_load_params *)paramsv;
|
2018-07-10 18:43:55 +02:00
|
|
|
result = dns_zone_load(zone, params->newonly);
|
|
|
|
if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE ||
|
2020-02-13 14:44:37 -08:00
|
|
|
result == DNS_R_DYNAMIC)
|
|
|
|
{
|
2002-09-10 02:23:46 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2018-07-10 18:43:55 +02:00
|
|
|
}
|
2011-09-02 21:15:39 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2019-12-13 13:58:47 +11:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
call_loaddone(dns_zt_t *zt) {
|
2019-12-13 13:58:47 +11:00
|
|
|
dns_zt_allloaded_t loaddone = zt->loaddone;
|
2020-02-13 14:44:37 -08:00
|
|
|
void *loaddone_arg = zt->loaddone_arg;
|
2019-12-13 13:58:47 +11:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set zt->loaddone, zt->loaddone_arg and zt->loadparams to NULL
|
|
|
|
* before calling loaddone.
|
|
|
|
*/
|
|
|
|
zt->loaddone = NULL;
|
|
|
|
zt->loaddone_arg = NULL;
|
|
|
|
|
|
|
|
isc_mem_put(zt->mctx, zt->loadparams, sizeof(struct zt_load_params));
|
|
|
|
zt->loadparams = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call the callback last.
|
|
|
|
*/
|
|
|
|
if (loaddone != NULL) {
|
|
|
|
loaddone(loaddone_arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 21:15:39 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_zt_asyncload(dns_zt_t *zt, bool newonly, dns_zt_allloaded_t alldone,
|
2020-02-13 14:44:37 -08:00
|
|
|
void *arg) {
|
|
|
|
isc_result_t result;
|
2019-12-13 13:58:47 +11:00
|
|
|
uint_fast32_t loads_pending;
|
2011-09-02 21:15:39 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
2019-12-13 13:58:47 +11:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Obtain a reference to zt->loads_pending so that asyncload can
|
|
|
|
* safely decrement both zt->references and zt->loads_pending
|
|
|
|
* without going to zero.
|
|
|
|
*/
|
|
|
|
loads_pending = isc_refcount_increment0(&zt->loads_pending);
|
|
|
|
INSIST(loads_pending == 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only one dns_zt_asyncload call at a time should be active so
|
|
|
|
* these pointers should be NULL. They are set back to NULL
|
|
|
|
* before the zt->loaddone (alldone) is called in call_loaddone.
|
|
|
|
*/
|
|
|
|
INSIST(zt->loadparams == NULL);
|
|
|
|
INSIST(zt->loaddone == NULL);
|
|
|
|
INSIST(zt->loaddone_arg == NULL);
|
|
|
|
|
2018-07-10 18:43:55 +02:00
|
|
|
zt->loadparams = isc_mem_get(zt->mctx, sizeof(struct zt_load_params));
|
|
|
|
zt->loadparams->dl = doneloading;
|
|
|
|
zt->loadparams->newonly = newonly;
|
2019-12-13 13:58:47 +11:00
|
|
|
zt->loaddone = alldone;
|
|
|
|
zt->loaddone_arg = arg;
|
2019-05-20 16:56:12 +02:00
|
|
|
|
2019-12-13 13:58:47 +11:00
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_read);
|
2018-07-10 18:43:55 +02:00
|
|
|
result = dns_zt_apply(zt, false, NULL, asyncload, zt);
|
2019-12-13 13:58:47 +11:00
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
|
2011-09-02 21:15:39 +00:00
|
|
|
|
2019-12-13 13:58:47 +11:00
|
|
|
/*
|
|
|
|
* Have all the loads completed?
|
|
|
|
*/
|
|
|
|
if (isc_refcount_decrement(&zt->loads_pending) == 1) {
|
|
|
|
call_loaddone(zt);
|
2018-07-10 18:43:55 +02:00
|
|
|
}
|
2011-09-02 21:15:39 +00:00
|
|
|
|
2002-09-10 02:23:46 +00:00
|
|
|
return (result);
|
1999-10-25 13:34:17 +00:00
|
|
|
}
|
|
|
|
|
2011-09-02 21:15:39 +00:00
|
|
|
/*
|
2011-09-02 23:46:33 +00:00
|
|
|
* Initiates asynchronous loading of zone 'zone'. 'callback' is a
|
2011-09-02 21:15:39 +00:00
|
|
|
* pointer to a function which will be used to inform the caller when
|
|
|
|
* the zone loading is complete.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
asyncload(dns_zone_t *zone, void *zt_) {
|
|
|
|
isc_result_t result;
|
2020-02-12 13:59:18 +01:00
|
|
|
struct dns_zt *zt = (dns_zt_t *)zt_;
|
2011-09-02 21:15:39 +00:00
|
|
|
REQUIRE(zone != NULL);
|
2019-05-20 16:56:12 +02:00
|
|
|
|
|
|
|
isc_refcount_increment(&zt->references);
|
|
|
|
isc_refcount_increment(&zt->loads_pending);
|
2015-06-03 18:18:55 -07:00
|
|
|
|
2019-12-13 13:58:47 +11:00
|
|
|
result = dns_zone_asyncload(zone, zt->loadparams->newonly,
|
|
|
|
*zt->loadparams->dl, zt);
|
2015-06-03 18:18:55 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2019-12-13 13:58:47 +11:00
|
|
|
/*
|
|
|
|
* Caller is holding a reference to zt->loads_pending
|
|
|
|
* and zt->references so these can't decrement to zero.
|
|
|
|
*/
|
2019-12-05 13:29:45 +11:00
|
|
|
isc_refcount_decrement1(&zt->references);
|
|
|
|
isc_refcount_decrement1(&zt->loads_pending);
|
2012-06-08 13:52:13 +10:00
|
|
|
}
|
2011-09-02 21:15:39 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2005-01-14 03:28:09 +00:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_freezezones(dns_zt_t *zt, bool freeze) {
|
2005-01-14 03:28:09 +00:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
|
|
|
RWLOCK(&zt->rwlock, isc_rwlocktype_read);
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_zt_apply(zt, false, &tresult, freezezones, &freeze);
|
2005-01-14 03:28:09 +00:00
|
|
|
RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (tresult == ISC_R_NOTFOUND) {
|
2011-09-02 21:15:39 +00:00
|
|
|
tresult = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
return ((result == ISC_R_SUCCESS) ? tresult : result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
freezezones(dns_zone_t *zone, void *uap) {
|
|
|
|
bool freeze = *(bool *)uap;
|
|
|
|
bool frozen;
|
2005-01-14 03:28:09 +00:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
char classstr[DNS_RDATACLASS_FORMATSIZE];
|
|
|
|
char zonename[DNS_NAME_FORMATSIZE];
|
|
|
|
dns_zone_t *raw = NULL;
|
|
|
|
dns_view_t *view;
|
|
|
|
const char *vname;
|
|
|
|
const char *sep;
|
|
|
|
int level;
|
2005-01-14 03:28:09 +00:00
|
|
|
|
2011-12-02 02:44:01 +00:00
|
|
|
dns_zone_getraw(zone, &raw);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (raw != NULL) {
|
2011-12-02 02:44:01 +00:00
|
|
|
zone = raw;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-12-02 02:44:01 +00:00
|
|
|
if (dns_zone_gettype(zone) != dns_zone_master) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (raw != NULL) {
|
2011-12-02 02:44:01 +00:00
|
|
|
dns_zone_detach(&raw);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2011-12-02 02:44:01 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
if (!dns_zone_isdynamic(zone, true)) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (raw != NULL) {
|
2011-12-02 02:44:01 +00:00
|
|
|
dns_zone_detach(&raw);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-03-21 07:22:14 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2011-12-02 02:44:01 +00:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
|
|
|
|
frozen = dns_zone_getupdatedisabled(zone);
|
|
|
|
if (freeze) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (frozen) {
|
2005-01-14 03:28:09 +00:00
|
|
|
result = DNS_R_FROZEN;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2005-01-14 03:28:09 +00:00
|
|
|
result = dns_zone_flush(zone);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2014-10-01 06:59:19 +10:00
|
|
|
dns_zone_setupdatedisabled(zone, freeze);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
} else {
|
|
|
|
if (frozen) {
|
2014-10-01 06:59:19 +10:00
|
|
|
result = dns_zone_loadandthaw(zone);
|
2005-01-14 03:28:09 +00:00
|
|
|
if (result == DNS_R_CONTINUE ||
|
2020-02-13 21:48:23 +01:00
|
|
|
result == DNS_R_UPTODATE) {
|
2005-01-14 03:28:09 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
view = dns_zone_getview(zone);
|
2020-02-12 13:59:18 +01:00
|
|
|
if (strcmp(view->name, "_bind") == 0 || strcmp(view->name, "_defaul"
|
2020-02-13 14:44:37 -08:00
|
|
|
"t") == 0)
|
|
|
|
{
|
2005-01-14 03:28:09 +00:00
|
|
|
vname = "";
|
|
|
|
sep = "";
|
|
|
|
} else {
|
|
|
|
vname = view->name;
|
|
|
|
sep = " ";
|
|
|
|
}
|
|
|
|
dns_rdataclass_format(dns_zone_getclass(zone), classstr,
|
|
|
|
sizeof(classstr));
|
|
|
|
dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
|
|
|
|
level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
|
|
|
|
level, "%s zone '%s/%s'%s%s: %s",
|
2020-02-12 13:59:18 +01:00
|
|
|
freeze ? "freezing" : "thawing", zonename, classstr, sep,
|
|
|
|
vname, isc_result_totext(result));
|
2020-02-13 21:48:23 +01:00
|
|
|
if (raw != NULL) {
|
2011-12-02 02:44:01 +00:00
|
|
|
dns_zone_detach(&raw);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2017-10-04 23:44:08 -07:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_setviewcommit(dns_zt_t *zt) {
|
|
|
|
dns_rbtnode_t *node;
|
2017-10-04 23:44:08 -07:00
|
|
|
dns_rbtnodechain_t chain;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2017-10-04 23:44:08 -07:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
2019-08-27 22:41:18 -07:00
|
|
|
dns_rbtnodechain_init(&chain);
|
2017-10-04 23:44:08 -07:00
|
|
|
|
|
|
|
result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
|
|
|
|
while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_rbtnodechain_current(&chain, NULL, NULL, &node);
|
2017-10-04 23:44:08 -07:00
|
|
|
if (result == ISC_R_SUCCESS && node->data != NULL) {
|
|
|
|
dns_zone_setviewcommit(node->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rbtnodechain_invalidate(&chain);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_zt_setviewrevert(dns_zt_t *zt) {
|
|
|
|
dns_rbtnode_t *node;
|
2017-10-04 23:44:08 -07:00
|
|
|
dns_rbtnodechain_t chain;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2017-10-04 23:44:08 -07:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
2019-08-27 22:41:18 -07:00
|
|
|
dns_rbtnodechain_init(&chain);
|
2017-10-04 23:44:08 -07:00
|
|
|
|
|
|
|
result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
|
|
|
|
while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_rbtnodechain_current(&chain, NULL, NULL, &node);
|
2017-10-04 23:44:08 -07:00
|
|
|
if (result == ISC_R_SUCCESS && node->data != NULL) {
|
|
|
|
dns_zone_setviewrevert(node->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rbtnodechain_invalidate(&chain);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_zt_apply(dns_zt_t *zt, bool stop, isc_result_t *sub,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t (*action)(dns_zone_t *, void *), void *uap) {
|
|
|
|
dns_rbtnode_t *node;
|
1999-10-13 18:19:56 +00:00
|
|
|
dns_rbtnodechain_t chain;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result, tresult = ISC_R_SUCCESS;
|
|
|
|
dns_zone_t *zone;
|
1999-10-13 18:19:56 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
1999-10-25 13:34:17 +00:00
|
|
|
REQUIRE(action != NULL);
|
1999-10-13 18:19:56 +00:00
|
|
|
|
2019-08-27 22:41:18 -07:00
|
|
|
dns_rbtnodechain_init(&chain);
|
1999-10-13 18:19:56 +00:00
|
|
|
result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2000-01-24 19:11:21 +00:00
|
|
|
/*
|
|
|
|
* The tree is empty.
|
|
|
|
*/
|
2011-09-02 21:15:39 +00:00
|
|
|
tresult = result;
|
2000-08-01 01:33:37 +00:00
|
|
|
result = ISC_R_NOMORE;
|
2000-01-24 19:11:21 +00:00
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_rbtnodechain_current(&chain, NULL, NULL, &node);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-10-13 18:19:56 +00:00
|
|
|
zone = node->data;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (zone != NULL) {
|
1999-10-26 02:29:49 +00:00
|
|
|
result = (action)(zone, uap);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-01-14 03:28:09 +00:00
|
|
|
if (result != ISC_R_SUCCESS && stop) {
|
|
|
|
tresult = result;
|
2020-02-12 13:59:18 +01:00
|
|
|
goto cleanup; /* don't break */
|
2005-01-14 03:28:09 +00:00
|
|
|
} else if (result != ISC_R_SUCCESS &&
|
2020-02-13 21:48:23 +01:00
|
|
|
tresult == ISC_R_SUCCESS) {
|
2005-01-14 03:28:09 +00:00
|
|
|
tresult = result;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 18:19:56 +00:00
|
|
|
}
|
|
|
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_NOMORE) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-26 02:29:49 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup:
|
1999-10-13 18:19:56 +00:00
|
|
|
dns_rbtnodechain_invalidate(&chain);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (sub != NULL) {
|
2005-01-14 03:28:09 +00:00
|
|
|
*sub = tresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 18:48:32 +00:00
|
|
|
|
1999-10-26 02:29:49 +00:00
|
|
|
return (result);
|
1999-10-13 18:19:56 +00:00
|
|
|
}
|
|
|
|
|
2011-09-02 21:15:39 +00:00
|
|
|
/*
|
|
|
|
* Decrement the loads_pending counter; when counter reaches
|
|
|
|
* zero, call the loaddone callback that was initially set by
|
|
|
|
* dns_zt_asyncload().
|
|
|
|
*/
|
2011-09-05 06:27:05 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) {
|
2011-09-02 21:15:39 +00:00
|
|
|
UNUSED(zone);
|
2011-09-03 19:53:15 +00:00
|
|
|
UNUSED(task);
|
2011-09-02 21:15:39 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_ZT(zt));
|
|
|
|
|
2019-05-20 16:56:12 +02:00
|
|
|
if (isc_refcount_decrement(&zt->loads_pending) == 1) {
|
2019-12-13 13:58:47 +11:00
|
|
|
call_loaddone(zt);
|
2011-09-02 21:15:39 +00:00
|
|
|
}
|
2011-09-05 03:45:22 +00:00
|
|
|
|
2019-05-20 16:56:12 +02:00
|
|
|
if (isc_refcount_decrement(&zt->references) == 1) {
|
2012-06-08 13:52:13 +10:00
|
|
|
zt_destroy(zt);
|
2019-05-20 16:56:12 +02:00
|
|
|
}
|
2012-06-08 13:52:13 +10:00
|
|
|
|
2011-09-05 03:45:22 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2011-09-02 21:15:39 +00:00
|
|
|
}
|
|
|
|
|
1999-10-13 18:19:56 +00:00
|
|
|
/***
|
|
|
|
*** Private
|
|
|
|
***/
|
|
|
|
|
1999-09-15 15:11:42 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
auto_detach(void *data, void *arg) {
|
1999-10-13 18:48:32 +00:00
|
|
|
dns_zone_t *zone = data;
|
1999-09-15 15:11:42 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
UNUSED(arg);
|
1999-10-13 18:48:32 +00:00
|
|
|
dns_zone_detach(&zone);
|
1999-09-15 15:11:42 +00:00
|
|
|
}
|