2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
23 * In finds, if task == NULL, no events will be generated, and no events
24 * have been sent. If task != NULL but taskaction == NULL, an event has been
25 * posted but not yet freed. If neither are NULL, no event was posted.
33 #include <isc/mutexblock.h>
34 #include <isc/netaddr.h>
35 #include <isc/random.h>
36 #include <isc/stats.h>
37 #include <isc/string.h> /* Required for HP/UX (and others?) */
43 #include <dns/events.h>
45 #include <dns/rdata.h>
46 #include <dns/rdataset.h>
47 #include <dns/rdatastruct.h>
48 #include <dns/rdatatype.h>
49 #include <dns/resolver.h>
50 #include <dns/result.h>
51 #include <dns/stats.h>
53 #define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
54 #define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
55 #define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
56 #define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
57 #define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
58 #define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
59 #define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
60 #define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
61 #define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
62 #define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
63 #define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
64 #define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
65 #define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
66 #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
69 * For type 3 negative cache entries, we will remember that the address is
70 * broken for this long. XXXMLG This is also used for actual addresses, too.
71 * The intent is to keep us from constantly asking about A/AAAA records
72 * if the zone has extremely low TTLs.
74 #define ADB_CACHE_MINIMUM 10 /*%< seconds */
75 #define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
76 #define ADB_ENTRY_WINDOW 1800 /*%< seconds */
79 * The period in seconds after which an ADB name entry is regarded as stale
80 * and forced to be cleaned up.
81 * TODO: This should probably be configurable at run-time.
83 #ifndef ADB_STALE_MARGIN
84 #define ADB_STALE_MARGIN 1800
87 #define FREE_ITEMS 64 /*%< free count for memory pools */
88 #define FILL_COUNT 16 /*%< fill count for memory pools */
90 #define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
92 #define DNS_ADB_MINADBSIZE (1024U*1024U) /*%< 1 Megabyte */
94 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
95 typedef struct dns_adbnamehook dns_adbnamehook_t;
96 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
97 typedef struct dns_adblameinfo dns_adblameinfo_t;
98 typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
99 typedef struct dns_adbfetch dns_adbfetch_t;
100 typedef struct dns_adbfetch6 dns_adbfetch6_t;
102 /*% dns adb structure */
107 isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
108 isc_mutex_t overmemlock; /*%< Covers overmem */
112 isc_taskmgr_t *taskmgr;
116 isc_interval_t tick_interval;
117 int next_cleanbucket;
119 unsigned int irefcnt;
120 unsigned int erefcnt;
123 isc_mempool_t *nmp; /*%< dns_adbname_t */
124 isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
125 isc_mempool_t *limp; /*%< dns_adblameinfo_t */
126 isc_mempool_t *emp; /*%< dns_adbentry_t */
127 isc_mempool_t *ahmp; /*%< dns_adbfind_t */
128 isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
129 isc_mempool_t *afmp; /*%< dns_adbfetch_t */
132 * Bucketized locks and lists for names.
134 * XXXRTH Have a per-bucket structure that contains all of these?
137 isc_mutex_t namescntlock;
138 unsigned int namescnt;
139 dns_adbnamelist_t *names;
140 dns_adbnamelist_t *deadnames;
141 isc_mutex_t *namelocks;
142 isc_boolean_t *name_sd;
143 unsigned int *name_refcnt;
146 * Bucketized locks and lists for entries.
148 * XXXRTH Have a per-bucket structure that contains all of these?
150 unsigned int nentries;
151 isc_mutex_t entriescntlock;
152 unsigned int entriescnt;
153 dns_adbentrylist_t *entries;
154 dns_adbentrylist_t *deadentries;
155 isc_mutex_t *entrylocks;
156 isc_boolean_t *entry_sd; /*%< shutting down */
157 unsigned int *entry_refcnt;
160 isc_boolean_t cevent_sent;
161 isc_boolean_t shutting_down;
162 isc_eventlist_t whenshutdown;
163 isc_event_t growentries;
164 isc_boolean_t growentries_sent;
165 isc_event_t grownames;
166 isc_boolean_t grownames_sent;
170 * XXXMLG Document these structures.
173 /*% dns_adbname structure */
178 unsigned int partial_result;
182 isc_stdtime_t expire_target;
183 isc_stdtime_t expire_v4;
184 isc_stdtime_t expire_v6;
186 dns_adbnamehooklist_t v4;
187 dns_adbnamehooklist_t v6;
188 dns_adbfetch_t *fetch_a;
189 dns_adbfetch_t *fetch_aaaa;
190 unsigned int fetch_err;
191 unsigned int fetch6_err;
192 dns_adbfindlist_t finds;
193 /* for LRU-based management */
194 isc_stdtime_t last_used;
196 ISC_LINK(dns_adbname_t) plink;
199 /*% The adbfetch structure */
200 struct dns_adbfetch {
203 dns_rdataset_t rdataset;
208 * This is a small widget that dangles off a dns_adbname_t. It contains a
209 * pointer to the address information about this host, and a link to the next
210 * namehook that will contain the next address this host has.
212 struct dns_adbnamehook {
214 dns_adbentry_t *entry;
215 ISC_LINK(dns_adbnamehook_t) plink;
219 * This is a small widget that holds qname-specific information about an
220 * address. Currently limited to lameness, but could just as easily be
221 * extended to other types of information about zones.
223 struct dns_adblameinfo {
227 dns_rdatatype_t qtype;
228 isc_stdtime_t lame_timer;
230 ISC_LINK(dns_adblameinfo_t) plink;
234 * An address entry. It holds quite a bit of information about addresses,
235 * including edns state (in "flags"), rtt, and of course the address of
238 struct dns_adbentry {
246 isc_sockaddr_t sockaddr;
248 isc_stdtime_t expires;
250 * A nonzero 'expires' field indicates that the entry should
251 * persist until that time. This allows entries found
252 * using dns_adb_findaddrinfo() to persist for a limited time
253 * even though they are not necessarily associated with a
257 ISC_LIST(dns_adblameinfo_t) lameinfo;
258 ISC_LINK(dns_adbentry_t) plink;
263 * Internal functions (and prototypes).
265 static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
266 static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
267 static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
269 static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
270 static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
272 static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
273 static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
274 static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
275 static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
276 static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
277 static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
279 static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
280 static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
281 static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
282 unsigned int, int *);
283 static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
284 isc_sockaddr_t *, int *,
286 static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
287 static void print_dns_name(FILE *, dns_name_t *);
288 static void print_namehook_list(FILE *, const char *legend,
289 dns_adbnamehooklist_t *list,
292 static void print_find_list(FILE *, dns_adbname_t *);
293 static void print_fetch_list(FILE *, dns_adbname_t *);
294 static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
295 static inline void inc_adb_irefcnt(dns_adb_t *);
296 static inline void inc_adb_erefcnt(dns_adb_t *);
297 static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
299 static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
300 dns_adbentry_t *, isc_boolean_t);
301 static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
302 static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
303 static void clean_target(dns_adb_t *, dns_name_t *);
304 static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
305 static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
306 static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
308 static void cancel_fetches_at_name(dns_adbname_t *);
309 static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
311 static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
312 unsigned int, isc_counter_t *qc,
314 static inline void check_exit(dns_adb_t *);
315 static void destroy(dns_adb_t *);
316 static isc_boolean_t shutdown_names(dns_adb_t *);
317 static isc_boolean_t shutdown_entries(dns_adb_t *);
318 static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
319 static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
320 static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
321 static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
322 static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
323 static void water(void *, int);
324 static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
327 * MUST NOT overlap DNS_ADBFIND_* flags!
329 #define FIND_EVENT_SENT 0x40000000
330 #define FIND_EVENT_FREED 0x80000000
331 #define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
332 #define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
334 #define NAME_NEEDS_POKE 0x80000000
335 #define NAME_IS_DEAD 0x40000000
336 #define NAME_HINT_OK DNS_ADBFIND_HINTOK
337 #define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
338 #define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
339 #define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
340 #define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
341 #define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
342 #define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
345 * Private flag(s) for entries.
346 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
348 #define ENTRY_IS_DEAD 0x80000000
351 * To the name, address classes are all that really exist. If it has a
352 * V6 address it doesn't care if it came from a AAAA query.
354 #define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
355 #define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
356 #define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
359 * Fetches are broken out into A and AAAA types. In some cases,
360 * however, it makes more sense to test for a particular class of fetches,
361 * like V4 or V6 above.
362 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
363 * are now equal to FETCH_V4 and FETCH_V6, respectively.
365 #define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
366 #define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
367 #define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
368 #define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
369 #define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
372 * Find options and tests to see if there are addresses on the list.
374 #define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
375 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
376 #define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
378 #define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
380 #define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
381 #define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
382 #define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
383 #define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
386 * These are currently used on simple unsigned ints, so they are
387 * not really associated with any particular type.
389 #define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
390 #define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
392 #define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
395 * Find out if the flags on a name (nf) indicate if it is a hint or
396 * glue, and compare this to the appropriate bits set in o, to see if
399 #define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
400 #define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
401 #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
402 #define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
403 ((o) & DNS_ADBFIND_STARTATZONE))
405 #define ENTER_LEVEL ISC_LOG_DEBUG(50)
406 #define EXIT_LEVEL ENTER_LEVEL
407 #define CLEAN_LEVEL ISC_LOG_DEBUG(100)
408 #define DEF_LEVEL ISC_LOG_DEBUG(5)
409 #define NCACHE_LEVEL ISC_LOG_DEBUG(20)
411 #define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
412 (r) == DNS_R_NCACHENXRRSET)
413 #define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
414 (r) == DNS_R_NXRRSET)
415 #define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
416 (r) == DNS_R_NCACHENXDOMAIN)
417 #define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
418 (r) == DNS_R_NXRRSET || \
419 (r) == DNS_R_HINTNXRRSET)
422 * Error state rankings.
425 #define FIND_ERR_SUCCESS 0 /* highest rank */
426 #define FIND_ERR_CANCELED 1
427 #define FIND_ERR_FAILURE 2
428 #define FIND_ERR_NXDOMAIN 3
429 #define FIND_ERR_NXRRSET 4
430 #define FIND_ERR_UNEXPECTED 5
431 #define FIND_ERR_NOTFOUND 6
432 #define FIND_ERR_MAX 7
434 static const char *errnames[] = {
444 #define NEWERR(old, new) (ISC_MIN((old), (new)))
446 static isc_result_t find_err_map[FIND_ERR_MAX] = {
453 ISC_R_NOTFOUND /* not YET found */
457 DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
460 DP(int level, const char *format, ...) {
463 va_start(args, format);
464 isc_log_vwrite(dns_lctx,
465 DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
466 level, format, args);
471 * Increment resolver-related statistics counters.
474 inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
475 if (adb->view->resstats != NULL)
476 isc_stats_increment(adb->view->resstats, counter);
479 static inline dns_ttl_t
480 ttlclamp(dns_ttl_t ttl) {
481 if (ttl < ADB_CACHE_MINIMUM)
482 ttl = ADB_CACHE_MINIMUM;
483 if (ttl > ADB_CACHE_MAXIMUM)
484 ttl = ADB_CACHE_MAXIMUM;
490 * Hashing is most efficient if the number of buckets is prime.
491 * The sequence below is the closest previous primes to 2^n and
492 * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
493 * no longer grow beyond 2^28 entries.)
495 static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
496 8191, 12281, 16381, 24571, 32749,
497 49193, 65521, 98299, 131071, 199603,
498 262139, 393209, 524287, 768431, 1048573,
499 1572853, 2097143, 3145721, 4194301,
500 6291449, 8388593, 12582893, 16777213,
501 25165813, 33554393, 50331599, 67108859,
502 100663291, 134217689, 201326557,
506 grow_entries(isc_task_t *task, isc_event_t *ev) {
509 dns_adbentrylist_t *newdeadentries = NULL;
510 dns_adbentrylist_t *newentries = NULL;
511 isc_boolean_t *newentry_sd = NULL;
512 isc_mutex_t *newentrylocks = NULL;
514 unsigned int *newentry_refcnt = NULL;
515 unsigned int i, n, bucket;
518 INSIST(DNS_ADB_VALID(adb));
522 result = isc_task_beginexclusive(task);
523 if (result != ISC_R_SUCCESS)
527 while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
529 if (nbuckets[i] != 0)
534 DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
537 * Are we shutting down?
539 for (i = 0; i < adb->nentries; i++)
540 if (adb->entry_sd[i])
544 * Grab all the resources we need.
546 newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
547 newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
548 newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
549 newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
550 newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
551 if (newentries == NULL || newdeadentries == NULL ||
552 newentrylocks == NULL || newentry_sd == NULL ||
553 newentry_refcnt == NULL)
557 * Initialise the new resources.
559 result = isc_mutexblock_init(newentrylocks, n);
560 if (result != ISC_R_SUCCESS)
563 for (i = 0; i < n; i++) {
564 ISC_LIST_INIT(newentries[i]);
565 ISC_LIST_INIT(newdeadentries[i]);
566 newentry_sd[i] = ISC_FALSE;
567 newentry_refcnt[i] = 0;
572 * Move entries to new arrays.
574 for (i = 0; i < adb->nentries; i++) {
575 e = ISC_LIST_HEAD(adb->entries[i]);
577 ISC_LIST_UNLINK(adb->entries[i], e, plink);
578 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
579 e->lock_bucket = bucket;
580 ISC_LIST_APPEND(newentries[bucket], e, plink);
581 INSIST(adb->entry_refcnt[i] > 0);
582 adb->entry_refcnt[i]--;
583 newentry_refcnt[bucket]++;
584 e = ISC_LIST_HEAD(adb->entries[i]);
586 e = ISC_LIST_HEAD(adb->deadentries[i]);
588 ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
589 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
590 e->lock_bucket = bucket;
591 ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
592 INSIST(adb->entry_refcnt[i] > 0);
593 adb->entry_refcnt[i]--;
594 newentry_refcnt[bucket]++;
595 e = ISC_LIST_HEAD(adb->deadentries[i]);
597 INSIST(adb->entry_refcnt[i] == 0);
602 * Cleanup old resources.
604 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
605 isc_mem_put(adb->mctx, adb->entries,
606 sizeof(*adb->entries) * adb->nentries);
607 isc_mem_put(adb->mctx, adb->deadentries,
608 sizeof(*adb->deadentries) * adb->nentries);
609 isc_mem_put(adb->mctx, adb->entrylocks,
610 sizeof(*adb->entrylocks) * adb->nentries);
611 isc_mem_put(adb->mctx, adb->entry_sd,
612 sizeof(*adb->entry_sd) * adb->nentries);
613 isc_mem_put(adb->mctx, adb->entry_refcnt,
614 sizeof(*adb->entry_refcnt) * adb->nentries);
617 * Install new resources.
619 adb->entries = newentries;
620 adb->deadentries = newdeadentries;
621 adb->entrylocks = newentrylocks;
622 adb->entry_sd = newentry_sd;
623 adb->entry_refcnt = newentry_refcnt;
627 * Only on success do we set adb->growentries_sent to ISC_FALSE.
628 * This will prevent us being continuously being called on error.
630 adb->growentries_sent = ISC_FALSE;
634 if (newentries != NULL)
635 isc_mem_put(adb->mctx, newentries,
636 sizeof(*newentries) * n);
637 if (newdeadentries != NULL)
638 isc_mem_put(adb->mctx, newdeadentries,
639 sizeof(*newdeadentries) * n);
640 if (newentrylocks != NULL)
641 isc_mem_put(adb->mctx, newentrylocks,
642 sizeof(*newentrylocks) * n);
643 if (newentry_sd != NULL)
644 isc_mem_put(adb->mctx, newentry_sd,
645 sizeof(*newentry_sd) * n);
646 if (newentry_refcnt != NULL)
647 isc_mem_put(adb->mctx, newentry_refcnt,
648 sizeof(*newentry_refcnt) * n);
650 isc_task_endexclusive(task);
654 if (dec_adb_irefcnt(adb))
657 DP(ISC_LOG_INFO, "adb: grow_entries finished");
661 grow_names(isc_task_t *task, isc_event_t *ev) {
664 dns_adbnamelist_t *newdeadnames = NULL;
665 dns_adbnamelist_t *newnames = NULL;
666 isc_boolean_t *newname_sd = NULL;
667 isc_mutex_t *newnamelocks = NULL;
669 unsigned int *newname_refcnt = NULL;
670 unsigned int i, n, bucket;
673 INSIST(DNS_ADB_VALID(adb));
677 result = isc_task_beginexclusive(task);
678 if (result != ISC_R_SUCCESS)
682 while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
684 if (nbuckets[i] != 0)
689 DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
692 * Are we shutting down?
694 for (i = 0; i < adb->nnames; i++)
699 * Grab all the resources we need.
701 newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
702 newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
703 newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
704 newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
705 newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
706 if (newnames == NULL || newdeadnames == NULL ||
707 newnamelocks == NULL || newname_sd == NULL ||
708 newname_refcnt == NULL)
712 * Initialise the new resources.
714 result = isc_mutexblock_init(newnamelocks, n);
715 if (result != ISC_R_SUCCESS)
718 for (i = 0; i < n; i++) {
719 ISC_LIST_INIT(newnames[i]);
720 ISC_LIST_INIT(newdeadnames[i]);
721 newname_sd[i] = ISC_FALSE;
722 newname_refcnt[i] = 0;
727 * Move names to new arrays.
729 for (i = 0; i < adb->nnames; i++) {
730 name = ISC_LIST_HEAD(adb->names[i]);
731 while (name != NULL) {
732 ISC_LIST_UNLINK(adb->names[i], name, plink);
733 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
734 name->lock_bucket = bucket;
735 ISC_LIST_APPEND(newnames[bucket], name, plink);
736 INSIST(adb->name_refcnt[i] > 0);
737 adb->name_refcnt[i]--;
738 newname_refcnt[bucket]++;
739 name = ISC_LIST_HEAD(adb->names[i]);
741 name = ISC_LIST_HEAD(adb->deadnames[i]);
742 while (name != NULL) {
743 ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
744 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
745 name->lock_bucket = bucket;
746 ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
747 INSIST(adb->name_refcnt[i] > 0);
748 adb->name_refcnt[i]--;
749 newname_refcnt[bucket]++;
750 name = ISC_LIST_HEAD(adb->deadnames[i]);
752 INSIST(adb->name_refcnt[i] == 0);
757 * Cleanup old resources.
759 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
760 isc_mem_put(adb->mctx, adb->names,
761 sizeof(*adb->names) * adb->nnames);
762 isc_mem_put(adb->mctx, adb->deadnames,
763 sizeof(*adb->deadnames) * adb->nnames);
764 isc_mem_put(adb->mctx, adb->namelocks,
765 sizeof(*adb->namelocks) * adb->nnames);
766 isc_mem_put(adb->mctx, adb->name_sd,
767 sizeof(*adb->name_sd) * adb->nnames);
768 isc_mem_put(adb->mctx, adb->name_refcnt,
769 sizeof(*adb->name_refcnt) * adb->nnames);
772 * Install new resources.
774 adb->names = newnames;
775 adb->deadnames = newdeadnames;
776 adb->namelocks = newnamelocks;
777 adb->name_sd = newname_sd;
778 adb->name_refcnt = newname_refcnt;
782 * Only on success do we set adb->grownames_sent to ISC_FALSE.
783 * This will prevent us being continuously being called on error.
785 adb->grownames_sent = ISC_FALSE;
789 if (newnames != NULL)
790 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
791 if (newdeadnames != NULL)
792 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
793 if (newnamelocks != NULL)
794 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
795 if (newname_sd != NULL)
796 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
797 if (newname_refcnt != NULL)
798 isc_mem_put(adb->mctx, newname_refcnt,
799 sizeof(*newname_refcnt) * n);
801 isc_task_endexclusive(task);
805 if (dec_adb_irefcnt(adb))
808 DP(ISC_LOG_INFO, "adb: grow_names finished");
812 * Requires the adbname bucket be locked and that no entry buckets be locked.
814 * This code handles A and AAAA rdatasets only.
817 import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
822 dns_adbnamehook_t *nh;
823 dns_adbnamehook_t *anh;
824 dns_rdata_t rdata = DNS_RDATA_INIT;
826 struct in6_addr in6a;
827 isc_sockaddr_t sockaddr;
828 dns_adbentry_t *foundentry; /* NO CLEAN UP! */
830 isc_boolean_t new_addresses_added;
831 dns_rdatatype_t rdtype;
832 unsigned int findoptions;
833 dns_adbnamehooklist_t *hookhead;
835 INSIST(DNS_ADBNAME_VALID(adbname));
837 INSIST(DNS_ADB_VALID(adb));
839 rdtype = rdataset->type;
840 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
841 if (rdtype == dns_rdatatype_a)
842 findoptions = DNS_ADBFIND_INET;
844 findoptions = DNS_ADBFIND_INET6;
846 addr_bucket = DNS_ADB_INVALIDBUCKET;
847 new_addresses_added = ISC_FALSE;
850 result = dns_rdataset_first(rdataset);
851 while (result == ISC_R_SUCCESS) {
852 dns_rdata_reset(&rdata);
853 dns_rdataset_current(rdataset, &rdata);
854 if (rdtype == dns_rdatatype_a) {
855 INSIST(rdata.length == 4);
856 memmove(&ina.s_addr, rdata.data, 4);
857 isc_sockaddr_fromin(&sockaddr, &ina, 0);
858 hookhead = &adbname->v4;
860 INSIST(rdata.length == 16);
861 memmove(in6a.s6_addr, rdata.data, 16);
862 isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
863 hookhead = &adbname->v6;
867 nh = new_adbnamehook(adb, NULL);
869 adbname->partial_result |= findoptions;
870 result = ISC_R_NOMEMORY;
874 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
876 if (foundentry == NULL) {
877 dns_adbentry_t *entry;
879 entry = new_adbentry(adb);
881 adbname->partial_result |= findoptions;
882 result = ISC_R_NOMEMORY;
886 entry->sockaddr = sockaddr;
891 link_entry(adb, addr_bucket, entry);
893 for (anh = ISC_LIST_HEAD(*hookhead);
895 anh = ISC_LIST_NEXT(anh, plink))
896 if (anh->entry == foundentry)
899 foundentry->refcnt++;
900 nh->entry = foundentry;
902 free_adbnamehook(adb, &nh);
905 new_addresses_added = ISC_TRUE;
907 ISC_LIST_APPEND(*hookhead, nh, plink);
909 result = dns_rdataset_next(rdataset);
914 free_adbnamehook(adb, &nh);
916 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
917 UNLOCK(&adb->entrylocks[addr_bucket]);
919 if (rdataset->trust == dns_trust_glue ||
920 rdataset->trust == dns_trust_additional)
921 rdataset->ttl = ADB_CACHE_MINIMUM;
922 else if (rdataset->trust == dns_trust_ultimate)
925 rdataset->ttl = ttlclamp(rdataset->ttl);
927 if (rdtype == dns_rdatatype_a) {
928 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
929 adbname->expire_v4, now + rdataset->ttl);
930 adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
931 now + rdataset->ttl);
933 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
934 adbname->expire_v6, now + rdataset->ttl);
935 adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
936 now + rdataset->ttl);
939 if (new_addresses_added) {
941 * Lie a little here. This is more or less so code that cares
942 * can find out if any new information was added or not.
944 return (ISC_R_SUCCESS);
951 * Requires the name's bucket be locked.
954 kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
956 isc_boolean_t result = ISC_FALSE;
957 isc_boolean_t result4, result6;
964 INSIST(DNS_ADBNAME_VALID(name));
966 INSIST(DNS_ADB_VALID(adb));
968 DP(DEF_LEVEL, "killing name %p", name);
971 * If we're dead already, just check to see if we should go
974 if (NAME_DEAD(name) && !NAME_FETCH(name)) {
975 result = unlink_name(adb, name);
976 free_adbname(adb, &name);
978 result = dec_adb_irefcnt(adb);
983 * Clean up the name's various lists. These two are destructive
984 * in that they will always empty the list.
986 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
987 result4 = clean_namehooks(adb, &name->v4);
988 result6 = clean_namehooks(adb, &name->v6);
989 clean_target(adb, &name->target);
990 result = ISC_TF(result4 || result6);
993 * If fetches are running, cancel them. If none are running, we can
994 * just kill the name here.
996 if (!NAME_FETCH(name)) {
997 INSIST(result == ISC_FALSE);
998 result = unlink_name(adb, name);
999 free_adbname(adb, &name);
1001 result = dec_adb_irefcnt(adb);
1003 cancel_fetches_at_name(name);
1004 if (!NAME_DEAD(name)) {
1005 bucket = name->lock_bucket;
1006 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1007 ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
1008 name->flags |= NAME_IS_DEAD;
1015 * Requires the name's bucket be locked and no entry buckets be locked.
1017 static isc_boolean_t
1018 check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
1020 isc_boolean_t result4 = ISC_FALSE;
1021 isc_boolean_t result6 = ISC_FALSE;
1023 INSIST(DNS_ADBNAME_VALID(name));
1025 INSIST(DNS_ADB_VALID(adb));
1028 * Check to see if we need to remove the v4 addresses
1030 if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
1031 if (NAME_HAS_V4(name)) {
1032 DP(DEF_LEVEL, "expiring v4 for name %p", name);
1033 result4 = clean_namehooks(adb, &name->v4);
1034 name->partial_result &= ~DNS_ADBFIND_INET;
1036 name->expire_v4 = INT_MAX;
1037 name->fetch_err = FIND_ERR_UNEXPECTED;
1041 * Check to see if we need to remove the v6 addresses
1043 if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
1044 if (NAME_HAS_V6(name)) {
1045 DP(DEF_LEVEL, "expiring v6 for name %p", name);
1046 result6 = clean_namehooks(adb, &name->v6);
1047 name->partial_result &= ~DNS_ADBFIND_INET6;
1049 name->expire_v6 = INT_MAX;
1050 name->fetch6_err = FIND_ERR_UNEXPECTED;
1054 * Check to see if we need to remove the alias target.
1056 if (EXPIRE_OK(name->expire_target, now)) {
1057 clean_target(adb, &name->target);
1058 name->expire_target = INT_MAX;
1060 return (ISC_TF(result4 || result6));
1064 * Requires the name's bucket be locked.
1067 link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1068 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
1070 ISC_LIST_PREPEND(adb->names[bucket], name, plink);
1071 name->lock_bucket = bucket;
1072 adb->name_refcnt[bucket]++;
1076 * Requires the name's bucket be locked.
1078 static inline isc_boolean_t
1079 unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
1081 isc_boolean_t result = ISC_FALSE;
1083 bucket = name->lock_bucket;
1084 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1086 if (NAME_DEAD(name))
1087 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
1089 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1090 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1091 INSIST(adb->name_refcnt[bucket] > 0);
1092 adb->name_refcnt[bucket]--;
1093 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
1099 * Requires the entry's bucket be locked.
1102 link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
1106 if (isc_mem_isovermem(adb->mctx)) {
1107 for (i = 0; i < 2; i++) {
1108 e = ISC_LIST_TAIL(adb->entries[bucket]);
1111 if (e->refcnt == 0) {
1112 unlink_entry(adb, e);
1113 free_adbentry(adb, &e);
1116 INSIST((e->flags & ENTRY_IS_DEAD) == 0);
1117 e->flags |= ENTRY_IS_DEAD;
1118 ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
1119 ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
1123 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
1124 entry->lock_bucket = bucket;
1125 adb->entry_refcnt[bucket]++;
1129 * Requires the entry's bucket be locked.
1131 static inline isc_boolean_t
1132 unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
1134 isc_boolean_t result = ISC_FALSE;
1136 bucket = entry->lock_bucket;
1137 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1139 if ((entry->flags & ENTRY_IS_DEAD) != 0)
1140 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
1142 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
1143 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1144 INSIST(adb->entry_refcnt[bucket] > 0);
1145 adb->entry_refcnt[bucket]--;
1146 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
1152 violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
1153 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
1161 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1162 * checked after calling this function.
1164 static isc_boolean_t
1165 shutdown_names(dns_adb_t *adb) {
1166 unsigned int bucket;
1167 isc_boolean_t result = ISC_FALSE;
1168 dns_adbname_t *name;
1169 dns_adbname_t *next_name;
1171 for (bucket = 0; bucket < adb->nnames; bucket++) {
1172 LOCK(&adb->namelocks[bucket]);
1173 adb->name_sd[bucket] = ISC_TRUE;
1175 name = ISC_LIST_HEAD(adb->names[bucket]);
1178 * This bucket has no names. We must decrement the
1179 * irefcnt ourselves, since it will not be
1180 * automatically triggered by a name being unlinked.
1182 INSIST(result == ISC_FALSE);
1183 result = dec_adb_irefcnt(adb);
1186 * Run through the list. For each name, clean up finds
1187 * found there, and cancel any fetches running. When
1188 * all the fetches are canceled, the name will destroy
1191 while (name != NULL) {
1192 next_name = ISC_LIST_NEXT(name, plink);
1193 INSIST(result == ISC_FALSE);
1194 result = kill_name(&name,
1195 DNS_EVENT_ADBSHUTDOWN);
1200 UNLOCK(&adb->namelocks[bucket]);
1206 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1207 * checked after calling this function.
1209 static isc_boolean_t
1210 shutdown_entries(dns_adb_t *adb) {
1211 unsigned int bucket;
1212 isc_boolean_t result = ISC_FALSE;
1213 dns_adbentry_t *entry;
1214 dns_adbentry_t *next_entry;
1216 for (bucket = 0; bucket < adb->nentries; bucket++) {
1217 LOCK(&adb->entrylocks[bucket]);
1218 adb->entry_sd[bucket] = ISC_TRUE;
1220 entry = ISC_LIST_HEAD(adb->entries[bucket]);
1221 if (adb->entry_refcnt[bucket] == 0) {
1223 * This bucket has no entries. We must decrement the
1224 * irefcnt ourselves, since it will not be
1225 * automatically triggered by an entry being unlinked.
1227 result = dec_adb_irefcnt(adb);
1230 * Run through the list. Cleanup any entries not
1231 * associated with names, and which are not in use.
1233 while (entry != NULL) {
1234 next_entry = ISC_LIST_NEXT(entry, plink);
1235 if (entry->refcnt == 0 &&
1236 entry->expires != 0) {
1237 result = unlink_entry(adb, entry);
1238 free_adbentry(adb, &entry);
1240 result = dec_adb_irefcnt(adb);
1246 UNLOCK(&adb->entrylocks[bucket]);
1252 * Name bucket must be locked
1255 cancel_fetches_at_name(dns_adbname_t *name) {
1256 if (NAME_FETCH_A(name))
1257 dns_resolver_cancelfetch(name->fetch_a->fetch);
1259 if (NAME_FETCH_AAAA(name))
1260 dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
1264 * Assumes the name bucket is locked.
1266 static isc_boolean_t
1267 clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
1268 dns_adbentry_t *entry;
1269 dns_adbnamehook_t *namehook;
1271 isc_boolean_t result = ISC_FALSE;
1272 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
1274 addr_bucket = DNS_ADB_INVALIDBUCKET;
1275 namehook = ISC_LIST_HEAD(*namehooks);
1276 while (namehook != NULL) {
1277 INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
1280 * Clean up the entry if needed.
1282 entry = namehook->entry;
1283 if (entry != NULL) {
1284 INSIST(DNS_ADBENTRY_VALID(entry));
1286 if (addr_bucket != entry->lock_bucket) {
1287 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1288 UNLOCK(&adb->entrylocks[addr_bucket]);
1289 addr_bucket = entry->lock_bucket;
1290 INSIST(addr_bucket != DNS_ADB_INVALIDBUCKET);
1291 LOCK(&adb->entrylocks[addr_bucket]);
1294 result = dec_entry_refcnt(adb, overmem, entry,
1301 namehook->entry = NULL;
1302 ISC_LIST_UNLINK(*namehooks, namehook, plink);
1303 free_adbnamehook(adb, &namehook);
1305 namehook = ISC_LIST_HEAD(*namehooks);
1308 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1309 UNLOCK(&adb->entrylocks[addr_bucket]);
1314 clean_target(dns_adb_t *adb, dns_name_t *target) {
1315 if (dns_name_countlabels(target) > 0) {
1316 dns_name_free(target, adb->mctx);
1317 dns_name_init(target, NULL);
1322 set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
1323 dns_rdataset_t *rdataset, dns_name_t *target)
1325 isc_result_t result;
1326 dns_namereln_t namereln;
1327 unsigned int nlabels;
1329 dns_rdata_t rdata = DNS_RDATA_INIT;
1330 dns_fixedname_t fixed1, fixed2;
1331 dns_name_t *prefix, *new_target;
1333 REQUIRE(dns_name_countlabels(target) == 0);
1335 if (rdataset->type == dns_rdatatype_cname) {
1336 dns_rdata_cname_t cname;
1339 * Copy the CNAME's target into the target name.
1341 result = dns_rdataset_first(rdataset);
1342 if (result != ISC_R_SUCCESS)
1344 dns_rdataset_current(rdataset, &rdata);
1345 result = dns_rdata_tostruct(&rdata, &cname, NULL);
1346 if (result != ISC_R_SUCCESS)
1348 result = dns_name_dup(&cname.cname, adb->mctx, target);
1349 dns_rdata_freestruct(&cname);
1350 if (result != ISC_R_SUCCESS)
1353 dns_rdata_dname_t dname;
1355 INSIST(rdataset->type == dns_rdatatype_dname);
1356 namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
1357 INSIST(namereln == dns_namereln_subdomain);
1359 * Get the target name of the DNAME.
1361 result = dns_rdataset_first(rdataset);
1362 if (result != ISC_R_SUCCESS)
1364 dns_rdataset_current(rdataset, &rdata);
1365 result = dns_rdata_tostruct(&rdata, &dname, NULL);
1366 if (result != ISC_R_SUCCESS)
1369 * Construct the new target name.
1371 dns_fixedname_init(&fixed1);
1372 prefix = dns_fixedname_name(&fixed1);
1373 dns_fixedname_init(&fixed2);
1374 new_target = dns_fixedname_name(&fixed2);
1375 dns_name_split(name, nlabels, prefix, NULL);
1376 result = dns_name_concatenate(prefix, &dname.dname, new_target,
1378 dns_rdata_freestruct(&dname);
1379 if (result != ISC_R_SUCCESS)
1381 result = dns_name_dup(new_target, adb->mctx, target);
1382 if (result != ISC_R_SUCCESS)
1386 return (ISC_R_SUCCESS);
1390 * Assumes nothing is locked, since this is called by the client.
1393 event_free(isc_event_t *event) {
1394 dns_adbfind_t *find;
1396 INSIST(event != NULL);
1397 find = event->ev_destroy_arg;
1398 INSIST(DNS_ADBFIND_VALID(find));
1401 find->flags |= FIND_EVENT_FREED;
1402 event->ev_destroy_arg = NULL;
1403 UNLOCK(&find->lock);
1407 * Assumes the name bucket is locked.
1410 clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
1415 dns_adbfind_t *find;
1416 dns_adbfind_t *next_find;
1417 isc_boolean_t process;
1418 unsigned int wanted, notify;
1421 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1422 name, evtype, addrs);
1424 find = ISC_LIST_HEAD(name->finds);
1425 while (find != NULL) {
1427 next_find = ISC_LIST_NEXT(find, plink);
1429 process = ISC_FALSE;
1430 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1431 notify = wanted & addrs;
1434 case DNS_EVENT_ADBMOREADDRESSES:
1435 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1436 if ((notify) != 0) {
1437 find->flags &= ~addrs;
1441 case DNS_EVENT_ADBNOMOREADDRESSES:
1442 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1443 find->flags &= ~addrs;
1444 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1449 find->flags &= ~addrs;
1454 DP(DEF_LEVEL, "cfan: processing find %p", find);
1456 * Unlink the find from the name, letting the caller
1457 * call dns_adb_destroyfind() on it to clean it up
1460 ISC_LIST_UNLINK(name->finds, find, plink);
1461 find->adbname = NULL;
1462 find->name_bucket = DNS_ADB_INVALIDBUCKET;
1464 INSIST(!FIND_EVENTSENT(find));
1467 task = ev->ev_sender;
1468 ev->ev_sender = find;
1469 find->result_v4 = find_err_map[name->fetch_err];
1470 find->result_v6 = find_err_map[name->fetch6_err];
1471 ev->ev_type = evtype;
1472 ev->ev_destroy = event_free;
1473 ev->ev_destroy_arg = find;
1476 "sending event %p to task %p for find %p",
1479 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
1481 DP(DEF_LEVEL, "cfan: skipping find %p", find);
1484 UNLOCK(&find->lock);
1488 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
1492 check_exit(dns_adb_t *adb) {
1495 * The caller must be holding the adb lock.
1497 if (adb->shutting_down) {
1499 * If there aren't any external references either, we're
1500 * done. Send the control event to initiate shutdown.
1502 INSIST(!adb->cevent_sent); /* Sanity check. */
1503 event = &adb->cevent;
1504 isc_task_send(adb->task, &event);
1505 adb->cevent_sent = ISC_TRUE;
1509 static inline isc_boolean_t
1510 dec_adb_irefcnt(dns_adb_t *adb) {
1513 isc_boolean_t result = ISC_FALSE;
1515 LOCK(&adb->reflock);
1517 INSIST(adb->irefcnt > 0);
1520 if (adb->irefcnt == 0) {
1521 event = ISC_LIST_HEAD(adb->whenshutdown);
1522 while (event != NULL) {
1523 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
1524 etask = event->ev_sender;
1525 event->ev_sender = adb;
1526 isc_task_sendanddetach(&etask, &event);
1527 event = ISC_LIST_HEAD(adb->whenshutdown);
1531 if (adb->irefcnt == 0 && adb->erefcnt == 0)
1533 UNLOCK(&adb->reflock);
1538 inc_adb_irefcnt(dns_adb_t *adb) {
1539 LOCK(&adb->reflock);
1541 UNLOCK(&adb->reflock);
1545 inc_adb_erefcnt(dns_adb_t *adb) {
1546 LOCK(&adb->reflock);
1548 UNLOCK(&adb->reflock);
1552 inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
1555 bucket = entry->lock_bucket;
1558 LOCK(&adb->entrylocks[bucket]);
1563 UNLOCK(&adb->entrylocks[bucket]);
1566 static inline isc_boolean_t
1567 dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
1571 isc_boolean_t destroy_entry;
1572 isc_boolean_t result = ISC_FALSE;
1574 bucket = entry->lock_bucket;
1577 LOCK(&adb->entrylocks[bucket]);
1579 INSIST(entry->refcnt > 0);
1582 destroy_entry = ISC_FALSE;
1583 if (entry->refcnt == 0 &&
1584 (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
1585 (entry->flags & ENTRY_IS_DEAD) != 0)) {
1586 destroy_entry = ISC_TRUE;
1587 result = unlink_entry(adb, entry);
1591 UNLOCK(&adb->entrylocks[bucket]);
1596 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1598 free_adbentry(adb, &entry);
1600 result = dec_adb_irefcnt(adb);
1605 static inline dns_adbname_t *
1606 new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
1607 dns_adbname_t *name;
1609 name = isc_mempool_get(adb->nmp);
1613 dns_name_init(&name->name, NULL);
1614 if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
1615 isc_mempool_put(adb->nmp, name);
1618 dns_name_init(&name->target, NULL);
1619 name->magic = DNS_ADBNAME_MAGIC;
1621 name->partial_result = 0;
1623 name->expire_v4 = INT_MAX;
1624 name->expire_v6 = INT_MAX;
1625 name->expire_target = INT_MAX;
1627 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1628 ISC_LIST_INIT(name->v4);
1629 ISC_LIST_INIT(name->v6);
1630 name->fetch_a = NULL;
1631 name->fetch_aaaa = NULL;
1632 name->fetch_err = FIND_ERR_UNEXPECTED;
1633 name->fetch6_err = FIND_ERR_UNEXPECTED;
1634 ISC_LIST_INIT(name->finds);
1635 ISC_LINK_INIT(name, plink);
1637 LOCK(&adb->namescntlock);
1639 if (!adb->grownames_sent && adb->excl != NULL &&
1640 adb->namescnt > (adb->nnames * 8))
1642 isc_event_t *event = &adb->grownames;
1643 inc_adb_irefcnt(adb);
1644 isc_task_send(adb->excl, &event);
1645 adb->grownames_sent = ISC_TRUE;
1647 UNLOCK(&adb->namescntlock);
1653 free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
1656 INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
1660 INSIST(!NAME_HAS_V4(n));
1661 INSIST(!NAME_HAS_V6(n));
1662 INSIST(!NAME_FETCH(n));
1663 INSIST(ISC_LIST_EMPTY(n->finds));
1664 INSIST(!ISC_LINK_LINKED(n, plink));
1665 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
1666 INSIST(n->adb == adb);
1669 dns_name_free(&n->name, adb->mctx);
1671 isc_mempool_put(adb->nmp, n);
1672 LOCK(&adb->namescntlock);
1674 UNLOCK(&adb->namescntlock);
1677 static inline dns_adbnamehook_t *
1678 new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
1679 dns_adbnamehook_t *nh;
1681 nh = isc_mempool_get(adb->nhmp);
1685 nh->magic = DNS_ADBNAMEHOOK_MAGIC;
1687 ISC_LINK_INIT(nh, plink);
1693 free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
1694 dns_adbnamehook_t *nh;
1696 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
1700 INSIST(nh->entry == NULL);
1701 INSIST(!ISC_LINK_LINKED(nh, plink));
1704 isc_mempool_put(adb->nhmp, nh);
1707 static inline dns_adblameinfo_t *
1708 new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
1709 dns_adblameinfo_t *li;
1711 li = isc_mempool_get(adb->limp);
1715 dns_name_init(&li->qname, NULL);
1716 if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
1717 isc_mempool_put(adb->limp, li);
1720 li->magic = DNS_ADBLAMEINFO_MAGIC;
1723 ISC_LINK_INIT(li, plink);
1729 free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
1730 dns_adblameinfo_t *li;
1732 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
1736 INSIST(!ISC_LINK_LINKED(li, plink));
1738 dns_name_free(&li->qname, adb->mctx);
1742 isc_mempool_put(adb->limp, li);
1745 static inline dns_adbentry_t *
1746 new_adbentry(dns_adb_t *adb) {
1750 e = isc_mempool_get(adb->emp);
1754 e->magic = DNS_ADBENTRY_MAGIC;
1755 e->lock_bucket = DNS_ADB_INVALIDBUCKET;
1759 e->srtt = (r & 0x1f) + 1;
1761 ISC_LIST_INIT(e->lameinfo);
1762 ISC_LINK_INIT(e, plink);
1763 LOCK(&adb->entriescntlock);
1765 if (!adb->growentries_sent && adb->growentries_sent &&
1766 adb->entriescnt > (adb->nentries * 8))
1768 isc_event_t *event = &adb->growentries;
1769 inc_adb_irefcnt(adb);
1770 isc_task_send(adb->task, &event);
1771 adb->growentries_sent = ISC_TRUE;
1773 UNLOCK(&adb->entriescntlock);
1779 free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
1781 dns_adblameinfo_t *li;
1783 INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
1787 INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
1788 INSIST(e->refcnt == 0);
1789 INSIST(!ISC_LINK_LINKED(e, plink));
1793 li = ISC_LIST_HEAD(e->lameinfo);
1794 while (li != NULL) {
1795 ISC_LIST_UNLINK(e->lameinfo, li, plink);
1796 free_adblameinfo(adb, &li);
1797 li = ISC_LIST_HEAD(e->lameinfo);
1800 isc_mempool_put(adb->emp, e);
1801 LOCK(&adb->entriescntlock);
1803 UNLOCK(&adb->entriescntlock);
1806 static inline dns_adbfind_t *
1807 new_adbfind(dns_adb_t *adb) {
1809 isc_result_t result;
1811 h = isc_mempool_get(adb->ahmp);
1820 h->partial_result = 0;
1823 h->result_v4 = ISC_R_UNEXPECTED;
1824 h->result_v6 = ISC_R_UNEXPECTED;
1825 ISC_LINK_INIT(h, publink);
1826 ISC_LINK_INIT(h, plink);
1827 ISC_LIST_INIT(h->list);
1829 h->name_bucket = DNS_ADB_INVALIDBUCKET;
1834 result = isc_mutex_init(&h->lock);
1835 if (result != ISC_R_SUCCESS) {
1836 isc_mempool_put(adb->ahmp, h);
1840 ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
1843 inc_adb_irefcnt(adb);
1844 h->magic = DNS_ADBFIND_MAGIC;
1848 static inline dns_adbfetch_t *
1849 new_adbfetch(dns_adb_t *adb) {
1852 f = isc_mempool_get(adb->afmp);
1859 dns_rdataset_init(&f->rdataset);
1861 f->magic = DNS_ADBFETCH_MAGIC;
1867 free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
1870 INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
1876 if (dns_rdataset_isassociated(&f->rdataset))
1877 dns_rdataset_disassociate(&f->rdataset);
1879 isc_mempool_put(adb->afmp, f);
1882 static inline isc_boolean_t
1883 free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
1884 dns_adbfind_t *find;
1886 INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
1890 INSIST(!FIND_HAS_ADDRS(find));
1891 INSIST(!ISC_LINK_LINKED(find, publink));
1892 INSIST(!ISC_LINK_LINKED(find, plink));
1893 INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
1894 INSIST(find->adbname == NULL);
1898 DESTROYLOCK(&find->lock);
1899 isc_mempool_put(adb->ahmp, find);
1900 return (dec_adb_irefcnt(adb));
1904 * Copy bits from the entry into the newly allocated addrinfo. The entry
1905 * must be locked, and the reference count must be bumped up by one
1906 * if this function returns a valid pointer.
1908 static inline dns_adbaddrinfo_t *
1909 new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
1910 dns_adbaddrinfo_t *ai;
1912 ai = isc_mempool_get(adb->aimp);
1916 ai->magic = DNS_ADBADDRINFO_MAGIC;
1917 ai->sockaddr = entry->sockaddr;
1918 isc_sockaddr_setport(&ai->sockaddr, port);
1919 ai->srtt = entry->srtt;
1920 ai->flags = entry->flags;
1922 ISC_LINK_INIT(ai, publink);
1928 free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
1929 dns_adbaddrinfo_t *ai;
1931 INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
1935 INSIST(ai->entry == NULL);
1936 INSIST(!ISC_LINK_LINKED(ai, publink));
1940 isc_mempool_put(adb->aimp, ai);
1944 * Search for the name. NOTE: The bucket is kept locked on both
1945 * success and failure, so it must always be unlocked by the caller!
1947 * On the first call to this function, *bucketp must be set to
1948 * DNS_ADB_INVALIDBUCKET.
1950 static inline dns_adbname_t *
1951 find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
1952 unsigned int options, int *bucketp)
1954 dns_adbname_t *adbname;
1957 bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
1959 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
1960 LOCK(&adb->namelocks[bucket]);
1962 } else if (*bucketp != bucket) {
1963 UNLOCK(&adb->namelocks[*bucketp]);
1964 LOCK(&adb->namelocks[bucket]);
1968 adbname = ISC_LIST_HEAD(adb->names[bucket]);
1969 while (adbname != NULL) {
1970 if (!NAME_DEAD(adbname)) {
1971 if (dns_name_equal(name, &adbname->name)
1972 && GLUEHINT_OK(adbname, options)
1973 && STARTATZONE_MATCHES(adbname, options))
1976 adbname = ISC_LIST_NEXT(adbname, plink);
1983 * Search for the address. NOTE: The bucket is kept locked on both
1984 * success and failure, so it must always be unlocked by the caller.
1986 * On the first call to this function, *bucketp must be set to
1987 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
1988 * later calls (within the same "lock path") it can be left alone, so
1989 * if this function is called multiple times locking is only done if
1990 * the bucket changes.
1992 static inline dns_adbentry_t *
1993 find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
1996 dns_adbentry_t *entry, *entry_next;
1999 bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
2001 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
2002 LOCK(&adb->entrylocks[bucket]);
2004 } else if (*bucketp != bucket) {
2005 UNLOCK(&adb->entrylocks[*bucketp]);
2006 LOCK(&adb->entrylocks[bucket]);
2010 /* Search the list, while cleaning up expired entries. */
2011 for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
2013 entry = entry_next) {
2014 entry_next = ISC_LIST_NEXT(entry, plink);
2015 (void)check_expire_entry(adb, &entry, now);
2016 if (entry != NULL &&
2017 isc_sockaddr_equal(addr, &entry->sockaddr)) {
2018 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
2019 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
2028 * Entry bucket MUST be locked!
2030 static isc_boolean_t
2031 entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
2032 dns_rdatatype_t qtype, isc_stdtime_t now)
2034 dns_adblameinfo_t *li, *next_li;
2035 isc_boolean_t is_bad;
2039 li = ISC_LIST_HEAD(entry->lameinfo);
2042 while (li != NULL) {
2043 next_li = ISC_LIST_NEXT(li, plink);
2046 * Has the entry expired?
2048 if (li->lame_timer < now) {
2049 ISC_LIST_UNLINK(entry->lameinfo, li, plink);
2050 free_adblameinfo(adb, &li);
2054 * Order tests from least to most expensive.
2056 * We do not break out of the main loop here as
2057 * we use the loop for house keeping.
2059 if (li != NULL && !is_bad && li->qtype == qtype &&
2060 dns_name_equal(qname, &li->qname))
2070 copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
2071 dns_rdatatype_t qtype, dns_adbname_t *name,
2074 dns_adbnamehook_t *namehook;
2075 dns_adbaddrinfo_t *addrinfo;
2076 dns_adbentry_t *entry;
2079 bucket = DNS_ADB_INVALIDBUCKET;
2081 if (find->options & DNS_ADBFIND_INET) {
2082 namehook = ISC_LIST_HEAD(name->v4);
2083 while (namehook != NULL) {
2084 entry = namehook->entry;
2085 bucket = entry->lock_bucket;
2086 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2087 LOCK(&adb->entrylocks[bucket]);
2089 if (!FIND_RETURNLAME(find)
2090 && entry_is_lame(adb, entry, qname, qtype, now)) {
2091 find->options |= DNS_ADBFIND_LAMEPRUNED;
2094 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2095 if (addrinfo == NULL) {
2096 find->partial_result |= DNS_ADBFIND_INET;
2100 * Found a valid entry. Add it to the find's list.
2102 inc_entry_refcnt(adb, entry, ISC_FALSE);
2103 ISC_LIST_APPEND(find->list, addrinfo, publink);
2106 UNLOCK(&adb->entrylocks[bucket]);
2107 bucket = DNS_ADB_INVALIDBUCKET;
2108 namehook = ISC_LIST_NEXT(namehook, plink);
2112 if (find->options & DNS_ADBFIND_INET6) {
2113 namehook = ISC_LIST_HEAD(name->v6);
2114 while (namehook != NULL) {
2115 entry = namehook->entry;
2116 bucket = entry->lock_bucket;
2117 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2118 LOCK(&adb->entrylocks[bucket]);
2120 if (!FIND_RETURNLAME(find)
2121 && entry_is_lame(adb, entry, qname, qtype, now)) {
2122 find->options |= DNS_ADBFIND_LAMEPRUNED;
2125 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2126 if (addrinfo == NULL) {
2127 find->partial_result |= DNS_ADBFIND_INET6;
2131 * Found a valid entry. Add it to the find's list.
2133 inc_entry_refcnt(adb, entry, ISC_FALSE);
2134 ISC_LIST_APPEND(find->list, addrinfo, publink);
2137 UNLOCK(&adb->entrylocks[bucket]);
2138 bucket = DNS_ADB_INVALIDBUCKET;
2139 namehook = ISC_LIST_NEXT(namehook, plink);
2144 if (bucket != DNS_ADB_INVALIDBUCKET)
2145 UNLOCK(&adb->entrylocks[bucket]);
2149 shutdown_task(isc_task_t *task, isc_event_t *ev) {
2155 INSIST(DNS_ADB_VALID(adb));
2157 isc_event_free(&ev);
2159 * Wait for lock around check_exit() call to be released.
2167 * Name bucket must be locked; adb may be locked; no other locks held.
2169 static isc_boolean_t
2170 check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
2171 dns_adbname_t *name;
2172 isc_boolean_t result = ISC_FALSE;
2174 INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
2177 if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
2179 if (NAME_FETCH(name))
2181 if (!EXPIRE_OK(name->expire_v4, now))
2183 if (!EXPIRE_OK(name->expire_v6, now))
2185 if (!EXPIRE_OK(name->expire_target, now))
2189 * The name is empty. Delete it.
2191 result = kill_name(&name, DNS_EVENT_ADBEXPIRED);
2195 * Our caller, or one of its callers, will be calling check_exit() at
2196 * some point, so we don't need to do it here.
2202 * Examine the tail entry of the LRU list to see if it expires or is stale
2203 * (unused for some period); if so, the name entry will be freed. If the ADB
2204 * is in the overmem condition, the tail and the next to tail entries
2205 * will be unconditionally removed (unless they have an outstanding fetch).
2206 * We don't care about a race on 'overmem' at the risk of causing some
2207 * collateral damage or a small delay in starting cleanup, so we don't bother
2208 * to lock ADB (if it's not locked).
2210 * Name bucket must be locked; adb may be locked; no other locks held.
2213 check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2214 int victims, max_victims;
2215 dns_adbname_t *victim, *next_victim;
2216 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
2219 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2221 max_victims = overmem ? 2 : 1;
2224 * We limit the number of scanned entries to 10 (arbitrary choice)
2225 * in order to avoid examining too many entries when there are many
2226 * tail entries that have fetches (this should be rare, but could
2229 victim = ISC_LIST_TAIL(adb->names[bucket]);
2231 victim != NULL && victims < max_victims && scans < 10;
2232 victim = next_victim) {
2233 INSIST(!NAME_DEAD(victim));
2235 next_victim = ISC_LIST_PREV(victim, plink);
2236 (void)check_expire_name(&victim, now);
2237 if (victim == NULL) {
2242 if (!NAME_FETCH(victim) &&
2243 (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
2244 RUNTIME_CHECK(kill_name(&victim,
2245 DNS_EVENT_ADBCANCELED) ==
2257 * Entry bucket must be locked; adb may be locked; no other locks held.
2259 static isc_boolean_t
2260 check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
2262 dns_adbentry_t *entry;
2263 isc_boolean_t result = ISC_FALSE;
2265 INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
2268 if (entry->refcnt != 0)
2271 if (entry->expires == 0 || entry->expires > now)
2275 * The entry is not in use. Delete it.
2277 DP(DEF_LEVEL, "killing entry %p", entry);
2278 INSIST(ISC_LINK_LINKED(entry, plink));
2279 result = unlink_entry(adb, entry);
2280 free_adbentry(adb, &entry);
2282 dec_adb_irefcnt(adb);
2288 * ADB must be locked, and no other locks held.
2290 static isc_boolean_t
2291 cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2292 dns_adbname_t *name;
2293 dns_adbname_t *next_name;
2294 isc_boolean_t result = ISC_FALSE;
2296 DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
2298 LOCK(&adb->namelocks[bucket]);
2299 if (adb->name_sd[bucket]) {
2300 UNLOCK(&adb->namelocks[bucket]);
2304 name = ISC_LIST_HEAD(adb->names[bucket]);
2305 while (name != NULL) {
2306 next_name = ISC_LIST_NEXT(name, plink);
2307 INSIST(result == ISC_FALSE);
2308 result = check_expire_namehooks(name, now);
2310 result = check_expire_name(&name, now);
2313 UNLOCK(&adb->namelocks[bucket]);
2318 * ADB must be locked, and no other locks held.
2320 static isc_boolean_t
2321 cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2322 dns_adbentry_t *entry, *next_entry;
2323 isc_boolean_t result = ISC_FALSE;
2325 DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
2327 LOCK(&adb->entrylocks[bucket]);
2328 entry = ISC_LIST_HEAD(adb->entries[bucket]);
2329 while (entry != NULL) {
2330 next_entry = ISC_LIST_NEXT(entry, plink);
2331 INSIST(result == ISC_FALSE);
2332 result = check_expire_entry(adb, &entry, now);
2335 UNLOCK(&adb->entrylocks[bucket]);
2340 destroy(dns_adb_t *adb) {
2343 isc_task_detach(&adb->task);
2344 if (adb->excl != NULL)
2345 isc_task_detach(&adb->excl);
2347 isc_mempool_destroy(&adb->nmp);
2348 isc_mempool_destroy(&adb->nhmp);
2349 isc_mempool_destroy(&adb->limp);
2350 isc_mempool_destroy(&adb->emp);
2351 isc_mempool_destroy(&adb->ahmp);
2352 isc_mempool_destroy(&adb->aimp);
2353 isc_mempool_destroy(&adb->afmp);
2355 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2356 isc_mem_put(adb->mctx, adb->entries,
2357 sizeof(*adb->entries) * adb->nentries);
2358 isc_mem_put(adb->mctx, adb->deadentries,
2359 sizeof(*adb->deadentries) * adb->nentries);
2360 isc_mem_put(adb->mctx, adb->entrylocks,
2361 sizeof(*adb->entrylocks) * adb->nentries);
2362 isc_mem_put(adb->mctx, adb->entry_sd,
2363 sizeof(*adb->entry_sd) * adb->nentries);
2364 isc_mem_put(adb->mctx, adb->entry_refcnt,
2365 sizeof(*adb->entry_refcnt) * adb->nentries);
2367 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2368 isc_mem_put(adb->mctx, adb->names,
2369 sizeof(*adb->names) * adb->nnames);
2370 isc_mem_put(adb->mctx, adb->deadnames,
2371 sizeof(*adb->deadnames) * adb->nnames);
2372 isc_mem_put(adb->mctx, adb->namelocks,
2373 sizeof(*adb->namelocks) * adb->nnames);
2374 isc_mem_put(adb->mctx, adb->name_sd,
2375 sizeof(*adb->name_sd) * adb->nnames);
2376 isc_mem_put(adb->mctx, adb->name_refcnt,
2377 sizeof(*adb->name_refcnt) * adb->nnames);
2379 DESTROYLOCK(&adb->reflock);
2380 DESTROYLOCK(&adb->lock);
2381 DESTROYLOCK(&adb->mplock);
2382 DESTROYLOCK(&adb->overmemlock);
2383 DESTROYLOCK(&adb->entriescntlock);
2384 DESTROYLOCK(&adb->namescntlock);
2386 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2395 dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
2396 isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
2399 isc_result_t result;
2402 REQUIRE(mem != NULL);
2403 REQUIRE(view != NULL);
2404 REQUIRE(timermgr != NULL); /* this is actually unused */
2405 REQUIRE(taskmgr != NULL);
2406 REQUIRE(newadb != NULL && *newadb == NULL);
2410 adb = isc_mem_get(mem, sizeof(dns_adb_t));
2412 return (ISC_R_NOMEMORY);
2415 * Initialize things here that cannot fail, and especially things
2416 * that must be NULL for the error return to work properly.
2432 adb->taskmgr = taskmgr;
2433 adb->next_cleanbucket = 0;
2434 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
2435 DNS_EVENT_ADBCONTROL, shutdown_task, adb,
2437 adb->cevent_sent = ISC_FALSE;
2438 adb->shutting_down = ISC_FALSE;
2439 ISC_LIST_INIT(adb->whenshutdown);
2441 adb->nentries = nbuckets[0];
2442 adb->entriescnt = 0;
2443 adb->entries = NULL;
2444 adb->deadentries = NULL;
2445 adb->entry_sd = NULL;
2446 adb->entry_refcnt = NULL;
2447 adb->entrylocks = NULL;
2448 ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
2449 DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
2451 adb->growentries_sent = ISC_FALSE;
2453 adb->nnames = nbuckets[0];
2456 adb->deadnames = NULL;
2457 adb->name_sd = NULL;
2458 adb->name_refcnt = NULL;
2459 adb->namelocks = NULL;
2460 ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
2461 DNS_EVENT_ADBGROWNAMES, grow_names, adb,
2463 adb->grownames_sent = ISC_FALSE;
2465 result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
2466 if (result != ISC_R_SUCCESS) {
2467 DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, "
2468 "intializing table sizes to %u\n",
2470 adb->nentries = nbuckets[11];
2471 adb->nnames= nbuckets[11];
2475 isc_mem_attach(mem, &adb->mctx);
2477 result = isc_mutex_init(&adb->lock);
2478 if (result != ISC_R_SUCCESS)
2481 result = isc_mutex_init(&adb->mplock);
2482 if (result != ISC_R_SUCCESS)
2485 result = isc_mutex_init(&adb->reflock);
2486 if (result != ISC_R_SUCCESS)
2489 result = isc_mutex_init(&adb->overmemlock);
2490 if (result != ISC_R_SUCCESS)
2493 result = isc_mutex_init(&adb->entriescntlock);
2494 if (result != ISC_R_SUCCESS)
2497 result = isc_mutex_init(&adb->namescntlock);
2498 if (result != ISC_R_SUCCESS)
2501 #define ALLOCENTRY(adb, el) \
2503 (adb)->el = isc_mem_get((adb)->mctx, \
2504 sizeof(*(adb)->el) * (adb)->nentries); \
2505 if ((adb)->el == NULL) { \
2506 result = ISC_R_NOMEMORY; \
2510 ALLOCENTRY(adb, entries);
2511 ALLOCENTRY(adb, deadentries);
2512 ALLOCENTRY(adb, entrylocks);
2513 ALLOCENTRY(adb, entry_sd);
2514 ALLOCENTRY(adb, entry_refcnt);
2517 #define ALLOCNAME(adb, el) \
2519 (adb)->el = isc_mem_get((adb)->mctx, \
2520 sizeof(*(adb)->el) * (adb)->nnames); \
2521 if ((adb)->el == NULL) { \
2522 result = ISC_R_NOMEMORY; \
2526 ALLOCNAME(adb, names);
2527 ALLOCNAME(adb, deadnames);
2528 ALLOCNAME(adb, namelocks);
2529 ALLOCNAME(adb, name_sd);
2530 ALLOCNAME(adb, name_refcnt);
2534 * Initialize the bucket locks for names and elements.
2535 * May as well initialize the list heads, too.
2537 result = isc_mutexblock_init(adb->namelocks, adb->nnames);
2538 if (result != ISC_R_SUCCESS)
2540 for (i = 0; i < adb->nnames; i++) {
2541 ISC_LIST_INIT(adb->names[i]);
2542 ISC_LIST_INIT(adb->deadnames[i]);
2543 adb->name_sd[i] = ISC_FALSE;
2544 adb->name_refcnt[i] = 0;
2547 for (i = 0; i < adb->nentries; i++) {
2548 ISC_LIST_INIT(adb->entries[i]);
2549 ISC_LIST_INIT(adb->deadentries[i]);
2550 adb->entry_sd[i] = ISC_FALSE;
2551 adb->entry_refcnt[i] = 0;
2554 result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
2555 if (result != ISC_R_SUCCESS)
2561 #define MPINIT(t, p, n) do { \
2562 result = isc_mempool_create(mem, sizeof(t), &(p)); \
2563 if (result != ISC_R_SUCCESS) \
2565 isc_mempool_setfreemax((p), FREE_ITEMS); \
2566 isc_mempool_setfillcount((p), FILL_COUNT); \
2567 isc_mempool_setname((p), n); \
2568 isc_mempool_associatelock((p), &adb->mplock); \
2571 MPINIT(dns_adbname_t, adb->nmp, "adbname");
2572 MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
2573 MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
2574 MPINIT(dns_adbentry_t, adb->emp, "adbentry");
2575 MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
2576 MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
2577 MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
2582 * Allocate an internal task.
2584 result = isc_task_create(adb->taskmgr, 0, &adb->task);
2585 if (result != ISC_R_SUCCESS)
2588 isc_task_setname(adb->task, "ADB", adb);
2593 adb->magic = DNS_ADB_MAGIC;
2595 return (ISC_R_SUCCESS);
2598 if (adb->task != NULL)
2599 isc_task_detach(&adb->task);
2601 /* clean up entrylocks */
2602 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2604 fail2: /* clean up namelocks */
2605 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2607 fail1: /* clean up only allocated memory */
2608 if (adb->entries != NULL)
2609 isc_mem_put(adb->mctx, adb->entries,
2610 sizeof(*adb->entries) * adb->nentries);
2611 if (adb->deadentries != NULL)
2612 isc_mem_put(adb->mctx, adb->deadentries,
2613 sizeof(*adb->deadentries) * adb->nentries);
2614 if (adb->entrylocks != NULL)
2615 isc_mem_put(adb->mctx, adb->entrylocks,
2616 sizeof(*adb->entrylocks) * adb->nentries);
2617 if (adb->entry_sd != NULL)
2618 isc_mem_put(adb->mctx, adb->entry_sd,
2619 sizeof(*adb->entry_sd) * adb->nentries);
2620 if (adb->entry_refcnt != NULL)
2621 isc_mem_put(adb->mctx, adb->entry_refcnt,
2622 sizeof(*adb->entry_refcnt) * adb->nentries);
2623 if (adb->names != NULL)
2624 isc_mem_put(adb->mctx, adb->names,
2625 sizeof(*adb->names) * adb->nnames);
2626 if (adb->deadnames != NULL)
2627 isc_mem_put(adb->mctx, adb->deadnames,
2628 sizeof(*adb->deadnames) * adb->nnames);
2629 if (adb->namelocks != NULL)
2630 isc_mem_put(adb->mctx, adb->namelocks,
2631 sizeof(*adb->namelocks) * adb->nnames);
2632 if (adb->name_sd != NULL)
2633 isc_mem_put(adb->mctx, adb->name_sd,
2634 sizeof(*adb->name_sd) * adb->nnames);
2635 if (adb->name_refcnt != NULL)
2636 isc_mem_put(adb->mctx, adb->name_refcnt,
2637 sizeof(*adb->name_refcnt) * adb->nnames);
2638 if (adb->nmp != NULL)
2639 isc_mempool_destroy(&adb->nmp);
2640 if (adb->nhmp != NULL)
2641 isc_mempool_destroy(&adb->nhmp);
2642 if (adb->limp != NULL)
2643 isc_mempool_destroy(&adb->limp);
2644 if (adb->emp != NULL)
2645 isc_mempool_destroy(&adb->emp);
2646 if (adb->ahmp != NULL)
2647 isc_mempool_destroy(&adb->ahmp);
2648 if (adb->aimp != NULL)
2649 isc_mempool_destroy(&adb->aimp);
2650 if (adb->afmp != NULL)
2651 isc_mempool_destroy(&adb->afmp);
2653 DESTROYLOCK(&adb->namescntlock);
2655 DESTROYLOCK(&adb->entriescntlock);
2657 DESTROYLOCK(&adb->overmemlock);
2659 DESTROYLOCK(&adb->reflock);
2661 DESTROYLOCK(&adb->mplock);
2663 DESTROYLOCK(&adb->lock);
2665 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2671 dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
2673 REQUIRE(DNS_ADB_VALID(adb));
2674 REQUIRE(adbx != NULL && *adbx == NULL);
2676 inc_adb_erefcnt(adb);
2681 dns_adb_detach(dns_adb_t **adbx) {
2683 isc_boolean_t need_exit_check;
2685 REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
2690 INSIST(adb->erefcnt > 0);
2692 LOCK(&adb->reflock);
2694 need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
2695 UNLOCK(&adb->reflock);
2697 if (need_exit_check) {
2699 INSIST(adb->shutting_down);
2706 dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
2709 isc_boolean_t zeroirefcnt = ISC_FALSE;
2712 * Send '*eventp' to 'task' when 'adb' has shutdown.
2715 REQUIRE(DNS_ADB_VALID(adb));
2716 REQUIRE(eventp != NULL);
2723 LOCK(&adb->reflock);
2724 zeroirefcnt = ISC_TF(adb->irefcnt == 0);
2726 if (adb->shutting_down && zeroirefcnt &&
2727 isc_mempool_getallocated(adb->ahmp) == 0) {
2729 * We're already shutdown. Send the event.
2731 event->ev_sender = adb;
2732 isc_task_send(task, &event);
2735 isc_task_attach(task, &clone);
2736 event->ev_sender = clone;
2737 ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
2740 UNLOCK(&adb->reflock);
2745 dns_adb_shutdown(dns_adb_t *adb) {
2746 isc_boolean_t need_check_exit;
2754 if (!adb->shutting_down) {
2755 adb->shutting_down = ISC_TRUE;
2756 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
2757 need_check_exit = shutdown_names(adb);
2758 if (!need_check_exit)
2759 need_check_exit = shutdown_entries(adb);
2760 if (need_check_exit)
2768 dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2769 void *arg, dns_name_t *name, dns_name_t *qname,
2770 dns_rdatatype_t qtype, unsigned int options,
2771 isc_stdtime_t now, dns_name_t *target,
2772 in_port_t port, dns_adbfind_t **findp)
2774 return (dns_adb_createfind2(adb, task, action, arg, name,
2775 qname, qtype, options, now,
2776 target, port, 0, NULL, findp));
2780 dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2781 void *arg, dns_name_t *name, dns_name_t *qname,
2782 dns_rdatatype_t qtype, unsigned int options,
2783 isc_stdtime_t now, dns_name_t *target,
2784 in_port_t port, unsigned int depth, isc_counter_t *qc,
2785 dns_adbfind_t **findp)
2787 dns_adbfind_t *find;
2788 dns_adbname_t *adbname;
2790 isc_boolean_t want_event, start_at_zone, alias, have_address;
2791 isc_result_t result;
2792 unsigned int wanted_addresses;
2793 unsigned int wanted_fetches;
2794 unsigned int query_pending;
2796 REQUIRE(DNS_ADB_VALID(adb));
2798 REQUIRE(action != NULL);
2800 REQUIRE(name != NULL);
2801 REQUIRE(qname != NULL);
2802 REQUIRE(findp != NULL && *findp == NULL);
2803 REQUIRE(target == NULL || dns_name_hasbuffer(target));
2805 REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
2807 result = ISC_R_UNEXPECTED;
2809 wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
2812 want_event = ISC_FALSE;
2813 start_at_zone = ISC_FALSE;
2817 isc_stdtime_get(&now);
2820 * XXXMLG Move this comment somewhere else!
2822 * Look up the name in our internal database.
2824 * Possibilities: Note that these are not always exclusive.
2826 * No name found. In this case, allocate a new name header and
2827 * an initial namehook or two. If any of these allocations
2828 * fail, clean up and return ISC_R_NOMEMORY.
2830 * Name found, valid addresses present. Allocate one addrinfo
2831 * structure for each found and append it to the linked list
2832 * of addresses for this header.
2834 * Name found, queries pending. In this case, if a task was
2835 * passed in, allocate a job id, attach it to the name's job
2836 * list and remember to tell the caller that there will be
2837 * more info coming later.
2840 find = new_adbfind(adb);
2842 return (ISC_R_NOMEMORY);
2847 * Remember what types of addresses we are interested in.
2849 find->options = options;
2850 find->flags |= wanted_addresses;
2851 if (FIND_WANTEVENT(find)) {
2852 REQUIRE(task != NULL);
2856 * Try to see if we know anything about this name at all.
2858 bucket = DNS_ADB_INVALIDBUCKET;
2859 adbname = find_name_and_lock(adb, name, find->options, &bucket);
2860 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2861 if (adb->name_sd[bucket]) {
2863 "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
2864 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2865 result = ISC_R_SHUTTINGDOWN;
2870 * Nothing found. Allocate a new adbname structure for this name.
2872 if (adbname == NULL) {
2874 * See if there is any stale name at the end of list, and purge
2877 check_stale_name(adb, bucket, now);
2879 adbname = new_adbname(adb, name);
2880 if (adbname == NULL) {
2881 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2882 result = ISC_R_NOMEMORY;
2885 link_name(adb, bucket, adbname);
2886 if (FIND_HINTOK(find))
2887 adbname->flags |= NAME_HINT_OK;
2888 if (FIND_GLUEOK(find))
2889 adbname->flags |= NAME_GLUE_OK;
2890 if (FIND_STARTATZONE(find))
2891 adbname->flags |= NAME_STARTATZONE;
2893 /* Move this name forward in the LRU list */
2894 ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
2895 ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
2897 adbname->last_used = now;
2900 * Expire old entries, etc.
2902 RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
2905 * Do we know that the name is an alias?
2907 if (!EXPIRE_OK(adbname->expire_target, now)) {
2912 "dns_adb_createfind: name %p is an alias (cached)",
2919 * Try to populate the name from the database and/or
2920 * start fetches. First try looking for an A record
2923 if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
2924 && WANT_INET(wanted_addresses)) {
2925 result = dbfind_name(adbname, now, dns_rdatatype_a);
2926 if (result == ISC_R_SUCCESS) {
2928 "dns_adb_createfind: found A for name %p in db",
2934 * Did we get a CNAME or DNAME?
2936 if (result == DNS_R_ALIAS) {
2938 "dns_adb_createfind: name %p is an alias",
2945 * If the name doesn't exist at all, don't bother with
2946 * v6 queries; they won't work.
2948 * If the name does exist but we didn't get our data, go
2949 * ahead and try AAAA.
2951 * If the result is neither of these, try a fetch for A.
2953 if (NXDOMAIN_RESULT(result))
2955 else if (NXRRSET_RESULT(result))
2958 if (!NAME_FETCH_V4(adbname))
2959 wanted_fetches |= DNS_ADBFIND_INET;
2963 if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
2964 && WANT_INET6(wanted_addresses)) {
2965 result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
2966 if (result == ISC_R_SUCCESS) {
2968 "dns_adb_createfind: found AAAA for name %p",
2974 * Did we get a CNAME or DNAME?
2976 if (result == DNS_R_ALIAS) {
2978 "dns_adb_createfind: name %p is an alias",
2985 * Listen to negative cache hints, and don't start
2988 if (NCACHE_RESULT(result) || AUTH_NX(result))
2991 if (!NAME_FETCH_V6(adbname))
2992 wanted_fetches |= DNS_ADBFIND_INET6;
2996 if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
2997 (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
2998 have_address = ISC_TRUE;
3000 have_address = ISC_FALSE;
3001 if (wanted_fetches != 0 &&
3002 ! (FIND_AVOIDFETCHES(find) && have_address)) {
3004 * We're missing at least one address family. Either the
3005 * caller hasn't instructed us to avoid fetches, or we don't
3006 * know anything about any of the address families that would
3007 * be acceptable so we have to launch fetches.
3010 if (FIND_STARTATZONE(find))
3011 start_at_zone = ISC_TRUE;
3016 if (WANT_INET(wanted_fetches) &&
3017 fetch_name(adbname, start_at_zone, depth, qc,
3018 dns_rdatatype_a) == ISC_R_SUCCESS) {
3020 "dns_adb_createfind: started A fetch for name %p",
3027 if (WANT_INET6(wanted_fetches) &&
3028 fetch_name(adbname, start_at_zone, depth, qc,
3029 dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
3031 "dns_adb_createfind: "
3032 "started AAAA fetch for name %p",
3038 * Run through the name and copy out the bits we are
3041 copy_namehook_lists(adb, find, qname, qtype, adbname, now);
3044 if (NAME_FETCH_V4(adbname))
3045 query_pending |= DNS_ADBFIND_INET;
3046 if (NAME_FETCH_V6(adbname))
3047 query_pending |= DNS_ADBFIND_INET6;
3050 * Attach to the name's query list if there are queries
3051 * already running, and we have been asked to.
3053 want_event = ISC_TRUE;
3054 if (!FIND_WANTEVENT(find))
3055 want_event = ISC_FALSE;
3056 if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
3057 want_event = ISC_FALSE;
3058 if ((wanted_addresses & query_pending) == 0)
3059 want_event = ISC_FALSE;
3061 want_event = ISC_FALSE;
3063 find->adbname = adbname;
3064 find->name_bucket = bucket;
3065 ISC_LIST_APPEND(adbname->finds, find, plink);
3066 find->query_pending = (query_pending & wanted_addresses);
3067 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3068 find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
3069 DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
3073 * Remove the flag so the caller knows there will never
3074 * be an event, and set internal flags to fake that
3075 * the event was sent and freed, so dns_adb_destroyfind() will
3076 * do the right thing.
3078 find->query_pending = (query_pending & wanted_addresses);
3079 find->options &= ~DNS_ADBFIND_WANTEVENT;
3080 find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
3081 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3084 find->partial_result |= (adbname->partial_result & wanted_addresses);
3086 if (target != NULL) {
3087 result = dns_name_copy(&adbname->target, target, NULL);
3088 if (result != ISC_R_SUCCESS)
3091 result = DNS_R_ALIAS;
3093 result = ISC_R_SUCCESS;
3096 * Copy out error flags from the name structure into the find.
3098 find->result_v4 = find_err_map[adbname->fetch_err];
3099 find->result_v6 = find_err_map[adbname->fetch6_err];
3108 INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
3110 isc_task_attach(task, &taskp);
3111 find->event.ev_sender = taskp;
3112 find->event.ev_action = action;
3113 find->event.ev_arg = arg;
3117 UNLOCK(&adb->namelocks[bucket]);
3123 dns_adb_destroyfind(dns_adbfind_t **findp) {
3124 dns_adbfind_t *find;
3125 dns_adbentry_t *entry;
3126 dns_adbaddrinfo_t *ai;
3129 isc_boolean_t overmem;
3131 REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
3137 DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
3140 REQUIRE(DNS_ADB_VALID(adb));
3142 REQUIRE(FIND_EVENTFREED(find));
3144 bucket = find->name_bucket;
3145 INSIST(bucket == DNS_ADB_INVALIDBUCKET);
3147 UNLOCK(&find->lock);
3150 * The find doesn't exist on any list, and nothing is locked.
3151 * Return the find to the memory pool, and decrement the adb's
3154 overmem = isc_mem_isovermem(adb->mctx);
3155 ai = ISC_LIST_HEAD(find->list);
3156 while (ai != NULL) {
3157 ISC_LIST_UNLINK(find->list, ai, publink);
3160 INSIST(DNS_ADBENTRY_VALID(entry));
3161 RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
3163 free_adbaddrinfo(adb, &ai);
3164 ai = ISC_LIST_HEAD(find->list);
3168 * WARNING: The find is freed with the adb locked. This is done
3169 * to avoid a race condition where we free the find, some other
3170 * thread tests to see if it should be destroyed, detects it should
3171 * be, destroys it, and then we try to lock it for our check, but the
3172 * lock is destroyed.
3175 if (free_adbfind(adb, &find))
3181 dns_adb_cancelfind(dns_adbfind_t *find) {
3190 DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
3193 REQUIRE(DNS_ADB_VALID(adb));
3195 REQUIRE(!FIND_EVENTFREED(find));
3196 REQUIRE(FIND_WANTEVENT(find));
3198 bucket = find->name_bucket;
3199 if (bucket == DNS_ADB_INVALIDBUCKET)
3203 * We need to get the adbname's lock to unlink the find.
3205 unlock_bucket = bucket;
3206 violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
3207 bucket = find->name_bucket;
3208 if (bucket != DNS_ADB_INVALIDBUCKET) {
3209 ISC_LIST_UNLINK(find->adbname->finds, find, plink);
3210 find->adbname = NULL;
3211 find->name_bucket = DNS_ADB_INVALIDBUCKET;
3213 UNLOCK(&adb->namelocks[unlock_bucket]);
3214 bucket = DNS_ADB_INVALIDBUCKET;
3219 if (!FIND_EVENTSENT(find)) {
3221 task = ev->ev_sender;
3222 ev->ev_sender = find;
3223 ev->ev_type = DNS_EVENT_ADBCANCELED;
3224 ev->ev_destroy = event_free;
3225 ev->ev_destroy_arg = find;
3226 find->result_v4 = ISC_R_CANCELED;
3227 find->result_v6 = ISC_R_CANCELED;
3229 DP(DEF_LEVEL, "sending event %p to task %p for find %p",
3232 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
3235 UNLOCK(&find->lock);
3239 dns_adb_dump(dns_adb_t *adb, FILE *f) {
3243 REQUIRE(DNS_ADB_VALID(adb));
3247 * Lock the adb itself, lock all the name buckets, then lock all
3248 * the entry buckets. This should put the adb into a state where
3249 * nothing can change, so we can iterate through everything and
3250 * print at our leisure.
3254 isc_stdtime_get(&now);
3256 for (i = 0; i < adb->nnames; i++)
3257 RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
3258 for (i = 0; i < adb->nentries; i++)
3259 RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
3261 dump_adb(adb, f, ISC_FALSE, now);
3266 dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
3267 if (value == INT_MAX)
3269 fprintf(f, " [%s TTL %d]", legend, value - now);
3273 dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
3275 dns_adbname_t *name;
3276 dns_adbentry_t *entry;
3278 fprintf(f, ";\n; Address database dump\n;\n");
3280 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
3281 adb, adb->erefcnt, adb->irefcnt,
3282 isc_mempool_getallocated(adb->nhmp));
3284 for (i = 0; i < adb->nnames; i++)
3285 LOCK(&adb->namelocks[i]);
3286 for (i = 0; i < adb->nentries; i++)
3287 LOCK(&adb->entrylocks[i]);
3292 for (i = 0; i < adb->nnames; i++) {
3293 name = ISC_LIST_HEAD(adb->names[i]);
3297 fprintf(f, "; bucket %d\n", i);
3300 name = ISC_LIST_NEXT(name, plink))
3303 fprintf(f, "; name %p (flags %08x)\n",
3307 print_dns_name(f, &name->name);
3308 if (dns_name_countlabels(&name->target) > 0) {
3309 fprintf(f, " alias ");
3310 print_dns_name(f, &name->target);
3313 dump_ttl(f, "v4", name->expire_v4, now);
3314 dump_ttl(f, "v6", name->expire_v6, now);
3315 dump_ttl(f, "target", name->expire_target, now);
3317 fprintf(f, " [v4 %s] [v6 %s]",
3318 errnames[name->fetch_err],
3319 errnames[name->fetch6_err]);
3323 print_namehook_list(f, "v4", &name->v4, debug, now);
3324 print_namehook_list(f, "v6", &name->v6, debug, now);
3327 print_fetch_list(f, name);
3329 print_find_list(f, name);
3334 fprintf(f, ";\n; Unassociated entries\n;\n");
3336 for (i = 0; i < adb->nentries; i++) {
3337 entry = ISC_LIST_HEAD(adb->entries[i]);
3338 while (entry != NULL) {
3339 if (entry->refcnt == 0)
3340 dump_entry(f, entry, debug, now);
3341 entry = ISC_LIST_NEXT(entry, plink);
3348 for (i = 0; i < adb->nentries; i++)
3349 UNLOCK(&adb->entrylocks[i]);
3350 for (i = 0; i < adb->nnames; i++)
3351 UNLOCK(&adb->namelocks[i]);
3355 dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
3358 char addrbuf[ISC_NETADDR_FORMATSIZE];
3359 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3360 isc_netaddr_t netaddr;
3361 dns_adblameinfo_t *li;
3363 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
3364 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
3367 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
3369 fprintf(f, ";\t%s [srtt %u] [flags %08x]",
3370 addrbuf, entry->srtt, entry->flags);
3371 if (entry->expires != 0)
3372 fprintf(f, " [ttl %d]", entry->expires - now);
3374 for (li = ISC_LIST_HEAD(entry->lameinfo);
3376 li = ISC_LIST_NEXT(li, plink)) {
3377 fprintf(f, ";\t\t");
3378 print_dns_name(f, &li->qname);
3379 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
3380 fprintf(f, " %s [lame TTL %d]\n", typebuf,
3381 li->lame_timer - now);
3386 dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
3389 dns_adbaddrinfo_t *ai;
3393 * Not used currently, in the API Just In Case we
3394 * want to dump out the name and/or entries too.
3399 fprintf(f, ";Find %p\n", find);
3400 fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
3401 find->query_pending, find->partial_result,
3402 find->options, find->flags);
3403 fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
3404 find->name_bucket, find->adbname, find->event.ev_sender);
3406 ai = ISC_LIST_HEAD(find->list);
3408 fprintf(f, "\tAddresses:\n");
3409 while (ai != NULL) {
3411 switch (sa->type.sa.sa_family) {
3413 tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
3417 tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
3425 tmpp = "BadAddress";
3427 fprintf(f, "\t\tentry %p, flags %08x"
3428 " srtt %u addr %s\n",
3429 ai->entry, ai->flags, ai->srtt, tmpp);
3431 ai = ISC_LIST_NEXT(ai, publink);
3434 UNLOCK(&find->lock);
3438 print_dns_name(FILE *f, dns_name_t *name) {
3439 char buf[DNS_NAME_FORMATSIZE];
3443 dns_name_format(name, buf, sizeof(buf));
3444 fprintf(f, "%s", buf);
3448 print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
3449 isc_boolean_t debug, isc_stdtime_t now)
3451 dns_adbnamehook_t *nh;
3453 for (nh = ISC_LIST_HEAD(*list);
3455 nh = ISC_LIST_NEXT(nh, plink))
3458 fprintf(f, ";\tHook(%s) %p\n", legend, nh);
3459 dump_entry(f, nh->entry, debug, now);
3464 print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
3465 fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
3466 type, ft, ft->fetch);
3470 print_fetch_list(FILE *f, dns_adbname_t *n) {
3471 if (NAME_FETCH_A(n))
3472 print_fetch(f, n->fetch_a, "A");
3473 if (NAME_FETCH_AAAA(n))
3474 print_fetch(f, n->fetch_aaaa, "AAAA");
3478 print_find_list(FILE *f, dns_adbname_t *name) {
3479 dns_adbfind_t *find;
3481 find = ISC_LIST_HEAD(name->finds);
3482 while (find != NULL) {
3483 dns_adb_dumpfind(find, f);
3484 find = ISC_LIST_NEXT(find, plink);
3489 dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
3491 isc_result_t result;
3492 dns_rdataset_t rdataset;
3494 dns_fixedname_t foundname;
3497 INSIST(DNS_ADBNAME_VALID(adbname));
3499 INSIST(DNS_ADB_VALID(adb));
3500 INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
3502 dns_fixedname_init(&foundname);
3503 fname = dns_fixedname_name(&foundname);
3504 dns_rdataset_init(&rdataset);
3506 if (rdtype == dns_rdatatype_a)
3507 adbname->fetch_err = FIND_ERR_UNEXPECTED;
3509 adbname->fetch6_err = FIND_ERR_UNEXPECTED;
3512 * We need to specify whether to search static-stub zones (if
3513 * configured) depending on whether this is a "start at zone" lookup,
3514 * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
3515 * case NAME_STARTATZONE is set) we need to stop the search at any
3516 * matching static-stub zone without looking into the cache to honor
3517 * the configuration on which server we should send queries to.
3519 result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
3520 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
3521 ISC_TF(NAME_HINTOK(adbname)),
3522 (adbname->flags & NAME_STARTATZONE) != 0 ?
3523 ISC_TRUE : ISC_FALSE,
3524 NULL, NULL, fname, &rdataset, NULL);
3526 /* XXXVIX this switch statement is too sparse to gen a jump table. */
3532 * Found in the database. Even if we can't copy out
3533 * any information, return success, or else a fetch
3534 * will be made, which will only make things worse.
3536 if (rdtype == dns_rdatatype_a)
3537 adbname->fetch_err = FIND_ERR_SUCCESS;
3539 adbname->fetch6_err = FIND_ERR_SUCCESS;
3540 result = import_rdataset(adbname, &rdataset, now);
3542 case DNS_R_NXDOMAIN:
3545 * We're authoritative and the data doesn't exist.
3546 * Make up a negative cache entry so we don't ask again
3549 * XXXRTH What time should we use? I'm putting in 30 seconds
3552 if (rdtype == dns_rdatatype_a) {
3553 adbname->expire_v4 = now + 30;
3555 "adb name %p: Caching auth negative entry for A",
3557 if (result == DNS_R_NXDOMAIN)
3558 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3560 adbname->fetch_err = FIND_ERR_NXRRSET;
3563 "adb name %p: Caching auth negative entry for AAAA",
3565 adbname->expire_v6 = now + 30;
3566 if (result == DNS_R_NXDOMAIN)
3567 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3569 adbname->fetch6_err = FIND_ERR_NXRRSET;
3572 case DNS_R_NCACHENXDOMAIN:
3573 case DNS_R_NCACHENXRRSET:
3575 * We found a negative cache entry. Pull the TTL from it
3576 * so we won't ask again for a while.
3578 rdataset.ttl = ttlclamp(rdataset.ttl);
3579 if (rdtype == dns_rdatatype_a) {
3580 adbname->expire_v4 = rdataset.ttl + now;
3581 if (result == DNS_R_NCACHENXDOMAIN)
3582 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3584 adbname->fetch_err = FIND_ERR_NXRRSET;
3586 "adb name %p: Caching negative entry for A (ttl %u)",
3587 adbname, rdataset.ttl);
3590 "adb name %p: Caching negative entry for AAAA (ttl %u)",
3591 adbname, rdataset.ttl);
3592 adbname->expire_v6 = rdataset.ttl + now;
3593 if (result == DNS_R_NCACHENXDOMAIN)
3594 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3596 adbname->fetch6_err = FIND_ERR_NXRRSET;
3602 * Clear the hint and glue flags, so this will match
3605 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
3607 rdataset.ttl = ttlclamp(rdataset.ttl);
3608 clean_target(adb, &adbname->target);
3609 adbname->expire_target = INT_MAX;
3610 result = set_target(adb, &adbname->name, fname, &rdataset,
3612 if (result == ISC_R_SUCCESS) {
3613 result = DNS_R_ALIAS;
3615 "adb name %p: caching alias target",
3617 adbname->expire_target = rdataset.ttl + now;
3619 if (rdtype == dns_rdatatype_a)
3620 adbname->fetch_err = FIND_ERR_SUCCESS;
3622 adbname->fetch6_err = FIND_ERR_SUCCESS;
3626 if (dns_rdataset_isassociated(&rdataset))
3627 dns_rdataset_disassociate(&rdataset);
3633 fetch_callback(isc_task_t *task, isc_event_t *ev) {
3634 dns_fetchevent_t *dev;
3635 dns_adbname_t *name;
3637 dns_adbfetch_t *fetch;
3639 isc_eventtype_t ev_status;
3641 isc_result_t result;
3642 unsigned int address_type;
3643 isc_boolean_t want_check_exit = ISC_FALSE;
3647 INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
3648 dev = (dns_fetchevent_t *)ev;
3650 INSIST(DNS_ADBNAME_VALID(name));
3652 INSIST(DNS_ADB_VALID(adb));
3654 bucket = name->lock_bucket;
3655 LOCK(&adb->namelocks[bucket]);
3657 INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
3659 if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
3660 address_type = DNS_ADBFIND_INET;
3661 fetch = name->fetch_a;
3662 name->fetch_a = NULL;
3663 } else if (NAME_FETCH_AAAA(name)
3664 && (name->fetch_aaaa->fetch == dev->fetch)) {
3665 address_type = DNS_ADBFIND_INET6;
3666 fetch = name->fetch_aaaa;
3667 name->fetch_aaaa = NULL;
3671 INSIST(address_type != 0 && fetch != NULL);
3673 dns_resolver_destroyfetch(&fetch->fetch);
3676 ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
3679 * Cleanup things we don't care about.
3681 if (dev->node != NULL)
3682 dns_db_detachnode(dev->db, &dev->node);
3683 if (dev->db != NULL)
3684 dns_db_detach(&dev->db);
3687 * If this name is marked as dead, clean up, throwing away
3688 * potentially good data.
3690 if (NAME_DEAD(name)) {
3691 free_adbfetch(adb, &fetch);
3692 isc_event_free(&ev);
3694 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED);
3696 UNLOCK(&adb->namelocks[bucket]);
3698 if (want_check_exit) {
3707 isc_stdtime_get(&now);
3710 * If we got a negative cache response, remember it.
3712 if (NCACHE_RESULT(dev->result)) {
3713 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3714 if (address_type == DNS_ADBFIND_INET) {
3715 DP(NCACHE_LEVEL, "adb fetch name %p: "
3716 "caching negative entry for A (ttl %u)",
3717 name, dev->rdataset->ttl);
3718 name->expire_v4 = ISC_MIN(name->expire_v4,
3719 dev->rdataset->ttl + now);
3720 if (dev->result == DNS_R_NCACHENXDOMAIN)
3721 name->fetch_err = FIND_ERR_NXDOMAIN;
3723 name->fetch_err = FIND_ERR_NXRRSET;
3724 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3726 DP(NCACHE_LEVEL, "adb fetch name %p: "
3727 "caching negative entry for AAAA (ttl %u)",
3728 name, dev->rdataset->ttl);
3729 name->expire_v6 = ISC_MIN(name->expire_v6,
3730 dev->rdataset->ttl + now);
3731 if (dev->result == DNS_R_NCACHENXDOMAIN)
3732 name->fetch6_err = FIND_ERR_NXDOMAIN;
3734 name->fetch6_err = FIND_ERR_NXRRSET;
3735 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3741 * Handle CNAME/DNAME.
3743 if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
3744 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3745 clean_target(adb, &name->target);
3746 name->expire_target = INT_MAX;
3747 result = set_target(adb, &name->name,
3748 dns_fixedname_name(&dev->foundname),
3751 if (result == ISC_R_SUCCESS) {
3753 "adb fetch name %p: caching alias target",
3755 name->expire_target = dev->rdataset->ttl + now;
3761 * Did we get back junk? If so, and there are no more fetches
3762 * sitting out there, tell all the finds about it.
3764 if (dev->result != ISC_R_SUCCESS) {
3765 char buf[DNS_NAME_FORMATSIZE];
3767 dns_name_format(&name->name, buf, sizeof(buf));
3768 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
3769 buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
3770 dns_result_totext(dev->result));
3772 * Don't record a failure unless this is the initial
3775 if (fetch->depth > 1)
3777 /* XXXMLG Don't pound on bad servers. */
3778 if (address_type == DNS_ADBFIND_INET) {
3779 name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
3780 name->fetch_err = FIND_ERR_FAILURE;
3781 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3783 name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
3784 name->fetch6_err = FIND_ERR_FAILURE;
3785 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3791 * We got something potentially useful.
3793 result = import_rdataset(name, &fetch->rdataset, now);
3796 if (result == ISC_R_SUCCESS) {
3797 ev_status = DNS_EVENT_ADBMOREADDRESSES;
3798 if (address_type == DNS_ADBFIND_INET)
3799 name->fetch_err = FIND_ERR_SUCCESS;
3801 name->fetch6_err = FIND_ERR_SUCCESS;
3805 free_adbfetch(adb, &fetch);
3806 isc_event_free(&ev);
3808 clean_finds_at_name(name, ev_status, address_type);
3810 UNLOCK(&adb->namelocks[bucket]);
3814 fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
3815 unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
3817 isc_result_t result;
3818 dns_adbfetch_t *fetch = NULL;
3820 dns_fixedname_t fixed;
3822 dns_rdataset_t rdataset;
3823 dns_rdataset_t *nameservers;
3824 unsigned int options;
3826 INSIST(DNS_ADBNAME_VALID(adbname));
3828 INSIST(DNS_ADB_VALID(adb));
3830 INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
3831 (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
3833 adbname->fetch_err = FIND_ERR_NOTFOUND;
3837 dns_rdataset_init(&rdataset);
3839 options = DNS_FETCHOPT_NOVALIDATE;
3840 if (start_at_zone) {
3842 "fetch_name: starting at zone for name %p",
3844 dns_fixedname_init(&fixed);
3845 name = dns_fixedname_name(&fixed);
3846 result = dns_view_findzonecut2(adb->view, &adbname->name, name,
3847 0, 0, ISC_TRUE, ISC_FALSE,
3849 if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
3851 nameservers = &rdataset;
3852 options |= DNS_FETCHOPT_UNSHARED;
3855 fetch = new_adbfetch(adb);
3856 if (fetch == NULL) {
3857 result = ISC_R_NOMEMORY;
3860 fetch->depth = depth;
3862 result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
3863 type, name, nameservers, NULL,
3864 NULL, 0, options, depth, qc,
3865 adb->task, fetch_callback, adbname,
3866 &fetch->rdataset, NULL,
3868 if (result != ISC_R_SUCCESS)
3871 if (type == dns_rdatatype_a) {
3872 adbname->fetch_a = fetch;
3873 inc_stats(adb, dns_resstatscounter_gluefetchv4);
3875 adbname->fetch_aaaa = fetch;
3876 inc_stats(adb, dns_resstatscounter_gluefetchv6);
3878 fetch = NULL; /* Keep us from cleaning this up below. */
3882 free_adbfetch(adb, &fetch);
3883 if (dns_rdataset_isassociated(&rdataset))
3884 dns_rdataset_disassociate(&rdataset);
3890 * XXXMLG Needs to take a find argument and an address info, no zone or adb,
3891 * since these can be extracted from the find itself.
3894 dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
3895 dns_rdatatype_t qtype, isc_stdtime_t expire_time)
3897 dns_adblameinfo_t *li;
3899 isc_result_t result = ISC_R_SUCCESS;
3901 REQUIRE(DNS_ADB_VALID(adb));
3902 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3903 REQUIRE(qname != NULL);
3905 bucket = addr->entry->lock_bucket;
3906 LOCK(&adb->entrylocks[bucket]);
3907 li = ISC_LIST_HEAD(addr->entry->lameinfo);
3908 while (li != NULL &&
3909 (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
3910 li = ISC_LIST_NEXT(li, plink);
3912 if (expire_time > li->lame_timer)
3913 li->lame_timer = expire_time;
3916 li = new_adblameinfo(adb, qname, qtype);
3918 result = ISC_R_NOMEMORY;
3922 li->lame_timer = expire_time;
3924 ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
3926 UNLOCK(&adb->entrylocks[bucket]);
3932 dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3933 unsigned int rtt, unsigned int factor)
3936 unsigned int new_srtt;
3939 REQUIRE(DNS_ADB_VALID(adb));
3940 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3941 REQUIRE(factor <= 10);
3943 bucket = addr->entry->lock_bucket;
3944 LOCK(&adb->entrylocks[bucket]);
3946 if (factor == DNS_ADB_RTTADJAGE)
3947 new_srtt = addr->entry->srtt * 98 / 100;
3949 new_srtt = (addr->entry->srtt / 10 * factor)
3950 + (rtt / 10 * (10 - factor));
3952 addr->entry->srtt = new_srtt;
3953 addr->srtt = new_srtt;
3955 if (addr->entry->expires == 0) {
3956 isc_stdtime_get(&now);
3957 addr->entry->expires = now + ADB_ENTRY_WINDOW;
3960 UNLOCK(&adb->entrylocks[bucket]);
3964 dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3965 unsigned int bits, unsigned int mask)
3970 REQUIRE(DNS_ADB_VALID(adb));
3971 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3973 bucket = addr->entry->lock_bucket;
3974 LOCK(&adb->entrylocks[bucket]);
3976 addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
3977 if (addr->entry->expires == 0) {
3978 isc_stdtime_get(&now);
3979 addr->entry->expires = now + ADB_ENTRY_WINDOW;
3983 * Note that we do not update the other bits in addr->flags with
3984 * the most recent values from addr->entry->flags.
3986 addr->flags = (addr->flags & ~mask) | (bits & mask);
3988 UNLOCK(&adb->entrylocks[bucket]);
3992 dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
3993 dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
3996 dns_adbentry_t *entry;
3997 dns_adbaddrinfo_t *addr;
3998 isc_result_t result;
4001 REQUIRE(DNS_ADB_VALID(adb));
4002 REQUIRE(addrp != NULL && *addrp == NULL);
4006 result = ISC_R_SUCCESS;
4007 bucket = DNS_ADB_INVALIDBUCKET;
4008 entry = find_entry_and_lock(adb, sa, &bucket, now);
4009 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
4010 if (adb->entry_sd[bucket]) {
4011 result = ISC_R_SHUTTINGDOWN;
4014 if (entry == NULL) {
4016 * We don't know anything about this address.
4018 entry = new_adbentry(adb);
4019 if (entry == NULL) {
4020 result = ISC_R_NOMEMORY;
4023 entry->sockaddr = *sa;
4024 link_entry(adb, bucket, entry);
4025 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
4027 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
4029 port = isc_sockaddr_getport(sa);
4030 addr = new_adbaddrinfo(adb, entry, port);
4032 result = ISC_R_NOMEMORY;
4034 inc_entry_refcnt(adb, entry, ISC_FALSE);
4039 UNLOCK(&adb->entrylocks[bucket]);
4045 dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
4046 dns_adbaddrinfo_t *addr;
4047 dns_adbentry_t *entry;
4050 isc_boolean_t want_check_exit = ISC_FALSE;
4051 isc_boolean_t overmem;
4053 REQUIRE(DNS_ADB_VALID(adb));
4054 REQUIRE(addrp != NULL);
4056 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4057 entry = addr->entry;
4058 REQUIRE(DNS_ADBENTRY_VALID(entry));
4061 overmem = isc_mem_isovermem(adb->mctx);
4063 bucket = addr->entry->lock_bucket;
4064 LOCK(&adb->entrylocks[bucket]);
4066 if (entry->expires == 0) {
4067 isc_stdtime_get(&now);
4068 entry->expires = now + ADB_ENTRY_WINDOW;
4071 want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
4073 UNLOCK(&adb->entrylocks[bucket]);
4076 free_adbaddrinfo(adb, &addr);
4078 if (want_check_exit) {
4086 dns_adb_flush(dns_adb_t *adb) {
4089 INSIST(DNS_ADB_VALID(adb));
4094 * Call our cleanup routines.
4096 for (i = 0; i < adb->nnames; i++)
4097 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
4098 for (i = 0; i < adb->nentries; i++)
4099 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
4101 #ifdef DUMP_ADB_AFTER_CLEANING
4102 dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
4109 dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
4110 dns_adbname_t *adbname;
4111 dns_adbname_t *nextname;
4114 INSIST(DNS_ADB_VALID(adb));
4117 bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
4118 LOCK(&adb->namelocks[bucket]);
4119 adbname = ISC_LIST_HEAD(adb->names[bucket]);
4120 while (adbname != NULL) {
4121 nextname = ISC_LIST_NEXT(adbname, plink);
4122 if (!NAME_DEAD(adbname) &&
4123 dns_name_equal(name, &adbname->name)) {
4124 RUNTIME_CHECK(kill_name(&adbname,
4125 DNS_EVENT_ADBCANCELED) ==
4130 UNLOCK(&adb->namelocks[bucket]);
4135 water(void *arg, int mark) {
4137 * We're going to change the way to handle overmem condition: use
4138 * isc_mem_isovermem() instead of storing the state via this callback,
4139 * since the latter way tends to cause race conditions.
4140 * To minimize the change, and in case we re-enable the callback
4141 * approach, however, keep this function at the moment.
4144 dns_adb_t *adb = arg;
4145 isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
4147 REQUIRE(DNS_ADB_VALID(adb));
4149 DP(ISC_LOG_DEBUG(1),
4150 "adb reached %s water mark", overmem ? "high" : "low");
4154 dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) {
4155 isc_uint32_t hiwater;
4156 isc_uint32_t lowater;
4158 INSIST(DNS_ADB_VALID(adb));
4160 if (size != 0U && size < DNS_ADB_MINADBSIZE)
4161 size = DNS_ADB_MINADBSIZE;
4163 hiwater = size - (size >> 3); /* Approximately 7/8ths. */
4164 lowater = size - (size >> 2); /* Approximately 3/4ths. */
4166 if (size == 0U || hiwater == 0U || lowater == 0U)
4167 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
4169 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);