2 * Copyright (C) 2004-2015 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/print.h>
34 #include <isc/random.h>
35 #include <isc/stats.h>
36 #include <isc/string.h> /* Required for HP/UX (and others?) */
42 #include <dns/events.h>
44 #include <dns/rdata.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/rdatatype.h>
48 #include <dns/resolver.h>
49 #include <dns/result.h>
50 #include <dns/stats.h>
52 #define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
53 #define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
54 #define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
55 #define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
56 #define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
57 #define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
58 #define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
59 #define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
60 #define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
61 #define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
62 #define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
63 #define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
64 #define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
65 #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
68 * For type 3 negative cache entries, we will remember that the address is
69 * broken for this long. XXXMLG This is also used for actual addresses, too.
70 * The intent is to keep us from constantly asking about A/AAAA records
71 * if the zone has extremely low TTLs.
73 #define ADB_CACHE_MINIMUM 10 /*%< seconds */
74 #define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
75 #define ADB_ENTRY_WINDOW 1800 /*%< seconds */
78 * The period in seconds after which an ADB name entry is regarded as stale
79 * and forced to be cleaned up.
80 * TODO: This should probably be configurable at run-time.
82 #ifndef ADB_STALE_MARGIN
83 #define ADB_STALE_MARGIN 1800
86 #define FREE_ITEMS 64 /*%< free count for memory pools */
87 #define FILL_COUNT 16 /*%< fill count for memory pools */
89 #define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
91 #define DNS_ADB_MINADBSIZE (1024U*1024U) /*%< 1 Megabyte */
93 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
94 typedef struct dns_adbnamehook dns_adbnamehook_t;
95 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
96 typedef struct dns_adblameinfo dns_adblameinfo_t;
97 typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
98 typedef struct dns_adbfetch dns_adbfetch_t;
99 typedef struct dns_adbfetch6 dns_adbfetch6_t;
101 /*% dns adb structure */
106 isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
107 isc_mutex_t overmemlock; /*%< Covers overmem */
111 isc_taskmgr_t *taskmgr;
115 isc_interval_t tick_interval;
116 int next_cleanbucket;
118 unsigned int irefcnt;
119 unsigned int erefcnt;
122 isc_mempool_t *nmp; /*%< dns_adbname_t */
123 isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
124 isc_mempool_t *limp; /*%< dns_adblameinfo_t */
125 isc_mempool_t *emp; /*%< dns_adbentry_t */
126 isc_mempool_t *ahmp; /*%< dns_adbfind_t */
127 isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
128 isc_mempool_t *afmp; /*%< dns_adbfetch_t */
131 * Bucketized locks and lists for names.
133 * XXXRTH Have a per-bucket structure that contains all of these?
136 isc_mutex_t namescntlock;
137 unsigned int namescnt;
138 dns_adbnamelist_t *names;
139 dns_adbnamelist_t *deadnames;
140 isc_mutex_t *namelocks;
141 isc_boolean_t *name_sd;
142 unsigned int *name_refcnt;
145 * Bucketized locks and lists for entries.
147 * XXXRTH Have a per-bucket structure that contains all of these?
149 unsigned int nentries;
150 isc_mutex_t entriescntlock;
151 unsigned int entriescnt;
152 dns_adbentrylist_t *entries;
153 dns_adbentrylist_t *deadentries;
154 isc_mutex_t *entrylocks;
155 isc_boolean_t *entry_sd; /*%< shutting down */
156 unsigned int *entry_refcnt;
159 isc_boolean_t cevent_out;
160 isc_boolean_t shutting_down;
161 isc_eventlist_t whenshutdown;
162 isc_event_t growentries;
163 isc_boolean_t growentries_sent;
164 isc_event_t grownames;
165 isc_boolean_t grownames_sent;
167 #ifdef ENABLE_FETCHLIMIT
169 isc_uint32_t atr_freq;
173 #endif /* ENABLE_FETCHLIMIT */
177 * XXXMLG Document these structures.
180 /*% dns_adbname structure */
185 unsigned int partial_result;
189 isc_stdtime_t expire_target;
190 isc_stdtime_t expire_v4;
191 isc_stdtime_t expire_v6;
193 dns_adbnamehooklist_t v4;
194 dns_adbnamehooklist_t v6;
195 dns_adbfetch_t *fetch_a;
196 dns_adbfetch_t *fetch_aaaa;
197 unsigned int fetch_err;
198 unsigned int fetch6_err;
199 dns_adbfindlist_t finds;
200 /* for LRU-based management */
201 isc_stdtime_t last_used;
203 ISC_LINK(dns_adbname_t) plink;
206 /*% The adbfetch structure */
207 struct dns_adbfetch {
210 dns_rdataset_t rdataset;
215 * This is a small widget that dangles off a dns_adbname_t. It contains a
216 * pointer to the address information about this host, and a link to the next
217 * namehook that will contain the next address this host has.
219 struct dns_adbnamehook {
221 dns_adbentry_t *entry;
222 ISC_LINK(dns_adbnamehook_t) plink;
226 * This is a small widget that holds qname-specific information about an
227 * address. Currently limited to lameness, but could just as easily be
228 * extended to other types of information about zones.
230 struct dns_adblameinfo {
234 dns_rdatatype_t qtype;
235 isc_stdtime_t lame_timer;
237 ISC_LINK(dns_adblameinfo_t) plink;
241 * An address entry. It holds quite a bit of information about addresses,
242 * including edns state (in "flags"), rtt, and of course the address of
245 struct dns_adbentry {
255 unsigned int timeouts;
256 unsigned int completed;
258 #ifdef ENABLE_FETCHLIMIT
263 #endif /* ENABLE_FETCHLIMIT */
265 isc_sockaddr_t sockaddr;
267 isc_stdtime_t expires;
268 isc_stdtime_t lastage;
270 * A nonzero 'expires' field indicates that the entry should
271 * persist until that time. This allows entries found
272 * using dns_adb_findaddrinfo() to persist for a limited time
273 * even though they are not necessarily associated with a
277 ISC_LIST(dns_adblameinfo_t) lameinfo;
278 ISC_LINK(dns_adbentry_t) plink;
283 * Internal functions (and prototypes).
285 static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
286 static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
287 static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
289 static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
290 static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
292 static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
293 static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
294 static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
295 static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
296 static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
297 static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
299 static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
300 static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
301 static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
302 unsigned int, int *);
303 static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
304 isc_sockaddr_t *, int *,
306 static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
307 static void print_dns_name(FILE *, dns_name_t *);
308 static void print_namehook_list(FILE *, const char *legend,
310 dns_adbnamehooklist_t *list,
313 static void print_find_list(FILE *, dns_adbname_t *);
314 static void print_fetch_list(FILE *, dns_adbname_t *);
315 static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
316 static inline void inc_adb_irefcnt(dns_adb_t *);
317 static inline void inc_adb_erefcnt(dns_adb_t *);
318 static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
320 static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
321 dns_adbentry_t *, isc_boolean_t);
322 static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
323 static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
324 static void clean_target(dns_adb_t *, dns_name_t *);
325 static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
326 static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
327 static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
329 static void cancel_fetches_at_name(dns_adbname_t *);
330 static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
332 static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
333 unsigned int, isc_counter_t *qc,
335 static inline void check_exit(dns_adb_t *);
336 static void destroy(dns_adb_t *);
337 static isc_boolean_t shutdown_names(dns_adb_t *);
338 static isc_boolean_t shutdown_entries(dns_adb_t *);
339 static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
340 static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
341 static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
342 static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
343 static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
344 static void water(void *, int);
345 static void dump_entry(FILE *, dns_adb_t *, dns_adbentry_t *,
346 isc_boolean_t, isc_stdtime_t);
347 static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt,
348 unsigned int factor, isc_stdtime_t now);
349 static void shutdown_task(isc_task_t *task, isc_event_t *ev);
350 #ifdef ENABLE_FETCHLIMIT
351 static void log_quota(dns_adbentry_t *entry, const char *fmt, ...)
352 ISC_FORMAT_PRINTF(2, 3);
353 #endif /* ENABLE_FETCHLIMIT */
356 * MUST NOT overlap DNS_ADBFIND_* flags!
358 #define FIND_EVENT_SENT 0x40000000
359 #define FIND_EVENT_FREED 0x80000000
360 #define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
361 #define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
363 #define NAME_NEEDS_POKE 0x80000000
364 #define NAME_IS_DEAD 0x40000000
365 #define NAME_HINT_OK DNS_ADBFIND_HINTOK
366 #define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
367 #define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
368 #define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
369 #define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
370 #define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
371 #define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
374 * Private flag(s) for entries.
375 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
377 #define ENTRY_IS_DEAD 0x00400000
380 * To the name, address classes are all that really exist. If it has a
381 * V6 address it doesn't care if it came from a AAAA query.
383 #define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
384 #define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
385 #define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
388 * Fetches are broken out into A and AAAA types. In some cases,
389 * however, it makes more sense to test for a particular class of fetches,
390 * like V4 or V6 above.
391 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
392 * are now equal to FETCH_V4 and FETCH_V6, respectively.
394 #define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
395 #define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
396 #define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
397 #define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
398 #define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
401 * Find options and tests to see if there are addresses on the list.
403 #define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
404 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
405 #define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
407 #define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
409 #define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
410 #define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
411 #define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
412 #define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
415 * These are currently used on simple unsigned ints, so they are
416 * not really associated with any particular type.
418 #define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
419 #define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
421 #define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
424 * Find out if the flags on a name (nf) indicate if it is a hint or
425 * glue, and compare this to the appropriate bits set in o, to see if
428 #define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
429 #define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
430 #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
431 #define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
432 ((o) & DNS_ADBFIND_STARTATZONE))
434 #define ENTER_LEVEL ISC_LOG_DEBUG(50)
435 #define EXIT_LEVEL ENTER_LEVEL
436 #define CLEAN_LEVEL ISC_LOG_DEBUG(100)
437 #define DEF_LEVEL ISC_LOG_DEBUG(5)
438 #define NCACHE_LEVEL ISC_LOG_DEBUG(20)
440 #define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
441 (r) == DNS_R_NCACHENXRRSET)
442 #define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
443 (r) == DNS_R_NXRRSET)
444 #define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
445 (r) == DNS_R_NCACHENXDOMAIN)
446 #define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
447 (r) == DNS_R_NXRRSET || \
448 (r) == DNS_R_HINTNXRRSET)
451 * Error state rankings.
454 #define FIND_ERR_SUCCESS 0 /* highest rank */
455 #define FIND_ERR_CANCELED 1
456 #define FIND_ERR_FAILURE 2
457 #define FIND_ERR_NXDOMAIN 3
458 #define FIND_ERR_NXRRSET 4
459 #define FIND_ERR_UNEXPECTED 5
460 #define FIND_ERR_NOTFOUND 6
461 #define FIND_ERR_MAX 7
463 static const char *errnames[] = {
473 #define NEWERR(old, new) (ISC_MIN((old), (new)))
475 static isc_result_t find_err_map[FIND_ERR_MAX] = {
482 ISC_R_NOTFOUND /* not YET found */
486 DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
489 DP(int level, const char *format, ...) {
492 va_start(args, format);
493 isc_log_vwrite(dns_lctx,
494 DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
495 level, format, args);
500 * Increment resolver-related statistics counters.
503 inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
504 if (adb->view->resstats != NULL)
505 isc_stats_increment(adb->view->resstats, counter);
508 static inline dns_ttl_t
509 ttlclamp(dns_ttl_t ttl) {
510 if (ttl < ADB_CACHE_MINIMUM)
511 ttl = ADB_CACHE_MINIMUM;
512 if (ttl > ADB_CACHE_MAXIMUM)
513 ttl = ADB_CACHE_MAXIMUM;
519 * Hashing is most efficient if the number of buckets is prime.
520 * The sequence below is the closest previous primes to 2^n and
521 * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
522 * no longer grow beyond 2^28 entries.)
524 static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
525 8191, 12281, 16381, 24571, 32749,
526 49193, 65521, 98299, 131071, 199603,
527 262139, 393209, 524287, 768431, 1048573,
528 1572853, 2097143, 3145721, 4194301,
529 6291449, 8388593, 12582893, 16777213,
530 25165813, 33554393, 50331599, 67108859,
531 100663291, 134217689, 201326557,
535 grow_entries(isc_task_t *task, isc_event_t *ev) {
538 dns_adbentrylist_t *newdeadentries = NULL;
539 dns_adbentrylist_t *newentries = NULL;
540 isc_boolean_t *newentry_sd = NULL;
541 isc_mutex_t *newentrylocks = NULL;
543 unsigned int *newentry_refcnt = NULL;
544 unsigned int i, n, bucket;
547 INSIST(DNS_ADB_VALID(adb));
551 result = isc_task_beginexclusive(task);
552 if (result != ISC_R_SUCCESS)
556 while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
558 if (nbuckets[i] != 0)
563 DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
566 * Are we shutting down?
568 for (i = 0; i < adb->nentries; i++)
569 if (adb->entry_sd[i])
573 * Grab all the resources we need.
575 newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
576 newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
577 newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
578 newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
579 newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
580 if (newentries == NULL || newdeadentries == NULL ||
581 newentrylocks == NULL || newentry_sd == NULL ||
582 newentry_refcnt == NULL)
586 * Initialise the new resources.
588 result = isc_mutexblock_init(newentrylocks, n);
589 if (result != ISC_R_SUCCESS)
592 for (i = 0; i < n; i++) {
593 ISC_LIST_INIT(newentries[i]);
594 ISC_LIST_INIT(newdeadentries[i]);
595 newentry_sd[i] = ISC_FALSE;
596 newentry_refcnt[i] = 0;
601 * Move entries to new arrays.
603 for (i = 0; i < adb->nentries; i++) {
604 e = ISC_LIST_HEAD(adb->entries[i]);
606 ISC_LIST_UNLINK(adb->entries[i], e, plink);
607 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
608 e->lock_bucket = bucket;
609 ISC_LIST_APPEND(newentries[bucket], e, plink);
610 INSIST(adb->entry_refcnt[i] > 0);
611 adb->entry_refcnt[i]--;
612 newentry_refcnt[bucket]++;
613 e = ISC_LIST_HEAD(adb->entries[i]);
615 e = ISC_LIST_HEAD(adb->deadentries[i]);
617 ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
618 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
619 e->lock_bucket = bucket;
620 ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
621 INSIST(adb->entry_refcnt[i] > 0);
622 adb->entry_refcnt[i]--;
623 newentry_refcnt[bucket]++;
624 e = ISC_LIST_HEAD(adb->deadentries[i]);
626 INSIST(adb->entry_refcnt[i] == 0);
631 * Cleanup old resources.
633 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
634 isc_mem_put(adb->mctx, adb->entries,
635 sizeof(*adb->entries) * adb->nentries);
636 isc_mem_put(adb->mctx, adb->deadentries,
637 sizeof(*adb->deadentries) * adb->nentries);
638 isc_mem_put(adb->mctx, adb->entrylocks,
639 sizeof(*adb->entrylocks) * adb->nentries);
640 isc_mem_put(adb->mctx, adb->entry_sd,
641 sizeof(*adb->entry_sd) * adb->nentries);
642 isc_mem_put(adb->mctx, adb->entry_refcnt,
643 sizeof(*adb->entry_refcnt) * adb->nentries);
646 * Install new resources.
648 adb->entries = newentries;
649 adb->deadentries = newdeadentries;
650 adb->entrylocks = newentrylocks;
651 adb->entry_sd = newentry_sd;
652 adb->entry_refcnt = newentry_refcnt;
656 * Only on success do we set adb->growentries_sent to ISC_FALSE.
657 * This will prevent us being continuously being called on error.
659 adb->growentries_sent = ISC_FALSE;
663 if (newentries != NULL)
664 isc_mem_put(adb->mctx, newentries,
665 sizeof(*newentries) * n);
666 if (newdeadentries != NULL)
667 isc_mem_put(adb->mctx, newdeadentries,
668 sizeof(*newdeadentries) * n);
669 if (newentrylocks != NULL)
670 isc_mem_put(adb->mctx, newentrylocks,
671 sizeof(*newentrylocks) * n);
672 if (newentry_sd != NULL)
673 isc_mem_put(adb->mctx, newentry_sd,
674 sizeof(*newentry_sd) * n);
675 if (newentry_refcnt != NULL)
676 isc_mem_put(adb->mctx, newentry_refcnt,
677 sizeof(*newentry_refcnt) * n);
679 isc_task_endexclusive(task);
683 if (dec_adb_irefcnt(adb))
686 DP(ISC_LOG_INFO, "adb: grow_entries finished");
690 grow_names(isc_task_t *task, isc_event_t *ev) {
693 dns_adbnamelist_t *newdeadnames = NULL;
694 dns_adbnamelist_t *newnames = NULL;
695 isc_boolean_t *newname_sd = NULL;
696 isc_mutex_t *newnamelocks = NULL;
698 unsigned int *newname_refcnt = NULL;
699 unsigned int i, n, bucket;
702 INSIST(DNS_ADB_VALID(adb));
706 result = isc_task_beginexclusive(task);
707 if (result != ISC_R_SUCCESS)
711 while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
713 if (nbuckets[i] != 0)
718 DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
721 * Are we shutting down?
723 for (i = 0; i < adb->nnames; i++)
728 * Grab all the resources we need.
730 newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
731 newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
732 newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
733 newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
734 newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
735 if (newnames == NULL || newdeadnames == NULL ||
736 newnamelocks == NULL || newname_sd == NULL ||
737 newname_refcnt == NULL)
741 * Initialise the new resources.
743 result = isc_mutexblock_init(newnamelocks, n);
744 if (result != ISC_R_SUCCESS)
747 for (i = 0; i < n; i++) {
748 ISC_LIST_INIT(newnames[i]);
749 ISC_LIST_INIT(newdeadnames[i]);
750 newname_sd[i] = ISC_FALSE;
751 newname_refcnt[i] = 0;
756 * Move names to new arrays.
758 for (i = 0; i < adb->nnames; i++) {
759 name = ISC_LIST_HEAD(adb->names[i]);
760 while (name != NULL) {
761 ISC_LIST_UNLINK(adb->names[i], name, plink);
762 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
763 name->lock_bucket = bucket;
764 ISC_LIST_APPEND(newnames[bucket], name, plink);
765 INSIST(adb->name_refcnt[i] > 0);
766 adb->name_refcnt[i]--;
767 newname_refcnt[bucket]++;
768 name = ISC_LIST_HEAD(adb->names[i]);
770 name = ISC_LIST_HEAD(adb->deadnames[i]);
771 while (name != NULL) {
772 ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
773 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
774 name->lock_bucket = bucket;
775 ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
776 INSIST(adb->name_refcnt[i] > 0);
777 adb->name_refcnt[i]--;
778 newname_refcnt[bucket]++;
779 name = ISC_LIST_HEAD(adb->deadnames[i]);
781 INSIST(adb->name_refcnt[i] == 0);
786 * Cleanup old resources.
788 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
789 isc_mem_put(adb->mctx, adb->names,
790 sizeof(*adb->names) * adb->nnames);
791 isc_mem_put(adb->mctx, adb->deadnames,
792 sizeof(*adb->deadnames) * adb->nnames);
793 isc_mem_put(adb->mctx, adb->namelocks,
794 sizeof(*adb->namelocks) * adb->nnames);
795 isc_mem_put(adb->mctx, adb->name_sd,
796 sizeof(*adb->name_sd) * adb->nnames);
797 isc_mem_put(adb->mctx, adb->name_refcnt,
798 sizeof(*adb->name_refcnt) * adb->nnames);
801 * Install new resources.
803 adb->names = newnames;
804 adb->deadnames = newdeadnames;
805 adb->namelocks = newnamelocks;
806 adb->name_sd = newname_sd;
807 adb->name_refcnt = newname_refcnt;
811 * Only on success do we set adb->grownames_sent to ISC_FALSE.
812 * This will prevent us being continuously being called on error.
814 adb->grownames_sent = ISC_FALSE;
818 if (newnames != NULL)
819 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
820 if (newdeadnames != NULL)
821 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
822 if (newnamelocks != NULL)
823 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
824 if (newname_sd != NULL)
825 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
826 if (newname_refcnt != NULL)
827 isc_mem_put(adb->mctx, newname_refcnt,
828 sizeof(*newname_refcnt) * n);
830 isc_task_endexclusive(task);
834 if (dec_adb_irefcnt(adb))
837 DP(ISC_LOG_INFO, "adb: grow_names finished");
841 * Requires the adbname bucket be locked and that no entry buckets be locked.
843 * This code handles A and AAAA rdatasets only.
846 import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
851 dns_adbnamehook_t *nh;
852 dns_adbnamehook_t *anh;
853 dns_rdata_t rdata = DNS_RDATA_INIT;
855 struct in6_addr in6a;
856 isc_sockaddr_t sockaddr;
857 dns_adbentry_t *foundentry; /* NO CLEAN UP! */
859 isc_boolean_t new_addresses_added;
860 dns_rdatatype_t rdtype;
861 unsigned int findoptions;
862 dns_adbnamehooklist_t *hookhead;
864 INSIST(DNS_ADBNAME_VALID(adbname));
866 INSIST(DNS_ADB_VALID(adb));
868 rdtype = rdataset->type;
869 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
870 if (rdtype == dns_rdatatype_a)
871 findoptions = DNS_ADBFIND_INET;
873 findoptions = DNS_ADBFIND_INET6;
875 addr_bucket = DNS_ADB_INVALIDBUCKET;
876 new_addresses_added = ISC_FALSE;
879 result = dns_rdataset_first(rdataset);
880 while (result == ISC_R_SUCCESS) {
881 dns_rdata_reset(&rdata);
882 dns_rdataset_current(rdataset, &rdata);
883 if (rdtype == dns_rdatatype_a) {
884 INSIST(rdata.length == 4);
885 memmove(&ina.s_addr, rdata.data, 4);
886 isc_sockaddr_fromin(&sockaddr, &ina, 0);
887 hookhead = &adbname->v4;
889 INSIST(rdata.length == 16);
890 memmove(in6a.s6_addr, rdata.data, 16);
891 isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
892 hookhead = &adbname->v6;
896 nh = new_adbnamehook(adb, NULL);
898 adbname->partial_result |= findoptions;
899 result = ISC_R_NOMEMORY;
903 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
905 if (foundentry == NULL) {
906 dns_adbentry_t *entry;
908 entry = new_adbentry(adb);
910 adbname->partial_result |= findoptions;
911 result = ISC_R_NOMEMORY;
915 entry->sockaddr = sockaddr;
921 link_entry(adb, addr_bucket, entry);
923 for (anh = ISC_LIST_HEAD(*hookhead);
925 anh = ISC_LIST_NEXT(anh, plink))
926 if (anh->entry == foundentry)
929 foundentry->refcnt++;
931 nh->entry = foundentry;
933 free_adbnamehook(adb, &nh);
936 new_addresses_added = ISC_TRUE;
938 ISC_LIST_APPEND(*hookhead, nh, plink);
940 result = dns_rdataset_next(rdataset);
945 free_adbnamehook(adb, &nh);
947 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
948 UNLOCK(&adb->entrylocks[addr_bucket]);
950 if (rdataset->trust == dns_trust_glue ||
951 rdataset->trust == dns_trust_additional)
952 rdataset->ttl = ADB_CACHE_MINIMUM;
953 else if (rdataset->trust == dns_trust_ultimate)
956 rdataset->ttl = ttlclamp(rdataset->ttl);
958 if (rdtype == dns_rdatatype_a) {
959 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
960 adbname->expire_v4, now + rdataset->ttl);
961 adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
962 now + rdataset->ttl);
964 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
965 adbname->expire_v6, now + rdataset->ttl);
966 adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
967 now + rdataset->ttl);
970 if (new_addresses_added) {
972 * Lie a little here. This is more or less so code that cares
973 * can find out if any new information was added or not.
975 return (ISC_R_SUCCESS);
982 * Requires the name's bucket be locked.
985 kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
987 isc_boolean_t result = ISC_FALSE;
988 isc_boolean_t result4, result6;
995 INSIST(DNS_ADBNAME_VALID(name));
997 INSIST(DNS_ADB_VALID(adb));
999 DP(DEF_LEVEL, "killing name %p", name);
1002 * If we're dead already, just check to see if we should go
1005 if (NAME_DEAD(name) && !NAME_FETCH(name)) {
1006 result = unlink_name(adb, name);
1007 free_adbname(adb, &name);
1009 result = dec_adb_irefcnt(adb);
1014 * Clean up the name's various lists. These two are destructive
1015 * in that they will always empty the list.
1017 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
1018 result4 = clean_namehooks(adb, &name->v4);
1019 result6 = clean_namehooks(adb, &name->v6);
1020 clean_target(adb, &name->target);
1021 result = ISC_TF(result4 || result6);
1024 * If fetches are running, cancel them. If none are running, we can
1025 * just kill the name here.
1027 if (!NAME_FETCH(name)) {
1028 INSIST(result == ISC_FALSE);
1029 result = unlink_name(adb, name);
1030 free_adbname(adb, &name);
1032 result = dec_adb_irefcnt(adb);
1034 cancel_fetches_at_name(name);
1035 if (!NAME_DEAD(name)) {
1036 bucket = name->lock_bucket;
1037 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1038 ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
1039 name->flags |= NAME_IS_DEAD;
1046 * Requires the name's bucket be locked and no entry buckets be locked.
1048 static isc_boolean_t
1049 check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
1051 isc_boolean_t result4 = ISC_FALSE;
1052 isc_boolean_t result6 = ISC_FALSE;
1054 INSIST(DNS_ADBNAME_VALID(name));
1056 INSIST(DNS_ADB_VALID(adb));
1059 * Check to see if we need to remove the v4 addresses
1061 if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
1062 if (NAME_HAS_V4(name)) {
1063 DP(DEF_LEVEL, "expiring v4 for name %p", name);
1064 result4 = clean_namehooks(adb, &name->v4);
1065 name->partial_result &= ~DNS_ADBFIND_INET;
1067 name->expire_v4 = INT_MAX;
1068 name->fetch_err = FIND_ERR_UNEXPECTED;
1072 * Check to see if we need to remove the v6 addresses
1074 if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
1075 if (NAME_HAS_V6(name)) {
1076 DP(DEF_LEVEL, "expiring v6 for name %p", name);
1077 result6 = clean_namehooks(adb, &name->v6);
1078 name->partial_result &= ~DNS_ADBFIND_INET6;
1080 name->expire_v6 = INT_MAX;
1081 name->fetch6_err = FIND_ERR_UNEXPECTED;
1085 * Check to see if we need to remove the alias target.
1087 if (EXPIRE_OK(name->expire_target, now)) {
1088 clean_target(adb, &name->target);
1089 name->expire_target = INT_MAX;
1091 return (ISC_TF(result4 || result6));
1095 * Requires the name's bucket be locked.
1098 link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1099 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
1101 ISC_LIST_PREPEND(adb->names[bucket], name, plink);
1102 name->lock_bucket = bucket;
1103 adb->name_refcnt[bucket]++;
1107 * Requires the name's bucket be locked.
1109 static inline isc_boolean_t
1110 unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
1112 isc_boolean_t result = ISC_FALSE;
1114 bucket = name->lock_bucket;
1115 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1117 if (NAME_DEAD(name))
1118 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
1120 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1121 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1122 INSIST(adb->name_refcnt[bucket] > 0);
1123 adb->name_refcnt[bucket]--;
1124 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
1130 * Requires the entry's bucket be locked.
1133 link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
1137 if (isc_mem_isovermem(adb->mctx)) {
1138 for (i = 0; i < 2; i++) {
1139 e = ISC_LIST_TAIL(adb->entries[bucket]);
1142 if (e->refcnt == 0) {
1143 unlink_entry(adb, e);
1144 free_adbentry(adb, &e);
1147 INSIST((e->flags & ENTRY_IS_DEAD) == 0);
1148 e->flags |= ENTRY_IS_DEAD;
1149 ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
1150 ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
1154 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
1155 entry->lock_bucket = bucket;
1156 adb->entry_refcnt[bucket]++;
1160 * Requires the entry's bucket be locked.
1162 static inline isc_boolean_t
1163 unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
1165 isc_boolean_t result = ISC_FALSE;
1167 bucket = entry->lock_bucket;
1168 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1170 if ((entry->flags & ENTRY_IS_DEAD) != 0)
1171 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
1173 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
1174 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1175 INSIST(adb->entry_refcnt[bucket] > 0);
1176 adb->entry_refcnt[bucket]--;
1177 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
1183 violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
1184 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
1192 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1193 * checked after calling this function.
1195 static isc_boolean_t
1196 shutdown_names(dns_adb_t *adb) {
1197 unsigned int bucket;
1198 isc_boolean_t result = ISC_FALSE;
1199 dns_adbname_t *name;
1200 dns_adbname_t *next_name;
1202 for (bucket = 0; bucket < adb->nnames; bucket++) {
1203 LOCK(&adb->namelocks[bucket]);
1204 adb->name_sd[bucket] = ISC_TRUE;
1206 name = ISC_LIST_HEAD(adb->names[bucket]);
1209 * This bucket has no names. We must decrement the
1210 * irefcnt ourselves, since it will not be
1211 * automatically triggered by a name being unlinked.
1213 INSIST(result == ISC_FALSE);
1214 result = dec_adb_irefcnt(adb);
1217 * Run through the list. For each name, clean up finds
1218 * found there, and cancel any fetches running. When
1219 * all the fetches are canceled, the name will destroy
1222 while (name != NULL) {
1223 next_name = ISC_LIST_NEXT(name, plink);
1224 INSIST(result == ISC_FALSE);
1225 result = kill_name(&name,
1226 DNS_EVENT_ADBSHUTDOWN);
1231 UNLOCK(&adb->namelocks[bucket]);
1237 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1238 * checked after calling this function.
1240 static isc_boolean_t
1241 shutdown_entries(dns_adb_t *adb) {
1242 unsigned int bucket;
1243 isc_boolean_t result = ISC_FALSE;
1244 dns_adbentry_t *entry;
1245 dns_adbentry_t *next_entry;
1247 for (bucket = 0; bucket < adb->nentries; bucket++) {
1248 LOCK(&adb->entrylocks[bucket]);
1249 adb->entry_sd[bucket] = ISC_TRUE;
1251 entry = ISC_LIST_HEAD(adb->entries[bucket]);
1252 if (adb->entry_refcnt[bucket] == 0) {
1254 * This bucket has no entries. We must decrement the
1255 * irefcnt ourselves, since it will not be
1256 * automatically triggered by an entry being unlinked.
1258 result = dec_adb_irefcnt(adb);
1261 * Run through the list. Cleanup any entries not
1262 * associated with names, and which are not in use.
1264 while (entry != NULL) {
1265 next_entry = ISC_LIST_NEXT(entry, plink);
1266 if (entry->refcnt == 0 &&
1267 entry->expires != 0) {
1268 result = unlink_entry(adb, entry);
1269 free_adbentry(adb, &entry);
1271 result = dec_adb_irefcnt(adb);
1277 UNLOCK(&adb->entrylocks[bucket]);
1283 * Name bucket must be locked
1286 cancel_fetches_at_name(dns_adbname_t *name) {
1287 if (NAME_FETCH_A(name))
1288 dns_resolver_cancelfetch(name->fetch_a->fetch);
1290 if (NAME_FETCH_AAAA(name))
1291 dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
1295 * Assumes the name bucket is locked.
1297 static isc_boolean_t
1298 clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
1299 dns_adbentry_t *entry;
1300 dns_adbnamehook_t *namehook;
1302 isc_boolean_t result = ISC_FALSE;
1303 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
1305 addr_bucket = DNS_ADB_INVALIDBUCKET;
1306 namehook = ISC_LIST_HEAD(*namehooks);
1307 while (namehook != NULL) {
1308 INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
1311 * Clean up the entry if needed.
1313 entry = namehook->entry;
1314 if (entry != NULL) {
1315 INSIST(DNS_ADBENTRY_VALID(entry));
1317 if (addr_bucket != entry->lock_bucket) {
1318 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1319 UNLOCK(&adb->entrylocks[addr_bucket]);
1320 addr_bucket = entry->lock_bucket;
1321 INSIST(addr_bucket != DNS_ADB_INVALIDBUCKET);
1322 LOCK(&adb->entrylocks[addr_bucket]);
1326 result = dec_entry_refcnt(adb, overmem, entry,
1333 namehook->entry = NULL;
1334 ISC_LIST_UNLINK(*namehooks, namehook, plink);
1335 free_adbnamehook(adb, &namehook);
1337 namehook = ISC_LIST_HEAD(*namehooks);
1340 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1341 UNLOCK(&adb->entrylocks[addr_bucket]);
1346 clean_target(dns_adb_t *adb, dns_name_t *target) {
1347 if (dns_name_countlabels(target) > 0) {
1348 dns_name_free(target, adb->mctx);
1349 dns_name_init(target, NULL);
1354 set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
1355 dns_rdataset_t *rdataset, dns_name_t *target)
1357 isc_result_t result;
1358 dns_namereln_t namereln;
1359 unsigned int nlabels;
1361 dns_rdata_t rdata = DNS_RDATA_INIT;
1362 dns_fixedname_t fixed1, fixed2;
1363 dns_name_t *prefix, *new_target;
1365 REQUIRE(dns_name_countlabels(target) == 0);
1367 if (rdataset->type == dns_rdatatype_cname) {
1368 dns_rdata_cname_t cname;
1371 * Copy the CNAME's target into the target name.
1373 result = dns_rdataset_first(rdataset);
1374 if (result != ISC_R_SUCCESS)
1376 dns_rdataset_current(rdataset, &rdata);
1377 result = dns_rdata_tostruct(&rdata, &cname, NULL);
1378 if (result != ISC_R_SUCCESS)
1380 result = dns_name_dup(&cname.cname, adb->mctx, target);
1381 dns_rdata_freestruct(&cname);
1382 if (result != ISC_R_SUCCESS)
1385 dns_rdata_dname_t dname;
1387 INSIST(rdataset->type == dns_rdatatype_dname);
1388 namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
1389 INSIST(namereln == dns_namereln_subdomain);
1391 * Get the target name of the DNAME.
1393 result = dns_rdataset_first(rdataset);
1394 if (result != ISC_R_SUCCESS)
1396 dns_rdataset_current(rdataset, &rdata);
1397 result = dns_rdata_tostruct(&rdata, &dname, NULL);
1398 if (result != ISC_R_SUCCESS)
1401 * Construct the new target name.
1403 dns_fixedname_init(&fixed1);
1404 prefix = dns_fixedname_name(&fixed1);
1405 dns_fixedname_init(&fixed2);
1406 new_target = dns_fixedname_name(&fixed2);
1407 dns_name_split(name, nlabels, prefix, NULL);
1408 result = dns_name_concatenate(prefix, &dname.dname, new_target,
1410 dns_rdata_freestruct(&dname);
1411 if (result != ISC_R_SUCCESS)
1413 result = dns_name_dup(new_target, adb->mctx, target);
1414 if (result != ISC_R_SUCCESS)
1418 return (ISC_R_SUCCESS);
1422 * Assumes nothing is locked, since this is called by the client.
1425 event_free(isc_event_t *event) {
1426 dns_adbfind_t *find;
1428 INSIST(event != NULL);
1429 find = event->ev_destroy_arg;
1430 INSIST(DNS_ADBFIND_VALID(find));
1433 find->flags |= FIND_EVENT_FREED;
1434 event->ev_destroy_arg = NULL;
1435 UNLOCK(&find->lock);
1439 * Assumes the name bucket is locked.
1442 clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
1447 dns_adbfind_t *find;
1448 dns_adbfind_t *next_find;
1449 isc_boolean_t process;
1450 unsigned int wanted, notify;
1453 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1454 name, evtype, addrs);
1456 find = ISC_LIST_HEAD(name->finds);
1457 while (find != NULL) {
1459 next_find = ISC_LIST_NEXT(find, plink);
1461 process = ISC_FALSE;
1462 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1463 notify = wanted & addrs;
1466 case DNS_EVENT_ADBMOREADDRESSES:
1467 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1468 if ((notify) != 0) {
1469 find->flags &= ~addrs;
1473 case DNS_EVENT_ADBNOMOREADDRESSES:
1474 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1475 find->flags &= ~addrs;
1476 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1481 find->flags &= ~addrs;
1486 DP(DEF_LEVEL, "cfan: processing find %p", find);
1488 * Unlink the find from the name, letting the caller
1489 * call dns_adb_destroyfind() on it to clean it up
1492 ISC_LIST_UNLINK(name->finds, find, plink);
1493 find->adbname = NULL;
1494 find->name_bucket = DNS_ADB_INVALIDBUCKET;
1496 INSIST(!FIND_EVENTSENT(find));
1499 task = ev->ev_sender;
1500 ev->ev_sender = find;
1501 find->result_v4 = find_err_map[name->fetch_err];
1502 find->result_v6 = find_err_map[name->fetch6_err];
1503 ev->ev_type = evtype;
1504 ev->ev_destroy = event_free;
1505 ev->ev_destroy_arg = find;
1508 "sending event %p to task %p for find %p",
1511 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
1512 find->flags |= FIND_EVENT_SENT;
1514 DP(DEF_LEVEL, "cfan: skipping find %p", find);
1517 UNLOCK(&find->lock);
1521 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
1525 check_exit(dns_adb_t *adb) {
1528 * The caller must be holding the adb lock.
1530 if (adb->shutting_down) {
1532 * If there aren't any external references either, we're
1533 * done. Send the control event to initiate shutdown.
1535 INSIST(!adb->cevent_out); /* Sanity check. */
1536 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
1537 DNS_EVENT_ADBCONTROL, shutdown_task, adb,
1539 event = &adb->cevent;
1540 isc_task_send(adb->task, &event);
1541 adb->cevent_out = ISC_TRUE;
1545 static inline isc_boolean_t
1546 dec_adb_irefcnt(dns_adb_t *adb) {
1549 isc_boolean_t result = ISC_FALSE;
1551 LOCK(&adb->reflock);
1553 INSIST(adb->irefcnt > 0);
1556 if (adb->irefcnt == 0) {
1557 event = ISC_LIST_HEAD(adb->whenshutdown);
1558 while (event != NULL) {
1559 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
1560 etask = event->ev_sender;
1561 event->ev_sender = adb;
1562 isc_task_sendanddetach(&etask, &event);
1563 event = ISC_LIST_HEAD(adb->whenshutdown);
1567 if (adb->irefcnt == 0 && adb->erefcnt == 0)
1569 UNLOCK(&adb->reflock);
1574 inc_adb_irefcnt(dns_adb_t *adb) {
1575 LOCK(&adb->reflock);
1577 UNLOCK(&adb->reflock);
1581 inc_adb_erefcnt(dns_adb_t *adb) {
1582 LOCK(&adb->reflock);
1584 UNLOCK(&adb->reflock);
1588 inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
1591 bucket = entry->lock_bucket;
1594 LOCK(&adb->entrylocks[bucket]);
1599 UNLOCK(&adb->entrylocks[bucket]);
1602 static inline isc_boolean_t
1603 dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
1607 isc_boolean_t destroy_entry;
1608 isc_boolean_t result = ISC_FALSE;
1610 bucket = entry->lock_bucket;
1613 LOCK(&adb->entrylocks[bucket]);
1615 INSIST(entry->refcnt > 0);
1618 destroy_entry = ISC_FALSE;
1619 if (entry->refcnt == 0 &&
1620 (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
1621 (entry->flags & ENTRY_IS_DEAD) != 0)) {
1622 destroy_entry = ISC_TRUE;
1623 result = unlink_entry(adb, entry);
1627 UNLOCK(&adb->entrylocks[bucket]);
1632 entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1634 free_adbentry(adb, &entry);
1636 result = dec_adb_irefcnt(adb);
1641 static inline dns_adbname_t *
1642 new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
1643 dns_adbname_t *name;
1645 name = isc_mempool_get(adb->nmp);
1649 dns_name_init(&name->name, NULL);
1650 if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
1651 isc_mempool_put(adb->nmp, name);
1654 dns_name_init(&name->target, NULL);
1655 name->magic = DNS_ADBNAME_MAGIC;
1657 name->partial_result = 0;
1659 name->expire_v4 = INT_MAX;
1660 name->expire_v6 = INT_MAX;
1661 name->expire_target = INT_MAX;
1663 name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1664 ISC_LIST_INIT(name->v4);
1665 ISC_LIST_INIT(name->v6);
1666 name->fetch_a = NULL;
1667 name->fetch_aaaa = NULL;
1668 name->fetch_err = FIND_ERR_UNEXPECTED;
1669 name->fetch6_err = FIND_ERR_UNEXPECTED;
1670 ISC_LIST_INIT(name->finds);
1671 ISC_LINK_INIT(name, plink);
1673 LOCK(&adb->namescntlock);
1675 if (!adb->grownames_sent && adb->excl != NULL &&
1676 adb->namescnt > (adb->nnames * 8))
1678 isc_event_t *event = &adb->grownames;
1679 inc_adb_irefcnt(adb);
1680 isc_task_send(adb->excl, &event);
1681 adb->grownames_sent = ISC_TRUE;
1683 UNLOCK(&adb->namescntlock);
1689 free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
1692 INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
1696 INSIST(!NAME_HAS_V4(n));
1697 INSIST(!NAME_HAS_V6(n));
1698 INSIST(!NAME_FETCH(n));
1699 INSIST(ISC_LIST_EMPTY(n->finds));
1700 INSIST(!ISC_LINK_LINKED(n, plink));
1701 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
1702 INSIST(n->adb == adb);
1705 dns_name_free(&n->name, adb->mctx);
1707 isc_mempool_put(adb->nmp, n);
1708 LOCK(&adb->namescntlock);
1710 UNLOCK(&adb->namescntlock);
1713 static inline dns_adbnamehook_t *
1714 new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
1715 dns_adbnamehook_t *nh;
1717 nh = isc_mempool_get(adb->nhmp);
1721 nh->magic = DNS_ADBNAMEHOOK_MAGIC;
1723 ISC_LINK_INIT(nh, plink);
1729 free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
1730 dns_adbnamehook_t *nh;
1732 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
1736 INSIST(nh->entry == NULL);
1737 INSIST(!ISC_LINK_LINKED(nh, plink));
1740 isc_mempool_put(adb->nhmp, nh);
1743 static inline dns_adblameinfo_t *
1744 new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
1745 dns_adblameinfo_t *li;
1747 li = isc_mempool_get(adb->limp);
1751 dns_name_init(&li->qname, NULL);
1752 if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
1753 isc_mempool_put(adb->limp, li);
1756 li->magic = DNS_ADBLAMEINFO_MAGIC;
1759 ISC_LINK_INIT(li, plink);
1765 free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
1766 dns_adblameinfo_t *li;
1768 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
1772 INSIST(!ISC_LINK_LINKED(li, plink));
1774 dns_name_free(&li->qname, adb->mctx);
1778 isc_mempool_put(adb->limp, li);
1781 static inline dns_adbentry_t *
1782 new_adbentry(dns_adb_t *adb) {
1786 e = isc_mempool_get(adb->emp);
1790 e->magic = DNS_ADBENTRY_MAGIC;
1791 e->lock_bucket = DNS_ADB_INVALIDBUCKET;
1798 e->srtt = (r & 0x1f) + 1;
1801 #ifdef ENABLE_FETCHLIMIT
1804 e->quota = adb->quota;
1806 #endif /* ENABLE_FETCHLIMIT */
1807 ISC_LIST_INIT(e->lameinfo);
1808 ISC_LINK_INIT(e, plink);
1809 LOCK(&adb->entriescntlock);
1811 if (!adb->growentries_sent && adb->excl != NULL &&
1812 adb->entriescnt > (adb->nentries * 8))
1814 isc_event_t *event = &adb->growentries;
1815 inc_adb_irefcnt(adb);
1816 isc_task_send(adb->excl, &event);
1817 adb->growentries_sent = ISC_TRUE;
1819 UNLOCK(&adb->entriescntlock);
1825 free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
1827 dns_adblameinfo_t *li;
1829 INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
1833 INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
1834 INSIST(e->refcnt == 0);
1835 INSIST(!ISC_LINK_LINKED(e, plink));
1839 li = ISC_LIST_HEAD(e->lameinfo);
1840 while (li != NULL) {
1841 ISC_LIST_UNLINK(e->lameinfo, li, plink);
1842 free_adblameinfo(adb, &li);
1843 li = ISC_LIST_HEAD(e->lameinfo);
1846 isc_mempool_put(adb->emp, e);
1847 LOCK(&adb->entriescntlock);
1849 UNLOCK(&adb->entriescntlock);
1852 static inline dns_adbfind_t *
1853 new_adbfind(dns_adb_t *adb) {
1855 isc_result_t result;
1857 h = isc_mempool_get(adb->ahmp);
1866 h->partial_result = 0;
1869 h->result_v4 = ISC_R_UNEXPECTED;
1870 h->result_v6 = ISC_R_UNEXPECTED;
1871 ISC_LINK_INIT(h, publink);
1872 ISC_LINK_INIT(h, plink);
1873 ISC_LIST_INIT(h->list);
1875 h->name_bucket = DNS_ADB_INVALIDBUCKET;
1880 result = isc_mutex_init(&h->lock);
1881 if (result != ISC_R_SUCCESS) {
1882 isc_mempool_put(adb->ahmp, h);
1886 ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
1889 inc_adb_irefcnt(adb);
1890 h->magic = DNS_ADBFIND_MAGIC;
1894 static inline dns_adbfetch_t *
1895 new_adbfetch(dns_adb_t *adb) {
1898 f = isc_mempool_get(adb->afmp);
1905 dns_rdataset_init(&f->rdataset);
1907 f->magic = DNS_ADBFETCH_MAGIC;
1913 free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
1916 INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
1922 if (dns_rdataset_isassociated(&f->rdataset))
1923 dns_rdataset_disassociate(&f->rdataset);
1925 isc_mempool_put(adb->afmp, f);
1928 static inline isc_boolean_t
1929 free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
1930 dns_adbfind_t *find;
1932 INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
1936 INSIST(!FIND_HAS_ADDRS(find));
1937 INSIST(!ISC_LINK_LINKED(find, publink));
1938 INSIST(!ISC_LINK_LINKED(find, plink));
1939 INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
1940 INSIST(find->adbname == NULL);
1944 DESTROYLOCK(&find->lock);
1945 isc_mempool_put(adb->ahmp, find);
1946 return (dec_adb_irefcnt(adb));
1950 * Copy bits from the entry into the newly allocated addrinfo. The entry
1951 * must be locked, and the reference count must be bumped up by one
1952 * if this function returns a valid pointer.
1954 static inline dns_adbaddrinfo_t *
1955 new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
1956 dns_adbaddrinfo_t *ai;
1958 ai = isc_mempool_get(adb->aimp);
1962 ai->magic = DNS_ADBADDRINFO_MAGIC;
1963 ai->sockaddr = entry->sockaddr;
1964 isc_sockaddr_setport(&ai->sockaddr, port);
1965 ai->srtt = entry->srtt;
1966 ai->flags = entry->flags;
1968 ISC_LINK_INIT(ai, publink);
1974 free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
1975 dns_adbaddrinfo_t *ai;
1977 INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
1981 INSIST(ai->entry == NULL);
1982 INSIST(!ISC_LINK_LINKED(ai, publink));
1986 isc_mempool_put(adb->aimp, ai);
1990 * Search for the name. NOTE: The bucket is kept locked on both
1991 * success and failure, so it must always be unlocked by the caller!
1993 * On the first call to this function, *bucketp must be set to
1994 * DNS_ADB_INVALIDBUCKET.
1996 static inline dns_adbname_t *
1997 find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
1998 unsigned int options, int *bucketp)
2000 dns_adbname_t *adbname;
2003 bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
2005 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
2006 LOCK(&adb->namelocks[bucket]);
2008 } else if (*bucketp != bucket) {
2009 UNLOCK(&adb->namelocks[*bucketp]);
2010 LOCK(&adb->namelocks[bucket]);
2014 adbname = ISC_LIST_HEAD(adb->names[bucket]);
2015 while (adbname != NULL) {
2016 if (!NAME_DEAD(adbname)) {
2017 if (dns_name_equal(name, &adbname->name)
2018 && GLUEHINT_OK(adbname, options)
2019 && STARTATZONE_MATCHES(adbname, options))
2022 adbname = ISC_LIST_NEXT(adbname, plink);
2029 * Search for the address. NOTE: The bucket is kept locked on both
2030 * success and failure, so it must always be unlocked by the caller.
2032 * On the first call to this function, *bucketp must be set to
2033 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
2034 * later calls (within the same "lock path") it can be left alone, so
2035 * if this function is called multiple times locking is only done if
2036 * the bucket changes.
2038 static inline dns_adbentry_t *
2039 find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
2042 dns_adbentry_t *entry, *entry_next;
2045 bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
2047 if (*bucketp == DNS_ADB_INVALIDBUCKET) {
2048 LOCK(&adb->entrylocks[bucket]);
2050 } else if (*bucketp != bucket) {
2051 UNLOCK(&adb->entrylocks[*bucketp]);
2052 LOCK(&adb->entrylocks[bucket]);
2056 /* Search the list, while cleaning up expired entries. */
2057 for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
2059 entry = entry_next) {
2060 entry_next = ISC_LIST_NEXT(entry, plink);
2061 (void)check_expire_entry(adb, &entry, now);
2062 if (entry != NULL &&
2063 isc_sockaddr_equal(addr, &entry->sockaddr)) {
2064 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
2065 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
2074 * Entry bucket MUST be locked!
2076 static isc_boolean_t
2077 entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
2078 dns_rdatatype_t qtype, isc_stdtime_t now)
2080 dns_adblameinfo_t *li, *next_li;
2081 isc_boolean_t is_bad;
2085 li = ISC_LIST_HEAD(entry->lameinfo);
2088 while (li != NULL) {
2089 next_li = ISC_LIST_NEXT(li, plink);
2092 * Has the entry expired?
2094 if (li->lame_timer < now) {
2095 ISC_LIST_UNLINK(entry->lameinfo, li, plink);
2096 free_adblameinfo(adb, &li);
2100 * Order tests from least to most expensive.
2102 * We do not break out of the main loop here as
2103 * we use the loop for house keeping.
2105 if (li != NULL && !is_bad && li->qtype == qtype &&
2106 dns_name_equal(qname, &li->qname))
2115 #ifdef ENABLE_FETCHLIMIT
2117 log_quota(dns_adbentry_t *entry, const char *fmt, ...) {
2120 char addrbuf[ISC_NETADDR_FORMATSIZE];
2121 isc_netaddr_t netaddr;
2124 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2127 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
2128 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
2130 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
2131 ISC_LOG_INFO, "adb: quota %s (%d/%d): %s",
2132 addrbuf, entry->active, entry->quota, msgbuf);
2134 #endif /* ENABLE_FETCHLIMIT */
2137 copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
2138 dns_rdatatype_t qtype, dns_adbname_t *name,
2141 dns_adbnamehook_t *namehook;
2142 dns_adbaddrinfo_t *addrinfo;
2143 dns_adbentry_t *entry;
2146 bucket = DNS_ADB_INVALIDBUCKET;
2148 if (find->options & DNS_ADBFIND_INET) {
2149 namehook = ISC_LIST_HEAD(name->v4);
2150 while (namehook != NULL) {
2151 entry = namehook->entry;
2152 bucket = entry->lock_bucket;
2153 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2154 LOCK(&adb->entrylocks[bucket]);
2156 #ifdef ENABLE_FETCHLIMIT
2157 if (entry->quota != 0 &&
2158 entry->active >= entry->quota)
2161 (DNS_ADBFIND_LAMEPRUNED|
2162 DNS_ADBFIND_OVERQUOTA);
2165 #endif /* ENABLE_FETCHLIMIT */
2167 if (!FIND_RETURNLAME(find)
2168 && entry_is_lame(adb, entry, qname, qtype, now)) {
2169 find->options |= DNS_ADBFIND_LAMEPRUNED;
2172 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2173 if (addrinfo == NULL) {
2174 find->partial_result |= DNS_ADBFIND_INET;
2178 * Found a valid entry. Add it to the find's list.
2180 inc_entry_refcnt(adb, entry, ISC_FALSE);
2181 ISC_LIST_APPEND(find->list, addrinfo, publink);
2184 UNLOCK(&adb->entrylocks[bucket]);
2185 bucket = DNS_ADB_INVALIDBUCKET;
2186 namehook = ISC_LIST_NEXT(namehook, plink);
2190 if (find->options & DNS_ADBFIND_INET6) {
2191 namehook = ISC_LIST_HEAD(name->v6);
2192 while (namehook != NULL) {
2193 entry = namehook->entry;
2194 bucket = entry->lock_bucket;
2195 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2196 LOCK(&adb->entrylocks[bucket]);
2198 #ifdef ENABLE_FETCHLIMIT
2199 if (entry->quota != 0 &&
2200 entry->active >= entry->quota)
2203 (DNS_ADBFIND_LAMEPRUNED|
2204 DNS_ADBFIND_OVERQUOTA);
2207 #endif /* ENABLE_FETCHLIMIT */
2209 if (!FIND_RETURNLAME(find)
2210 && entry_is_lame(adb, entry, qname, qtype, now)) {
2211 find->options |= DNS_ADBFIND_LAMEPRUNED;
2214 addrinfo = new_adbaddrinfo(adb, entry, find->port);
2215 if (addrinfo == NULL) {
2216 find->partial_result |= DNS_ADBFIND_INET6;
2220 * Found a valid entry. Add it to the find's list.
2222 inc_entry_refcnt(adb, entry, ISC_FALSE);
2223 ISC_LIST_APPEND(find->list, addrinfo, publink);
2226 UNLOCK(&adb->entrylocks[bucket]);
2227 bucket = DNS_ADB_INVALIDBUCKET;
2228 namehook = ISC_LIST_NEXT(namehook, plink);
2233 if (bucket != DNS_ADB_INVALIDBUCKET)
2234 UNLOCK(&adb->entrylocks[bucket]);
2238 shutdown_task(isc_task_t *task, isc_event_t *ev) {
2244 INSIST(DNS_ADB_VALID(adb));
2246 isc_event_free(&ev);
2248 * Wait for lock around check_exit() call to be released.
2256 * Name bucket must be locked; adb may be locked; no other locks held.
2258 static isc_boolean_t
2259 check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
2260 dns_adbname_t *name;
2261 isc_boolean_t result = ISC_FALSE;
2263 INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
2266 if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
2268 if (NAME_FETCH(name))
2270 if (!EXPIRE_OK(name->expire_v4, now))
2272 if (!EXPIRE_OK(name->expire_v6, now))
2274 if (!EXPIRE_OK(name->expire_target, now))
2278 * The name is empty. Delete it.
2280 result = kill_name(&name, DNS_EVENT_ADBEXPIRED);
2284 * Our caller, or one of its callers, will be calling check_exit() at
2285 * some point, so we don't need to do it here.
2291 * Examine the tail entry of the LRU list to see if it expires or is stale
2292 * (unused for some period); if so, the name entry will be freed. If the ADB
2293 * is in the overmem condition, the tail and the next to tail entries
2294 * will be unconditionally removed (unless they have an outstanding fetch).
2295 * We don't care about a race on 'overmem' at the risk of causing some
2296 * collateral damage or a small delay in starting cleanup, so we don't bother
2297 * to lock ADB (if it's not locked).
2299 * Name bucket must be locked; adb may be locked; no other locks held.
2302 check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2303 int victims, max_victims;
2304 dns_adbname_t *victim, *next_victim;
2305 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
2308 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2310 max_victims = overmem ? 2 : 1;
2313 * We limit the number of scanned entries to 10 (arbitrary choice)
2314 * in order to avoid examining too many entries when there are many
2315 * tail entries that have fetches (this should be rare, but could
2318 victim = ISC_LIST_TAIL(adb->names[bucket]);
2320 victim != NULL && victims < max_victims && scans < 10;
2321 victim = next_victim) {
2322 INSIST(!NAME_DEAD(victim));
2324 next_victim = ISC_LIST_PREV(victim, plink);
2325 (void)check_expire_name(&victim, now);
2326 if (victim == NULL) {
2331 if (!NAME_FETCH(victim) &&
2332 (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
2333 RUNTIME_CHECK(kill_name(&victim,
2334 DNS_EVENT_ADBCANCELED) ==
2346 * Entry bucket must be locked; adb may be locked; no other locks held.
2348 static isc_boolean_t
2349 check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
2351 dns_adbentry_t *entry;
2352 isc_boolean_t result = ISC_FALSE;
2354 INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
2357 if (entry->refcnt != 0)
2360 if (entry->expires == 0 || entry->expires > now)
2364 * The entry is not in use. Delete it.
2366 DP(DEF_LEVEL, "killing entry %p", entry);
2367 INSIST(ISC_LINK_LINKED(entry, plink));
2368 result = unlink_entry(adb, entry);
2369 free_adbentry(adb, &entry);
2371 dec_adb_irefcnt(adb);
2377 * ADB must be locked, and no other locks held.
2379 static isc_boolean_t
2380 cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2381 dns_adbname_t *name;
2382 dns_adbname_t *next_name;
2383 isc_boolean_t result = ISC_FALSE;
2385 DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
2387 LOCK(&adb->namelocks[bucket]);
2388 if (adb->name_sd[bucket]) {
2389 UNLOCK(&adb->namelocks[bucket]);
2393 name = ISC_LIST_HEAD(adb->names[bucket]);
2394 while (name != NULL) {
2395 next_name = ISC_LIST_NEXT(name, plink);
2396 INSIST(result == ISC_FALSE);
2397 result = check_expire_namehooks(name, now);
2399 result = check_expire_name(&name, now);
2402 UNLOCK(&adb->namelocks[bucket]);
2407 * ADB must be locked, and no other locks held.
2409 static isc_boolean_t
2410 cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2411 dns_adbentry_t *entry, *next_entry;
2412 isc_boolean_t result = ISC_FALSE;
2414 DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
2416 LOCK(&adb->entrylocks[bucket]);
2417 entry = ISC_LIST_HEAD(adb->entries[bucket]);
2418 while (entry != NULL) {
2419 next_entry = ISC_LIST_NEXT(entry, plink);
2420 INSIST(result == ISC_FALSE);
2421 result = check_expire_entry(adb, &entry, now);
2424 UNLOCK(&adb->entrylocks[bucket]);
2429 destroy(dns_adb_t *adb) {
2432 isc_task_detach(&adb->task);
2433 if (adb->excl != NULL)
2434 isc_task_detach(&adb->excl);
2436 isc_mempool_destroy(&adb->nmp);
2437 isc_mempool_destroy(&adb->nhmp);
2438 isc_mempool_destroy(&adb->limp);
2439 isc_mempool_destroy(&adb->emp);
2440 isc_mempool_destroy(&adb->ahmp);
2441 isc_mempool_destroy(&adb->aimp);
2442 isc_mempool_destroy(&adb->afmp);
2444 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2445 isc_mem_put(adb->mctx, adb->entries,
2446 sizeof(*adb->entries) * adb->nentries);
2447 isc_mem_put(adb->mctx, adb->deadentries,
2448 sizeof(*adb->deadentries) * adb->nentries);
2449 isc_mem_put(adb->mctx, adb->entrylocks,
2450 sizeof(*adb->entrylocks) * adb->nentries);
2451 isc_mem_put(adb->mctx, adb->entry_sd,
2452 sizeof(*adb->entry_sd) * adb->nentries);
2453 isc_mem_put(adb->mctx, adb->entry_refcnt,
2454 sizeof(*adb->entry_refcnt) * adb->nentries);
2456 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2457 isc_mem_put(adb->mctx, adb->names,
2458 sizeof(*adb->names) * adb->nnames);
2459 isc_mem_put(adb->mctx, adb->deadnames,
2460 sizeof(*adb->deadnames) * adb->nnames);
2461 isc_mem_put(adb->mctx, adb->namelocks,
2462 sizeof(*adb->namelocks) * adb->nnames);
2463 isc_mem_put(adb->mctx, adb->name_sd,
2464 sizeof(*adb->name_sd) * adb->nnames);
2465 isc_mem_put(adb->mctx, adb->name_refcnt,
2466 sizeof(*adb->name_refcnt) * adb->nnames);
2468 DESTROYLOCK(&adb->reflock);
2469 DESTROYLOCK(&adb->lock);
2470 DESTROYLOCK(&adb->mplock);
2471 DESTROYLOCK(&adb->overmemlock);
2472 DESTROYLOCK(&adb->entriescntlock);
2473 DESTROYLOCK(&adb->namescntlock);
2475 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2484 dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
2485 isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
2488 isc_result_t result;
2491 REQUIRE(mem != NULL);
2492 REQUIRE(view != NULL);
2493 REQUIRE(timermgr != NULL); /* this is actually unused */
2494 REQUIRE(taskmgr != NULL);
2495 REQUIRE(newadb != NULL && *newadb == NULL);
2499 adb = isc_mem_get(mem, sizeof(dns_adb_t));
2501 return (ISC_R_NOMEMORY);
2504 * Initialize things here that cannot fail, and especially things
2505 * that must be NULL for the error return to work properly.
2521 adb->taskmgr = taskmgr;
2522 adb->next_cleanbucket = 0;
2523 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent),
2524 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
2525 adb->cevent_out = ISC_FALSE;
2526 adb->shutting_down = ISC_FALSE;
2527 ISC_LIST_INIT(adb->whenshutdown);
2529 adb->nentries = nbuckets[0];
2530 adb->entriescnt = 0;
2531 adb->entries = NULL;
2532 adb->deadentries = NULL;
2533 adb->entry_sd = NULL;
2534 adb->entry_refcnt = NULL;
2535 adb->entrylocks = NULL;
2536 ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
2537 DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
2539 adb->growentries_sent = ISC_FALSE;
2541 #ifdef ENABLE_FETCHLIMIT
2545 adb->atr_high = 0.0;
2546 adb->atr_discount = 0.0;
2547 #endif /* ENABLE_FETCHLIMIT */
2549 adb->nnames = nbuckets[0];
2552 adb->deadnames = NULL;
2553 adb->name_sd = NULL;
2554 adb->name_refcnt = NULL;
2555 adb->namelocks = NULL;
2556 ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
2557 DNS_EVENT_ADBGROWNAMES, grow_names, adb,
2559 adb->grownames_sent = ISC_FALSE;
2561 result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
2562 if (result != ISC_R_SUCCESS) {
2563 DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, "
2564 "intializing table sizes to %u\n",
2566 adb->nentries = nbuckets[11];
2567 adb->nnames = nbuckets[11];
2570 isc_mem_attach(mem, &adb->mctx);
2572 result = isc_mutex_init(&adb->lock);
2573 if (result != ISC_R_SUCCESS)
2576 result = isc_mutex_init(&adb->mplock);
2577 if (result != ISC_R_SUCCESS)
2580 result = isc_mutex_init(&adb->reflock);
2581 if (result != ISC_R_SUCCESS)
2584 result = isc_mutex_init(&adb->overmemlock);
2585 if (result != ISC_R_SUCCESS)
2588 result = isc_mutex_init(&adb->entriescntlock);
2589 if (result != ISC_R_SUCCESS)
2592 result = isc_mutex_init(&adb->namescntlock);
2593 if (result != ISC_R_SUCCESS)
2596 #define ALLOCENTRY(adb, el) \
2598 (adb)->el = isc_mem_get((adb)->mctx, \
2599 sizeof(*(adb)->el) * (adb)->nentries); \
2600 if ((adb)->el == NULL) { \
2601 result = ISC_R_NOMEMORY; \
2605 ALLOCENTRY(adb, entries);
2606 ALLOCENTRY(adb, deadentries);
2607 ALLOCENTRY(adb, entrylocks);
2608 ALLOCENTRY(adb, entry_sd);
2609 ALLOCENTRY(adb, entry_refcnt);
2612 #define ALLOCNAME(adb, el) \
2614 (adb)->el = isc_mem_get((adb)->mctx, \
2615 sizeof(*(adb)->el) * (adb)->nnames); \
2616 if ((adb)->el == NULL) { \
2617 result = ISC_R_NOMEMORY; \
2621 ALLOCNAME(adb, names);
2622 ALLOCNAME(adb, deadnames);
2623 ALLOCNAME(adb, namelocks);
2624 ALLOCNAME(adb, name_sd);
2625 ALLOCNAME(adb, name_refcnt);
2629 * Initialize the bucket locks for names and elements.
2630 * May as well initialize the list heads, too.
2632 result = isc_mutexblock_init(adb->namelocks, adb->nnames);
2633 if (result != ISC_R_SUCCESS)
2635 for (i = 0; i < adb->nnames; i++) {
2636 ISC_LIST_INIT(adb->names[i]);
2637 ISC_LIST_INIT(adb->deadnames[i]);
2638 adb->name_sd[i] = ISC_FALSE;
2639 adb->name_refcnt[i] = 0;
2642 for (i = 0; i < adb->nentries; i++) {
2643 ISC_LIST_INIT(adb->entries[i]);
2644 ISC_LIST_INIT(adb->deadentries[i]);
2645 adb->entry_sd[i] = ISC_FALSE;
2646 adb->entry_refcnt[i] = 0;
2649 result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
2650 if (result != ISC_R_SUCCESS)
2656 #define MPINIT(t, p, n) do { \
2657 result = isc_mempool_create(mem, sizeof(t), &(p)); \
2658 if (result != ISC_R_SUCCESS) \
2660 isc_mempool_setfreemax((p), FREE_ITEMS); \
2661 isc_mempool_setfillcount((p), FILL_COUNT); \
2662 isc_mempool_setname((p), n); \
2663 isc_mempool_associatelock((p), &adb->mplock); \
2666 MPINIT(dns_adbname_t, adb->nmp, "adbname");
2667 MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
2668 MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
2669 MPINIT(dns_adbentry_t, adb->emp, "adbentry");
2670 MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
2671 MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
2672 MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
2677 * Allocate an internal task.
2679 result = isc_task_create(adb->taskmgr, 0, &adb->task);
2680 if (result != ISC_R_SUCCESS)
2683 isc_task_setname(adb->task, "ADB", adb);
2688 adb->magic = DNS_ADB_MAGIC;
2690 return (ISC_R_SUCCESS);
2693 if (adb->task != NULL)
2694 isc_task_detach(&adb->task);
2696 /* clean up entrylocks */
2697 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2699 fail2: /* clean up namelocks */
2700 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2702 fail1: /* clean up only allocated memory */
2703 if (adb->entries != NULL)
2704 isc_mem_put(adb->mctx, adb->entries,
2705 sizeof(*adb->entries) * adb->nentries);
2706 if (adb->deadentries != NULL)
2707 isc_mem_put(adb->mctx, adb->deadentries,
2708 sizeof(*adb->deadentries) * adb->nentries);
2709 if (adb->entrylocks != NULL)
2710 isc_mem_put(adb->mctx, adb->entrylocks,
2711 sizeof(*adb->entrylocks) * adb->nentries);
2712 if (adb->entry_sd != NULL)
2713 isc_mem_put(adb->mctx, adb->entry_sd,
2714 sizeof(*adb->entry_sd) * adb->nentries);
2715 if (adb->entry_refcnt != NULL)
2716 isc_mem_put(adb->mctx, adb->entry_refcnt,
2717 sizeof(*adb->entry_refcnt) * adb->nentries);
2718 if (adb->names != NULL)
2719 isc_mem_put(adb->mctx, adb->names,
2720 sizeof(*adb->names) * adb->nnames);
2721 if (adb->deadnames != NULL)
2722 isc_mem_put(adb->mctx, adb->deadnames,
2723 sizeof(*adb->deadnames) * adb->nnames);
2724 if (adb->namelocks != NULL)
2725 isc_mem_put(adb->mctx, adb->namelocks,
2726 sizeof(*adb->namelocks) * adb->nnames);
2727 if (adb->name_sd != NULL)
2728 isc_mem_put(adb->mctx, adb->name_sd,
2729 sizeof(*adb->name_sd) * adb->nnames);
2730 if (adb->name_refcnt != NULL)
2731 isc_mem_put(adb->mctx, adb->name_refcnt,
2732 sizeof(*adb->name_refcnt) * adb->nnames);
2733 if (adb->nmp != NULL)
2734 isc_mempool_destroy(&adb->nmp);
2735 if (adb->nhmp != NULL)
2736 isc_mempool_destroy(&adb->nhmp);
2737 if (adb->limp != NULL)
2738 isc_mempool_destroy(&adb->limp);
2739 if (adb->emp != NULL)
2740 isc_mempool_destroy(&adb->emp);
2741 if (adb->ahmp != NULL)
2742 isc_mempool_destroy(&adb->ahmp);
2743 if (adb->aimp != NULL)
2744 isc_mempool_destroy(&adb->aimp);
2745 if (adb->afmp != NULL)
2746 isc_mempool_destroy(&adb->afmp);
2748 DESTROYLOCK(&adb->namescntlock);
2750 DESTROYLOCK(&adb->entriescntlock);
2752 DESTROYLOCK(&adb->overmemlock);
2754 DESTROYLOCK(&adb->reflock);
2756 DESTROYLOCK(&adb->mplock);
2758 DESTROYLOCK(&adb->lock);
2760 if (adb->excl != NULL)
2761 isc_task_detach(&adb->excl);
2762 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2768 dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
2770 REQUIRE(DNS_ADB_VALID(adb));
2771 REQUIRE(adbx != NULL && *adbx == NULL);
2773 inc_adb_erefcnt(adb);
2778 dns_adb_detach(dns_adb_t **adbx) {
2780 isc_boolean_t need_exit_check;
2782 REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
2787 INSIST(adb->erefcnt > 0);
2789 LOCK(&adb->reflock);
2791 need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
2792 UNLOCK(&adb->reflock);
2794 if (need_exit_check) {
2796 INSIST(adb->shutting_down);
2803 dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
2806 isc_boolean_t zeroirefcnt = ISC_FALSE;
2809 * Send '*eventp' to 'task' when 'adb' has shutdown.
2812 REQUIRE(DNS_ADB_VALID(adb));
2813 REQUIRE(eventp != NULL);
2820 LOCK(&adb->reflock);
2821 zeroirefcnt = ISC_TF(adb->irefcnt == 0);
2823 if (adb->shutting_down && zeroirefcnt &&
2824 isc_mempool_getallocated(adb->ahmp) == 0) {
2826 * We're already shutdown. Send the event.
2828 event->ev_sender = adb;
2829 isc_task_send(task, &event);
2832 isc_task_attach(task, &clone);
2833 event->ev_sender = clone;
2834 ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
2837 UNLOCK(&adb->reflock);
2842 shutdown_stage2(isc_task_t *task, isc_event_t *event) {
2847 adb = event->ev_arg;
2848 INSIST(DNS_ADB_VALID(adb));
2851 INSIST(adb->shutting_down);
2852 adb->cevent_out = ISC_FALSE;
2853 (void)shutdown_names(adb);
2854 (void)shutdown_entries(adb);
2855 if (dec_adb_irefcnt(adb))
2861 dns_adb_shutdown(dns_adb_t *adb) {
2870 if (!adb->shutting_down) {
2871 adb->shutting_down = ISC_TRUE;
2872 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
2874 * Isolate shutdown_names and shutdown_entries calls.
2876 inc_adb_irefcnt(adb);
2877 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
2878 DNS_EVENT_ADBCONTROL, shutdown_stage2, adb,
2880 adb->cevent_out = ISC_TRUE;
2881 event = &adb->cevent;
2882 isc_task_send(adb->task, &event);
2889 dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2890 void *arg, dns_name_t *name, dns_name_t *qname,
2891 dns_rdatatype_t qtype, unsigned int options,
2892 isc_stdtime_t now, dns_name_t *target,
2893 in_port_t port, dns_adbfind_t **findp)
2895 return (dns_adb_createfind2(adb, task, action, arg, name,
2896 qname, qtype, options, now,
2897 target, port, 0, NULL, findp));
2901 dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2902 void *arg, dns_name_t *name, dns_name_t *qname,
2903 dns_rdatatype_t qtype, unsigned int options,
2904 isc_stdtime_t now, dns_name_t *target,
2905 in_port_t port, unsigned int depth, isc_counter_t *qc,
2906 dns_adbfind_t **findp)
2908 dns_adbfind_t *find;
2909 dns_adbname_t *adbname;
2911 isc_boolean_t want_event, start_at_zone, alias, have_address;
2912 isc_result_t result;
2913 unsigned int wanted_addresses;
2914 unsigned int wanted_fetches;
2915 unsigned int query_pending;
2917 REQUIRE(DNS_ADB_VALID(adb));
2919 REQUIRE(action != NULL);
2921 REQUIRE(name != NULL);
2922 REQUIRE(qname != NULL);
2923 REQUIRE(findp != NULL && *findp == NULL);
2924 REQUIRE(target == NULL || dns_name_hasbuffer(target));
2926 REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
2928 result = ISC_R_UNEXPECTED;
2930 wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
2933 want_event = ISC_FALSE;
2934 start_at_zone = ISC_FALSE;
2938 isc_stdtime_get(&now);
2941 * XXXMLG Move this comment somewhere else!
2943 * Look up the name in our internal database.
2945 * Possibilities: Note that these are not always exclusive.
2947 * No name found. In this case, allocate a new name header and
2948 * an initial namehook or two. If any of these allocations
2949 * fail, clean up and return ISC_R_NOMEMORY.
2951 * Name found, valid addresses present. Allocate one addrinfo
2952 * structure for each found and append it to the linked list
2953 * of addresses for this header.
2955 * Name found, queries pending. In this case, if a task was
2956 * passed in, allocate a job id, attach it to the name's job
2957 * list and remember to tell the caller that there will be
2958 * more info coming later.
2961 find = new_adbfind(adb);
2963 return (ISC_R_NOMEMORY);
2968 * Remember what types of addresses we are interested in.
2970 find->options = options;
2971 find->flags |= wanted_addresses;
2972 if (FIND_WANTEVENT(find)) {
2973 REQUIRE(task != NULL);
2977 * Try to see if we know anything about this name at all.
2979 bucket = DNS_ADB_INVALIDBUCKET;
2980 adbname = find_name_and_lock(adb, name, find->options, &bucket);
2981 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2982 if (adb->name_sd[bucket]) {
2984 "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
2985 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2986 result = ISC_R_SHUTTINGDOWN;
2991 * Nothing found. Allocate a new adbname structure for this name.
2993 if (adbname == NULL) {
2995 * See if there is any stale name at the end of list, and purge
2998 check_stale_name(adb, bucket, now);
3000 adbname = new_adbname(adb, name);
3001 if (adbname == NULL) {
3002 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
3003 result = ISC_R_NOMEMORY;
3006 link_name(adb, bucket, adbname);
3007 if (FIND_HINTOK(find))
3008 adbname->flags |= NAME_HINT_OK;
3009 if (FIND_GLUEOK(find))
3010 adbname->flags |= NAME_GLUE_OK;
3011 if (FIND_STARTATZONE(find))
3012 adbname->flags |= NAME_STARTATZONE;
3014 /* Move this name forward in the LRU list */
3015 ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
3016 ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
3018 adbname->last_used = now;
3021 * Expire old entries, etc.
3023 RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
3026 * Do we know that the name is an alias?
3028 if (!EXPIRE_OK(adbname->expire_target, now)) {
3033 "dns_adb_createfind: name %p is an alias (cached)",
3040 * Try to populate the name from the database and/or
3041 * start fetches. First try looking for an A record
3044 if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
3045 && WANT_INET(wanted_addresses)) {
3046 result = dbfind_name(adbname, now, dns_rdatatype_a);
3047 if (result == ISC_R_SUCCESS) {
3049 "dns_adb_createfind: found A for name %p in db",
3055 * Did we get a CNAME or DNAME?
3057 if (result == DNS_R_ALIAS) {
3059 "dns_adb_createfind: name %p is an alias",
3066 * If the name doesn't exist at all, don't bother with
3067 * v6 queries; they won't work.
3069 * If the name does exist but we didn't get our data, go
3070 * ahead and try AAAA.
3072 * If the result is neither of these, try a fetch for A.
3074 if (NXDOMAIN_RESULT(result))
3076 else if (NXRRSET_RESULT(result))
3079 if (!NAME_FETCH_V4(adbname))
3080 wanted_fetches |= DNS_ADBFIND_INET;
3084 if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
3085 && WANT_INET6(wanted_addresses)) {
3086 result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
3087 if (result == ISC_R_SUCCESS) {
3089 "dns_adb_createfind: found AAAA for name %p",
3095 * Did we get a CNAME or DNAME?
3097 if (result == DNS_R_ALIAS) {
3099 "dns_adb_createfind: name %p is an alias",
3106 * Listen to negative cache hints, and don't start
3109 if (NCACHE_RESULT(result) || AUTH_NX(result))
3112 if (!NAME_FETCH_V6(adbname))
3113 wanted_fetches |= DNS_ADBFIND_INET6;
3117 if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
3118 (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
3119 have_address = ISC_TRUE;
3121 have_address = ISC_FALSE;
3122 if (wanted_fetches != 0 &&
3123 ! (FIND_AVOIDFETCHES(find) && have_address)) {
3125 * We're missing at least one address family. Either the
3126 * caller hasn't instructed us to avoid fetches, or we don't
3127 * know anything about any of the address families that would
3128 * be acceptable so we have to launch fetches.
3131 if (FIND_STARTATZONE(find))
3132 start_at_zone = ISC_TRUE;
3137 if (WANT_INET(wanted_fetches) &&
3138 fetch_name(adbname, start_at_zone, depth, qc,
3139 dns_rdatatype_a) == ISC_R_SUCCESS) {
3141 "dns_adb_createfind: started A fetch for name %p",
3148 if (WANT_INET6(wanted_fetches) &&
3149 fetch_name(adbname, start_at_zone, depth, qc,
3150 dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
3152 "dns_adb_createfind: "
3153 "started AAAA fetch for name %p",
3159 * Run through the name and copy out the bits we are
3162 copy_namehook_lists(adb, find, qname, qtype, adbname, now);
3165 if (NAME_FETCH_V4(adbname))
3166 query_pending |= DNS_ADBFIND_INET;
3167 if (NAME_FETCH_V6(adbname))
3168 query_pending |= DNS_ADBFIND_INET6;
3171 * Attach to the name's query list if there are queries
3172 * already running, and we have been asked to.
3174 want_event = ISC_TRUE;
3175 if (!FIND_WANTEVENT(find))
3176 want_event = ISC_FALSE;
3177 if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
3178 want_event = ISC_FALSE;
3179 if ((wanted_addresses & query_pending) == 0)
3180 want_event = ISC_FALSE;
3182 want_event = ISC_FALSE;
3184 find->adbname = adbname;
3185 find->name_bucket = bucket;
3186 ISC_LIST_APPEND(adbname->finds, find, plink);
3187 find->query_pending = (query_pending & wanted_addresses);
3188 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3189 find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
3190 DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
3194 * Remove the flag so the caller knows there will never
3195 * be an event, and set internal flags to fake that
3196 * the event was sent and freed, so dns_adb_destroyfind() will
3197 * do the right thing.
3199 find->query_pending = (query_pending & wanted_addresses);
3200 find->options &= ~DNS_ADBFIND_WANTEVENT;
3201 find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
3202 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3205 find->partial_result |= (adbname->partial_result & wanted_addresses);
3207 if (target != NULL) {
3208 result = dns_name_copy(&adbname->target, target, NULL);
3209 if (result != ISC_R_SUCCESS)
3212 result = DNS_R_ALIAS;
3214 result = ISC_R_SUCCESS;
3217 * Copy out error flags from the name structure into the find.
3219 find->result_v4 = find_err_map[adbname->fetch_err];
3220 find->result_v6 = find_err_map[adbname->fetch6_err];
3229 INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
3231 isc_task_attach(task, &taskp);
3232 find->event.ev_sender = taskp;
3233 find->event.ev_action = action;
3234 find->event.ev_arg = arg;
3238 UNLOCK(&adb->namelocks[bucket]);
3244 dns_adb_destroyfind(dns_adbfind_t **findp) {
3245 dns_adbfind_t *find;
3246 dns_adbentry_t *entry;
3247 dns_adbaddrinfo_t *ai;
3250 isc_boolean_t overmem;
3252 REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
3258 DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
3261 REQUIRE(DNS_ADB_VALID(adb));
3263 REQUIRE(FIND_EVENTFREED(find));
3265 bucket = find->name_bucket;
3266 INSIST(bucket == DNS_ADB_INVALIDBUCKET);
3268 UNLOCK(&find->lock);
3271 * The find doesn't exist on any list, and nothing is locked.
3272 * Return the find to the memory pool, and decrement the adb's
3275 overmem = isc_mem_isovermem(adb->mctx);
3276 ai = ISC_LIST_HEAD(find->list);
3277 while (ai != NULL) {
3278 ISC_LIST_UNLINK(find->list, ai, publink);
3281 INSIST(DNS_ADBENTRY_VALID(entry));
3282 RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
3284 free_adbaddrinfo(adb, &ai);
3285 ai = ISC_LIST_HEAD(find->list);
3289 * WARNING: The find is freed with the adb locked. This is done
3290 * to avoid a race condition where we free the find, some other
3291 * thread tests to see if it should be destroyed, detects it should
3292 * be, destroys it, and then we try to lock it for our check, but the
3293 * lock is destroyed.
3296 if (free_adbfind(adb, &find))
3302 dns_adb_cancelfind(dns_adbfind_t *find) {
3311 DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
3314 REQUIRE(DNS_ADB_VALID(adb));
3316 REQUIRE(!FIND_EVENTFREED(find));
3317 REQUIRE(FIND_WANTEVENT(find));
3319 bucket = find->name_bucket;
3320 if (bucket == DNS_ADB_INVALIDBUCKET)
3324 * We need to get the adbname's lock to unlink the find.
3326 unlock_bucket = bucket;
3327 violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
3328 bucket = find->name_bucket;
3329 if (bucket != DNS_ADB_INVALIDBUCKET) {
3330 ISC_LIST_UNLINK(find->adbname->finds, find, plink);
3331 find->adbname = NULL;
3332 find->name_bucket = DNS_ADB_INVALIDBUCKET;
3334 UNLOCK(&adb->namelocks[unlock_bucket]);
3335 bucket = DNS_ADB_INVALIDBUCKET;
3340 if (!FIND_EVENTSENT(find)) {
3342 task = ev->ev_sender;
3343 ev->ev_sender = find;
3344 ev->ev_type = DNS_EVENT_ADBCANCELED;
3345 ev->ev_destroy = event_free;
3346 ev->ev_destroy_arg = find;
3347 find->result_v4 = ISC_R_CANCELED;
3348 find->result_v6 = ISC_R_CANCELED;
3350 DP(DEF_LEVEL, "sending event %p to task %p for find %p",
3353 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
3356 UNLOCK(&find->lock);
3360 dns_adb_dump(dns_adb_t *adb, FILE *f) {
3364 REQUIRE(DNS_ADB_VALID(adb));
3368 * Lock the adb itself, lock all the name buckets, then lock all
3369 * the entry buckets. This should put the adb into a state where
3370 * nothing can change, so we can iterate through everything and
3371 * print at our leisure.
3375 isc_stdtime_get(&now);
3377 for (i = 0; i < adb->nnames; i++)
3378 RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
3379 for (i = 0; i < adb->nentries; i++)
3380 RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
3382 dump_adb(adb, f, ISC_FALSE, now);
3387 dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
3388 if (value == INT_MAX)
3390 fprintf(f, " [%s TTL %d]", legend, value - now);
3394 dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
3396 dns_adbname_t *name;
3397 dns_adbentry_t *entry;
3399 fprintf(f, ";\n; Address database dump\n;\n");
3401 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
3402 adb, adb->erefcnt, adb->irefcnt,
3403 isc_mempool_getallocated(adb->nhmp));
3405 for (i = 0; i < adb->nnames; i++)
3406 LOCK(&adb->namelocks[i]);
3407 for (i = 0; i < adb->nentries; i++)
3408 LOCK(&adb->entrylocks[i]);
3413 for (i = 0; i < adb->nnames; i++) {
3414 name = ISC_LIST_HEAD(adb->names[i]);
3418 fprintf(f, "; bucket %d\n", i);
3421 name = ISC_LIST_NEXT(name, plink))
3424 fprintf(f, "; name %p (flags %08x)\n",
3428 print_dns_name(f, &name->name);
3429 if (dns_name_countlabels(&name->target) > 0) {
3430 fprintf(f, " alias ");
3431 print_dns_name(f, &name->target);
3434 dump_ttl(f, "v4", name->expire_v4, now);
3435 dump_ttl(f, "v6", name->expire_v6, now);
3436 dump_ttl(f, "target", name->expire_target, now);
3438 fprintf(f, " [v4 %s] [v6 %s]",
3439 errnames[name->fetch_err],
3440 errnames[name->fetch6_err]);
3444 print_namehook_list(f, "v4", adb,
3445 &name->v4, debug, now);
3446 print_namehook_list(f, "v6", adb,
3447 &name->v6, debug, now);
3450 print_fetch_list(f, name);
3452 print_find_list(f, name);
3456 fprintf(f, ";\n; Unassociated entries\n;\n");
3458 for (i = 0; i < adb->nentries; i++) {
3459 entry = ISC_LIST_HEAD(adb->entries[i]);
3460 while (entry != NULL) {
3462 dump_entry(f, adb, entry, debug, now);
3463 entry = ISC_LIST_NEXT(entry, plink);
3470 for (i = 0; i < adb->nentries; i++)
3471 UNLOCK(&adb->entrylocks[i]);
3472 for (i = 0; i < adb->nnames; i++)
3473 UNLOCK(&adb->namelocks[i]);
3477 dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry,
3478 isc_boolean_t debug, isc_stdtime_t now)
3480 char addrbuf[ISC_NETADDR_FORMATSIZE];
3481 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3482 isc_netaddr_t netaddr;
3483 dns_adblameinfo_t *li;
3485 #ifndef ENABLE_FETCHLIMIT
3487 #endif /* !ENABLE_FETCHLIMIT */
3489 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
3490 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
3493 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
3495 fprintf(f, ";\t%s [srtt %u] [flags %08x]",
3496 addrbuf, entry->srtt, entry->flags);
3497 if (entry->expires != 0)
3498 fprintf(f, " [ttl %d]", entry->expires - now);
3500 #ifdef ENABLE_FETCHLIMIT
3501 if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) {
3502 fprintf(f, " [atr %0.2f] [quota %d]",
3503 entry->atr, entry->quota);
3505 #endif /* ENABLE_FETCHLIMIT */
3508 for (li = ISC_LIST_HEAD(entry->lameinfo);
3510 li = ISC_LIST_NEXT(li, plink))
3512 fprintf(f, ";\t\t");
3513 print_dns_name(f, &li->qname);
3514 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
3515 fprintf(f, " %s [lame TTL %d]\n", typebuf,
3516 li->lame_timer - now);
3521 dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
3524 dns_adbaddrinfo_t *ai;
3528 * Not used currently, in the API Just In Case we
3529 * want to dump out the name and/or entries too.
3534 fprintf(f, ";Find %p\n", find);
3535 fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
3536 find->query_pending, find->partial_result,
3537 find->options, find->flags);
3538 fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
3539 find->name_bucket, find->adbname, find->event.ev_sender);
3541 ai = ISC_LIST_HEAD(find->list);
3543 fprintf(f, "\tAddresses:\n");
3544 while (ai != NULL) {
3546 switch (sa->type.sa.sa_family) {
3548 tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
3552 tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
3560 tmpp = "BadAddress";
3562 fprintf(f, "\t\tentry %p, flags %08x"
3563 " srtt %u addr %s\n",
3564 ai->entry, ai->flags, ai->srtt, tmpp);
3566 ai = ISC_LIST_NEXT(ai, publink);
3569 UNLOCK(&find->lock);
3573 print_dns_name(FILE *f, dns_name_t *name) {
3574 char buf[DNS_NAME_FORMATSIZE];
3578 dns_name_format(name, buf, sizeof(buf));
3579 fprintf(f, "%s", buf);
3583 print_namehook_list(FILE *f, const char *legend,
3584 dns_adb_t *adb, dns_adbnamehooklist_t *list,
3585 isc_boolean_t debug, isc_stdtime_t now)
3587 dns_adbnamehook_t *nh;
3589 for (nh = ISC_LIST_HEAD(*list);
3591 nh = ISC_LIST_NEXT(nh, plink))
3594 fprintf(f, ";\tHook(%s) %p\n", legend, nh);
3595 dump_entry(f, adb, nh->entry, debug, now);
3600 print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
3601 fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
3602 type, ft, ft->fetch);
3606 print_fetch_list(FILE *f, dns_adbname_t *n) {
3607 if (NAME_FETCH_A(n))
3608 print_fetch(f, n->fetch_a, "A");
3609 if (NAME_FETCH_AAAA(n))
3610 print_fetch(f, n->fetch_aaaa, "AAAA");
3614 print_find_list(FILE *f, dns_adbname_t *name) {
3615 dns_adbfind_t *find;
3617 find = ISC_LIST_HEAD(name->finds);
3618 while (find != NULL) {
3619 dns_adb_dumpfind(find, f);
3620 find = ISC_LIST_NEXT(find, plink);
3625 dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
3627 isc_result_t result;
3628 dns_rdataset_t rdataset;
3630 dns_fixedname_t foundname;
3633 INSIST(DNS_ADBNAME_VALID(adbname));
3635 INSIST(DNS_ADB_VALID(adb));
3636 INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
3638 dns_fixedname_init(&foundname);
3639 fname = dns_fixedname_name(&foundname);
3640 dns_rdataset_init(&rdataset);
3642 if (rdtype == dns_rdatatype_a)
3643 adbname->fetch_err = FIND_ERR_UNEXPECTED;
3645 adbname->fetch6_err = FIND_ERR_UNEXPECTED;
3648 * We need to specify whether to search static-stub zones (if
3649 * configured) depending on whether this is a "start at zone" lookup,
3650 * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
3651 * case NAME_STARTATZONE is set) we need to stop the search at any
3652 * matching static-stub zone without looking into the cache to honor
3653 * the configuration on which server we should send queries to.
3655 result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
3656 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
3657 ISC_TF(NAME_HINTOK(adbname)),
3658 (adbname->flags & NAME_STARTATZONE) != 0 ?
3659 ISC_TRUE : ISC_FALSE,
3660 NULL, NULL, fname, &rdataset, NULL);
3662 /* XXXVIX this switch statement is too sparse to gen a jump table. */
3668 * Found in the database. Even if we can't copy out
3669 * any information, return success, or else a fetch
3670 * will be made, which will only make things worse.
3672 if (rdtype == dns_rdatatype_a)
3673 adbname->fetch_err = FIND_ERR_SUCCESS;
3675 adbname->fetch6_err = FIND_ERR_SUCCESS;
3676 result = import_rdataset(adbname, &rdataset, now);
3678 case DNS_R_NXDOMAIN:
3681 * We're authoritative and the data doesn't exist.
3682 * Make up a negative cache entry so we don't ask again
3685 * XXXRTH What time should we use? I'm putting in 30 seconds
3688 if (rdtype == dns_rdatatype_a) {
3689 adbname->expire_v4 = now + 30;
3691 "adb name %p: Caching auth negative entry for A",
3693 if (result == DNS_R_NXDOMAIN)
3694 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3696 adbname->fetch_err = FIND_ERR_NXRRSET;
3699 "adb name %p: Caching auth negative entry for AAAA",
3701 adbname->expire_v6 = now + 30;
3702 if (result == DNS_R_NXDOMAIN)
3703 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3705 adbname->fetch6_err = FIND_ERR_NXRRSET;
3708 case DNS_R_NCACHENXDOMAIN:
3709 case DNS_R_NCACHENXRRSET:
3711 * We found a negative cache entry. Pull the TTL from it
3712 * so we won't ask again for a while.
3714 rdataset.ttl = ttlclamp(rdataset.ttl);
3715 if (rdtype == dns_rdatatype_a) {
3716 adbname->expire_v4 = rdataset.ttl + now;
3717 if (result == DNS_R_NCACHENXDOMAIN)
3718 adbname->fetch_err = FIND_ERR_NXDOMAIN;
3720 adbname->fetch_err = FIND_ERR_NXRRSET;
3722 "adb name %p: Caching negative entry for A (ttl %u)",
3723 adbname, rdataset.ttl);
3726 "adb name %p: Caching negative entry for AAAA (ttl %u)",
3727 adbname, rdataset.ttl);
3728 adbname->expire_v6 = rdataset.ttl + now;
3729 if (result == DNS_R_NCACHENXDOMAIN)
3730 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3732 adbname->fetch6_err = FIND_ERR_NXRRSET;
3738 * Clear the hint and glue flags, so this will match
3741 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
3743 rdataset.ttl = ttlclamp(rdataset.ttl);
3744 clean_target(adb, &adbname->target);
3745 adbname->expire_target = INT_MAX;
3746 result = set_target(adb, &adbname->name, fname, &rdataset,
3748 if (result == ISC_R_SUCCESS) {
3749 result = DNS_R_ALIAS;
3751 "adb name %p: caching alias target",
3753 adbname->expire_target = rdataset.ttl + now;
3755 if (rdtype == dns_rdatatype_a)
3756 adbname->fetch_err = FIND_ERR_SUCCESS;
3758 adbname->fetch6_err = FIND_ERR_SUCCESS;
3762 if (dns_rdataset_isassociated(&rdataset))
3763 dns_rdataset_disassociate(&rdataset);
3769 fetch_callback(isc_task_t *task, isc_event_t *ev) {
3770 dns_fetchevent_t *dev;
3771 dns_adbname_t *name;
3773 dns_adbfetch_t *fetch;
3775 isc_eventtype_t ev_status;
3777 isc_result_t result;
3778 unsigned int address_type;
3779 isc_boolean_t want_check_exit = ISC_FALSE;
3783 INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
3784 dev = (dns_fetchevent_t *)ev;
3786 INSIST(DNS_ADBNAME_VALID(name));
3788 INSIST(DNS_ADB_VALID(adb));
3790 bucket = name->lock_bucket;
3791 LOCK(&adb->namelocks[bucket]);
3793 INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
3795 if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
3796 address_type = DNS_ADBFIND_INET;
3797 fetch = name->fetch_a;
3798 name->fetch_a = NULL;
3799 } else if (NAME_FETCH_AAAA(name)
3800 && (name->fetch_aaaa->fetch == dev->fetch)) {
3801 address_type = DNS_ADBFIND_INET6;
3802 fetch = name->fetch_aaaa;
3803 name->fetch_aaaa = NULL;
3807 INSIST(address_type != 0 && fetch != NULL);
3809 dns_resolver_destroyfetch(&fetch->fetch);
3812 ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
3815 * Cleanup things we don't care about.
3817 if (dev->node != NULL)
3818 dns_db_detachnode(dev->db, &dev->node);
3819 if (dev->db != NULL)
3820 dns_db_detach(&dev->db);
3823 * If this name is marked as dead, clean up, throwing away
3824 * potentially good data.
3826 if (NAME_DEAD(name)) {
3827 free_adbfetch(adb, &fetch);
3828 isc_event_free(&ev);
3830 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED);
3832 UNLOCK(&adb->namelocks[bucket]);
3834 if (want_check_exit) {
3843 isc_stdtime_get(&now);
3846 * If we got a negative cache response, remember it.
3848 if (NCACHE_RESULT(dev->result)) {
3849 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3850 if (address_type == DNS_ADBFIND_INET) {
3851 DP(NCACHE_LEVEL, "adb fetch name %p: "
3852 "caching negative entry for A (ttl %u)",
3853 name, dev->rdataset->ttl);
3854 name->expire_v4 = ISC_MIN(name->expire_v4,
3855 dev->rdataset->ttl + now);
3856 if (dev->result == DNS_R_NCACHENXDOMAIN)
3857 name->fetch_err = FIND_ERR_NXDOMAIN;
3859 name->fetch_err = FIND_ERR_NXRRSET;
3860 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3862 DP(NCACHE_LEVEL, "adb fetch name %p: "
3863 "caching negative entry for AAAA (ttl %u)",
3864 name, dev->rdataset->ttl);
3865 name->expire_v6 = ISC_MIN(name->expire_v6,
3866 dev->rdataset->ttl + now);
3867 if (dev->result == DNS_R_NCACHENXDOMAIN)
3868 name->fetch6_err = FIND_ERR_NXDOMAIN;
3870 name->fetch6_err = FIND_ERR_NXRRSET;
3871 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3877 * Handle CNAME/DNAME.
3879 if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
3880 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3881 clean_target(adb, &name->target);
3882 name->expire_target = INT_MAX;
3883 result = set_target(adb, &name->name,
3884 dns_fixedname_name(&dev->foundname),
3887 if (result == ISC_R_SUCCESS) {
3889 "adb fetch name %p: caching alias target",
3891 name->expire_target = dev->rdataset->ttl + now;
3897 * Did we get back junk? If so, and there are no more fetches
3898 * sitting out there, tell all the finds about it.
3900 if (dev->result != ISC_R_SUCCESS) {
3901 char buf[DNS_NAME_FORMATSIZE];
3903 dns_name_format(&name->name, buf, sizeof(buf));
3904 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
3905 buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
3906 dns_result_totext(dev->result));
3908 * Don't record a failure unless this is the initial
3911 if (fetch->depth > 1)
3913 /* XXXMLG Don't pound on bad servers. */
3914 if (address_type == DNS_ADBFIND_INET) {
3915 name->expire_v4 = ISC_MIN(name->expire_v4, now + 10);
3916 name->fetch_err = FIND_ERR_FAILURE;
3917 inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3919 name->expire_v6 = ISC_MIN(name->expire_v6, now + 10);
3920 name->fetch6_err = FIND_ERR_FAILURE;
3921 inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3927 * We got something potentially useful.
3929 result = import_rdataset(name, &fetch->rdataset, now);
3932 if (result == ISC_R_SUCCESS) {
3933 ev_status = DNS_EVENT_ADBMOREADDRESSES;
3934 if (address_type == DNS_ADBFIND_INET)
3935 name->fetch_err = FIND_ERR_SUCCESS;
3937 name->fetch6_err = FIND_ERR_SUCCESS;
3941 free_adbfetch(adb, &fetch);
3942 isc_event_free(&ev);
3944 clean_finds_at_name(name, ev_status, address_type);
3946 UNLOCK(&adb->namelocks[bucket]);
3950 fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
3951 unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
3953 isc_result_t result;
3954 dns_adbfetch_t *fetch = NULL;
3956 dns_fixedname_t fixed;
3958 dns_rdataset_t rdataset;
3959 dns_rdataset_t *nameservers;
3960 unsigned int options;
3962 INSIST(DNS_ADBNAME_VALID(adbname));
3964 INSIST(DNS_ADB_VALID(adb));
3966 INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
3967 (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
3969 adbname->fetch_err = FIND_ERR_NOTFOUND;
3973 dns_rdataset_init(&rdataset);
3975 options = DNS_FETCHOPT_NOVALIDATE;
3976 if (start_at_zone) {
3978 "fetch_name: starting at zone for name %p",
3980 dns_fixedname_init(&fixed);
3981 name = dns_fixedname_name(&fixed);
3982 result = dns_view_findzonecut2(adb->view, &adbname->name, name,
3983 0, 0, ISC_TRUE, ISC_FALSE,
3985 if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
3987 nameservers = &rdataset;
3988 options |= DNS_FETCHOPT_UNSHARED;
3991 fetch = new_adbfetch(adb);
3992 if (fetch == NULL) {
3993 result = ISC_R_NOMEMORY;
3996 fetch->depth = depth;
3998 result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
3999 type, name, nameservers, NULL,
4000 NULL, 0, options, depth, qc,
4001 adb->task, fetch_callback, adbname,
4002 &fetch->rdataset, NULL,
4004 if (result != ISC_R_SUCCESS)
4007 if (type == dns_rdatatype_a) {
4008 adbname->fetch_a = fetch;
4009 inc_stats(adb, dns_resstatscounter_gluefetchv4);
4011 adbname->fetch_aaaa = fetch;
4012 inc_stats(adb, dns_resstatscounter_gluefetchv6);
4014 fetch = NULL; /* Keep us from cleaning this up below. */
4018 free_adbfetch(adb, &fetch);
4019 if (dns_rdataset_isassociated(&rdataset))
4020 dns_rdataset_disassociate(&rdataset);
4026 * XXXMLG Needs to take a find argument and an address info, no zone or adb,
4027 * since these can be extracted from the find itself.
4030 dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
4031 dns_rdatatype_t qtype, isc_stdtime_t expire_time)
4033 dns_adblameinfo_t *li;
4035 isc_result_t result = ISC_R_SUCCESS;
4037 REQUIRE(DNS_ADB_VALID(adb));
4038 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4039 REQUIRE(qname != NULL);
4041 bucket = addr->entry->lock_bucket;
4042 LOCK(&adb->entrylocks[bucket]);
4043 li = ISC_LIST_HEAD(addr->entry->lameinfo);
4044 while (li != NULL &&
4045 (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
4046 li = ISC_LIST_NEXT(li, plink);
4048 if (expire_time > li->lame_timer)
4049 li->lame_timer = expire_time;
4052 li = new_adblameinfo(adb, qname, qtype);
4054 result = ISC_R_NOMEMORY;
4058 li->lame_timer = expire_time;
4060 ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
4062 UNLOCK(&adb->entrylocks[bucket]);
4068 dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
4069 unsigned int rtt, unsigned int factor)
4072 isc_stdtime_t now = 0;
4074 REQUIRE(DNS_ADB_VALID(adb));
4075 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4076 REQUIRE(factor <= 10);
4078 bucket = addr->entry->lock_bucket;
4079 LOCK(&adb->entrylocks[bucket]);
4081 if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE)
4082 isc_stdtime_get(&now);
4083 adjustsrtt(addr, rtt, factor, now);
4085 UNLOCK(&adb->entrylocks[bucket]);
4089 dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) {
4092 REQUIRE(DNS_ADB_VALID(adb));
4093 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4095 bucket = addr->entry->lock_bucket;
4096 LOCK(&adb->entrylocks[bucket]);
4098 adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now);
4100 UNLOCK(&adb->entrylocks[bucket]);
4104 adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
4107 isc_uint64_t new_srtt;
4109 if (factor == DNS_ADB_RTTADJAGE) {
4110 if (addr->entry->lastage != now) {
4111 new_srtt = addr->entry->srtt;
4113 new_srtt -= addr->entry->srtt;
4115 addr->entry->lastage = now;
4117 new_srtt = addr->entry->srtt;
4119 new_srtt = (addr->entry->srtt / 10 * factor)
4120 + (rtt / 10 * (10 - factor));
4122 new_srtt &= 0xffffffff;
4123 addr->entry->srtt = (unsigned int) new_srtt;
4124 addr->srtt = (unsigned int) new_srtt;
4126 if (addr->entry->expires == 0)
4127 addr->entry->expires = now + ADB_ENTRY_WINDOW;
4131 dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
4132 unsigned int bits, unsigned int mask)
4137 REQUIRE(DNS_ADB_VALID(adb));
4138 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4140 REQUIRE((bits & ENTRY_IS_DEAD) == 0);
4141 REQUIRE((mask & ENTRY_IS_DEAD) == 0);
4143 bucket = addr->entry->lock_bucket;
4144 LOCK(&adb->entrylocks[bucket]);
4146 addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
4147 if (addr->entry->expires == 0) {
4148 isc_stdtime_get(&now);
4149 addr->entry->expires = now + ADB_ENTRY_WINDOW;
4153 * Note that we do not update the other bits in addr->flags with
4154 * the most recent values from addr->entry->flags.
4156 addr->flags = (addr->flags & ~mask) | (bits & mask);
4158 UNLOCK(&adb->entrylocks[bucket]);
4161 #ifdef ENABLE_FETCHLIMIT
4163 * (10000 / ((10 + n) / 10)^(3/2)) for n in 0..99.
4164 * These will be used to make quota adjustments.
4166 static int quota_adj[] = {
4167 10000, 8668, 7607, 6747, 6037, 5443, 4941, 4512, 4141,
4168 3818, 3536, 3286, 3065, 2867, 2690, 2530, 2385, 2254,
4169 2134, 2025, 1925, 1832, 1747, 1668, 1595, 1527, 1464,
4170 1405, 1350, 1298, 1250, 1205, 1162, 1121, 1083, 1048,
4171 1014, 981, 922, 894, 868, 843, 820, 797, 775, 755,
4172 735, 716, 698, 680, 664, 648, 632, 618, 603, 590, 577,
4173 564, 552, 540, 529, 518, 507, 497, 487, 477, 468, 459,
4174 450, 442, 434, 426, 418, 411, 404, 397, 390, 383, 377,
4175 370, 364, 358, 353, 347, 342, 336, 331, 326, 321, 316,
4176 312, 307, 303, 298, 294, 290, 286, 282, 278
4180 * Caller must hold adbentry lock
4183 maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
4184 isc_boolean_t timeout)
4190 if (adb->quota == 0 || adb->atr_freq == 0)
4194 addr->entry->timeouts++;
4196 if (addr->entry->completed++ <= adb->atr_freq)
4200 * Calculate an exponential rolling average of the timeout ratio
4202 * XXX: Integer arithmetic might be better than floating point
4204 tr = (double) addr->entry->timeouts / addr->entry->completed;
4205 addr->entry->timeouts = addr->entry->completed = 0;
4206 INSIST(addr->entry->atr >= 0.0);
4207 INSIST(addr->entry->atr <= 1.0);
4208 INSIST(adb->atr_discount >= 0.0);
4209 INSIST(adb->atr_discount <= 1.0);
4210 addr->entry->atr *= 1.0 - adb->atr_discount;
4211 addr->entry->atr += tr * adb->atr_discount;
4212 addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0);
4214 if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) {
4215 addr->entry->quota = adb->quota *
4216 quota_adj[--addr->entry->mode] / 10000;
4217 log_quota(addr->entry, "atr %0.2f, quota increased to %d",
4218 addr->entry->atr, addr->entry->quota);
4219 } else if (addr->entry->atr > adb->atr_high && addr->entry->mode < 99) {
4220 addr->entry->quota = adb->quota *
4221 quota_adj[++addr->entry->mode] / 10000;
4222 log_quota(addr->entry, "atr %0.2f, quota decreased to %d",
4223 addr->entry->atr, addr->entry->quota);
4226 /* Ensure we don't drop to zero */
4227 if (addr->entry->quota == 0)
4228 addr->entry->quota = 1;
4230 #endif /* ENABLE_FETCHLIMIT */
4233 dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
4236 REQUIRE(DNS_ADB_VALID(adb));
4237 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4239 bucket = addr->entry->lock_bucket;
4240 LOCK(&adb->entrylocks[bucket]);
4242 #ifdef ENABLE_FETCHLIMIT
4243 maybe_adjust_quota(adb, addr, ISC_FALSE);
4244 #endif /* ENABLE_FETCHLIMIT */
4246 UNLOCK(&adb->entrylocks[bucket]);
4250 dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
4251 #ifdef ENABLE_FETCHLIMIT
4254 REQUIRE(DNS_ADB_VALID(adb));
4255 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4257 bucket = addr->entry->lock_bucket;
4258 LOCK(&adb->entrylocks[bucket]);
4259 maybe_adjust_quota(adb, addr, ISC_TRUE);
4260 UNLOCK(&adb->entrylocks[bucket]);
4266 #endif /* !ENABLE_FETCHLIMIT */
4270 dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
4271 dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
4274 dns_adbentry_t *entry;
4275 dns_adbaddrinfo_t *addr;
4276 isc_result_t result;
4279 REQUIRE(DNS_ADB_VALID(adb));
4280 REQUIRE(addrp != NULL && *addrp == NULL);
4284 result = ISC_R_SUCCESS;
4285 bucket = DNS_ADB_INVALIDBUCKET;
4286 entry = find_entry_and_lock(adb, sa, &bucket, now);
4287 INSIST(bucket != DNS_ADB_INVALIDBUCKET);
4288 if (adb->entry_sd[bucket]) {
4289 result = ISC_R_SHUTTINGDOWN;
4292 if (entry == NULL) {
4294 * We don't know anything about this address.
4296 entry = new_adbentry(adb);
4297 if (entry == NULL) {
4298 result = ISC_R_NOMEMORY;
4301 entry->sockaddr = *sa;
4302 link_entry(adb, bucket, entry);
4303 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
4305 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
4307 port = isc_sockaddr_getport(sa);
4308 addr = new_adbaddrinfo(adb, entry, port);
4310 result = ISC_R_NOMEMORY;
4312 inc_entry_refcnt(adb, entry, ISC_FALSE);
4317 UNLOCK(&adb->entrylocks[bucket]);
4323 dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
4324 dns_adbaddrinfo_t *addr;
4325 dns_adbentry_t *entry;
4328 isc_boolean_t want_check_exit = ISC_FALSE;
4329 isc_boolean_t overmem;
4331 REQUIRE(DNS_ADB_VALID(adb));
4332 REQUIRE(addrp != NULL);
4334 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4335 entry = addr->entry;
4336 REQUIRE(DNS_ADBENTRY_VALID(entry));
4339 overmem = isc_mem_isovermem(adb->mctx);
4341 bucket = addr->entry->lock_bucket;
4342 LOCK(&adb->entrylocks[bucket]);
4344 if (entry->expires == 0) {
4345 isc_stdtime_get(&now);
4346 entry->expires = now + ADB_ENTRY_WINDOW;
4349 want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
4351 UNLOCK(&adb->entrylocks[bucket]);
4354 free_adbaddrinfo(adb, &addr);
4356 if (want_check_exit) {
4364 dns_adb_flush(dns_adb_t *adb) {
4367 INSIST(DNS_ADB_VALID(adb));
4372 * Call our cleanup routines.
4374 for (i = 0; i < adb->nnames; i++)
4375 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
4376 for (i = 0; i < adb->nentries; i++)
4377 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
4379 #ifdef DUMP_ADB_AFTER_CLEANING
4380 dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
4387 dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
4388 dns_adbname_t *adbname;
4389 dns_adbname_t *nextname;
4392 INSIST(DNS_ADB_VALID(adb));
4395 bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
4396 LOCK(&adb->namelocks[bucket]);
4397 adbname = ISC_LIST_HEAD(adb->names[bucket]);
4398 while (adbname != NULL) {
4399 nextname = ISC_LIST_NEXT(adbname, plink);
4400 if (!NAME_DEAD(adbname) &&
4401 dns_name_equal(name, &adbname->name)) {
4402 RUNTIME_CHECK(kill_name(&adbname,
4403 DNS_EVENT_ADBCANCELED) ==
4408 UNLOCK(&adb->namelocks[bucket]);
4413 water(void *arg, int mark) {
4415 * We're going to change the way to handle overmem condition: use
4416 * isc_mem_isovermem() instead of storing the state via this callback,
4417 * since the latter way tends to cause race conditions.
4418 * To minimize the change, and in case we re-enable the callback
4419 * approach, however, keep this function at the moment.
4422 dns_adb_t *adb = arg;
4423 isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
4425 REQUIRE(DNS_ADB_VALID(adb));
4427 DP(ISC_LOG_DEBUG(1),
4428 "adb reached %s water mark", overmem ? "high" : "low");
4432 dns_adb_setadbsize(dns_adb_t *adb, size_t size) {
4433 size_t hiwater, lowater;
4435 INSIST(DNS_ADB_VALID(adb));
4437 if (size != 0U && size < DNS_ADB_MINADBSIZE)
4438 size = DNS_ADB_MINADBSIZE;
4440 hiwater = size - (size >> 3); /* Approximately 7/8ths. */
4441 lowater = size - (size >> 2); /* Approximately 3/4ths. */
4443 if (size == 0U || hiwater == 0U || lowater == 0U)
4444 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
4446 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
4450 dns_adb_setquota(dns_adb_t *adb, isc_uint32_t quota, isc_uint32_t freq,
4451 double low, double high, double discount)
4453 #ifdef ENABLE_FETCHLIMIT
4454 REQUIRE(DNS_ADB_VALID(adb));
4457 adb->atr_freq = freq;
4459 adb->atr_high = high;
4460 adb->atr_discount = discount;
4470 #endif /* !ENABLE_FETCHLIMIT */
4474 dns_adbentry_overquota(dns_adbentry_t *entry) {
4475 #ifdef ENABLE_FETCHLIMIT
4476 isc_boolean_t block;
4477 REQUIRE(DNS_ADBENTRY_VALID(entry));
4478 block = ISC_TF(entry->quota != 0 && entry->active >= entry->quota);
4484 #endif /* !ENABLE_FETCHLIMIT */
4488 dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
4489 #ifdef ENABLE_FETCHLIMIT
4492 REQUIRE(DNS_ADB_VALID(adb));
4493 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4495 bucket = addr->entry->lock_bucket;
4497 LOCK(&adb->entrylocks[bucket]);
4498 addr->entry->active++;
4499 UNLOCK(&adb->entrylocks[bucket]);
4505 #endif /* !ENABLE_FETCHLIMIT */
4509 dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
4510 #ifdef ENABLE_FETCHLIMIT
4513 REQUIRE(DNS_ADB_VALID(adb));
4514 REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4516 bucket = addr->entry->lock_bucket;
4518 LOCK(&adb->entrylocks[bucket]);
4519 if (addr->entry->active > 0)
4520 addr->entry->active--;
4521 UNLOCK(&adb->entrylocks[bucket]);
4527 #endif /* !ENABLE_FETCHLIMIT */