2000-02-23 23:31:33 +00:00
|
|
|
/*
|
2017-10-11 21:11:37 -07:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-02-23 23:31:33 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
2000-02-23 23:31:33 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
2000-02-23 23:31:33 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2017-10-27 15:45:18 -07:00
|
|
|
* information regarding copyright ownership.
|
2000-02-23 23:31:33 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2018-01-24 18:55:56 +11:00
|
|
|
#include <isc/refcount.h>
|
2021-10-04 17:14:53 +02:00
|
|
|
#include <isc/result.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
#include <isc/rwlock.h>
|
2022-04-11 15:53:34 +01:00
|
|
|
#include <isc/string.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
#include <isc/util.h>
|
|
|
|
|
2019-12-11 00:09:15 -08:00
|
|
|
#include <dns/dnssec.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
#include <dns/fixedname.h>
|
|
|
|
#include <dns/keytable.h>
|
2023-04-15 14:49:45 -07:00
|
|
|
#include <dns/qp.h>
|
2019-09-16 21:06:23 -07:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
|
|
|
#include <dns/rdatastruct.h>
|
2023-04-15 14:49:45 -07:00
|
|
|
#include <dns/view.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2016-07-22 20:02:17 +10:00
|
|
|
#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
|
|
|
|
#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
|
|
|
|
|
|
|
|
#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd')
|
|
|
|
#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
|
|
|
|
|
|
|
|
struct dns_keytable {
|
|
|
|
unsigned int magic;
|
|
|
|
isc_mem_t *mctx;
|
2018-01-24 18:55:56 +11:00
|
|
|
isc_refcount_t references;
|
2016-07-22 20:02:17 +10:00
|
|
|
isc_rwlock_t rwlock;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_t *table;
|
2016-07-22 20:02:17 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
struct dns_keynode {
|
|
|
|
unsigned int magic;
|
2020-06-10 17:07:52 +10:00
|
|
|
isc_mem_t *mctx;
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_refcount_t references;
|
2020-06-10 17:07:52 +10:00
|
|
|
isc_rwlock_t rwlock;
|
2024-03-13 13:42:57 -07:00
|
|
|
dns_name_t name;
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_rdatalist_t *dslist;
|
|
|
|
dns_rdataset_t dsset;
|
2019-09-15 16:36:16 -07:00
|
|
|
bool managed;
|
|
|
|
bool initial;
|
2016-07-22 20:02:17 +10:00
|
|
|
};
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
static dns_keynode_t *
|
2023-04-15 14:49:45 -07:00
|
|
|
new_keynode(const dns_name_t *name, dns_rdata_ds_t *ds,
|
|
|
|
dns_keytable_t *keytable, bool managed, bool initial);
|
|
|
|
|
|
|
|
/* QP trie methods */
|
|
|
|
static void
|
|
|
|
qp_attach(void *uctx, void *pval, uint32_t ival);
|
|
|
|
static void
|
|
|
|
qp_detach(void *uctx, void *pval, uint32_t ival);
|
|
|
|
static size_t
|
|
|
|
qp_makekey(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival);
|
|
|
|
static void
|
|
|
|
qp_triename(void *uctx, char *buf, size_t size);
|
|
|
|
|
|
|
|
static dns_qpmethods_t qpmethods = {
|
|
|
|
qp_attach,
|
|
|
|
qp_detach,
|
|
|
|
qp_makekey,
|
|
|
|
qp_triename,
|
|
|
|
};
|
2020-06-10 17:07:52 +10:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
/* rdataset methods */
|
2020-06-10 17:07:52 +10:00
|
|
|
static void
|
2023-01-05 09:12:35 +01:00
|
|
|
keynode_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG);
|
2020-06-10 17:07:52 +10:00
|
|
|
static isc_result_t
|
|
|
|
keynode_first(dns_rdataset_t *rdataset);
|
|
|
|
static isc_result_t
|
|
|
|
keynode_next(dns_rdataset_t *rdataset);
|
|
|
|
static void
|
|
|
|
keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
|
|
|
|
static void
|
2023-01-05 09:12:35 +01:00
|
|
|
keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG);
|
2020-06-10 17:07:52 +10:00
|
|
|
|
|
|
|
static dns_rdatasetmethods_t methods = {
|
2023-02-17 11:46:58 -08:00
|
|
|
.disassociate = keynode_disassociate,
|
|
|
|
.first = keynode_first,
|
|
|
|
.next = keynode_next,
|
|
|
|
.current = keynode_current,
|
|
|
|
.clone = keynode_clone,
|
2020-06-10 17:07:52 +10:00
|
|
|
};
|
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
static void
|
2023-04-15 14:49:45 -07:00
|
|
|
destroy_keynode(dns_keynode_t *knode) {
|
|
|
|
isc_rwlock_destroy(&knode->rwlock);
|
|
|
|
if (knode->dslist != NULL) {
|
2025-05-23 13:02:22 -07:00
|
|
|
ISC_LIST_FOREACH (knode->dslist->rdata, rdata, link) {
|
2023-04-15 14:49:45 -07:00
|
|
|
ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link);
|
|
|
|
isc_mem_put(knode->mctx, rdata->data,
|
|
|
|
DNS_DS_BUFFERSIZE);
|
|
|
|
isc_mem_put(knode->mctx, rdata, sizeof(*rdata));
|
2019-12-23 20:26:03 -08:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_mem_put(knode->mctx, knode->dslist, sizeof(*knode->dslist));
|
|
|
|
}
|
2000-04-05 17:19:43 +00:00
|
|
|
|
2024-03-13 13:42:57 -07:00
|
|
|
dns_name_free(&knode->name, knode->mctx);
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_mem_putanddetach(&knode->mctx, knode, sizeof(dns_keynode_t));
|
2000-04-05 17:19:43 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
ISC_REFCOUNT_IMPL(dns_keynode, destroy_keynode);
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keytable_create(dns_view_t *view, dns_keytable_t **keytablep) {
|
|
|
|
dns_keytable_t *keytable = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a keytable.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(keytablep != NULL && *keytablep == NULL);
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
keytable = isc_mem_get(view->mctx, sizeof(*keytable));
|
|
|
|
*keytable = (dns_keytable_t){
|
|
|
|
.magic = KEYTABLE_MAGIC,
|
|
|
|
};
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_mem_attach(view->mctx, &keytable->mctx);
|
|
|
|
dns_qpmulti_create(view->mctx, &qpmethods, view, &keytable->table);
|
2018-08-01 11:46:11 +02:00
|
|
|
isc_refcount_init(&keytable->references, 1);
|
2000-02-23 23:31:33 +00:00
|
|
|
*keytablep = keytable;
|
2023-04-15 14:49:45 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
static void
|
|
|
|
destroy_keytable(dns_keytable_t *keytable) {
|
|
|
|
dns_qpread_t qpr;
|
|
|
|
dns_qpiter_t iter;
|
|
|
|
void *pval = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
keytable->magic = 0;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
|
|
|
dns_qpiter_init(&qpr, &iter);
|
2023-09-19 00:41:57 -07:00
|
|
|
while (dns_qpiter_next(&iter, NULL, &pval, NULL) == ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *n = pval;
|
|
|
|
dns_keynode_detach(&n);
|
|
|
|
}
|
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_destroy(&keytable->table);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_mem_putanddetach(&keytable->mctx, keytable, sizeof(*keytable));
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
ISC_REFCOUNT_IMPL(dns_keytable, destroy_keytable);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
static void
|
2019-12-20 16:23:25 -08:00
|
|
|
add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
|
|
|
|
isc_result_t result;
|
2025-03-20 22:25:56 -07:00
|
|
|
dns_rdata_t *dsrdata = NULL;
|
2019-12-20 16:23:25 -08:00
|
|
|
void *data = NULL;
|
2019-12-23 20:26:03 -08:00
|
|
|
bool exists = false;
|
2019-12-20 16:23:25 -08:00
|
|
|
isc_buffer_t b;
|
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
dsrdata = isc_mem_get(mctx, sizeof(*dsrdata));
|
|
|
|
dns_rdata_init(dsrdata);
|
2017-10-27 15:45:18 -07:00
|
|
|
|
2019-12-20 16:23:25 -08:00
|
|
|
data = isc_mem_get(mctx, DNS_DS_BUFFERSIZE);
|
|
|
|
isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
result = dns_rdata_fromstruct(dsrdata, dns_rdataclass_in,
|
2019-12-20 16:23:25 -08:00
|
|
|
dns_rdatatype_ds, ds, &b);
|
2020-06-10 17:07:52 +10:00
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
RWLOCK(&knode->rwlock, isc_rwlocktype_write);
|
|
|
|
|
|
|
|
if (knode->dslist == NULL) {
|
|
|
|
knode->dslist = isc_mem_get(mctx, sizeof(*knode->dslist));
|
|
|
|
dns_rdatalist_init(knode->dslist);
|
|
|
|
knode->dslist->rdclass = dns_rdataclass_in;
|
|
|
|
knode->dslist->type = dns_rdatatype_ds;
|
|
|
|
|
|
|
|
INSIST(knode->dsset.methods == NULL);
|
|
|
|
knode->dsset.methods = &methods;
|
|
|
|
knode->dsset.rdclass = knode->dslist->rdclass;
|
|
|
|
knode->dsset.type = knode->dslist->type;
|
|
|
|
knode->dsset.covers = knode->dslist->covers;
|
|
|
|
knode->dsset.ttl = knode->dslist->ttl;
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
knode->dsset.keytable.node = knode;
|
|
|
|
knode->dsset.keytable.iter = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
knode->dsset.trust = dns_trust_ultimate;
|
2019-12-20 16:23:25 -08:00
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2025-03-20 22:25:56 -07:00
|
|
|
ISC_LIST_FOREACH (knode->dslist->rdata, rdata, link) {
|
2019-12-23 20:26:03 -08:00
|
|
|
if (dns_rdata_compare(rdata, dsrdata) == 0) {
|
|
|
|
exists = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exists) {
|
|
|
|
isc_mem_put(mctx, dsrdata->data, DNS_DS_BUFFERSIZE);
|
|
|
|
isc_mem_put(mctx, dsrdata, sizeof(*dsrdata));
|
2020-06-10 17:07:52 +10:00
|
|
|
} else {
|
|
|
|
ISC_LIST_APPEND(knode->dslist->rdata, dsrdata, link);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
static isc_result_t
|
2023-04-15 14:49:45 -07:00
|
|
|
delete_ds(dns_qp_t *qp, dns_keytable_t *keytable, dns_keynode_t *knode,
|
|
|
|
dns_rdata_ds_t *ds) {
|
2019-12-23 20:26:03 -08:00
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t dsrdata = DNS_RDATA_INIT;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *newnode = NULL;
|
2019-12-23 20:26:03 -08:00
|
|
|
unsigned char data[DNS_DS_BUFFERSIZE];
|
|
|
|
bool found = false;
|
2023-04-15 14:49:45 -07:00
|
|
|
void *pval = NULL;
|
2019-12-23 20:26:03 -08:00
|
|
|
isc_buffer_t b;
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
RWLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
if (knode->dslist == NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
|
|
|
|
|
|
|
|
result = dns_rdata_fromstruct(&dsrdata, dns_rdataclass_in,
|
|
|
|
dns_rdatatype_ds, ds, &b);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
|
2019-12-23 20:26:03 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2025-03-20 22:25:56 -07:00
|
|
|
ISC_LIST_FOREACH (knode->dslist->rdata, rdata, link) {
|
2019-12-23 20:26:03 -08:00
|
|
|
if (dns_rdata_compare(rdata, &dsrdata) == 0) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
if (!found) {
|
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
/*
|
|
|
|
* The keyname must have matched or we wouldn't be here,
|
|
|
|
* so we use DNS_R_PARTIALMATCH instead of ISC_R_NOTFOUND.
|
|
|
|
*/
|
|
|
|
return DNS_R_PARTIALMATCH;
|
|
|
|
}
|
2020-06-10 17:07:52 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Replace knode with a new instance without the DS.
|
|
|
|
*/
|
2024-03-13 13:42:57 -07:00
|
|
|
newnode = new_keynode(&knode->name, NULL, keytable, knode->managed,
|
2023-04-15 14:49:45 -07:00
|
|
|
knode->initial);
|
2025-03-20 22:25:56 -07:00
|
|
|
ISC_LIST_FOREACH (knode->dslist->rdata, rdata, link) {
|
2020-06-10 17:07:52 +10:00
|
|
|
if (dns_rdata_compare(rdata, &dsrdata) != 0) {
|
|
|
|
dns_rdata_ds_t ds0;
|
|
|
|
result = dns_rdata_tostruct(rdata, &ds0, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
2023-04-15 14:49:45 -07:00
|
|
|
add_ds(newnode, &ds0, keytable->mctx);
|
2020-06-10 17:07:52 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 13:42:57 -07:00
|
|
|
result = dns_qp_deletename(qp, &knode->name, &pval, NULL);
|
2023-04-15 14:49:45 -07:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
INSIST(pval == knode);
|
|
|
|
|
|
|
|
result = dns_qp_insert(qp, newnode, 0);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2020-06-10 17:07:52 +10:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_detach(&knode);
|
2020-06-10 17:07:52 +10:00
|
|
|
return ISC_R_SUCCESS;
|
2019-12-23 20:26:03 -08:00
|
|
|
}
|
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*%
|
2019-12-20 16:23:25 -08:00
|
|
|
* Create a keynode for "ds" (or a null key node if "ds" is NULL), set
|
|
|
|
* "managed" and "initial" as requested and attach the keynode to
|
|
|
|
* to "node" in "keytable".
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2020-06-10 17:07:52 +10:00
|
|
|
static dns_keynode_t *
|
2023-04-15 14:49:45 -07:00
|
|
|
new_keynode(const dns_name_t *name, dns_rdata_ds_t *ds,
|
|
|
|
dns_keytable_t *keytable, bool managed, bool initial) {
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_t *knode = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(!initial || managed);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2019-12-20 16:23:25 -08:00
|
|
|
knode = isc_mem_get(keytable->mctx, sizeof(dns_keynode_t));
|
2024-03-13 13:42:57 -07:00
|
|
|
*knode = (dns_keynode_t){ .name = DNS_NAME_INITEMPTY,
|
|
|
|
.magic = KEYNODE_MAGIC };
|
2019-12-20 16:23:25 -08:00
|
|
|
|
|
|
|
dns_rdataset_init(&knode->dsset);
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_refcount_init(&knode->references, 1);
|
Add the reader-writer synchronization with modified C-RW-WP
This changes the internal isc_rwlock implementation to:
Irina Calciu, Dave Dice, Yossi Lev, Victor Luchangco, Virendra
J. Marathe, and Nir Shavit. 2013. NUMA-aware reader-writer locks.
SIGPLAN Not. 48, 8 (August 2013), 157–166.
DOI:https://doi.org/10.1145/2517327.24425
(The full article available from:
http://mcg.cs.tau.ac.il/papers/ppopp2013-rwlocks.pdf)
The implementation is based on the The Writer-Preference Lock (C-RW-WP)
variant (see the 3.4 section of the paper for the rationale).
The implemented algorithm has been modified for simplicity and for usage
patterns in rbtdb.c.
The changes compared to the original algorithm:
* We haven't implemented the cohort locks because that would require a
knowledge of NUMA nodes, instead a simple atomic_bool is used as
synchronization point for writer lock.
* The per-thread reader counters are not being used - this would
require the internal thread id (isc_tid_v) to be always initialized,
even in the utilities; the change has a slight performance penalty,
so we might revisit this change in the future. However, this change
also saves a lot of memory, because cache-line aligned counters were
used, so on 32-core machine, the rwlock would be 4096+ bytes big.
* The readers use a writer_barrier that will raise after a while when
readers lock can't be acquired to prevent readers starvation.
* Separate ingress and egress readers counters queues to reduce both
inter and intra-thread contention.
2021-03-24 17:52:56 +01:00
|
|
|
isc_rwlock_init(&knode->rwlock);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2025-02-21 12:09:28 +01:00
|
|
|
dns_name_dup(name, keytable->mctx, &knode->name);
|
2023-04-15 14:49:45 -07:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
2019-12-20 16:23:25 -08:00
|
|
|
* If a DS was supplied, initialize an rdatalist.
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2019-12-20 16:23:25 -08:00
|
|
|
if (ds != NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
add_ds(knode, ds, keytable->mctx);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
isc_mem_attach(keytable->mctx, &knode->mctx);
|
2017-10-27 15:45:18 -07:00
|
|
|
knode->managed = managed;
|
|
|
|
knode->initial = initial;
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
return knode;
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*%
|
2019-12-20 16:23:25 -08:00
|
|
|
* Add key trust anchor "ds" at "keyname" in "keytable". If an anchor
|
|
|
|
* already exists at the requested name does not contain "ds", update it.
|
|
|
|
* If "ds" is NULL, add a null key to indicate that "keyname" should be
|
|
|
|
* treated as a secure domain without supplying key data which would allow
|
|
|
|
* the domain to be validated.
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
|
|
|
static isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
insert(dns_keytable_t *keytable, bool managed, bool initial,
|
2022-06-17 10:40:47 +10:00
|
|
|
const dns_name_t *keyname, dns_rdata_ds_t *ds,
|
|
|
|
dns_keytable_callback_t callback, void *callback_arg) {
|
2017-10-27 15:45:18 -07:00
|
|
|
isc_result_t result;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *newnode = NULL;
|
|
|
|
dns_qp_t *qp = NULL;
|
|
|
|
void *pval = NULL;
|
2009-07-13 21:53:03 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_write(keytable->table, &qp);
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
result = dns_qp_getname(qp, keyname, &pval, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
2023-04-15 14:49:45 -07:00
|
|
|
* There was no match for "keyname" in "keytable" yet, so one
|
2019-09-16 21:06:23 -07:00
|
|
|
* was created. Create a new key node for the supplied
|
2019-12-23 20:26:03 -08:00
|
|
|
* trust anchor (or a null key node if "ds" is NULL)
|
2023-04-15 14:49:45 -07:00
|
|
|
* and insert it.
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2023-04-15 14:49:45 -07:00
|
|
|
newnode = new_keynode(keyname, ds, keytable, managed, initial);
|
|
|
|
result = dns_qp_insert(qp, newnode, 0);
|
2022-06-17 10:40:47 +10:00
|
|
|
if (callback != NULL) {
|
|
|
|
(*callback)(keyname, callback_arg);
|
|
|
|
}
|
2023-04-15 14:49:45 -07:00
|
|
|
} else {
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
|
|
|
* A node already exists for "keyname" in "keytable".
|
|
|
|
*/
|
2020-06-10 17:07:52 +10:00
|
|
|
if (ds != NULL) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *knode = pval;
|
|
|
|
add_ds(knode, ds, keytable->mctx);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2020-06-10 17:07:52 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
|
|
|
dns_qpmulti_commit(keytable->table, &qp);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2019-12-20 11:37:11 -08:00
|
|
|
dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial,
|
2022-06-17 10:40:47 +10:00
|
|
|
dns_name_t *name, dns_rdata_ds_t *ds,
|
|
|
|
dns_keytable_callback_t callback, void *callback_arg) {
|
2019-12-20 11:37:11 -08:00
|
|
|
REQUIRE(ds != NULL);
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(!initial || managed);
|
2019-12-23 20:26:03 -08:00
|
|
|
|
2022-06-17 10:40:47 +10:00
|
|
|
return insert(keytable, managed, initial, name, ds, callback,
|
|
|
|
callback_arg);
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
|
2022-06-17 10:40:47 +10:00
|
|
|
return insert(keytable, true, false, name, NULL, NULL, NULL);
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2022-06-17 10:40:47 +10:00
|
|
|
dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname,
|
|
|
|
dns_keytable_callback_t callback, void *callback_arg) {
|
2009-06-30 02:53:46 +00:00
|
|
|
isc_result_t result;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qp_t *qp = NULL;
|
|
|
|
void *pval = NULL;
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(keyname != NULL);
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_write(keytable->table, &qp);
|
|
|
|
result = dns_qp_deletename(qp, keyname, &pval, NULL);
|
2009-06-30 02:53:46 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *n = pval;
|
|
|
|
if (callback != NULL) {
|
|
|
|
(*callback)(keyname, callback_arg);
|
2019-12-23 20:26:03 -08:00
|
|
|
}
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_detach(&n);
|
2019-12-23 20:26:03 -08:00
|
|
|
}
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
|
|
|
dns_qpmulti_commit(keytable->table, &qp);
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2019-12-11 00:09:15 -08:00
|
|
|
dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
|
|
|
|
dns_rdata_dnskey_t *dnskey) {
|
2009-06-30 02:53:46 +00:00
|
|
|
isc_result_t result;
|
2019-12-23 20:26:03 -08:00
|
|
|
dns_keynode_t *knode = NULL;
|
2019-12-11 00:09:15 -08:00
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2019-12-23 20:26:03 -08:00
|
|
|
unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
|
|
|
|
dns_rdata_ds_t ds;
|
|
|
|
isc_buffer_t b;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qp_t *qp = NULL;
|
|
|
|
void *pval = NULL;
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2019-12-11 00:09:15 -08:00
|
|
|
REQUIRE(dnskey != NULL);
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_write(keytable->table, &qp);
|
|
|
|
result = dns_qp_getname(qp, keyname, &pval, NULL);
|
2019-12-11 00:09:15 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-06-30 02:53:46 +00:00
|
|
|
goto finish;
|
2019-12-11 00:09:15 -08:00
|
|
|
}
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
knode = pval;
|
2019-12-23 20:26:03 -08:00
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
RWLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
if (knode->dslist == NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
result = DNS_R_PARTIALMATCH;
|
2009-06-30 02:53:46 +00:00
|
|
|
goto finish;
|
|
|
|
}
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2022-11-29 16:07:39 +11:00
|
|
|
isc_buffer_init(&b, data, sizeof(data));
|
|
|
|
result = dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
|
|
|
|
dns_rdatatype_dnskey, dnskey, &b);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
|
|
|
|
digest, &ds);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto finish;
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
result = delete_ds(qp, keytable, knode, &ds);
|
2019-12-11 00:09:15 -08:00
|
|
|
|
2019-12-23 20:26:03 -08:00
|
|
|
finish:
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
|
|
|
dns_qpmulti_commit(keytable->table, &qp);
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_t **keynodep) {
|
|
|
|
isc_result_t result;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_t qpr;
|
|
|
|
void *pval = NULL;
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(keyname != NULL);
|
|
|
|
REQUIRE(keynodep != NULL && *keynodep == NULL);
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
|
|
|
result = dns_qp_getname(&qpr, keyname, &pval, NULL);
|
2009-06-30 02:53:46 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *knode = pval;
|
|
|
|
dns_keynode_attach(knode, keynodep);
|
2019-07-23 09:52:02 -04:00
|
|
|
}
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2000-04-18 17:47:17 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
|
2000-04-18 17:47:17 +00:00
|
|
|
dns_name_t *foundname) {
|
|
|
|
isc_result_t result;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_t qpr;
|
|
|
|
dns_keynode_t *keynode = NULL;
|
|
|
|
void *pval = NULL;
|
2000-04-18 17:47:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for the deepest match in 'keytable'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(foundname != NULL);
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
2023-09-26 20:19:37 -07:00
|
|
|
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
|
2023-04-15 14:49:45 -07:00
|
|
|
keynode = pval;
|
2000-04-18 17:47:17 +00:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
2024-03-13 13:42:57 -07:00
|
|
|
dns_name_copy(&keynode->name, foundname);
|
2000-04-18 17:47:17 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-04-18 17:47:17 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2000-04-18 17:47:17 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_name_t *foundname, bool *wantdnssecp) {
|
2000-02-23 23:31:33 +00:00
|
|
|
isc_result_t result;
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_t qpr;
|
|
|
|
dns_keynode_t *keynode = NULL;
|
|
|
|
void *pval = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Is 'name' at or beneath a trusted key?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(wantdnssecp != NULL);
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
2023-09-26 20:19:37 -07:00
|
|
|
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
|
2000-02-23 23:31:33 +00:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
2023-04-15 14:49:45 -07:00
|
|
|
keynode = pval;
|
|
|
|
if (foundname != NULL) {
|
2024-03-13 13:42:57 -07:00
|
|
|
dns_name_copy(&keynode->name, foundname);
|
2023-04-15 14:49:45 -07:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
*wantdnssecp = true;
|
2000-03-16 23:57:02 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-02-23 23:31:33 +00:00
|
|
|
} else if (result == ISC_R_NOTFOUND) {
|
2018-04-17 08:29:14 -07:00
|
|
|
*wantdnssecp = false;
|
2000-03-16 23:57:02 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
static isc_result_t
|
|
|
|
putstr(isc_buffer_t **b, const char *str) {
|
|
|
|
isc_result_t result;
|
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
result = isc_buffer_reserve(*b, strlen(str));
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2015-02-05 17:18:15 -08:00
|
|
|
return result;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2015-02-06 23:45:21 +00:00
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
isc_buffer_putstr(*b, str);
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-06-25 03:24:05 +00:00
|
|
|
isc_result_t
|
2015-02-05 17:18:15 -08:00
|
|
|
dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t *text = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(fp != NULL);
|
|
|
|
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(keytable->mctx, &text, 4096);
|
2015-02-05 17:18:15 -08:00
|
|
|
|
|
|
|
result = dns_keytable_totext(keytable, &text);
|
|
|
|
|
|
|
|
if (isc_buffer_usedlength(text) != 0) {
|
|
|
|
(void)putstr(&text, "\n");
|
2019-09-16 21:06:23 -07:00
|
|
|
} else if (result == ISC_R_SUCCESS) {
|
2015-02-05 17:18:15 -08:00
|
|
|
(void)putstr(&text, "none");
|
2019-09-16 21:06:23 -07:00
|
|
|
} else {
|
2015-02-05 17:18:15 -08:00
|
|
|
(void)putstr(&text, "could not dump key table: ");
|
|
|
|
(void)putstr(&text, isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "%.*s", (int)isc_buffer_usedlength(text),
|
|
|
|
(char *)isc_buffer_base(text));
|
|
|
|
|
|
|
|
isc_buffer_free(&text);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
static isc_result_t
|
2023-04-15 14:49:45 -07:00
|
|
|
keynode_dslist_totext(dns_keynode_t *keynode, isc_buffer_t **text) {
|
2019-09-16 21:06:23 -07:00
|
|
|
isc_result_t result;
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
char obuf[DNS_NAME_FORMATSIZE + 200];
|
2020-06-10 17:07:52 +10:00
|
|
|
dns_rdataset_t dsset;
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
dns_rdataset_init(&dsset);
|
|
|
|
if (!dns_keynode_dsset(keynode, &dsset)) {
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2024-03-13 13:42:57 -07:00
|
|
|
dns_name_format(&keynode->name, namebuf, sizeof(namebuf));
|
2023-04-15 14:49:45 -07:00
|
|
|
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH (&dsset) {
|
2019-09-16 21:06:23 -07:00
|
|
|
char algbuf[DNS_SECALG_FORMATSIZE];
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
dns_rdata_ds_t ds;
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
dns_rdataset_current(&dsset, &rdata);
|
2019-09-16 21:06:23 -07:00
|
|
|
result = dns_rdata_tostruct(&rdata, &ds, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
|
|
|
|
|
2020-10-01 10:39:49 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
2019-12-23 20:26:03 -08:00
|
|
|
snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s\n", namebuf,
|
2019-09-16 21:06:23 -07:00
|
|
|
algbuf, ds.key_tag,
|
|
|
|
keynode->initial ? "initializing " : "",
|
|
|
|
keynode->managed ? "managed" : "static");
|
2020-10-01 10:39:49 +10:00
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
2019-09-16 21:06:23 -07:00
|
|
|
|
|
|
|
result = putstr(text, obuf);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-06-10 17:07:52 +10:00
|
|
|
dns_rdataset_disassociate(&dsset);
|
2019-09-16 21:06:23 -07:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2020-06-10 17:07:52 +10:00
|
|
|
dns_rdataset_disassociate(&dsset);
|
2019-09-16 21:06:23 -07:00
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
dns_qpread_t qpr;
|
|
|
|
dns_qpiter_t iter;
|
|
|
|
void *pval = NULL;
|
2010-06-25 03:24:05 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2015-02-05 17:18:15 -08:00
|
|
|
REQUIRE(text != NULL && *text != NULL);
|
2010-06-25 03:24:05 +00:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
|
|
|
dns_qpiter_init(&qpr, &iter);
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2023-09-19 00:41:57 -07:00
|
|
|
while (dns_qpiter_next(&iter, NULL, &pval, NULL) == ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *knode = pval;
|
|
|
|
if (knode->dslist != NULL) {
|
|
|
|
result = keynode_dslist_totext(knode, text);
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
break;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2010-06-25 03:24:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2010-06-25 03:24:05 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
void
|
2016-07-22 20:02:17 +10:00
|
|
|
dns_keytable_forall(dns_keytable_t *keytable,
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
void (*func)(dns_keytable_t *, dns_keynode_t *,
|
|
|
|
dns_name_t *, void *),
|
2016-07-22 20:02:17 +10:00
|
|
|
void *arg) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_t qpr;
|
|
|
|
dns_qpiter_t iter;
|
|
|
|
void *pval = NULL;
|
2016-07-22 20:02:17 +10:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpmulti_query(keytable->table, &qpr);
|
|
|
|
dns_qpiter_init(&qpr, &iter);
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
|
2023-09-19 00:41:57 -07:00
|
|
|
while (dns_qpiter_next(&iter, NULL, &pval, NULL) == ISC_R_SUCCESS) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *knode = pval;
|
2024-03-13 13:42:57 -07:00
|
|
|
(*func)(keytable, knode, &knode->name, arg);
|
2016-07-22 20:02:17 +10:00
|
|
|
}
|
2019-12-23 20:26:03 -08:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_qpread_destroy(keytable->table, &qpr);
|
2016-07-22 20:02:17 +10:00
|
|
|
}
|
|
|
|
|
2020-06-10 17:07:52 +10:00
|
|
|
bool
|
|
|
|
dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset) {
|
2020-10-01 10:39:49 +10:00
|
|
|
bool result;
|
2023-04-15 14:49:45 -07:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
2020-06-10 17:07:52 +10:00
|
|
|
REQUIRE(rdataset == NULL || DNS_RDATASET_VALID(rdataset));
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2020-10-01 10:39:49 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
2019-09-16 21:06:23 -07:00
|
|
|
if (keynode->dslist != NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
if (rdataset != NULL) {
|
2023-01-05 09:12:35 +01:00
|
|
|
keynode_clone(&keynode->dsset,
|
|
|
|
rdataset DNS__DB_FILELINE);
|
2020-06-10 17:07:52 +10:00
|
|
|
}
|
2020-10-01 10:39:49 +10:00
|
|
|
result = true;
|
|
|
|
} else {
|
|
|
|
result = false;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2020-10-01 10:39:49 +10:00
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
return result;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_managed(dns_keynode_t *keynode) {
|
2020-10-01 10:39:49 +10:00
|
|
|
bool managed;
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
2020-10-01 10:39:49 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
managed = keynode->managed;
|
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return managed;
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2017-10-27 15:45:18 -07:00
|
|
|
dns_keynode_initial(dns_keynode_t *keynode) {
|
2020-10-01 10:39:49 +10:00
|
|
|
bool initial;
|
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
2020-10-01 10:39:49 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
initial = keynode->initial;
|
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return initial;
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keynode_trust(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
2020-10-01 10:39:49 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_write);
|
2018-04-17 08:29:14 -07:00
|
|
|
keynode->initial = false;
|
2020-10-01 10:39:49 +10:00
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_write);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2020-06-10 17:07:52 +10:00
|
|
|
|
|
|
|
static void
|
2023-01-05 09:12:35 +01:00
|
|
|
keynode_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *keynode = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
|
|
|
rdataset->methods = NULL;
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
keynode = rdataset->keytable.node;
|
|
|
|
rdataset->keytable.node = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_detach(&keynode);
|
2020-06-10 17:07:52 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
keynode_first(dns_rdataset_t *rdataset) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *keynode = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
keynode = rdataset->keytable.node;
|
2020-06-10 17:07:52 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
rdataset->keytable.iter = ISC_LIST_HEAD(keynode->dslist->rdata);
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
if (rdataset->keytable.iter == NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
return ISC_R_NOMORE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
keynode_next(dns_rdataset_t *rdataset) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *keynode = NULL;
|
|
|
|
dns_rdata_t *rdata = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
rdata = rdataset->keytable.iter;
|
2020-06-10 17:07:52 +10:00
|
|
|
if (rdata == NULL) {
|
|
|
|
return ISC_R_NOMORE;
|
|
|
|
}
|
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
keynode = rdataset->keytable.node;
|
2020-06-10 17:07:52 +10:00
|
|
|
RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
rdataset->keytable.iter = ISC_LIST_NEXT(rdata, link);
|
2020-06-10 17:07:52 +10:00
|
|
|
RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
|
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
if (rdataset->keytable.iter == NULL) {
|
2020-06-10 17:07:52 +10:00
|
|
|
return ISC_R_NOMORE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_rdata_t *list_rdata = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
list_rdata = rdataset->keytable.iter;
|
2020-06-10 17:07:52 +10:00
|
|
|
INSIST(list_rdata != NULL);
|
|
|
|
|
|
|
|
dns_rdata_clone(list_rdata, rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-01-05 09:12:35 +01:00
|
|
|
keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) {
|
2023-04-15 14:49:45 -07:00
|
|
|
dns_keynode_t *keynode = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
keynode = source->keytable.node;
|
2023-04-15 14:49:45 -07:00
|
|
|
isc_refcount_increment(&keynode->references);
|
2020-06-10 17:07:52 +10:00
|
|
|
|
|
|
|
*target = *source;
|
Give the rdataset->privateN fields more helpful names
BIND's rdataset structure is a view of some DNS records. It is
polymorphic, so the details of how the records are stored can vary.
For instance, the records can be held in an rdatalist, or in an
rdataslab in the rbtdb.
The dns_rdataset structure previously had a number of fields called
`private1` up to `private7`, which were used by the various rdataset
implementations. It was not at all clear what these fields were for,
without reading the code and working it out from context.
This change makes the rdataset inheritance hierarchy more clear. The
polymorphic part of a `struct dns_rdataset` is now a union of structs,
each of which is named for the class of implementation using it. The
fields of these structs replace the old `privateN` fields. (Note: the
term "inheritance hierarchy" refers to the fact that the builtin and
SDLZ implementations are based on and inherit from the rdatalist
implementation, which in turn inherits from the generic rdataset.
Most of this change is mechanical, but there are a few extras.
In keynode.c there were a number of REQUIRE()ments that were not
necessary: they had already been checked by the rdataset method
dispatch code. On the other hand, In ncache.c there was a public
function which needed to REQUIRE() that an rdataset was valid.
I have removed lots of "reset iterator state" comments, because it
should now be clear from `target->iter = NULL` where before
`target->private5 = NULL` could have been doing anything.
Initialization is a bit neater in a few places, using C structure
literals where appropriate.
The pointer arithmetic for translating between an rdataslab header and
its raw contents is now fractionally safer.
2023-04-28 01:12:39 +01:00
|
|
|
target->keytable.iter = NULL;
|
2020-06-10 17:07:52 +10:00
|
|
|
}
|
2023-04-15 14:49:45 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval,
|
|
|
|
uint32_t ival ISC_ATTR_UNUSED) {
|
|
|
|
dns_keynode_t *keynode = pval;
|
|
|
|
dns_keynode_ref(keynode);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
qp_detach(void *uctx ISC_ATTR_UNUSED, void *pval,
|
|
|
|
uint32_t ival ISC_ATTR_UNUSED) {
|
|
|
|
dns_keynode_t *keynode = pval;
|
|
|
|
dns_keynode_detach(&keynode);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
|
|
|
|
uint32_t ival ISC_ATTR_UNUSED) {
|
|
|
|
dns_keynode_t *keynode = pval;
|
2024-03-13 13:42:57 -07:00
|
|
|
return dns_qpkey_fromname(key, &keynode->name);
|
2023-04-15 14:49:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
qp_triename(void *uctx, char *buf, size_t size) {
|
|
|
|
dns_view_t *view = uctx;
|
|
|
|
snprintf(buf, size, "view %s secroots table", view->name);
|
|
|
|
}
|