diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h index 633aa2a78f..07b54032c9 100644 --- a/lib/dns/include/dns/tsig.h +++ b/lib/dns/include/dns/tsig.h @@ -15,7 +15,7 @@ * 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 #define DNS_TSIG_H 1 @@ -42,7 +42,7 @@ extern dns_name_t *dns_tsig_hmacmd5_name; #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; }; @@ -61,10 +61,8 @@ struct dns_tsigkey { 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) @@ -116,25 +114,25 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp); */ 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 @@ -201,13 +199,13 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, 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 @@ -216,12 +214,12 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring); 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 diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 181ee96581..8e6547893a 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -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 */ @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -123,12 +124,12 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, 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); @@ -141,30 +142,31 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, 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; } - ISC_LIST_APPEND(ring->keys, tkey, 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; + } + 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) { @@ -204,17 +206,9 @@ dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { 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) @@ -227,30 +221,32 @@ tsigkey_free(dns_tsigkey_t *key) { } 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 @@ -1024,6 +1020,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, { dns_tsigkey_t *key; isc_stdtime_t now; + isc_result_t result; 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); 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)); }