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.
21 * In finds, if task == NULL, no events will be generated, and no events
22 * have been sent. If task != NULL but taskaction == NULL, an event has been
23 * posted but not yet freed. If neither are NULL, no event was posted.
31 #include <isc/mutexblock.h>
32 #include <isc/netaddr.h>
33 #include <isc/random.h>
34 #include <isc/stats.h>
35 #include <isc/string.h> /* Required for HP/UX (and others?) */
41 #include <dns/events.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatastruct.h>
46 #include <dns/rdatatype.h>
47 #include <dns/resolver.h>
48 #include <dns/result.h>
49 #include <dns/stats.h>
51 #define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
52 #define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
53 #define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
54 #define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
55 #define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
56 #define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
57 #define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
58 #define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
59 #define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
60 #define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
61 #define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
62 #define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
63 #define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
64 #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
67 * For type 3 negative cache entries, we will remember that the address is
68 * broken for this long. XXXMLG This is also used for actual addresses, too.
69 * The intent is to keep us from constantly asking about A/AAAA records
70 * if the zone has extremely low TTLs.
72 #define ADB_CACHE_MINIMUM 10 /*%< seconds */
73 #define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
74 #define ADB_ENTRY_WINDOW 1800 /*%< seconds */
77 * The period in seconds after which an ADB name entry is regarded as stale
78 * and forced to be cleaned up.
79 * TODO: This should probably be configurable at run-time.
81 #ifndef ADB_STALE_MARGIN
82 #define ADB_STALE_MARGIN 1800
85 #define FREE_ITEMS 64 /*%< free count for memory pools */
86 #define FILL_COUNT 16 /*%< fill count for memory pools */
88 #define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
90 #define DNS_ADB_MINADBSIZE (1024U*1024U) /*%< 1 Megabyte */
92 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
93 typedef struct dns_adbnamehook dns_adbnamehook_t;
94 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
95 typedef struct dns_adblameinfo dns_adblameinfo_t;
96 typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
97 typedef struct dns_adbfetch dns_adbfetch_t;
98 typedef struct dns_adbfetch6 dns_adbfetch6_t;
100 /*% dns adb structure */
105 isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
106 isc_mutex_t overmemlock; /*%< Covers overmem */
110 isc_taskmgr_t *taskmgr;
114 isc_interval_t tick_interval;
115 int next_cleanbucket;
117 unsigned int irefcnt;
118 unsigned int erefcnt;
121 isc_mempool_t *nmp; /*%< dns_adbname_t */
122 isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
123 isc_mempool_t *limp; /*%< dns_adblameinfo_t */
124 isc_mempool_t *emp; /*%< dns_adbentry_t */
125 isc_mempool_t *ahmp; /*%< dns_adbfind_t */
126 isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
127 isc_mempool_t *afmp; /*%< dns_adbfetch_t */
130 * Bucketized locks and lists for names.
132 * XXXRTH Have a per-bucket structure that contains all of these?
135 isc_mutex_t namescntlock;
136 unsigned int namescnt;
137 dns_adbnamelist_t *names;
138 dns_adbnamelist_t *deadnames;
139 isc_mutex_t *namelocks;
140 isc_boolean_t *name_sd;
141 unsigned int *name_refcnt;
144 * Bucketized locks and lists for entries.
146 * XXXRTH Have a per-bucket structure that contains all of these?
148 unsigned int nentries;
149 isc_mutex_t entriescntlock;
150 unsigned int entriescnt;
151 dns_adbentrylist_t *entries;
152 dns_adbentrylist_t *deadentries;
153 isc_mutex_t *entrylocks;
154 isc_boolean_t *entry_sd; /*%< shutting down */
155 unsigned int *entry_refcnt;
158 isc_boolean_t cevent_out;
159 isc_boolean_t shutting_down;
160 isc_eventlist_t whenshutdown;
161 isc_event_t growentries;
162 isc_boolean_t growentries_sent;
163 isc_event_t grownames;
164 isc_boolean_t grownames_sent;
168 * XXXMLG Document these structures.
171 /*% dns_adbname structure */
176 unsigned int partial_result;
180 isc_stdtime_t expire_target;
181 isc_stdtime_t expire_v4;
182 isc_stdtime_t expire_v6;
184 dns_adbnamehooklist_t v4;
185 dns_adbnamehooklist_t v6;
186 dns_adbfetch_t *fetch_a;
187 dns_adbfetch_t *fetch_aaaa;
188 unsigned int fetch_err;
189 unsigned int fetch6_err;
190 dns_adbfindlist_t finds;
191 /* for LRU-based management */
192 isc_stdtime_t last_used;
194 ISC_LINK(dns_adbname_t) plink;
197 /*% The adbfetch structure */
198 struct dns_adbfetch {
201 dns_rdataset_t rdataset;
206 * This is a small widget that dangles off a dns_adbname_t. It contains a
207 * pointer to the address information about this host, and a link to the next
208 * namehook that will contain the next address this host has.
210 struct dns_adbnamehook {
212 dns_adbentry_t *entry;
213 ISC_LINK(dns_adbnamehook_t) plink;
217 * This is a small widget that holds qname-specific information about an
218 * address. Currently limited to lameness, but could just as easily be
219 * extended to other types of information about zones.
221 struct dns_adblameinfo {
225 dns_rdatatype_t qtype;
226 isc_stdtime_t lame_timer;
228 ISC_LINK(dns_adblameinfo_t) plink;
232 * An address entry. It holds quite a bit of information about addresses,
233 * including edns state (in "flags"), rtt, and of course the address of
236 struct dns_adbentry {
244 isc_sockaddr_t sockaddr;
246 isc_stdtime_t expires;
247 isc_stdtime_t lastage;
249 * A nonzero 'expires' field indicates that the entry should
250 * persist until that time. This allows entries found
251 * using dns_adb_findaddrinfo() to persist for a limited time
252 * even though they are not necessarily associated with a
256 ISC_LIST(dns_adblameinfo_t) lameinfo;
257 ISC_LINK(dns_adbentry_t) plink;
262 * Internal functions (and prototypes).
264 static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
265 static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
266 static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
268 static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
269 static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
271 static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
272 static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
273 static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
274 static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
275 static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
276 static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
278 static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
279 static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
280 static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
281 unsigned int, int *);
282 static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
283 isc_sockaddr_t *, int *,
285 static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
286 static void print_dns_name(FILE *, dns_name_t *);
287 static void print_namehook_list(FILE *, const char *legend,
288 dns_adbnamehooklist_t *list,
291 static void print_find_list(FILE *, dns_adbname_t *);
292 static void print_fetch_list(FILE *, dns_adbname_t *);
293 static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
294 static inline void inc_adb_irefcnt(dns_adb_t *);
295 static inline void inc_adb_erefcnt(dns_adb_t *);
296 static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
298 static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
299 dns_adbentry_t *, isc_boolean_t);
300 static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
301 static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
302 static void clean_target(dns_adb_t *, dns_name_t *);
303 static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
304 static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
305 static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
307 static void cancel_fetches_at_name(dns_adbname_t *);
308 static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
310 static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
311 unsigned int, isc_counter_t *qc,
313 static inline void check_exit(dns_adb_t *);
314 static void destroy(dns_adb_t *);
315 static isc_boolean_t shutdown_names(dns_adb_t *);
316 static isc_boolean_t shutdown_entries(dns_adb_t *);
317 static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
318 static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
319 static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
320 static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
321 static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
322 static void water(void *, int);
323 static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
324 static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt,
325 unsigned int factor, isc_stdtime_t now);
326 static void shutdown_task(isc_task_t *task, isc_event_t *ev);
329 * MUST NOT overlap DNS_ADBFIND_* flags!
331 #define FIND_EVENT_SENT 0x40000000
332 #define FIND_EVENT_FREED 0x80000000
333 #define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
334 #define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
336 #define NAME_NEEDS_POKE 0x80000000
337 #define NAME_IS_DEAD 0x40000000
338 #define NAME_HINT_OK DNS_ADBFIND_HINTOK
339 #define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
340 #define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
341 #define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
342 #define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
343 #define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
344 #define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
347 * Private flag(s) for entries.
348 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
350 #define ENTRY_IS_DEAD 0x00400000
353 * To the name, address classes are all that really exist. If it has a
354 * V6 address it doesn't care if it came from a AAAA query.
356 #define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
357 #define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
358 #define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
361 * Fetches are broken out into A and AAAA types. In some cases,
362 * however, it makes more sense to test for a particular class of fetches,
363 * like V4 or V6 above.
364 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
365 * are now equal to FETCH_V4 and FETCH_V6, respectively.
367 #define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
368 #define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
369 #define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
370 #define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
371 #define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
374 * Find options and tests to see if there are addresses on the list.
376 #define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
377 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
378 #define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
380 #define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
382 #define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
383 #define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
384 #define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
385 #define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
388 * These are currently used on simple unsigned ints, so they are
389 * not really associated with any particular type.
391 #define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
392 #define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
394 #define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
397 * Find out if the flags on a name (nf) indicate if it is a hint or
398 * glue, and compare this to the appropriate bits set in o, to see if
401 #define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
402 #define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
403 #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
404 #define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
405 ((o) & DNS_ADBFIND_STARTATZONE))
407 #define ENTER_LEVEL ISC_LOG_DEBUG(50)
408 #define EXIT_LEVEL ENTER_LEVEL
409 #define CLEAN_LEVEL ISC_LOG_DEBUG(100)
410 #define DEF_LEVEL ISC_LOG_DEBUG(5)
411 #define NCACHE_LEVEL ISC_LOG_DEBUG(20)
413 #define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
414 (r) == DNS_R_NCACHENXRRSET)
415 #define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
416 (r) == DNS_R_NXRRSET)
417 #define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
418 (r) == DNS_R_NCACHENXDOMAIN)
419 #define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
420 (r) == DNS_R_NXRRSET || \
421 (r) == DNS_R_HINTNXRRSET)
424 * Error state rankings.
427 #define FIND_ERR_SUCCESS 0 /* highest rank */
428 #define FIND_ERR_CANCELED 1
429 #define FIND_ERR_FAILURE 2
430 #define FIND_ERR_NXDOMAIN 3
431 #define FIND_ERR_NXRRSET 4
432 #define FIND_ERR_UNEXPECTED 5
433 #define FIND_ERR_NOTFOUND 6
434 #define FIND_ERR_MAX 7
436 static const char *errnames[] = {
446 #define NEWERR(old, new) (ISC_MIN((old), (new)))
448 static isc_result_t find_err_map[FIND_ERR_MAX] = {
455 ISC_R_NOTFOUND /* not YET found */
459 DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
462 DP(int level, const char *format, ...) {
465 va_start(args, format);
466 isc_log_vwrite(dns_lctx,
467 DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
468 level, format, args);
473 * Increment resolver-related statistics counters.
476 inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
477 if (adb->view->resstats != NULL)
478 isc_stats_increment(adb->view->resstats, counter);
481 static inline dns_ttl_t
482 ttlclamp(dns_ttl_t ttl) {
483 if (ttl < ADB_CACHE_MINIMUM)
484 ttl = ADB_CACHE_MINIMUM;
485 if (ttl > ADB_CACHE_MAXIMUM)
486 ttl = ADB_CACHE_MAXIMUM;
492 * Hashing is most efficient if the number of buckets is prime.
493 * The sequence below is the closest previous primes to 2^n and
494 * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
495 * no longer grow beyond 2^28 entries.)
497 static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
498 8191, 12281, 16381, 24571, 32749,
499 49193, 65521, 98299, 131071, 199603,
500 262139, 393209, 524287, 768431, 1048573,
501 1572853, 2097143, 3145721, 4194301,
502 6291449, 8388593, 12582893, 16777213,
503 25165813, 33554393, 50331599, 67108859,
504 100663291, 134217689, 201326557,
508 grow_entries(isc_task_t *task, isc_event_t *ev) {
511 dns_adbentrylist_t *newdeadentries = NULL;
512 dns_adbentrylist_t *newentries = NULL;
513 isc_boolean_t *newentry_sd = NULL;
514 isc_mutex_t *newentrylocks = NULL;
516 unsigned int *newentry_refcnt = NULL;
517 unsigned int i, n, bucket;
520 INSIST(DNS_ADB_VALID(adb));
524 result = isc_task_beginexclusive(task);
525 if (result != ISC_R_SUCCESS)
529 while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
531 if (nbuckets[i] != 0)
536 DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
539 * Are we shutting down?
541 for (i = 0; i < adb->nentries; i++)
542 if (adb->entry_sd[i])
546 * Grab all the resources we need.
548 newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
549 newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
550 newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
551 newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
552 newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
553 if (newentries == NULL || newdeadentries == NULL ||
554 newentrylocks == NULL || newentry_sd == NULL ||
555 newentry_refcnt == NULL)
559 * Initialise the new resources.
561 result = isc_mutexblock_init(newentrylocks, n);
562 if (result != ISC_R_SUCCESS)
565 for (i = 0; i < n; i++) {
566 ISC_LIST_INIT(newentries[i]);
567 ISC_LIST_INIT(newdeadentries[i]);
568 newentry_sd[i] = ISC_FALSE;
569 newentry_refcnt[i] = 0;
574 * Move entries to new arrays.
576 for (i = 0; i < adb->nentries; i++) {
577 e = ISC_LIST_HEAD(adb->entries[i]);
579 ISC_LIST_UNLINK(adb->entries[i], e, plink);
580 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
581 e->lock_bucket = bucket;
582 ISC_LIST_APPEND(newentries[bucket], e, plink);
583 INSIST(adb->entry_refcnt[i] > 0);
584 adb->entry_refcnt[i]--;
585 newentry_refcnt[bucket]++;
586 e = ISC_LIST_HEAD(adb->entries[i]);
588 e = ISC_LIST_HEAD(adb->deadentries[i]);
590 ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
591 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
592 e->lock_bucket = bucket;
593 ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
594 INSIST(adb->entry_refcnt[i] > 0);
595 adb->entry_refcnt[i]--;
596 newentry_refcnt[bucket]++;
597 e = ISC_LIST_HEAD(adb->deadentries[i]);
599 INSIST(adb->entry_refcnt[i] == 0);
604 * Cleanup old resources.
606 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
607 isc_mem_put(adb->mctx, adb->entries,
608 sizeof(*adb->entries) * adb->nentries);
609 isc_mem_put(adb->mctx, adb->deadentries,
610 sizeof(*adb->deadentries) * adb->nentries);
611 isc_mem_put(adb->mctx, adb->entrylocks,
612 sizeof(*adb->entrylocks) * adb->nentries);
613 isc_mem_put(adb->mctx, adb->entry_sd,
614 sizeof(*adb->entry_sd) * adb->nentries);
615 isc_mem_put(adb->mctx, adb->entry_refcnt,
616 sizeof(*adb->entry_refcnt) * adb->nentries);
619 * Install new resources.
621 adb->entries = newentries;
622 adb->deadentries = newdeadentries;
623 adb->entrylocks = newentrylocks;
624 adb->entry_sd = newentry_sd;
625 adb->entry_refcnt = newentry_refcnt;
629 * Only on success do we set adb->growentries_sent to ISC_FALSE.
630 * This will prevent us being continuously being called on error.
632 adb->growentries_sent = ISC_FALSE;
636 if (newentries != NULL)
637 isc_mem_put(adb->mctx, newentries,
638 sizeof(*newentries) * n);
639 if (newdeadentries != NULL)
640 isc_mem_put(adb->mctx, newdeadentries,
641 sizeof(*newdeadentries) * n);
642 if (newentrylocks != NULL)
643 isc_mem_put(adb->mctx, newentrylocks,
644 sizeof(*newentrylocks) * n);
645 if (newentry_sd != NULL)
646 isc_mem_put(adb->mctx, newentry_sd,
647 sizeof(*newentry_sd) * n);
648 if (newentry_refcnt != NULL)
649 isc_mem_put(adb->mctx, newentry_refcnt,
650 sizeof(*newentry_refcnt) * n);
652 isc_task_endexclusive(task);
656 if (dec_adb_irefcnt(adb))
659 DP(ISC_LOG_INFO, "adb: grow_entries finished");
663 grow_names(isc_task_t *task, isc_event_t *ev) {
666 dns_adbnamelist_t *newdeadnames = NULL;
667 dns_adbnamelist_t *newnames = NULL;
668 isc_boolean_t *newname_sd = NULL;
669 isc_mutex_t *newnamelocks = NULL;
671 unsigned int *newname_refcnt = NULL;
672 unsigned int i, n, bucket;
675 INSIST(DNS_ADB_VALID(adb));
679 result = isc_task_beginexclusive(task);
680 if (result != ISC_R_SUCCESS)
684 while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
686 if (nbuckets[i] != 0)
691 DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
694 * Are we shutting down?
696 for (i = 0; i < adb->nnames; i++)
701 * Grab all the resources we need.
703 newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
704 newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
705 newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
706 newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
707 newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
708 if (newnames == NULL || newdeadnames == NULL ||
709 newnamelocks == NULL || newname_sd == NULL ||
710 newname_refcnt == NULL)
714 * Initialise the new resources.
716 result = isc_mutexblock_init(newnamelocks, n);
717 if (result != ISC_R_SUCCESS)
720 for (i = 0; i < n; i++) {
721 ISC_LIST_INIT(newnames[i]);
722 ISC_LIST_INIT(newdeadnames[i]);
723 newname_sd[i] = ISC_FALSE;
724 newname_refcnt[i] = 0;
729 * Move names to new arrays.
731 for (i = 0; i < adb->nnames; i++) {
732 name = ISC_LIST_HEAD(adb->names[i]);
733 while (name != NULL) {
734 ISC_LIST_UNLINK(adb->names[i], name, plink);
735 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
736 name->lock_bucket = bucket;
737 ISC_LIST_APPEND(newnames[bucket], name, plink);
738 INSIST(adb->name_refcnt[i] > 0);
739 adb->name_refcnt[i]--;
740 newname_refcnt[bucket]++;
741 name = ISC_LIST_HEAD(adb->names[i]);
743 name = ISC_LIST_HEAD(adb->deadnames[i]);
744 while (name != NULL) {
745 ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
746 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
747 name->lock_bucket = bucket;
748 ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
749 INSIST(adb->name_refcnt[i] > 0);
750 adb->name_refcnt[i]--;
751 newname_refcnt[bucket]++;
752 name = ISC_LIST_HEAD(adb->deadnames[i]);
754 INSIST(adb->name_refcnt[i] == 0);
759 * Cleanup old resources.
761 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
762 isc_mem_put(adb->mctx, adb->names,
763 sizeof(*adb->names) * adb->nnames);
764 isc_mem_put(adb->mctx, adb->deadnames,
765 sizeof(*adb->deadnames) * adb->nnames);
766 isc_mem_put(adb->mctx, adb->namelocks,
767 sizeof(*adb->namelocks) * adb->nnames);
768 isc_mem_put(adb->mctx, adb->name_sd,
769 sizeof(*adb->name_sd) * adb->nnames);
770 isc_mem_put(adb->mctx, adb->name_refcnt,
771 sizeof(*adb->name_refcnt) * adb->nnames);
774 * Install new resources.
776 adb->names = newnames;
777 adb->deadnames = newdeadnames;
778 adb->namelocks = newnamelocks;
779 adb->name_sd = newname_sd;
780 adb->name_refcnt = newname_refcnt;
784 * Only on success do we set adb->grownames_sent to ISC_FALSE.
785 * This will prevent us being continuously being called on error.
787 adb->grownames_sent = ISC_FALSE;
791 if (newnames != NULL)
792 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
793 if (newdeadnames != NULL)
794 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
795 if (newnamelocks != NULL)
796 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
797 if (newname_sd != NULL)
798 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
799 if (newname_refcnt != NULL)
800 isc_mem_put(adb->mctx, newname_refcnt,
801 sizeof(*newname_refcnt) * n);
803 isc_task_endexclusive(task);
807 if (dec_adb_irefcnt(adb))
810 DP(ISC_LOG_INFO, "adb: grow_names finished");
814 * Requires the adbname bucket be locked and that no entry buckets be locked.
816 * This code handles A and AAAA rdatasets only.
819 import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
824 dns_adbnamehook_t *nh;
825 dns_adbnamehook_t *anh;
826 dns_rdata_t rdata = DNS_RDATA_INIT;
828 struct in6_addr in6a;
829 isc_sockaddr_t sockaddr;
830 dns_adbentry_t *foundentry; /* NO CLEAN UP! */
832 isc_boolean_t new_addresses_added;
833 dns_rdatatype_t rdtype;
834 unsigned int findoptions;
835 dns_adbnamehooklist_t *hookhead;
837 INSIST(DNS_ADBNAME_VALID(adbname));
839 INSIST(DNS_ADB_VALID(adb));
841 rdtype = rdataset->type;
842 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
843 if (rdtype == dns_rdatatype_a)
844 findoptions = DNS_ADBFIND_INET;
846 findoptions = DNS_ADBFIND_INET6;
848 addr_bucket = DNS_ADB_INVALIDBUCKET;
849 new_addresses_added = ISC_FALSE;
852 result = dns_rdataset_first(rdataset);
853 while (result == ISC_R_SUCCESS) {
854 dns_rdata_reset(&rdata);
855 dns_rdataset_current(rdataset, &rdata);
856 if (rdtype == dns_rdatatype_a) {
857 INSIST(rdata.length == 4);
858 memmove(&ina.s_addr, rdata.data, 4);
859 isc_sockaddr_fromin(&sockaddr, &ina, 0);
860 hookhead = &adbname->v4;
862 INSIST(rdata.length == 16);
863 memmove(in6a.s6_addr, rdata.data, 16);
864 isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
865 hookhead = &adbname->v6;
869 nh = new_adbnamehook(adb, NULL);
871 adbname->partial_result |= findoptions;
872 result = ISC_R_NOMEMORY;
876 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
878 if (foundentry == NULL) {
879 dns_adbentry_t *entry;
881 entry = new_adbentry(adb);
883 adbname->partial_result |= findoptions;
884 result = ISC_R_NOMEMORY;
888 entry->sockaddr = sockaddr;
893 link_entry(adb, addr_bucket, entry);
895 for (anh = ISC_LIST_HEAD(*hookhead);
897 anh = ISC_LIST_NEXT(anh, plink))
898 if (anh->entry == foundentry)
901 foundentry->refcnt++;
902 nh->entry = foundentry;
904 free_adbnamehook(adb, &nh);
907 new_addresses_added = ISC_TRUE;
909 ISC_LIST_APPEND(*hookhead, nh, plink);
911 result = dns_rdataset_next(rdataset);
916 free_adbnamehook(adb, &nh);
918 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
919 UNLOCK(&adb->entrylocks[addr_bucket]);
921 if (rdataset->trust == dns_trust_glue ||
922 rdataset->trust == dns_trust_additional)
923 rdataset->ttl = ADB_CACHE_MINIMUM;
924 else if (rdataset->trust == dns_trust_ultimate)
927 rdataset->ttl = ttlclamp(rdataset->ttl);
929 if (rdtype == dns_rdatatype_a) {
930 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
931 adbname->expire_v4, now + rdataset->ttl);
932 adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
933 now + rdataset->ttl);
935 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
936 adbname->expire_v6, now + rdataset->ttl);
937 adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
938 now + rdataset->ttl);
941 if (new_addresses_added) {
943 * Lie a little here. This is more or less so code that cares
944 * can find out if any new information was added or not.
946 return (ISC_R_SUCCESS);
953 * Requires the name's bucket be locked.
956 kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
958 isc_boolean_t result = ISC_FALSE;
959 isc_boolean_t result4, result6;
966 INSIST(DNS_ADBNAME_VALID(name));
968 INSIST(DNS_ADB_VALID(adb));
970 DP(DEF_LEVEL, "killing name %p", name);
973 * If we're dead already, just check to see if we should go
976 if (NAME_DEAD(name) && !NAME_FETCH(name)) {
977 result = unlink_name(adb, name);
978 free_adbname(adb, &name);
980 result = dec_adb_irefcnt(adb);
985 * Clean up the name's various lists. These two are destructive
986 * in that they will always empty the list.
988 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
989 result4 = clean_namehooks(adb, &name->v4);
990 result6 = clean_namehooks(adb, &name->v6);
991 clean_target(adb, &name->target);
992 result = ISC_TF(result4 || result6);
995 * If fetches are running, cancel them. If none are running, we can
996 * just kill the name here.
998 if (!NAME_FETCH(name)) {
999 INSIST(result == ISC_FALSE);
1000 result = unlink_name(adb, name);
1001 free_adbname(adb, &name);
1003 result = dec_adb_irefcnt(adb);
1005 cancel_fetches_at_name(name);
1006 if (!NAME_DEAD(name)) {
1007 bucket = name->lock_bucket;
1008 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1009 ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
1010 name->flags |= NAME_IS_DEAD;
1017 * Requires the name's bucket be locked and no entry buckets be locked.
1019 static isc_boolean_t
1020 check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
1022 isc_boolean_t result4 = ISC_FALSE;
1023 isc_boolean_t result6 = ISC_FALSE;
1025 INSIST(DNS_ADBNAME_VALID(name));
1027 INSIST(DNS_ADB_VALID(adb));
1030 * Check to see if we need to remove the v4 addresses
1032 if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
1033 if (NAME_HAS_V4(name)) {
1034 DP(DEF_LEVEL, "expiring v4 for name %p", name);
1035 result4 = clean_namehooks(adb, &name->v4);
1036 name->partial_result &= ~DNS_ADBFIND_INET;
1038 name->expire_v4 = INT_MAX;
1039 name->fetch_err = FIND_ERR_UNEXPECTED;
1043 * Check to see if we need to remove the v6 addresses
1045 if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
1046 if (NAME_HAS_V6(name)) {
1047 DP(DEF_LEVEL, "expiring v6 for name %p", name);
1048 result6 = clean_namehooks(adb, &name->v6);
1049 name->partial_result &= ~DNS_ADBFIND_INET6;
1051 name->expire_v6 = INT_MAX;
1052 name->fetch6_err = FIND_ERR_UNEXPECTED;
1056 * Check to see if we need to remove the alias target.
1058 if (EXPIRE_OK(name->expire_target, now)) {
1059 clean_target(adb, &name->target);
1060 name->expire_target = INT_MAX;
1062 return (ISC_TF(result4 || result6));
1066 * Requires the name's bucket be locked.
1069 link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1070 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
1072 ISC_LIST_PREPEND(adb->names[bucket], name, plink);
1073 name->lock_bucket = bucket;
1074 adb->name_refcnt[bucket]++;
1078 * Requires the name's bucket be locked.
1080 static inline isc_boolean_t
1081 unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
1083 isc_boolean_t result = ISC_FALSE;
1085 bucket = name->lock_bucket;
1086 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1088 if (NAME_DEAD(name))
1089 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
1091 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1092 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1093 INSIST(adb->name_refcnt[bucket] > 0);
1094 adb->name_refcnt[bucket]--;
1095 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
1101 * Requires the entry's bucket be locked.
1104 link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
1108 if (isc_mem_isovermem(adb->mctx)) {
1109 for (i = 0; i < 2; i++) {
1110 e = ISC_LIST_TAIL(adb->entries[bucket]);
1113 if (e->refcnt == 0) {
1114 unlink_entry(adb, e);
1115 free_adbentry(adb, &e);
1118 INSIST((e->flags & ENTRY_IS_DEAD) == 0);
1119 e->flags |= ENTRY_IS_DEAD;
1120 ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
1121 ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
1125 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
1126 entry->lock_bucket = bucket;
1127 adb->entry_refcnt[bucket]++;
1131 * Requires the entry's bucket be locked.
1133 static inline isc_boolean_t
1134 unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
1136 isc_boolean_t result = ISC_FALSE;
1138 bucket = entry->lock_bucket;
1139 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1141 if ((entry->flags & ENTRY_IS_DEAD) != 0)
1142 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
1144 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
1145 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1146 INSIST(adb->entry_refcnt[bucket] > 0);
1147 adb->entry_refcnt[bucket]--;
1148 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
1154 violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
1155 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
1163 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1164 * checked after calling this function.
1166 static isc_boolean_t
1167 shutdown_names(dns_adb_t *adb) {
1168 unsigned int bucket;
1169 isc_boolean_t result = ISC_FALSE;
1170 dns_adbname_t *name;
1171 dns_adbname_t *next_name;
1173 for (bucket = 0; bucket < adb->nnames; bucket++) {
1174 LOCK(&adb->namelocks[bucket]);
1175 adb->name_sd[bucket] = ISC_TRUE;
1177 name = ISC_LIST_HEAD(adb->names[bucket]);
1180 * This bucket has no names. We must decrement the
1181 * irefcnt ourselves, since it will not be
1182 * automatically triggered by a name being unlinked.
1184 INSIST(result == ISC_FALSE);
1185 result = dec_adb_irefcnt(adb);
1188 * Run through the list. For each name, clean up finds
1189 * found there, and cancel any fetches running. When
1190 * all the fetches are canceled, the name will destroy
1193 while (name != NULL) {
1194 next_name = ISC_LIST_NEXT(name, plink);
1195 INSIST(result == ISC_FALSE);
1196 result = kill_name(&name,
1197 DNS_EVENT_ADBSHUTDOWN);
1202 UNLOCK(&adb->namelocks[bucket]);
1208 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1209 * checked after calling this function.
1211 static isc_boolean_t
1212 shutdown_entries(dns_adb_t *adb) {
1213 unsigned int bucket;
1214 isc_boolean_t result = ISC_FALSE;
1215 dns_adbentry_t *entry;
1216 dns_adbentry_t *next_entry;
1218 for (bucket = 0; bucket < adb->nentries; bucket++) {
1219 LOCK(&adb->entrylocks[bucket]);
1220 adb->entry_sd[bucket] = ISC_TRUE;
1222 entry = ISC_LIST_HEAD(adb->entries[bucket]);
1223 if (adb->entry_refcnt[bucket] == 0) {
1225 * This bucket has no entries. We must decrement the
1226 * irefcnt ourselves, since it will not be
1227 * automatically triggered by an entry being unlinked.
1229 result = dec_adb_irefcnt(adb);
1232 * Run through the list. Cleanup any entries not
1233 * associated with names, and which are not in use.
1235 while (entry != NULL) {
1236 next_entry = ISC_LIST_NEXT(entry, plink);
1237 if (entry->refcnt == 0 &&
1238 entry->expires != 0) {
1239 result = unlink_entry(adb, entry);
1240 free_adbentry(adb, &entry);
1242 result = dec_adb_irefcnt(adb);
1248 UNLOCK(&adb->entrylocks[bucket]);
1254 * Name bucket must be locked
1257 cancel_fetches_at_name(dns_adbname_t *name) {
1258 if (NAME_FETCH_A(name))
1259 dns_resolver_cancelfetch(name->fetch_a->fetch);
1261 if (NAME_FETCH_AAAA(name))
1262 dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
1266 * Assumes the name bucket is locked.
1268 static isc_boolean_t
1269 clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
1270 dns_adbentry_t *entry;
1271 dns_adbnamehook_t *namehook;
1273 isc_boolean_t result = ISC_FALSE;
1274 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
1276 addr_bucket = DNS_ADB_INVALIDBUCKET;
1277 namehook = ISC_LIST_HEAD(*namehooks);
1278 while (namehook != NULL) {
1279 INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
1282 * Clean up the entry if needed.
1284 entry = namehook->entry;
1285 if (entry != NULL) {
1286 INSIST(DNS_ADBENTRY_VALID(entry));
1288 if (addr_bucket != entry->lock_bucket) {
1289 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1290 UNLOCK(&adb->entrylocks[addr_bucket]);
1291 addr_bucket = entry->lock_bucket;
1292 INSIST(addr_bucket != DNS_ADB_INVALIDBUCKET);
1293 LOCK(&adb->entrylocks[addr_bucket]);
1296 result = dec_entry_refcnt(adb, overmem, entry,
1303 namehook->entry = NULL;
1304 ISC_LIST_UNLINK(*namehooks, namehook, plink);
1305 free_adbnamehook(adb, &namehook);
1307 namehook = ISC_LIST_HEAD(*namehooks);
1310 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1311 UNLOCK(&adb->entrylocks[addr_bucket]);
1316 clean_target(dns_adb_t *adb, dns_name_t *target) {
1317 if (dns_name_countlabels(target) > 0) {
1318 dns_name_free(target, adb->mctx);
1319 dns_name_init(target, NULL);
1324 set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
1325 dns_rdataset_t *rdataset, dns_name_t *target)
1327 isc_result_t result;
1328 dns_namereln_t namereln;
1329 unsigned int nlabels;
1331 dns_rdata_t rdata = DNS_RDATA_INIT;
1332 dns_fixedname_t fixed1, fixed2;
1333 dns_name_t *prefix, *new_target;
1335 REQUIRE(dns_name_countlabels(target) == 0);
1337 if (rdataset->type == dns_rdatatype_cname) {
1338 dns_rdata_cname_t cname;
1341 * Copy the CNAME's target into the target name.
1343 result = dns_rdataset_first(rdataset);
1344 if (result != ISC_R_SUCCESS)
1346 dns_rdataset_current(rdataset, &rdata);
1347 result = dns_rdata_tostruct(&rdata, &cname, NULL);
1348 if (result != ISC_R_SUCCESS)
1350 result = dns_name_dup(&cname.cname, adb->mctx, target);
1351 dns_rdata_freestruct(&cname);
1352 if (result != ISC_R_SUCCESS)
1355 dns_rdata_dname_t dname;
1357 INSIST(rdataset->type == dns_rdatatype_dname);
1358 namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
1359 INSIST(namereln == dns_namereln_subdomain);
1361 * Get the target name of the DNAME.
1363 result = dns_rdataset_first(rdataset);
1364 if (result != ISC_R_SUCCESS)
1366 dns_rdataset_current(rdataset, &rdata);
1367 result = dns_rdata_tostruct(&rdata, &dname, NULL);
1368 if (result != ISC_R_SUCCESS)
1371 * Construct the new target name.
1373 dns_fixedname_init(&fixed1);
1374 prefix = dns_fixedname_name(&fixed1);
1375 dns_fixedname_init(&fixed2);
1376 new_target = dns_fixedname_name(&fixed2);
1377 dns_name_split(name, nlabels, prefix, NULL);
1378 result = dns_name_concatenate(prefix, &dname.dname, new_target,
1380 dns_rdata_freestruct(&dname);
1381 if (result != ISC_R_SUCCESS)
1383 result = dns_name_dup(new_target, adb->mctx, target);
1384 if (result != ISC_R_SUCCESS)
1388 return (ISC_R_SUCCESS);
1392 * Assumes nothing is locked, since this is called by the client.
1395 event_free(isc_event_t *event) {
1396 dns_adbfind_t *find;
1398 INSIST(event != NULL);
1399 find = event->ev_destroy_arg;
1400 INSIST(DNS_ADBFIND_VALID(find));
1403 find->flags |= FIND_EVENT_FREED;
1404 event->ev_destroy_arg = NULL;
1405 UNLOCK(&find->lock);
1409 * Assumes the name bucket is locked.
1412 clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
1417 dns_adbfind_t *find;
1418 dns_adbfind_t *next_find;
1419 isc_boolean_t process;
1420 unsigned int wanted, notify;
1423 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1424 name, evtype, addrs);
1426 find = ISC_LIST_HEAD(name->finds);
1427 while (find != NULL) {
1429 next_find = ISC_LIST_NEXT(find, plink);
1431 process = ISC_FALSE;
1432 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1433 notify = wanted & addrs;
1436 case DNS_EVENT_ADBMOREADDRESSES:
1437 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1438 if ((notify) != 0) {
1439 find->flags &= ~addrs;
1443 case DNS_EVENT_ADBNOMOREADDRESSES:
1444 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1445 find->flags &= ~addrs;
1446 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1451 find->flags &= ~addrs;
1456 DP(DEF_LEVEL, "cfan: processing find %p", find);
1458 * Unlink the find from the name, letting the caller
1459 * call dns_adb_destroyfind() on it to clean it up
1462 ISC_LIST_UNLINK(name->finds, find, plink);
1463 find->adbname = NULL;
1464 find->name_bucket = DNS_ADB_INVALIDBUCKET;
1466 INSIST(!FIND_EVENTSENT(find));
1469 task = ev->ev_sender;
1470 ev->ev_sender = find;
1471 find->result_v4 = find_err_map[name->fetch_err];
1472 find->result_v6 = find_err_map[name->fetch6_err];
1473 ev->ev_type = evtype;
1474 ev->ev_destroy = event_free;
1475 ev->ev_destroy_arg = find;
1478 "sending event %p to task %p for find %p",
1481 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
1483 DP(DEF_LEVEL, "cfan: skipping find %p", find);
1486 UNLOCK(&find->lock);
1490 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
1494 check_exit(dns_adb_t *adb) {
1497 * The caller must be holding the adb lock.
1499 if (adb->shutting_down) {
1501 * If there aren't any external references either, we're
1502 * done. Send the control event to initiate shutdown.
1504 INSIST(!adb->cevent_out); /* Sanity check. */
1505 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
1506 DNS_EVENT_ADBCONTROL, shutdown_task, adb,
1508 event = &adb->cevent;
1509 isc_task_send(adb->task, &event);
1510 adb->cevent_out = ISC_TRUE;
1514 static inline isc_boolean_t
1515 dec_adb_irefcnt(dns_adb_t *adb) {
1518 isc_boolean_t result = ISC_FALSE;
1520 LOCK(&adb->reflock);
1522 INSIST(adb->irefcnt > 0);
1525 if (adb->irefcnt == 0) {
1526 event = ISC_LIST_HEAD(adb->whenshutdown);
1527 while (event != NULL) {
1528 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
1529 etask = event->ev_sender;
1530 event->ev_sender = adb;
1531 isc_task_sendanddetach(&etask, &event);
1532 event = ISC_LIST_HEAD(adb->whenshutdown);
1536 if (adb->irefcnt == 0 && adb->erefcnt == 0)
1538 UNLOCK(&adb->reflock);
1543 inc_adb_irefcnt(dns_adb_t *adb) {
1544 LOCK(&adb->reflock);
1546 UNLOCK(&adb->reflock);
1550 inc_adb_erefcnt(dns_adb_t *adb) {
1551 LOCK(&adb->reflock);
1553 UNLOCK(&adb->reflock);
1557 inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
1560 bucket = entry->lock_bucket;
1563 LOCK(&adb->entrylocks[bucket]);
1568 UNLOCK(&adb->entrylocks[bucket]);
1571 static inline isc_boolean_t
1572 dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
1576 isc_boolean_t destroy_entry;
1577 isc_boolean_t result = ISC_FALSE;
1579 bucket = entry->lock_bucket;
1582 LOCK(&adb->entrylocks[bucket]);
1584 INSIST(entry->refcnt > 0);
1587 destroy_entry = ISC_FALSE;
1588 if (entry->refcnt == 0 &&
1589 (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
1590 (entry->flags & ENTRY_IS_DEAD) != 0)) {
1591 destroy_entry = ISC_TRUE;
1592 result = unlink_entry(adb, entry);
1596 UNLOCK(&adb->entrylocks[bucket]);
1601 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1603 free_adbentry(adb, &entry);
1605 result = dec_adb_irefcnt(adb);
1610 static inline dns_adbname_t *
1611 new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
1612 dns_adbname_t *name;
1614 name = isc_mempool_get(adb->nmp);
1618 dns_name_init(&name->name, NULL);
1619 if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
1620 isc_mempool_put(adb->nmp, name);
1623 dns_name_init(&name->target, NULL);
1624 name->magic = DNS_ADBNAME_MAGIC;
1626 name->partial_result = 0;
1628 name->expire_v4 = INT_MAX;
1629 name->expire_v6 = INT_MAX;
1630 name->expire_target = INT_MAX;
1632 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1633 ISC_LIST_INIT(name->v4);
1634 ISC_LIST_INIT(name->v6);
1635 name->fetch_a = NULL;
1636 name->fetch_aaaa = NULL;
1637 name->fetch_err = FIND_ERR_UNEXPECTED;
1638 name->fetch6_err = FIND_ERR_UNEXPECTED;
1639 ISC_LIST_INIT(name->finds);
1640 ISC_LINK_INIT(name, plink);
1642 LOCK(&adb->namescntlock);
1644 if (!adb->grownames_sent && adb->excl != NULL &&
1645 adb->namescnt > (adb->nnames * 8))
1647 isc_event_t *event = &adb->grownames;
1648 inc_adb_irefcnt(adb);
1649 isc_task_send(adb->excl, &event);
1650 adb->grownames_sent = ISC_TRUE;
1652 UNLOCK(&adb->namescntlock);
1658 free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
1661 INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
1665 INSIST(!NAME_HAS_V4(n));
1666 INSIST(!NAME_HAS_V6(n));
1667 INSIST(!NAME_FETCH(n));
1668 INSIST(ISC_LIST_EMPTY(n->finds));
1669 INSIST(!ISC_LINK_LINKED(n, plink));
1670 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
1671 INSIST(n->adb == adb);
1674 dns_name_free(&n->name, adb->mctx);
1676 isc_mempool_put(adb->nmp, n);
1677 LOCK(&adb->namescntlock);
1679 UNLOCK(&adb->namescntlock);
1682 static inline dns_adbnamehook_t *
1683 new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
1684 dns_adbnamehook_t *nh;
1686 nh = isc_mempool_get(adb->nhmp);
1690 nh->magic = DNS_ADBNAMEHOOK_MAGIC;
1692 ISC_LINK_INIT(nh, plink);
1698 free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
1699 dns_adbnamehook_t *nh;
1701 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
1705 INSIST(nh->entry == NULL);
1706 INSIST(!ISC_LINK_LINKED(nh, plink));
1709 isc_mempool_put(adb->nhmp, nh);
1712 static inline dns_adblameinfo_t *
1713 new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
1714 dns_adblameinfo_t *li;
1716 li = isc_mempool_get(adb->limp);
1720 dns_name_init(&li->qname, NULL);
1721 if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
1722 isc_mempool_put(adb->limp, li);
1725 li->magic = DNS_ADBLAMEINFO_MAGIC;
1728 ISC_LINK_INIT(li, plink);
1734 free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
1735 dns_adblameinfo_t *li;
1737 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
1741 INSIST(!ISC_LINK_LINKED(li, plink));
1743 dns_name_free(&li->qname, adb->mctx);
1747 isc_mempool_put(adb->limp, li);
1750 static inline dns_adbentry_t *
1751 new_adbentry(dns_adb_t *adb) {
1755 e = isc_mempool_get(adb->emp);
1759 e->magic = DNS_ADBENTRY_MAGIC;
1760 e->lock_bucket = DNS_ADB_INVALIDBUCKET;
1764 e->srtt = (r & 0x1f) + 1;
1767 ISC_LIST_INIT(e->lameinfo);
1768 ISC_LINK_INIT(e, plink);
1769 LOCK(&adb->entriescntlock);
1771 if (!adb->growentries_sent && adb->growentries_sent &&
1772 adb->entriescnt > (adb->nentries * 8))
1774 isc_event_t *event = &adb->growentries;
1775 inc_adb_irefcnt(adb);
1776 isc_task_send(adb->task, &event);
1777 adb->growentries_sent = ISC_TRUE;
1779 UNLOCK(&adb->entriescntlock);
1785 free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
1787 dns_adblameinfo_t *li;
1789 INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
1793 INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
1794 INSIST(e->refcnt == 0);
1795 INSIST(!ISC_LINK_LINKED(e, plink));
1799 li = ISC_LIST_HEAD(e->lameinfo);
1800 while (li != NULL) {
1801 ISC_LIST_UNLINK(e->lameinfo, li, plink);
1802 free_adblameinfo(adb, &li);
1803 li = ISC_LIST_HEAD(e->lameinfo);
1806 isc_mempool_put(adb->emp, e);
1807 LOCK(&adb->entriescntlock);
1809 UNLOCK(&adb->entriescntlock);
1812 static inline dns_adbfind_t *
1813 new_adbfind(dns_adb_t *adb) {
1815 isc_result_t result;
1817 h = isc_mempool_get(adb->ahmp);
1826 h->partial_result = 0;
1829 h->result_v4 = ISC_R_UNEXPECTED;
1830 h->result_v6 = ISC_R_UNEXPECTED;
1831 ISC_LINK_INIT(h, publink);
1832 ISC_LINK_INIT(h, plink);
1833 ISC_LIST_INIT(h->list);
1835 h->name_bucket = DNS_ADB_INVALIDBUCKET;
1840 result = isc_mutex_init(&h->lock);
1841 if (result != ISC_R_SUCCESS) {
1842 isc_mempool_put(adb->ahmp, h);
1846 ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
1849 inc_adb_irefcnt(adb);
1850 h->magic = DNS_ADBFIND_MAGIC;
1854 static inline dns_adbfetch_t *
1855 new_adbfetch(dns_adb_t *adb) {
1858 f = isc_mempool_get(adb->afmp);
1865 dns_rdataset_init(&f->rdataset);
1867 f->magic = DNS_ADBFETCH_MAGIC;
1873 free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
1876 INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
1882 if (dns_rdataset_isassociated(&f->rdataset))
1883 dns_rdataset_disassociate(&f->rdataset);
1885 isc_mempool_put(adb->afmp, f);
1888 static inline isc_boolean_t
1889 free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
1890 dns_adbfind_t *find;
1892 INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
1896 INSIST(!FIND_HAS_ADDRS(find));
1897 INSIST(!ISC_LINK_LINKED(find, publink));
1898 INSIST(!ISC_LINK_LINKED(find, plink));
1899 INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
1900 INSIST(find->adbname == NULL);
1904 DESTROYLOCK(&find->lock);
1905 isc_mempool_put(adb->ahmp, find);
1906 return (dec_adb_irefcnt(adb));
1910 * Copy bits from the entry into the newly allocated addrinfo. The entry
1911 * must be locked, and the reference count must be bumped up by one
1912 * if this function returns a valid pointer.
1914 static inline dns_adbaddrinfo_t *
1915 new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
1916 dns_adbaddrinfo_t *ai;
1918 ai = isc_mempool_get(adb->aimp);
1922 ai->magic = DNS_ADBADDRINFO_MAGIC;
1923 ai->sockaddr = entry->sockaddr;
1924 isc_sockaddr_setport(&ai->sockaddr, port);
1925 ai->srtt = entry->srtt;
1926 ai->flags = entry->flags;
1928 ISC_LINK_INIT(ai, publink);
1934 free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
1935 dns_adbaddrinfo_t *ai;
1937 INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
1941 INSIST(ai->entry == NULL);
1942 INSIST(!ISC_LINK_LINKED(ai, publink));
1946 isc_mempool_put(adb->aimp, ai);
1950 * Search for the name. NOTE: The bucket is kept locked on both
1951 * success and failure, so it must always be unlocked by the caller!
1953 * On the first call to this function, *bucketp must be set to
1954 * DNS_ADB_INVALIDBUCKET.
1956 static inline dns_adbname_t *
1957 find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
1958 unsigned int options, int *bucketp)
1960 dns_adbname_t *adbname;
1963 bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
1965 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
1966 LOCK(&adb->namelocks[bucket]);
1968 } else if (*bucketp != bucket) {
1969 UNLOCK(&adb->namelocks[*bucketp]);
1970 LOCK(&adb->namelocks[bucket]);
1974 adbname = ISC_LIST_HEAD(adb->names[bucket]);
1975 while (adbname != NULL) {
1976 if (!NAME_DEAD(adbname)) {
1977 if (dns_name_equal(name, &adbname->name)
1978 && GLUEHINT_OK(adbname, options)
1979 && STARTATZONE_MATCHES(adbname, options))
1982 adbname = ISC_LIST_NEXT(adbname, plink);
1989 * Search for the address. NOTE: The bucket is kept locked on both
1990 * success and failure, so it must always be unlocked by the caller.
1992 * On the first call to this function, *bucketp must be set to
1993 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
1994 * later calls (within the same "lock path") it can be left alone, so
1995 * if this function is called multiple times locking is only done if
1996 * the bucket changes.
1998 static inline dns_adbentry_t *
1999 find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
2002 dns_adbentry_t *entry, *entry_next;
2005 bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
2007 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
2008 LOCK(&adb->entrylocks[bucket]);
2010 } else if (*bucketp != bucket) {
2011 UNLOCK(&adb->entrylocks[*bucketp]);
2012 LOCK(&adb->entrylocks[bucket]);
2016 /* Search the list, while cleaning up expired entries. */
2017 for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
2019 entry = entry_next) {
2020 entry_next = ISC_LIST_NEXT(entry, plink);
2021 (void)check_expire_entry(adb, &entry, now);
2022 if (entry != NULL &&
2023 isc_sockaddr_equal(addr, &entry->sockaddr)) {
2024 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
2025 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
2034 * Entry bucket MUST be locked!
2036 static isc_boolean_t
2037 entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
2038 dns_rdatatype_t qtype, isc_stdtime_t now)
2040 dns_adblameinfo_t *li, *next_li;
2041 isc_boolean_t is_bad;
2045 li = ISC_LIST_HEAD(entry->lameinfo);
2048 while (li != NULL) {
2049 next_li = ISC_LIST_NEXT(li, plink);
2052 * Has the entry expired?
2054 if (li->lame_timer < now) {
2055 ISC_LIST_UNLINK(entry->lameinfo, li, plink);
2056 free_adblameinfo(adb, &li);
2060 * Order tests from least to most expensive.
2062 * We do not break out of the main loop here as
2063 * we use the loop for house keeping.
2065 if (li != NULL && !is_bad && li->qtype == qtype &&
2066 dns_name_equal(qname, &li->qname))
2076 copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
2077 dns_rdatatype_t qtype, dns_adbname_t *name,
2080 dns_adbnamehook_t *namehook;
2081 dns_adbaddrinfo_t *addrinfo;
2082 dns_adbentry_t *entry;
2085 bucket = DNS_ADB_INVALIDBUCKET;
2087 if (find->options & DNS_ADBFIND_INET) {
2088 namehook = ISC_LIST_HEAD(name->v4);
2089 while (namehook != NULL) {
2090 entry = namehook->entry;
2091 bucket = entry->lock_bucket;
2092 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2093 LOCK(&adb->entrylocks[bucket]);
2095 if (!FIND_RETURNLAME(find)
2096 && entry_is_lame(adb, entry, qname, qtype, now)) {
2097 find->options |= DNS_ADBFIND_LAMEPRUNED;
2100 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2101 if (addrinfo == NULL) {
2102 find->partial_result |= DNS_ADBFIND_INET;
2106 * Found a valid entry. Add it to the find's list.
2108 inc_entry_refcnt(adb, entry, ISC_FALSE);
2109 ISC_LIST_APPEND(find->list, addrinfo, publink);
2112 UNLOCK(&adb->entrylocks[bucket]);
2113 bucket = DNS_ADB_INVALIDBUCKET;
2114 namehook = ISC_LIST_NEXT(namehook, plink);
2118 if (find->options & DNS_ADBFIND_INET6) {
2119 namehook = ISC_LIST_HEAD(name->v6);
2120 while (namehook != NULL) {
2121 entry = namehook->entry;
2122 bucket = entry->lock_bucket;
2123 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2124 LOCK(&adb->entrylocks[bucket]);
2126 if (!FIND_RETURNLAME(find)
2127 && entry_is_lame(adb, entry, qname, qtype, now)) {
2128 find->options |= DNS_ADBFIND_LAMEPRUNED;
2131 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2132 if (addrinfo == NULL) {
2133 find->partial_result |= DNS_ADBFIND_INET6;
2137 * Found a valid entry. Add it to the find's list.
2139 inc_entry_refcnt(adb, entry, ISC_FALSE);
2140 ISC_LIST_APPEND(find->list, addrinfo, publink);
2143 UNLOCK(&adb->entrylocks[bucket]);
2144 bucket = DNS_ADB_INVALIDBUCKET;
2145 namehook = ISC_LIST_NEXT(namehook, plink);
2150 if (bucket != DNS_ADB_INVALIDBUCKET)
2151 UNLOCK(&adb->entrylocks[bucket]);
2155 shutdown_task(isc_task_t *task, isc_event_t *ev) {
2161 INSIST(DNS_ADB_VALID(adb));
2163 isc_event_free(&ev);
2165 * Wait for lock around check_exit() call to be released.
2173 * Name bucket must be locked; adb may be locked; no other locks held.
2175 static isc_boolean_t
2176 check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
2177 dns_adbname_t *name;
2178 isc_boolean_t result = ISC_FALSE;
2180 INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
2183 if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
2185 if (NAME_FETCH(name))
2187 if (!EXPIRE_OK(name->expire_v4, now))
2189 if (!EXPIRE_OK(name->expire_v6, now))
2191 if (!EXPIRE_OK(name->expire_target, now))
2195 * The name is empty. Delete it.
2197 result = kill_name(&name, DNS_EVENT_ADBEXPIRED);
2201 * Our caller, or one of its callers, will be calling check_exit() at
2202 * some point, so we don't need to do it here.
2208 * Examine the tail entry of the LRU list to see if it expires or is stale
2209 * (unused for some period); if so, the name entry will be freed. If the ADB
2210 * is in the overmem condition, the tail and the next to tail entries
2211 * will be unconditionally removed (unless they have an outstanding fetch).
2212 * We don't care about a race on 'overmem' at the risk of causing some
2213 * collateral damage or a small delay in starting cleanup, so we don't bother
2214 * to lock ADB (if it's not locked).
2216 * Name bucket must be locked; adb may be locked; no other locks held.
2219 check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2220 int victims, max_victims;
2221 dns_adbname_t *victim, *next_victim;
2222 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
2225 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2227 max_victims = overmem ? 2 : 1;
2230 * We limit the number of scanned entries to 10 (arbitrary choice)
2231 * in order to avoid examining too many entries when there are many
2232 * tail entries that have fetches (this should be rare, but could
2235 victim = ISC_LIST_TAIL(adb->names[bucket]);
2237 victim != NULL && victims < max_victims && scans < 10;
2238 victim = next_victim) {
2239 INSIST(!NAME_DEAD(victim));
2241 next_victim = ISC_LIST_PREV(victim, plink);
2242 (void)check_expire_name(&victim, now);
2243 if (victim == NULL) {
2248 if (!NAME_FETCH(victim) &&
2249 (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
2250 RUNTIME_CHECK(kill_name(&victim,
2251 DNS_EVENT_ADBCANCELED) ==
2263 * Entry bucket must be locked; adb may be locked; no other locks held.
2265 static isc_boolean_t
2266 check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
2268 dns_adbentry_t *entry;
2269 isc_boolean_t result = ISC_FALSE;
2271 INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
2274 if (entry->refcnt != 0)
2277 if (entry->expires == 0 || entry->expires > now)
2281 * The entry is not in use. Delete it.
2283 DP(DEF_LEVEL, "killing entry %p", entry);
2284 INSIST(ISC_LINK_LINKED(entry, plink));
2285 result = unlink_entry(adb, entry);
2286 free_adbentry(adb, &entry);
2288 dec_adb_irefcnt(adb);
2294 * ADB must be locked, and no other locks held.
2296 static isc_boolean_t
2297 cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2298 dns_adbname_t *name;
2299 dns_adbname_t *next_name;
2300 isc_boolean_t result = ISC_FALSE;
2302 DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
2304 LOCK(&adb->namelocks[bucket]);
2305 if (adb->name_sd[bucket]) {
2306 UNLOCK(&adb->namelocks[bucket]);
2310 name = ISC_LIST_HEAD(adb->names[bucket]);
2311 while (name != NULL) {
2312 next_name = ISC_LIST_NEXT(name, plink);
2313 INSIST(result == ISC_FALSE);
2314 result = check_expire_namehooks(name, now);
2316 result = check_expire_name(&name, now);
2319 UNLOCK(&adb->namelocks[bucket]);
2324 * ADB must be locked, and no other locks held.
2326 static isc_boolean_t
2327 cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2328 dns_adbentry_t *entry, *next_entry;
2329 isc_boolean_t result = ISC_FALSE;
2331 DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
2333 LOCK(&adb->entrylocks[bucket]);
2334 entry = ISC_LIST_HEAD(adb->entries[bucket]);
2335 while (entry != NULL) {
2336 next_entry = ISC_LIST_NEXT(entry, plink);
2337 INSIST(result == ISC_FALSE);
2338 result = check_expire_entry(adb, &entry, now);
2341 UNLOCK(&adb->entrylocks[bucket]);
2346 destroy(dns_adb_t *adb) {
2349 isc_task_detach(&adb->task);
2350 if (adb->excl != NULL)
2351 isc_task_detach(&adb->excl);
2353 isc_mempool_destroy(&adb->nmp);
2354 isc_mempool_destroy(&adb->nhmp);
2355 isc_mempool_destroy(&adb->limp);
2356 isc_mempool_destroy(&adb->emp);
2357 isc_mempool_destroy(&adb->ahmp);
2358 isc_mempool_destroy(&adb->aimp);
2359 isc_mempool_destroy(&adb->afmp);
2361 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2362 isc_mem_put(adb->mctx, adb->entries,
2363 sizeof(*adb->entries) * adb->nentries);
2364 isc_mem_put(adb->mctx, adb->deadentries,
2365 sizeof(*adb->deadentries) * adb->nentries);
2366 isc_mem_put(adb->mctx, adb->entrylocks,
2367 sizeof(*adb->entrylocks) * adb->nentries);
2368 isc_mem_put(adb->mctx, adb->entry_sd,
2369 sizeof(*adb->entry_sd) * adb->nentries);
2370 isc_mem_put(adb->mctx, adb->entry_refcnt,
2371 sizeof(*adb->entry_refcnt) * adb->nentries);
2373 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2374 isc_mem_put(adb->mctx, adb->names,
2375 sizeof(*adb->names) * adb->nnames);
2376 isc_mem_put(adb->mctx, adb->deadnames,
2377 sizeof(*adb->deadnames) * adb->nnames);
2378 isc_mem_put(adb->mctx, adb->namelocks,
2379 sizeof(*adb->namelocks) * adb->nnames);
2380 isc_mem_put(adb->mctx, adb->name_sd,
2381 sizeof(*adb->name_sd) * adb->nnames);
2382 isc_mem_put(adb->mctx, adb->name_refcnt,
2383 sizeof(*adb->name_refcnt) * adb->nnames);
2385 DESTROYLOCK(&adb->reflock);
2386 DESTROYLOCK(&adb->lock);
2387 DESTROYLOCK(&adb->mplock);
2388 DESTROYLOCK(&adb->overmemlock);
2389 DESTROYLOCK(&adb->entriescntlock);
2390 DESTROYLOCK(&adb->namescntlock);
2392 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2401 dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
2402 isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
2405 isc_result_t result;
2408 REQUIRE(mem != NULL);
2409 REQUIRE(view != NULL);
2410 REQUIRE(timermgr != NULL); /* this is actually unused */
2411 REQUIRE(taskmgr != NULL);
2412 REQUIRE(newadb != NULL && *newadb == NULL);
2416 adb = isc_mem_get(mem, sizeof(dns_adb_t));
2418 return (ISC_R_NOMEMORY);
2421 * Initialize things here that cannot fail, and especially things
2422 * that must be NULL for the error return to work properly.
2438 adb->taskmgr = taskmgr;
2439 adb->next_cleanbucket = 0;
2440 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent),
2441 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
2442 adb->cevent_out = ISC_FALSE;
2443 adb->shutting_down = ISC_FALSE;
2444 ISC_LIST_INIT(adb->whenshutdown);
2446 adb->nentries = nbuckets[0];
2447 adb->entriescnt = 0;
2448 adb->entries = NULL;
2449 adb->deadentries = NULL;
2450 adb->entry_sd = NULL;
2451 adb->entry_refcnt = NULL;
2452 adb->entrylocks = NULL;
2453 ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
2454 DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
2456 adb->growentries_sent = ISC_FALSE;
2458 adb->nnames = nbuckets[0];
2461 adb->deadnames = NULL;
2462 adb->name_sd = NULL;
2463 adb->name_refcnt = NULL;
2464 adb->namelocks = NULL;
2465 ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
2466 DNS_EVENT_ADBGROWNAMES, grow_names, adb,
2468 adb->grownames_sent = ISC_FALSE;
2470 result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
2471 if (result != ISC_R_SUCCESS) {
2472 DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, "
2473 "intializing table sizes to %u\n",
2475 adb->nentries = nbuckets[11];
2476 adb->nnames = nbuckets[11];
2480 isc_mem_attach(mem, &adb->mctx);
2482 result = isc_mutex_init(&adb->lock);
2483 if (result != ISC_R_SUCCESS)
2486 result = isc_mutex_init(&adb->mplock);
2487 if (result != ISC_R_SUCCESS)
2490 result = isc_mutex_init(&adb->reflock);
2491 if (result != ISC_R_SUCCESS)
2494 result = isc_mutex_init(&adb->overmemlock);
2495 if (result != ISC_R_SUCCESS)
2498 result = isc_mutex_init(&adb->entriescntlock);
2499 if (result != ISC_R_SUCCESS)
2502 result = isc_mutex_init(&adb->namescntlock);
2503 if (result != ISC_R_SUCCESS)
2506 #define ALLOCENTRY(adb, el) \
2508 (adb)->el = isc_mem_get((adb)->mctx, \
2509 sizeof(*(adb)->el) * (adb)->nentries); \
2510 if ((adb)->el == NULL) { \
2511 result = ISC_R_NOMEMORY; \
2515 ALLOCENTRY(adb, entries);
2516 ALLOCENTRY(adb, deadentries);
2517 ALLOCENTRY(adb, entrylocks);
2518 ALLOCENTRY(adb, entry_sd);
2519 ALLOCENTRY(adb, entry_refcnt);
2522 #define ALLOCNAME(adb, el) \
2524 (adb)->el = isc_mem_get((adb)->mctx, \
2525 sizeof(*(adb)->el) * (adb)->nnames); \
2526 if ((adb)->el == NULL) { \
2527 result = ISC_R_NOMEMORY; \
2531 ALLOCNAME(adb, names);
2532 ALLOCNAME(adb, deadnames);
2533 ALLOCNAME(adb, namelocks);
2534 ALLOCNAME(adb, name_sd);
2535 ALLOCNAME(adb, name_refcnt);
2539 * Initialize the bucket locks for names and elements.
2540 * May as well initialize the list heads, too.
2542 result = isc_mutexblock_init(adb->namelocks, adb->nnames);
2543 if (result != ISC_R_SUCCESS)
2545 for (i = 0; i < adb->nnames; i++) {
2546 ISC_LIST_INIT(adb->names[i]);
2547 ISC_LIST_INIT(adb->deadnames[i]);
2548 adb->name_sd[i] = ISC_FALSE;
2549 adb->name_refcnt[i] = 0;
2552 for (i = 0; i < adb->nentries; i++) {
2553 ISC_LIST_INIT(adb->entries[i]);
2554 ISC_LIST_INIT(adb->deadentries[i]);
2555 adb->entry_sd[i] = ISC_FALSE;
2556 adb->entry_refcnt[i] = 0;
2559 result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
2560 if (result != ISC_R_SUCCESS)
2566 #define MPINIT(t, p, n) do { \
2567 result = isc_mempool_create(mem, sizeof(t), &(p)); \
2568 if (result != ISC_R_SUCCESS) \
2570 isc_mempool_setfreemax((p), FREE_ITEMS); \
2571 isc_mempool_setfillcount((p), FILL_COUNT); \
2572 isc_mempool_setname((p), n); \
2573 isc_mempool_associatelock((p), &adb->mplock); \
2576 MPINIT(dns_adbname_t, adb->nmp, "adbname");
2577 MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
2578 MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
2579 MPINIT(dns_adbentry_t, adb->emp, "adbentry");
2580 MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
2581 MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
2582 MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
2587 * Allocate an internal task.
2589 result = isc_task_create(adb->taskmgr, 0, &adb->task);
2590 if (result != ISC_R_SUCCESS)
2593 isc_task_setname(adb->task, "ADB", adb);
2598 adb->magic = DNS_ADB_MAGIC;
2600 return (ISC_R_SUCCESS);
2603 if (adb->task != NULL)
2604 isc_task_detach(&adb->task);
2606 /* clean up entrylocks */
2607 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2609 fail2: /* clean up namelocks */
2610 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2612 fail1: /* clean up only allocated memory */
2613 if (adb->entries != NULL)
2614 isc_mem_put(adb->mctx, adb->entries,
2615 sizeof(*adb->entries) * adb->nentries);
2616 if (adb->deadentries != NULL)
2617 isc_mem_put(adb->mctx, adb->deadentries,
2618 sizeof(*adb->deadentries) * adb->nentries);
2619 if (adb->entrylocks != NULL)
2620 isc_mem_put(adb->mctx, adb->entrylocks,
2621 sizeof(*adb->entrylocks) * adb->nentries);
2622 if (adb->entry_sd != NULL)
2623 isc_mem_put(adb->mctx, adb->entry_sd,
2624 sizeof(*adb->entry_sd) * adb->nentries);
2625 if (adb->entry_refcnt != NULL)
2626 isc_mem_put(adb->mctx, adb->entry_refcnt,
2627 sizeof(*adb->entry_refcnt) * adb->nentries);
2628 if (adb->names != NULL)
2629 isc_mem_put(adb->mctx, adb->names,
2630 sizeof(*adb->names) * adb->nnames);
2631 if (adb->deadnames != NULL)
2632 isc_mem_put(adb->mctx, adb->deadnames,
2633 sizeof(*adb->deadnames) * adb->nnames);
2634 if (adb->namelocks != NULL)
2635 isc_mem_put(adb->mctx, adb->namelocks,
2636 sizeof(*adb->namelocks) * adb->nnames);
2637 if (adb->name_sd != NULL)
2638 isc_mem_put(adb->mctx, adb->name_sd,
2639 sizeof(*adb->name_sd) * adb->nnames);
2640 if (adb->name_refcnt != NULL)
2641 isc_mem_put(adb->mctx, adb->name_refcnt,
2642 sizeof(*adb->name_refcnt) * adb->nnames);
2643 if (adb->nmp != NULL)
2644 isc_mempool_destroy(&adb->nmp);
2645 if (adb->nhmp != NULL)
2646 isc_mempool_destroy(&adb->nhmp);
2647 if (adb->limp != NULL)
2648 isc_mempool_destroy(&adb->limp);
2649 if (adb->emp != NULL)
2650 isc_mempool_destroy(&adb->emp);
2651 if (adb->ahmp != NULL)
2652 isc_mempool_destroy(&adb->ahmp);
2653 if (adb->aimp != NULL)
2654 isc_mempool_destroy(&adb->aimp);
2655 if (adb->afmp != NULL)
2656 isc_mempool_destroy(&adb->afmp);
2658 DESTROYLOCK(&adb->namescntlock);
2660 DESTROYLOCK(&adb->entriescntlock);
2662 DESTROYLOCK(&adb->overmemlock);
2664 DESTROYLOCK(&adb->reflock);
2666 DESTROYLOCK(&adb->mplock);
2668 DESTROYLOCK(&adb->lock);
2670 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2676 dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
2678 REQUIRE(DNS_ADB_VALID(adb));
2679 REQUIRE(adbx != NULL && *adbx == NULL);
2681 inc_adb_erefcnt(adb);
2686 dns_adb_detach(dns_adb_t **adbx) {
2688 isc_boolean_t need_exit_check;
2690 REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
2695 INSIST(adb->erefcnt > 0);
2697 LOCK(&adb->reflock);
2699 need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
2700 UNLOCK(&adb->reflock);
2702 if (need_exit_check) {
2704 INSIST(adb->shutting_down);
2711 dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
2714 isc_boolean_t zeroirefcnt = ISC_FALSE;
2717 * Send '*eventp' to 'task' when 'adb' has shutdown.
2720 REQUIRE(DNS_ADB_VALID(adb));
2721 REQUIRE(eventp != NULL);
2728 LOCK(&adb->reflock);
2729 zeroirefcnt = ISC_TF(adb->irefcnt == 0);
2731 if (adb->shutting_down && zeroirefcnt &&
2732 isc_mempool_getallocated(adb->ahmp) == 0) {
2734 * We're already shutdown. Send the event.
2736 event->ev_sender = adb;
2737 isc_task_send(task, &event);
2740 isc_task_attach(task, &clone);
2741 event->ev_sender = clone;
2742 ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
2745 UNLOCK(&adb->reflock);
2750 shutdown_stage2(isc_task_t *task, isc_event_t *event) {
2755 adb = event->ev_arg;
2756 INSIST(DNS_ADB_VALID(adb));
2759 INSIST(adb->shutting_down);
2760 adb->cevent_out = ISC_FALSE;
2761 (void)shutdown_names(adb);
2762 (void)shutdown_entries(adb);
2763 if (dec_adb_irefcnt(adb))
2769 dns_adb_shutdown(dns_adb_t *adb) {
2778 if (!adb->shutting_down) {
2779 adb->shutting_down = ISC_TRUE;
2780 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
2782 * Isolate shutdown_names and shutdown_entries calls.
2784 inc_adb_irefcnt(adb);
2785 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
2786 DNS_EVENT_ADBCONTROL, shutdown_stage2, adb,
2788 adb->cevent_out = ISC_TRUE;
2789 event = &adb->cevent;
2790 isc_task_send(adb->task, &event);
2797 dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2798 void *arg, dns_name_t *name, dns_name_t *qname,
2799 dns_rdatatype_t qtype, unsigned int options,
2800 isc_stdtime_t now, dns_name_t *target,
2801 in_port_t port, dns_adbfind_t **findp)
2803 return (dns_adb_createfind2(adb, task, action, arg, name,
2804 qname, qtype, options, now,
2805 target, port, 0, NULL, findp));
2809 dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2810 void *arg, dns_name_t *name, dns_name_t *qname,
2811 dns_rdatatype_t qtype, unsigned int options,
2812 isc_stdtime_t now, dns_name_t *target,
2813 in_port_t port, unsigned int depth, isc_counter_t *qc,
2814 dns_adbfind_t **findp)
2816 dns_adbfind_t *find;
2817 dns_adbname_t *adbname;
2819 isc_boolean_t want_event, start_at_zone, alias, have_address;
2820 isc_result_t result;
2821 unsigned int wanted_addresses;
2822 unsigned int wanted_fetches;
2823 unsigned int query_pending;
2825 REQUIRE(DNS_ADB_VALID(adb));
2827 REQUIRE(action != NULL);
2829 REQUIRE(name != NULL);
2830 REQUIRE(qname != NULL);
2831 REQUIRE(findp != NULL && *findp == NULL);
2832 REQUIRE(target == NULL || dns_name_hasbuffer(target));
2834 REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
2836 result = ISC_R_UNEXPECTED;
2838 wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
2841 want_event = ISC_FALSE;
2842 start_at_zone = ISC_FALSE;
2846 isc_stdtime_get(&now);
2849 * XXXMLG Move this comment somewhere else!
2851 * Look up the name in our internal database.
2853 * Possibilities: Note that these are not always exclusive.
2855 * No name found. In this case, allocate a new name header and
2856 * an initial namehook or two. If any of these allocations
2857 * fail, clean up and return ISC_R_NOMEMORY.
2859 * Name found, valid addresses present. Allocate one addrinfo
2860 * structure for each found and append it to the linked list
2861 * of addresses for this header.
2863 * Name found, queries pending. In this case, if a task was
2864 * passed in, allocate a job id, attach it to the name's job
2865 * list and remember to tell the caller that there will be
2866 * more info coming later.
2869 find = new_adbfind(adb);
2871 return (ISC_R_NOMEMORY);
2876 * Remember what types of addresses we are interested in.
2878 find->options = options;
2879 find->flags |= wanted_addresses;
2880 if (FIND_WANTEVENT(find)) {
2881 REQUIRE(task != NULL);
2885 * Try to see if we know anything about this name at all.
2887 bucket = DNS_ADB_INVALIDBUCKET;
2888 adbname = find_name_and_lock(adb, name, find->options, &bucket);
2889 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2890 if (adb->name_sd[bucket]) {
2892 "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
2893 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2894 result = ISC_R_SHUTTINGDOWN;
2899 * Nothing found. Allocate a new adbname structure for this name.
2901 if (adbname == NULL) {
2903 * See if there is any stale name at the end of list, and purge
2906 check_stale_name(adb, bucket, now);
2908 adbname = new_adbname(adb, name);
2909 if (adbname == NULL) {
2910 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2911 result = ISC_R_NOMEMORY;
2914 link_name(adb, bucket, adbname);
2915 if (FIND_HINTOK(find))
2916 adbname->flags |= NAME_HINT_OK;
2917 if (FIND_GLUEOK(find))
2918 adbname->flags |= NAME_GLUE_OK;
2919 if (FIND_STARTATZONE(find))
2920 adbname->flags |= NAME_STARTATZONE;
2922 /* Move this name forward in the LRU list */
2923 ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
2924 ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
2926 adbname->last_used = now;
2929 * Expire old entries, etc.
2931 RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
2934 * Do we know that the name is an alias?
2936 if (!EXPIRE_OK(adbname->expire_target, now)) {
2941 "dns_adb_createfind: name %p is an alias (cached)",
2948 * Try to populate the name from the database and/or
2949 * start fetches. First try looking for an A record
2952 if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
2953 && WANT_INET(wanted_addresses)) {
2954 result = dbfind_name(adbname, now, dns_rdatatype_a);
2955 if (result == ISC_R_SUCCESS) {
2957 "dns_adb_createfind: found A for name %p in db",
2963 * Did we get a CNAME or DNAME?
2965 if (result == DNS_R_ALIAS) {
2967 "dns_adb_createfind: name %p is an alias",
2974 * If the name doesn't exist at all, don't bother with
2975 * v6 queries; they won't work.
2977 * If the name does exist but we didn't get our data, go
2978 * ahead and try AAAA.
2980 * If the result is neither of these, try a fetch for A.
2982 if (NXDOMAIN_RESULT(result))
2984 else if (NXRRSET_RESULT(result))
2987 if (!NAME_FETCH_V4(adbname))
2988 wanted_fetches |= DNS_ADBFIND_INET;
2992 if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
2993 && WANT_INET6(wanted_addresses)) {
2994 result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
2995 if (result == ISC_R_SUCCESS) {
2997 "dns_adb_createfind: found AAAA for name %p",
3003 * Did we get a CNAME or DNAME?
3005 if (result == DNS_R_ALIAS) {
3007 "dns_adb_createfind: name %p is an alias",
3014 * Listen to negative cache hints, and don't start
3017 if (NCACHE_RESULT(result) || AUTH_NX(result))
3020 if (!NAME_FETCH_V6(adbname))
3021 wanted_fetches |= DNS_ADBFIND_INET6;
3025 if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
3026 (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
3027 have_address = ISC_TRUE;
3029 have_address = ISC_FALSE;
3030 if (wanted_fetches != 0 &&
3031 ! (FIND_AVOIDFETCHES(find) && have_address)) {
3033 * We're missing at least one address family. Either the
3034 * caller hasn't instructed us to avoid fetches, or we don't
3035 * know anything about any of the address families that would
3036 * be acceptable so we have to launch fetches.
3039 if (FIND_STARTATZONE(find))
3040 start_at_zone = ISC_TRUE;
3045 if (WANT_INET(wanted_fetches) &&
3046 fetch_name(adbname, start_at_zone, depth, qc,
3047 dns_rdatatype_a) == ISC_R_SUCCESS) {
3049 "dns_adb_createfind: started A fetch for name %p",
3056 if (WANT_INET6(wanted_fetches) &&
3057 fetch_name(adbname, start_at_zone, depth, qc,
3058 dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
3060 "dns_adb_createfind: "
3061 "started AAAA fetch for name %p",
3067 * Run through the name and copy out the bits we are
3070 copy_namehook_lists(adb, find, qname, qtype, adbname, now);
3073 if (NAME_FETCH_V4(adbname))
3074 query_pending |= DNS_ADBFIND_INET;
3075 if (NAME_FETCH_V6(adbname))
3076 query_pending |= DNS_ADBFIND_INET6;
3079 * Attach to the name's query list if there are queries
3080 * already running, and we have been asked to.
3082 want_event = ISC_TRUE;
3083 if (!FIND_WANTEVENT(find))
3084 want_event = ISC_FALSE;
3085 if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
3086 want_event = ISC_FALSE;
3087 if ((wanted_addresses & query_pending) == 0)
3088 want_event = ISC_FALSE;
3090 want_event = ISC_FALSE;
3092 find->adbname = adbname;
3093 find->name_bucket = bucket;
3094 ISC_LIST_APPEND(adbname->finds, find, plink);
3095 find->query_pending = (query_pending & wanted_addresses);
3096 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3097 find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
3098 DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
3102 * Remove the flag so the caller knows there will never
3103 * be an event, and set internal flags to fake that
3104 * the event was sent and freed, so dns_adb_destroyfind() will
3105 * do the right thing.
3107 find->query_pending = (query_pending & wanted_addresses);
3108 find->options &= ~DNS_ADBFIND_WANTEVENT;
3109 find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
3110 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3113 find->partial_result |= (adbname->partial_result & wanted_addresses);
3115 if (target != NULL) {
3116 result = dns_name_copy(&adbname->target, target, NULL);
3117 if (result != ISC_R_SUCCESS)
3120 result = DNS_R_ALIAS;
3122 result = ISC_R_SUCCESS;
3125 * Copy out error flags from the name structure into the find.
3127 find->result_v4 = find_err_map[adbname->fetch_err];
3128 find->result_v6 = find_err_map[adbname->fetch6_err];
3137 INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
3139 isc_task_attach(task, &taskp);
3140 find->event.ev_sender = taskp;
3141 find->event.ev_action = action;
3142 find->event.ev_arg = arg;
3146 UNLOCK(&adb->namelocks[bucket]);
3152 dns_adb_destroyfind(dns_adbfind_t **findp) {
3153 dns_adbfind_t *find;
3154 dns_adbentry_t *entry;
3155 dns_adbaddrinfo_t *ai;
3158 isc_boolean_t overmem;
3160 REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
3166 DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
3169 REQUIRE(DNS_ADB_VALID(adb));
3171 REQUIRE(FIND_EVENTFREED(find));
3173 bucket = find->name_bucket;
3174 INSIST(bucket == DNS_ADB_INVALIDBUCKET);
3176 UNLOCK(&find->lock);
3179 * The find doesn't exist on any list, and nothing is locked.
3180 * Return the find to the memory pool, and decrement the adb's
3183 overmem = isc_mem_isovermem(adb->mctx);
3184 ai = ISC_LIST_HEAD(find->list);
3185 while (ai != NULL) {
3186 ISC_LIST_UNLINK(find->list, ai, publink);
3189 INSIST(DNS_ADBENTRY_VALID(entry));
3190 RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
3192 free_adbaddrinfo(adb, &ai);
3193 ai = ISC_LIST_HEAD(find->list);
3197 * WARNING: The find is freed with the adb locked. This is done
3198 * to avoid a race condition where we free the find, some other
3199 * thread tests to see if it should be destroyed, detects it should
3200 * be, destroys it, and then we try to lock it for our check, but the
3201 * lock is destroyed.
3204 if (free_adbfind(adb, &find))
3210 dns_adb_cancelfind(dns_adbfind_t *find) {
3219 DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
3222 REQUIRE(DNS_ADB_VALID(adb));
3224 REQUIRE(!FIND_EVENTFREED(find));
3225 REQUIRE(FIND_WANTEVENT(find));
3227 bucket = find->name_bucket;
3228 if (bucket == DNS_ADB_INVALIDBUCKET)
3232 * We need to get the adbname's lock to unlink the find.
3234 unlock_bucket = bucket;
3235 violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
3236 bucket = find->name_bucket;
3237 if (bucket != DNS_ADB_INVALIDBUCKET) {
3238 ISC_LIST_UNLINK(find->adbname->finds, find, plink);
3239 find->adbname = NULL;
3240 find->name_bucket = DNS_ADB_INVALIDBUCKET;
3242 UNLOCK(&adb->namelocks[unlock_bucket]);
3243 bucket = DNS_ADB_INVALIDBUCKET;
3248 if (!FIND_EVENTSENT(find)) {
3250 task = ev->ev_sender;
3251 ev->ev_sender = find;
3252 ev->ev_type = DNS_EVENT_ADBCANCELED;
3253 ev->ev_destroy = event_free;
3254 ev->ev_destroy_arg = find;
3255 find->result_v4 = ISC_R_CANCELED;
3256 find->result_v6 = ISC_R_CANCELED;
3258 DP(DEF_LEVEL, "sending event %p to task %p for find %p",
3261 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
3264 UNLOCK(&find->lock);
3268 dns_adb_dump(dns_adb_t *adb, FILE *f) {
3272 REQUIRE(DNS_ADB_VALID(adb));
3276 * Lock the adb itself, lock all the name buckets, then lock all
3277 * the entry buckets. This should put the adb into a state where
3278 * nothing can change, so we can iterate through everything and
3279 * print at our leisure.
3283 isc_stdtime_get(&now);
3285 for (i = 0; i < adb->nnames; i++)
3286 RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
3287 for (i = 0; i < adb->nentries; i++)
3288 RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
3290 dump_adb(adb, f, ISC_FALSE, now);
3295 dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
3296 if (value == INT_MAX)
3298 fprintf(f, " [%s TTL %d]", legend, value - now);
3302 dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
3304 dns_adbname_t *name;
3305 dns_adbentry_t *entry;
3307 fprintf(f, ";\n; Address database dump\n;\n");
3309 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
3310 adb, adb->erefcnt, adb->irefcnt,
3311 isc_mempool_getallocated(adb->nhmp));
3313 for (i = 0; i < adb->nnames; i++)
3314 LOCK(&adb->namelocks[i]);
3315 for (i = 0; i < adb->nentries; i++)
3316 LOCK(&adb->entrylocks[i]);
3321 for (i = 0; i < adb->nnames; i++) {
3322 name = ISC_LIST_HEAD(adb->names[i]);
3326 fprintf(f, "; bucket %d\n", i);
3329 name = ISC_LIST_NEXT(name, plink))
3332 fprintf(f, "; name %p (flags %08x)\n",
3336 print_dns_name(f, &name->name);
3337 if (dns_name_countlabels(&name->target) > 0) {
3338 fprintf(f, " alias ");
3339 print_dns_name(f, &name->target);
3342 dump_ttl(f, "v4", name->expire_v4, now);
3343 dump_ttl(f, "v6", name->expire_v6, now);
3344 dump_ttl(f, "target", name->expire_target, now);
3346 fprintf(f, " [v4 %s] [v6 %s]",
3347 errnames[name->fetch_err],
3348 errnames[name->fetch6_err]);
3352 print_namehook_list(f, "v4", &name->v4, debug, now);
3353 print_namehook_list(f, "v6", &name->v6, debug, now);
3356 print_fetch_list(f, name);
3358 print_find_list(f, name);
3363 fprintf(f, ";\n; Unassociated entries\n;\n");
3365 for (i = 0; i < adb->nentries; i++) {
3366 entry = ISC_LIST_HEAD(adb->entries[i]);
3367 while (entry != NULL) {
3368 if (entry->refcnt == 0)
3369 dump_entry(f, entry, debug, now);
3370 entry = ISC_LIST_NEXT(entry, plink);
3377 for (i = 0; i < adb->nentries; i++)
3378 UNLOCK(&adb->entrylocks[i]);
3379 for (i = 0; i < adb->nnames; i++)
3380 UNLOCK(&adb->namelocks[i]);
3384 dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
3387 char addrbuf[ISC_NETADDR_FORMATSIZE];
3388 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3389 isc_netaddr_t netaddr;
3390 dns_adblameinfo_t *li;
3392 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
3393 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
3396 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
3398 fprintf(f, ";\t%s [srtt %u] [flags %08x]",
3399 addrbuf, entry->srtt, entry->flags);
3400 if (entry->expires != 0)
3401 fprintf(f, " [ttl %d]", entry->expires - now);
3403 for (li = ISC_LIST_HEAD(entry->lameinfo);
3405 li = ISC_LIST_NEXT(li, plink)) {
3406 fprintf(f, ";\t\t");
3407 print_dns_name(f, &li->qname);
3408 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
3409 fprintf(f, " %s [lame TTL %d]\n", typebuf,
3410 li->lame_timer - now);
3415 dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
3418 dns_adbaddrinfo_t *ai;
3422 * Not used currently, in the API Just In Case we
3423 * want to dump out the name and/or entries too.
3428 fprintf(f, ";Find %p\n", find);
3429 fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
3430 find->query_pending, find->partial_result,
3431 find->options, find->flags);
3432 fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
3433 find->name_bucket, find->adbname, find->event.ev_sender);
3435 ai = ISC_LIST_HEAD(find->list);
3437 fprintf(f, "\tAddresses:\n");
3438 while (ai != NULL) {
3440 switch (sa->type.sa.sa_family) {
3442 tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
3446 tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
3454 tmpp = "BadAddress";
3456 fprintf(f, "\t\tentry %p, flags %08x"
3457 " srtt %u addr %s\n",
3458 ai->entry, ai->flags, ai->srtt, tmpp);
3460 ai = ISC_LIST_NEXT(ai, publink);
3463 UNLOCK(&find->lock);
3467 print_dns_name(FILE *f, dns_name_t *name) {
3468 char buf[DNS_NAME_FORMATSIZE];
3472 dns_name_format(name, buf, sizeof(buf));
3473 fprintf(f, "%s", buf);
3477 print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
3478 isc_boolean_t debug, isc_stdtime_t now)
3480 dns_adbnamehook_t *nh;
3482 for (nh = ISC_LIST_HEAD(*list);
3484 nh = ISC_LIST_NEXT(nh, plink))
3487 fprintf(f, ";\tHook(%s) %p\n", legend, nh);
3488 dump_entry(f, nh->entry, debug, now);
3493 print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
3494 fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
3495 type, ft, ft->fetch);
3499 print_fetch_list(FILE *f, dns_adbname_t *n) {
3500 if (NAME_FETCH_A(n))
3501 print_fetch(f, n->fetch_a, "A");
3502 if (NAME_FETCH_AAAA(n))
3503 print_fetch(f, n->fetch_aaaa, "AAAA");
3507 print_find_list(FILE *f, dns_adbname_t *name) {
3508 dns_adbfind_t *find;
3510 find = ISC_LIST_HEAD(name->finds);
3511 while (find != NULL) {
3512 dns_adb_dumpfind(find, f);
3513 find = ISC_LIST_NEXT(find, plink);
3518 dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
3520 isc_result_t result;
3521 dns_rdataset_t rdataset;
3523 dns_fixedname_t foundname;
3526 INSIST(DNS_ADBNAME_VALID(adbname));
3528 INSIST(DNS_ADB_VALID(adb));
3529 INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
3531 dns_fixedname_init(&foundname);
3532 fname = dns_fixedname_name(&foundname);
3533 dns_rdataset_init(&rdataset);
3535 if (rdtype == dns_rdatatype_a)
3536 adbname->fetch_err = FIND_ERR_UNEXPECTED;
3538 adbname->fetch6_err = FIND_ERR_UNEXPECTED;
3541 * We need to specify whether to search static-stub zones (if
3542 * configured) depending on whether this is a "start at zone" lookup,
3543 * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
3544 * case NAME_STARTATZONE is set) we need to stop the search at any
3545 * matching static-stub zone without looking into the cache to honor
3546 * the configuration on which server we should send queries to.
3548 result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
3549 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
3550 ISC_TF(NAME_HINTOK(adbname)),
3551 (adbname->flags & NAME_STARTATZONE) != 0 ?
3552 ISC_TRUE : ISC_FALSE,
3553 NULL, NULL, fname, &rdataset, NULL);
3555 /* XXXVIX this switch statement is too sparse to gen a jump table. */
3561 * Found in the database. Even if we can't copy out
3562 * any information, return success, or else a fetch
3563 * will be made, which will only make things worse.
3565 if (rdtype == dns_rdatatype_a)
3566 adbname->fetch_err = FIND_ERR_SUCCESS;
3568 adbname->fetch6_err = FIND_ERR_SUCCESS;
3569 result = import_rdataset(adbname, &rdataset, now);
3571 case DNS_R_NXDOMAIN:
3574 * We're authoritative and the data doesn't exist.
3575 * Make up a negative cache entry so we don't ask again
3578 * XXXRTH What time should we use? I'm putting in 30 seconds
3581 if (rdtype == dns_rdatatype_a) {
3582 adbname->expire_v4 = now + 30;
3584 "adb name %p: Caching auth negative entry for A",
3586 if (result == DNS_R_NXDOMAIN)
3587 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3589 adbname->fetch_err = FIND_ERR_NXRRSET;
3592 "adb name %p: Caching auth negative entry for AAAA",
3594 adbname->expire_v6 = now + 30;
3595 if (result == DNS_R_NXDOMAIN)
3596 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3598 adbname->fetch6_err = FIND_ERR_NXRRSET;
3601 case DNS_R_NCACHENXDOMAIN:
3602 case DNS_R_NCACHENXRRSET:
3604 * We found a negative cache entry. Pull the TTL from it
3605 * so we won't ask again for a while.
3607 rdataset.ttl = ttlclamp(rdataset.ttl);
3608 if (rdtype == dns_rdatatype_a) {
3609 adbname->expire_v4 = rdataset.ttl + now;
3610 if (result == DNS_R_NCACHENXDOMAIN)
3611 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3613 adbname->fetch_err = FIND_ERR_NXRRSET;
3615 "adb name %p: Caching negative entry for A (ttl %u)",
3616 adbname, rdataset.ttl);
3619 "adb name %p: Caching negative entry for AAAA (ttl %u)",
3620 adbname, rdataset.ttl);
3621 adbname->expire_v6 = rdataset.ttl + now;
3622 if (result == DNS_R_NCACHENXDOMAIN)
3623 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3625 adbname->fetch6_err = FIND_ERR_NXRRSET;
3631 * Clear the hint and glue flags, so this will match
3634 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
3636 rdataset.ttl = ttlclamp(rdataset.ttl);
3637 clean_target(adb, &adbname->target);
3638 adbname->expire_target = INT_MAX;
3639 result = set_target(adb, &adbname->name, fname, &rdataset,
3641 if (result == ISC_R_SUCCESS) {
3642 result = DNS_R_ALIAS;
3644 "adb name %p: caching alias target",
3646 adbname->expire_target = rdataset.ttl + now;
3648 if (rdtype == dns_rdatatype_a)
3649 adbname->fetch_err = FIND_ERR_SUCCESS;
3651 adbname->fetch6_err = FIND_ERR_SUCCESS;
3655 if (dns_rdataset_isassociated(&rdataset))
3656 dns_rdataset_disassociate(&rdataset);
3662 fetch_callback(isc_task_t *task, isc_event_t *ev) {
3663 dns_fetchevent_t *dev;
3664 dns_adbname_t *name;
3666 dns_adbfetch_t *fetch;
3668 isc_eventtype_t ev_status;
3670 isc_result_t result;
3671 unsigned int address_type;
3672 isc_boolean_t want_check_exit = ISC_FALSE;
3676 INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
3677 dev = (dns_fetchevent_t *)ev;
3679 INSIST(DNS_ADBNAME_VALID(name));
3681 INSIST(DNS_ADB_VALID(adb));
3683 bucket = name->lock_bucket;
3684 LOCK(&adb->namelocks[bucket]);
3686 INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
3688 if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
3689 address_type = DNS_ADBFIND_INET;
3690 fetch = name->fetch_a;
3691 name->fetch_a = NULL;
3692 } else if (NAME_FETCH_AAAA(name)
3693 && (name->fetch_aaaa->fetch == dev->fetch)) {
3694 address_type = DNS_ADBFIND_INET6;
3695 fetch = name->fetch_aaaa;
3696 name->fetch_aaaa = NULL;
3700 INSIST(address_type != 0 && fetch != NULL);
3702 dns_resolver_destroyfetch(&fetch->fetch);
3705 ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
3708 * Cleanup things we don't care about.
3710 if (dev->node != NULL)
3711 dns_db_detachnode(dev->db, &dev->node);
3712 if (dev->db != NULL)
3713 dns_db_detach(&dev->db);
3716 * If this name is marked as dead, clean up, throwing away
3717 * potentially good data.
3719 if (NAME_DEAD(name)) {
3720 free_adbfetch(adb, &fetch);
3721 isc_event_free(&ev);
3723 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED);
3725 UNLOCK(&adb->namelocks[bucket]);
3727 if (want_check_exit) {
3736 isc_stdtime_get(&now);
3739 * If we got a negative cache response, remember it.
3741 if (NCACHE_RESULT(dev->result)) {
3742 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3743 if (address_type == DNS_ADBFIND_INET) {
3744 DP(NCACHE_LEVEL, "adb fetch name %p: "
3745 "caching negative entry for A (ttl %u)",
3746 name, dev->rdataset->ttl);
3747 name->expire_v4 = ISC_MIN(name->expire_v4,
3748 dev->rdataset->ttl + now);
3749 if (dev->result == DNS_R_NCACHENXDOMAIN)
3750 name->fetch_err = FIND_ERR_NXDOMAIN;
3752 name->fetch_err = FIND_ERR_NXRRSET;
3753 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3755 DP(NCACHE_LEVEL, "adb fetch name %p: "
3756 "caching negative entry for AAAA (ttl %u)",
3757 name, dev->rdataset->ttl);
3758 name->expire_v6 = ISC_MIN(name->expire_v6,
3759 dev->rdataset->ttl + now);
3760 if (dev->result == DNS_R_NCACHENXDOMAIN)
3761 name->fetch6_err = FIND_ERR_NXDOMAIN;
3763 name->fetch6_err = FIND_ERR_NXRRSET;
3764 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3770 * Handle CNAME/DNAME.
3772 if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
3773 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3774 clean_target(adb, &name->target);
3775 name->expire_target = INT_MAX;
3776 result = set_target(adb, &name->name,
3777 dns_fixedname_name(&dev->foundname),
3780 if (result == ISC_R_SUCCESS) {
3782 "adb fetch name %p: caching alias target",
3784 name->expire_target = dev->rdataset->ttl + now;
3790 * Did we get back junk? If so, and there are no more fetches
3791 * sitting out there, tell all the finds about it.
3793 if (dev->result != ISC_R_SUCCESS) {
3794 char buf[DNS_NAME_FORMATSIZE];
3796 dns_name_format(&name->name, buf, sizeof(buf));
3797 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
3798 buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
3799 dns_result_totext(dev->result));
3801 * Don't record a failure unless this is the initial
3804 if (fetch->depth > 1)
3806 /* XXXMLG Don't pound on bad servers. */
3807 if (address_type == DNS_ADBFIND_INET) {
3808 name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
3809 name->fetch_err = FIND_ERR_FAILURE;
3810 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3812 name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
3813 name->fetch6_err = FIND_ERR_FAILURE;
3814 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3820 * We got something potentially useful.
3822 result = import_rdataset(name, &fetch->rdataset, now);
3825 if (result == ISC_R_SUCCESS) {
3826 ev_status = DNS_EVENT_ADBMOREADDRESSES;
3827 if (address_type == DNS_ADBFIND_INET)
3828 name->fetch_err = FIND_ERR_SUCCESS;
3830 name->fetch6_err = FIND_ERR_SUCCESS;
3834 free_adbfetch(adb, &fetch);
3835 isc_event_free(&ev);
3837 clean_finds_at_name(name, ev_status, address_type);
3839 UNLOCK(&adb->namelocks[bucket]);
3843 fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
3844 unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
3846 isc_result_t result;
3847 dns_adbfetch_t *fetch = NULL;
3849 dns_fixedname_t fixed;
3851 dns_rdataset_t rdataset;
3852 dns_rdataset_t *nameservers;
3853 unsigned int options;
3855 INSIST(DNS_ADBNAME_VALID(adbname));
3857 INSIST(DNS_ADB_VALID(adb));
3859 INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
3860 (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
3862 adbname->fetch_err = FIND_ERR_NOTFOUND;
3866 dns_rdataset_init(&rdataset);
3868 options = DNS_FETCHOPT_NOVALIDATE;
3869 if (start_at_zone) {
3871 "fetch_name: starting at zone for name %p",
3873 dns_fixedname_init(&fixed);
3874 name = dns_fixedname_name(&fixed);
3875 result = dns_view_findzonecut2(adb->view, &adbname->name, name,
3876 0, 0, ISC_TRUE, ISC_FALSE,
3878 if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
3880 nameservers = &rdataset;
3881 options |= DNS_FETCHOPT_UNSHARED;
3884 fetch = new_adbfetch(adb);
3885 if (fetch == NULL) {
3886 result = ISC_R_NOMEMORY;
3889 fetch->depth = depth;
3891 result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
3892 type, name, nameservers, NULL,
3893 NULL, 0, options, depth, qc,
3894 adb->task, fetch_callback, adbname,
3895 &fetch->rdataset, NULL,
3897 if (result != ISC_R_SUCCESS)
3900 if (type == dns_rdatatype_a) {
3901 adbname->fetch_a = fetch;
3902 inc_stats(adb, dns_resstatscounter_gluefetchv4);
3904 adbname->fetch_aaaa = fetch;
3905 inc_stats(adb, dns_resstatscounter_gluefetchv6);
3907 fetch = NULL; /* Keep us from cleaning this up below. */
3911 free_adbfetch(adb, &fetch);
3912 if (dns_rdataset_isassociated(&rdataset))
3913 dns_rdataset_disassociate(&rdataset);
3919 * XXXMLG Needs to take a find argument and an address info, no zone or adb,
3920 * since these can be extracted from the find itself.
3923 dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
3924 dns_rdatatype_t qtype, isc_stdtime_t expire_time)
3926 dns_adblameinfo_t *li;
3928 isc_result_t result = ISC_R_SUCCESS;
3930 REQUIRE(DNS_ADB_VALID(adb));
3931 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3932 REQUIRE(qname != NULL);
3934 bucket = addr->entry->lock_bucket;
3935 LOCK(&adb->entrylocks[bucket]);
3936 li = ISC_LIST_HEAD(addr->entry->lameinfo);
3937 while (li != NULL &&
3938 (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
3939 li = ISC_LIST_NEXT(li, plink);
3941 if (expire_time > li->lame_timer)
3942 li->lame_timer = expire_time;
3945 li = new_adblameinfo(adb, qname, qtype);
3947 result = ISC_R_NOMEMORY;
3951 li->lame_timer = expire_time;
3953 ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
3955 UNLOCK(&adb->entrylocks[bucket]);
3961 dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3962 unsigned int rtt, unsigned int factor)
3965 isc_stdtime_t now = 0;
3967 REQUIRE(DNS_ADB_VALID(adb));
3968 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3969 REQUIRE(factor <= 10);
3971 bucket = addr->entry->lock_bucket;
3972 LOCK(&adb->entrylocks[bucket]);
3974 if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE)
3975 isc_stdtime_get(&now);
3976 adjustsrtt(addr, rtt, factor, now);
3978 UNLOCK(&adb->entrylocks[bucket]);
3982 dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) {
3985 REQUIRE(DNS_ADB_VALID(adb));
3986 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3988 bucket = addr->entry->lock_bucket;
3989 LOCK(&adb->entrylocks[bucket]);
3991 adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now);
3993 UNLOCK(&adb->entrylocks[bucket]);
3997 adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
4000 isc_uint64_t new_srtt;
4002 if (factor == DNS_ADB_RTTADJAGE) {
4003 if (addr->entry->lastage != now) {
4004 new_srtt = addr->entry->srtt;
4006 new_srtt -= addr->entry->srtt;
4008 addr->entry->lastage = now;
4010 new_srtt = addr->entry->srtt;
4012 new_srtt = (addr->entry->srtt / 10 * factor)
4013 + (rtt / 10 * (10 - factor));
4015 new_srtt &= 0xffffffff;
4016 addr->entry->srtt = (unsigned int) new_srtt;
4017 addr->srtt = (unsigned int) new_srtt;
4019 if (addr->entry->expires == 0)
4020 addr->entry->expires = now + ADB_ENTRY_WINDOW;
4024 dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
4025 unsigned int bits, unsigned int mask)
4030 REQUIRE(DNS_ADB_VALID(adb));
4031 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4033 REQUIRE((bits & ENTRY_IS_DEAD) == 0);
4034 REQUIRE((mask & ENTRY_IS_DEAD) == 0);
4036 bucket = addr->entry->lock_bucket;
4037 LOCK(&adb->entrylocks[bucket]);
4039 addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
4040 if (addr->entry->expires == 0) {
4041 isc_stdtime_get(&now);
4042 addr->entry->expires = now + ADB_ENTRY_WINDOW;
4046 * Note that we do not update the other bits in addr->flags with
4047 * the most recent values from addr->entry->flags.
4049 addr->flags = (addr->flags & ~mask) | (bits & mask);
4051 UNLOCK(&adb->entrylocks[bucket]);
4055 dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
4056 dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
4059 dns_adbentry_t *entry;
4060 dns_adbaddrinfo_t *addr;
4061 isc_result_t result;
4064 REQUIRE(DNS_ADB_VALID(adb));
4065 REQUIRE(addrp != NULL && *addrp == NULL);
4069 result = ISC_R_SUCCESS;
4070 bucket = DNS_ADB_INVALIDBUCKET;
4071 entry = find_entry_and_lock(adb, sa, &bucket, now);
4072 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
4073 if (adb->entry_sd[bucket]) {
4074 result = ISC_R_SHUTTINGDOWN;
4077 if (entry == NULL) {
4079 * We don't know anything about this address.
4081 entry = new_adbentry(adb);
4082 if (entry == NULL) {
4083 result = ISC_R_NOMEMORY;
4086 entry->sockaddr = *sa;
4087 link_entry(adb, bucket, entry);
4088 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
4090 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
4092 port = isc_sockaddr_getport(sa);
4093 addr = new_adbaddrinfo(adb, entry, port);
4095 result = ISC_R_NOMEMORY;
4097 inc_entry_refcnt(adb, entry, ISC_FALSE);
4102 UNLOCK(&adb->entrylocks[bucket]);
4108 dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
4109 dns_adbaddrinfo_t *addr;
4110 dns_adbentry_t *entry;
4113 isc_boolean_t want_check_exit = ISC_FALSE;
4114 isc_boolean_t overmem;
4116 REQUIRE(DNS_ADB_VALID(adb));
4117 REQUIRE(addrp != NULL);
4119 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4120 entry = addr->entry;
4121 REQUIRE(DNS_ADBENTRY_VALID(entry));
4124 overmem = isc_mem_isovermem(adb->mctx);
4126 bucket = addr->entry->lock_bucket;
4127 LOCK(&adb->entrylocks[bucket]);
4129 if (entry->expires == 0) {
4130 isc_stdtime_get(&now);
4131 entry->expires = now + ADB_ENTRY_WINDOW;
4134 want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
4136 UNLOCK(&adb->entrylocks[bucket]);
4139 free_adbaddrinfo(adb, &addr);
4141 if (want_check_exit) {
4149 dns_adb_flush(dns_adb_t *adb) {
4152 INSIST(DNS_ADB_VALID(adb));
4157 * Call our cleanup routines.
4159 for (i = 0; i < adb->nnames; i++)
4160 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
4161 for (i = 0; i < adb->nentries; i++)
4162 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
4164 #ifdef DUMP_ADB_AFTER_CLEANING
4165 dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
4172 dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
4173 dns_adbname_t *adbname;
4174 dns_adbname_t *nextname;
4177 INSIST(DNS_ADB_VALID(adb));
4180 bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
4181 LOCK(&adb->namelocks[bucket]);
4182 adbname = ISC_LIST_HEAD(adb->names[bucket]);
4183 while (adbname != NULL) {
4184 nextname = ISC_LIST_NEXT(adbname, plink);
4185 if (!NAME_DEAD(adbname) &&
4186 dns_name_equal(name, &adbname->name)) {
4187 RUNTIME_CHECK(kill_name(&adbname,
4188 DNS_EVENT_ADBCANCELED) ==
4193 UNLOCK(&adb->namelocks[bucket]);
4198 water(void *arg, int mark) {
4200 * We're going to change the way to handle overmem condition: use
4201 * isc_mem_isovermem() instead of storing the state via this callback,
4202 * since the latter way tends to cause race conditions.
4203 * To minimize the change, and in case we re-enable the callback
4204 * approach, however, keep this function at the moment.
4207 dns_adb_t *adb = arg;
4208 isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
4210 REQUIRE(DNS_ADB_VALID(adb));
4212 DP(ISC_LOG_DEBUG(1),
4213 "adb reached %s water mark", overmem ? "high" : "low");
4217 dns_adb_setadbsize(dns_adb_t *adb, size_t size) {
4218 size_t hiwater, lowater;
4220 INSIST(DNS_ADB_VALID(adb));
4222 if (size != 0U && size < DNS_ADB_MINADBSIZE)
4223 size = DNS_ADB_MINADBSIZE;
4225 hiwater = size - (size >> 3); /* Approximately 7/8ths. */
4226 lowater = size - (size >> 2); /* Approximately 3/4ths. */
4228 if (size == 0U || hiwater == 0U || lowater == 0U)
4229 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
4231 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);