adb.c revision a14eb88840e06b8d458c1556e5452b6d2a50012e
5fa46bc91672ef5737aee6f99763161511566c24Tinderbox User * Copyright (C) 1999, 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Implementation notes
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * --------------------
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff * In finds, if task == NULL, no events will be generated, and no events
de153390f5a1f6d4fa86af91d4cae772d9846ca0Mark Andrews * have been sent. If task != NULL but taskaction == NULL, an event has been
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff * posted but not yet freed. If neither are NULL, no event was posted.
242bba8991b030b7764f0bdca3922d75c34ea51eAndreas Gustafsson * After we have cleaned all buckets, dump the database contents.
28b863e609ff2d97b78663b46894494cfa2ea411Mark Andrews#include <isc/string.h> /* Required for HP/UX (and others?) */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBNAME_MAGIC 0x6164624e /* adbN. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBNAMEHOOK_MAGIC 0x61644e48 /* adNH. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews#define DNS_ADBZONEINFO_MAGIC 0x6164625a /* adbZ. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBZONEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBZONEINFO_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBENTRY_MAGIC 0x61646245 /* adbE. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBFETCH_MAGIC 0x61644634 /* adF4. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBFETCH6_MAGIC 0x61644636 /* adF6. */
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews * The number of buckets needs to be a prime (for good hashing).
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence * XXXRTH How many buckets do we need?
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews * This value must be coordinated with CLEAN_SECONDS (below).
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define NBUCKETS 1009 /* how many buckets for names/addrs */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * For type 3 negative cache entries, we will remember that the address is
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrence * broken for this long. XXXMLG This is also used for actual addresses, too.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * The intent is to keep us from constantly asking about A/A6/AAAA records
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews * if the zone has extremely low TTLs.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define ADB_CACHE_MAXIMUM 86400 /* seconds (86400 = 24 hours) */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Clean CLEAN_BUCKETS buckets every CLEAN_SECONDS.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define CLEAN_PERIOD 3600 /* one pass through every N seconds */
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define CLEAN_BUCKETS ((NBUCKETS / CLEAN_PERIOD) + 0.5)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define CLEAN_SECONDS (CLEAN_PERIOD * CLEAN_BUCKETS / NBUCKETS)
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews#define FREE_ITEMS 64 /* free count for memory pools */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews#define FILL_COUNT 16 /* fill count for memory pools */
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews#define DNS_ADB_INVALIDBUCKET (-1) /* invalid bucket address */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeintypedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencetypedef struct dns_adbnamehook dns_adbnamehook_t;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssontypedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssontypedef struct dns_adbzoneinfo dns_adbzoneinfo_t;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssontypedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssontypedef struct dns_adbfetch dns_adbfetch_t;
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington * Bucketized locks and lists for names.
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington * XXXRTH Have a per-bucket structure that contains all of these?
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * Bucketized locks for entries.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * XXXRTH Have a per-bucket structure that contains all of these?
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * XXXMLG Document these structures.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews unsigned int magic;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int flags;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int chains;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int magic;
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews unsigned int magic;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int flags;
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews * dns_adbnamehook_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * This is a small widget that dangles off a dns_adbname_t. It contains a
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * pointer to the address information about this host, and a link to the next
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * namehook that will contain the next address this host has.
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews unsigned int magic;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews * dns_adbzoneinfo_t
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews * This is a small widget that holds zone-specific information about an
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews * address. Currently limited to lameness, but could just as easily be
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews * extended to other types of information about zones.
b6a0341bcb113e93bd0bc41a9f9a1fc117444da6Mark Andrews unsigned int magic;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * An address entry. It holds quite a bit of information about addresses,
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews * including edns state, rtt, and of course the address of the host.
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews unsigned int refcnt;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews unsigned int flags;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews unsigned int srtt;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * Internal functions (and prototypes).
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void free_adbname(dns_adb_t *, dns_adbname_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrewsstatic inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrewsstatic inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *, dns_name_t *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void free_adbzoneinfo(dns_adb_t *, dns_adbzoneinfo_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbentry_t *new_adbentry(dns_adb_t *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbfind_t *new_adbfind(dns_adb_t *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void free_adbfind(dns_adb_t *, dns_adbfind_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbfetch6_t *new_adbfetch6(dns_adb_t *, dns_adbname_t *,
d981ca645597116d227a48bf37cc5edc061c854dBob Halleystatic inline void free_adbfetch6(dns_adb_t *, dns_adbfetch6_t **);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
e6bd97dded968f82e26b270842b789bff7bca422Mark Andrews unsigned int, int *);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic void print_dns_name(FILE *, dns_name_t *);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic void print_namehook_list(FILE *, dns_adbname_t *);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrewsstatic void print_find_list(FILE *, dns_adbname_t *);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic void print_fetch_list(FILE *, dns_adbname_t *);
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellingtonstatic inline void dec_adb_irefcnt(dns_adb_t *);
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellingtonstatic inline void inc_adb_erefcnt(dns_adb_t *, isc_boolean_t);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic inline void dec_adb_erefcnt(dns_adb_t *, isc_boolean_t);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic inline void dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic void clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic void clean_target(dns_adb_t *, dns_name_t *);
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsstatic void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews unsigned int);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic void cancel_fetches_at_name(dns_adbname_t *);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic isc_result_t fetch_name_v4(dns_adbname_t *, isc_boolean_t);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic isc_result_t fetch_name_aaaa(dns_adbname_t *);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic isc_result_t fetch_name_a6(dns_adbname_t *, isc_boolean_t);
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellingtonstatic void timer_cleanup(isc_task_t *, isc_event_t *);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic inline void link_name(dns_adb_t *, int, dns_adbname_t *);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic inline void unlink_name(dns_adb_t *, dns_adbname_t *);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic inline void unlink_entry(dns_adb_t *, dns_adbentry_t *);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic void kill_name(dns_adbname_t **, isc_eventtype_t);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic void fetch_callback_a6(isc_task_t *, isc_event_t *);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrewsstatic isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews * MUST NOT overlap DNS_ADBFIND_* flags!
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * To the name, address classes are all that really exist. If it has a
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * V6 address it doesn't care if it came from an A6 chain or an AAAA query.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Fetches are broken out into A, AAAA, and A6 types. In some cases,
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews * however, it makes more sense to test for a particular class of fetches,
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews * like V4 or V6 above.
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews#define NAME_FETCH_A6(n) (!ISC_LIST_EMPTY((n)->fetches_a6))
90e303b114e56db5809fdd19805243457fa43cd9Olafur Gudmundsson#define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n) || NAME_FETCH_A6(n))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * Was this fetch started using the hints database?
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * Was this the initial fetch for the A6 record? If so, we might want to
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * start AAAA queries if it fails.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FETCH_FIRSTA6(f) (((f)->flags & FETCH_FIRST_A6) != 0)
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews * Find options and tests to see if there are addresses on the list.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_STARTATROOT(fn) (((fn)->options & DNS_ADBFIND_STARTATROOT) \
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * These are currently used on simple unsigned ints, so they are
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * not really associated with any particular type.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Find out if the flags on a name (nf) indicate if it is a hint or
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * glue, and compare this to the appropriate bits set in o, to see if
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * this is ok.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
d981ca645597116d227a48bf37cc5edc061c854dBob Halley#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Requires the adbname bucket be locked and that no entry buckets be locked.
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews * This code handles A and AAAA rdatasets only.
19d365e4448f1782611280b020987988b7ac3210Mark Andrewsimport_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
6bebabb376b93e7d12f53a253b197a3fc0e0b001Andreas Gustafsson dns_adbentry_t *foundentry; /* NO CLEAN UP! */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson adbname->expire_v6, now + rdataset->ttl);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * Lie a little here. This is more or less so code that cares
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * can find out if any new information was added or not.
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington dns_adbentry_t *foundentry; /* NO CLEAN UP! */
f16495732753175e4a9fc144323a12fdcc29b561Brian Wellington DP(ENTER_LEVEL, "ENTER: import_a6() name %p", name);
e086935752b6e2f51ef2985fee21ccfff617b115David Lawrence name->partial_result |= DNS_ADBFIND_INET6; /* clear for AAAA */
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_sockaddr_fromin6(&sockaddr, &a6ctx->in6addr, 0);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) in import_v6",
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews name->expire_v6 = ISC_MIN(name->expire_v6, a6ctx->expiration);
8dd5237a27e2e824d18f835dc711573aeb23a173Mark Andrews * Requires the name's bucket be locked.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewskill_name(dns_adbname_t **n, isc_eventtype_t ev) {
228c679d7a269423019f7c528db92e855f08240bMark Andrews * If we're dead already, just check to see if we should go
b6a0341bcb113e93bd0bc41a9f9a1fc117444da6Mark Andrews * away now or not.
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * Clean up the name's various lists. These two are destructive
228c679d7a269423019f7c528db92e855f08240bMark Andrews * in that they will always empty the list.
e85702ce5be33d7c07eff6487c6bb4730165f331Mark Andrews clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
e85702ce5be33d7c07eff6487c6bb4730165f331Mark Andrews * If fetches are running, cancel them. If none are running, we can
e85702ce5be33d7c07eff6487c6bb4730165f331Mark Andrews * just kill the name here.
e85702ce5be33d7c07eff6487c6bb4730165f331Mark Andrews * Requires the name's bucket be locked and no entry buckets be locked.
b8e2e5dd861bdc72a5496a745a85f8761bef7dc4Tinderbox Usercheck_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews * Check to see if we need to remove the v4 addresses
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews DP(DEF_LEVEL, "expiring v4 for name %p", name);
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * Check to see if we need to remove the v6 addresses
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff DP(DEF_LEVEL, "expiring v6 for name %p", name);
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * Check to see if we need to remove the alias target.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Requires the name's bucket be locked.
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrewsstatic inline void
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrewslink_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews ISC_LIST_PREPEND(adb->names[bucket], name, plink);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Requires the name's bucket be locked.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsunlink_name(dns_adb_t *adb, dns_adbname_t *name) {
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews ISC_LIST_UNLINK(adb->names[bucket], name, plink);
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews * Requires the entry's bucket be locked.
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrewsstatic inline void
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrewslink_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews * Requires the entry's bucket be locked.
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrewsstatic inline void
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrewsunlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrews if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
fe3472c80b76b6fed0ae674fd63471d02477a03aMark Andrewsstatic inline void
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffviolate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * The ADB _MUST_ be locked before calling. Also, exit conditions must be
19d365e4448f1782611280b020987988b7ac3210Mark Andrews * checked after calling this function.
f8aae502686e2448c48f56697c212a50e2a1cbaeAndreas Gustafsson for (bucket = 0 ; bucket < NBUCKETS ; bucket++) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * This bucket has no names. We must decrement the
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * irefcnt ourselves, since it will not be
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * automatically triggered by a name being unlinked.
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * Run through the list. For each name, clean up finds
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * found there, and cancel any fetches running. When
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * all the fetches are canceled, the name will destroy
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * The ADB _MUST_ be locked before calling. Also, exit conditions must be
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews * checked after calling this function.
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson for (bucket = 0 ; bucket < NBUCKETS ; bucket++) {
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * This bucket has no entries. We must decrement the
9a859983d7059a6eb9c877c1d2ac6a3a5b7170f7Evan Hunt * irefcnt ourselves, since it will not be
9a859983d7059a6eb9c877c1d2ac6a3a5b7170f7Evan Hunt * automatically triggered by an entry being unlinked.
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * Run through the list. Cleanup any entries not
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * associated with names, and which are not in use.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Name bucket must be locked
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews dns_resolver_cancelfetch(name->fetch_a->fetch);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Assumes the name bucket is locked.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsclean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Clean up the entry if needed.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * Free the namehook
d981ca645597116d227a48bf37cc5edc061c854dBob Halleyclean_target(dns_adb_t *adb, dns_name_t *target) {
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halleyset_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley * Copy the CNAME's target into the target name.
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews result = dns_name_dup(&tname, adb->mctx, target);
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews namereln = dns_name_fullcompare(name, fname, &order,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews * Get the target name of the DNAME.
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * Construct the new target name.
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = dns_name_split(name, nlabels, nbits, prefix, NULL);
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = dns_name_concatenate(prefix, &tname, new_target,
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff result = dns_name_dup(new_target, adb->mctx, target);
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews * Assumes nothing is locked, since this is called by the client.
a98551ef592e9be6008e0141ceeb32efd586c5efMark Andrews * Assumes the name bucket is locked.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceclean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
471e0563c7965c556c759775882cd3448dae78eaMark Andrews unsigned int addrs)
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews DP(DEF_LEVEL, "cfan: processing find %p", find);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Unlink the find from the name, letting the caller
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * call dns_adb_destroyfind() on it to clean it up
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff "Sending event %p to task %p for find %p",
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * The caller must be holding the adb lock.
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews * We're now shutdown. Send any whenshutdown events.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * If there aren't any external references either, we're
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * done. Send the control event to initiate shutdown.
ad493ef9ddb5a3e78e9d99f57abe75552f36a8f4Andreas Gustafssonstatic inline void
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrewsstatic inline void
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrewsinc_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrewsstatic inline void
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrewsdec_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffinc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
bfb2a81b65579882a80855c279cedc45aebd62e8Mark Andrewsstatic inline void
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffdec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont (adb->entry_sd[bucket] || entry->expires == 0)) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontnew_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontstatic inline void
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontfree_adbname(dns_adb_t *adb, dns_adbname_t **name) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontnew_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontstatic inline void
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontfree_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontnew_adbzoneinfo(dns_adb_t *adb, dns_name_t *zone) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont if (dns_name_dup(zone, adb->mctx, &zi->zone) != ISC_R_SUCCESS) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontstatic inline void
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupontfree_adbzoneinfo(dns_adb_t *adb, dns_adbzoneinfo_t **zoneinfo) {
9fe8cca06537c45375c1e1d36b82501caf0ae090Francis Dupont INSIST(zoneinfo != NULL && DNS_ADBZONEINFO_VALID(*zoneinfo));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsstatic inline void
38b84a1fcfdbda4d1d0fdca409004ae83be2ace8Mark Andrewsfree_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
38b84a1fcfdbda4d1d0fdca409004ae83be2ace8Mark Andrews INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington * Public members.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * private members
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews "isc_mutex_init failed in new_adbfind()");
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence ISC_EVENT_INIT(&h->event, sizeof (isc_event_t), 0, 0, 0, NULL, NULL,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic inline void
035504dbd8ca5949e8380b860873b3385a4e61e5Mark Andrewsfree_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Caller must be holding the name lock.
5a219d878f0bd786e86da2c9b92999260dda3f8dAndreas Gustafssona6find(void *arg, dns_name_t *a6name, dns_rdatatype_t type, isc_stdtime_t now,
5a219d878f0bd786e86da2c9b92999260dda3f8dAndreas Gustafsson dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (dns_view_simplefind(adb->view, a6name, type, now,
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews * Caller must be holding the name lock.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrencea6missing(dns_a6context_t *a6ctx, dns_name_t *a6name) {
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews result = dns_resolver_createfetch(adb->view->resolver, a6name,
8a17d1e7cdba9fdcf71fb2f821a954a251204105Mark Andrews ISC_LIST_APPEND(name->fetches_a6, fetch, plink);
8a17d1e7cdba9fdcf71fb2f821a954a251204105Mark Andrewsnew_adbfetch6(dns_adb_t *adb, dns_adbname_t *name, dns_a6context_t *a6ctx) {
15330e4fa27c82ac04cc2ce234ec930e4b6b42d3Mark Andrews dns_a6_init(&f->a6ctx, a6find, NULL, import_a6,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsstatic inline void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencefree_adbfetch6(dns_adb_t *adb, dns_adbfetch6_t **fetch) {
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews INSIST(fetch != NULL && DNS_ADBFETCH6_VALID(*fetch));
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsstatic inline void
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsfree_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * Copy bits from the entry into the newly allocated addrinfo. The entry
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * must be locked, and the reference count must be bumped up by one
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * if this function returns a valid pointer.
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsnew_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic inline void
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencefree_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * Search for the name. NOTE: The bucket is kept locked on both
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * success and failure, so it must always be unlocked by the caller!
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * On the first call to this function, *bucketp must be set to
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington * DNS_ADB_INVALIDBUCKET.
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsfind_name_and_lock(dns_adb_t *adb, dns_name_t *name,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * Search for the address. NOTE: The bucket is kept locked on both
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * success and failure, so it must always be unlocked by the caller.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * On the first call to this function, *bucketp must be set to
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington * later calls (within the same "lock path") it can be left alone, so
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington * if this function is called multiple times locking is only done if
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews * the bucket changes.
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsfind_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews if (isc_sockaddr_equal(addr, &entry->sockaddr))
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * Entry bucket MUST be locked!
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsentry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * Has the entry expired?
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater ISC_LIST_UNLINK(entry->zoneinfo, zi, plink);
83ac7ce833930a5c6cb92ad9c04a58e775579e73Bob Halley * Order tests from least to most expensive.
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewscopy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *zone,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews * Check for avoid bitstring timeout.
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews && entry_is_bad_for_zone(adb, entry, zone, now)) {
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews addrinfo = new_adbaddrinfo(adb, entry, find->port);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Found a valid entry. Add it to the find's list.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ISC_LIST_APPEND(find->list, addrinfo, publink);
b6a0341bcb113e93bd0bc41a9f9a1fc117444da6Mark Andrews * Check for avoid bitstring timeout.
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews if (entry_is_bad_for_zone(adb, entry, zone, now))
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews addrinfo = new_adbaddrinfo(adb, entry, find->port);
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews * Found a valid entry. Add it to the find's list.
c5223c9cb7c22620d5ee6611228673e95b48a270Mark Andrews ISC_LIST_APPEND(find->list, addrinfo, publink);
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrewsshutdown_task(isc_task_t *task, isc_event_t *ev) {
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * Kill the timer, and then the ADB itself. Note that this implies
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * that this task was the one scheduled to get timer events. If
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * this is not true (and it is unfortunate there is no way to INSIST()
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * this) badness will occur.
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * name bucket must be locked; adb may be locked; no other locks held.
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrewscheck_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews * The name is empty. Delete it.
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * Our caller, or one of its callers, will be calling check_exit() at
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley * some point, so we don't need to do it here.
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halley * entry bucket must be locked; adb may be locked; no other locks held.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencecheck_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
3bb3b7ac462a90c2b8b1fb783324d800e2ba748cMichael Graff if (entry->expires == 0 || entry->expires > now)
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff * The entry is not in use. Delete it.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * ADB must be locked, and no other locks held.
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graffcleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * ADB must be locked, and no other locks held.
6324997211a5e2d82528dcde98e8981190a35faeMichael Graffcleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
b469f0321d2bcea3914c57d26fd43319e506c313Andreas Gustafsson entry = ISC_LIST_HEAD(adb->entries[bucket]);
014892d86d30b7eceb0003d51788f9b5cadfc1bfAndreas Gustafsson next_entry = ISC_LIST_NEXT(entry, plink);
014892d86d30b7eceb0003d51788f9b5cadfc1bfAndreas Gustafsson if (entry != NULL && entry->goodness != 0) {
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉timer_cleanup(isc_task_t *task, isc_event_t *ev) {
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 unsigned int i;
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 for (i = 0 ; i < CLEAN_BUCKETS ; i++) {
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * Call our cleanup routines.
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 cleanup_names(adb, adb->next_cleanbucket, now);
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 cleanup_entries(adb, adb->next_cleanbucket, now);
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * Set the next bucket to be cleaned.
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * Reset the timer.
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * ISC_R_NOMEMORY, but it isn't clear what could be done here
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * if either one of those things happened.
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 (void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * The timer is already dead, from the task's shutdown callback.
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 isc_mutexblock_destroy(adb->entrylocks, NBUCKETS);
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 isc_mutexblock_destroy(adb->namelocks, NBUCKETS);
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 isc_mem_put(adb->mctx, adb, sizeof (dns_adb_t));
return (ISC_R_NOMEMORY);
goto fail0a;
goto fail0b;
goto fail0c;
goto fail0d;
goto fail1;
for (i = 0 ; i < NBUCKETS ; i++) {
for (i = 0 ; i < NBUCKETS ; i++) {
goto fail2;
#define MPINIT(t, p, n) do { \
goto fail3; \
isc_mempool_setname((p), n); \
goto fail3;
goto fail3;
return (ISC_R_SUCCESS);
return (result);
int bucket;
unsigned int wanted_addresses;
unsigned int wanted_fetches;
unsigned int query_pending;
wanted_fetches = 0;
query_pending = 0;
if (now == 0)
return (ISC_R_NOMEMORY);
goto out;
goto out;
adbname);
goto post_copy;
adbname);
goto v6;
adbname);
goto post_copy;
goto v6;
v6:
adbname);
goto fetch;
adbname);
goto post_copy;
goto fetch;
if (wanted_fetches != 0 &&
adbname);
adbname);
if (alias)
if (want_event) {
if (alias) {
goto out;
out:
if (want_event) {
return (result);
int bucket;
int bucket;
int unlock_bucket;
goto cleanup;
const char *tmpp;
for (i = 0 ; i < NBUCKETS ; i++)
for (i = 0 ; i < NBUCKETS ; i++)
for (i = 0 ; i < NBUCKETS ; i++) {
for (i = 0 ; i < NBUCKETS ; i++) {
case AF_INET:
case AF_INET6:
for (i = 0 ; i < NBUCKETS ; i++)
for (i = 0 ; i < NBUCKETS ; i++)
const char *tmpp;
case AF_INET:
case AF_INET6:
if (NAME_FETCH_A(n))
if (NAME_FETCH_AAAA(n))
static isc_result_t
switch (result) {
case DNS_R_GLUE:
case DNS_R_HINT:
case ISC_R_SUCCESS:
case DNS_R_NXDOMAIN:
case DNS_R_NXRRSET:
adbname);
adbname);
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
case DNS_R_CNAME:
case DNS_R_DNAME:
adbname);
return (result);
static isc_result_t
switch (result) {
case DNS_R_GLUE:
case DNS_R_HINT:
case ISC_R_SUCCESS:
case DNS_R_NXDOMAIN:
case DNS_R_NXRRSET:
adbname);
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
case DNS_R_CNAME:
case DNS_R_DNAME:
adbname);
return (result);
int bucket;
unsigned int address_type;
(void)task;
address_type = 0;
if (want_check_exit) {
goto out;
name);
goto check_result;
goto out;
out:
int bucket;
(void)task;
if (want_check_exit) {
name);
goto out;
name);
goto out;
goto out;
name);
goto out;
goto out;
out:
static isc_result_t
if (start_at_root) {
adbname);
goto cleanup;
goto cleanup;
goto cleanup;
return (result);
static isc_result_t
goto cleanup;
goto cleanup;
return (result);
static isc_result_t
if (start_at_root) {
adbname);
goto cleanup;
goto cleanup;
goto cleanup;
return (result);
int bucket;
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
int goodness_adjustment)
int bucket;
if (goodness_adjustment == 0)
if (goodness_adjustment > 0) {
int bucket;
unsigned int new_srtt;
int bucket;
int bucket;
int bucket;
if (now == 0)
goto unlock;
goto unlock;
return (result);
int bucket;
if (want_check_exit) {