2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 15:05:23 +00:00

Store tsig keys in an rbt, not a list.

This commit is contained in:
Brian Wellington
2000-07-21 20:53:59 +00:00
parent b6e3718b20
commit a49acbf201
2 changed files with 116 additions and 104 deletions

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: tsig.h,v 1.25 2000/07/18 00:46:03 bwelling Exp $ */ /* $Id: tsig.h,v 1.26 2000/07/21 20:53:59 bwelling Exp $ */
#ifndef DNS_TSIG_H #ifndef DNS_TSIG_H
#define DNS_TSIG_H 1 #define DNS_TSIG_H 1
@@ -42,7 +42,7 @@ extern dns_name_t *dns_tsig_hmacmd5_name;
#define DNS_TSIG_FUDGE 300 #define DNS_TSIG_FUDGE 300
struct dns_tsig_keyring { struct dns_tsig_keyring {
ISC_LIST(dns_tsigkey_t) keys; dns_rbt_t *keys;
isc_rwlock_t lock; isc_rwlock_t lock;
isc_mem_t *mctx; isc_mem_t *mctx;
}; };
@@ -61,10 +61,8 @@ struct dns_tsigkey {
dns_tsig_keyring_t *ring; /* the enclosing keyring */ dns_tsig_keyring_t *ring; /* the enclosing keyring */
isc_mutex_t lock; isc_mutex_t lock;
/* Locked */ /* Locked */
isc_boolean_t deleted; /* has this been deleted? */
isc_uint32_t refs; /* reference counter */ isc_uint32_t refs; /* reference counter */
/* Unlocked */ /* Unlocked */
ISC_LINK(dns_tsigkey_t) link;
}; };
#define dns_tsigkey_empty(tsigkey) ((tsigkey)->key == NULL) #define dns_tsigkey_empty(tsigkey) ((tsigkey)->key == NULL)
@@ -116,25 +114,25 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp);
*/ */
void void
dns_tsigkey_detach(dns_tsigkey_t **key); dns_tsigkey_detach(dns_tsigkey_t **keyp);
/* /*
* Detaches from the tsig key structure pointed to by '*key'. * Detaches from the tsig key structure pointed to by '*key'.
* *
* Requires: * Requires:
* 'key' not NULL and '*key' is a valid TSIG key * 'keyp' is not NULL and '*keyp' is a valid TSIG key
* *
* Ensures: * Ensures:
* 'key' points to NULL * 'keyp' points to NULL
*/ */
void void
dns_tsigkey_setdeleted(dns_tsigkey_t *key); dns_tsigkey_setdeleted(dns_tsigkey_t *key);
/* /*
* Marks this key as deleted. It will be deleted when no references * Prevents this key from being used again. It will be deleted when
* exist. * no references * exist.
* *
* Requires: * Requires:
* 'key' is a valid TSIG key * 'key' is a valid TSIG key on a keyring
*/ */
isc_result_t isc_result_t
@@ -201,13 +199,13 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
isc_result_t isc_result_t
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring); dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
/* /*
* Create an empty TSIG key ring. * Create an empty TSIG key ring.
* *
* Requires: * Requires:
* 'mctx' is not NULL * 'mctx' is not NULL
* 'ring' is not NULL, and '*ring' is NULL * 'ringp' is not NULL, and '*ringp' is NULL
* *
* Returns: * Returns:
* ISC_R_SUCCESS * ISC_R_SUCCESS
@@ -216,12 +214,12 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring);
void void
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring); dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
/* /*
* Destroy a TSIG key ring. * Destroy a TSIG key ring.
* *
* Requires: * Requires:
* 'ring' is not NULL * 'ringp' is not NULL
*/ */
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS

View File

