adb.c revision 3f6a66689410910ef601a4d26f10a24f331ef83c
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999 Internet Software Consortium.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Permission to use, copy, modify, and distribute this software for any
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Implementation notes
364a82f7c25b62967678027043425201a5e5171aBob Halley * --------------------
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * In handles, if task == NULL, no events will be generated, and no events
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * have been sent. If task != NULL but taskaction == NULL, an event has been
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * posted but not yet freed. If neigher are NULL, no event was posted.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADB_MAGIC 0x44616462 /* Dadb. */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
2e91b1f3d417cd65e7ec9db1097dfa12e72d8e47Andreas Gustafsson#define DNS_ADBNAME_MAGIC 0x6164624e /* adbN. */
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson#define DNS_ADBNAMEHOOK_MAGIC 0x61644e48 /* adNH. */
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson#define DNS_ADBZONEINFO_MAGIC 0x6164625a /* adbZ. */
3eef7eaba00e9bd468d8036c709a296a0e5b76f1Andreas Gustafsson#define DNS_ADBZONEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBZONEINFO_MAGIC)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADBENTRY_MAGIC 0x61646245 /* adbE. */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * Lengths of lists needs to be powers of two.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADBNAMELIST_LENGTH 32 /* how many buckets for names */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADBENTRYLIST_LENGTH 32 /* how many buckets for addresses */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define FREE_ITEMS 16 /* free count for memory pools */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define FILL_COUNT 8 /* fill count for memory pools */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#define DNS_ADB_INVALIDBUCKET (-1) /* invalid bucket address */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssontypedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssontypedef struct dns_adbnamehook dns_adbnamehook_t;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssontypedef struct dns_adbzoneinfo dns_adbzoneinfo_t;
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafssontypedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafsson isc_mempool_t *nhmp; /* dns_adbnamehook_t */
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafsson isc_mempool_t *zimp; /* dns_adbzoneinfo_t */
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafsson isc_mempool_t *ahmp; /* dns_adbhandle_t */
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson * Bucketized locks and lists for names.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_adbnamelist_t names[DNS_ADBNAMELIST_LENGTH];
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_mutex_t namelocks[DNS_ADBNAMELIST_LENGTH];
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_boolean_t name_sd[DNS_ADBNAMELIST_LENGTH];
94a3e829e0b9e25660ec136742ad5c3694067c70Andreas Gustafsson unsigned int name_refcnt[DNS_ADBNAMELIST_LENGTH];
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Bucketized locks for entries.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_adbentrylist_t entries[DNS_ADBENTRYLIST_LENGTH];
e5a213d7ee3258524936f96191250c1edea2d6baDavid Lawrence isc_mutex_t entrylocks[DNS_ADBENTRYLIST_LENGTH];
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * dns_adbnamehook_t
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * This is a small widget that dangles off a dns_adbname_t. It contains a
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * pointer to the address information about this host, and a link to the next
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * namehook that will contain the next address this host has.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * dns_adbzoneinfo_t
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * This is a small widget that holds zone-specific information about an
94a3e829e0b9e25660ec136742ad5c3694067c70Andreas Gustafsson * address. Currently limited to lameness, but could just as easily be
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson * extended to other types of information about zones.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * An address entry. It holds quite a bit of information about addresses,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * including edns state, rtt, and of course the address of the host.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff unsigned int srtt;
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafsson * Internal functions (and prototypes).
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline void free_adbname(dns_adb_t *, dns_adbname_t **);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *, dns_name_t *);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline void free_adbzoneinfo(dns_adb_t *, dns_adbzoneinfo_t **);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbentry_t *new_adbentry(dns_adb_t *);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbhandle_t *new_adbhandle(dns_adb_t *);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline void free_adbhandle(dns_adb_t *, dns_adbhandle_t **);
ade06bd257e7c888588a89ddd8247c66cbf6c9a5Andreas Gustafssonstatic inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *,
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic void print_dns_name(FILE *, dns_name_t *);
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic void print_namehook_list(FILE *, dns_adbname_t *);
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic void print_handle_list(FILE *, dns_adbname_t *);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic inline void inc_adb_irefcnt(dns_adb_t *, isc_boolean_t);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic inline void dec_adb_irefcnt(dns_adb_t *, isc_boolean_t);
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafssonstatic inline void inc_adb_erefcnt(dns_adb_t *, isc_boolean_t);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic inline void dec_adb_erefcnt(dns_adb_t *, isc_boolean_t);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic inline void dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafssonstatic inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafssonstatic void clean_namehooks_at_name(dns_adb_t *, dns_adbname_t *);
22eeba5ec6b621eb81aec084a1a4e0776aee0f41Andreas Gustafssonstatic void clean_handles_at_name(dns_adbname_t *, isc_eventtype_t);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonstatic isc_result_t construct_name(dns_adb_t *, dns_adbhandle_t *,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic inline void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrenceviolate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
6fcfd0c35d3fd6aea3d36ad002b68e59ac62fdc7Brian Wellington * The ADB _MUST_ be locked before calling.
6fcfd0c35d3fd6aea3d36ad002b68e59ac62fdc7Brian Wellingtonshutdown_names(dns_adb_t *adb, isc_boolean_t kill_fetches)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson (void)kill_fetches; /* XXX need to implement */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson for (bucket = 0 ; bucket < DNS_ADBNAMELIST_LENGTH ; bucket++) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Run through the list. For each name, clean up handles
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * found there, and cancel any fetches running. When
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * all the fetches are canceled, the name will destroy
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson name = ISC_LIST_HEAD(adb->names[bucket]);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson clean_handles_at_name(name, DNS_EVENT_ADBSHUTDOWN);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson /* XXX TODO: cancel fetches */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson /* if no fetches, kill! */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ISC_LIST_UNLINK(adb->names[bucket], name, link);
a672bfbee46c261729811405685db409bd7c9285Andreas Gustafsson name = ISC_LIST_HEAD(adb->names[bucket]);
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsclean_namehooks_at_name(dns_adb_t *adb, dns_adbname_t *name)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson namehook = ISC_LIST_HEAD(name->namehooks);
bb56f556f520621bcab33688c31d655953774adcAndreas Gustafsson * Clean up the entry if needed.
bb56f556f520621bcab33688c31d655953774adcAndreas Gustafsson if (addr_bucket != DNS_ADB_INVALIDBUCKET)
c718c8aa60e77ed39da5a16d24798e46cfc74f8dAndreas Gustafsson * Free the namehook
cb284e7bd479a4309bfa9ccfb139a07ceb3edfd6Andreas Gustafsson ISC_LIST_UNLINK(name->namehooks, namehook, link);
cb284e7bd479a4309bfa9ccfb139a07ceb3edfd6Andreas Gustafsson namehook = ISC_LIST_HEAD(name->namehooks);
cb284e7bd479a4309bfa9ccfb139a07ceb3edfd6Andreas Gustafsson if (addr_bucket != DNS_ADB_INVALIDBUCKET)
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafssonclean_handles_at_name(dns_adbname_t *name, isc_eventtype_t evtype)
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafsson * Unlink the handle from the name, letting the caller
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafsson * call dns_adb_done() on it to clean it up later.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ISC_LIST_UNLINK(name->handles, handle, link);
3e8a8028a47e2a6a1303fb8c3483e781ac940478Mark Andrewsstatic inline void
3e8a8028a47e2a6a1303fb8c3483e781ac940478Mark Andrewsinc_adb_irefcnt(dns_adb_t *adb, isc_boolean_t lock)
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsstatic inline void
6c7e680943ccdb75f23b050a7bc5ac0825e5244aMark Andrewsdec_adb_irefcnt(dns_adb_t *adb, isc_boolean_t lock)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic inline void
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssoninc_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock)
c47baa985c31bbcf396b52958654164afd1091c6James Bristerstatic inline void
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssondec_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock)
e82d19b0c77c8e408b3c1fb2e34488d4993f4b21Andreas Gustafssonstatic inline void
bb56f556f520621bcab33688c31d655953774adcAndreas Gustafssoninc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic inline void
cb284e7bd479a4309bfa9ccfb139a07ceb3edfd6Andreas Gustafssondec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock)
a7e803adb0894257fbc0fc4560ff5d915c2b6194Andreas Gustafsson ISC_LIST_UNLINK(adb->entries[bucket], entry, link);
94a3e829e0b9e25660ec136742ad5c3694067c70Andreas Gustafsson entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
94a3e829e0b9e25660ec136742ad5c3694067c70Andreas Gustafssonnew_adbname(dns_adb_t *adb, dns_name_t *dnsname)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafssonstatic inline void
6889d57aabc5f48eaee78894e20054215319b461Andreas Gustafssonfree_adbname(dns_adb_t *adb, dns_adbname_t **name)
94a3e829e0b9e25660ec136742ad5c3694067c70Andreas Gustafsson INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
static inline dns_adbnamehook_t *
return (NULL);
return (nh);
static inline dns_adbzoneinfo_t *
return (NULL);
return (NULL);
return (zi);
static inline dns_adbentry_t *
dns_adbentry_t *e;
if (e == NULL)
return (NULL);
e->refcnt = 0;
e->flags = 0;
e->goodness = 0;
e->srtt = 0;
dns_adbentry_t *e;
e = *entry;
e->magic = 0;
static inline dns_adbhandle_t *
dns_adbhandle_t *h;
if (h == NULL)
return (NULL);
h->magic = 0;
return (NULL);
static inline dns_adbaddrinfo_t *
return (NULL);
return (ai);
static inline dns_adbname_t *
int bucket;
return (adbname);
return (NULL);
static inline dns_adbentry_t *
int bucket;
return (entry);
return (NULL);
static isc_boolean_t
return (ISC_FALSE);
return (is_bad);
int bucket;
goto next;
goto out;
next:
out:
return (ISC_R_NOMEMORY);
goto fail0a;
goto fail0b;
goto fail0c;
goto fail1;
for (i = 0 ; i < DNS_ADBNAMELIST_LENGTH ; i++) {
for (i = 0 ; i < DNS_ADBENTRYLIST_LENGTH ; i++)
goto fail2;
#define MPINIT(t, p, l, n) do { \
goto fail3; \
isc_mempool_setname((p), n); \
return (ISC_R_SUCCESS);
return (result);
if (!done)
} while (!done);
int bucket;
goto out;
goto fail;
goto fail;
goto out;
goto fail;
goto again;
fail:
out:
if (attach_to_task) {
return (result);
int name_bucket;
return (ISC_R_NOTFOUND);
if (decr_adbrefcnt)
return (DNS_R_SUCCESS);
goto out;
goto out;
goto out;
goto out;
return (ISC_R_SUCCESS);
out:
if (free_name)
if (free_entry)
if (free_namehook)
return (result);
int bucket;
goto cleanup;
const char *tmpp;
for (i = 0 ; i < DNS_ADBNAMELIST_LENGTH ; i++)
for (i = 0 ; i < DNS_ADBENTRYLIST_LENGTH ; i++)
for (i = 0 ; i < DNS_ADBNAMELIST_LENGTH ; i++) {
for (i = 0 ; i < DNS_ADBENTRYLIST_LENGTH ; i++) {
case AF_INET:
case AF_INET6:
for (i = 0 ; i < DNS_ADBENTRYLIST_LENGTH ; i++)
for (i = 0 ; i < DNS_ADBNAMELIST_LENGTH ; i++)
const char *tmpp;
(void)adb;
case AF_INET:
case AF_INET6:
isc_buffer_t b;
static isc_result_t
int addr_bucket;
goto fail;
goto fail;
fail:
if (return_success)
return (ISC_R_SUCCESS);
return (result);
int bucket;
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);