* SOFTWARE.
*/
-/* $Id: tsig.h,v 1.24.2.1 2000/07/27 23:45:53 gson Exp $ */
+/* $Id: tsig.h,v 1.24.2.2 2000/07/27 23:57:35 gson Exp $ */
#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1
#define DNS_TSIG_FUDGE 300
struct dns_tsig_keyring {
- ISC_LIST(dns_tsigkey_t) keys;
+ dns_rbt_t *keys;
isc_rwlock_t lock;
isc_mem_t *mctx;
};
dns_tsig_keyring_t *ring; /* the enclosing keyring */
isc_mutex_t lock;
/* Locked */
- isc_boolean_t deleted; /* has this been deleted? */
isc_uint32_t refs; /* reference counter */
/* Unlocked */
- ISC_LINK(dns_tsigkey_t) link;
};
#define dns_tsigkey_empty(tsigkey) ((tsigkey)->key == NULL)
*/
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'.
*
* Requires:
- * 'key' not NULL and '*key' is a valid TSIG key
+ * 'keyp' is not NULL and '*keyp' is a valid TSIG key
*
* Ensures:
- * 'key' points to NULL
+ * 'keyp' points to NULL
*/
void
dns_tsigkey_setdeleted(dns_tsigkey_t *key);
/*
- * Marks this key as deleted. It will be deleted when no references
- * exist.
+ * Prevents this key from being used again. It will be deleted when
+ * no references * exist.
*
* Requires:
- * 'key' is a valid TSIG key
+ * 'key' is a valid TSIG key on a keyring
*/
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.
*
* Requires:
* 'mctx' is not NULL
- * 'ring' is not NULL, and '*ring' is NULL
+ * 'ringp' is not NULL, and '*ringp' is NULL
*
* Returns:
* ISC_R_SUCCESS
void
-dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring);
+dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
/*
* Destroy a TSIG key ring.
*
* Requires:
- * 'ring' is not NULL
+ * 'ringp' is not NULL
*/
ISC_LANG_ENDDECLS
*/
/*
- * $Id: tsig.c,v 1.72.2.2 2000/07/27 23:45:51 gson Exp $
+ * $Id: tsig.c,v 1.72.2.3 2000/07/27 23:57:33 gson Exp $
* Principal Author: Brian Wellington
*/
#include <dns/keyvalues.h>
#include <dns/message.h>
+#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
else
tkey->creator = NULL;
- ISC_LINK_INIT(tkey, link);
tkey->key = NULL;
tkey->ring = ring;
+ tkey->refs = 0;
if (length > 0) {
- dns_tsigkey_t *tmp;
+ dns_tsigkey_t *tmp = NULL;
isc_buffer_init(&b, secret, length);
isc_buffer_add(&b, length);
if (ring != NULL) {
RWLOCK(&ring->lock, isc_rwlocktype_write);
- tmp = ISC_LIST_HEAD(ring->keys);
- while (tmp != NULL) {
- if (dns_name_equal(&tkey->name, &tmp->name) &&
- !tmp->deleted)
- {
- ret = ISC_R_EXISTS;
- RWUNLOCK(&ring->lock,
- isc_rwlocktype_write);
- goto cleanup_algorithm;
- }
- tmp = ISC_LIST_NEXT(tmp, link);
+ ret = dns_rbt_findname(ring->keys, name, 0, NULL,
+ (void *)&tmp);
+ if (ret == ISC_R_SUCCESS) {
+ ret = ISC_R_EXISTS;
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+ goto cleanup_algorithm;
+ }
+ 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);
}
}
- tkey->refs = 0;
if (key != NULL)
tkey->refs++;
tkey->generated = generated;
tkey->inception = inception;
tkey->expire = expire;
- tkey->deleted = ISC_FALSE;
tkey->mctx = mctx;
ret = isc_mutex_init(&tkey->lock);
if (ret != ISC_R_SUCCESS) {
static void
tsigkey_free(dns_tsigkey_t *key) {
- dns_tsig_keyring_t *ring;
-
REQUIRE(VALID_TSIG_KEY(key));
- ring = key->ring;
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->algorithm, key->mctx);
if (key->key != NULL)
}
void
-dns_tsigkey_detach(dns_tsigkey_t **key) {
- dns_tsigkey_t *tkey;
+dns_tsigkey_detach(dns_tsigkey_t **keyp) {
+ dns_tsigkey_t *key;
isc_boolean_t should_free = ISC_FALSE;
- REQUIRE(key != NULL);
- REQUIRE(VALID_TSIG_KEY(*key));
- tkey = *key;
- *key = NULL;
+ REQUIRE(keyp != NULL);
+ REQUIRE(VALID_TSIG_KEY(*keyp));
+ key = *keyp;
+ *keyp = NULL;
- LOCK(&tkey->lock);
- tkey->refs--;
- if (tkey->refs == 0 && (tkey->deleted || tkey->key == NULL))
+ LOCK(&key->lock);
+ key->refs--;
+ if (key->refs == 0)
should_free = ISC_TRUE;
- UNLOCK(&tkey->lock);
+ UNLOCK(&key->lock);
if (should_free)
- tsigkey_free(tkey);
+ tsigkey_free(key);
}
void
dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
- INSIST(VALID_TSIG_KEY(key));
- LOCK(&key->lock);
- key->deleted = ISC_TRUE;
- UNLOCK(&key->lock);
+ REQUIRE(VALID_TSIG_KEY(key));
+ REQUIRE(key->ring != NULL);
+
+ 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
{
dns_tsigkey_t *key;
isc_stdtime_t now;
+ isc_result_t result;
REQUIRE(tsigkey != NULL);
REQUIRE(*tsigkey == NULL);
isc_stdtime_get(&now);
RWLOCK(&ring->lock, isc_rwlocktype_read);
- key = ISC_LIST_HEAD(ring->keys);
- while (key != NULL) {
- if (dns_name_equal(&key->name, name) &&
- (algorithm == NULL ||
- dns_name_equal(&key->algorithm, algorithm)) &&
- !key->deleted)
- {
- if (key->inception != key->expire &&
- key->expire < now)
- {
- /*
- * The key has expired.
- */
- key->deleted = ISC_TRUE;
- continue;
- }
- LOCK(&key->lock);
- key->refs++;
- UNLOCK(&key->lock);
- *tsigkey = key;
- RWUNLOCK(&ring->lock, isc_rwlocktype_read);
- return (ISC_R_SUCCESS);
- }
- key = ISC_LIST_NEXT(key, link);
+ key = NULL;
+ result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
+ if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
+ }
+ if (algorithm != NULL && !dns_name_equal(&key->algorithm, algorithm)) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
}
+ if (key->inception != key->expire && key->expire < now) {
+ /*
+ * The key has expired.
+ */
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ 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);
+ key->refs++;
+ UNLOCK(&key->lock);
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
- *tsigkey = NULL;
- return (ISC_R_NOTFOUND);
+ *tsigkey = key;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+free_tsignode(void *node, void *_unused) {
+ dns_tsigkey_t *key;
+
+ UNUSED(_unused);
+
+ REQUIRE(node != NULL);
+
+ key = node;
+ dns_tsigkey_detach(&key);
}
isc_result_t
-dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring) {
- isc_result_t ret;
+dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
+ isc_result_t result;
+ dns_tsig_keyring_t *ring;
REQUIRE(mctx != NULL);
- REQUIRE(ring != NULL);
- REQUIRE(*ring == NULL);
+ REQUIRE(ringp != 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)
return (ISC_R_NOMEMORY);
- ret = isc_rwlock_init(&(*ring)->lock, 0, 0);
- if (ret != ISC_R_SUCCESS) {
+ result = isc_rwlock_init(&ring->lock, 0, 0);
+ if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_rwlock_init() failed: %s",
- isc_result_totext(ret));
+ isc_result_totext(result));
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);
}
void
-dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring) {
- isc_mem_t *mctx;
+dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
+ dns_tsig_keyring_t *ring;
- REQUIRE(ring != NULL);
- REQUIRE(*ring != NULL);
+ REQUIRE(ringp != NULL);
+ REQUIRE(*ringp != NULL);
- while (!ISC_LIST_EMPTY((*ring)->keys)) {
- dns_tsigkey_t *key = ISC_LIST_HEAD((*ring)->keys);
- 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 = *ringp;
+ *ringp = NULL;
- *ring = NULL;
+ dns_rbt_destroy(&ring->keys);
+ isc_rwlock_destroy(&ring->lock);
+ isc_mem_put(ring->mctx, ring, sizeof(dns_tsig_keyring_t));
}