@@ -16,7 +16,7 @@
*/ */
/* /*
* $Id: tsig.c,v 1.75 2000/07/21 20:32:12 bwelling Exp $ * $Id: tsig.c,v 1.76 2000/07/21 20:53:58 bwelling Exp $
* Principal Author: Brian Wellington * Principal Author: Brian Wellington
*/ */
@@ -32,6 +32,7 @@
#include <dns/keyvalues.h> #include <dns/keyvalues.h>
#include <dns/log.h> #include <dns/log.h>
#include <dns/message.h> #include <dns/message.h>
#include <dns/rbt.h>
#include <dns/rdata.h> #include <dns/rdata.h>
#include <dns/rdatalist.h> #include <dns/rdatalist.h>
#include <dns/rdataset.h> #include <dns/rdataset.h>
@@ -123,12 +124,12 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
else else
tkey->creator = NULL; tkey->creator = NULL;
ISC_LINK_INIT(tkey, link);
tkey->key = NULL; tkey->key = NULL;
tkey->ring = ring; tkey->ring = ring;
tkey->refs = 0;
if (length > 0) { if (length > 0) {
dns_tsigkey_t *tmp; dns_tsigkey_t *tmp = NULL;
isc_buffer_init(&b, secret, length); isc_buffer_init(&b, secret, length);
isc_buffer_add(&b, length); isc_buffer_add(&b, length);
@@ -141,30 +142,31 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
if (ring != NULL) { if (ring != NULL) {
RWLOCK(&ring->lock, isc_rwlocktype_write); RWLOCK(&ring->lock, isc_rwlocktype_write);
tmp = ISC_LIST_HEAD(ring->keys); ret = dns_rbt_findname(ring->keys, name, 0, NULL,
while (tmp != NULL) { (void *)&tmp);
if (dns_name_equal(&tkey->name, &tmp->name) && if (ret == ISC_R_SUCCESS) {
!tmp->deleted)
{
ret = ISC_R_EXISTS; ret = ISC_R_EXISTS;
RWUNLOCK(&ring->lock, RWUNLOCK(&ring->lock, isc_rwlocktype_write);
isc_rwlocktype_write);
goto cleanup_algorithm; goto cleanup_algorithm;
} }
tmp = ISC_LIST_NEXT(tmp, link); INSIST(ret == ISC_R_NOTFOUND ||
ret == DNS_R_PARTIALMATCH);
ret = dns_rbt_addname(ring->keys, name, tkey);
if (ret != ISC_R_SUCCESS) {
ret = ISC_R_EXISTS;
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
goto cleanup_algorithm;
} }
ISC_LIST_APPEND(ring->keys, tkey, link); tkey->refs++;
RWUNLOCK(&ring->lock, isc_rwlocktype_write); RWUNLOCK(&ring->lock, isc_rwlocktype_write);
} }
} }
tkey->refs = 0;
if (key != NULL) if (key != NULL)
tkey->refs++; tkey->refs++;
tkey->generated = generated; tkey->generated = generated;
tkey->inception = inception; tkey->inception = inception;
tkey->expire = expire; tkey->expire = expire;
tkey->deleted = ISC_FALSE;
tkey->mctx = mctx; tkey->mctx = mctx;
ret = isc_mutex_init(&tkey->lock); ret = isc_mutex_init(&tkey->lock);
if (ret != ISC_R_SUCCESS) { if (ret != ISC_R_SUCCESS) {
@@ -204,17 +206,9 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
static void static void
tsigkey_free(dns_tsigkey_t *key) { tsigkey_free(dns_tsigkey_t *key) {
dns_tsig_keyring_t *ring;
REQUIRE(VALID_TSIG_KEY(key)); REQUIRE(VALID_TSIG_KEY(key));
ring = key->ring;
key->magic = 0; key->magic = 0;
if (ring != NULL) {
RWLOCK(&ring->lock, isc_rwlocktype_write);
ISC_LIST_UNLINK(ring->keys, key, link);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
}
dns_name_free(&key->name, key->mctx); dns_name_free(&key->name, key->mctx);
dns_name_free(&key->algorithm, key->mctx); dns_name_free(&key->algorithm, key->mctx);
if (key->key != NULL) if (key->key != NULL)
@@ -227,30 +221,32 @@ tsigkey_free(dns_tsigkey_t *key) {
} }
void void
dns_tsigkey_detach(dns_tsigkey_t **key) { dns_tsigkey_detach(dns_tsigkey_t **keyp) {
dns_tsigkey_t *tkey; dns_tsigkey_t *key;
isc_boolean_t should_free = ISC_FALSE; isc_boolean_t should_free = ISC_FALSE;
REQUIRE(key != NULL); REQUIRE(keyp != NULL);
REQUIRE(VALID_TSIG_KEY(*key)); REQUIRE(VALID_TSIG_KEY(*keyp));
tkey = *key; key = *keyp;
*key = NULL; *keyp = NULL;
LOCK(&tkey->lock); LOCK(&key->lock);
tkey->refs--; key->refs--;
if (tkey->refs == 0 && (tkey->deleted || tkey->key == NULL)) if (key->refs == 0)
should_free = ISC_TRUE; should_free = ISC_TRUE;
UNLOCK(&tkey->lock); UNLOCK(&key->lock);
if (should_free) if (should_free)
tsigkey_free(tkey); tsigkey_free(key);
} }
void void
dns_tsigkey_setdeleted(dns_tsigkey_t *key) { dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
INSIST(VALID_TSIG_KEY(key)); REQUIRE(VALID_TSIG_KEY(key));
LOCK(&key->lock); REQUIRE(key->ring != NULL);
key->deleted = ISC_TRUE;
UNLOCK(&key->lock); RWLOCK(&key->ring->lock, isc_rwlocktype_write);
(void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE);
RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
} }
isc_result_t isc_result_t
@@ -1024,6 +1020,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
{ {
dns_tsigkey_t *key; dns_tsigkey_t *key;
isc_stdtime_t now; isc_stdtime_t now;
isc_result_t result;
REQUIRE(tsigkey != NULL); REQUIRE(tsigkey != NULL);
REQUIRE(*tsigkey == NULL); REQUIRE(*tsigkey == NULL);
@@ -1032,79 +1029,96 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
isc_stdtime_get(&now); isc_stdtime_get(&now);
RWLOCK(&ring->lock, isc_rwlocktype_read); RWLOCK(&ring->lock, isc_rwlocktype_read);
key = ISC_LIST_HEAD(ring->keys); key = NULL;
while (key != NULL) { result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
if (dns_name_equal(&key->name, name) && if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
(algorithm == NULL || RWUNLOCK(&ring->lock, isc_rwlocktype_read);
dns_name_equal(&key->algorithm, algorithm)) && return (ISC_R_NOTFOUND);
!key->deleted) }
{ if (algorithm != NULL && !dns_name_equal(&key->algorithm, algorithm)) {
if (key->inception != key->expire && RWUNLOCK(&ring->lock, isc_rwlocktype_read);
key->expire < now) return (ISC_R_NOTFOUND);
{ }
if (key->inception != key->expire && key->expire < now) {
/* /*
* The key has expired. * The key has expired.
*/ */
key->deleted = ISC_TRUE; RWUNLOCK(&ring->lock, isc_rwlocktype_read);
continue; LOCK(&key->lock);
key->refs--;
UNLOCK(&key->lock);
RWLOCK(&ring->lock, isc_rwlocktype_write);
(void) dns_rbt_deletename(ring->keys, name, ISC_FALSE);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
return (ISC_R_NOTFOUND);
} }
LOCK(&key->lock); LOCK(&key->lock);
key->refs++; key->refs++;
UNLOCK(&key->lock); UNLOCK(&key->lock);
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
*tsigkey = key; *tsigkey = key;
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
key = ISC_LIST_NEXT(key, link);
} static void
RWUNLOCK(&ring->lock, isc_rwlocktype_read); free_tsignode(void *node, void *_unused) {
*tsigkey = NULL; dns_tsigkey_t *key;
return (ISC_R_NOTFOUND);
UNUSED(_unused);
REQUIRE(node != NULL);
key = node;
dns_tsigkey_detach(&key);
} }
isc_result_t isc_result_t
dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring) { dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
isc_result_t ret; isc_result_t result;
dns_tsig_keyring_t *ring;
REQUIRE(mctx != NULL); REQUIRE(mctx != NULL);
REQUIRE(ring != NULL); REQUIRE(ringp != NULL);
REQUIRE(*ring == NULL); REQUIRE(*ringp == NULL);
*ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t)); ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
if (ring == NULL) if (ring == NULL)
return (ISC_R_NOMEMORY); return (ISC_R_NOMEMORY);
ret = isc_rwlock_init(&(*ring)->lock, 0, 0); result = isc_rwlock_init(&ring->lock, 0, 0);
if (ret != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_rwlock_init() failed: %s", "isc_rwlock_init() failed: %s",
isc_result_totext(ret)); isc_result_totext(result));
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
} }
ISC_LIST_INIT((*ring)->keys); ring->keys = NULL;
result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
if (result != ISC_R_SUCCESS) {
isc_rwlock_destroy(&ring->lock);
isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
return (result);
}
(*ring)->mctx = mctx; ring->mctx = mctx;
*ringp = ring;
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
void void
dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring) { dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
isc_mem_t *mctx; dns_tsig_keyring_t *ring;
REQUIRE(ring != NULL); REQUIRE(ringp != NULL);
REQUIRE(*ring != NULL); REQUIRE(*ringp != NULL);
while (!ISC_LIST_EMPTY((*ring)->keys)) { ring = *ringp;
dns_tsigkey_t *key = ISC_LIST_HEAD((*ring)->keys); *ringp = NULL;
key->refs = 0;
key->deleted = ISC_TRUE;
tsigkey_free(key);
}
isc_rwlock_destroy(&(*ring)->lock);
mctx = (*ring)->mctx;
isc_mem_put(mctx, *ring, sizeof(dns_tsig_keyring_t));
*ring = NULL; dns_rbt_destroy(&ring->keys);
isc_rwlock_destroy(&ring->lock);
isc_mem_put(ring->mctx, ring, sizeof(dns_tsig_keyring_t));
} }