2016-05-26 21:23:19 +02:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2016-05-26 21:23:19 +02:00
|
|
|
*
|
2021-06-03 08:37:05 +02:00
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
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>
|
2018-03-28 14:19:37 +02:00
|
|
|
|
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>
|
2017-07-26 01:24:25 -07:00
|
|
|
#include <isc/print.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
#include <isc/result.h>
|
|
|
|
#include <isc/task.h>
|
2017-10-19 12:26:32 +11:00
|
|
|
#include <isc/util.h>
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
#include <dns/catz.h>
|
|
|
|
#include <dns/dbiterator.h>
|
|
|
|
#include <dns/events.h>
|
|
|
|
#include <dns/rdatasetiter.h>
|
|
|
|
#include <dns/view.h>
|
|
|
|
#include <dns/zone.h>
|
2016-05-26 12:36:17 -07:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define DNS_CATZ_ZONE_MAGIC ISC_MAGIC('c', 'a', 't', 'z')
|
2018-11-28 18:57:38 +11:00
|
|
|
#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
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define DNS_CATZ_ZONE_VALID(catz) ISC_MAGIC_VALID(catz, DNS_CATZ_ZONE_MAGIC)
|
2018-11-28 18:57:38 +11:00
|
|
|
#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;
|
|
|
|
isc_refcount_t refs;
|
|
|
|
};
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/*%
|
|
|
|
* Single member zone in a catalog
|
|
|
|
*/
|
|
|
|
struct dns_catz_entry {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
dns_name_t name;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_catz_options_t opts;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_refcount_t refs;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Catalog zone
|
|
|
|
*/
|
|
|
|
struct dns_catz_zone {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
dns_name_t name;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_catz_zones_t *catzs;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_rdata_t soa;
|
2016-05-26 21:23:19 +02:00
|
|
|
/* key in entries is 'mhash', not domain name! */
|
2020-02-12 13:59:18 +01:00
|
|
|
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
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_catz_options_t defoptions;
|
|
|
|
dns_catz_options_t zoneoptions;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_time_t lastupdated;
|
|
|
|
bool updatepending;
|
|
|
|
uint32_t version;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_db_t *db;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_dbversion_t *dbversion;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_timer_t *updatetimer;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
bool active;
|
|
|
|
bool db_registered;
|
2022-03-17 14:43:18 +00:00
|
|
|
bool broken;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_refcount_t refs;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static isc_result_t
|
|
|
|
catz_process_zones_entry(dns_catz_zone_t *zone, dns_rdataset_t *value,
|
|
|
|
dns_label_t *mhash);
|
|
|
|
static isc_result_t
|
|
|
|
catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value,
|
|
|
|
dns_label_t *mhash, dns_name_t *name);
|
2021-09-24 17:42:12 +00:00
|
|
|
static void
|
|
|
|
catz_entry_add_or_mod(dns_catz_zone_t *target, isc_ht_t *ht, unsigned char *key,
|
|
|
|
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 {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic;
|
|
|
|
isc_ht_t *zones;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
isc_refcount_t refs;
|
|
|
|
isc_mutex_t lock;
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_catz_zonemodmethods_t *zmm;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_taskmgr_t *taskmgr;
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_loopmgr_t *loopmgr;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_view_t *view;
|
|
|
|
isc_task_t *updater;
|
2016-05-26 21:23:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
2020-02-13 14:44:37 -08:00
|
|
|
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);
|
|
|
|
|
2020-02-13 21:48:23 +01: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;
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (options->allow_query != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_free(&options->allow_query);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (options->allow_transfer != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
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,
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
2020-02-13 21:48:23 +01: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
|
|
|
}
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (src->zonedir != NULL) {
|
2016-05-31 10:36:27 -07:00
|
|
|
dst->zonedir = isc_mem_strdup(mctx, src->zonedir);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (src->allow_query != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
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
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (src->allow_transfer != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
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,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_options_t *opts) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(defaults != NULL);
|
|
|
|
REQUIRE(opts != NULL);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (opts->masters.count == 0 && defaults->masters.count != 0) {
|
2016-06-20 13:39:44 +02:00
|
|
|
dns_ipkeylist_copy(mctx, &defaults->masters, &opts->masters);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
|
2020-02-13 21:48:23 +01: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
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (opts->allow_query == NULL && defaults->allow_query != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_dup(mctx, &opts->allow_query, defaults->allow_query);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (opts->allow_transfer == NULL && defaults->allow_transfer != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
ncoo = isc_mem_get(mctx, sizeof(dns_catz_coo_t));
|
|
|
|
dns_name_init(&ncoo->name, NULL);
|
|
|
|
dns_name_dup(domain, mctx, &ncoo->name);
|
|
|
|
isc_refcount_init(&ncoo->refs, 1);
|
|
|
|
ncoo->magic = DNS_CATZ_COO_MAGIC;
|
|
|
|
*ncoop = ncoo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
catz_coo_detach(dns_catz_zone_t *zone, dns_catz_coo_t **coop) {
|
|
|
|
dns_catz_coo_t *coo;
|
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
|
|
|
REQUIRE(coop != NULL && DNS_CATZ_COO_VALID(*coop));
|
|
|
|
coo = *coop;
|
|
|
|
*coop = NULL;
|
|
|
|
|
|
|
|
if (isc_refcount_decrement(&coo->refs) == 1) {
|
|
|
|
isc_mem_t *mctx = zone->catzs->mctx;
|
|
|
|
coo->magic = 0;
|
|
|
|
isc_refcount_destroy(&coo->refs);
|
|
|
|
if (dns_name_dynamic(&coo->name)) {
|
|
|
|
dns_name_free(&coo->name, mctx);
|
|
|
|
}
|
|
|
|
isc_mem_put(mctx, coo, sizeof(dns_catz_coo_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_entry_t **nentryp) {
|
2016-05-26 21:23:19 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
nentry = isc_mem_get(mctx, sizeof(dns_catz_entry_t));
|
|
|
|
|
|
|
|
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);
|
|
|
|
isc_refcount_init(&nentry->refs, 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 *
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_copy(dns_catz_zone_t *zone, const dns_catz_entry_t *entry,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_entry_t **nentryp) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_t *nentry = NULL;
|
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
|
|
|
REQUIRE(DNS_CATZ_ENTRY_VALID(entry));
|
|
|
|
REQUIRE(nentryp != NULL && *nentryp == NULL);
|
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
dns_catz_entry_new(zone->catzs->mctx, &entry->name, &nentry);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2021-10-06 12:43:35 +02:00
|
|
|
dns_catz_options_copy(zone->catzs->mctx, &entry->opts, &nentry->opts);
|
2016-05-26 21:23:19 +02:00
|
|
|
*nentryp = nentry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&entry->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
*entryp = entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_entry_detach(dns_catz_zone_t *zone, dns_catz_entry_t **entryp) {
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry;
|
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
if (isc_refcount_decrement(&entry->refs) == 1) {
|
2018-08-28 10:18:59 +02:00
|
|
|
isc_mem_t *mctx = zone->catzs->mctx;
|
2018-11-28 18:57:38 +11:00
|
|
|
entry->magic = 0;
|
|
|
|
isc_refcount_destroy(&entry->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_free(&entry->opts, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (dns_name_dynamic(&entry->name)) {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_free(&entry->name, mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_mem_put(mctx, entry, sizeof(dns_catz_entry_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08: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
|
2020-02-13 14:44:37 -08: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));
|
|
|
|
|
2020-02-13 21:48:23 +01: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
|
|
|
|
2020-02-13 21:48:23 +01: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,
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
/* If one is NULL and the other isn't, the entries don't match */
|
2020-02-13 21:48:23 +01: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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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) !=
|
2020-02-13 21:48:23 +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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
/* xxxwpk TODO compare dscps/keys! */
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_getname(dns_catz_zone_t *zone) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return (&zone->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_options_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_getdefoptions(dns_catz_zone_t *zone) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return (&zone->defoptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_resetdefoptions(dns_catz_zone_t *zone) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
dns_catz_options_free(&zone->defoptions, zone->catzs->mctx);
|
|
|
|
dns_catz_options_init(&zone->defoptions);
|
|
|
|
}
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_ht_iter_t *iter1 = NULL, *iter2 = NULL;
|
|
|
|
isc_ht_iter_t *iteradd = NULL, *itermod = NULL;
|
|
|
|
isc_ht_t *toadd = NULL, *tomod = NULL;
|
|
|
|
bool delcur = false;
|
|
|
|
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
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(newzone));
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(target));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
/* TODO verify the new zone first! */
|
|
|
|
|
2016-05-31 23:01:53 +02:00
|
|
|
addzone = target->catzs->zmm->addzone;
|
|
|
|
modzone = target->catzs->zmm->modzone;
|
|
|
|
delzone = target->catzs->zmm->delzone;
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
/* Copy zoneoptions from newzone into target. */
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_options_free(&target->zoneoptions, target->catzs->mctx);
|
|
|
|
dns_catz_options_copy(target->catzs->mctx, &newzone->zoneoptions,
|
|
|
|
&target->zoneoptions);
|
|
|
|
dns_catz_options_setdefault(target->catzs->mctx, &target->defoptions,
|
|
|
|
&target->zoneoptions);
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_format(&target->name, czname, DNS_NAME_FORMATSIZE);
|
|
|
|
|
2022-03-16 21:58:55 +01:00
|
|
|
isc_ht_init(&toadd, target->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
|
2016-07-21 13:07:56 +02:00
|
|
|
|
2022-03-16 21:58:55 +01:00
|
|
|
isc_ht_init(&tomod, target->catzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
|
2016-07-21 13:07:56 +02:00
|
|
|
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(newzone->entries, &iter1);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(target->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);
|
2016-07-21 13:07:56 +02:00
|
|
|
|
2022-03-08 11:22:55 +01:00
|
|
|
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
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(iter1); result == ISC_R_SUCCESS;
|
|
|
|
result = delcur ? isc_ht_iter_delcurrent_next(iter1)
|
2020-02-13 14:44:37 -08:00
|
|
|
: 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;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned char *key = NULL;
|
|
|
|
size_t keysize;
|
2018-04-17 08:29:14 -07:00
|
|
|
delcur = false;
|
2016-05-31 23:01:53 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_ht_iter_current(iter1, (void **)&nentry);
|
2016-06-22 10:49:25 +02:00
|
|
|
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) {
|
|
|
|
dns_catz_entry_detach(newzone, &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);
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_options_setdefault(target->catzs->mctx,
|
|
|
|
&target->zoneoptions,
|
|
|
|
&nentry->opts);
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
/* Try to find the zone in the view */
|
|
|
|
zt_find_result = dns_zt_find(target->catzs->view->zonetable,
|
|
|
|
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];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change of ownership (coo) processing, if required
|
|
|
|
*/
|
|
|
|
parentcatz = dns_zone_get_parentcatz(zone);
|
|
|
|
if (parentcatz != NULL && parentcatz != target &&
|
|
|
|
isc_ht_find(parentcatz->coos, nentry->name.ndata,
|
|
|
|
nentry->name.length,
|
|
|
|
(void **)&coo) == ISC_R_SUCCESS &&
|
|
|
|
dns_name_equal(&coo->name, &target->name))
|
|
|
|
{
|
|
|
|
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->taskmgr,
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (zt_find_result == ISC_R_SUCCESS ||
|
|
|
|
zt_find_result == DNS_R_PARTIALMATCH) {
|
|
|
|
dns_zone_detach(&zone);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to find the zone in the old catalog zone */
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_ht_find(target->entries, key, (uint32_t)keysize,
|
|
|
|
(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 &&
|
|
|
|
parentcatz == target) {
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2021-09-24 17:42:12 +00:00
|
|
|
catz_entry_add_or_mod(target, toadd, key, keysize,
|
|
|
|
nentry, NULL, "adding", zname,
|
|
|
|
czname);
|
|
|
|
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);
|
|
|
|
catz_entry_add_or_mod(target, 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) {
|
2021-09-24 17:42:12 +00:00
|
|
|
catz_entry_add_or_mod(target, tomod, key, keysize,
|
|
|
|
nentry, oentry, "modifying",
|
|
|
|
zname, czname);
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
dns_catz_entry_detach(target, &oentry);
|
|
|
|
result = isc_ht_delete(target->entries, key, (uint32_t)keysize);
|
|
|
|
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
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(iter2); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter2))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2020-02-12 13:59:18 +01: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);
|
2016-05-31 23:01:53 +02:00
|
|
|
result = delzone(entry, target, target->catzs->view,
|
2020-02-12 13:59:18 +01:00
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->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));
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_entry_detach(target, &entry);
|
|
|
|
}
|
|
|
|
RUNTIME_CHECK(result == ISC_R_NOMORE);
|
2016-06-22 10:49:25 +02:00
|
|
|
isc_ht_iter_destroy(&iter2);
|
|
|
|
/* At this moment target->entries has to be be empty. */
|
2016-05-26 21:23:19 +02:00
|
|
|
INSIST(isc_ht_count(target->entries) == 0);
|
|
|
|
isc_ht_destroy(&target->entries);
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(iteradd); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_ht_iter_delcurrent_next(iteradd))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2020-02-12 13:59:18 +01: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);
|
2016-07-21 13:07:56 +02:00
|
|
|
result = addzone(entry, target, target->catzs->view,
|
2020-01-30 15:30:32 -08:00
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->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",
|
2020-02-12 13:59:18 +01:00
|
|
|
zname, czname, isc_result_totext(result));
|
2016-07-21 13:07:56 +02:00
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(itermod); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_ht_iter_delcurrent_next(itermod))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2020-02-12 13:59:18 +01: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);
|
2016-07-21 13:07:56 +02:00
|
|
|
result = modzone(entry, target, target->catzs->view,
|
|
|
|
target->catzs->taskmgr,
|
|
|
|
target->catzs->zmm->udata);
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: modifying zone '%s' from catalog "
|
|
|
|
"'%s' - %s",
|
2020-02-12 13:59:18 +01:00
|
|
|
zname, czname, isc_result_totext(result));
|
2016-07-21 13:07:56 +02:00
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
target->entries = newzone->entries;
|
|
|
|
newzone->entries = NULL;
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
if (target->coos != NULL && newzone->coos != NULL) {
|
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
|
|
|
|
isc_ht_iter_create(target->coos, &iter);
|
|
|
|
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);
|
|
|
|
catz_coo_detach(target, &coo);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
|
|
|
|
|
|
|
/* The hashtable has to be empty now. */
|
|
|
|
INSIST(isc_ht_count(target->coos) == 0);
|
|
|
|
isc_ht_destroy(&target->coos);
|
|
|
|
|
|
|
|
target->coos = newzone->coos;
|
|
|
|
newzone->coos = NULL;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2016-07-21 13:07:56 +02:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
|
|
|
|
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_loopmgr_t *loopmgr) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zones_t *new_zones;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
|
|
|
REQUIRE(zmm != NULL);
|
|
|
|
|
|
|
|
new_zones = isc_mem_get(mctx, sizeof(*new_zones));
|
|
|
|
memset(new_zones, 0, sizeof(*new_zones));
|
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&new_zones->lock);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2018-08-01 11:46:11 +02:00
|
|
|
isc_refcount_init(&new_zones->refs, 1);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-16 21:58:55 +01:00
|
|
|
isc_ht_init(&new_zones->zones, mctx, 4, ISC_HT_CASE_SENSITIVE);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_mem_attach(mctx, &new_zones->mctx);
|
|
|
|
new_zones->zmm = zmm;
|
2022-07-26 13:03:40 +02:00
|
|
|
new_zones->loopmgr = loopmgr;
|
2016-05-31 08:12:51 +10:00
|
|
|
new_zones->taskmgr = taskmgr;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-07-26 13:03:45 +02:00
|
|
|
result = isc_task_create(taskmgr, &new_zones->updater, 0);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-31 08:12:51 +10:00
|
|
|
goto cleanup_ht;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2018-11-28 18:57:38 +11:00
|
|
|
new_zones->magic = DNS_CATZ_ZONES_MAGIC;
|
2016-05-31 08:12:51 +10:00
|
|
|
|
|
|
|
*catzsp = new_zones;
|
2016-05-26 21:23:19 +02:00
|
|
|
return (ISC_R_SUCCESS);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_ht:
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_ht_destroy(&new_zones->zones);
|
|
|
|
isc_refcount_destroy(&new_zones->refs);
|
|
|
|
isc_mutex_destroy(&new_zones->lock);
|
|
|
|
isc_mem_put(mctx, new_zones, sizeof(*new_zones));
|
|
|
|
|
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
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));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(view != NULL);
|
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
|
|
|
|
dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
|
2020-02-13 14:44:37 -08:00
|
|
|
const dns_name_t *name) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_t *new_zone;
|
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(zonep != NULL && *zonep == 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
|
|
|
|
|
|
|
new_zone = isc_mem_get(catzs->mctx, sizeof(*new_zone));
|
|
|
|
|
|
|
|
memset(new_zone, 0, sizeof(*new_zone));
|
|
|
|
|
|
|
|
dns_name_init(&new_zone->name, NULL);
|
2019-11-01 08:31:13 -05:00
|
|
|
dns_name_dup(name, catzs->mctx, &new_zone->name);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-16 21:58:55 +01:00
|
|
|
isc_ht_init(&new_zone->entries, catzs->mctx, 4, ISC_HT_CASE_SENSITIVE);
|
2022-03-17 13:09:11 +00:00
|
|
|
isc_ht_init(&new_zone->coos, catzs->mctx, 4, ISC_HT_CASE_INSENSITIVE);
|
2016-05-31 08:12:51 +10:00
|
|
|
|
|
|
|
new_zone->updatetimer = NULL;
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_timer_create(isc_loop_main(catzs->loopmgr),
|
2022-03-11 12:09:35 +01:00
|
|
|
dns_catz_update_taskaction, new_zone,
|
|
|
|
&new_zone->updatetimer);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_time_settoepoch(&new_zone->lastupdated);
|
2018-04-17 08:29:14 -07:00
|
|
|
new_zone->updatepending = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
new_zone->db = NULL;
|
|
|
|
new_zone->dbversion = NULL;
|
|
|
|
new_zone->catzs = catzs;
|
|
|
|
dns_catz_options_init(&new_zone->defoptions);
|
|
|
|
dns_catz_options_init(&new_zone->zoneoptions);
|
2018-04-17 08:29:14 -07:00
|
|
|
new_zone->active = true;
|
|
|
|
new_zone->db_registered = false;
|
2022-03-16 20:11:17 +00:00
|
|
|
new_zone->version = DNS_CATZ_VERSION_UNDEFINED;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_refcount_init(&new_zone->refs, 1);
|
2018-11-28 18:57:38 +11:00
|
|
|
new_zone->magic = DNS_CATZ_ZONE_MAGIC;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
*zonep = new_zone;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_t **zonep) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_t *new_zone = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result, tresult;
|
|
|
|
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));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(zonep != NULL && *zonep == 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);
|
2020-02-12 13:59:18 +01:00
|
|
|
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);
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_new_zone(catzs, &new_zone, name);
|
2020-02-13 21:48:23 +01: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
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_add(catzs->zones, new_zone->name.ndata,
|
|
|
|
new_zone->name.length, new_zone);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_detach(&new_zone);
|
2020-02-13 21:48:23 +01: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) {
|
2020-02-12 13:59:18 +01:00
|
|
|
tresult = isc_ht_find(catzs->zones, name->ndata, name->length,
|
|
|
|
(void **)&new_zone);
|
2017-07-10 09:06:13 +10:00
|
|
|
INSIST(tresult == ISC_R_SUCCESS && !new_zone->active);
|
2018-04-17 08:29:14 -07:00
|
|
|
new_zone->active = true;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*zonep = new_zone;
|
|
|
|
|
2020-02-12 13:59:18 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
dns_catz_zone_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
|
|
|
result = isc_ht_find(catzs->zones, name->ndata, name->length,
|
2020-02-12 13:59:18 +01:00
|
|
|
(void **)&found);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return (found);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_catzs_attach(dns_catz_zones_t *catzs, dns_catz_zones_t **catzsp) {
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(catzsp != NULL && *catzsp == NULL);
|
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&catzs->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
*catzsp = catzs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_attach(dns_catz_zone_t *zone, dns_catz_zone_t **zonep) {
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(zonep != NULL && *zonep == NULL);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&zone->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
*zonep = zone;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_detach(dns_catz_zone_t **zonep) {
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(zonep != NULL && *zonep != NULL);
|
2018-08-28 10:18:59 +02:00
|
|
|
dns_catz_zone_t *zone = *zonep;
|
|
|
|
*zonep = NULL;
|
2018-08-17 15:16:59 +02:00
|
|
|
|
|
|
|
if (isc_refcount_decrement(&zone->refs) == 1) {
|
2018-11-28 18:57:38 +11:00
|
|
|
isc_mem_t *mctx = zone->catzs->mctx;
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_destroy(&zone->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
if (zone->entries != NULL) {
|
2018-08-28 10:18:59 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(zone->entries, &iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
for (result = isc_ht_iter_first(iter);
|
|
|
|
result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_ht_iter_current(iter, (void **)&entry);
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_entry_detach(zone, &entry);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/* The hashtable has to be empty now. */
|
2016-05-26 21:23:19 +02:00
|
|
|
INSIST(isc_ht_count(zone->entries) == 0);
|
|
|
|
isc_ht_destroy(&zone->entries);
|
|
|
|
}
|
2022-03-17 13:09:11 +00:00
|
|
|
if (zone->coos != NULL) {
|
|
|
|
isc_ht_iter_t *iter = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_ht_iter_create(zone->coos, &iter);
|
|
|
|
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);
|
|
|
|
catz_coo_detach(zone, &coo);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
|
|
|
|
|
|
|
/* The hashtable has to be empty now. */
|
|
|
|
INSIST(isc_ht_count(zone->coos) == 0);
|
|
|
|
isc_ht_destroy(&zone->coos);
|
|
|
|
}
|
2018-11-28 18:57:38 +11:00
|
|
|
zone->magic = 0;
|
2022-04-02 00:42:20 +02:00
|
|
|
isc_timer_destroy(&zone->updatetimer);
|
2020-03-30 13:47:58 -07:00
|
|
|
if (zone->db_registered) {
|
2018-08-28 10:18:59 +02:00
|
|
|
INSIST(dns_db_updatenotify_unregister(
|
2020-02-12 13:59:18 +01:00
|
|
|
zone->db, dns_catz_dbupdate_callback,
|
|
|
|
zone->catzs) == ISC_R_SUCCESS);
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (zone->dbversion) {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_db_closeversion(zone->db, &zone->dbversion, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (zone->db != NULL) {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_db_detach(&zone->db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_name_free(&zone->name, mctx);
|
|
|
|
dns_catz_options_free(&zone->defoptions, mctx);
|
|
|
|
dns_catz_options_free(&zone->zoneoptions, mctx);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
zone->catzs = NULL;
|
|
|
|
isc_mem_put(mctx, zone, sizeof(dns_catz_zone_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_catzs_detach(dns_catz_zones_t **catzsp) {
|
2019-02-13 16:13:16 +11:00
|
|
|
dns_catz_zones_t *catzs;
|
|
|
|
|
2018-08-28 10:18:59 +02:00
|
|
|
REQUIRE(catzsp != NULL && *catzsp != NULL);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
catzs = *catzsp;
|
|
|
|
*catzsp = NULL;
|
2018-08-28 10:18:59 +02:00
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
if (isc_refcount_decrement(&catzs->refs) == 1) {
|
2018-11-28 18:57:38 +11:00
|
|
|
catzs->magic = 0;
|
2022-05-09 12:58:34 +02:00
|
|
|
isc_task_detach(&catzs->updater);
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&catzs->lock);
|
2016-05-26 21:23:19 +02:00
|
|
|
if (catzs->zones != NULL) {
|
2018-08-28 10:18:59 +02:00
|
|
|
isc_ht_iter_t *iter = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
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);
|
2020-02-12 13:59:18 +01:00
|
|
|
result == ISC_R_SUCCESS;) {
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_zone_t *zone = NULL;
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_ht_iter_current(iter, (void **)&zone);
|
2016-06-22 10:49:25 +02:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zone_detach(&zone);
|
|
|
|
}
|
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
INSIST(isc_ht_count(catzs->zones) == 0);
|
|
|
|
isc_ht_destroy(&catzs->zones);
|
|
|
|
}
|
2018-10-30 13:41:07 +01:00
|
|
|
isc_refcount_destroy(&catzs->refs);
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_mem_putanddetach(&catzs->mctx, catzs, sizeof(*catzs));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2020-02-13 14:44:37 -08: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 &&
|
|
|
|
memcmp(opt, option->base + 1, len) == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2020-02-13 21:48:23 +01: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
|
2020-02-13 14:44:37 -08:00
|
|
|
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") ||
|
|
|
|
catz_opt_cmp(option, "primaries")) {
|
2022-03-25 11:28:07 +00:00
|
|
|
return (CATZ_OPT_PRIMARIES);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (catz_opt_cmp(option, "allow-query")) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (CATZ_OPT_ALLOW_QUERY);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (catz_opt_cmp(option, "allow-transfer")) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (CATZ_OPT_ALLOW_TRANSFER);
|
2022-03-17 13:09:11 +00:00
|
|
|
} else if (catz_opt_cmp(option, "coo")) {
|
|
|
|
return (CATZ_OPT_COO);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (catz_opt_cmp(option, "version")) {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (CATZ_OPT_VERSION);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2016-05-26 21:23:19 +02:00
|
|
|
return (CATZ_OPT_NONE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2016-06-22 10:49:25 +02:00
|
|
|
catz_process_zones(dns_catz_zone_t *zone, dns_rdataset_t *value,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *name) {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t mhash;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t opt;
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->labels == 0) {
|
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
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_name_getlabel(name, name->labels - 1, &mhash);
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (name->labels == 1) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (catz_process_zones_entry(zone, value, &mhash));
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_name_init(&opt, NULL);
|
|
|
|
dns_name_split(name, 1, &opt, NULL);
|
2020-02-12 13:59:18 +01:00
|
|
|
return (catz_process_zones_suboption(zone, value, &mhash,
|
|
|
|
&opt));
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 13:09:11 +00:00
|
|
|
static isc_result_t
|
|
|
|
catz_process_coo(dns_catz_zone_t *zone, dns_label_t *mhash,
|
|
|
|
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;
|
|
|
|
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
|
|
|
REQUIRE(mhash != NULL);
|
|
|
|
REQUIRE(DNS_RDATASET_VALID(value));
|
|
|
|
|
|
|
|
/* Change of Ownership was introduced in version "2" of the schema. */
|
|
|
|
if (zone->version < 2) {
|
|
|
|
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");
|
|
|
|
zone->broken = true;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = isc_ht_find(zone->entries, mhash->base, mhash->length,
|
|
|
|
(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = isc_ht_find(zone->coos, entry->name.ndata, entry->name.length,
|
|
|
|
(void **)&ocoo);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
/* The change of ownership permission was already registered. */
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
catz_coo_new(zone->catzs->mctx, &ptr.ptr, &ncoo);
|
|
|
|
result = isc_ht_add(zone->coos, entry->name.ndata, entry->name.length,
|
|
|
|
ncoo);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
catz_coo_detach(zone, &ncoo);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
static isc_result_t
|
|
|
|
catz_process_zones_entry(dns_catz_zone_t *zone, dns_rdataset_t *value,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_label_t *mhash) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_ptr_t ptr;
|
2016-05-26 21:23:19 +02:00
|
|
|
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");
|
|
|
|
zone->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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_ht_find(zone->entries, mhash->base, mhash->length,
|
|
|
|
(void **)&entry);
|
2016-06-22 10:49:25 +02:00
|
|
|
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 {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_name_dup(&ptr.ptr, zone->catzs->mctx, &entry->name);
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
|
|
|
} else {
|
2021-10-06 12:43:35 +02:00
|
|
|
dns_catz_entry_new(zone->catzs->mctx, &ptr.ptr, &entry);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_ht_add(zone->entries, mhash->base, mhash->length,
|
|
|
|
entry);
|
2016-06-22 10:49:25 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_rdata_freestruct(&ptr);
|
|
|
|
dns_catz_entry_detach(zone, &entry);
|
|
|
|
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
|
2020-02-13 14:44:37 -08:00
|
|
|
catz_process_version(dns_catz_zone_t *zone, dns_rdataset_t *value) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_txt_t rdatatxt;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_txt_string_t rdatastr;
|
2020-02-13 14:44:37 -08:00
|
|
|
uint32_t tversion;
|
|
|
|
char t[16];
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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");
|
|
|
|
zone->broken = true;
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(value);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-31 08:12:51 +10:00
|
|
|
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);
|
2020-02-13 21:48:23 +01: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
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdata_txt_current(&rdatatxt, &rdatastr);
|
2020-02-13 21:48:23 +01: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-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;
|
|
|
|
}
|
|
|
|
zone->version = tversion;
|
2016-05-31 08:12:51 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rdata_freestruct(&rdatatxt);
|
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");
|
|
|
|
zone->broken = true;
|
|
|
|
}
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2021-10-05 11:28:24 +02:00
|
|
|
catz_process_primaries(dns_catz_zone_t *zone, dns_ipkeylist_t *ipkl,
|
|
|
|
dns_rdataset_t *value, dns_name_t *name) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_in_a_t rdata_a;
|
|
|
|
dns_rdata_in_aaaa_t rdata_aaaa;
|
|
|
|
dns_rdata_txt_t rdata_txt;
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_rdata_txt_string_t rdatastr;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t *keyname = NULL;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
char keycbuf[DNS_NAME_FORMATSIZE];
|
|
|
|
isc_buffer_t keybuf;
|
|
|
|
unsigned int rcount;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
mctx = zone->catzs->mctx;
|
|
|
|
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);
|
2020-02-12 13:59:18 +01:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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);
|
2020-02-13 21:48:23 +01:00
|
|
|
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 */
|
|
|
|
keyname = isc_mem_get(mctx, sizeof(dns_name_t));
|
|
|
|
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);
|
|
|
|
isc_mem_put(mctx, keyname, sizeof(dns_name_t));
|
|
|
|
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 &&
|
2020-02-13 21:48:23 +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 */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (value->type == dns_rdatatype_txt) {
|
2016-06-22 10:49:25 +02:00
|
|
|
ipkl->keys[i] = keyname;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else { /* A/AAAA */
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(&ipkl->addrs[i], &sockaddr,
|
|
|
|
sizeof(isc_sockaddr_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
} else {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_ipkeylist_resize(mctx, ipkl, i + 1);
|
2016-06-22 10:49:25 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
ipkl->labels[i] = isc_mem_get(mctx, sizeof(dns_name_t));
|
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
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (value->type == dns_rdatatype_txt) {
|
2016-06-22 10:49:25 +02:00
|
|
|
ipkl->keys[i] = keyname;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else { /* A/AAAA */
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(&ipkl->addrs[i], &sockaddr,
|
|
|
|
sizeof(isc_sockaddr_t));
|
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 */
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
if (value->type != dns_rdatatype_a && value->type != dns_rdatatype_aaaa)
|
|
|
|
{
|
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
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = dns_rdataset_first(value); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
catz_process_apl(dns_catz_zone_t *zone, isc_buffer_t **aclbp,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_rdataset_t *value) {
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
dns_rdata_in_apl_t rdata_apl;
|
2016-06-20 13:39:44 +02:00
|
|
|
dns_rdata_apl_ent_t apl_ent;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_netaddr_t addr;
|
|
|
|
isc_buffer_t *aclb = NULL;
|
|
|
|
unsigned char buf[256]; /* larger than INET6_ADDRSTRLEN */
|
2016-06-20 13:39:44 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &rdata_apl, zone->catzs->mctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-06-20 13:39:44 +02:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(zone->catzs->mctx, &aclb, 16);
|
2018-04-17 08:29:14 -07:00
|
|
|
isc_buffer_setautorealloc(aclb, true);
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = dns_rdata_apl_first(&rdata_apl); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = dns_rdata_apl_next(&rdata_apl))
|
|
|
|
{
|
2016-06-20 13:39:44 +02:00
|
|
|
result = dns_rdata_apl_current(&rdata_apl, &apl_ent);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
memset(buf, 0, sizeof(buf));
|
2020-02-13 21:48:23 +01:00
|
|
|
if (apl_ent.data != NULL && apl_ent.length > 0) {
|
2018-01-22 09:36:12 +11:00
|
|
|
memmove(buf, apl_ent.data, apl_ent.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (apl_ent.family == 1) {
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_netaddr_fromin(&addr, (struct in_addr *)buf);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (apl_ent.family == 2) {
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_netaddr_fromin6(&addr, (struct in6_addr *)buf);
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2016-06-20 13:39:44 +02:00
|
|
|
continue; /* xxxwpk log it or simply ignore? */
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (apl_ent.negative) {
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_putuint8(aclb, '!');
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_reserve(&aclb, INET6_ADDRSTRLEN);
|
|
|
|
result = isc_netaddr_totext(&addr, aclb);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
if ((apl_ent.family == 1 && apl_ent.prefix < 32) ||
|
2020-02-13 14:44:37 -08:00
|
|
|
(apl_ent.family == 2 && apl_ent.prefix < 128))
|
|
|
|
{
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_buffer_putuint8(aclb, '/');
|
|
|
|
isc_buffer_putdecint(aclb, apl_ent.prefix);
|
|
|
|
}
|
|
|
|
isc_buffer_putstr(aclb, "; ");
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_NOMORE) {
|
2016-06-20 13:39:44 +02:00
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2016-06-20 13:39:44 +02:00
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
*aclbp = aclb;
|
|
|
|
aclb = NULL;
|
|
|
|
cleanup:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (aclb != NULL) {
|
2016-06-20 13:39:44 +02:00
|
|
|
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
|
2016-06-22 10:49:25 +02:00
|
|
|
catz_process_zones_suboption(dns_catz_zone_t *zone, dns_rdataset_t *value,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_label_t *mhash, dns_name_t *name) {
|
|
|
|
isc_result_t result;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_t *entry = NULL;
|
2020-02-13 14:44:37 -08: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
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
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.
|
|
|
|
*/
|
|
|
|
if (zone->version >= 2 && opt >= CATZ_OPT_CUSTOM_START) {
|
|
|
|
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
|
|
|
*/
|
2016-06-22 10:49:25 +02:00
|
|
|
result = isc_ht_find(zone->entries, mhash->base, mhash->length,
|
2020-02-12 13:59:18 +01:00
|
|
|
(void **)&entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2021-10-06 12:43:35 +02:00
|
|
|
dns_catz_entry_new(zone->catzs->mctx, NULL, &entry);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_add(zone->entries, mhash->base, mhash->length,
|
|
|
|
entry);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_entry_detach(zone, &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:
|
|
|
|
return (catz_process_coo(zone, mhash, value));
|
2022-03-25 11:28:07 +00:00
|
|
|
case CATZ_OPT_PRIMARIES:
|
2021-10-05 11:28:24 +02:00
|
|
|
return (catz_process_primaries(zone, &entry->opts.masters,
|
|
|
|
value, &prefix));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix.labels != 0) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &entry->opts.allow_query,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_TRANSFER:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix.labels != 0) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &entry->opts.allow_transfer,
|
|
|
|
value));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2021-09-24 17:42:12 +00:00
|
|
|
catz_entry_add_or_mod(dns_catz_zone_t *target, isc_ht_t *ht, unsigned char *key,
|
|
|
|
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) {
|
|
|
|
dns_catz_entry_detach(target, &oentry);
|
|
|
|
result = isc_ht_delete(target->entries, key, (uint32_t)keysize);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
static isc_result_t
|
2016-06-22 10:49:25 +02:00
|
|
|
catz_process_value(dns_catz_zone_t *zone, dns_name_t *name,
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_rdataset_t *rdataset) {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_label_t option;
|
2020-02-13 14:44:37 -08:00
|
|
|
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
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
if (zone->version >= 2 && opt >= CATZ_OPT_CUSTOM_START) {
|
|
|
|
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:
|
|
|
|
return (catz_process_zones(zone, rdataset, &prefix));
|
2022-03-25 11:28:07 +00:00
|
|
|
case CATZ_OPT_PRIMARIES:
|
2021-10-05 11:28:24 +02:00
|
|
|
return (catz_process_primaries(zone, &zone->zoneoptions.masters,
|
|
|
|
rdataset, &prefix));
|
2016-05-26 21:23:19 +02:00
|
|
|
case CATZ_OPT_ALLOW_QUERY:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix.labels != 0) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
return (catz_process_apl(zone, &zone->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:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix.labels != 0) {
|
2016-06-22 10:49:25 +02:00
|
|
|
return (ISC_R_FAILURE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
return (catz_process_apl(
|
|
|
|
zone, &zone->zoneoptions.allow_transfer, rdataset));
|
2016-06-22 10:49:25 +02:00
|
|
|
case CATZ_OPT_VERSION:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (prefix.labels != 0) {
|
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
|
|
|
return (catz_process_version(zone, rdataset));
|
2016-05-26 21:23:19 +02:00
|
|
|
default:
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_catz_update_process(dns_catz_zones_t *catzs, dns_catz_zone_t *zone,
|
2020-02-13 14:44:37 -08:00
|
|
|
const dns_name_t *src_name, dns_rdataset_t *rdataset) {
|
|
|
|
isc_result_t result;
|
|
|
|
int order;
|
|
|
|
unsigned int nlabels;
|
|
|
|
dns_namereln_t nrres;
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdata_soa_t soa;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_name_t prefix;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
|
|
|
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");
|
|
|
|
zone->broken = true;
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
nrres = dns_name_fullcompare(src_name, &zone->name, &order, &nlabels);
|
|
|
|
if (nrres == dns_namereln_equal) {
|
|
|
|
if (rdataset->type == dns_rdatatype_soa) {
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdataset_first(rdataset);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-31 08:12:51 +10:00
|
|
|
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);
|
|
|
|
dns_name_split(src_name, zone->name.labels, &prefix, NULL);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = catz_process_value(zone, &prefix, rdataset);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
return (result);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
2018-06-01 09:31:59 +02:00
|
|
|
static isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
digest2hex(unsigned char *digest, unsigned int digestlen, char *hash,
|
2020-02-13 14:44:37 -08:00
|
|
|
size_t hashlen) {
|
2018-06-01 09:31:59 +02:00
|
|
|
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
|
|
|
|
dns_catz_generate_masterfilename(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t **buffer) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_t *tbuf = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result;
|
|
|
|
size_t rlen;
|
|
|
|
bool special = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(entry != NULL);
|
|
|
|
REQUIRE(buffer != NULL && *buffer != NULL);
|
|
|
|
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(zone->catzs->mctx, &tbuf,
|
2020-02-12 13:59:18 +01:00
|
|
|
strlen(zone->catzs->view->name) +
|
|
|
|
2 * DNS_NAME_FORMATSIZE + 2);
|
2016-05-31 10:36:27 -07:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_putstr(tbuf, zone->catzs->view->name);
|
|
|
|
isc_buffer_putstr(tbuf, "_");
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_name_totext(&zone->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
|
|
|
|
2016-08-16 12:29:09 +10: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];
|
2020-02-13 14:44:37 -08:00
|
|
|
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 */
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_md(ISC_MD_SHA256, r.base, r.length, digest,
|
|
|
|
&digestlen);
|
2018-06-01 09:31:59 +02:00
|
|
|
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;
|
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_buffer_putstr(*buffer, (char *)r.base);
|
2016-05-26 21:23:19 +02:00
|
|
|
} 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;
|
|
|
|
* primaries [ dscp X ] { ip1 port port1; ip2 port port2; };
|
|
|
|
* }
|
|
|
|
*/
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_result_t
|
|
|
|
dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry,
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_buffer_t **buf) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_buffer_t *buffer = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_region_t region;
|
|
|
|
isc_result_t result;
|
|
|
|
uint32_t i;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_netaddr_t netaddr;
|
2017-07-12 09:38:24 +02:00
|
|
|
char pbuf[sizeof("65535")]; /* used both for port number and DSCP */
|
2018-01-15 20:49:05 +01: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_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
REQUIRE(entry != NULL);
|
|
|
|
REQUIRE(buf != NULL && *buf == NULL);
|
|
|
|
|
|
|
|
/*
|
2016-05-31 08:12:51 +10:00
|
|
|
* The buffer will be reallocated if something won't fit,
|
2017-07-12 09:38:24 +02:00
|
|
|
* ISC_BUFFER_INCR seems like a good start.
|
2016-05-26 21:23:19 +02:00
|
|
|
*/
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(zone->catzs->mctx, &buffer, ISC_BUFFER_INCR);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
isc_buffer_setautorealloc(buffer, true);
|
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
|
|
|
|
|
|
|
/*
|
2021-10-05 11:07:44 +02:00
|
|
|
* DSCP value has no default, but when it is specified, it is
|
|
|
|
* identical for all primaries and cannot be overridden for a
|
|
|
|
* specific primary IP, so use the DSCP value set for the first
|
|
|
|
* primary.
|
2017-07-12 09:38:24 +02:00
|
|
|
*/
|
2020-02-13 14:44:37 -08:00
|
|
|
if (entry->opts.masters.count > 0 && entry->opts.masters.dscps[0] >= 0)
|
|
|
|
{
|
2017-07-12 09:38:24 +02:00
|
|
|
isc_buffer_putstr(buffer, " dscp ");
|
2018-02-24 17:55:24 -08:00
|
|
|
snprintf(pbuf, sizeof(pbuf), "%hd",
|
2017-07-12 09:38:24 +02:00
|
|
|
entry->opts.masters.dscps[0]);
|
|
|
|
isc_buffer_putstr(buffer, pbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
|
|
|
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
|
|
|
}
|
|
|
|
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 \"");
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_generate_masterfilename(zone, 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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-07-26 13:03:40 +02:00
|
|
|
dns_catz_update_taskaction(void *arg) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2022-07-26 13:03:40 +02:00
|
|
|
dns_catz_zone_t *zone = arg;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
LOCK(&zone->catzs->lock);
|
2018-04-17 08:29:14 -07:00
|
|
|
zone->updatepending = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_update_from_db(zone->db, zone->catzs);
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_timer_stop(zone->updatetimer);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_time_now(&zone->lastupdated);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2016-05-26 21:23:19 +02:00
|
|
|
UNLOCK(&zone->catzs->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zones_t *catzs;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_zone_t *zone = NULL;
|
|
|
|
isc_time_t now;
|
|
|
|
uint64_t tdiff;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_region_t r;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(DNS_DB_VALID(db));
|
|
|
|
REQUIRE(fn_arg != NULL);
|
2020-02-12 13:59:18 +01: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);
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&zone);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-31 08:12:51 +10:00
|
|
|
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 */
|
|
|
|
if (zone->db != NULL && zone->db != db) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (zone->dbversion != NULL) {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_db_closeversion(zone->db, &zone->dbversion, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_db_detach(&zone->db);
|
|
|
|
/*
|
|
|
|
* We're not registering db update callback, it will be
|
|
|
|
* registered at the end of update_from_db
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
zone->db_registered = false;
|
2016-06-22 10:49:25 +02:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (zone->db == NULL) {
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_db_attach(db, &zone->db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-06-22 10:49:25 +02:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!zone->updatepending) {
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_interval_t interval;
|
2018-04-17 08:29:14 -07:00
|
|
|
zone->updatepending = true;
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_time_now(&now);
|
2020-02-12 13:59:18 +01:00
|
|
|
tdiff = isc_time_microdiff(&now, &zone->lastupdated) / 1000000;
|
2016-05-26 21:23:19 +02:00
|
|
|
if (tdiff < zone->defoptions.min_update_interval) {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
|
|
|
|
"catz: new zone version came too soon, "
|
|
|
|
"deferring update");
|
2016-05-30 17:10:08 +02:00
|
|
|
isc_interval_set(&interval,
|
2016-06-22 10:49:25 +02:00
|
|
|
zone->defoptions.min_update_interval -
|
2020-02-12 13:59:18 +01:00
|
|
|
(unsigned int)tdiff,
|
|
|
|
0);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
2022-07-26 13:03:40 +02:00
|
|
|
isc_interval_set(&interval, 0, 0);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2022-07-26 13:03:40 +02:00
|
|
|
dns_db_currentversion(db, &zone->dbversion);
|
|
|
|
isc_timer_start(zone->updatetimer, isc_timertype_once,
|
|
|
|
&interval);
|
2016-05-26 21:23:19 +02:00
|
|
|
} else {
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
|
|
|
|
"catz: update already queued");
|
2020-02-13 21:48:23 +01:00
|
|
|
if (zone->dbversion != NULL) {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_db_closeversion(zone->db, &zone->dbversion, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_currentversion(zone->db, &zone->dbversion);
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01: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);
|
|
|
|
}
|
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) {
|
|
|
|
dns_catz_zone_t *oldzone = NULL, *newzone = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_region_t r;
|
|
|
|
dns_dbnode_t *node = NULL;
|
2022-03-24 20:24:00 +00:00
|
|
|
const dns_dbnode_t *vers_node = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_dbiterator_t *it = NULL;
|
|
|
|
dns_fixedname_t fixname;
|
|
|
|
dns_name_t *name;
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
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;
|
2020-02-13 14:44:37 -08:00
|
|
|
uint32_t vers;
|
2022-03-17 14:43:18 +00:00
|
|
|
uint32_t catz_vers;
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
REQUIRE(DNS_DB_VALID(db));
|
2018-11-28 18:57:38 +11:00
|
|
|
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2022-03-17 14:47:15 +00:00
|
|
|
dns_name_format(&db->origin, bname, DNS_NAME_FORMATSIZE);
|
|
|
|
|
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
|
|
|
*/
|
|
|
|
dns_name_toregion(&db->origin, &r);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&oldzone);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-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,
|
2020-02-12 13:59:18 +01:00
|
|
|
"catz: zone '%s' not in config", bname);
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_getsoaserial(db, oldzone->dbversion, &vers);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
/* A zone without SOA record?!? */
|
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
2020-02-12 13:59:18 +01:00
|
|
|
"catz: zone '%s' has no SOA record (%s)", bname,
|
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_INFO,
|
|
|
|
"catz: updating catalog zone '%s' with serial %d", bname,
|
|
|
|
vers);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_new_zone(catzs, &newzone, &db->origin);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, false);
|
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));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_createiterator(db, DNS_DB_NONSEC3, &it);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_catz_zone_detach(&newzone);
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, false);
|
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));
|
2016-05-26 21:23:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
*/
|
2022-03-24 20:24:00 +00:00
|
|
|
result = dns_name_fromstring2(name, "version", &db->origin, 0, NULL);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2022-03-24 20:24:00 +00:00
|
|
|
dns_dbiterator_destroy(&it);
|
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, false);
|
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));
|
2022-03-24 20:24:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
result = dns_dbiterator_seek(it, name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
dns_dbiterator_destroy(&it);
|
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, false);
|
|
|
|
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));
|
2022-03-17 14:43:18 +00:00
|
|
|
newzone->broken = true;
|
|
|
|
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) {
|
|
|
|
result = dns_dbiterator_current(it, &node, name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to get db iterator - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
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 */
|
|
|
|
dns_db_detachnode(db, &node);
|
|
|
|
result = dns_dbiterator_next(it);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_db_allrdatasets(db, node, oldzone->dbversion, 0,
|
2020-02-12 13:59:18 +01:00
|
|
|
&rdsiter);
|
2016-05-31 08:12:51 +10:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
|
|
|
"catz: failed to fetch rrdatasets - %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_db_detachnode(db, &node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_rdataset_init(&rdataset);
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_rdatasetiter_first(rdsiter);
|
|
|
|
while (result == ISC_R_SUCCESS) {
|
2016-05-26 21:23:19 +02:00
|
|
|
dns_rdatasetiter_current(rdsiter, &rdataset);
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_update_process(catzs, newzone, name,
|
|
|
|
&rdataset);
|
|
|
|
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);
|
|
|
|
|
|
|
|
dns_db_detachnode(db, &node);
|
2022-03-24 20:24:00 +00:00
|
|
|
|
|
|
|
if (!is_vers_processed) {
|
|
|
|
is_vers_processed = true;
|
|
|
|
result = dns_dbiterator_first(it);
|
|
|
|
} else {
|
|
|
|
result = dns_dbiterator_next(it);
|
|
|
|
}
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_dbiterator_destroy(&it);
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_db_closeversion(db, &oldzone->dbversion, false);
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3),
|
2016-05-26 21:23:19 +02:00
|
|
|
"catz: update_from_db: iteration finished");
|
|
|
|
|
2022-03-17 14:43:18 +00:00
|
|
|
/*
|
|
|
|
* Check catalog zone version compatibilites.
|
|
|
|
*/
|
|
|
|
catz_vers = (newzone->version == DNS_CATZ_VERSION_UNDEFINED)
|
|
|
|
? oldzone->version
|
|
|
|
: newzone->version;
|
|
|
|
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);
|
|
|
|
newzone->broken = true;
|
|
|
|
} 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);
|
|
|
|
newzone->broken = true;
|
|
|
|
} else {
|
|
|
|
oldzone->version = catz_vers;
|
|
|
|
}
|
|
|
|
|
|
|
|
final:
|
|
|
|
if (newzone->broken) {
|
|
|
|
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);
|
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
*/
|
2016-05-31 08:12:51 +10:00
|
|
|
result = dns_catz_zones_merge(oldzone, newzone);
|
2016-06-22 10:49:25 +02:00
|
|
|
dns_catz_zone_detach(&newzone);
|
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,
|
2020-02-12 13:59:18 +01:00
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
|
2016-05-26 21:23:19 +02:00
|
|
|
"catz: failed merging zones: %s",
|
2016-05-31 08:12:51 +10:00
|
|
|
isc_result_totext(result));
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
|
|
|
|
ISC_LOG_DEBUG(3),
|
2016-05-26 21:23:19 +02:00
|
|
|
"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.
|
|
|
|
*/
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!oldzone->db_registered) {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_db_updatenotify_register(
|
|
|
|
db, dns_catz_dbupdate_callback, oldzone->catzs);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
oldzone->db_registered = 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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_prereconfig(dns_catz_zones_t *catzs) {
|
|
|
|
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
|
|
|
|
2022-03-08 11:22:55 +01:00
|
|
|
isc_ht_iter_create(catzs->zones, &iter);
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_ht_iter_next(iter))
|
|
|
|
{
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_zone_t *zone = NULL;
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_ht_iter_current(iter, (void **)&zone);
|
2018-04-17 08:29:14 -07:00
|
|
|
zone->active = false;
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
2016-05-31 23:01:53 +02:00
|
|
|
INSIST(result == ISC_R_NOMORE);
|
|
|
|
isc_ht_iter_destroy(&iter);
|
2016-05-26 21:23:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
dns_catz_postreconfig(dns_catz_zones_t *catzs) {
|
|
|
|
isc_result_t result;
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zone_t *newzone = NULL;
|
2020-02-13 14:44:37 -08: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);
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;) {
|
2018-11-28 18:57:38 +11:00
|
|
|
dns_catz_zone_t *zone = NULL;
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_ht_iter_current(iter, (void **)&zone);
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!zone->active) {
|
2016-05-31 23:01:53 +02:00
|
|
|
char cname[DNS_NAME_FORMATSIZE];
|
2016-06-20 13:39:44 +02:00
|
|
|
dns_name_format(&zone->name, cname,
|
|
|
|
DNS_NAME_FORMATSIZE);
|
2016-05-31 23:01:53 +02:00
|
|
|
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
2020-02-12 13:59:18 +01:00
|
|
|
DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
|
2016-05-31 23:01:53 +02:00
|
|
|
"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
|
|
|
*/
|
2020-02-13 14:44:37 -08:00
|
|
|
result = dns_catz_new_zone(catzs, &newzone,
|
|
|
|
&zone->name);
|
2016-05-31 23:01:53 +02:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
dns_catz_zones_merge(zone, newzone);
|
|
|
|
dns_catz_zone_detach(&newzone);
|
|
|
|
|
2016-06-22 10:49:25 +02:00
|
|
|
/* Make sure that we have an empty catalog zone. */
|
2016-05-31 23:01:53 +02:00
|
|
|
INSIST(isc_ht_count(zone->entries) == 0);
|
2016-06-22 10:49:25 +02:00
|
|
|
result = isc_ht_iter_delcurrent_next(iter);
|
2016-05-31 23:01:53 +02:00
|
|
|
dns_catz_zone_detach(&zone);
|
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
|
2020-02-13 14:44:37 -08: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
|
|
|
}
|