2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 18:19:42 +00:00
bind/lib/dns/keytable.c

829 lines
21 KiB
C
Raw Normal View History

2000-02-23 23:31:33 +00:00
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* 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 http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
2000-02-23 23:31:33 +00:00
*/
/*! \file */
2000-06-22 22:00:42 +00:00
#include <stdbool.h>
#include <isc/mem.h>
2015-02-06 13:30:22 +11:00
#include <isc/print.h>
#include <isc/refcount.h>
2000-02-23 23:31:33 +00:00
#include <isc/rwlock.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
2000-02-23 23:31:33 +00:00
#include <isc/util.h>
#include <dns/keytable.h>
#include <dns/fixedname.h>
#include <dns/rbt.h>
#include <dns/result.h>
2000-02-23 23:31:33 +00: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 {
2016-07-22 23:46:17 +00:00
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
isc_refcount_t active_nodes;
isc_refcount_t references;
2016-07-22 23:46:17 +00:00
isc_rwlock_t rwlock;
/* Locked by rwlock. */
dns_rbt_t *table;
};
struct dns_keynode {
2016-07-22 23:46:17 +00:00
unsigned int magic;
isc_refcount_t refcount;
dst_key_t * key;
bool managed;
bool initial;
2016-07-22 23:46:17 +00:00
struct dns_keynode * next;
};
static void
free_keynode(void *node, void *arg) {
dns_keynode_t *keynode = node;
isc_mem_t *mctx = arg;
dns_keynode_detachall(mctx, &keynode);
}
2000-02-23 23:31:33 +00:00
isc_result_t
dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
dns_keytable_t *keytable;
isc_result_t result;
/*
* Create a keytable.
*/
REQUIRE(keytablep != NULL && *keytablep == NULL);
2001-11-12 19:05:39 +00:00
keytable = isc_mem_get(mctx, sizeof(*keytable));
if (keytable == NULL) {
return (ISC_R_NOMEMORY);
}
2000-02-23 23:31:33 +00:00
keytable->table = NULL;
result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
if (result != ISC_R_SUCCESS) {
2000-02-23 23:31:33 +00:00
goto cleanup_keytable;
}
2000-02-23 23:31:33 +00:00
result = isc_rwlock_init(&keytable->rwlock, 0, 0);
if (result != ISC_R_SUCCESS) {
2000-02-23 23:31:33 +00:00
goto cleanup_rbt;
}
2000-02-23 23:31:33 +00:00
isc_refcount_init(&keytable->active_nodes, 0);
isc_refcount_init(&keytable->references, 1);
2000-02-23 23:31:33 +00:00
keytable->mctx = NULL;
isc_mem_attach(mctx, &keytable->mctx);
2000-02-24 00:33:02 +00:00
keytable->magic = KEYTABLE_MAGIC;
2000-02-23 23:31:33 +00:00
*keytablep = keytable;
return (ISC_R_SUCCESS);
cleanup_rbt:
2000-02-23 23:31:33 +00:00
dns_rbt_destroy(&keytable->table);
cleanup_keytable:
isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
2000-02-23 23:31:33 +00:00
return (result);
}
void
dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
/*
* Attach *targetp to source.
*/
REQUIRE(VALID_KEYTABLE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
2000-02-23 23:31:33 +00:00
*targetp = source;
}
void
dns_keytable_detach(dns_keytable_t **keytablep) {
REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
dns_keytable_t *keytable = *keytablep;
*keytablep = NULL;
2000-02-23 23:31:33 +00:00
if (isc_refcount_decrement(&keytable->references) == 1) {
isc_refcount_destroy(&keytable->references);
isc_refcount_destroy(&keytable->active_nodes);
2000-02-23 23:31:33 +00:00
dns_rbt_destroy(&keytable->table);
isc_rwlock_destroy(&keytable->rwlock);
keytable->magic = 0;
isc_mem_putanddetach(&keytable->mctx,
keytable, sizeof(*keytable));
2000-02-23 23:31:33 +00:00
}
}
/*%
* Search "node" for either a null key node or a key node for the exact same
* key as the one supplied in "keyp" and, if found, update it accordingly.
*/
static isc_result_t
update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
dns_keynode_t *knode;
REQUIRE(keyp != NULL && *keyp != NULL);
REQUIRE(node != NULL);
for (knode = node->data; knode != NULL; knode = knode->next) {
if (knode->key == NULL) {
/*
* Null key node found. Attach the supplied key to it,
* making it a non-null key node and transferring key
* ownership to the keytable.
*/
knode->key = *keyp;
*keyp = NULL;
return (ISC_R_SUCCESS);
} else if (dst_key_compare(knode->key, *keyp)) {
/*
* Key node found for the supplied key. Free the
* supplied copy of the key and update the found key
* node's flags if necessary.
*/
dst_key_free(keyp);
if (!initial) {
dns_keynode_trust(knode);
}
return (ISC_R_SUCCESS);
}
}
return (ISC_R_NOTFOUND);
}
/*%
* Create a key node for "keyp" (or a null key node if "keyp" is NULL), set
* "managed" and "initial" as requested and make the created key node the first
* one attached to "node" in "keytable".
*/
static isc_result_t
prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
dns_keytable_t *keytable, bool managed,
bool initial)
{
dns_keynode_t *knode = NULL;
isc_result_t result;
2000-02-23 23:31:33 +00:00
REQUIRE(keyp == NULL || *keyp != NULL);
2000-02-23 23:31:33 +00:00
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(!initial || managed);
2000-02-23 23:31:33 +00:00
result = dns_keynode_create(keytable->mctx, &knode);
if (result != ISC_R_SUCCESS) {
return (result);
}
2000-02-23 23:31:33 +00:00
/*
* If a key was supplied, transfer its ownership to the keytable.
*/
if (keyp) {
knode->key = *keyp;
*keyp = NULL;
}
2000-02-23 23:31:33 +00:00
knode->managed = managed;
knode->initial = initial;
knode->next = node->data;
node->data = knode;
2000-02-23 23:31:33 +00:00
return (ISC_R_SUCCESS);
}
2000-02-23 23:31:33 +00:00
/*%
* Add key "keyp" at "keyname" in "keytable". If the key already exists at the
* requested name, update its flags. If "keyp" 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.
*/
static isc_result_t
insert(dns_keytable_t *keytable, bool managed, bool initial,
const dns_name_t *keyname, dst_key_t **keyp)
{
dns_rbtnode_t *node = NULL;
isc_result_t result;
REQUIRE(VALID_KEYTABLE(keytable));
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
result = dns_rbt_addnode(keytable->table, keyname, &node);
if (result == ISC_R_SUCCESS) {
/*
* There was no node for "keyname" in "keytable" yet, so one
* was created. Create a new key node for the supplied key (or
* a null key node if "keyp" is NULL) and attach it to the
* created node.
*/
result = prepend_keynode(keyp, node, keytable, managed,
initial);
} else if (result == ISC_R_EXISTS) {
/*
* A node already exists for "keyname" in "keytable".
*/
if (keyp == NULL) {
/*
* We were told to add a null key at "keyname", which
* means there is nothing left to do as there is either
* a null key at this node already or there is a
* non-null key node which would not be affected.
* Reset result to reflect the fact that the node for
* "keyname" is already marked as secure.
*/
result = ISC_R_SUCCESS;
} else {
/*
* We were told to add the key supplied in "keyp" at
* "keyname". Try to find an already existing key node
* we could reuse for the supplied key (i.e. a null key
* node or a key node for the exact same key) and, if
* found, update it accordingly.
*/
result = update_keynode(keyp, node, initial);
if (result == ISC_R_NOTFOUND) {
/*
* The node for "keyname" only contains key
* nodes for keys different than the supplied
* one. Create a new key node for the supplied
* key and prepend it before the others.
*/
result = prepend_keynode(keyp, node, keytable,
managed, initial);
}
}
2000-02-23 23:31:33 +00:00
}
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
return (result);
}
isc_result_t
dns_keytable_add(dns_keytable_t *keytable, bool managed,
bool initial, dst_key_t **keyp)
2009-07-01 23:47:36 +00:00
{
REQUIRE(keyp != NULL && *keyp != NULL);
REQUIRE(!initial || managed);
return (insert(keytable, managed, initial, dst_key_name(*keyp), keyp));
}
isc_result_t
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
return (insert(keytable, true, false, name, NULL));
}
isc_result_t
dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) {
isc_result_t result;
dns_rbtnode_t *node = NULL;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(keyname != NULL);
2009-07-01 23:47:36 +00:00
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL)
result = dns_rbt_deletenode(keytable->table,
node, false);
else
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_PARTIALMATCH)
result = ISC_R_NOTFOUND;
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
return (result);
}
isc_result_t
dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
isc_result_t result;
dns_name_t *keyname;
dns_rbtnode_t *node = NULL;
dns_keynode_t *knode = NULL, **kprev = NULL;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(dstkey != NULL);
keyname = dst_key_name(dstkey);
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == DNS_R_PARTIALMATCH)
result = ISC_R_NOTFOUND;
if (result != ISC_R_SUCCESS)
goto finish;
if (node->data == NULL) {
result = ISC_R_NOTFOUND;
goto finish;
}
knode = node->data;
if (knode->next == NULL && knode->key != NULL &&
dst_key_compare(knode->key, dstkey) == true)
{
result = dns_rbt_deletenode(keytable->table, node, false);
goto finish;
}
2009-07-01 23:47:36 +00:00
kprev = (dns_keynode_t **) &node->data;
while (knode != NULL) {
if (knode->key != NULL &&
dst_key_compare(knode->key, dstkey) == true)
break;
kprev = &knode->next;
knode = knode->next;
}
if (knode != NULL) {
if (knode->key != NULL)
dst_key_free(&knode->key);
/*
* This is equivalent to:
* dns_keynode_attach(knode->next, &tmp);
* dns_keynode_detach(kprev);
* dns_keynode_attach(tmp, &kprev);
* dns_keynode_detach(&tmp);
*/
*kprev = knode->next;
knode->next = NULL;
dns_keynode_detach(keytable->mctx, &knode);
} else
result = DNS_R_PARTIALMATCH;
finish:
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
return (result);
}
isc_result_t
dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
dns_keynode_t **keynodep)
{
isc_result_t result;
dns_rbtnode_t *node = NULL;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(keyname != NULL);
REQUIRE(keynodep != NULL && *keynodep == NULL);
2009-07-01 23:47:36 +00:00
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL) {
isc_refcount_increment0(&keytable->active_nodes);
dns_keynode_attach(node->data, keynodep);
} else
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_PARTIALMATCH)
result = ISC_R_NOTFOUND;
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
2000-02-23 23:31:33 +00:00
return (result);
}
isc_result_t
dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_keynode_t **nextnodep)
{
/*
* Return the next key after 'keynode', regardless of
* properties.
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(VALID_KEYNODE(keynode));
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
if (keynode->next == NULL)
return (ISC_R_NOTFOUND);
dns_keynode_attach(keynode->next, nextnodep);
isc_refcount_increment(&keytable->active_nodes);
return (ISC_R_SUCCESS);
}
2000-02-23 23:31:33 +00:00
isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
2000-02-23 23:31:33 +00:00
dns_secalg_t algorithm, dns_keytag_t tag,
dns_keynode_t **keynodep)
{
isc_result_t result;
dns_keynode_t *knode;
void *data;
/*
* Search for a key named 'name', matching 'algorithm' and 'tag' in
* 'keytable'.
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(dns_name_isabsolute(name));
REQUIRE(keynodep != NULL && *keynodep == NULL);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
/*
* Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname()
* as that indicates that 'name' was not found.
*
* DNS_R_PARTIALMATCH indicates that the name was found but we
* didn't get a match on algorithm and key id arguments.
*/
2000-02-23 23:31:33 +00:00
knode = NULL;
data = NULL;
2000-04-19 18:27:24 +00:00
result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
2000-02-23 23:31:33 +00:00
if (result == ISC_R_SUCCESS) {
INSIST(data != NULL);
for (knode = data; knode != NULL; knode = knode->next) {
if (knode->key == NULL) {
knode = NULL;
break;
}
if (algorithm == dst_key_alg(knode->key)
&& tag == dst_key_id(knode->key))
2000-02-23 23:31:33 +00:00
break;
}
if (knode != NULL) {
isc_refcount_increment0(&keytable->active_nodes);
dns_keynode_attach(knode, keynodep);
2000-02-23 23:31:33 +00:00
} else
result = DNS_R_PARTIALMATCH;
2000-02-23 23:31:33 +00:00
} else if (result == DNS_R_PARTIALMATCH)
result = ISC_R_NOTFOUND;
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
isc_result_t
dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_keynode_t **nextnodep)
{
isc_result_t result;
dns_keynode_t *knode;
/*
* Search for the next key with the same properties as 'keynode' in
* 'keytable'.
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(VALID_KEYNODE(keynode));
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
for (knode = keynode->next; knode != NULL; knode = knode->next) {
if (knode->key == NULL) {
knode = NULL;
break;
}
if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
dst_key_id(keynode->key) == dst_key_id(knode->key))
break;
}
if (knode != NULL) {
isc_refcount_increment(&keytable->active_nodes);
result = ISC_R_SUCCESS;
dns_keynode_attach(knode, nextnodep);
} else
result = ISC_R_NOTFOUND;
return (result);
}
2000-04-18 17:47:17 +00:00
isc_result_t
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;
void *data;
/*
* Search for the deepest match in 'keytable'.
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(dns_name_isabsolute(name));
REQUIRE(foundname != NULL);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
data = NULL;
2000-04-19 18:27:24 +00:00
result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
2000-04-18 17:47:17 +00:00
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
result = ISC_R_SUCCESS;
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
void
dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
dns_keynode_t **target)
{
/*
* Give back a keynode found via dns_keytable_findkeynode().
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(VALID_KEYNODE(source));
REQUIRE(target != NULL && *target == NULL);
isc_refcount_increment(&keytable->active_nodes);
dns_keynode_attach(source, target);
}
2000-02-23 23:31:33 +00:00
void
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
2000-02-23 23:31:33 +00:00
{
/*
* Give back a keynode found via dns_keytable_findkeynode().
*/
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
INSIST(isc_refcount_decrement(&keytable->active_nodes) > 0);
dns_keynode_detach(keytable->mctx, keynodep);
2000-02-23 23:31:33 +00:00
}
isc_result_t
dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
dns_name_t *foundname, bool *wantdnssecp)
2000-02-23 23:31:33 +00:00
{
isc_result_t result;
dns_rbtnode_t *node = 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);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
result = dns_rbt_findnode(keytable->table, name, foundname, &node,
NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL);
2000-02-23 23:31:33 +00:00
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
INSIST(node->data != NULL);
*wantdnssecp = true;
result = ISC_R_SUCCESS;
2000-02-23 23:31:33 +00:00
} else if (result == ISC_R_NOTFOUND) {
*wantdnssecp = false;
result = ISC_R_SUCCESS;
2000-02-23 23:31:33 +00:00
}
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
static isc_result_t
putstr(isc_buffer_t **b, const char *str) {
isc_result_t result;
result = isc_buffer_reserve(b, strlen(str));
if (result != ISC_R_SUCCESS)
return (result);
2015-02-06 23:45:21 +00:00
isc_buffer_putstr(*b, str);
return (ISC_R_SUCCESS);
}
isc_result_t
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);
result = isc_buffer_allocate(keytable->mctx, &text, 4096);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_keytable_totext(keytable, &text);
if (isc_buffer_usedlength(text) != 0) {
(void) putstr(&text, "\n");
} else if (result == ISC_R_SUCCESS)
(void) putstr(&text, "none");
else {
(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);
}
isc_result_t
dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
isc_result_t result;
dns_keynode_t *knode;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(text != NULL && *text != NULL);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain, keytable->mctx);
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOTFOUND)
result = ISC_R_SUCCESS;
goto cleanup;
}
for (;;) {
char pbuf[DST_KEY_FORMATSIZE];
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
for (knode = node->data; knode != NULL; knode = knode->next) {
char obuf[DNS_NAME_FORMATSIZE + 200];
if (knode->key == NULL)
continue;
dst_key_format(knode->key, pbuf, sizeof(pbuf));
snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf,
knode->initial ? "initializing " : "",
knode->managed ? "managed" : "static");
result = putstr(text, obuf);
if (result != ISC_R_SUCCESS)
break;
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
break;
}
}
cleanup:
dns_rbtnodechain_invalidate(&chain);
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
isc_result_t
dns_keytable_forall(dns_keytable_t *keytable,
void (*func)(dns_keytable_t *, dns_keynode_t *, void *),
void *arg)
{
isc_result_t result;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
REQUIRE(VALID_KEYTABLE(keytable));
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain, keytable->mctx);
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOTFOUND)
result = ISC_R_SUCCESS;
goto cleanup;
}
isc_refcount_increment0(&keytable->active_nodes);
for (;;) {
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
if (node->data != NULL)
(*func)(keytable, node->data, arg);
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
break;
}
}
INSIST(isc_refcount_decrement(&keytable->active_nodes) > 0);
cleanup:
dns_rbtnodechain_invalidate(&chain);
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
2000-02-23 23:31:33 +00:00
dst_key_t *
dns_keynode_key(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
return (keynode->key);
}
bool
dns_keynode_managed(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
return (keynode->managed);
}
bool
dns_keynode_initial(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
return (keynode->initial);
}
void
dns_keynode_trust(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
keynode->initial = false;
}
isc_result_t
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
dns_keynode_t *knode;
REQUIRE(target != NULL && *target == NULL);
knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
if (knode == NULL)
return (ISC_R_NOMEMORY);
knode->magic = KEYNODE_MAGIC;
knode->managed = false;
knode->initial = false;
knode->key = NULL;
knode->next = NULL;
isc_refcount_init(&knode->refcount, 1);
*target = knode;
return (ISC_R_SUCCESS);
}
void
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
REQUIRE(VALID_KEYNODE(source));
isc_refcount_increment(&source->refcount);
*target = source;
}
void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
REQUIRE(keynode != NULL && VALID_KEYNODE(*keynode));
dns_keynode_t *node = *keynode;
*keynode = NULL;
if (isc_refcount_decrement(&node->refcount) == 1) {
isc_refcount_destroy(&node->refcount);
if (node->key != NULL) {
dst_key_free(&node->key);
}
isc_mem_put(mctx, node, sizeof(dns_keynode_t));
}
}
void
dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) {
dns_keynode_t *next = NULL, *node = *keynode;
REQUIRE(VALID_KEYNODE(node));
while (node != NULL) {
next = node->next;
dns_keynode_detach(mctx, &node);
node = next;
}
*keynode = NULL;
}