2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-05-26 12:36:17 -07:00
|
|
|
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
|
2016-05-26 21:23:19 +02:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*! \file */
|
|
|
|
|
2016-05-26 12:36:17 -07:00
|
|
|
#include <config.h>
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
#include <isc/hex.h>
|
|
|
|
#include <isc/mem.h>
|
2016-05-26 12:36:17 -07:00
|
|
|
#include <isc/parseint.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
#include <isc/result.h>
|
2016-05-26 12:36:17 -07:00
|
|
|
#include <isc/sha2.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
#include <isc/task.h>
|
|
|
|
|
|
|
|
#include <dns/catz.h>
|
|
|
|
#include <dns/dbiterator.h>
|
|
|
|
#include <dns/events.h>
|
|
|
|
#include <dns/rdatasetiter.h>
|
|
|
|
#include <dns/view.h>
|
|
|
|
#include <dns/zone.h>
|
2016-05-26 12:36:17 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/*%
|
|
|
|
* Single member zone in a catalog
|
|
|
|
*/
|
|
|
|
struct dns_catz_entry {
|
|
|
|
dns_name_t name;
|
|
|
|
dns_catz_options_t opts;
|
|
|
|
isc_refcount_t refs;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Catalog zone
|
|
|
|
*/
|
|
|
|
struct dns_catz_zone {
|
|
|
|
dns_name_t name;
|
|
|
|
dns_catz_zones_t *catzs;
|
|
|
|
dns_rdata_t soa;
|
|
|
|
/* key in entries is 'mhash', not domain name! */
|
|
|
|
isc_ht_t *entries;
|
|
|
|
/*
|
|
|
|
* defoptions are taken from named.conf
|
|
|
|
* zoneoptions are global options from zone
|
|
|
|
*/
|
|
|
|
dns_catz_options_t defoptions;
|
|
|
|
dns_catz_options_t zoneoptions;
|
|
|
|
isc_time_t lastupdated;
|
|
|
|
isc_boolean_t updatepending;
|
|
|
|
isc_uint32_t version;
|
|
|
|
|
|
|
|
dns_db_t *db;
|
|
|
|
dns_dbversion_t *dbversion;
|
|
|
|
|
|
|
|
isc_timer_t *updatetimer;
|
|
|
|
isc_event_t updateevent;
|
|
|
|
|
|
|
|
isc_boolean_t active;
|
|
|
|
|
|
|
|
isc_refcount_t refs;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Collection of catalog zones for a view
|
|
|
|
*/
|
|
|
|
struct dns_catz_zones {
|
|
|
|
isc_ht_t *zones;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_refcount_t refs;
|
|
|
|
isc_mutex_t lock;
|
|
|
|
dns_catz_zonemodmethods_t *zmm;
|
|
|
|
isc_taskmgr_t *taskmgr;
|
|
|
|
isc_timermgr_t *timermgr;
|
|
|
|
dns_view_t *view;
|
|
|
|
isc_task_t *updater;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_options_init(dns_catz_options_t *options) {
|
|
|
|
options->masters.addrs = NULL;
|
|
|
|
options->masters.dscps = NULL;
|
|
|
|
options->masters.keys = NULL;
|
|
|
|
options->masters.count = 0;
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
options->allow_query = NULL;
|
|
|
|
options->allow_transfer = NULL;
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
options->in_memory = ISC_FALSE;
|
|
|
|
options->min_update_interval = 5;
|
2016-05-31 10:36:27 -07:00
|
|
|
options->zonedir = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_options_free(dns_catz_options_t *options, isc_mem_t *mctx) {
|
2016-05-31 23:01:53 +02:00
|
|
|
if (options->masters.count != 0)
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_ipkeylist_clear(mctx, &options->masters);
|
2016-05-31 10:36:27 -07:00
|
|
|
if (options->zonedir != NULL) {
|
|
|
|
isc_mem_free(mctx, options->zonedir);
|
|
|
|
options->zonedir = NULL;
|
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
if (options->allow_query != NULL)
|
|
|
|
isc_buffer_free(&options->allow_query);
|
|
|
|
if (options->allow_transfer != NULL)
|
|
|
|
isc_buffer_free(&options->allow_transfer);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *src,
|
|
|
|
dns_catz_options_t *dst)
|
|
|
|
{
|
|
|
|
/* TODO error handling */
|
|
|
|
REQUIRE(dst != NULL);
|
|
|
|
REQUIRE(dst->masters.count == 0);
|
2016-06-20 13:39:44 +02:00
|
|
|
REQUIRE(dst->allow_query == NULL);
|
|
|
|
REQUIRE(dst->allow_transfer == NULL);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 10:36:27 -07:00
|
|
|
if (src->masters.count != 0)
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_ipkeylist_copy(mctx, &src->masters, &dst->masters);
|
2016-05-31 10:36:27 -07:00
|
|
|
|
|
|
|
if (dst->zonedir != NULL) {
|
|
|
|
isc_mem_free(mctx, dst->zonedir);
|
|
|
|
dst->zonedir = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 10:36:27 -07:00
|
|
|
if (src->zonedir != NULL)
|
|
|
|
dst->zonedir = isc_mem_strdup(mctx, src->zonedir);
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
if (src->allow_query != NULL)
|
|
|
|
isc_buffer_dup(mctx, &dst->allow_query, src->allow_query);
|
|
|
|
|
|
|
|
if (src->allow_transfer != NULL)
|
|
|
|
isc_buffer_dup(mctx, &dst->allow_transfer, src->allow_transfer);
|
|
|
|
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults,
|
|
|
|
dns_catz_options_t *opts)
|
|
|
|
{
|
2016-06-20 13:39:44 +02:00
|
|
|
if (opts->masters.count == 0 && defaults->masters.count != 0)
|
|
|
|
dns_ipkeylist_copy(mctx, &defaults->masters, &opts->masters);
|
|
|
|
|
|
|
|
if (defaults->zonedir != NULL)
|
2016-05-31 10:36:27 -07:00
|
|
|
opts->zonedir = isc_mem_strdup(mctx, defaults->zonedir);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
if (opts->allow_query == NULL && defaults->allow_query != NULL)
|
|
|
|
isc_buffer_dup(mctx, &opts->allow_query, defaults->allow_query);
|
|
|
|
if (opts->allow_transfer == NULL && defaults->allow_transfer != NULL)
|
|
|
|
isc_buffer_dup(mctx, &opts->allow_transfer,
|
|
|
|
defaults->allow_transfer);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/* This option is always taken from config, so it's always 'default' */
|
|
|
|
opts->in_memory = defaults->in_memory;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain,
|
|
|
|
dns_catz_entry_t **nentryp)
|
|
|
|
{
|
|
|
|
dns_catz_entry_t *nentry;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(nentryp != NULL && *nentryp == NULL);
|
|
|
|
REQUIRE(domain != NULL);
|
|
|
|
|
|
|
|
nentry = isc_mem_get(mctx, sizeof(dns_catz_entry_t));
|
|
|
|
if (nentry == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
|
|
|
dns_name_init(&nentry->name, NULL);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_dup(domain, mctx, &nentry->name);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
dns_catz_options_init(&nentry->opts);
|
|
|
|
isc_refcount_init(&nentry->refs, 1);
|
|
|
|
*nentryp = nentry;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
isc_mem_put(mctx, nentry, sizeof(dns_catz_entry_t));
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_t *
|
|
|
|
dns_catz_entry_getname(dns_catz_entry_t *entry) {
|
|
|
|
return (&entry->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry,
|
|
|
|
dns_catz_entry_t **nentryp)
|
|
|
|
{
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_t *nentry = NULL;
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_entry_new(zone->catzs->mctx, &entry->name, &nentry);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_options_copy(zone->catzs->mctx, &entry->opts,
|
|
|
|
&nentry->opts);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_detach(zone, &nentry);
|
|
|
|
|
|
|
|
*nentryp = nentry;
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp) {
|
|
|
|
REQUIRE(entryp != NULL && *entryp == NULL);
|
|
|
|
isc_refcount_increment(&entry->refs, NULL);
|
|
|
|
*entryp = entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp) {
|
|
|
|
dns_catz_entry_t *entry;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
unsigned int refs;
|
|
|
|
|
|
|
|
REQUIRE(entryp != NULL && *entryp != NULL);
|
|
|
|
|
|
|
|
entry = *entryp;
|
|
|
|
*entryp = NULL;
|
|
|
|
|
|
|
|
mctx = zone->catzs->mctx;
|
|
|
|
|
|
|
|
isc_refcount_decrement(&entry->refs, &refs);
|
|
|
|
if (refs == 0) {
|
|
|
|
dns_catz_options_free(&entry->opts, mctx);
|
|
|
|
dns_name_free(&entry->name, mctx);
|
|
|
|
isc_refcount_destroy(&entry->refs);
|
|
|
|
isc_mem_put(mctx, entry, sizeof(dns_catz_entry_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_boolean_t
|
|
|
|
dns_catz_entry_validate(const dns_catz_entry_t *entry) {
|
|
|
|
UNUSED(entry);
|
|
|
|
|
|
|
|
return (ISC_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_boolean_t
|
|
|
|
dns_catz_entry_cmp(const dns_catz_entry_t *ea, const dns_catz_entry_t *eb) {
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_region_t ra, rb;
|
2016-05-26 21:23:19 +02:00
|
|
|
if (ea->opts.masters.count != eb->opts.masters.count)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
if (memcmp(ea->opts.masters.addrs, eb->opts.masters.addrs,
|
|
|
|
ea->opts.masters.count * sizeof(isc_sockaddr_t)))
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
/* If one is NULL and the other isn't, the entries don't match */
|
|
|
|
if ((ea->opts.allow_query == NULL) !=
|
|
|
|
(eb->opts.allow_query == NULL))
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
/* If one is non-NULL, then they both are */
|
|
|
|
if (ea->opts.allow_query != NULL) {
|
|
|
|
isc_buffer_usedregion(ea->opts.allow_query, &ra);
|
|
|
|
isc_buffer_usedregion(eb->opts.allow_query, &rb);
|
|
|
|
if (isc_region_compare(&ra, &rb))
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Repeat the above checks with allow_transfer */
|
|
|
|
if ((ea->opts.allow_transfer == NULL) !=
|
|
|
|
(eb->opts.allow_transfer == NULL))
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
if (ea->opts.allow_transfer != NULL) {
|
|
|
|
isc_buffer_usedregion(ea->opts.allow_transfer, &ra);
|
|
|
|
isc_buffer_usedregion(eb->opts.allow_transfer, &rb);
|
|
|
|
if (isc_region_compare(&ra, &rb))
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/* xxxwpk TODO compare dscps/keys! */
|
|
|
|
return (ISC_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_t *
|
|
|
|
dns_catz_zone_getname(dns_catz_zone_t *zone) {
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
return (&zone->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_options_t *
|
|
|
|
dns_catz_zone_getdefoptions(dns_catz_zone_t *zone) {
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
return (&zone->defoptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_zone_resetdefoptions(dns_catz_zone_t *zone) {
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
dns_catz_options_free(&zone->defoptions, zone->catzs->mctx);
|
|
|
|
dns_catz_options_init(&zone->defoptions);
|
|
|
|
}
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_result_t
|
|
|
|
dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_result_t result;
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
char cznamebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
char znamebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
isc_buffer_t czname;
|
|
|
|
isc_buffer_t zname;
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zoneop_fn_t addzone, modzone, delzone;
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(newzone != NULL);
|
|
|
|
|
|
|
|
/* TODO verify the new zone first! */
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
addzone = target->catzs->zmm->addzone;
|
|
|
|
modzone = target->catzs->zmm->modzone;
|
|
|
|
delzone = target->catzs->zmm->delzone;
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
/* Copy zoneoptions from newzone into target. */
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_free(&target->zoneoptions, target->catzs->mctx);
|
|
|
|
dns_catz_options_copy(target->catzs->mctx, &newzone->zoneoptions,
|
|
|
|
&target->zoneoptions);
|
|
|
|
dns_catz_options_setdefault(target->catzs->mctx, &target->defoptions,
|
|
|
|
&target->zoneoptions);
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_buffer_init(&czname, cznamebuf, DNS_NAME_FORMATSIZE);
|
|
|
|
isc_buffer_init(&zname, znamebuf, DNS_NAME_FORMATSIZE);
|
|
|
|
dns_name_totext(&target->name, ISC_TRUE, &czname);
|
|
|
|
isc_buffer_putuint8(&czname, 0);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
|
|
|
* first - walk the new zone and find all nodes that are not in the
|
|
|
|
* old zone, or are in both zones and are modified
|
|
|
|
*/
|
2016-05-31 23:01:53 +02:00
|
|
|
result = isc_ht_iter_create(newzone->entries, &iter);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
result = isc_ht_iter_first(iter);
|
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_next(iter))
|
|
|
|
{
|
|
|
|
dns_catz_entry_t *nentry;
|
|
|
|
dns_catz_entry_t *oentry;
|
|
|
|
unsigned char * key;
|
|
|
|
size_t keysize;
|
|
|
|
|
|
|
|
isc_ht_iter_current(iter, (void **) &nentry);
|
|
|
|
isc_ht_iter_currentkey(iter, &key, &keysize);
|
|
|
|
|
|
|
|
isc_buffer_clear(&zname);
|
|
|
|
dns_name_totext(&nentry->name, ISC_TRUE, &zname);
|
|
|
|
isc_buffer_putuint8(&zname, 0);
|
|
|
|
|
|
|
|
dns_catz_options_setdefault(target->catzs->mctx,
|
|
|
|
&target->zoneoptions,
|
|
|
|
&nentry->opts);
|
|
|
|
|
|
|
|
result = isc_ht_find(target->entries, key, keysize,
|
|
|
|
(void **) &oentry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = addzone(nentry, target, target->catzs->view,
|
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->catzs->zmm->udata);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: adding zone '%s' from catalog "
|
|
|
|
"'%s' - %s",
|
|
|
|
znamebuf, cznamebuf,
|
|
|
|
isc_result_totext(result));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dns_catz_entry_cmp(oentry, nentry) != ISC_TRUE) {
|
|
|
|
result = modzone(nentry, target, target->catzs->view,
|
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->catzs->zmm->udata);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: modifying zone '%s' from catalog "
|
|
|
|
"'%s' - %s",
|
|
|
|
znamebuf, cznamebuf,
|
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_entry_detach(target, &oentry);
|
|
|
|
result = isc_ht_delete(target->entries, key, keysize);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* then - walk the old zone; only deleted entries should remain
|
|
|
|
*/
|
2016-05-31 23:01:53 +02:00
|
|
|
result = isc_ht_iter_create(target->entries, &iter);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
|
|
|
dns_catz_entry_t *entry;
|
|
|
|
isc_ht_iter_current(iter, (void **) &entry);
|
|
|
|
|
|
|
|
isc_buffer_clear(&zname);
|
|
|
|
dns_name_totext(&entry->name, ISC_TRUE, &zname);
|
|
|
|
isc_buffer_putuint8(&zname, 0);
|
|
|
|
result = delzone(entry, target, target->catzs->view,
|
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->catzs->zmm->udata);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: deleting zone '%s' from catalog '%s' - %s",
|
|
|
|
znamebuf, cznamebuf, isc_result_totext(result));
|
|
|
|
dns_catz_entry_detach(target, &entry);
|
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/* at this moment target->entries has to be be empty */
|
|
|
|
INSIST(isc_ht_count(target->entries) == 0);
|
|
|
|
isc_ht_destroy(&target->entries);
|
|
|
|
|
|
|
|
target->entries = newzone->entries;
|
|
|
|
newzone->entries = NULL;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
|
|
|
|
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
|
|
|
isc_timermgr_t *timermgr)
|
|
|
|
{
|
|
|
|
dns_catz_zones_t *new_zones;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
|
|
|
REQUIRE(zmm != NULL);
|
|
|
|
|
|
|
|
new_zones = isc_mem_get(mctx, sizeof(*new_zones));
|
|
|
|
if (new_zones == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
memset(new_zones, 0, sizeof(*new_zones));
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_mutex_init(&new_zones->lock);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_newzones;
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
result = isc_refcount_init(&new_zones->refs, 1);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_mutex;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
result = isc_ht_init(&new_zones->zones, mctx, 4);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_refcount;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_mem_attach(mctx, &new_zones->mctx);
|
|
|
|
new_zones->zmm = zmm;
|
|
|
|
new_zones->timermgr = timermgr;
|
2016-05-31 08:12:51 +10:00
|
|
|
new_zones->taskmgr = taskmgr;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_task_create(taskmgr, 0, &new_zones->updater);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_ht;
|
|
|
|
|
|
|
|
*catzsp = new_zones;
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
|
|
|
cleanup_ht:
|
|
|
|
isc_ht_destroy(&new_zones->zones);
|
|
|
|
cleanup_refcount:
|
|
|
|
isc_refcount_destroy(&new_zones->refs);
|
|
|
|
cleanup_mutex:
|
|
|
|
isc_mutex_destroy(&new_zones->lock);
|
|
|
|
cleanup_newzones:
|
|
|
|
isc_mem_put(mctx, new_zones, sizeof(*new_zones));
|
|
|
|
|
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view) {
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
REQUIRE(view != NULL);
|
|
|
|
/* either it's a new one or it's being reconfigured */
|
|
|
|
REQUIRE(catzs->view == NULL || !strcmp(catzs->view->name, view->name));
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
catzs->view = view;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
|
|
|
const dns_name_t *name) {
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_t *new_zone;
|
|
|
|
|
|
|
|
REQUIRE(zonep != NULL && *zonep == NULL);
|
|
|
|
|
|
|
|
new_zone = isc_mem_get(catzs->mctx, sizeof(*new_zone));
|
2016-05-31 08:12:51 +10:00
|
|
|
if (new_zone == NULL)
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
|
|
|
memset(new_zone, 0, sizeof(*new_zone));
|
|
|
|
|
|
|
|
dns_name_init(&new_zone->name, NULL);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_dup(name, catzs->mctx, &new_zone->name);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_newzone;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_init(&new_zone->entries, catzs->mctx, 4);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_name;
|
|
|
|
|
|
|
|
new_zone->updatetimer = NULL;
|
|
|
|
result = isc_timer_create(catzs->timermgr, isc_timertype_inactive,
|
2016-05-30 23:45:27 +00:00
|
|
|
NULL, NULL, catzs->updater,
|
|
|
|
dns_catz_update_taskaction,
|
|
|
|
new_zone, &new_zone->updatetimer);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup_ht;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_time_settoepoch(&new_zone->lastupdated);
|
|
|
|
new_zone->updatepending = ISC_FALSE;
|
|
|
|
new_zone->db = NULL;
|
|
|
|
new_zone->dbversion = NULL;
|
|
|
|
new_zone->catzs = catzs;
|
|
|
|
dns_catz_options_init(&new_zone->defoptions);
|
|
|
|
dns_catz_options_init(&new_zone->zoneoptions);
|
|
|
|
new_zone->active = ISC_TRUE;
|
|
|
|
new_zone->version = (isc_uint32_t)(-1);
|
|
|
|
isc_refcount_init(&new_zone->refs, 1);
|
|
|
|
|
|
|
|
*zonep = new_zone;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
|
|
|
cleanup_ht:
|
|
|
|
isc_ht_destroy(&new_zone->entries);
|
|
|
|
cleanup_name:
|
|
|
|
dns_name_free(&new_zone->name, catzs->mctx);
|
|
|
|
cleanup_newzone:
|
|
|
|
isc_mem_put(catzs->mctx, new_zone, sizeof(*new_zone));
|
|
|
|
|
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name,
|
|
|
|
dns_catz_zone_t **zonep)
|
|
|
|
{
|
|
|
|
dns_catz_zone_t *new_zone = NULL;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
REQUIRE(name != NULL);
|
|
|
|
REQUIRE(zonep != NULL && *zonep == NULL);
|
|
|
|
|
|
|
|
LOCK(&catzs->lock);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_new_zone(catzs, &new_zone, name);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_add(catzs->zones, new_zone->name.ndata,
|
|
|
|
new_zone->name.length, new_zone);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_detach(&new_zone);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_EXISTS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result == ISC_R_EXISTS) {
|
|
|
|
result = isc_ht_find(catzs->zones, name->ndata,
|
2016-05-26 21:23:19 +02:00
|
|
|
name->length, (void **) &new_zone);
|
2016-05-31 08:12:51 +10:00
|
|
|
INSIST(result == ISC_R_SUCCESS && !new_zone->active);
|
2016-05-26 21:23:19 +02:00
|
|
|
new_zone->active = ISC_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*zonep = new_zone;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
UNLOCK(&catzs->lock);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_zone_t *
|
|
|
|
dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_catz_zone_t *found;
|
|
|
|
|
|
|
|
result = isc_ht_find(catzs->zones, name->ndata, name->length,
|
|
|
|
(void **) &found);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
return (found);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp) {
|
|
|
|
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
|
|
|
|
|
|
|
isc_refcount_increment(&catzs->refs, NULL);
|
|
|
|
*catzsp = catzs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep) {
|
|
|
|
REQUIRE(zonep != NULL && *zonep == NULL);
|
|
|
|
isc_refcount_increment(&zone->refs, NULL);
|
|
|
|
*zonep = zone;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_zone_detach(dns_catz_zone_t **zonep) {
|
|
|
|
dns_catz_zone_t *zone;
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
unsigned int refs;
|
|
|
|
|
|
|
|
REQUIRE(zonep != NULL && *zonep != NULL);
|
|
|
|
|
|
|
|
zone = *zonep;
|
|
|
|
*zonep = NULL;
|
|
|
|
isc_refcount_decrement(&zone->refs, &refs);
|
|
|
|
if (refs == 0) {
|
|
|
|
if (zone->entries != NULL) {
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
result = isc_ht_iter_create(zone->entries, &iter);
|
2016-05-31 08:12:51 +10:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2016-05-31 23:01:53 +02:00
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
|
|
|
dns_catz_entry_t *entry;
|
|
|
|
isc_ht_iter_current(iter, (void **) &entry);
|
|
|
|
dns_catz_entry_detach(zone, &entry);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/* the hashtable has to be empty now */
|
|
|
|
INSIST(isc_ht_count(zone->entries) == 0);
|
|
|
|
isc_ht_destroy(&zone->entries);
|
|
|
|
}
|
|
|
|
mctx = zone->catzs->mctx;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_timer_detach(&zone->updatetimer);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_refcount_destroy(&zone->refs);
|
|
|
|
dns_name_free(&zone->name, mctx);
|
|
|
|
dns_catz_options_free(&zone->defoptions, mctx);
|
|
|
|
dns_catz_options_free(&zone->zoneoptions, mctx);
|
|
|
|
zone->catzs = NULL;
|
|
|
|
isc_mem_put(mctx, zone, sizeof(dns_catz_zone_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_catzs_detach(dns_catz_zones_t ** catzsp) {
|
|
|
|
dns_catz_zones_t *catzs;
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
unsigned int refs;
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zone_t *zone;
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(catzsp != NULL);
|
|
|
|
catzs = *catzsp;
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
|
|
|
|
*catzsp = NULL;
|
|
|
|
isc_refcount_decrement(&catzs->refs, &refs);
|
|
|
|
|
|
|
|
if (refs == 0) {
|
|
|
|
DESTROYLOCK(&catzs->lock);
|
|
|
|
if (catzs->zones != NULL) {
|
2016-05-31 23:01:53 +02:00
|
|
|
result = isc_ht_iter_create(catzs->zones, &iter);
|
2016-05-31 08:12:51 +10:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2016-05-31 23:01:53 +02:00
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
|
|
|
isc_ht_iter_current(iter, (void **) &zone);
|
|
|
|
dns_catz_zone_detach(&zone);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
INSIST(isc_ht_count(catzs->zones) == 0);
|
|
|
|
isc_ht_destroy(&catzs->zones);
|
|
|
|
}
|
|
|
|
isc_refcount_destroy(&catzs->refs);
|
|
|
|
isc_task_destroy(&catzs->updater);
|
|
|
|
isc_mem_putanddetach(&catzs->mctx, catzs, sizeof(*catzs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
CATZ_OPT_NONE,
|
|
|
|
CATZ_OPT_ZONES,
|
|
|
|
CATZ_OPT_MASTERS,
|
|
|
|
CATZ_OPT_ALLOW_QUERY,
|
|
|
|
CATZ_OPT_ALLOW_TRANSFER,
|
|
|
|
CATZ_OPT_VERSION,
|
|
|
|
} catz_opt_t;
|
|
|
|
|
|
|
|
static isc_boolean_t
|
|
|
|
catz_opt_cmp(const dns_label_t *option, const char *opt) {
|
|
|
|
unsigned int l = strlen(opt);
|
|
|
|
if (option->length - 1 == l &&
|
|
|
|
memcmp(opt, option->base + 1, l - 1) == 0)
|
|
|
|
return (ISC_TRUE);
|
|
|
|
else
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static catz_opt_t
|
|
|
|
catz_get_option(const dns_label_t *option) {
|
|
|
|
if (catz_opt_cmp(option, "zones"))
|
|
|
|
return (CATZ_OPT_ZONES);
|
|
|
|
else if (catz_opt_cmp(option, "masters"))
|
|
|
|
return (CATZ_OPT_MASTERS);
|
|
|
|
else if (catz_opt_cmp(option, "allow-query"))
|
|
|
|
return (CATZ_OPT_ALLOW_QUERY);
|
|
|
|
else if (catz_opt_cmp(option, "allow-transfer"))
|
|
|
|
return (CATZ_OPT_ALLOW_TRANSFER);
|
|
|
|
else if (catz_opt_cmp(option, "version"))
|
|
|
|
return (CATZ_OPT_VERSION);
|
|
|
|
else
|
|
|
|
return (CATZ_OPT_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_global_list(dns_catz_zone_t *zone, catz_opt_t opt,
|
|
|
|
dns_rdataset_t *value, dns_label_t *mhash)
|
|
|
|
{
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_ptr_t ptr;
|
|
|
|
dns_catz_entry_t *entry = NULL;
|
|
|
|
dns_name_t emptyname;
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
REQUIRE(mhash != NULL);
|
|
|
|
|
|
|
|
dns_name_init(&emptyname, NULL);
|
|
|
|
switch (opt) {
|
|
|
|
case CATZ_OPT_ZONES:
|
|
|
|
if (value->rdclass != dns_rdataclass_in ||
|
|
|
|
value->type != dns_rdatatype_ptr) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We only take -first- value, as mhash must be
|
|
|
|
* different
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
break;
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_tostruct(&rdata, &ptr, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_find(zone->entries, mhash->base,
|
|
|
|
mhash->length, (void **) &entry);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
if (dns_name_countlabels(&entry->name) != 0) {
|
|
|
|
/* we have a duplicate */
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
} else {
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_dup(&ptr.ptr,
|
|
|
|
zone->catzs->mctx,
|
|
|
|
&entry->name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_freestruct(&ptr);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_entry_new(zone->catzs->mctx, &ptr.ptr,
|
|
|
|
&entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_freestruct(&ptr);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_add(zone->entries, mhash->base,
|
|
|
|
mhash->length, entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
dns_catz_entry_detach(zone, &entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_version(dns_catz_zone_t *zone, dns_rdataset_t *value) {
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_txt_t rdatatxt;
|
|
|
|
dns_rdata_txt_string_t rdatastr;
|
|
|
|
isc_uint32_t tversion;
|
|
|
|
char t[16];
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
|
|
|
if (value->rdclass != dns_rdataclass_in ||
|
|
|
|
value->type != dns_rdatatype_txt)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_tostruct(&rdata, &rdatatxt, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_txt_first(&rdatatxt);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_txt_current(&rdatatxt, &rdatastr);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_txt_next(&rdatatxt);
|
|
|
|
if (result != ISC_R_NOMORE) {
|
|
|
|
result = ISC_R_FAILURE;
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (rdatastr.length > 15) {
|
2016-05-31 08:12:51 +10:00
|
|
|
result = ISC_R_BADNUMBER;
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
memcpy(t, rdatastr.data, rdatastr.length);
|
|
|
|
t[rdatastr.length] = 0;
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_parse_uint32(&tversion, t, 10);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
zone->version = tversion;
|
2016-05-31 08:12:51 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rdata_freestruct(&rdatatxt);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_ipkl(dns_catz_zone_t *zone, dns_ipkeylist_t *ipkl,
|
|
|
|
dns_rdataset_t *value)
|
|
|
|
{
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_t rdata;
|
2016-05-31 08:12:51 +10:00
|
|
|
dns_rdata_in_a_t rdata_a;
|
|
|
|
unsigned int rcount;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(ipkl != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
2016-05-31 08:12:51 +10:00
|
|
|
REQUIRE(dns_rdataset_isassociated(value));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
if (value->rdclass != dns_rdataclass_in ||
|
|
|
|
value->type != dns_rdatatype_a)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
rcount = dns_rdataset_count(value);
|
|
|
|
|
|
|
|
ipkl->addrs = isc_mem_reallocate(zone->catzs->mctx, ipkl->addrs,
|
|
|
|
(rcount * sizeof(isc_sockaddr_t)));
|
|
|
|
if (ipkl->addrs == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
|
|
|
ipkl->keys = isc_mem_reallocate(zone->catzs->mctx, ipkl->keys,
|
|
|
|
(rcount * sizeof(dns_name_t *)));
|
|
|
|
if (ipkl->keys == NULL) {
|
|
|
|
isc_mem_free(zone->catzs->mctx, ipkl->addrs);
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (result = dns_rdataset_first(value);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = dns_rdataset_next(value))
|
|
|
|
{
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_a, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* port 0 == take the default
|
|
|
|
*/
|
|
|
|
isc_sockaddr_fromin(&ipkl->addrs[ipkl->count],
|
2016-05-31 08:12:51 +10:00
|
|
|
&rdata_a.in_addr, 0);
|
2016-05-26 21:23:19 +02:00
|
|
|
ipkl->keys[ipkl->count] = NULL;
|
|
|
|
ipkl->count++;
|
2016-05-31 08:12:51 +10:00
|
|
|
dns_rdata_freestruct(&rdata_a);
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
static isc_result_t
|
|
|
|
catz_process_apl(dns_catz_zone_t *zone, isc_buffer_t **aclbp,
|
|
|
|
dns_rdataset_t *value)
|
|
|
|
{
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_in_apl_t rdata_apl;
|
|
|
|
dns_rdata_apl_ent_t apl_ent;
|
|
|
|
isc_netaddr_t addr;
|
|
|
|
isc_buffer_t *aclb = NULL;
|
|
|
|
unsigned char buf[256]; /* larger than INET6_ADDRSTRLEN */
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(aclbp != NULL);
|
|
|
|
REQUIRE(*aclbp == NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
REQUIRE(dns_rdataset_isassociated(value));
|
|
|
|
|
|
|
|
if (value->rdclass != dns_rdataclass_in ||
|
|
|
|
value->type != dns_rdatatype_apl)
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
|
|
|
|
|
|
|
|
if (dns_rdataset_count(value) > 1) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: more than one APL entry for member zone, "
|
|
|
|
"result is undefined");
|
|
|
|
}
|
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_apl, zone->catzs->mctx);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = isc_buffer_allocate(zone->catzs->mctx, &aclb, 16);
|
|
|
|
isc_buffer_setautorealloc(aclb, ISC_TRUE);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
for (result = dns_rdata_apl_first(&rdata_apl);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = dns_rdata_apl_next(&rdata_apl)) {
|
|
|
|
result = dns_rdata_apl_current(&rdata_apl, &apl_ent);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
memcpy(buf, apl_ent.data, apl_ent.length);
|
|
|
|
if (apl_ent.family == 1)
|
|
|
|
isc_netaddr_fromin(&addr, (struct in_addr*) buf);
|
|
|
|
else if (apl_ent.family == 2)
|
|
|
|
isc_netaddr_fromin6(&addr, (struct in6_addr*) buf);
|
|
|
|
else
|
|
|
|
continue; /* xxxwpk log it or simply ignore? */
|
|
|
|
if (apl_ent.negative)
|
|
|
|
isc_buffer_putuint8(aclb, '!');
|
|
|
|
isc_buffer_reserve(&aclb, INET6_ADDRSTRLEN);
|
|
|
|
result = isc_netaddr_totext(&addr, aclb);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
if ((apl_ent.family == 1 && apl_ent.prefix < 32) ||
|
|
|
|
(apl_ent.family == 2 && apl_ent.prefix < 128)) {
|
|
|
|
isc_buffer_putuint8(aclb, '/');
|
|
|
|
isc_buffer_putdecint(aclb, apl_ent.prefix);
|
|
|
|
}
|
|
|
|
isc_buffer_putstr(aclb, "; ");
|
|
|
|
}
|
|
|
|
if (result == ISC_R_NOMORE)
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
else
|
|
|
|
goto cleanup;
|
|
|
|
*aclbp = aclb;
|
|
|
|
aclb = NULL;
|
|
|
|
cleanup:
|
|
|
|
if (aclb != NULL)
|
|
|
|
isc_buffer_free(&aclb);
|
|
|
|
dns_rdata_freestruct(&rdata_apl);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
static isc_result_t
|
|
|
|
catz_process_suboption(dns_catz_zone_t *zone, dns_label_t *mhash,
|
|
|
|
catz_opt_t subopt, dns_rdataset_t *value)
|
|
|
|
{
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(mhash != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we're adding this entry now, in case the option is invalid we'll get
|
|
|
|
* rid of in verification phase
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_find(zone->entries, mhash->base,
|
|
|
|
mhash->length, (void **) &entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
result = dns_catz_entry_new(zone->catzs->mctx, NULL, &entry);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = isc_ht_add(zone->entries, mhash->base, mhash->length,
|
|
|
|
entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_detach(zone, &entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (subopt) {
|
|
|
|
case CATZ_OPT_MASTERS:
|
|
|
|
return (catz_process_ipkl(zone, &entry->opts.masters, value));
|
|
|
|
break;
|
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &entry->opts.allow_query,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_TRANSFER:
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &entry->opts.allow_transfer,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_global_option(dns_catz_zone_t *zone, catz_opt_t option,
|
|
|
|
dns_rdataset_t *value)
|
|
|
|
{
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
|
|
|
switch (option) {
|
|
|
|
case CATZ_OPT_MASTERS:
|
|
|
|
return (catz_process_ipkl(zone, &zone->zoneoptions.masters,
|
|
|
|
value));
|
|
|
|
case CATZ_OPT_VERSION:
|
|
|
|
return (catz_process_version(zone, value));
|
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &zone->zoneoptions.allow_query,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_TRANSFER:
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &zone->zoneoptions.allow_transfer,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_value(dns_catz_zone_t *zone, dns_name_t *value,
|
|
|
|
dns_rdataset_t *rdataset)
|
|
|
|
{
|
|
|
|
dns_label_t suboption, option, mhash;
|
|
|
|
catz_opt_t opt, subopt;
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(value != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
|
|
|
|
|
|
|
switch (value->labels) {
|
|
|
|
case 1:
|
|
|
|
/* Catalog zone-wide option */
|
|
|
|
dns_name_getlabel(value, 0, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
return (catz_process_global_option(zone, opt, rdataset));
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
/* Global list (eg. 'zones') */
|
|
|
|
dns_name_getlabel(value, 0, &mhash);
|
|
|
|
dns_name_getlabel(value, 1, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
return (catz_process_global_list(zone, opt, rdataset, &mhash));
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
/* Zone option */
|
|
|
|
dns_name_getlabel(value, 0, &suboption);
|
|
|
|
dns_name_getlabel(value, 1, &mhash);
|
|
|
|
dns_name_getlabel(value, 2, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
subopt = catz_get_option(&suboption);
|
|
|
|
if (opt == CATZ_OPT_ZONES)
|
|
|
|
return (catz_process_suboption(zone, &mhash, subopt,
|
|
|
|
rdataset));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_update_process(dns_catz_zones_t *catzs, dns_catz_zone_t *zone,
|
|
|
|
dns_name_t *src_name, dns_rdataset_t *rdataset)
|
|
|
|
{
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
int order;
|
|
|
|
unsigned int nlabels;
|
|
|
|
dns_namereln_t nrres;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
dns_rdata_soa_t soa;
|
|
|
|
dns_name_t prefix;
|
|
|
|
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
nrres = dns_name_fullcompare(src_name, &zone->name, &order, &nlabels);
|
|
|
|
if (nrres == dns_namereln_equal) {
|
|
|
|
if (rdataset->type == dns_rdatatype_soa) {
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(rdataset);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdataset_current(rdataset, &rdata);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_tostruct(&rdata, &soa, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
|
|
|
* xxxwpk TODO do we want to save something from SOA?
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
} else if (rdataset->type == dns_rdatatype_ns) {
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
} else {
|
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
} else if (nrres != dns_namereln_subdomain) {
|
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_init(&prefix, NULL);
|
|
|
|
dns_name_split(src_name, zone->name.labels, &prefix, NULL);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = catz_process_value(zone, &prefix, rdataset);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
|
|
|
isc_buffer_t **buffer)
|
|
|
|
{
|
|
|
|
isc_buffer_t *tbuf = NULL;
|
|
|
|
isc_sha256_t sha256;
|
|
|
|
isc_region_t r;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-31 10:36:27 -07:00
|
|
|
size_t rlen;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(entry != NULL);
|
|
|
|
REQUIRE(buffer != NULL && *buffer != NULL);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_buffer_allocate(zone->catzs->mctx, &tbuf,
|
|
|
|
strlen(zone->catzs->view->name) +
|
2016-05-31 10:36:27 -07:00
|
|
|
2 * DNS_NAME_FORMATSIZE + 2);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
INSIST(tbuf != NULL);
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(tbuf, zone->catzs->view->name);
|
|
|
|
isc_buffer_putstr(tbuf, "_");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_totext(&zone->name, ISC_TRUE, tbuf);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(tbuf, "_");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_totext(&entry->name, ISC_TRUE, tbuf);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-31 10:36:27 -07:00
|
|
|
/* __catz__<digest>.db */
|
|
|
|
rlen = ISC_SHA256_DIGESTSTRINGLENGTH + 12;
|
|
|
|
|
|
|
|
/* optionally prepend with <zonedir>/ */
|
|
|
|
if (entry->opts.zonedir != NULL)
|
|
|
|
rlen += strlen(entry->opts.zonedir) + 1;
|
|
|
|
|
|
|
|
result = isc_buffer_reserve(buffer, rlen);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-31 10:36:27 -07:00
|
|
|
if (entry->opts.zonedir != NULL) {
|
|
|
|
isc_buffer_putstr(*buffer, entry->opts.zonedir);
|
|
|
|
isc_buffer_putstr(*buffer, "/");
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_usedregion(tbuf, &r);
|
|
|
|
isc_buffer_putstr(*buffer, "__catz__");
|
|
|
|
if (tbuf->used > ISC_SHA256_DIGESTSTRINGLENGTH) {
|
|
|
|
isc_sha256_init(&sha256);
|
|
|
|
isc_sha256_update(&sha256, r.base, r.length);
|
2016-05-31 23:01:53 +02:00
|
|
|
/* we can do that because digest string < 2 * DNS_NAME */
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_sha256_end(&sha256, (char *) r.base);
|
|
|
|
isc_buffer_putstr(*buffer, (char *) r.base);
|
|
|
|
} else {
|
|
|
|
isc_buffer_copyregion(*buffer, &r);
|
|
|
|
}
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(*buffer, ".db");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
cleanup:
|
2016-06-04 08:49:10 +02:00
|
|
|
isc_buffer_free(&tbuf);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
|
|
|
isc_buffer_t **buf)
|
|
|
|
{
|
2016-06-20 13:39:44 +02:00
|
|
|
/*
|
|
|
|
* We have to generate a text buffer with regular zone config:
|
2016-05-26 21:23:19 +02:00
|
|
|
* zone foo.bar {
|
|
|
|
* type slave;
|
|
|
|
* masters { ip1 port1; ip2 port2; };
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
isc_buffer_t *buffer = NULL;
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_region_t region;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_uint32_t i;
|
|
|
|
isc_netaddr_t netaddr;
|
|
|
|
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
REQUIRE(entry != NULL);
|
|
|
|
REQUIRE(buf != NULL && *buf == NULL);
|
|
|
|
|
|
|
|
/*
|
2016-05-31 08:12:51 +10:00
|
|
|
* The buffer will be reallocated if something won't fit,
|
|
|
|
* ISC_BUFFER_INC seems like a good start.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_buffer_allocate(zone->catzs->mctx, &buffer,
|
|
|
|
ISC_BUFFER_INCR);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_setautorealloc(buffer, ISC_TRUE);
|
|
|
|
isc_buffer_putstr(buffer, "zone ");
|
|
|
|
dns_name_totext(&entry->name, ISC_TRUE, buffer);
|
|
|
|
isc_buffer_putstr(buffer, " { type slave; masters { ");
|
|
|
|
for (i = 0; i < entry->opts.masters.count; i++) {
|
|
|
|
/* TODO port and DSCP */
|
|
|
|
isc_netaddr_fromsockaddr(&netaddr,
|
|
|
|
&entry->opts.masters.addrs[i]);
|
|
|
|
isc_buffer_reserve(&buffer, INET6_ADDRSTRLEN);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_netaddr_totext(&netaddr, buffer);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
if (entry->opts.masters.keys[i] != NULL) {
|
|
|
|
isc_buffer_putstr(buffer, " key ");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_totext(entry->opts.masters.keys[i],
|
2016-05-30 23:45:27 +00:00
|
|
|
ISC_TRUE, buffer);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
isc_buffer_putstr(buffer, "; ");
|
|
|
|
}
|
|
|
|
isc_buffer_putstr(buffer, "};");
|
|
|
|
if (entry->opts.in_memory == ISC_FALSE) {
|
|
|
|
isc_buffer_putstr(buffer, "file \"");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_generate_masterfilename(zone, entry, &buffer);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(buffer, "\";");
|
|
|
|
|
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
if (entry->opts.allow_query != NULL) {
|
|
|
|
isc_buffer_putstr(buffer, "allow-query { ");
|
|
|
|
isc_buffer_usedregion(entry->opts.allow_query, ®ion);
|
|
|
|
isc_buffer_copyregion(buffer, ®ion);
|
|
|
|
isc_buffer_putstr(buffer, "};");
|
|
|
|
}
|
|
|
|
if (entry->opts.allow_transfer != NULL) {
|
|
|
|
isc_buffer_putstr(buffer, "allow-transfer { ");
|
|
|
|
isc_buffer_usedregion(entry->opts.allow_transfer, ®ion);
|
|
|
|
isc_buffer_copyregion(buffer, ®ion);
|
|
|
|
isc_buffer_putstr(buffer, "};");
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_putstr(buffer, "};");
|
2016-05-26 21:23:19 +02:00
|
|
|
*buf = buffer;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (buffer)
|
|
|
|
isc_buffer_free(&buffer);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event) {
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_t * zone;
|
|
|
|
(void) task;
|
|
|
|
|
|
|
|
REQUIRE(event != NULL);
|
|
|
|
zone = event->ev_arg;
|
|
|
|
REQUIRE(zone != NULL);
|
|
|
|
|
|
|
|
LOCK(&zone->catzs->lock);
|
|
|
|
zone->updatepending = ISC_FALSE;
|
|
|
|
dns_catz_update_from_db(zone->db, zone->catzs);
|
|
|
|
dns_db_detach(&zone->db);
|
2016-06-04 09:08:48 +02:00
|
|
|
result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
|
|
|
|
NULL, NULL, ISC_TRUE);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_event_free(&event);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_time_now(&zone->lastupdated);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
UNLOCK(&zone->catzs->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
|
|
|
|
dns_catz_zones_t *catzs;
|
|
|
|
dns_catz_zone_t *zone = NULL;
|
|
|
|
isc_time_t now;
|
|
|
|
isc_uint64_t tdiff;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
REQUIRE(DNS_DB_VALID(db));
|
|
|
|
REQUIRE(fn_arg != NULL);
|
2016-05-31 23:01:53 +02:00
|
|
|
catzs = (dns_catz_zones_t *) fn_arg;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
dns_name_toregion(&db->origin, &r);
|
|
|
|
|
|
|
|
LOCK(&catzs->lock);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **) &zone);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
if (zone->updatepending == ISC_FALSE) {
|
2016-05-31 08:12:51 +10:00
|
|
|
zone->updatepending = ISC_TRUE;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_time_now(&now);
|
|
|
|
tdiff = isc_time_microdiff(&now, &zone->lastupdated)/1000000;
|
|
|
|
if (tdiff < zone->defoptions.min_update_interval) {
|
|
|
|
isc_interval_t interval;
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: new zone version came too soon, "
|
|
|
|
"deferring update");
|
2016-05-30 17:10:08 +02:00
|
|
|
isc_interval_set(&interval,
|
|
|
|
5 - (unsigned int)tdiff, 0);
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_attach(db, &zone->db);
|
|
|
|
dns_db_currentversion(db, &zone->dbversion);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_timer_reset(zone->updatetimer,
|
2016-05-30 23:45:27 +00:00
|
|
|
isc_timertype_once,
|
|
|
|
NULL, &interval, ISC_TRUE);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
|
|
|
isc_event_t *event;
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_attach(db, &zone->db);
|
|
|
|
dns_db_currentversion(db, &zone->dbversion);
|
|
|
|
ISC_EVENT_INIT(&zone->updateevent,
|
|
|
|
sizeof(zone->updateevent), 0, NULL,
|
|
|
|
DNS_EVENT_CATZUPDATED,
|
|
|
|
dns_catz_update_taskaction,
|
|
|
|
zone, zone, NULL, NULL);
|
|
|
|
event = &zone->updateevent;
|
|
|
|
isc_task_send(catzs->updater, &event);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
INSIST(db == zone->db);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: update already queued");
|
|
|
|
dns_db_closeversion(zone->db, &zone->dbversion, ISC_FALSE);
|
|
|
|
dns_db_currentversion(zone->db, &zone->dbversion);
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
cleanup:
|
2016-05-26 21:23:19 +02:00
|
|
|
UNLOCK(&catzs->lock);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) {
|
|
|
|
dns_catz_zone_t *oldzone = NULL, *newzone = NULL;
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_region_t r;
|
|
|
|
dns_dbnode_t *node = NULL;
|
|
|
|
dns_dbiterator_t *it = NULL;
|
|
|
|
dns_fixedname_t fixname;
|
|
|
|
dns_name_t *name;
|
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
char bname[DNS_NAME_FORMATSIZE];
|
|
|
|
isc_buffer_t ibname;
|
|
|
|
isc_uint32_t vers;
|
|
|
|
|
|
|
|
REQUIRE(DNS_DB_VALID(db));
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new catz in the same context as current catz
|
|
|
|
*/
|
|
|
|
dns_name_toregion(&db->origin, &r);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&oldzone);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
/* this can happen if we remove the zone in the meantime */
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: zone '%s' not in config",
|
|
|
|
bname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_init(&ibname, bname, DNS_NAME_FORMATSIZE);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_name_totext(&db->origin, ISC_TRUE, &ibname);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_getsoaserial(db, oldzone->dbversion, &vers);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
/* A zone without SOA record?!? */
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: zone '%s' has no SOA record (%s)",
|
2016-05-31 08:12:51 +10:00
|
|
|
bname, isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: updating catalog zone '%s' with serial %d",
|
|
|
|
bname, vers);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_new_zone(catzs, &newzone, &db->origin);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, ISC_FALSE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to create new zone - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_createiterator(db, DNS_DB_NONSEC3, &it);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, ISC_FALSE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to create DB iterator - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_fixedname_init(&fixname);
|
|
|
|
name = dns_fixedname_name(&fixname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iterate over database to fill the new zone
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_dbiterator_first(it);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to get db iterator - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
while (result == ISC_R_SUCCESS) {
|
|
|
|
result = dns_dbiterator_current(it, &node, name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to get db iterator - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_allrdatasets(db, node, oldzone->dbversion, 0,
|
2016-05-26 21:23:19 +02:00
|
|
|
&rdsiter);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to fetch rrdatasets - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_detachnode(db, &node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rdataset_init(&rdataset);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdatasetiter_first(rdsiter);
|
|
|
|
while (result == ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdatasetiter_current(rdsiter, &rdataset);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_update_process(catzs, newzone, name,
|
|
|
|
&rdataset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
char cname[DNS_NAME_FORMATSIZE];
|
|
|
|
dns_name_format(name, cname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"catz: unknown record in catalog "
|
|
|
|
"zone - %s (%s) - ignoring",
|
|
|
|
cname,
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdatasetiter_next(rdsiter);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_rdatasetiter_destroy(&rdsiter);
|
|
|
|
|
|
|
|
dns_db_detachnode(db, &node);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_dbiterator_next(it);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_dbiterator_destroy(&it);
|
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, ISC_FALSE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: update_from_db: iteration finished");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally merge new zone into old zone
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_zones_merge(oldzone, newzone);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"catz: failed merging zones: %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: update_from_db: new zone merged");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_prereconfig(dns_catz_zones_t *catzs) {
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_t result;
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
dns_catz_zone_t *zone;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(catzs != NULL);
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
result = isc_ht_iter_create(catzs->zones, &iter);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_next(iter))
|
|
|
|
{
|
|
|
|
isc_ht_iter_current(iter, (void **) &zone);
|
|
|
|
zone->active = ISC_FALSE;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2016-05-31 23:01:53 +02:00
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_postreconfig(dns_catz_zones_t *catzs) {
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_result_t result;
|
|
|
|
dns_catz_zone_t *newzone = NULL;
|
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
dns_catz_zone_t *zone;
|
|
|
|
|
|
|
|
result = isc_ht_iter_create(catzs->zones, &iter);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_next(iter))
|
|
|
|
{
|
|
|
|
isc_ht_iter_current(iter, (void **) &zone);
|
|
|
|
if (zone->active == ISC_FALSE) {
|
|
|
|
char cname[DNS_NAME_FORMATSIZE];
|
2016-06-20 13:39:44 +02:00
|
|
|
dns_name_format(&zone->name, cname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"catz: removing catalog zone %s", cname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Merge the old zone with an empty one to remove
|
|
|
|
* all members
|
|
|
|
*/
|
|
|
|
result = dns_catz_new_zone(catzs, &newzone,
|
|
|
|
&zone->name);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
dns_catz_zones_merge(zone, newzone);
|
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
|
|
|
|
/* Make sure that we have an empty catalog zone */
|
|
|
|
INSIST(isc_ht_count(zone->entries) == 0);
|
|
|
|
dns_catz_zone_detach(&zone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp) {
|
|
|
|
return (isc_ht_iter_create(catz->entries, itp));
|
|
|
|
}
|