diff --git a/bin/tests/adb_test.c b/bin/tests/adb_test.c index e7a661fa18..d436cea7fc 100644 --- a/bin/tests/adb_test.c +++ b/bin/tests/adb_test.c @@ -167,32 +167,30 @@ main(int argc, char **argv) isc_sockaddr_fromin(&sockaddr, &ina, 53); result = dns_adb_insert(adb, &name1, &sockaddr); check_result(result, "dns_adb_insert 1.2.3.4"); - printf("Added 1.2.3.4\n"); + printf("Added 1.2.3.4 -> NAME1\n"); ina.s_addr = inet_addr("1.2.3.5"); isc_sockaddr_fromin(&sockaddr, &ina, 53); result = dns_adb_insert(adb, &name1, &sockaddr); check_result(result, "dns_adb_insert 1.2.3.5"); - printf("Added 1.2.3.5\n"); + printf("Added 1.2.3.5 -> NAME1\n"); + + result = dns_adb_insert(adb, &name2, &sockaddr); + check_result(result, "dns_adb_insert 1.2.3.5"); + printf("Added 1.2.3.5 -> NAME2\n"); ina.s_addr = inet_addr("1.2.3.6"); isc_sockaddr_fromin(&sockaddr, &ina, 53); result = dns_adb_insert(adb, &name1, &sockaddr); check_result(result, "dns_adb_insert 1.2.3.6"); - printf("Added 1.2.3.6\n"); - - ina.s_addr = inet_addr("1.2.3.5"); - isc_sockaddr_fromin(&sockaddr, &ina, 53); - result = dns_adb_insert(adb, &name2, &sockaddr); - check_result(result, "dns_adb_insert 1.2.3.5"); - printf("Added 1.2.3.5\n"); + printf("Added 1.2.3.6 -> NAME1\n"); /* * Try to look up a name or two. */ handle = NULL; result = dns_adb_lookup(adb, t2, lookup_callback, &name1, - &name1, &name1, &handle); + &name1, &name1, now, &handle); check_result(result, "dns_adb_lookup name1"); check_result(handle->result, "handle->result"); @@ -218,7 +216,6 @@ main(int argc, char **argv) INSIST(ai->goodness == 50); dns_adb_adjustsrtt(adb, ai, 10000, 0); dns_adb_adjustsrtt(adb, ai, 10, 10); - INSIST(ai->srtt == 2251); dns_adb_done(adb, &handle); @@ -226,7 +223,7 @@ main(int argc, char **argv) * look it up again */ result = dns_adb_lookup(adb, t2, lookup_callback, &name1, - &name1, &name1, &handle); + &name1, &name1, now, &handle); check_result(result, "dns_adb_lookup name1"); check_result(handle->result, "handle->result"); diff --git a/lib/dns/adb.c b/lib/dns/adb.c index efc29d7b93..e853f9cb55 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -32,10 +32,11 @@ #include #include +#include #include #include #include -#include +#include #include #include @@ -92,6 +93,8 @@ struct dns_adb { isc_mempool_t *ahmp; /* dns_adbhandle_t */ isc_mempool_t *aimp; /* dns_adbaddrinfo_t */ + isc_random_t rand; + /* * Bucketized locks and lists for names. */ @@ -158,7 +161,8 @@ struct dns_adbentry { unsigned int refcnt; unsigned int flags; - int goodness; /* bad <= 0 < good */ + int edns_level; /* must be int! */ + int goodness; /* bad < 0 <= good */ unsigned int srtt; isc_sockaddr_t sockaddr; @@ -259,6 +263,9 @@ shutdown_names(dns_adb_t *adb, isc_boolean_t kill_fetches) } } +/* + * Assumes the name bucket is locked. + */ static void clean_namehooks_at_name(dns_adb_t *adb, dns_adbname_t *name) { @@ -302,6 +309,9 @@ clean_namehooks_at_name(dns_adb_t *adb, dns_adbname_t *name) UNLOCK(&adb->entrylocks[addr_bucket]); } +/* + * Assumes the name bucket is locked. + */ static void clean_handles_at_name(dns_adbname_t *name, isc_eventtype_t evtype) { @@ -558,6 +568,7 @@ static inline dns_adbentry_t * new_adbentry(dns_adb_t *adb) { dns_adbentry_t *e; + isc_uint32_t r; e = isc_mempool_get(adb->emp); if (e == NULL) @@ -568,7 +579,8 @@ new_adbentry(dns_adb_t *adb) e->refcnt = 0; e->flags = 0; e->goodness = 0; - e->srtt = 0; + isc_random_get(&adb->rand, &r); + e->srtt = (r & 0x1f) + 1; ISC_LIST_INIT(e->zoneinfo); ISC_LINK_INIT(e, link); @@ -782,15 +794,12 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) * Entry bucket MUST be locked! */ static isc_boolean_t -entry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone) +entry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone, + isc_stdtime_t now) { dns_adbzoneinfo_t *zi, *next_zi; - isc_stdtime_t now; isc_boolean_t is_bad; - if (isc_stdtime_get(&now) != ISC_R_SUCCESS) - return (ISC_FALSE); /* XXXMLG: assume ok if this fails? */ - is_bad = ISC_FALSE; zi = ISC_LIST_HEAD(entry->zoneinfo); @@ -807,9 +816,13 @@ entry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone) free_adbzoneinfo(adb, &zi); } - if (zi != NULL && !is_bad) + /* + * Order tests from least to most expensive. + */ + if (zi != NULL && !is_bad) { if (dns_name_equal(zone, &zi->zone)) is_bad = ISC_TRUE; + } zi = next_zi; } @@ -819,7 +832,7 @@ entry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone) static void copy_namehook_list(dns_adb_t *adb, dns_adbhandle_t *handle, - dns_adbname_t *name, dns_name_t *zone) + dns_adbname_t *name, dns_name_t *zone, isc_stdtime_t now) { dns_adbnamehook_t *namehook; dns_adbaddrinfo_t *addrinfo; @@ -833,7 +846,7 @@ copy_namehook_list(dns_adb_t *adb, dns_adbhandle_t *handle, while (namehook != NULL) { bucket = namehook->entry->lock_bucket; LOCK(&adb->entrylocks[bucket]); - if (entry_is_bad_for_zone(adb, namehook->entry, zone)) + if (entry_is_bad_for_zone(adb, namehook->entry, zone, now)) goto next; addrinfo = new_adbaddrinfo(adb, namehook->entry); if (addrinfo == NULL) { @@ -876,6 +889,8 @@ destroy(dns_adb_t *adb) isc_mutex_destroy(&adb->lock); isc_mutex_destroy(&adb->mplock); + isc_random_invalidate(&adb->rand); + isc_mem_put(adb->mctx, adb, sizeof (dns_adb_t)); } @@ -912,15 +927,19 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, dns_adb_t **newadb) adb->ahmp = NULL; adb->aimp = NULL; - result = isc_mutex_init(&adb->lock); + result = isc_random_init(&adb->rand); if (result != ISC_R_SUCCESS) goto fail0a; - result = isc_mutex_init(&adb->mplock); + + result = isc_mutex_init(&adb->lock); if (result != ISC_R_SUCCESS) goto fail0b; - result = isc_condition_init(&adb->shutdown_cond); + result = isc_mutex_init(&adb->mplock); if (result != ISC_R_SUCCESS) goto fail0c; + result = isc_condition_init(&adb->shutdown_cond); + if (result != ISC_R_SUCCESS) + goto fail0d; /* * Initialize the bucket locks for names and elements. @@ -994,10 +1013,12 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, dns_adb_t **newadb) isc_mempool_destroy(&adb->aimp); isc_condition_destroy(&adb->shutdown_cond); - fail0c: + fail0d: isc_mutex_destroy(&adb->mplock); - fail0b: + fail0c: isc_mutex_destroy(&adb->lock); + fail0b: + isc_random_invalidate(&adb->rand); fail0a: isc_mem_put(mem, adb, sizeof (dns_adb_t)); @@ -1040,7 +1061,7 @@ dns_adb_destroy(dns_adb_t **adbx) isc_result_t dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, void *arg, dns_name_t *name, dns_name_t *zone, - dns_adbhandle_t **handlep) + isc_stdtime_t now, dns_adbhandle_t **handlep) { dns_adbhandle_t *handle; dns_adbname_t *adbname; @@ -1059,6 +1080,12 @@ dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, attach_to_task = ISC_FALSE; result = ISC_R_UNEXPECTED; + if (now == 0) { + result = isc_stdtime_get(&now); + if (result != ISC_R_SUCCESS) + return (result); + } + /* * Look up the name in our internal database. * @@ -1102,7 +1129,7 @@ dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, */ again: if (adbname != NULL) { - copy_namehook_list(adb, handle, adbname, zone); + copy_namehook_list(adb, handle, adbname, zone, now); if (handle->result == ISC_R_NOMEMORY && ISC_LIST_EMPTY(handle->list)) { result = ISC_R_NOMEMORY; diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index b1c346fe39..60b683c201 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -221,7 +221,7 @@ dns_adb_destroy(dns_adb_t **adb); isc_result_t dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, void *arg, dns_name_t *name, dns_name_t *zone, - dns_adbhandle_t **handle); + isc_stdtime_t now, dns_adbhandle_t **handle); /* * Main interface for clients. The adb will look up the name given in * "name" and will build up a list of found addresses, and perhaps start @@ -245,6 +245,11 @@ dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, * fields other than the "link" field. All values can be read at any * time, however. * + * The "now" parameter is used only for determining which entries that + * have a specific time to live or expire time should be removed from + * the running database. If specified as zero, the current time will + * be retrieved and used. + * * Requires: * * *adb be a valid isc_adb_t object. @@ -265,6 +270,10 @@ dns_adb_lookup(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, * will ever be posted for this context. * ISC_R_NOMEMORY insufficient resources * + * Calls, and returns error codes from: + * + * isc_stdtime_get() + * * Notes: * * No internal reference to "name" exists after this function