keytable.c revision dafcb997e390efa4423883dafd100c975c4095d6
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont/*
9eb24f1f84885d5c2e51a7f675264db398c31af7Tinderbox User * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * Copyright (C) 2000, 2001 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * copyright notice and this permission notice appear in all copies.
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont *
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * PERFORMANCE OF THIS SOFTWARE.
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont */
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont/* $Id: keytable.c,v 1.28 2004/03/05 05:09:20 marka Exp $ */
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <config.h>
22b23fb59dcedebdb735ec1406d0557225b649abEvan Hunt
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <isc/mem.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <isc/rwlock.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <isc/string.h> /* Required for HP/UX (and others?) */
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#include <isc/util.h>
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt#include <dns/keytable.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <dns/fixedname.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <dns/rbt.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#include <dns/result.h>
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontstruct dns_keytable {
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont /* Unlocked. */
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont unsigned int magic;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_mem_t *mctx;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_mutex_t lock;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_rwlock_t rwlock;
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt /* Locked by lock. */
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt isc_uint32_t active_nodes;
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt /* Locked by rwlock. */
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt isc_uint32_t references;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_rbt_t *table;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont};
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontstruct dns_keynode {
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt unsigned int magic;
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt dst_key_t * key;
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt struct dns_keynode * next;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews};
cc6cddfd94e8f0c58c290317b0853dac30b1b895Evan Hunt
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd')
78608b0a454246d0e1e0169f1d671b8427e48199Francis Dupont#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
78608b0a454246d0e1e0169f1d671b8427e48199Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontstatic void
debd489a44363870f96f75818e89ec27d3cab736Francis Dupontfree_keynode(void *node, void *arg) {
debd489a44363870f96f75818e89ec27d3cab736Francis Dupont dns_keynode_t *keynode = node;
debd489a44363870f96f75818e89ec27d3cab736Francis Dupont isc_mem_t *mctx = arg;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(VALID_KEYNODE(keynode));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dst_key_free(&keynode->key);
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt if (keynode->next != NULL)
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont free_keynode(keynode->next, mctx);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_mem_put(mctx, keynode, sizeof(dns_keynode_t));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont}
210970a2488bb4c7eb679b3cbd918a9031fc5649Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontisc_result_t
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt dns_keytable_t *keytable;
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt isc_result_t result;
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt /*
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont * Create a keytable.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt */
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt REQUIRE(keytablep != NULL && *keytablep == NULL);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt keytable = isc_mem_get(mctx, sizeof(*keytable));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt if (keytable == NULL)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt return (ISC_R_NOMEMORY);
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt keytable->table = NULL;
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont if (result != ISC_R_SUCCESS)
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt goto cleanup_keytable;
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt result = isc_mutex_init(&keytable->lock);
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt if (result != ISC_R_SUCCESS) {
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont UNEXPECTED_ERROR(__FILE__, __LINE__,
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont "isc_mutex_init() failed: %s",
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont isc_result_totext(result));
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont result = ISC_R_UNEXPECTED;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont goto cleanup_rbt;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont }
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont result = isc_rwlock_init(&keytable->rwlock, 0, 0);
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman if (result != ISC_R_SUCCESS) {
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont UNEXPECTED_ERROR(__FILE__, __LINE__,
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont "isc_rwlock_init() failed: %s",
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews isc_result_totext(result));
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews result = ISC_R_UNEXPECTED;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont goto cleanup_lock;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont }
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont keytable->mctx = mctx;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews keytable->active_nodes = 0;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews keytable->references = 1;
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt keytable->magic = KEYTABLE_MAGIC;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont *keytablep = keytable;
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt return (ISC_R_SUCCESS);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt cleanup_lock:
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt DESTROYLOCK(&keytable->lock);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont cleanup_rbt:
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_rbt_destroy(&keytable->table);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont cleanup_keytable:
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_mem_put(mctx, keytable, sizeof(*keytable));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont return (result);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont}
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
411d2914ade28174f3789d4a8e43636fc68eb310Mark Andrews
411d2914ade28174f3789d4a8e43636fc68eb310Mark Andrewsvoid
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupontdns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt /*
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont * Attach *targetp to source.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt */
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont REQUIRE(VALID_KEYTABLE(source));
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont REQUIRE(targetp != NULL && *targetp == NULL);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont RWLOCK(&source->rwlock, isc_rwlocktype_write);
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont INSIST(source->references > 0);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont source->references++;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont INSIST(source->references != 0);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont *targetp = source;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont}
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontvoid
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_detach(dns_keytable_t **keytablep) {
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_boolean_t destroy = ISC_FALSE;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_keytable_t *keytable;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont /*
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * Detach *keytablep from its keytable.
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont */
f79a36eeedfeb1295e0702f8ea2800dae28245b3Mark Andrews
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont keytable = *keytablep;
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt INSIST(keytable->references > 0);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont keytable->references--;
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt LOCK(&keytable->lock);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont if (keytable->references == 0 && keytable->active_nodes == 0)
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt destroy = ISC_TRUE;
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt UNLOCK(&keytable->lock);
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
4bf4beede27aff2da69d31c5baa995f594838378Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews if (destroy) {
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews dns_rbt_destroy(&keytable->table);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews isc_rwlock_destroy(&keytable->rwlock);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont DESTROYLOCK(&keytable->lock);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont keytable->magic = 0;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_mem_put(keytable->mctx, keytable, sizeof(*keytable));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont }
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont *keytablep = NULL;
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt}
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Huntisc_result_t
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp) {
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_result_t result;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_keynode_t *knode;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_rbtnode_t *node;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont dns_name_t *keyname;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman /*
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt * Add '*keyp' to 'keytable'.
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont */
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt REQUIRE(VALID_KEYTABLE(keytable));
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt REQUIRE(keyp != NULL);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont keyname = dst_key_name(*keyp);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont knode = isc_mem_get(keytable->mctx, sizeof(*knode));
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont if (knode == NULL)
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont return (ISC_R_NOMEMORY);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont node = NULL;
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont result = dns_rbt_addnode(keytable->table, keyname, &node);
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
4bf4beede27aff2da69d31c5baa995f594838378Mark Andrews knode->magic = KEYNODE_MAGIC;
4bf4beede27aff2da69d31c5baa995f594838378Mark Andrews knode->key = *keyp;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont knode->next = node->data;
4bf4beede27aff2da69d31c5baa995f594838378Mark Andrews node->data = knode;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont *keyp = NULL;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont knode = NULL;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont result = ISC_R_SUCCESS;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont }
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt
8f0502e922120f27207fbf6b6dda18f1112e486cEvan Hunt if (knode != NULL)
8f0502e922120f27207fbf6b6dda18f1112e486cEvan Hunt isc_mem_put(keytable->mctx, knode, sizeof(*knode));
e3b59e4af757d4b26ecb96e65f9953488283c216Evan Hunt
8f0502e922120f27207fbf6b6dda18f1112e486cEvan Hunt return (result);
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt}
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontisc_result_t
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt dns_secalg_t algorithm, dns_keytag_t tag,
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt dns_keynode_t **keynodep)
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt{
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_result_t result;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont dns_keynode_t *knode;
6f6f08b7a4ea50806099b23ca97010195c1365cdEvan Hunt void *data;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont /*
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * Search for a key named 'name', matching 'algorithm' and 'tag' in
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont * 'keytable'.
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont */
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(VALID_KEYTABLE(keytable));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(dns_name_isabsolute(name));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(keynodep != NULL && *keynodep == NULL);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont knode = NULL;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont data = NULL;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont if (result == ISC_R_SUCCESS) {
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont INSIST(data != NULL);
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt for (knode = data; knode != NULL; knode = knode->next) {
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt if (algorithm == dst_key_alg(knode->key)
8a198fa776a09beb4dabf40b73a54d9c7bd70ac9Evan Hunt && tag == dst_key_id(knode->key))
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt break;
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt }
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt if (knode != NULL) {
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont LOCK(&keytable->lock);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews keytable->active_nodes++;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews UNLOCK(&keytable->lock);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews *keynodep = knode;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews } else
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews result = ISC_R_NOTFOUND;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews } else if (result == DNS_R_PARTIALMATCH)
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews result = ISC_R_NOTFOUND;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews return (result);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews}
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupontisc_result_t
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupontdns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont dns_keynode_t **nextnodep)
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt{
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt isc_result_t result;
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt dns_keynode_t *knode;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont /*
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont * Search for the next key with the same properties as 'keynode' in
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont * 'keytable'.
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont */
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt REQUIRE(VALID_KEYTABLE(keytable));
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt REQUIRE(VALID_KEYNODE(keynode));
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont REQUIRE(nextnodep != NULL && *nextnodep == NULL);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont for (knode = keynode->next; knode != NULL; knode = knode->next) {
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont dst_key_id(keynode->key) == dst_key_id(knode->key))
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt break;
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt }
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt if (knode != NULL) {
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont LOCK(&keytable->lock);
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt keytable->active_nodes++;
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt UNLOCK(&keytable->lock);
b843f577bbcd6660fbaa506d9e55b156c689a5a8Evan Hunt result = ISC_R_SUCCESS;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont *nextnodep = knode;
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt } else
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt result = ISC_R_NOTFOUND;
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont return (result);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont}
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrewsisc_result_t
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrewsdns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews dns_name_t *foundname)
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews{
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews isc_result_t result;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews void *data;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews /*
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews * Search for the deepest match in 'keytable'.
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews */
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews REQUIRE(VALID_KEYTABLE(keytable));
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont REQUIRE(dns_name_isabsolute(name));
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont REQUIRE(foundname != NULL);
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews
a165a17a81ff3285f4f4d79785fafb465e626183Evan Hunt data = NULL;
1f821c10583d9cddbaf3626a96ff8cf10cdb645bFrancis Dupont result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt result = ISC_R_SUCCESS;
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
ddac1a2b9822b00aa936ef24c6d971f4a1407532Francis Dupont return (result);
ddac1a2b9822b00aa936ef24c6d971f4a1407532Francis Dupont}
ddac1a2b9822b00aa936ef24c6d971f4a1407532Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontvoid
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont{
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont /*
ddac1a2b9822b00aa936ef24c6d971f4a1407532Francis Dupont * Give back a keynode found via dns_keytable_findkeynode().
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont */
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(VALID_KEYTABLE(keytable));
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman LOCK(&keytable->lock);
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman INSIST(keytable->active_nodes > 0);
42782931073786f98d3d0a617351db40066949a4Mukund Sivaraman keytable->active_nodes--;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont UNLOCK(&keytable->lock);
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont *keynodep = NULL;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont}
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontisc_result_t
2a31bd531072824ef252c18303859d6af7451b00Francis Dupontdns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont isc_boolean_t *wantdnssecp)
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont{
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont isc_result_t result;
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont void *data;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont /*
8b78c993cb475cc94e88560941b28c37684789d9Francis Dupont * Is 'name' at or beneath a trusted key?
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont */
11463c0ac24692e229ec87f307f5e7df3c0a7e10Evan Hunt
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont REQUIRE(VALID_KEYTABLE(keytable));
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt REQUIRE(dns_name_isabsolute(name));
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt REQUIRE(wantdnssecp != NULL);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt data = NULL;
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt INSIST(data != NULL);
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt *wantdnssecp = ISC_TRUE;
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt result = ISC_R_SUCCESS;
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt } else if (result == ISC_R_NOTFOUND) {
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt *wantdnssecp = ISC_FALSE;
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt result = ISC_R_SUCCESS;
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt }
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
7d769b7ba79707d51e241813fdafa79f74eb7f17Evan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt return (result);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt}
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Huntdst_key_t *
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Huntdns_keynode_key(dns_keynode_t *keynode) {
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt /*
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt * Get the DST key associated with keynode.
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt */
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt REQUIRE(VALID_KEYNODE(keynode));
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt
d1f39121a69b6afa6c0c9e44eceb60910d1d7f81Evan Hunt return (keynode->key);
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt}
a60bf97f9f7dcde6f4ca6e8188245fb0866200dbEvan Hunt