2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-05-26 12:36:17 -07:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2016-05-26 21:23:19 +02:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
2016-05-26 21:23:19 +02: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
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
2016-05-26 21:23:19 +02:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2016-06-22 10:49:25 +02:00
|
|
|
* information regarding copyright ownership.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*! \file */
|
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2023-02-09 10:32:33 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
#include <isc/async.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
#include <isc/hex.h>
|
2022-07-26 13:03:40 +02:00
|
|
|
#include <isc/loop.h>
|
2018-06-01 09:31:59 +02:00
|
|
|
#include <isc/md.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
#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>
|
2017-10-19 12:26:32 +11:00
|
|
|
#include <isc/util.h>
|
2023-02-21 14:23:38 +00:00
|
|
|
#include <isc/work.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
#include <dns/catz.h>
|
|
|
|
#include <dns/dbiterator.h>
|
|
|
|
#include <dns/rdatasetiter.h>
|
|
|
|
#include <dns/view.h>
|
|
|
|
#include <dns/zone.h>
|
2016-05-26 12:36:17 -07:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
#define DNS_CATZ_ZONE_MAGIC ISC_MAGIC('c', 'a', 't', 'z')
|
|
|
|
#define DNS_CATZ_ZONES_MAGIC ISC_MAGIC('c', 'a', 't', 's')
|
|
|
|
#define DNS_CATZ_ENTRY_MAGIC ISC_MAGIC('c', 'a', 't', 'e')
|
2022-03-17 13:09:11 +00:00
|
|
|
#define DNS_CATZ_COO_MAGIC ISC_MAGIC('c', 'a', 't', 'c')
|
2018-11-28 18:57:38 +11:00
|
|
|
|
|
|
|
#define DNS_CATZ_ZONE_VALID(catz) ISC_MAGIC_VALID(catz, DNS_CATZ_ZONE_MAGIC)
|
|
|
|
#define DNS_CATZ_ZONES_VALID(catzs) ISC_MAGIC_VALID(catzs, DNS_CATZ_ZONES_MAGIC)
|
|
|
|
#define DNS_CATZ_ENTRY_VALID(entry) ISC_MAGIC_VALID(entry, DNS_CATZ_ENTRY_MAGIC)
|
2022-03-17 13:09:11 +00:00
|
|
|
#define DNS_CATZ_COO_VALID(coo) ISC_MAGIC_VALID(coo, DNS_CATZ_COO_MAGIC)
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-16 20:11:17 +00:00
|
|
|
#define DNS_CATZ_VERSION_UNDEFINED ((uint32_t)(-1))
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
/*%
|
|
|
|
* Change of ownership permissions
|
|
|
|
*/
|
|
|
|
struct dns_catz_coo {
|
|
|
|
unsigned int magic;
|
|
|
|
dns_name_t name;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_t references;
|
2022-03-17 13:09:11 +00:00
|
|
|
};
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*%
|
|
|
|
* Single member zone in a catalog
|
|
|
|
*/
|
|
|
|
struct dns_catz_entry {
|
2018-11-28 18:57:38 +11:00
|
|
|
unsigned int magic;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_name_t name;
|
|
|
|
dns_catz_options_t opts;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_t references;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Catalog zone
|
|
|
|
*/
|
|
|
|
struct dns_catz_zone {
|
2018-11-28 18:57:38 +11:00
|
|
|
unsigned int magic;
|
2023-02-21 21:14:44 +00:00
|
|
|
isc_loop_t *loop;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_name_t name;
|
|
|
|
dns_catz_zones_t *catzs;
|
|
|
|
dns_rdata_t soa;
|
2023-02-21 14:23:38 +00:00
|
|
|
uint32_t version;
|
2016-05-26 21:23:19 +02:00
|
|
|
/* key in entries is 'mhash', not domain name! */
|
|
|
|
isc_ht_t *entries;
|
2022-03-17 13:09:11 +00:00
|
|
|
/* key in coos is domain name */
|
|
|
|
isc_ht_t *coos;
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
bool updatepending; /* there is an update pending */
|
|
|
|
bool updaterunning; /* there is an update running */
|
|
|
|
isc_result_t updateresult; /* result from the offloaded work */
|
|
|
|
dns_db_t *db; /* zones database */
|
|
|
|
dns_dbversion_t *dbversion; /* version we will be updating to */
|
|
|
|
dns_db_t *updb; /* zones database we're working on */
|
|
|
|
dns_dbversion_t *updbversion; /* version we're working on */
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_timer_t *updatetimer;
|
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
bool active;
|
|
|
|
bool db_registered;
|
2022-03-17 14:43:18 +00:00
|
|
|
bool broken;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_refcount_t references;
|
2023-03-01 14:41:59 +00:00
|
|
|
isc_mutex_t lock;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
static void
|
|
|
|
dns__catz_timer_cb(void *);
|
2022-09-12 16:36:19 +02:00
|
|
|
static void
|
2023-02-21 14:11:04 +00:00
|
|
|
dns__catz_timer_start(dns_catz_zone_t *catz);
|
2023-02-21 21:14:44 +00:00
|
|
|
static void
|
|
|
|
dns__catz_timer_stop(void *arg);
|
2022-09-12 16:36:19 +02:00
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
static void
|
|
|
|
dns__catz_update_cb(void *data);
|
|
|
|
static void
|
|
|
|
dns__catz_done_cb(void *data);
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_zones_entry(dns_catz_zone_t *catz, dns_rdataset_t *value,
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t *mhash);
|
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_zones_suboption(dns_catz_zone_t *catz, dns_rdataset_t *value,
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t *mhash, dns_name_t *name);
|
2021-09-24 17:42:12 +00:00
|
|
|
static void
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_entry_add_or_mod(dns_catz_zone_t *catz, isc_ht_t *ht, unsigned char *key,
|
2021-09-24 17:42:12 +00:00
|
|
|
size_t keysize, dns_catz_entry_t *nentry,
|
|
|
|
dns_catz_entry_t *oentry, const char *msg,
|
|
|
|
const char *zname, const char *czname);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*%
|
|
|
|
* Collection of catalog zones for a view
|
|
|
|
*/
|
|
|
|
struct dns_catz_zones {
|
2018-11-28 18:57:38 +11:00
|
|
|
unsigned int magic;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_ht_t *zones;
|
|
|
|
isc_mem_t *mctx;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_t references;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_mutex_t lock;
|
|
|
|
dns_catz_zonemodmethods_t *zmm;
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_loopmgr_t *loopmgr;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_view_t *view;
|
2023-02-21 21:14:44 +00:00
|
|
|
atomic_bool shuttingdown;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_options_init(dns_catz_options_t *options) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(options != NULL);
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_ipkeylist_init(&options->masters);
|
|
|
|
|
|
|
|
options->allow_query = NULL;
|
|
|
|
options->allow_transfer = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
options->allow_query = NULL;
|
|
|
|
options->allow_transfer = NULL;
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
options->in_memory = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
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) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(options != NULL);
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
if (options->allow_transfer != NULL) {
|
|
|
|
isc_buffer_free(&options->allow_transfer);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
void
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_copy(isc_mem_t *mctx, const dns_catz_options_t *src,
|
|
|
|
dns_catz_options_t *dst) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(mctx != NULL);
|
2017-09-27 10:27:09 +10:00
|
|
|
REQUIRE(src != NULL);
|
2016-05-26 21:23:19 +02:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
if (src->allow_query != NULL) {
|
|
|
|
isc_buffer_dup(mctx, &dst->allow_query, src->allow_query);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
if (src->allow_transfer != NULL) {
|
|
|
|
isc_buffer_dup(mctx, &dst->allow_transfer, src->allow_transfer);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
void
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_setdefault(isc_mem_t *mctx, const dns_catz_options_t *defaults,
|
|
|
|
dns_catz_options_t *opts) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(defaults != NULL);
|
|
|
|
REQUIRE(opts != NULL);
|
|
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
if (defaults->zonedir != NULL) {
|
2016-05-31 10:36:27 -07:00
|
|
|
opts->zonedir = isc_mem_strdup(mctx, defaults->zonedir);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
if (opts->allow_transfer == NULL && defaults->allow_transfer != NULL) {
|
|
|
|
isc_buffer_dup(mctx, &opts->allow_transfer,
|
|
|
|
defaults->allow_transfer);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
static void
|
|
|
|
catz_coo_new(isc_mem_t *mctx, const dns_name_t *domain,
|
|
|
|
dns_catz_coo_t **ncoop) {
|
|
|
|
dns_catz_coo_t *ncoo;
|
|
|
|
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(domain != NULL);
|
|
|
|
REQUIRE(ncoop != NULL && *ncoop == NULL);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
ncoo = isc_mem_get(mctx, sizeof(*ncoo));
|
2022-03-17 13:09:11 +00:00
|
|
|
dns_name_init(&ncoo->name, NULL);
|
|
|
|
dns_name_dup(domain, mctx, &ncoo->name);
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_init(&ncoo->references, 1);
|
2022-03-17 13:09:11 +00:00
|
|
|
ncoo->magic = DNS_CATZ_COO_MAGIC;
|
|
|
|
*ncoop = ncoo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_coo_detach(dns_catz_zone_t *catz, dns_catz_coo_t **coop) {
|
2022-03-17 13:09:11 +00:00
|
|
|
dns_catz_coo_t *coo;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-03-17 13:09:11 +00:00
|
|
|
REQUIRE(coop != NULL && DNS_CATZ_COO_VALID(*coop));
|
|
|
|
coo = *coop;
|
|
|
|
*coop = NULL;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
if (isc_refcount_decrement(&coo->references) == 1) {
|
|
|
|
isc_mem_t *mctx = catz->catzs->mctx;
|
2022-03-17 13:09:11 +00:00
|
|
|
coo->magic = 0;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_destroy(&coo->references);
|
2022-03-17 13:09:11 +00:00
|
|
|
if (dns_name_dynamic(&coo->name)) {
|
|
|
|
dns_name_free(&coo->name, mctx);
|
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_mem_put(mctx, coo, sizeof(*coo));
|
2022-03-17 13:09:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
void
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_new(isc_mem_t *mctx, const dns_name_t *domain,
|
|
|
|
dns_catz_entry_t **nentryp) {
|
|
|
|
dns_catz_entry_t *nentry;
|
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(mctx != NULL);
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(nentryp != NULL && *nentryp == NULL);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
nentry = isc_mem_get(mctx, sizeof(*nentry));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
dns_name_init(&nentry->name, NULL);
|
2016-06-22 10:49:25 +02:00
|
|
|
if (domain != NULL) {
|
2019-11-01 08:31:13 -05:00
|
|
|
dns_name_dup(domain, mctx, &nentry->name);
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
dns_catz_options_init(&nentry->opts);
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_init(&nentry->references, 1);
|
2018-11-28 18:57:38 +11:00
|
|
|
nentry->magic = DNS_CATZ_ENTRY_MAGIC;
|
2016-05-26 21:23:19 +02:00
|
|
|
*nentryp = nentry;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_t *
|
|
|
|
dns_catz_entry_getname(dns_catz_entry_t *entry) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
return (&entry->name);
|
|
|
|
}
|
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
void
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_copy(dns_catz_zone_t *catz, const dns_catz_entry_t *entry,
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_t **nentryp) {
|
|
|
|
dns_catz_entry_t *nentry = NULL;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
|
|
|
REQUIRE(nentryp != NULL && *nentryp == NULL);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_new(catz->catzs->mctx, &entry->name, &nentry);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_options_copy(catz->catzs->mctx, &entry->opts, &nentry->opts);
|
2016-05-26 21:23:19 +02:00
|
|
|
*nentryp = nentry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_entry_attach(dns_catz_entry_t *entry, dns_catz_entry_t **entryp) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(entryp != NULL && *entryp == NULL);
|
2018-11-28 18:57:38 +11:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_increment(&entry->references);
|
2016-05-26 21:23:19 +02:00
|
|
|
*entryp = entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(dns_catz_zone_t *catz, dns_catz_entry_t **entryp) {
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-03-25 11:49:12 +00:00
|
|
|
REQUIRE(entryp != NULL && DNS_CATZ_ENTRY_VALID(*entryp));
|
2018-11-28 18:57:38 +11:00
|
|
|
entry = *entryp;
|
2018-08-28 10:18:59 +02:00
|
|
|
*entryp = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
if (isc_refcount_decrement(&entry->references) == 1) {
|
|
|
|
isc_mem_t *mctx = catz->catzs->mctx;
|
2018-11-28 18:57:38 +11:00
|
|
|
entry->magic = 0;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_destroy(&entry->references);
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_free(&entry->opts, mctx);
|
2016-06-22 10:49:25 +02:00
|
|
|
if (dns_name_dynamic(&entry->name)) {
|
|
|
|
dns_name_free(&entry->name, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_mem_put(mctx, entry, sizeof(*entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_validate(const dns_catz_entry_t *entry) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
UNUSED(entry);
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2016-05-26 21:23:19 +02:00
|
|
|
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-06-22 10:49:25 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(ea));
|
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(eb));
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
if (ea == eb) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
if (ea->opts.masters.count != eb->opts.masters.count) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
if (memcmp(ea->opts.masters.addrs, eb->opts.masters.addrs,
|
|
|
|
ea->opts.masters.count * sizeof(isc_sockaddr_t)))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-09-23 16:52:44 +10:00
|
|
|
for (size_t i = 0; i < eb->opts.masters.count; i++) {
|
|
|
|
if ((ea->opts.masters.keys[i] == NULL) !=
|
2022-11-02 19:33:14 +01:00
|
|
|
(eb->opts.masters.keys[i] == NULL))
|
|
|
|
{
|
2022-09-23 16:52:44 +10:00
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
if (ea->opts.masters.keys[i] == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!dns_name_equal(ea->opts.masters.keys[i],
|
2022-11-02 19:33:14 +01:00
|
|
|
eb->opts.masters.keys[i]))
|
|
|
|
{
|
2022-09-23 16:52:44 +10:00
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 06:55:52 +00:00
|
|
|
for (size_t i = 0; i < eb->opts.masters.count; i++) {
|
|
|
|
if ((ea->opts.masters.tlss[i] == NULL) !=
|
2022-11-02 19:33:14 +01:00
|
|
|
(eb->opts.masters.tlss[i] == NULL))
|
|
|
|
{
|
2022-11-02 06:55:52 +00:00
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
if (ea->opts.masters.tlss[i] == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!dns_name_equal(ea->opts.masters.tlss[i],
|
2022-11-02 19:33:14 +01:00
|
|
|
eb->opts.masters.tlss[i]))
|
|
|
|
{
|
2022-11-02 06:55:52 +00:00
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
/* If one is NULL and the other isn't, the entries don't match */
|
2016-06-22 10:49:25 +02:00
|
|
|
if ((ea->opts.allow_query == NULL) != (eb->opts.allow_query == NULL)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
/* 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)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Repeat the above checks with allow_transfer */
|
|
|
|
if ((ea->opts.allow_transfer == NULL) !=
|
2022-11-02 19:33:14 +01:00
|
|
|
(eb->opts.allow_transfer == NULL))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
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)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_t *
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_getname(dns_catz_zone_t *catz) {
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
return (&catz->name);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_options_t *
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_getdefoptions(dns_catz_zone_t *catz) {
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
return (&catz->defoptions);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_resetdefoptions(dns_catz_zone_t *catz) {
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_options_free(&catz->defoptions, catz->catzs->mctx);
|
|
|
|
dns_catz_options_init(&catz->defoptions);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
/*%<
|
|
|
|
* Merge 'newcatz' into 'catz', calling addzone/delzone/modzone
|
|
|
|
* (from catz->catzs->zmm) for appropriate member zones.
|
|
|
|
*
|
|
|
|
* Requires:
|
|
|
|
* \li 'catz' is a valid dns_catz_zone_t.
|
|
|
|
* \li 'newcatz' is a valid dns_catz_zone_t.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
dns__catz_zones_merge(dns_catz_zone_t *catz, dns_catz_zone_t *newcatz) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_result_t result;
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_t *iter1 = NULL, *iter2 = NULL;
|
2016-07-21 13:07:56 +02:00
|
|
|
isc_ht_iter_t *iteradd = NULL, *itermod = NULL;
|
|
|
|
isc_ht_t *toadd = NULL, *tomod = NULL;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool delcur = false;
|
2016-06-22 10:49:25 +02:00
|
|
|
char czname[DNS_NAME_FORMATSIZE];
|
|
|
|
char zname[DNS_NAME_FORMATSIZE];
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zoneop_fn_t addzone, modzone, delzone;
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(newcatz));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
LOCK(&catz->lock);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/* TODO verify the new zone first! */
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
addzone = catz->catzs->zmm->addzone;
|
|
|
|
modzone = catz->catzs->zmm->modzone;
|
|
|
|
delzone = catz->catzs->zmm->delzone;
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
/* Copy zoneoptions from newcatz into catz. */
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_options_free(&catz->zoneoptions, catz->catzs->mctx);
|
|
|
|
dns_catz_options_copy(catz->catzs->mctx, &newcatz->zoneoptions,
|
|
|
|
&catz->zoneoptions);
|
|
|
|
dns_catz_options_setdefault(catz->catzs->mctx, &catz->defoptions,
|
|
|
|
&catz->zoneoptions);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_format(&catz->name, czname, DNS_NAME_FORMATSIZE);
|
2016-07-21 13:07:56 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_ht_init(&toadd, catz->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
|
|
|
|
isc_ht_init(&tomod, catz->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
|
|
|
|
isc_ht_iter_create(newcatz->entries, &iter1);
|
|
|
|
isc_ht_iter_create(catz->entries, &iter2);
|
2016-07-21 13:07:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We can create those iterators now, even though toadd and tomod are
|
|
|
|
* empty
|
|
|
|
*/
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(toadd, &iteradd);
|
|
|
|
isc_ht_iter_create(tomod, &itermod);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-06-22 10:49:25 +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-26 21:23:19 +02:00
|
|
|
*/
|
2016-06-22 10:49:25 +02:00
|
|
|
for (result = isc_ht_iter_first(iter1); result == ISC_R_SUCCESS;
|
2016-07-21 13:07:56 +02:00
|
|
|
result = delcur ? isc_ht_iter_delcurrent_next(iter1)
|
|
|
|
: isc_ht_iter_next(iter1))
|
|
|
|
{
|
2022-03-17 13:09:11 +00:00
|
|
|
isc_result_t zt_find_result;
|
2022-03-17 17:11:04 +00:00
|
|
|
dns_catz_zone_t *parentcatz = NULL;
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *nentry = NULL;
|
|
|
|
dns_catz_entry_t *oentry = NULL;
|
2021-09-24 17:42:12 +00:00
|
|
|
dns_zone_t *zone = NULL;
|
2018-11-28 18:57:38 +11:00
|
|
|
unsigned char *key = NULL;
|
2016-05-31 23:01:53 +02:00
|
|
|
size_t keysize;
|
2018-04-17 08:29:14 -07:00
|
|
|
delcur = false;
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_current(iter1, (void **)&nentry);
|
|
|
|
isc_ht_iter_currentkey(iter1, &key, &keysize);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/*
|
|
|
|
* Spurious record that came from suboption without main
|
2016-07-21 13:07:56 +02:00
|
|
|
* record, removed.
|
|
|
|
* xxxwpk: make it a separate verification phase?
|
2016-06-22 10:49:25 +02:00
|
|
|
*/
|
2016-07-21 13:07:56 +02:00
|
|
|
if (dns_name_countlabels(&nentry->name) == 0) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(newcatz, &nentry);
|
2018-04-17 08:29:14 -07:00
|
|
|
delcur = true;
|
2016-06-22 10:49:25 +02:00
|
|
|
continue;
|
2016-07-21 13:07:56 +02:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
dns_name_format(&nentry->name, zname, DNS_NAME_FORMATSIZE);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: iterating over '%s' from catalog '%s'",
|
|
|
|
zname, czname);
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_options_setdefault(catz->catzs->mctx,
|
|
|
|
&catz->zoneoptions, &nentry->opts);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
/* Try to find the zone in the view */
|
2023-02-09 10:32:33 +00:00
|
|
|
zt_find_result = dns_zt_find(catz->catzs->view->zonetable,
|
2022-03-17 13:09:11 +00:00
|
|
|
dns_catz_entry_getname(nentry), 0,
|
|
|
|
NULL, &zone);
|
|
|
|
if (zt_find_result == ISC_R_SUCCESS) {
|
|
|
|
dns_catz_coo_t *coo = NULL;
|
|
|
|
char pczname[DNS_NAME_FORMATSIZE];
|
2023-03-01 14:41:59 +00:00
|
|
|
bool parentcatz_locked = false;
|
2022-03-17 13:09:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Change of ownership (coo) processing, if required
|
|
|
|
*/
|
|
|
|
parentcatz = dns_zone_get_parentcatz(zone);
|
2023-03-01 14:41:59 +00:00
|
|
|
if (parentcatz != NULL && parentcatz != catz) {
|
|
|
|
UNLOCK(&catz->lock);
|
|
|
|
LOCK(&parentcatz->lock);
|
|
|
|
parentcatz_locked = true;
|
|
|
|
}
|
|
|
|
if (parentcatz_locked &&
|
2022-03-17 13:09:11 +00:00
|
|
|
isc_ht_find(parentcatz->coos, nentry->name.ndata,
|
|
|
|
nentry->name.length,
|
|
|
|
(void **)&coo) == ISC_R_SUCCESS &&
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_equal(&coo->name, &catz->name))
|
2022-03-17 13:09:11 +00:00
|
|
|
{
|
|
|
|
dns_name_format(&parentcatz->name, pczname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3),
|
|
|
|
"catz: zone '%s' "
|
|
|
|
"change of ownership from "
|
|
|
|
"'%s' to '%s'",
|
|
|
|
zname, pczname, czname);
|
|
|
|
result = delzone(nentry, parentcatz,
|
|
|
|
parentcatz->catzs->view,
|
|
|
|
parentcatz->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",
|
|
|
|
zname, pczname,
|
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
2023-03-01 14:41:59 +00:00
|
|
|
if (parentcatz_locked) {
|
|
|
|
UNLOCK(&parentcatz->lock);
|
|
|
|
LOCK(&catz->lock);
|
|
|
|
}
|
2022-03-17 13:09:11 +00:00
|
|
|
}
|
|
|
|
if (zt_find_result == ISC_R_SUCCESS ||
|
2022-11-02 19:33:14 +01:00
|
|
|
zt_find_result == DNS_R_PARTIALMATCH)
|
|
|
|
{
|
2022-03-17 13:09:11 +00:00
|
|
|
dns_zone_detach(&zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to find the zone in the old catalog zone */
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catz->entries, key, (uint32_t)keysize,
|
2018-03-28 14:19:37 +02:00
|
|
|
(void **)&oentry);
|
2016-05-31 23:01:53 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-03-17 17:11:04 +00:00
|
|
|
if (zt_find_result == ISC_R_SUCCESS &&
|
2023-02-09 10:32:33 +00:00
|
|
|
parentcatz == catz)
|
2022-11-02 19:33:14 +01:00
|
|
|
{
|
2022-03-17 17:11:04 +00:00
|
|
|
/*
|
|
|
|
* This means that the zone's unique label
|
|
|
|
* has been changed, in that case we must
|
|
|
|
* reset the zone's internal state by removing
|
|
|
|
* and re-adding it.
|
|
|
|
*
|
|
|
|
* Scheduling the addition now, the removal will
|
|
|
|
* be scheduled below, when walking the old
|
|
|
|
* zone for remaining entries, and then we will
|
|
|
|
* perform deletions earlier than additions and
|
|
|
|
* modifications.
|
|
|
|
*/
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_INFO,
|
|
|
|
"catz: zone '%s' unique label "
|
|
|
|
"has changed, reset state",
|
|
|
|
zname);
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_entry_add_or_mod(catz, toadd, key, keysize, nentry,
|
|
|
|
NULL, "adding", zname, czname);
|
2021-09-24 17:42:12 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
if (zt_find_result != ISC_R_SUCCESS) {
|
2021-09-24 17:42:12 +00:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: zone '%s' was expected to exist "
|
|
|
|
"but can not be found, will be restored",
|
|
|
|
zname);
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_entry_add_or_mod(catz, toadd, key, keysize, nentry,
|
|
|
|
oentry, "adding", zname, czname);
|
2016-05-31 23:01:53 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
if (dns_catz_entry_cmp(oentry, nentry) != true) {
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_entry_add_or_mod(catz, tomod, key, keysize, nentry,
|
|
|
|
oentry, "modifying", zname,
|
|
|
|
czname);
|
2021-09-24 17:42:12 +00:00
|
|
|
continue;
|
2016-05-31 23:01:53 +02:00
|
|
|
}
|
Prevent existing catalog zone entries being incorrectly deleted
After receiving a new version of a catalog zone it is required
to merge it with the old version.
The algorithm walks through the new version's hash table and applies
the following logic:
1. If an entry from the new version does not exist in the old
version, then it's a new entry, add the entry to the `toadd` hash
table.
2. If the zone does not exist in the set of configured zones, because
it was deleted via rndc delzone or it was removed from another
catalog zone instance, then add into to the `toadd` hash table to
be reinstantiated.
3. If an entry from the new version also exists in the old version,
but is modified, then add the entry to the `tomod` hash table, then
remove it from the old version's hash table.
4. If an entry from the new version also exists in the old version and
is the same (unmodified) then just remove it from the old version's
hash table.
The algorithm then deletes all the remaining zones which still exist
in the old version's hash table (because only the ones that don't
exist in the new version should now remain there), then adds the ones
that were added to the `toadd`, and modifies the ones that were added
to the `tomod`, completing the merge.
During a recent refactoring, the part when the entry should be
removed from the old version's hash table on condition (4.) above
was accidentally omitted, so the unmodified zones were remaining
in the old version's hash table and consequently being deleted.
2021-10-13 17:06:48 +11:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete the old entry so that it won't accidentally be
|
|
|
|
* removed as a non-existing entry below.
|
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &oentry);
|
|
|
|
result = isc_ht_delete(catz->entries, key, (uint32_t)keysize);
|
Prevent existing catalog zone entries being incorrectly deleted
After receiving a new version of a catalog zone it is required
to merge it with the old version.
The algorithm walks through the new version's hash table and applies
the following logic:
1. If an entry from the new version does not exist in the old
version, then it's a new entry, add the entry to the `toadd` hash
table.
2. If the zone does not exist in the set of configured zones, because
it was deleted via rndc delzone or it was removed from another
catalog zone instance, then add into to the `toadd` hash table to
be reinstantiated.
3. If an entry from the new version also exists in the old version,
but is modified, then add the entry to the `tomod` hash table, then
remove it from the old version's hash table.
4. If an entry from the new version also exists in the old version and
is the same (unmodified) then just remove it from the old version's
hash table.
The algorithm then deletes all the remaining zones which still exist
in the old version's hash table (because only the ones that don't
exist in the new version should now remain there), then adds the ones
that were added to the `toadd`, and modifies the ones that were added
to the `tomod`, completing the merge.
During a recent refactoring, the part when the entry should be
removed from the old version's hash table on condition (4.) above
was accidentally omitted, so the unmodified zones were remaining
in the old version's hash table and consequently being deleted.
2021-10-13 17:06:48 +11:00
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-31 23:01:53 +02:00
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_destroy(&iter1);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/*
|
2016-06-22 10:49:25 +02:00
|
|
|
* Then - walk the old zone; only deleted entries should remain.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2016-06-22 10:49:25 +02:00
|
|
|
for (result = isc_ht_iter_first(iter2); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter2))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_current(iter2, (void **)&entry);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_format(&entry->name, zname, DNS_NAME_FORMATSIZE);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = delzone(entry, catz, catz->catzs->view,
|
|
|
|
catz->catzs->zmm->udata);
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: deleting zone '%s' from catalog '%s' - %s",
|
2016-06-22 10:49:25 +02:00
|
|
|
zname, czname, isc_result_totext(result));
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &entry);
|
2016-05-31 23:01:53 +02:00
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_destroy(&iter2);
|
2023-02-09 10:32:33 +00:00
|
|
|
/* At this moment catz->entries has to be be empty. */
|
|
|
|
INSIST(isc_ht_count(catz->entries) == 0);
|
|
|
|
isc_ht_destroy(&catz->entries);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-07-21 13:07:56 +02:00
|
|
|
for (result = isc_ht_iter_first(iteradd); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iteradd))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2016-07-21 13:07:56 +02:00
|
|
|
isc_ht_iter_current(iteradd, (void **)&entry);
|
2017-07-10 10:36:56 +10:00
|
|
|
|
|
|
|
dns_name_format(&entry->name, zname, DNS_NAME_FORMATSIZE);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = addzone(entry, catz, catz->catzs->view,
|
|
|
|
catz->catzs->zmm->udata);
|
2016-07-21 13:07:56 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: adding zone '%s' from catalog "
|
|
|
|
"'%s' - %s",
|
|
|
|
zname, czname, isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (result = isc_ht_iter_first(itermod); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(itermod))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2016-07-21 13:07:56 +02:00
|
|
|
isc_ht_iter_current(itermod, (void **)&entry);
|
2018-11-28 15:59:30 +11:00
|
|
|
|
|
|
|
dns_name_format(&entry->name, zname, DNS_NAME_FORMATSIZE);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = modzone(entry, catz, catz->catzs->view,
|
|
|
|
catz->catzs->zmm->udata);
|
2016-07-21 13:07:56 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: modifying zone '%s' from catalog "
|
|
|
|
"'%s' - %s",
|
|
|
|
zname, czname, isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->entries = newcatz->entries;
|
|
|
|
newcatz->entries = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
/*
|
|
|
|
* We do not need to merge old coo (change of ownership) permission
|
|
|
|
* records with the new ones, just replace them.
|
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->coos != NULL && newcatz->coos != NULL) {
|
2022-03-17 13:09:11 +00:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_ht_iter_create(catz->coos, &iter);
|
2022-03-17 13:09:11 +00:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
|
|
|
dns_catz_coo_t *coo = NULL;
|
|
|
|
|
|
|
|
isc_ht_iter_current(iter, (void **)&coo);
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_coo_detach(catz, &coo);
|
2022-03-17 13:09:11 +00:00
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
|
|
|
|
|
|
|
/* The hashtable has to be empty now. */
|
2023-02-09 10:32:33 +00:00
|
|
|
INSIST(isc_ht_count(catz->coos) == 0);
|
|
|
|
isc_ht_destroy(&catz->coos);
|
2022-03-17 13:09:11 +00:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->coos = newcatz->coos;
|
|
|
|
newcatz->coos = NULL;
|
2022-03-17 13:09:11 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 13:07:56 +02:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_destroy(&iteradd);
|
|
|
|
isc_ht_iter_destroy(&itermod);
|
|
|
|
isc_ht_destroy(&toadd);
|
|
|
|
isc_ht_destroy(&tomod);
|
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
UNLOCK(&catz->lock);
|
|
|
|
|
2016-07-21 13:07:56 +02:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2022-10-29 03:53:47 -07:00
|
|
|
void
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_new_zones(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
|
|
|
|
dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm) {
|
|
|
|
dns_catz_zones_t *catzs = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(loopmgr != NULL);
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
|
|
|
REQUIRE(zmm != NULL);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catzs = isc_mem_get(mctx, sizeof(*catzs));
|
|
|
|
*catzs = (dns_catz_zones_t){ .loopmgr = loopmgr,
|
|
|
|
.zmm = zmm,
|
|
|
|
.magic = DNS_CATZ_ZONES_MAGIC };
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_mutex_init(&catzs->lock);
|
|
|
|
isc_refcount_init(&catzs->references, 1);
|
|
|
|
isc_ht_init(&catzs->zones, mctx, 4, ISC_HT_CASE_SENSITIVE);
|
|
|
|
isc_mem_attach(mctx, &catzs->mctx);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
*catzsp = catzs;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_catzs_set_view(dns_catz_zones_t *catzs, dns_view_t *view) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2022-12-01 12:51:30 +11:00
|
|
|
REQUIRE(DNS_VIEW_VALID(view));
|
2016-06-22 10:49:25 +02:00
|
|
|
/* Either it's a new one or it's being reconfigured. */
|
2016-05-26 21:23:19 +02:00
|
|
|
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
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **catzp,
|
2016-06-22 10:49:25 +02:00
|
|
|
const dns_name_t *name) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t *catz;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(catzp != NULL && *catzp == NULL);
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz = isc_mem_get(catzs->mctx, sizeof(*catz));
|
|
|
|
*catz = (dns_catz_zone_t){ .catzs = catzs,
|
|
|
|
.active = true,
|
|
|
|
.version = DNS_CATZ_VERSION_UNDEFINED,
|
|
|
|
.magic = DNS_CATZ_ZONE_MAGIC };
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
isc_mutex_init(&catz->lock);
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_refcount_init(&catz->references, 1);
|
|
|
|
isc_ht_init(&catz->entries, catzs->mctx, 4, ISC_HT_CASE_SENSITIVE);
|
|
|
|
isc_ht_init(&catz->coos, catzs->mctx, 4, ISC_HT_CASE_INSENSITIVE);
|
|
|
|
isc_time_settoepoch(&catz->lastupdated);
|
|
|
|
dns_catz_options_init(&catz->defoptions);
|
|
|
|
dns_catz_options_init(&catz->zoneoptions);
|
|
|
|
dns_name_init(&catz->name, NULL);
|
|
|
|
dns_name_dup(name, catzs->mctx, &catz->name);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
*catzp = catz;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2023-02-21 14:11:04 +00:00
|
|
|
static void
|
|
|
|
dns__catz_timer_start(dns_catz_zone_t *catz) {
|
2022-09-12 16:36:19 +02:00
|
|
|
uint64_t tdiff;
|
|
|
|
isc_interval_t interval;
|
2023-02-21 14:11:04 +00:00
|
|
|
isc_time_t now;
|
2022-09-12 16:36:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
|
|
|
|
2023-03-31 00:12:33 +02:00
|
|
|
now = isc_time_now();
|
2023-02-09 10:32:33 +00:00
|
|
|
tdiff = isc_time_microdiff(&now, &catz->lastupdated) / 1000000;
|
|
|
|
if (tdiff < catz->defoptions.min_update_interval) {
|
|
|
|
uint64_t defer = catz->defoptions.min_update_interval - tdiff;
|
|
|
|
char dname[DNS_NAME_FORMATSIZE];
|
|
|
|
|
|
|
|
dns_name_format(&catz->name, dname, DNS_NAME_FORMATSIZE);
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
2023-02-09 10:32:33 +00:00
|
|
|
"catz: %s: new zone version came "
|
|
|
|
"too soon, deferring update for "
|
|
|
|
"%" PRIu64 " seconds",
|
|
|
|
dname, defer);
|
|
|
|
isc_interval_set(&interval, (unsigned int)defer, 0);
|
2022-09-12 16:36:19 +02:00
|
|
|
} else {
|
|
|
|
isc_interval_set(&interval, 0, 0);
|
|
|
|
}
|
|
|
|
|
2023-02-21 21:14:44 +00:00
|
|
|
catz->loop = isc_loop_current(catz->catzs->loopmgr);
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
isc_timer_create(catz->loop, dns__catz_timer_cb, catz,
|
2023-02-21 21:14:44 +00:00
|
|
|
&catz->updatetimer);
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_timer_start(catz->updatetimer, isc_timertype_once, &interval);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 21:14:44 +00:00
|
|
|
static void
|
|
|
|
dns__catz_timer_stop(void *arg) {
|
|
|
|
dns_catz_zone_t *catz = arg;
|
2023-02-24 19:17:09 +00:00
|
|
|
dns_catz_zones_t *catzs = NULL;
|
2023-02-21 21:14:44 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
|
|
|
|
|
|
|
isc_timer_stop(catz->updatetimer);
|
|
|
|
isc_timer_destroy(&catz->updatetimer);
|
|
|
|
catz->loop = NULL;
|
2023-02-24 19:17:09 +00:00
|
|
|
catzs = catz->catzs;
|
2023-02-21 21:14:44 +00:00
|
|
|
|
|
|
|
dns_catz_detach_catz(&catz);
|
2023-02-24 19:17:09 +00:00
|
|
|
dns_catz_unref_catzs(catzs);
|
2023-02-21 21:14:44 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t **catzp) {
|
|
|
|
dns_catz_zone_t *catz = NULL;
|
2017-07-10 09:06:13 +10:00
|
|
|
isc_result_t result, tresult;
|
2016-06-22 10:49:25 +02:00
|
|
|
char zname[DNS_NAME_FORMATSIZE];
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(catzp != NULL && *catzp == NULL);
|
2018-11-28 18:57:38 +11:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_format(name, zname, DNS_NAME_FORMATSIZE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3), "catz: dns_catz_add_zone %s", zname);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
LOCK(&catzs->lock);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = dns_catz_new_zone(catzs, &catz, name);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_add(catzs->zones, catz->name.ndata, catz->name.length,
|
|
|
|
catz);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&catz);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_EXISTS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result == ISC_R_EXISTS) {
|
2017-07-10 09:06:13 +10:00
|
|
|
tresult = isc_ht_find(catzs->zones, name->ndata, name->length,
|
2023-02-09 10:32:33 +00:00
|
|
|
(void **)&catz);
|
|
|
|
INSIST(tresult == ISC_R_SUCCESS && !catz->active);
|
|
|
|
catz->active = true;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
*catzp = catz;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
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;
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_zone_t *found = NULL;
|
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-01-27 18:04:41 +00:00
|
|
|
LOCK(&catzs->lock);
|
2016-05-26 21:23:19 +02:00
|
|
|
result = isc_ht_find(catzs->zones, name->ndata, name->length,
|
|
|
|
(void **)&found);
|
2023-01-27 18:04:41 +00:00
|
|
|
UNLOCK(&catzs->lock);
|
2016-05-26 21:23:19 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return (found);
|
|
|
|
}
|
|
|
|
|
2023-02-21 21:14:44 +00:00
|
|
|
static void
|
|
|
|
dns__catz_shutdown(dns_catz_zone_t *catz) {
|
|
|
|
/* lock must be locked */
|
|
|
|
if (catz->updatetimer != NULL) {
|
|
|
|
/* Don't wait for timer to trigger for shutdown */
|
|
|
|
INSIST(catz->loop != NULL);
|
|
|
|
|
|
|
|
dns_catz_ref_catzs(catz->catzs);
|
|
|
|
isc_async_run(catz->loop, dns__catz_timer_stop, catz);
|
|
|
|
} else {
|
|
|
|
dns_catz_detach_catz(&catz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
static void
|
2023-02-09 10:32:33 +00:00
|
|
|
dns__catz_zone_destroy(dns_catz_zone_t *catz) {
|
|
|
|
isc_mem_t *mctx = catz->catzs->mctx;
|
2023-02-21 14:11:04 +00:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->entries != NULL) {
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
isc_result_t result;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_ht_iter_create(catz->entries, &iter);
|
2022-09-12 16:36:19 +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 = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_ht_iter_current(iter, (void **)&entry);
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &entry);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2022-09-12 16:36:19 +02:00
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2022-03-17 13:09:11 +00:00
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
/* The hashtable has to be empty now. */
|
2023-02-09 10:32:33 +00:00
|
|
|
INSIST(isc_ht_count(catz->entries) == 0);
|
|
|
|
isc_ht_destroy(&catz->entries);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->coos != NULL) {
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
isc_result_t result;
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_ht_iter_create(catz->coos, &iter);
|
2022-09-12 16:36:19 +02:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
|
|
|
dns_catz_coo_t *coo = NULL;
|
2022-03-17 13:09:11 +00:00
|
|
|
|
2022-09-12 16:36:19 +02:00
|
|
|
isc_ht_iter_current(iter, (void **)&coo);
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_coo_detach(catz, &coo);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2022-09-12 16:36:19 +02:00
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
|
|
|
|
|
|
|
/* The hashtable has to be empty now. */
|
2023-02-09 10:32:33 +00:00
|
|
|
INSIST(isc_ht_count(catz->coos) == 0);
|
|
|
|
isc_ht_destroy(&catz->coos);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->magic = 0;
|
2023-03-01 14:41:59 +00:00
|
|
|
isc_mutex_destroy(&catz->lock);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->updatetimer != NULL) {
|
|
|
|
isc_timer_async_destroy(&catz->updatetimer);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->db_registered) {
|
2022-11-30 18:40:27 +11:00
|
|
|
dns_db_updatenotify_unregister(
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->db, dns_catz_dbupdate_callback, catz->catzs);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->dbversion != NULL) {
|
|
|
|
dns_db_closeversion(catz->db, &catz->dbversion, false);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->db != NULL) {
|
|
|
|
dns_db_detach(&catz->db);
|
2022-09-12 16:36:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
INSIST(!catz->updaterunning);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_free(&catz->name, mctx);
|
|
|
|
dns_catz_options_free(&catz->defoptions, mctx);
|
|
|
|
dns_catz_options_free(&catz->zoneoptions, mctx);
|
|
|
|
|
|
|
|
catz->catzs = NULL;
|
|
|
|
isc_refcount_destroy(&catz->references);
|
2022-09-12 16:36:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_mem_put(mctx, catz, sizeof(*catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 14:11:04 +00:00
|
|
|
static void
|
|
|
|
dns__catz_zones_destroy(dns_catz_zones_t *catzs) {
|
2023-02-21 21:14:44 +00:00
|
|
|
REQUIRE(atomic_load(&catzs->shuttingdown));
|
|
|
|
REQUIRE(catzs->zones == NULL);
|
|
|
|
|
|
|
|
catzs->magic = 0;
|
|
|
|
isc_mutex_destroy(&catzs->lock);
|
|
|
|
isc_refcount_destroy(&catzs->references);
|
|
|
|
|
|
|
|
isc_mem_putanddetach(&catzs->mctx, catzs, sizeof(*catzs));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_catz_shutdown_catzs(dns_catz_zones_t *catzs) {
|
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
|
|
|
|
|
|
|
if (!atomic_compare_exchange_strong(&catzs->shuttingdown,
|
|
|
|
&(bool){ false }, true))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCK(&catzs->lock);
|
2023-02-21 14:11:04 +00:00
|
|
|
if (catzs->zones != NULL) {
|
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_ht_iter_create(catzs->zones, &iter);
|
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;)
|
|
|
|
{
|
2023-02-21 21:14:44 +00:00
|
|
|
dns_catz_zone_t *catz = NULL;
|
|
|
|
isc_ht_iter_current(iter, (void **)&catz);
|
2023-02-21 14:11:04 +00:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter);
|
2023-02-21 21:14:44 +00:00
|
|
|
dns__catz_shutdown(catz);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2023-02-21 14:11:04 +00:00
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
|
|
|
INSIST(isc_ht_count(catzs->zones) == 0);
|
|
|
|
isc_ht_destroy(&catzs->zones);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2023-02-21 21:14:44 +00:00
|
|
|
UNLOCK(&catzs->lock);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 14:11:04 +00:00
|
|
|
#ifdef DNS_CATZ_TRACE
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(dns_catz_zone, dns__catz_zone_destroy);
|
|
|
|
ISC_REFCOUNT_TRACE_IMPL(dns_catz_zones, dns__catz_zones_destroy);
|
|
|
|
#else
|
|
|
|
ISC_REFCOUNT_IMPL(dns_catz_zone, dns__catz_zone_destroy);
|
|
|
|
ISC_REFCOUNT_IMPL(dns_catz_zones, dns__catz_zones_destroy);
|
|
|
|
#endif
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
typedef enum {
|
|
|
|
CATZ_OPT_NONE,
|
|
|
|
CATZ_OPT_ZONES,
|
2022-03-17 13:09:11 +00:00
|
|
|
CATZ_OPT_COO,
|
2022-03-16 20:11:17 +00:00
|
|
|
CATZ_OPT_VERSION,
|
|
|
|
CATZ_OPT_CUSTOM_START, /* CATZ custom properties must go below this */
|
|
|
|
CATZ_OPT_EXT,
|
2022-03-25 11:28:07 +00:00
|
|
|
CATZ_OPT_PRIMARIES,
|
2016-05-26 21:23:19 +02:00
|
|
|
CATZ_OPT_ALLOW_QUERY,
|
|
|
|
CATZ_OPT_ALLOW_TRANSFER,
|
|
|
|
} catz_opt_t;
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2016-05-26 21:23:19 +02:00
|
|
|
catz_opt_cmp(const dns_label_t *option, const char *opt) {
|
2021-09-03 00:59:57 +00:00
|
|
|
size_t len = strlen(opt);
|
|
|
|
|
|
|
|
if (option->length - 1 == len &&
|
2022-11-02 19:33:14 +01:00
|
|
|
memcmp(opt, option->base + 1, len) == 0)
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static catz_opt_t
|
|
|
|
catz_get_option(const dns_label_t *option) {
|
2022-03-16 20:11:17 +00:00
|
|
|
if (catz_opt_cmp(option, "ext")) {
|
|
|
|
return (CATZ_OPT_EXT);
|
|
|
|
} else if (catz_opt_cmp(option, "zones")) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (CATZ_OPT_ZONES);
|
2021-09-03 00:56:47 +00:00
|
|
|
} else if (catz_opt_cmp(option, "masters") ||
|
2022-11-02 19:33:14 +01:00
|
|
|
catz_opt_cmp(option, "primaries"))
|
|
|
|
{
|
2022-03-25 11:28:07 +00:00
|
|
|
return (CATZ_OPT_PRIMARIES);
|
2016-05-26 21:23:19 +02:00
|
|
|
} 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);
|
2022-03-17 13:09:11 +00:00
|
|
|
} else if (catz_opt_cmp(option, "coo")) {
|
|
|
|
return (CATZ_OPT_COO);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else if (catz_opt_cmp(option, "version")) {
|
|
|
|
return (CATZ_OPT_VERSION);
|
|
|
|
} else {
|
|
|
|
return (CATZ_OPT_NONE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_zones(dns_catz_zone_t *catz, dns_rdataset_t *value,
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_t *name) {
|
|
|
|
dns_label_t mhash;
|
|
|
|
dns_name_t opt;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-06-22 10:49:25 +02:00
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
if (name->labels == 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
dns_name_getlabel(name, name->labels - 1, &mhash);
|
|
|
|
|
|
|
|
if (name->labels == 1) {
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_zones_entry(catz, value, &mhash));
|
2016-06-22 10:49:25 +02:00
|
|
|
} else {
|
|
|
|
dns_name_init(&opt, NULL);
|
|
|
|
dns_name_split(name, 1, &opt, NULL);
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_zones_suboption(catz, value, &mhash,
|
2016-06-22 10:49:25 +02:00
|
|
|
&opt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_coo(dns_catz_zone_t *catz, dns_label_t *mhash,
|
2022-03-17 13:09:11 +00:00
|
|
|
dns_rdataset_t *value) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_ptr_t ptr;
|
|
|
|
dns_catz_entry_t *entry = NULL;
|
|
|
|
dns_catz_coo_t *ncoo = NULL;
|
|
|
|
dns_catz_coo_t *ocoo = NULL;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-03-17 13:09:11 +00:00
|
|
|
REQUIRE(mhash != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
|
|
|
/* Change of Ownership was introduced in version "2" of the schema. */
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->version < 2) {
|
2022-03-17 13:09:11 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2022-04-15 15:50:43 +00:00
|
|
|
if (value->type != dns_rdatatype_ptr) {
|
2022-03-17 13:09:11 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2022-03-17 14:43:18 +00:00
|
|
|
if (dns_rdataset_count(value) != 1) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: 'coo' property PTR RRset contains "
|
|
|
|
"more than one record, which is invalid");
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
|
|
|
|
result = dns_rdata_tostruct(&rdata, &ptr, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dns_name_countlabels(&ptr.ptr) == 0) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catz->entries, mhash->base, mhash->length,
|
2022-03-17 13:09:11 +00:00
|
|
|
(void **)&entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
/* The entry was not found .*/
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dns_name_countlabels(&entry->name) == 0) {
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catz->coos, entry->name.ndata, entry->name.length,
|
2022-03-17 13:09:11 +00:00
|
|
|
(void **)&ocoo);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
/* The change of ownership permission was already registered. */
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_coo_new(catz->catzs->mctx, &ptr.ptr, &ncoo);
|
|
|
|
result = isc_ht_add(catz->coos, entry->name.ndata, entry->name.length,
|
2022-03-17 13:09:11 +00:00
|
|
|
ncoo);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_coo_detach(catz, &ncoo);
|
2022-03-17 13:09:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_zones_entry(dns_catz_zone_t *catz, dns_rdataset_t *value,
|
2016-06-22 10:49:25 +02:00
|
|
|
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;
|
|
|
|
|
2022-04-15 15:50:43 +00:00
|
|
|
if (value->type != dns_rdatatype_ptr) {
|
2022-03-17 14:43:18 +00:00
|
|
|
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: member zone PTR RRset contains "
|
|
|
|
"more than one record, which is invalid");
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->broken = true;
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-03-17 14:43:18 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
result = dns_rdata_tostruct(&rdata, &ptr, NULL);
|
2022-03-17 14:43:18 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catz->entries, mhash->base, mhash->length,
|
2016-06-22 10:49:25 +02:00
|
|
|
(void **)&entry);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
if (dns_name_countlabels(&entry->name) != 0) {
|
|
|
|
/* We have a duplicate. */
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
return (ISC_R_FAILURE);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_dup(&ptr.ptr, catz->catzs->mctx, &entry->name);
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_new(catz->catzs->mctx, &ptr.ptr, &entry);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_add(catz->entries, mhash->base, mhash->length,
|
2016-06-22 10:49:25 +02:00
|
|
|
entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_rdata_freestruct(&ptr);
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &entry);
|
2016-06-22 10:49:25 +02:00
|
|
|
return (result);
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_version(dns_catz_zone_t *catz, 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;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t tversion;
|
2016-05-26 21:23:19 +02:00
|
|
|
char t[16];
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
2022-04-15 15:50:43 +00:00
|
|
|
if (value->type != dns_rdatatype_txt) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-17 14:43:18 +00:00
|
|
|
if (dns_rdataset_count(value) != 1) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: 'version' property TXT RRset contains "
|
|
|
|
"more than one record, which is invalid");
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-31 08:12:51 +10:00
|
|
|
|
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);
|
2022-03-17 14:43:18 +00:00
|
|
|
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_rdata_txt_first(&rdatatxt);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
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;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
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;
|
|
|
|
}
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(t, rdatastr.data, rdatastr.length);
|
2016-05-26 21:23:19 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->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);
|
2022-03-17 14:43:18 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: invalid record for the catalog "
|
|
|
|
"zone version property");
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
}
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_primaries(dns_catz_zone_t *catz, dns_ipkeylist_t *ipkl,
|
2021-10-05 11:28:24 +02:00
|
|
|
dns_rdataset_t *value, 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_rdata_t rdata;
|
2016-05-31 08:12:51 +10:00
|
|
|
dns_rdata_in_a_t rdata_a;
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_rdata_in_aaaa_t rdata_aaaa;
|
|
|
|
dns_rdata_txt_t rdata_txt;
|
|
|
|
dns_rdata_txt_string_t rdatastr;
|
|
|
|
dns_name_t *keyname = NULL;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
char keycbuf[DNS_NAME_FORMATSIZE];
|
|
|
|
isc_buffer_t keybuf;
|
2016-05-31 08:12:51 +10:00
|
|
|
unsigned int rcount;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(ipkl != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
2016-05-31 08:12:51 +10:00
|
|
|
REQUIRE(dns_rdataset_isassociated(value));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
mctx = catz->catzs->mctx;
|
2016-06-22 10:49:25 +02:00
|
|
|
memset(&rdata_a, 0, sizeof(rdata_a));
|
|
|
|
memset(&rdata_aaaa, 0, sizeof(rdata_aaaa));
|
|
|
|
memset(&rdata_txt, 0, sizeof(rdata_txt));
|
|
|
|
isc_buffer_init(&keybuf, keycbuf, sizeof(keycbuf));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have three possibilities here:
|
|
|
|
* - either empty name and IN A/IN AAAA record
|
|
|
|
* - label and IN A/IN AAAA
|
|
|
|
* - label and IN TXT - TSIG key name
|
|
|
|
*/
|
|
|
|
if (name->labels > 0) {
|
|
|
|
isc_sockaddr_t sockaddr;
|
2021-10-06 12:43:35 +02:00
|
|
|
size_t i;
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/*
|
|
|
|
* We're pre-preparing the data once, we'll put it into
|
2021-10-05 11:07:44 +02:00
|
|
|
* the right spot in the primaries array once we find it.
|
2016-06-22 10:49:25 +02:00
|
|
|
*/
|
|
|
|
result = dns_rdataset_first(value);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
dns_rdata_init(&rdata);
|
|
|
|
dns_rdataset_current(value, &rdata);
|
|
|
|
switch (value->type) {
|
|
|
|
case dns_rdatatype_a:
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_a, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
isc_sockaddr_fromin(&sockaddr, &rdata_a.in_addr, 0);
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_a);
|
2016-06-22 10:49:25 +02:00
|
|
|
break;
|
|
|
|
case dns_rdatatype_aaaa:
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_aaaa, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
isc_sockaddr_fromin6(&sockaddr, &rdata_aaaa.in6_addr,
|
|
|
|
0);
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_aaaa);
|
2016-06-22 10:49:25 +02:00
|
|
|
break;
|
|
|
|
case dns_rdatatype_txt:
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_txt, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
result = dns_rdata_txt_first(&rdata_txt);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_txt);
|
2016-06-22 10:49:25 +02:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
result = dns_rdata_txt_current(&rdata_txt, &rdatastr);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_txt);
|
2016-06-22 10:49:25 +02:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
result = dns_rdata_txt_next(&rdata_txt);
|
|
|
|
if (result != ISC_R_NOMORE) {
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_txt);
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
/* rdatastr.length < DNS_NAME_MAXTEXT */
|
2023-02-09 10:32:33 +00:00
|
|
|
keyname = isc_mem_get(mctx, sizeof(*keyname));
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_init(keyname, 0);
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(keycbuf, rdatastr.data, rdatastr.length);
|
2016-06-22 10:49:25 +02:00
|
|
|
keycbuf[rdatastr.length] = 0;
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_txt);
|
2016-06-22 10:49:25 +02:00
|
|
|
result = dns_name_fromstring(keyname, keycbuf, 0, mctx);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_name_free(keyname, mctx);
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_mem_put(mctx, keyname, sizeof(*keyname));
|
2016-06-22 10:49:25 +02:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2021-10-05 11:07:44 +02:00
|
|
|
* We have to find the appropriate labeled record in
|
|
|
|
* primaries if it exists. In the common case we'll
|
|
|
|
* have no more than 3-4 records here, so no optimization.
|
2016-06-22 10:49:25 +02:00
|
|
|
*/
|
|
|
|
for (i = 0; i < ipkl->count; i++) {
|
2016-06-26 17:23:58 +10:00
|
|
|
if (ipkl->labels[i] != NULL &&
|
2022-11-02 19:33:14 +01:00
|
|
|
!dns_name_compare(name, ipkl->labels[i]))
|
|
|
|
{
|
2016-06-22 10:49:25 +02:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i < ipkl->count) { /* we have this record already */
|
|
|
|
if (value->type == dns_rdatatype_txt) {
|
|
|
|
ipkl->keys[i] = keyname;
|
|
|
|
} else { /* A/AAAA */
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(&ipkl->addrs[i], &sockaddr,
|
2023-02-09 10:32:33 +00:00
|
|
|
sizeof(sockaddr));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
} else {
|
|
|
|
result = dns_ipkeylist_resize(mctx, ipkl, i + 1);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
ipkl->labels[i] = isc_mem_get(mctx,
|
|
|
|
sizeof(*ipkl->labels[0]));
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_init(ipkl->labels[i], NULL);
|
2019-11-01 08:31:13 -05:00
|
|
|
dns_name_dup(name, mctx, ipkl->labels[i]);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
if (value->type == dns_rdatatype_txt) {
|
|
|
|
ipkl->keys[i] = keyname;
|
|
|
|
} else { /* A/AAAA */
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(&ipkl->addrs[i], &sockaddr,
|
2023-02-09 10:32:33 +00:00
|
|
|
sizeof(sockaddr));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
ipkl->count++;
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
/* else - 'simple' case - without labels */
|
|
|
|
|
|
|
|
if (value->type != dns_rdatatype_a && value->type != dns_rdatatype_aaaa)
|
|
|
|
{
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
rcount = dns_rdataset_count(value) + ipkl->count;
|
|
|
|
|
|
|
|
result = dns_ipkeylist_resize(mctx, ipkl, rcount);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2016-05-31 08:12:51 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
/*
|
|
|
|
* port 0 == take the default
|
|
|
|
*/
|
2016-06-22 10:49:25 +02:00
|
|
|
if (value->type == dns_rdatatype_a) {
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_a, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
isc_sockaddr_fromin(&ipkl->addrs[ipkl->count],
|
|
|
|
&rdata_a.in_addr, 0);
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_a);
|
2016-06-22 10:49:25 +02:00
|
|
|
} else {
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_aaaa, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
isc_sockaddr_fromin6(&ipkl->addrs[ipkl->count],
|
|
|
|
&rdata_aaaa.in6_addr, 0);
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&rdata_aaaa);
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
ipkl->keys[ipkl->count] = NULL;
|
2016-06-22 10:49:25 +02:00
|
|
|
ipkl->labels[ipkl->count] = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
ipkl->count++;
|
2016-05-31 08:12:51 +10:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_apl(dns_catz_zone_t *catz, isc_buffer_t **aclbp,
|
2016-06-20 13:39:44 +02:00
|
|
|
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 */
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-06-20 13:39:44 +02:00
|
|
|
REQUIRE(aclbp != NULL);
|
|
|
|
REQUIRE(*aclbp == NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
REQUIRE(dns_rdataset_isassociated(value));
|
|
|
|
|
2022-04-15 15:50:43 +00:00
|
|
|
if (value->type != dns_rdatatype_apl) {
|
2016-06-20 13:39:44 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
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);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_apl, catz->catzs->mctx);
|
2016-06-20 13:39:44 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_buffer_allocate(catz->catzs->mctx, &aclb, 16);
|
2016-06-20 13:39:44 +02:00
|
|
|
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));
|
2018-01-22 09:36:12 +11:00
|
|
|
if (apl_ent.data != NULL && apl_ent.length > 0) {
|
|
|
|
memmove(buf, apl_ent.data, apl_ent.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
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? */
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
if (apl_ent.negative) {
|
|
|
|
isc_buffer_putuint8(aclb, '!');
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2022-12-15 11:54:51 +01:00
|
|
|
isc_buffer_reserve(aclb, INET6_ADDRSTRLEN);
|
2016-06-20 13:39:44 +02:00
|
|
|
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, '/');
|
2022-12-15 22:15:37 +01:00
|
|
|
isc_buffer_printf(aclb, "%" PRId8, apl_ent.prefix);
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
|
|
|
isc_buffer_putstr(aclb, "; ");
|
|
|
|
}
|
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
} else {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
*aclbp = aclb;
|
|
|
|
aclb = NULL;
|
|
|
|
cleanup:
|
|
|
|
if (aclb != NULL) {
|
|
|
|
isc_buffer_free(&aclb);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
dns_rdata_freestruct(&rdata_apl);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_zones_suboption(dns_catz_zone_t *catz, dns_rdataset_t *value,
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t *mhash, 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_entry_t *entry = NULL;
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t option;
|
|
|
|
dns_name_t prefix;
|
|
|
|
catz_opt_t opt;
|
2022-03-16 20:11:17 +00:00
|
|
|
unsigned int suffix_labels = 1;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(mhash != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-16 20:11:17 +00:00
|
|
|
if (name->labels < 1) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_getlabel(name, name->labels - 1, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
|
2022-03-16 20:11:17 +00:00
|
|
|
/*
|
|
|
|
* The custom properties in version 2 schema must be placed under the
|
|
|
|
* "ext" label.
|
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->version >= 2 && opt >= CATZ_OPT_CUSTOM_START) {
|
2022-03-16 20:11:17 +00:00
|
|
|
if (opt != CATZ_OPT_EXT || name->labels < 2) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
suffix_labels++;
|
|
|
|
dns_name_getlabel(name, name->labels - 2, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-06-22 10:49:25 +02:00
|
|
|
* We're adding this entry now, in case the option is invalid we'll get
|
|
|
|
* rid of it in verification phase.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catz->entries, mhash->base, mhash->length,
|
2016-06-22 10:49:25 +02:00
|
|
|
(void **)&entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_new(catz->catzs->mctx, NULL, &entry);
|
|
|
|
result = isc_ht_add(catz->entries, mhash->base, mhash->length,
|
2016-05-31 08:12:51 +10:00
|
|
|
entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_init(&prefix, NULL);
|
2022-03-16 20:11:17 +00:00
|
|
|
dns_name_split(name, suffix_labels, &prefix, NULL);
|
2016-06-22 10:49:25 +02:00
|
|
|
switch (opt) {
|
2022-03-17 13:09:11 +00:00
|
|
|
case CATZ_OPT_COO:
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_coo(catz, mhash, value));
|
2022-03-25 11:28:07 +00:00
|
|
|
case CATZ_OPT_PRIMARIES:
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_primaries(catz, &entry->opts.masters,
|
2021-10-05 11:28:24 +02:00
|
|
|
value, &prefix));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2016-06-22 10:49:25 +02:00
|
|
|
if (prefix.labels != 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_apl(catz, &entry->opts.allow_query,
|
2016-06-20 13:39:44 +02:00
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_TRANSFER:
|
2016-06-22 10:49:25 +02:00
|
|
|
if (prefix.labels != 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_apl(catz, &entry->opts.allow_transfer,
|
2016-06-20 13:39:44 +02:00
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_entry_add_or_mod(dns_catz_zone_t *catz, isc_ht_t *ht, unsigned char *key,
|
2021-09-24 17:42:12 +00:00
|
|
|
size_t keysize, dns_catz_entry_t *nentry,
|
|
|
|
dns_catz_entry_t *oentry, const char *msg,
|
|
|
|
const char *zname, const char *czname) {
|
|
|
|
isc_result_t result = isc_ht_add(ht, key, (uint32_t)keysize, nentry);
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: error %s zone '%s' from catalog '%s' - %s",
|
|
|
|
msg, zname, czname, isc_result_totext(result));
|
|
|
|
}
|
|
|
|
if (oentry != NULL) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_entry_detach(catz, &oentry);
|
|
|
|
result = isc_ht_delete(catz->entries, key, (uint32_t)keysize);
|
2021-09-24 17:42:12 +00:00
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
static isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_process_value(dns_catz_zone_t *catz, dns_name_t *name,
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_rdataset_t *rdataset) {
|
|
|
|
dns_label_t option;
|
|
|
|
dns_name_t prefix;
|
|
|
|
catz_opt_t opt;
|
2022-03-16 20:11:17 +00:00
|
|
|
unsigned int suffix_labels = 1;
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
2016-06-22 10:49:25 +02:00
|
|
|
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-16 20:11:17 +00:00
|
|
|
if (name->labels < 1) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_getlabel(name, name->labels - 1, &option);
|
|
|
|
opt = catz_get_option(&option);
|
2022-03-16 20:11:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The custom properties in version 2 schema must be placed under the
|
|
|
|
* "ext" label.
|
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->version >= 2 && opt >= CATZ_OPT_CUSTOM_START) {
|
2022-03-16 20:11:17 +00:00
|
|
|
if (opt != CATZ_OPT_EXT || name->labels < 2) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
suffix_labels++;
|
|
|
|
dns_name_getlabel(name, name->labels - 2, &option);
|
|
|
|
opt = catz_get_option(&option);
|
|
|
|
}
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_init(&prefix, NULL);
|
2022-03-16 20:11:17 +00:00
|
|
|
dns_name_split(name, suffix_labels, &prefix, NULL);
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
switch (opt) {
|
|
|
|
case CATZ_OPT_ZONES:
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_zones(catz, rdataset, &prefix));
|
2022-03-25 11:28:07 +00:00
|
|
|
case CATZ_OPT_PRIMARIES:
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_primaries(catz, &catz->zoneoptions.masters,
|
2021-10-05 11:28:24 +02:00
|
|
|
rdataset, &prefix));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2016-06-22 10:49:25 +02:00
|
|
|
if (prefix.labels != 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_apl(catz, &catz->zoneoptions.allow_query,
|
2016-06-22 10:49:25 +02:00
|
|
|
rdataset));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_TRANSFER:
|
2016-06-22 10:49:25 +02:00
|
|
|
if (prefix.labels != 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
return (catz_process_apl(
|
2023-02-09 10:32:33 +00:00
|
|
|
catz, &catz->zoneoptions.allow_transfer, rdataset));
|
2016-06-22 10:49:25 +02:00
|
|
|
case CATZ_OPT_VERSION:
|
|
|
|
if (prefix.labels != 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
return (catz_process_version(catz, rdataset));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
/*%<
|
|
|
|
* Process a single rdataset from a catalog zone 'catz' update, src_name is the
|
|
|
|
* record name.
|
|
|
|
*
|
|
|
|
* Requires:
|
|
|
|
* \li 'catz' is a valid dns_catz_zone_t.
|
|
|
|
* \li 'src_name' is a valid dns_name_t.
|
|
|
|
* \li 'rdataset' is valid rdataset.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
|
|
|
dns__catz_update_process(dns_catz_zone_t *catz, const 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;
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(ISC_MAGIC_VALID(src_name, DNS_NAME_MAGIC));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-17 14:43:18 +00:00
|
|
|
if (rdataset->rdclass != dns_rdataclass_in) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: RR found which has a non-IN class");
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
nrres = dns_name_fullcompare(src_name, &catz->name, &order, &nlabels);
|
2016-05-26 21:23:19 +02:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-31 08:12:51 +10:00
|
|
|
|
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?
|
|
|
|
*/
|
2022-03-17 14:09:21 +00:00
|
|
|
dns_rdata_freestruct(&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);
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_split(src_name, catz->name.labels, &prefix, NULL);
|
|
|
|
result = catz_process_value(catz, &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
|
|
|
}
|
|
|
|
|
2018-06-01 09:31:59 +02:00
|
|
|
static isc_result_t
|
|
|
|
digest2hex(unsigned char *digest, unsigned int digestlen, char *hash,
|
|
|
|
size_t hashlen) {
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < digestlen; i++) {
|
|
|
|
size_t left = hashlen - i * 2;
|
2021-10-06 12:43:35 +02:00
|
|
|
int ret = snprintf(hash + i * 2, left, "%02x", digest[i]);
|
2018-06-01 09:31:59 +02:00
|
|
|
if (ret < 0 || (size_t)ret >= left) {
|
|
|
|
return (ISC_R_NOSPACE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_generate_masterfilename(dns_catz_zone_t *catz, dns_catz_entry_t *entry,
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_t **buffer) {
|
|
|
|
isc_buffer_t *tbuf = NULL;
|
|
|
|
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;
|
2020-01-30 15:30:32 -08:00
|
|
|
bool special = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-12-01 12:51:30 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(buffer != NULL && *buffer != NULL);
|
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_buffer_allocate(catz->catzs->mctx, &tbuf,
|
|
|
|
strlen(catz->catzs->view->name) +
|
2020-02-02 08:35:46 +01:00
|
|
|
2 * DNS_NAME_FORMATSIZE + 2);
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_buffer_putstr(tbuf, catz->catzs->view->name);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(tbuf, "_");
|
2023-02-09 10:32:33 +00:00
|
|
|
result = dns_name_totext(&catz->name, true, tbuf);
|
2020-01-30 15:30:32 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(tbuf, "_");
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_totext(&entry->name, true, tbuf);
|
2020-01-30 15:30:32 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for slash and other special characters in the view and
|
|
|
|
* zone names. Add a null terminator so we can use strpbrk(), then
|
|
|
|
* remove it.
|
|
|
|
*/
|
|
|
|
isc_buffer_putuint8(tbuf, 0);
|
|
|
|
if (strpbrk(isc_buffer_base(tbuf), "\\/:") != NULL) {
|
|
|
|
special = true;
|
|
|
|
}
|
|
|
|
isc_buffer_subtract(tbuf, 1);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 10:36:27 -07:00
|
|
|
/* __catz__<digest>.db */
|
2018-06-01 09:31:59 +02:00
|
|
|
rlen = (isc_md_type_get_size(ISC_MD_SHA256) * 2 + 1) + 12;
|
2016-05-31 10:36:27 -07:00
|
|
|
|
|
|
|
/* optionally prepend with <zonedir>/ */
|
2020-01-30 15:30:32 -08:00
|
|
|
if (entry->opts.zonedir != NULL) {
|
2016-05-31 10:36:27 -07:00
|
|
|
rlen += strlen(entry->opts.zonedir) + 1;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
result = isc_buffer_reserve(*buffer, (unsigned int)rlen);
|
2020-01-30 15:30:32 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
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__");
|
2020-01-30 15:30:32 -08:00
|
|
|
if (special || tbuf->used > ISC_SHA256_DIGESTLENGTH * 2 + 1) {
|
2018-06-01 09:31:59 +02:00
|
|
|
unsigned char digest[ISC_MAX_MD_SIZE];
|
|
|
|
unsigned int digestlen;
|
2020-01-30 15:30:32 -08:00
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
/* we can do that because digest string < 2 * DNS_NAME */
|
2018-06-01 09:31:59 +02:00
|
|
|
result = isc_md(ISC_MD_SHA256, r.base, r.length, digest,
|
|
|
|
&digestlen);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
result = digest2hex(digest, digestlen, (char *)r.base,
|
|
|
|
ISC_SHA256_DIGESTLENGTH * 2 + 1);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-10-05 11:07:44 +02:00
|
|
|
/*
|
|
|
|
* We have to generate a text buffer with regular zone config:
|
|
|
|
* zone "foo.bar" {
|
|
|
|
* type secondary;
|
2023-01-05 22:18:55 -08:00
|
|
|
* primaries { ip1 port port1; ip2 port port2; };
|
2021-10-05 11:07:44 +02:00
|
|
|
* }
|
|
|
|
*/
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_result_t
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_generate_zonecfg(dns_catz_zone_t *catz, dns_catz_entry_t *entry,
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_t **buf) {
|
|
|
|
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;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t i;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_netaddr_t netaddr;
|
2023-01-05 22:18:55 -08:00
|
|
|
char pbuf[sizeof("65535")]; /* used for port number */
|
2018-01-15 20:49:05 +01:00
|
|
|
char zname[DNS_NAME_FORMATSIZE];
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-12-01 12:51:30 +11:00
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(buf != NULL && *buf == NULL);
|
|
|
|
|
|
|
|
/*
|
2016-05-31 08:12:51 +10:00
|
|
|
* The buffer will be reallocated if something won't fit,
|
2017-07-12 09:38:24 +02:00
|
|
|
* ISC_BUFFER_INCR seems like a good start.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_buffer_allocate(catz->catzs->mctx, &buffer, ISC_BUFFER_INCR);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-01-30 15:30:32 -08:00
|
|
|
isc_buffer_putstr(buffer, "zone \"");
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_name_totext(&entry->name, true, buffer);
|
2021-10-05 11:28:24 +02:00
|
|
|
isc_buffer_putstr(buffer, "\" { type secondary; primaries");
|
2017-07-12 09:38:24 +02:00
|
|
|
|
|
|
|
isc_buffer_putstr(buffer, " { ");
|
2016-05-26 21:23:19 +02:00
|
|
|
for (i = 0; i < entry->opts.masters.count; i++) {
|
2018-01-15 20:49:05 +01:00
|
|
|
/*
|
2021-10-05 11:07:44 +02:00
|
|
|
* Every primary must have an IP address assigned.
|
2018-01-15 20:49:05 +01:00
|
|
|
*/
|
|
|
|
switch (entry->opts.masters.addrs[i].type.sa.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
case AF_INET6:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
dns_name_format(&entry->name, zname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
2021-10-05 11:28:24 +02:00
|
|
|
"catz: zone '%s' uses an invalid primary "
|
2018-01-15 20:49:05 +01:00
|
|
|
"(no IP address assigned)",
|
|
|
|
zname);
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_netaddr_fromsockaddr(&netaddr,
|
|
|
|
&entry->opts.masters.addrs[i]);
|
2022-12-15 11:54:51 +01:00
|
|
|
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
|
|
|
|
2017-07-12 09:38:24 +02:00
|
|
|
isc_buffer_putstr(buffer, " port ");
|
|
|
|
snprintf(pbuf, sizeof(pbuf), "%u",
|
|
|
|
isc_sockaddr_getport(&entry->opts.masters.addrs[i]));
|
|
|
|
isc_buffer_putstr(buffer, pbuf);
|
|
|
|
|
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],
|
2018-04-17 08:29:14 -07:00
|
|
|
true, buffer);
|
2020-01-30 15:30:32 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
goto cleanup;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2022-11-02 06:55:52 +00:00
|
|
|
|
|
|
|
if (entry->opts.masters.tlss[i] != NULL) {
|
|
|
|
isc_buffer_putstr(buffer, " tls ");
|
|
|
|
result = dns_name_totext(entry->opts.masters.tlss[i],
|
|
|
|
true, buffer);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(buffer, "; ");
|
|
|
|
}
|
2018-01-15 20:49:05 +01:00
|
|
|
isc_buffer_putstr(buffer, "}; ");
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!entry->opts.in_memory) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(buffer, "file \"");
|
2023-02-09 10:32:33 +00:00
|
|
|
result = dns_catz_generate_masterfilename(catz, entry, &buffer);
|
2020-01-30 15:30:32 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-31 08:12:51 +10:00
|
|
|
goto cleanup;
|
2020-01-30 15:30:32 -08:00
|
|
|
}
|
2018-01-15 20:49:05 +01:00
|
|
|
isc_buffer_putstr(buffer, "\"; ");
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
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);
|
2018-01-15 20:49:05 +01:00
|
|
|
isc_buffer_putstr(buffer, "}; ");
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
|
|
|
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);
|
2018-01-15 20:49:05 +01:00
|
|
|
isc_buffer_putstr(buffer, "}; ");
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
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;
|
2020-01-30 15:30:32 -08:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
cleanup:
|
2020-02-05 15:41:26 +11:00
|
|
|
isc_buffer_free(&buffer);
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
static void
|
|
|
|
dns__catz_timer_cb(void *arg) {
|
|
|
|
char domain[DNS_NAME_FORMATSIZE];
|
|
|
|
dns_catz_zone_t *catz = (dns_catz_zone_t *)arg;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-24 09:46:00 +00:00
|
|
|
if (atomic_load(&catz->catzs->shuttingdown)) {
|
|
|
|
return;
|
2023-02-21 14:23:38 +00:00
|
|
|
}
|
|
|
|
|
2023-02-24 09:46:00 +00:00
|
|
|
LOCK(&catz->catzs->lock);
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
INSIST(DNS_DB_VALID(catz->db));
|
2023-03-02 13:19:53 +00:00
|
|
|
INSIST(catz->dbversion != NULL);
|
2023-03-02 08:52:25 +00:00
|
|
|
INSIST(catz->updb == NULL);
|
|
|
|
INSIST(catz->updbversion == NULL);
|
2023-02-21 14:23:38 +00:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->updatepending = false;
|
2023-02-21 14:23:38 +00:00
|
|
|
catz->updaterunning = true;
|
|
|
|
catz->updateresult = ISC_R_UNSET;
|
|
|
|
|
2023-03-02 13:19:53 +00:00
|
|
|
dns_name_format(&catz->name, domain, DNS_NAME_FORMATSIZE);
|
|
|
|
|
|
|
|
if (!catz->active) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: %s: no longer active, reload is canceled",
|
|
|
|
domain);
|
|
|
|
catz->updaterunning = false;
|
|
|
|
catz->updateresult = ISC_R_CANCELED;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_attach(catz->db, &catz->updb);
|
|
|
|
catz->updbversion = catz->dbversion;
|
|
|
|
catz->dbversion = NULL;
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_INFO, "catz: %s: reload start", domain);
|
|
|
|
|
|
|
|
dns_catz_ref_catzs(catz->catzs);
|
2023-03-21 09:56:36 +00:00
|
|
|
dns_catz_ref_catz(catz);
|
2023-02-21 14:23:38 +00:00
|
|
|
isc_work_enqueue(catz->loop, dns__catz_update_cb, dns__catz_done_cb,
|
|
|
|
catz);
|
|
|
|
|
2023-03-02 13:19:53 +00:00
|
|
|
exit:
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_timer_destroy(&catz->updatetimer);
|
2023-02-21 21:14:44 +00:00
|
|
|
catz->loop = NULL;
|
2023-02-21 14:23:38 +00:00
|
|
|
|
2023-03-31 00:12:33 +02:00
|
|
|
catz->lastupdated = isc_time_now();
|
2023-02-24 09:46:00 +00:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
UNLOCK(&catz->catzs->lock);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zones_t *catzs = NULL;
|
|
|
|
dns_catz_zone_t *catz = NULL;
|
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));
|
2022-12-01 12:51:30 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(fn_arg));
|
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);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&catz);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/* New zone came as AXFR */
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->db != NULL && catz->db != db) {
|
|
|
|
if (catz->dbversion != NULL) {
|
|
|
|
dns_db_closeversion(catz->db, &catz->dbversion, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-01-27 08:47:52 +00:00
|
|
|
dns_db_updatenotify_unregister(
|
|
|
|
catz->db, dns_catz_dbupdate_callback, catz->catzs);
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_db_detach(&catz->db);
|
2016-06-22 10:49:25 +02:00
|
|
|
/*
|
|
|
|
* We're not registering db update callback, it will be
|
2023-02-21 14:23:38 +00:00
|
|
|
* registered at the end of dns__catz_update_cb()
|
2016-06-22 10:49:25 +02:00
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->db_registered = false;
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
if (catz->db == NULL) {
|
|
|
|
dns_db_attach(db, &catz->db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
if (!catz->updatepending && !catz->updaterunning) {
|
2023-02-09 10:32:33 +00:00
|
|
|
catz->updatepending = true;
|
|
|
|
dns_db_currentversion(db, &catz->dbversion);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns__catz_timer_start(catz);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
2023-02-09 10:32:33 +00:00
|
|
|
char dname[DNS_NAME_FORMATSIZE];
|
|
|
|
|
|
|
|
catz->updatepending = true;
|
|
|
|
dns_name_format(&catz->name, dname, DNS_NAME_FORMATSIZE);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
2023-02-09 10:32:33 +00:00
|
|
|
"catz: %s: update already queued or running",
|
|
|
|
dname);
|
|
|
|
if (catz->dbversion != NULL) {
|
|
|
|
dns_db_closeversion(catz->db, &catz->dbversion, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_db_currentversion(catz->db, &catz->dbversion);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-06-01 08:51:55 +00:00
|
|
|
static bool
|
|
|
|
catz_rdatatype_is_processable(const dns_rdatatype_t type) {
|
|
|
|
return (!dns_rdatatype_isdnssec(type) && type != dns_rdatatype_cds &&
|
|
|
|
type != dns_rdatatype_cdnskey && type != dns_rdatatype_zonemd);
|
|
|
|
}
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
/*
|
|
|
|
* Process an updated database for a catalog zone.
|
|
|
|
* It creates a new catz, iterates over database to fill it with content, and
|
|
|
|
* then merges new catz into old catz.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dns__catz_update_cb(void *data) {
|
|
|
|
dns_catz_zone_t *catz = (dns_catz_zone_t *)data;
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_t *updb = NULL;
|
2023-02-21 14:23:38 +00:00
|
|
|
dns_catz_zones_t *catzs = NULL;
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t *oldcatz = NULL, *newcatz = 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;
|
2022-03-24 20:24:00 +00:00
|
|
|
const dns_dbnode_t *vers_node = NULL;
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_dbiterator_t *updbit = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_fixedname_t fixname;
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_t *name = NULL;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
char bname[DNS_NAME_FORMATSIZE];
|
2022-03-17 14:43:18 +00:00
|
|
|
char cname[DNS_NAME_FORMATSIZE];
|
2022-03-24 20:24:00 +00:00
|
|
|
bool is_vers_processed = false;
|
2023-03-02 13:32:21 +00:00
|
|
|
bool is_active;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t vers;
|
2022-03-17 14:43:18 +00:00
|
|
|
uint32_t catz_vers;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2023-03-27 10:56:22 +00:00
|
|
|
REQUIRE(DNS_DB_VALID(catz->updb));
|
2023-02-21 14:23:38 +00:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catz->catzs));
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
updb = catz->updb;
|
2023-02-21 14:23:38 +00:00
|
|
|
catzs = catz->catzs;
|
|
|
|
|
2023-02-21 21:14:44 +00:00
|
|
|
if (atomic_load(&catzs->shuttingdown)) {
|
2023-02-21 14:23:38 +00:00
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
|
|
goto exit;
|
2023-02-21 21:14:44 +00:00
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_name_format(&updb->origin, bname, DNS_NAME_FORMATSIZE);
|
2022-03-17 14:47:15 +00:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-06-22 10:49:25 +02:00
|
|
|
* Create a new catz in the same context as current catz.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_name_toregion(&updb->origin, &r);
|
2023-02-24 09:46:00 +00:00
|
|
|
LOCK(&catzs->lock);
|
2023-02-09 10:32:33 +00:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&oldcatz);
|
2023-03-02 13:32:21 +00:00
|
|
|
is_active = (result == ISC_R_SUCCESS && oldcatz->active);
|
2023-02-24 09:46:00 +00:00
|
|
|
UNLOCK(&catzs->lock);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-06-22 10:49:25 +02:00
|
|
|
/* This can happen if we remove the zone in the meantime. */
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: zone '%s' not in config", bname);
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-03-02 13:32:21 +00:00
|
|
|
if (!is_active) {
|
|
|
|
/* This can happen during a reconfiguration. */
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: zone '%s' is no longer active", bname);
|
|
|
|
result = ISC_R_CANCELED;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_db_getsoaserial(updb, oldcatz->updbversion, &vers);
|
2016-05-31 08:12:51 +10:00
|
|
|
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)", bname,
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_INFO,
|
2022-12-14 14:40:31 +00:00
|
|
|
"catz: updating catalog zone '%s' with serial %" PRIu32,
|
|
|
|
bname, vers);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_catz_new_zone(catzs, &newcatz, &updb->origin);
|
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 create new zone - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_db_createiterator(updb, DNS_DB_NONSEC3, &updbit);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&newcatz);
|
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 create DB iterator - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixname);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/*
|
2022-03-24 20:24:00 +00:00
|
|
|
* Take the version record to process first, because the other
|
|
|
|
* records might be processed differently depending on the version of
|
|
|
|
* the catalog zone's schema.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_name_fromstring2(name, "version", &updb->origin, 0, NULL);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_dbiterator_destroy(&updbit);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&newcatz);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
2022-03-24 20:24:00 +00:00
|
|
|
"catz: failed to create name from string - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2022-03-24 20:24:00 +00:00
|
|
|
}
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_dbiterator_seek(updbit, name);
|
2022-03-24 20:24:00 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_dbiterator_destroy(&updbit);
|
2022-03-24 20:24:00 +00:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: zone '%s' has no 'version' record (%s)",
|
|
|
|
bname, isc_result_totext(result));
|
2023-02-09 10:32:33 +00:00
|
|
|
newcatz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
goto final;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2022-03-24 20:24:00 +00:00
|
|
|
name = dns_fixedname_initname(&fixname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iterate over database to fill the new zone.
|
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
while (result == ISC_R_SUCCESS) {
|
2023-02-24 09:46:00 +00:00
|
|
|
if (atomic_load(&catzs->shuttingdown)) {
|
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_dbiterator_current(updbit, &node, name);
|
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 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;
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_dbiterator_pause(updbit);
|
2023-02-23 11:10:39 +01:00
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
2022-03-24 20:24:00 +00:00
|
|
|
if (!is_vers_processed) {
|
|
|
|
/* Keep the version node to skip it later in the loop */
|
|
|
|
vers_node = node;
|
|
|
|
} else if (node == vers_node) {
|
|
|
|
/* Skip the already processed version node */
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_detachnode(updb, &node);
|
|
|
|
result = dns_dbiterator_next(updbit);
|
2022-03-24 20:24:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_db_allrdatasets(updb, node, oldcatz->updbversion,
|
|
|
|
0, 0, &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));
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_detachnode(updb, &node);
|
2016-05-26 21:23:19 +02:00
|
|
|
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);
|
2022-06-01 08:51:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip processing DNSSEC-related and ZONEMD types,
|
|
|
|
* because we are not interested in them in the context
|
|
|
|
* of a catalog zone, and processing them will fail
|
|
|
|
* and produce an unnecessary warning message.
|
|
|
|
*/
|
|
|
|
if (!catz_rdatatype_is_processable(rdataset.type)) {
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
2023-03-01 14:41:59 +00:00
|
|
|
/*
|
|
|
|
* Although newcatz->coos is accessed in
|
|
|
|
* catz_process_coo() in the call-chain below, we don't
|
|
|
|
* need to hold the newcatz->lock, because the newcatz
|
|
|
|
* is still local to this thread and function and
|
|
|
|
* newcatz->coos can't be accessed from the outside
|
|
|
|
* until dns__catz_zones_merge() has been called.
|
|
|
|
*/
|
|
|
|
result = dns__catz_update_process(newcatz, name,
|
|
|
|
&rdataset);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2017-08-10 08:42:04 +10:00
|
|
|
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
|
|
|
char classbuf[DNS_RDATACLASS_FORMATSIZE];
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_name_format(name, cname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
2017-08-10 08:42:04 +10:00
|
|
|
dns_rdataclass_format(rdataset.rdclass,
|
|
|
|
classbuf,
|
|
|
|
sizeof(classbuf));
|
|
|
|
dns_rdatatype_format(rdataset.type, typebuf,
|
|
|
|
sizeof(typebuf));
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_WARNING,
|
2022-03-17 14:43:18 +00:00
|
|
|
"catz: invalid record in catalog "
|
|
|
|
"zone - %s %s %s (%s) - ignoring",
|
2017-08-10 08:42:04 +10:00
|
|
|
cname, classbuf, typebuf,
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2022-06-01 08:51:55 +00:00
|
|
|
next:
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdataset_disassociate(&rdataset);
|
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);
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_detachnode(updb, &node);
|
2022-03-24 20:24:00 +00:00
|
|
|
|
|
|
|
if (!is_vers_processed) {
|
|
|
|
is_vers_processed = true;
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_dbiterator_first(updbit);
|
2022-03-24 20:24:00 +00:00
|
|
|
} else {
|
2023-03-02 08:52:25 +00:00
|
|
|
result = dns_dbiterator_next(updbit);
|
2022-03-24 20:24:00 +00:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_dbiterator_destroy(&updbit);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3),
|
2023-02-24 09:46:00 +00:00
|
|
|
"catz: update_from_db: iteration finished: %s",
|
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-17 14:43:18 +00:00
|
|
|
/*
|
|
|
|
* Check catalog zone version compatibilites.
|
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
catz_vers = (newcatz->version == DNS_CATZ_VERSION_UNDEFINED)
|
|
|
|
? oldcatz->version
|
|
|
|
: newcatz->version;
|
2022-03-17 14:43:18 +00:00
|
|
|
if (catz_vers == DNS_CATZ_VERSION_UNDEFINED) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: zone '%s' version is not set", bname);
|
2023-02-09 10:32:33 +00:00
|
|
|
newcatz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
} else if (catz_vers != 1 && catz_vers != 2) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
|
|
|
"catz: zone '%s' unsupported version "
|
|
|
|
"'%" PRIu32 "'",
|
|
|
|
bname, catz_vers);
|
2023-02-09 10:32:33 +00:00
|
|
|
newcatz->broken = true;
|
2022-03-17 14:43:18 +00:00
|
|
|
} else {
|
2023-02-09 10:32:33 +00:00
|
|
|
oldcatz->version = catz_vers;
|
2022-03-17 14:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
final:
|
2023-02-09 10:32:33 +00:00
|
|
|
if (newcatz->broken) {
|
2022-03-17 14:43:18 +00:00
|
|
|
dns_name_format(name, cname, DNS_NAME_FORMATSIZE);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: new catalog zone '%s' is broken and "
|
|
|
|
"will not be processed",
|
|
|
|
bname);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&newcatz);
|
2023-02-21 14:23:38 +00:00
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
goto exit;
|
2022-03-17 14:43:18 +00:00
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2016-06-22 10:49:25 +02:00
|
|
|
* Finally merge new zone into old zone.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2023-03-01 14:41:59 +00:00
|
|
|
result = dns__catz_zones_merge(oldcatz, newcatz);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&newcatz);
|
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 merging zones: %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
goto exit;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3),
|
|
|
|
"catz: update_from_db: new zone merged");
|
2016-06-22 10:49:25 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When we're doing reconfig and setting a new catalog zone
|
|
|
|
* from an existing zone we won't have a chance to set up
|
|
|
|
* update callback in zone_startload or axfr_makedb, but we will
|
|
|
|
* call onupdate() artificially so we can register the callback here.
|
|
|
|
*/
|
2023-03-02 10:18:11 +00:00
|
|
|
LOCK(&catzs->lock);
|
2023-02-09 10:32:33 +00:00
|
|
|
if (!oldcatz->db_registered) {
|
2016-06-22 10:49:25 +02:00
|
|
|
result = dns_db_updatenotify_register(
|
2023-03-02 08:52:25 +00:00
|
|
|
updb, dns_catz_dbupdate_callback, oldcatz->catzs);
|
2016-06-22 10:49:25 +02:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2023-02-09 10:32:33 +00:00
|
|
|
oldcatz->db_registered = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2023-03-02 10:18:11 +00:00
|
|
|
UNLOCK(&catzs->lock);
|
2023-02-21 14:23:38 +00:00
|
|
|
|
|
|
|
exit:
|
|
|
|
catz->updateresult = result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dns__catz_done_cb(void *data) {
|
|
|
|
dns_catz_zone_t *catz = (dns_catz_zone_t *)data;
|
|
|
|
char dname[DNS_NAME_FORMATSIZE];
|
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
|
|
|
|
|
|
|
LOCK(&catz->catzs->lock);
|
|
|
|
catz->updaterunning = false;
|
|
|
|
|
|
|
|
dns_name_format(&catz->name, dname, DNS_NAME_FORMATSIZE);
|
|
|
|
|
2023-02-24 09:46:00 +00:00
|
|
|
if (catz->updatepending && !atomic_load(&catz->catzs->shuttingdown)) {
|
2023-02-21 14:23:38 +00:00
|
|
|
/* Restart the timer */
|
|
|
|
dns__catz_timer_start(catz);
|
|
|
|
}
|
|
|
|
|
2023-03-02 08:52:25 +00:00
|
|
|
dns_db_closeversion(catz->updb, &catz->updbversion, false);
|
|
|
|
dns_db_detach(&catz->updb);
|
|
|
|
|
2023-02-21 14:23:38 +00:00
|
|
|
UNLOCK(&catz->catzs->lock);
|
|
|
|
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_INFO, "catz: %s: reload done: %s", dname,
|
|
|
|
isc_result_totext(catz->updateresult));
|
|
|
|
|
2023-03-21 09:56:36 +00:00
|
|
|
dns_catz_unref_catz(catz);
|
2023-02-21 14:23:38 +00:00
|
|
|
dns_catz_unref_catzs(catz->catzs);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2023-03-02 13:19:09 +00:00
|
|
|
LOCK(&catzs->lock);
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(catzs->zones, &iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
|
|
|
result = isc_ht_iter_next(iter))
|
|
|
|
{
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t *catz = NULL;
|
|
|
|
isc_ht_iter_current(iter, (void **)&catz);
|
|
|
|
catz->active = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2023-03-02 13:19:09 +00:00
|
|
|
UNLOCK(&catzs->lock);
|
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;
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t *newcatz = NULL;
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2018-11-28 18:57:38 +11:00
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
LOCK(&catzs->lock);
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(catzs->zones, &iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;) {
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_catz_zone_t *catz = NULL;
|
2018-11-28 18:57:38 +11:00
|
|
|
|
2023-02-09 10:32:33 +00:00
|
|
|
isc_ht_iter_current(iter, (void **)&catz);
|
|
|
|
if (!catz->active) {
|
2016-05-31 23:01:53 +02:00
|
|
|
char cname[DNS_NAME_FORMATSIZE];
|
2023-02-09 10:32:33 +00:00
|
|
|
dns_name_format(&catz->name, cname,
|
2016-06-20 13:39:44 +02:00
|
|
|
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
|
2016-06-22 10:49:25 +02:00
|
|
|
* all members.
|
2016-05-31 23:01:53 +02:00
|
|
|
*/
|
2023-02-09 10:32:33 +00:00
|
|
|
result = dns_catz_new_zone(catzs, &newcatz,
|
|
|
|
&catz->name);
|
2016-05-31 23:01:53 +02:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2023-03-01 14:41:59 +00:00
|
|
|
dns__catz_zones_merge(catz, newcatz);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&newcatz);
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/* Make sure that we have an empty catalog zone. */
|
2023-02-09 10:32:33 +00:00
|
|
|
INSIST(isc_ht_count(catz->entries) == 0);
|
2016-06-22 10:49:25 +02:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter);
|
2023-02-21 14:11:04 +00:00
|
|
|
dns_catz_detach_catz(&catz);
|
2016-06-22 10:49:25 +02:00
|
|
|
} else {
|
|
|
|
result = isc_ht_iter_next(iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
}
|
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
UNLOCK(&catzs->lock);
|
2016-05-31 23:01:53 +02:00
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2022-03-08 11:30:37 +01:00
|
|
|
void
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(catz));
|
2022-03-08 11:22:55 +01:00
|
|
|
|
2022-03-08 11:30:37 +01:00
|
|
|
isc_ht_iter_create(catz->entries, itp);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|