adb.c revision 245163
1/*
2 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
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.
8 *
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.
16 */
17
18/* $Id$ */
19
20/*! \file
21 *
22 * \note
23 * In finds, if task == NULL, no events will be generated, and no events
24 * have been sent.  If task != NULL but taskaction == NULL, an event has been
25 * posted but not yet freed.  If neither are NULL, no event was posted.
26 *
27 */
28
29#include <config.h>
30
31#include <limits.h>
32
33#include <isc/mutexblock.h>
34#include <isc/netaddr.h>
35#include <isc/random.h>
36#include <isc/stats.h>
37#include <isc/string.h>         /* Required for HP/UX (and others?) */
38#include <isc/task.h>
39#include <isc/util.h>
40
41#include <dns/adb.h>
42#include <dns/db.h>
43#include <dns/events.h>
44#include <dns/log.h>
45#include <dns/rdata.h>
46#include <dns/rdataset.h>
47#include <dns/rdatastruct.h>
48#include <dns/rdatatype.h>
49#include <dns/resolver.h>
50#include <dns/result.h>
51#include <dns/stats.h>
52
53#define DNS_ADB_MAGIC             ISC_MAGIC('D', 'a', 'd', 'b')
54#define DNS_ADB_VALID(x)          ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
55#define DNS_ADBNAME_MAGIC         ISC_MAGIC('a', 'd', 'b', 'N')
56#define DNS_ADBNAME_VALID(x)      ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
57#define DNS_ADBNAMEHOOK_MAGIC     ISC_MAGIC('a', 'd', 'N', 'H')
58#define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
59#define DNS_ADBLAMEINFO_MAGIC     ISC_MAGIC('a', 'd', 'b', 'Z')
60#define DNS_ADBLAMEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
61#define DNS_ADBENTRY_MAGIC        ISC_MAGIC('a', 'd', 'b', 'E')
62#define DNS_ADBENTRY_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
63#define DNS_ADBFETCH_MAGIC        ISC_MAGIC('a', 'd', 'F', '4')
64#define DNS_ADBFETCH_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
65#define DNS_ADBFETCH6_MAGIC       ISC_MAGIC('a', 'd', 'F', '6')
66#define DNS_ADBFETCH6_VALID(x)    ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
67
68/*!
69 * For type 3 negative cache entries, we will remember that the address is
70 * broken for this long.  XXXMLG This is also used for actual addresses, too.
71 * The intent is to keep us from constantly asking about A/AAAA records
72 * if the zone has extremely low TTLs.
73 */
74#define ADB_CACHE_MINIMUM       10      /*%< seconds */
75#define ADB_CACHE_MAXIMUM       86400   /*%< seconds (86400 = 24 hours) */
76#define ADB_ENTRY_WINDOW        1800    /*%< seconds */
77
78/*%
79 * The period in seconds after which an ADB name entry is regarded as stale
80 * and forced to be cleaned up.
81 * TODO: This should probably be configurable at run-time.
82 */
83#ifndef ADB_STALE_MARGIN
84#define ADB_STALE_MARGIN        1800
85#endif
86
87#define FREE_ITEMS              64      /*%< free count for memory pools */
88#define FILL_COUNT              16      /*%< fill count for memory pools */
89
90#define DNS_ADB_INVALIDBUCKET (-1)      /*%< invalid bucket address */
91
92#define DNS_ADB_MINADBSIZE      (1024*1024)     /*%< 1 Megabyte */
93
94typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
95typedef struct dns_adbnamehook dns_adbnamehook_t;
96typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
97typedef struct dns_adblameinfo dns_adblameinfo_t;
98typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
99typedef struct dns_adbfetch dns_adbfetch_t;
100typedef struct dns_adbfetch6 dns_adbfetch6_t;
101
102/*% dns adb structure */
103struct dns_adb {
104	unsigned int                    magic;
105
106	isc_mutex_t                     lock;
107	isc_mutex_t                     reflock; /*%< Covers irefcnt, erefcnt */
108	isc_mutex_t                     overmemlock; /*%< Covers overmem */
109	isc_mem_t                      *mctx;
110	dns_view_t                     *view;
111
112	isc_taskmgr_t                  *taskmgr;
113	isc_task_t                     *task;
114	isc_task_t                     *excl;
115
116	isc_interval_t                  tick_interval;
117	int                             next_cleanbucket;
118
119	unsigned int                    irefcnt;
120	unsigned int                    erefcnt;
121
122	isc_mutex_t                     mplock;
123	isc_mempool_t                  *nmp;    /*%< dns_adbname_t */
124	isc_mempool_t                  *nhmp;   /*%< dns_adbnamehook_t */
125	isc_mempool_t                  *limp;   /*%< dns_adblameinfo_t */
126	isc_mempool_t                  *emp;    /*%< dns_adbentry_t */
127	isc_mempool_t                  *ahmp;   /*%< dns_adbfind_t */
128	isc_mempool_t                  *aimp;   /*%< dns_adbaddrinfo_t */
129	isc_mempool_t                  *afmp;   /*%< dns_adbfetch_t */
130
131	/*!
132	 * Bucketized locks and lists for names.
133	 *
134	 * XXXRTH  Have a per-bucket structure that contains all of these?
135	 */
136	unsigned int			nnames;
137	isc_mutex_t                     namescntlock;
138	unsigned int			namescnt;
139	dns_adbnamelist_t               *names;
140	dns_adbnamelist_t               *deadnames;
141	isc_mutex_t                     *namelocks;
142	isc_boolean_t                   *name_sd;
143	unsigned int                    *name_refcnt;
144
145	/*!
146	 * Bucketized locks and lists for entries.
147	 *
148	 * XXXRTH  Have a per-bucket structure that contains all of these?
149	 */
150	unsigned int			nentries;
151	isc_mutex_t                     entriescntlock;
152	unsigned int			entriescnt;
153	dns_adbentrylist_t              *entries;
154	dns_adbentrylist_t              *deadentries;
155	isc_mutex_t                     *entrylocks;
156	isc_boolean_t                   *entry_sd; /*%< shutting down */
157	unsigned int                    *entry_refcnt;
158
159	isc_event_t                     cevent;
160	isc_boolean_t                   cevent_sent;
161	isc_boolean_t                   shutting_down;
162	isc_eventlist_t                 whenshutdown;
163	isc_event_t			growentries;
164	isc_boolean_t			growentries_sent;
165	isc_event_t			grownames;
166	isc_boolean_t			grownames_sent;
167};
168
169/*
170 * XXXMLG  Document these structures.
171 */
172
173/*% dns_adbname structure */
174struct dns_adbname {
175	unsigned int                    magic;
176	dns_name_t                      name;
177	dns_adb_t                      *adb;
178	unsigned int                    partial_result;
179	unsigned int                    flags;
180	int                             lock_bucket;
181	dns_name_t                      target;
182	isc_stdtime_t                   expire_target;
183	isc_stdtime_t                   expire_v4;
184	isc_stdtime_t                   expire_v6;
185	unsigned int                    chains;
186	dns_adbnamehooklist_t           v4;
187	dns_adbnamehooklist_t           v6;
188	dns_adbfetch_t                 *fetch_a;
189	dns_adbfetch_t                 *fetch_aaaa;
190	unsigned int                    fetch_err;
191	unsigned int                    fetch6_err;
192	dns_adbfindlist_t               finds;
193	/* for LRU-based management */
194	isc_stdtime_t                   last_used;
195
196	ISC_LINK(dns_adbname_t)         plink;
197};
198
199/*% The adbfetch structure */
200struct dns_adbfetch {
201	unsigned int                    magic;
202	dns_fetch_t                    *fetch;
203	dns_rdataset_t                  rdataset;
204};
205
206/*%
207 * This is a small widget that dangles off a dns_adbname_t.  It contains a
208 * pointer to the address information about this host, and a link to the next
209 * namehook that will contain the next address this host has.
210 */
211struct dns_adbnamehook {
212	unsigned int                    magic;
213	dns_adbentry_t                 *entry;
214	ISC_LINK(dns_adbnamehook_t)     plink;
215};
216
217/*%
218 * This is a small widget that holds qname-specific information about an
219 * address.  Currently limited to lameness, but could just as easily be
220 * extended to other types of information about zones.
221 */
222struct dns_adblameinfo {
223	unsigned int                    magic;
224
225	dns_name_t                      qname;
226	dns_rdatatype_t                 qtype;
227	isc_stdtime_t                   lame_timer;
228
229	ISC_LINK(dns_adblameinfo_t)     plink;
230};
231
232/*%
233 * An address entry.  It holds quite a bit of information about addresses,
234 * including edns state (in "flags"), rtt, and of course the address of
235 * the host.
236 */
237struct dns_adbentry {
238	unsigned int                    magic;
239
240	int                             lock_bucket;
241	unsigned int                    refcnt;
242
243	unsigned int                    flags;
244	unsigned int                    srtt;
245	isc_sockaddr_t                  sockaddr;
246
247	isc_stdtime_t                   expires;
248	/*%<
249	 * A nonzero 'expires' field indicates that the entry should
250	 * persist until that time.  This allows entries found
251	 * using dns_adb_findaddrinfo() to persist for a limited time
252	 * even though they are not necessarily associated with a
253	 * name.
254	 */
255
256	ISC_LIST(dns_adblameinfo_t)     lameinfo;
257	ISC_LINK(dns_adbentry_t)        plink;
258
259};
260
261/*
262 * Internal functions (and prototypes).
263 */
264static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
265static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
266static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
267						 dns_adbentry_t *);
268static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
269static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
270						 dns_rdatatype_t);
271static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
272static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
273static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
274static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
275static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
276static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
277						 in_port_t);
278static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
279static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
280static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
281						unsigned int, int *);
282static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
283						  isc_sockaddr_t *, int *,
284						  isc_stdtime_t);
285static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
286static void print_dns_name(FILE *, dns_name_t *);
287static void print_namehook_list(FILE *, const char *legend,
288				dns_adbnamehooklist_t *list,
289				isc_boolean_t debug,
290				isc_stdtime_t now);
291static void print_find_list(FILE *, dns_adbname_t *);
292static void print_fetch_list(FILE *, dns_adbname_t *);
293static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
294static inline void inc_adb_irefcnt(dns_adb_t *);
295static inline void inc_adb_erefcnt(dns_adb_t *);
296static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
297				    isc_boolean_t);
298static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
299					     dns_adbentry_t *, isc_boolean_t);
300static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
301static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
302static void clean_target(dns_adb_t *, dns_name_t *);
303static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
304				unsigned int);
305static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
306static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
307					isc_stdtime_t);
308static void cancel_fetches_at_name(dns_adbname_t *);
309static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
310				dns_rdatatype_t);
311static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
312			       dns_rdatatype_t);
313static inline void check_exit(dns_adb_t *);
314static void destroy(dns_adb_t *);
315static isc_boolean_t shutdown_names(dns_adb_t *);
316static isc_boolean_t shutdown_entries(dns_adb_t *);
317static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
318static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
319static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
320static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
321static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
322static void water(void *, int);
323static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
324
325/*
326 * MUST NOT overlap DNS_ADBFIND_* flags!
327 */
328#define FIND_EVENT_SENT         0x40000000
329#define FIND_EVENT_FREED        0x80000000
330#define FIND_EVENTSENT(h)       (((h)->flags & FIND_EVENT_SENT) != 0)
331#define FIND_EVENTFREED(h)      (((h)->flags & FIND_EVENT_FREED) != 0)
332
333#define NAME_NEEDS_POKE         0x80000000
334#define NAME_IS_DEAD            0x40000000
335#define NAME_HINT_OK            DNS_ADBFIND_HINTOK
336#define NAME_GLUE_OK            DNS_ADBFIND_GLUEOK
337#define NAME_STARTATZONE        DNS_ADBFIND_STARTATZONE
338#define NAME_DEAD(n)            (((n)->flags & NAME_IS_DEAD) != 0)
339#define NAME_NEEDSPOKE(n)       (((n)->flags & NAME_NEEDS_POKE) != 0)
340#define NAME_GLUEOK(n)          (((n)->flags & NAME_GLUE_OK) != 0)
341#define NAME_HINTOK(n)          (((n)->flags & NAME_HINT_OK) != 0)
342
343/*
344 * Private flag(s) for entries.
345 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
346 */
347#define ENTRY_IS_DEAD		0x80000000
348
349/*
350 * To the name, address classes are all that really exist.  If it has a
351 * V6 address it doesn't care if it came from a AAAA query.
352 */
353#define NAME_HAS_V4(n)          (!ISC_LIST_EMPTY((n)->v4))
354#define NAME_HAS_V6(n)          (!ISC_LIST_EMPTY((n)->v6))
355#define NAME_HAS_ADDRS(n)       (NAME_HAS_V4(n) || NAME_HAS_V6(n))
356
357/*
358 * Fetches are broken out into A and AAAA types.  In some cases,
359 * however, it makes more sense to test for a particular class of fetches,
360 * like V4 or V6 above.
361 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
362 * are now equal to FETCH_V4 and FETCH_V6, respectively.
363 */
364#define NAME_FETCH_A(n)         ((n)->fetch_a != NULL)
365#define NAME_FETCH_AAAA(n)      ((n)->fetch_aaaa != NULL)
366#define NAME_FETCH_V4(n)        (NAME_FETCH_A(n))
367#define NAME_FETCH_V6(n)        (NAME_FETCH_AAAA(n))
368#define NAME_FETCH(n)           (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
369
370/*
371 * Find options and tests to see if there are addresses on the list.
372 */
373#define FIND_WANTEVENT(fn)      (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
374#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
375#define FIND_AVOIDFETCHES(fn)   (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
376				 != 0)
377#define FIND_STARTATZONE(fn)    (((fn)->options & DNS_ADBFIND_STARTATZONE) \
378				 != 0)
379#define FIND_HINTOK(fn)         (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
380#define FIND_GLUEOK(fn)         (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
381#define FIND_HAS_ADDRS(fn)      (!ISC_LIST_EMPTY((fn)->list))
382#define FIND_RETURNLAME(fn)     (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
383
384/*
385 * These are currently used on simple unsigned ints, so they are
386 * not really associated with any particular type.
387 */
388#define WANT_INET(x)            (((x) & DNS_ADBFIND_INET) != 0)
389#define WANT_INET6(x)           (((x) & DNS_ADBFIND_INET6) != 0)
390
391#define EXPIRE_OK(exp, now)     ((exp == INT_MAX) || (exp < now))
392
393/*
394 * Find out if the flags on a name (nf) indicate if it is a hint or
395 * glue, and compare this to the appropriate bits set in o, to see if
396 * this is ok.
397 */
398#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
399#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
400#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
401#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
402				    ((o) & DNS_ADBFIND_STARTATZONE))
403
404#define ENTER_LEVEL             ISC_LOG_DEBUG(50)
405#define EXIT_LEVEL              ENTER_LEVEL
406#define CLEAN_LEVEL             ISC_LOG_DEBUG(100)
407#define DEF_LEVEL               ISC_LOG_DEBUG(5)
408#define NCACHE_LEVEL            ISC_LOG_DEBUG(20)
409
410#define NCACHE_RESULT(r)        ((r) == DNS_R_NCACHENXDOMAIN || \
411				 (r) == DNS_R_NCACHENXRRSET)
412#define AUTH_NX(r)              ((r) == DNS_R_NXDOMAIN || \
413				 (r) == DNS_R_NXRRSET)
414#define NXDOMAIN_RESULT(r)      ((r) == DNS_R_NXDOMAIN || \
415				 (r) == DNS_R_NCACHENXDOMAIN)
416#define NXRRSET_RESULT(r)       ((r) == DNS_R_NCACHENXRRSET || \
417				 (r) == DNS_R_NXRRSET || \
418				 (r) == DNS_R_HINTNXRRSET)
419
420/*
421 * Error state rankings.
422 */
423
424#define FIND_ERR_SUCCESS                0  /* highest rank */
425#define FIND_ERR_CANCELED               1
426#define FIND_ERR_FAILURE                2
427#define FIND_ERR_NXDOMAIN               3
428#define FIND_ERR_NXRRSET                4
429#define FIND_ERR_UNEXPECTED             5
430#define FIND_ERR_NOTFOUND               6
431#define FIND_ERR_MAX                    7
432
433static const char *errnames[] = {
434	"success",
435	"canceled",
436	"failure",
437	"nxdomain",
438	"nxrrset",
439	"unexpected",
440	"not_found"
441};
442
443#define NEWERR(old, new)        (ISC_MIN((old), (new)))
444
445static isc_result_t find_err_map[FIND_ERR_MAX] = {
446	ISC_R_SUCCESS,
447	ISC_R_CANCELED,
448	ISC_R_FAILURE,
449	DNS_R_NXDOMAIN,
450	DNS_R_NXRRSET,
451	ISC_R_UNEXPECTED,
452	ISC_R_NOTFOUND          /* not YET found */
453};
454
455static void
456DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
457
458static void
459DP(int level, const char *format, ...) {
460	va_list args;
461
462	va_start(args, format);
463	isc_log_vwrite(dns_lctx,
464		       DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
465		       level, format, args);
466	va_end(args);
467}
468
469/*%
470 * Increment resolver-related statistics counters.
471 */
472static inline void
473inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
474	if (adb->view->resstats != NULL)
475		isc_stats_increment(adb->view->resstats, counter);
476}
477
478static inline dns_ttl_t
479ttlclamp(dns_ttl_t ttl) {
480	if (ttl < ADB_CACHE_MINIMUM)
481		ttl = ADB_CACHE_MINIMUM;
482	if (ttl > ADB_CACHE_MAXIMUM)
483		ttl = ADB_CACHE_MAXIMUM;
484
485	return (ttl);
486}
487
488/*
489 * Hashing is most efficient if the number of buckets is prime.
490 * The sequence below is the closest previous primes to 2^n and
491 * 1.5 * 2^n, for values of n from 10 to 28.  (The tables will
492 * no longer grow beyond 2^28 entries.)
493 */
494static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
495				     8191, 12281, 16381, 24571, 32749,
496				     49193, 65521, 98299, 131071, 199603,
497				     262139, 393209, 524287, 768431, 1048573,
498				     1572853, 2097143, 3145721, 4194301,
499				     6291449, 8388593, 12582893, 16777213,
500				     25165813, 33554393, 50331599, 67108859,
501				     100663291, 134217689, 201326557,
502				     268535431, 0 };
503
504static void
505grow_entries(isc_task_t *task, isc_event_t *ev) {
506	dns_adb_t *adb;
507	dns_adbentry_t *e;
508	dns_adbentrylist_t *newdeadentries = NULL;
509	dns_adbentrylist_t *newentries = NULL;
510	isc_boolean_t *newentry_sd = NULL;
511	isc_mutex_t *newentrylocks = NULL;
512	isc_result_t result;
513	unsigned int *newentry_refcnt = NULL;
514	unsigned int i, n, bucket;
515
516	adb = ev->ev_arg;
517	INSIST(DNS_ADB_VALID(adb));
518
519	isc_event_free(&ev);
520
521	isc_task_beginexclusive(task);
522
523	i = 0;
524	while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
525		i++;
526	if (nbuckets[i] != 0)
527		n = nbuckets[i];
528	else
529		goto done;
530
531	DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
532
533	/*
534	 * Are we shutting down?
535	 */
536	for (i = 0; i < adb->nentries; i++)
537		if (adb->entry_sd[i])
538			goto cleanup;
539
540	/*
541	 * Grab all the resources we need.
542	 */
543	newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
544	newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
545	newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
546	newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
547	newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
548	if (newentries == NULL || newdeadentries == NULL ||
549	    newentrylocks == NULL || newentry_sd == NULL ||
550	    newentry_refcnt == NULL)
551		goto cleanup;
552
553	/*
554	 * Initialise the new resources.
555	 */
556	result = isc_mutexblock_init(newentrylocks, n);
557	if (result != ISC_R_SUCCESS)
558		goto cleanup;
559
560	for (i = 0; i < n; i++) {
561		ISC_LIST_INIT(newentries[i]);
562		ISC_LIST_INIT(newdeadentries[i]);
563		newentry_sd[i] = ISC_FALSE;
564		newentry_refcnt[i] = 0;
565		adb->irefcnt++;
566	}
567
568	/*
569	 * Move entries to new arrays.
570	 */
571	for (i = 0; i < adb->nentries; i++) {
572		e = ISC_LIST_HEAD(adb->entries[i]);
573		while (e != NULL) {
574			ISC_LIST_UNLINK(adb->entries[i], e, plink);
575			bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
576			e->lock_bucket = bucket;
577			ISC_LIST_APPEND(newentries[bucket], e, plink);
578			INSIST(adb->entry_refcnt[i] > 0);
579			adb->entry_refcnt[i]--;
580			newentry_refcnt[bucket]++;
581			e = ISC_LIST_HEAD(adb->entries[i]);
582		}
583		e = ISC_LIST_HEAD(adb->deadentries[i]);
584		while (e != NULL) {
585			ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
586			bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
587			e->lock_bucket = bucket;
588			ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
589			INSIST(adb->entry_refcnt[i] > 0);
590			adb->entry_refcnt[i]--;
591			newentry_refcnt[bucket]++;
592			e = ISC_LIST_HEAD(adb->deadentries[i]);
593		}
594		INSIST(adb->entry_refcnt[i] == 0);
595		adb->irefcnt--;
596	}
597
598	/*
599	 * Cleanup old resources.
600	 */
601	DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
602	isc_mem_put(adb->mctx, adb->entries,
603		    sizeof(*adb->entries) * adb->nentries);
604	isc_mem_put(adb->mctx, adb->deadentries,
605		    sizeof(*adb->deadentries) * adb->nentries);
606	isc_mem_put(adb->mctx, adb->entrylocks,
607		    sizeof(*adb->entrylocks) * adb->nentries);
608	isc_mem_put(adb->mctx, adb->entry_sd,
609		    sizeof(*adb->entry_sd) * adb->nentries);
610	isc_mem_put(adb->mctx, adb->entry_refcnt,
611		    sizeof(*adb->entry_refcnt) * adb->nentries);
612
613	/*
614	 * Install new resources.
615	 */
616	adb->entries = newentries;
617	adb->deadentries = newdeadentries;
618	adb->entrylocks = newentrylocks;
619	adb->entry_sd = newentry_sd;
620	adb->entry_refcnt = newentry_refcnt;
621	adb->nentries = n;
622
623	/*
624	 * Only on success do we set adb->growentries_sent to ISC_FALSE.
625	 * This will prevent us being continuously being called on error.
626	 */
627	adb->growentries_sent = ISC_FALSE;
628	goto done;
629
630 cleanup:
631	if (newentries != NULL)
632		isc_mem_put(adb->mctx, newentries,
633			    sizeof(*newentries) * n);
634	if (newdeadentries != NULL)
635		isc_mem_put(adb->mctx, newdeadentries,
636			    sizeof(*newdeadentries) * n);
637	if (newentrylocks != NULL)
638		isc_mem_put(adb->mctx, newentrylocks,
639			    sizeof(*newentrylocks) * n);
640	if (newentry_sd != NULL)
641		isc_mem_put(adb->mctx, newentry_sd,
642			    sizeof(*newentry_sd) * n);
643	if (newentry_refcnt != NULL)
644		isc_mem_put(adb->mctx, newentry_refcnt,
645			     sizeof(*newentry_refcnt) * n);
646 done:
647	isc_task_endexclusive(task);
648
649	LOCK(&adb->lock);
650	if (dec_adb_irefcnt(adb))
651		check_exit(adb);
652	UNLOCK(&adb->lock);
653	DP(ISC_LOG_INFO, "adb: grow_entries finished");
654}
655
656static void
657grow_names(isc_task_t *task, isc_event_t *ev) {
658	dns_adb_t *adb;
659	dns_adbname_t *name;
660	dns_adbnamelist_t *newdeadnames = NULL;
661	dns_adbnamelist_t *newnames = NULL;
662	isc_boolean_t *newname_sd = NULL;
663	isc_mutex_t *newnamelocks = NULL;
664	isc_result_t result;
665	unsigned int *newname_refcnt = NULL;
666	unsigned int i, n, bucket;
667
668	adb = ev->ev_arg;
669	INSIST(DNS_ADB_VALID(adb));
670
671	isc_event_free(&ev);
672
673	isc_task_beginexclusive(task);
674
675	i = 0;
676	while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
677		i++;
678	if (nbuckets[i] != 0)
679		n = nbuckets[i];
680	else
681		goto done;
682
683	DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
684
685	/*
686	 * Are we shutting down?
687	 */
688	for (i = 0; i < adb->nnames; i++)
689		if (adb->name_sd[i])
690			goto cleanup;
691
692	/*
693	 * Grab all the resources we need.
694	 */
695	newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
696	newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
697	newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
698	newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
699	newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
700	if (newnames == NULL || newdeadnames == NULL ||
701	    newnamelocks == NULL || newname_sd == NULL ||
702	    newname_refcnt == NULL)
703		goto cleanup;
704
705	/*
706	 * Initialise the new resources.
707	 */
708	result = isc_mutexblock_init(newnamelocks, n);
709	if (result != ISC_R_SUCCESS)
710		goto cleanup;
711
712	for (i = 0; i < n; i++) {
713		ISC_LIST_INIT(newnames[i]);
714		ISC_LIST_INIT(newdeadnames[i]);
715		newname_sd[i] = ISC_FALSE;
716		newname_refcnt[i] = 0;
717		adb->irefcnt++;
718	}
719
720	/*
721	 * Move names to new arrays.
722	 */
723	for (i = 0; i < adb->nnames; i++) {
724		name = ISC_LIST_HEAD(adb->names[i]);
725		while (name != NULL) {
726			ISC_LIST_UNLINK(adb->names[i], name, plink);
727			bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
728			name->lock_bucket = bucket;
729			ISC_LIST_APPEND(newnames[bucket], name, plink);
730			INSIST(adb->name_refcnt[i] > 0);
731			adb->name_refcnt[i]--;
732			newname_refcnt[bucket]++;
733			name = ISC_LIST_HEAD(adb->names[i]);
734		}
735		name = ISC_LIST_HEAD(adb->deadnames[i]);
736		while (name != NULL) {
737			ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
738			bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
739			name->lock_bucket = bucket;
740			ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
741			INSIST(adb->name_refcnt[i] > 0);
742			adb->name_refcnt[i]--;
743			newname_refcnt[bucket]++;
744			name = ISC_LIST_HEAD(adb->deadnames[i]);
745		}
746		INSIST(adb->name_refcnt[i] == 0);
747		adb->irefcnt--;
748	}
749
750	/*
751	 * Cleanup old resources.
752	 */
753	DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
754	isc_mem_put(adb->mctx, adb->names,
755		    sizeof(*adb->names) * adb->nnames);
756	isc_mem_put(adb->mctx, adb->deadnames,
757		    sizeof(*adb->deadnames) * adb->nnames);
758	isc_mem_put(adb->mctx, adb->namelocks,
759		    sizeof(*adb->namelocks) * adb->nnames);
760	isc_mem_put(adb->mctx, adb->name_sd,
761		    sizeof(*adb->name_sd) * adb->nnames);
762	isc_mem_put(adb->mctx, adb->name_refcnt,
763		    sizeof(*adb->name_refcnt) * adb->nnames);
764
765	/*
766	 * Install new resources.
767	 */
768	adb->names = newnames;
769	adb->deadnames = newdeadnames;
770	adb->namelocks = newnamelocks;
771	adb->name_sd = newname_sd;
772	adb->name_refcnt = newname_refcnt;
773	adb->nnames = n;
774
775	/*
776	 * Only on success do we set adb->grownames_sent to ISC_FALSE.
777	 * This will prevent us being continuously being called on error.
778	 */
779	adb->grownames_sent = ISC_FALSE;
780	goto done;
781
782 cleanup:
783	if (newnames != NULL)
784		isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
785	if (newdeadnames != NULL)
786		isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
787	if (newnamelocks != NULL)
788		isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
789	if (newname_sd != NULL)
790		isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
791	if (newname_refcnt != NULL)
792		isc_mem_put(adb->mctx, newname_refcnt,
793			     sizeof(*newname_refcnt) * n);
794 done:
795	isc_task_endexclusive(task);
796
797	LOCK(&adb->lock);
798	if (dec_adb_irefcnt(adb))
799		check_exit(adb);
800	UNLOCK(&adb->lock);
801	DP(ISC_LOG_INFO, "adb: grow_names finished");
802}
803
804/*
805 * Requires the adbname bucket be locked and that no entry buckets be locked.
806 *
807 * This code handles A and AAAA rdatasets only.
808 */
809static isc_result_t
810import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
811		isc_stdtime_t now)
812{
813	isc_result_t result;
814	dns_adb_t *adb;
815	dns_adbnamehook_t *nh;
816	dns_adbnamehook_t *anh;
817	dns_rdata_t rdata = DNS_RDATA_INIT;
818	struct in_addr ina;
819	struct in6_addr in6a;
820	isc_sockaddr_t sockaddr;
821	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
822	int addr_bucket;
823	isc_boolean_t new_addresses_added;
824	dns_rdatatype_t rdtype;
825	unsigned int findoptions;
826	dns_adbnamehooklist_t *hookhead;
827
828	INSIST(DNS_ADBNAME_VALID(adbname));
829	adb = adbname->adb;
830	INSIST(DNS_ADB_VALID(adb));
831
832	rdtype = rdataset->type;
833	INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
834	if (rdtype == dns_rdatatype_a)
835		findoptions = DNS_ADBFIND_INET;
836	else
837		findoptions = DNS_ADBFIND_INET6;
838
839	addr_bucket = DNS_ADB_INVALIDBUCKET;
840	new_addresses_added = ISC_FALSE;
841
842	nh = NULL;
843	result = dns_rdataset_first(rdataset);
844	while (result == ISC_R_SUCCESS) {
845		dns_rdata_reset(&rdata);
846		dns_rdataset_current(rdataset, &rdata);
847		if (rdtype == dns_rdatatype_a) {
848			INSIST(rdata.length == 4);
849			memcpy(&ina.s_addr, rdata.data, 4);
850			isc_sockaddr_fromin(&sockaddr, &ina, 0);
851			hookhead = &adbname->v4;
852		} else {
853			INSIST(rdata.length == 16);
854			memcpy(in6a.s6_addr, rdata.data, 16);
855			isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
856			hookhead = &adbname->v6;
857		}
858
859		INSIST(nh == NULL);
860		nh = new_adbnamehook(adb, NULL);
861		if (nh == NULL) {
862			adbname->partial_result |= findoptions;
863			result = ISC_R_NOMEMORY;
864			goto fail;
865		}
866
867		foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
868						 now);
869		if (foundentry == NULL) {
870			dns_adbentry_t *entry;
871
872			entry = new_adbentry(adb);
873			if (entry == NULL) {
874				adbname->partial_result |= findoptions;
875				result = ISC_R_NOMEMORY;
876				goto fail;
877			}
878
879			entry->sockaddr = sockaddr;
880			entry->refcnt = 1;
881
882			nh->entry = entry;
883
884			link_entry(adb, addr_bucket, entry);
885		} else {
886			for (anh = ISC_LIST_HEAD(*hookhead);
887			     anh != NULL;
888			     anh = ISC_LIST_NEXT(anh, plink))
889				if (anh->entry == foundentry)
890					break;
891			if (anh == NULL) {
892				foundentry->refcnt++;
893				nh->entry = foundentry;
894			} else
895				free_adbnamehook(adb, &nh);
896		}
897
898		new_addresses_added = ISC_TRUE;
899		if (nh != NULL)
900			ISC_LIST_APPEND(*hookhead, nh, plink);
901		nh = NULL;
902		result = dns_rdataset_next(rdataset);
903	}
904
905 fail:
906	if (nh != NULL)
907		free_adbnamehook(adb, &nh);
908
909	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
910		UNLOCK(&adb->entrylocks[addr_bucket]);
911
912	if (rdataset->trust == dns_trust_glue ||
913	    rdataset->trust == dns_trust_additional)
914		rdataset->ttl = ADB_CACHE_MINIMUM;
915	else if (rdataset->trust == dns_trust_ultimate)
916		rdataset->ttl = 0;
917	else
918		rdataset->ttl = ttlclamp(rdataset->ttl);
919
920	if (rdtype == dns_rdatatype_a) {
921		DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
922		   adbname->expire_v4, now + rdataset->ttl);
923		adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
924					     now + rdataset->ttl);
925	} else {
926		DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
927		   adbname->expire_v6, now + rdataset->ttl);
928		adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
929					     now + rdataset->ttl);
930	}
931
932	if (new_addresses_added) {
933		/*
934		 * Lie a little here.  This is more or less so code that cares
935		 * can find out if any new information was added or not.
936		 */
937		return (ISC_R_SUCCESS);
938	}
939
940	return (result);
941}
942
943/*
944 * Requires the name's bucket be locked.
945 */
946static isc_boolean_t
947kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
948	dns_adbname_t *name;
949	isc_boolean_t result = ISC_FALSE;
950	isc_boolean_t result4, result6;
951	int bucket;
952	dns_adb_t *adb;
953
954	INSIST(n != NULL);
955	name = *n;
956	*n = NULL;
957	INSIST(DNS_ADBNAME_VALID(name));
958	adb = name->adb;
959	INSIST(DNS_ADB_VALID(adb));
960
961	DP(DEF_LEVEL, "killing name %p", name);
962
963	/*
964	 * If we're dead already, just check to see if we should go
965	 * away now or not.
966	 */
967	if (NAME_DEAD(name) && !NAME_FETCH(name)) {
968		result = unlink_name(adb, name);
969		free_adbname(adb, &name);
970		if (result)
971			result = dec_adb_irefcnt(adb);
972		return (result);
973	}
974
975	/*
976	 * Clean up the name's various lists.  These two are destructive
977	 * in that they will always empty the list.
978	 */
979	clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
980	result4 = clean_namehooks(adb, &name->v4);
981	result6 = clean_namehooks(adb, &name->v6);
982	clean_target(adb, &name->target);
983	result = ISC_TF(result4 || result6);
984
985	/*
986	 * If fetches are running, cancel them.  If none are running, we can
987	 * just kill the name here.
988	 */
989	if (!NAME_FETCH(name)) {
990		INSIST(result == ISC_FALSE);
991		result = unlink_name(adb, name);
992		free_adbname(adb, &name);
993		if (result)
994			result = dec_adb_irefcnt(adb);
995	} else {
996		cancel_fetches_at_name(name);
997		if (!NAME_DEAD(name)) {
998			bucket = name->lock_bucket;
999			ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1000			ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
1001			name->flags |= NAME_IS_DEAD;
1002		}
1003	}
1004	return (result);
1005}
1006
1007/*
1008 * Requires the name's bucket be locked and no entry buckets be locked.
1009 */
1010static isc_boolean_t
1011check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
1012	dns_adb_t *adb;
1013	isc_boolean_t result4 = ISC_FALSE;
1014	isc_boolean_t result6 = ISC_FALSE;
1015
1016	INSIST(DNS_ADBNAME_VALID(name));
1017	adb = name->adb;
1018	INSIST(DNS_ADB_VALID(adb));
1019
1020	/*
1021	 * Check to see if we need to remove the v4 addresses
1022	 */
1023	if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
1024		if (NAME_HAS_V4(name)) {
1025			DP(DEF_LEVEL, "expiring v4 for name %p", name);
1026			result4 = clean_namehooks(adb, &name->v4);
1027			name->partial_result &= ~DNS_ADBFIND_INET;
1028		}
1029		name->expire_v4 = INT_MAX;
1030		name->fetch_err = FIND_ERR_UNEXPECTED;
1031	}
1032
1033	/*
1034	 * Check to see if we need to remove the v6 addresses
1035	 */
1036	if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
1037		if (NAME_HAS_V6(name)) {
1038			DP(DEF_LEVEL, "expiring v6 for name %p", name);
1039			result6 = clean_namehooks(adb, &name->v6);
1040			name->partial_result &= ~DNS_ADBFIND_INET6;
1041		}
1042		name->expire_v6 = INT_MAX;
1043		name->fetch6_err = FIND_ERR_UNEXPECTED;
1044	}
1045
1046	/*
1047	 * Check to see if we need to remove the alias target.
1048	 */
1049	if (EXPIRE_OK(name->expire_target, now)) {
1050		clean_target(adb, &name->target);
1051		name->expire_target = INT_MAX;
1052	}
1053	return (ISC_TF(result4 || result6));
1054}
1055
1056/*
1057 * Requires the name's bucket be locked.
1058 */
1059static inline void
1060link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1061	INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
1062
1063	ISC_LIST_PREPEND(adb->names[bucket], name, plink);
1064	name->lock_bucket = bucket;
1065	adb->name_refcnt[bucket]++;
1066}
1067
1068/*
1069 * Requires the name's bucket be locked.
1070 */
1071static inline isc_boolean_t
1072unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
1073	int bucket;
1074	isc_boolean_t result = ISC_FALSE;
1075
1076	bucket = name->lock_bucket;
1077	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1078
1079	if (NAME_DEAD(name))
1080		ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
1081	else
1082		ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1083	name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1084	INSIST(adb->name_refcnt[bucket] > 0);
1085	adb->name_refcnt[bucket]--;
1086	if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
1087		result = ISC_TRUE;
1088	return (result);
1089}
1090
1091/*
1092 * Requires the entry's bucket be locked.
1093 */
1094static inline void
1095link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
1096	int i;
1097	dns_adbentry_t *e;
1098
1099	if (isc_mem_isovermem(adb->mctx)) {
1100		for (i = 0; i < 2; i++) {
1101			e = ISC_LIST_TAIL(adb->entries[bucket]);
1102			if (e == NULL)
1103				break;
1104			if (e->refcnt == 0) {
1105				unlink_entry(adb, e);
1106				free_adbentry(adb, &e);
1107				continue;
1108			}
1109			INSIST((e->flags & ENTRY_IS_DEAD) == 0);
1110			e->flags |= ENTRY_IS_DEAD;
1111			ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
1112			ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
1113		}
1114	}
1115
1116	ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
1117	entry->lock_bucket = bucket;
1118	adb->entry_refcnt[bucket]++;
1119}
1120
1121/*
1122 * Requires the entry's bucket be locked.
1123 */
1124static inline isc_boolean_t
1125unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
1126	int bucket;
1127	isc_boolean_t result = ISC_FALSE;
1128
1129	bucket = entry->lock_bucket;
1130	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1131
1132	if ((entry->flags & ENTRY_IS_DEAD) != 0)
1133		ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
1134	else
1135		ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
1136	entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1137	INSIST(adb->entry_refcnt[bucket] > 0);
1138	adb->entry_refcnt[bucket]--;
1139	if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
1140		result = ISC_TRUE;
1141	return (result);
1142}
1143
1144static inline void
1145violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
1146	if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
1147		UNLOCK(have);
1148		LOCK(want);
1149		LOCK(have);
1150	}
1151}
1152
1153/*
1154 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
1155 * checked after calling this function.
1156 */
1157static isc_boolean_t
1158shutdown_names(dns_adb_t *adb) {
1159	unsigned int bucket;
1160	isc_boolean_t result = ISC_FALSE;
1161	dns_adbname_t *name;
1162	dns_adbname_t *next_name;
1163
1164	for (bucket = 0; bucket < adb->nnames; bucket++) {
1165		LOCK(&adb->namelocks[bucket]);
1166		adb->name_sd[bucket] = ISC_TRUE;
1167
1168		name = ISC_LIST_HEAD(adb->names[bucket]);
1169		if (name == NULL) {
1170			/*
1171			 * This bucket has no names.  We must decrement the
1172			 * irefcnt ourselves, since it will not be
1173			 * automatically triggered by a name being unlinked.
1174			 */
1175			INSIST(result == ISC_FALSE);
1176			result = dec_adb_irefcnt(adb);
1177		} else {
1178			/*
1179			 * Run through the list.  For each name, clean up finds
1180			 * found there, and cancel any fetches running.  When
1181			 * all the fetches are canceled, the name will destroy
1182			 * itself.
1183			 */
1184			while (name != NULL) {
1185				next_name = ISC_LIST_NEXT(name, plink);
1186				INSIST(result == ISC_FALSE);
1187				result = kill_name(&name,
1188						   DNS_EVENT_ADBSHUTDOWN);
1189				name = next_name;
1190			}
1191		}
1192
1193		UNLOCK(&adb->namelocks[bucket]);
1194	}
1195	return (result);
1196}
1197
1198/*
1199 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
1200 * checked after calling this function.
1201 */
1202static isc_boolean_t
1203shutdown_entries(dns_adb_t *adb) {
1204	unsigned int bucket;
1205	isc_boolean_t result = ISC_FALSE;
1206	dns_adbentry_t *entry;
1207	dns_adbentry_t *next_entry;
1208
1209	for (bucket = 0; bucket < adb->nentries; bucket++) {
1210		LOCK(&adb->entrylocks[bucket]);
1211		adb->entry_sd[bucket] = ISC_TRUE;
1212
1213		entry = ISC_LIST_HEAD(adb->entries[bucket]);
1214		if (adb->entry_refcnt[bucket] == 0) {
1215			/*
1216			 * This bucket has no entries.  We must decrement the
1217			 * irefcnt ourselves, since it will not be
1218			 * automatically triggered by an entry being unlinked.
1219			 */
1220			result = dec_adb_irefcnt(adb);
1221		} else {
1222			/*
1223			 * Run through the list.  Cleanup any entries not
1224			 * associated with names, and which are not in use.
1225			 */
1226			while (entry != NULL) {
1227				next_entry = ISC_LIST_NEXT(entry, plink);
1228				if (entry->refcnt == 0 &&
1229				    entry->expires != 0) {
1230					result = unlink_entry(adb, entry);
1231					free_adbentry(adb, &entry);
1232					if (result)
1233						result = dec_adb_irefcnt(adb);
1234				}
1235				entry = next_entry;
1236			}
1237		}
1238
1239		UNLOCK(&adb->entrylocks[bucket]);
1240	}
1241	return (result);
1242}
1243
1244/*
1245 * Name bucket must be locked
1246 */
1247static void
1248cancel_fetches_at_name(dns_adbname_t *name) {
1249	if (NAME_FETCH_A(name))
1250	    dns_resolver_cancelfetch(name->fetch_a->fetch);
1251
1252	if (NAME_FETCH_AAAA(name))
1253	    dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
1254}
1255
1256/*
1257 * Assumes the name bucket is locked.
1258 */
1259static isc_boolean_t
1260clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
1261	dns_adbentry_t *entry;
1262	dns_adbnamehook_t *namehook;
1263	int addr_bucket;
1264	isc_boolean_t result = ISC_FALSE;
1265	isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
1266
1267	addr_bucket = DNS_ADB_INVALIDBUCKET;
1268	namehook = ISC_LIST_HEAD(*namehooks);
1269	while (namehook != NULL) {
1270		INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
1271
1272		/*
1273		 * Clean up the entry if needed.
1274		 */
1275		entry = namehook->entry;
1276		if (entry != NULL) {
1277			INSIST(DNS_ADBENTRY_VALID(entry));
1278
1279			if (addr_bucket != entry->lock_bucket) {
1280				if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1281					UNLOCK(&adb->entrylocks[addr_bucket]);
1282				addr_bucket = entry->lock_bucket;
1283				LOCK(&adb->entrylocks[addr_bucket]);
1284			}
1285
1286			result = dec_entry_refcnt(adb, overmem, entry,
1287						  ISC_FALSE);
1288		}
1289
1290		/*
1291		 * Free the namehook
1292		 */
1293		namehook->entry = NULL;
1294		ISC_LIST_UNLINK(*namehooks, namehook, plink);
1295		free_adbnamehook(adb, &namehook);
1296
1297		namehook = ISC_LIST_HEAD(*namehooks);
1298	}
1299
1300	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1301		UNLOCK(&adb->entrylocks[addr_bucket]);
1302	return (result);
1303}
1304
1305static void
1306clean_target(dns_adb_t *adb, dns_name_t *target) {
1307	if (dns_name_countlabels(target) > 0) {
1308		dns_name_free(target, adb->mctx);
1309		dns_name_init(target, NULL);
1310	}
1311}
1312
1313static isc_result_t
1314set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
1315	   dns_rdataset_t *rdataset, dns_name_t *target)
1316{
1317	isc_result_t result;
1318	dns_namereln_t namereln;
1319	unsigned int nlabels;
1320	int order;
1321	dns_rdata_t rdata = DNS_RDATA_INIT;
1322	dns_fixedname_t fixed1, fixed2;
1323	dns_name_t *prefix, *new_target;
1324
1325	REQUIRE(dns_name_countlabels(target) == 0);
1326
1327	if (rdataset->type == dns_rdatatype_cname) {
1328		dns_rdata_cname_t cname;
1329
1330		/*
1331		 * Copy the CNAME's target into the target name.
1332		 */
1333		result = dns_rdataset_first(rdataset);
1334		if (result != ISC_R_SUCCESS)
1335			return (result);
1336		dns_rdataset_current(rdataset, &rdata);
1337		result = dns_rdata_tostruct(&rdata, &cname, NULL);
1338		if (result != ISC_R_SUCCESS)
1339			return (result);
1340		result = dns_name_dup(&cname.cname, adb->mctx, target);
1341		dns_rdata_freestruct(&cname);
1342		if (result != ISC_R_SUCCESS)
1343			return (result);
1344	} else {
1345		dns_rdata_dname_t dname;
1346
1347		INSIST(rdataset->type == dns_rdatatype_dname);
1348		namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
1349		INSIST(namereln == dns_namereln_subdomain);
1350		/*
1351		 * Get the target name of the DNAME.
1352		 */
1353		result = dns_rdataset_first(rdataset);
1354		if (result != ISC_R_SUCCESS)
1355			return (result);
1356		dns_rdataset_current(rdataset, &rdata);
1357		result = dns_rdata_tostruct(&rdata, &dname, NULL);
1358		if (result != ISC_R_SUCCESS)
1359			return (result);
1360		/*
1361		 * Construct the new target name.
1362		 */
1363		dns_fixedname_init(&fixed1);
1364		prefix = dns_fixedname_name(&fixed1);
1365		dns_fixedname_init(&fixed2);
1366		new_target = dns_fixedname_name(&fixed2);
1367		dns_name_split(name, nlabels, prefix, NULL);
1368		result = dns_name_concatenate(prefix, &dname.dname, new_target,
1369					      NULL);
1370		dns_rdata_freestruct(&dname);
1371		if (result != ISC_R_SUCCESS)
1372			return (result);
1373		result = dns_name_dup(new_target, adb->mctx, target);
1374		if (result != ISC_R_SUCCESS)
1375			return (result);
1376	}
1377
1378	return (ISC_R_SUCCESS);
1379}
1380
1381/*
1382 * Assumes nothing is locked, since this is called by the client.
1383 */
1384static void
1385event_free(isc_event_t *event) {
1386	dns_adbfind_t *find;
1387
1388	INSIST(event != NULL);
1389	find = event->ev_destroy_arg;
1390	INSIST(DNS_ADBFIND_VALID(find));
1391
1392	LOCK(&find->lock);
1393	find->flags |= FIND_EVENT_FREED;
1394	event->ev_destroy_arg = NULL;
1395	UNLOCK(&find->lock);
1396}
1397
1398/*
1399 * Assumes the name bucket is locked.
1400 */
1401static void
1402clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
1403		    unsigned int addrs)
1404{
1405	isc_event_t *ev;
1406	isc_task_t *task;
1407	dns_adbfind_t *find;
1408	dns_adbfind_t *next_find;
1409	isc_boolean_t process;
1410	unsigned int wanted, notify;
1411
1412	DP(ENTER_LEVEL,
1413	   "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1414	   name, evtype, addrs);
1415
1416	find = ISC_LIST_HEAD(name->finds);
1417	while (find != NULL) {
1418		LOCK(&find->lock);
1419		next_find = ISC_LIST_NEXT(find, plink);
1420
1421		process = ISC_FALSE;
1422		wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1423		notify = wanted & addrs;
1424
1425		switch (evtype) {
1426		case DNS_EVENT_ADBMOREADDRESSES:
1427			DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1428			if ((notify) != 0) {
1429				find->flags &= ~addrs;
1430				process = ISC_TRUE;
1431			}
1432			break;
1433		case DNS_EVENT_ADBNOMOREADDRESSES:
1434			DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1435			find->flags &= ~addrs;
1436			wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1437			if (wanted == 0)
1438				process = ISC_TRUE;
1439			break;
1440		default:
1441			find->flags &= ~addrs;
1442			process = ISC_TRUE;
1443		}
1444
1445		if (process) {
1446			DP(DEF_LEVEL, "cfan: processing find %p", find);
1447			/*
1448			 * Unlink the find from the name, letting the caller
1449			 * call dns_adb_destroyfind() on it to clean it up
1450			 * later.
1451			 */
1452			ISC_LIST_UNLINK(name->finds, find, plink);
1453			find->adbname = NULL;
1454			find->name_bucket = DNS_ADB_INVALIDBUCKET;
1455
1456			INSIST(!FIND_EVENTSENT(find));
1457
1458			ev = &find->event;
1459			task = ev->ev_sender;
1460			ev->ev_sender = find;
1461			find->result_v4 = find_err_map[name->fetch_err];
1462			find->result_v6 = find_err_map[name->fetch6_err];
1463			ev->ev_type = evtype;
1464			ev->ev_destroy = event_free;
1465			ev->ev_destroy_arg = find;
1466
1467			DP(DEF_LEVEL,
1468			   "sending event %p to task %p for find %p",
1469			   ev, task, find);
1470
1471			isc_task_sendanddetach(&task, (isc_event_t **)&ev);
1472		} else {
1473			DP(DEF_LEVEL, "cfan: skipping find %p", find);
1474		}
1475
1476		UNLOCK(&find->lock);
1477		find = next_find;
1478	}
1479
1480	DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
1481}
1482
1483static inline void
1484check_exit(dns_adb_t *adb) {
1485	isc_event_t *event;
1486	/*
1487	 * The caller must be holding the adb lock.
1488	 */
1489	if (adb->shutting_down) {
1490		/*
1491		 * If there aren't any external references either, we're
1492		 * done.  Send the control event to initiate shutdown.
1493		 */
1494		INSIST(!adb->cevent_sent);      /* Sanity check. */
1495		event = &adb->cevent;
1496		isc_task_send(adb->task, &event);
1497		adb->cevent_sent = ISC_TRUE;
1498	}
1499}
1500
1501static inline isc_boolean_t
1502dec_adb_irefcnt(dns_adb_t *adb) {
1503	isc_event_t *event;
1504	isc_task_t *etask;
1505	isc_boolean_t result = ISC_FALSE;
1506
1507	LOCK(&adb->reflock);
1508
1509	INSIST(adb->irefcnt > 0);
1510	adb->irefcnt--;
1511
1512	if (adb->irefcnt == 0) {
1513		event = ISC_LIST_HEAD(adb->whenshutdown);
1514		while (event != NULL) {
1515			ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
1516			etask = event->ev_sender;
1517			event->ev_sender = adb;
1518			isc_task_sendanddetach(&etask, &event);
1519			event = ISC_LIST_HEAD(adb->whenshutdown);
1520		}
1521	}
1522
1523	if (adb->irefcnt == 0 && adb->erefcnt == 0)
1524		result = ISC_TRUE;
1525	UNLOCK(&adb->reflock);
1526	return (result);
1527}
1528
1529static inline void
1530inc_adb_irefcnt(dns_adb_t *adb) {
1531	LOCK(&adb->reflock);
1532	adb->irefcnt++;
1533	UNLOCK(&adb->reflock);
1534}
1535
1536static inline void
1537inc_adb_erefcnt(dns_adb_t *adb) {
1538	LOCK(&adb->reflock);
1539	adb->erefcnt++;
1540	UNLOCK(&adb->reflock);
1541}
1542
1543static inline void
1544inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
1545	int bucket;
1546
1547	bucket = entry->lock_bucket;
1548
1549	if (lock)
1550		LOCK(&adb->entrylocks[bucket]);
1551
1552	entry->refcnt++;
1553
1554	if (lock)
1555		UNLOCK(&adb->entrylocks[bucket]);
1556}
1557
1558static inline isc_boolean_t
1559dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
1560		 isc_boolean_t lock)
1561{
1562	int bucket;
1563	isc_boolean_t destroy_entry;
1564	isc_boolean_t result = ISC_FALSE;
1565
1566	bucket = entry->lock_bucket;
1567
1568	if (lock)
1569		LOCK(&adb->entrylocks[bucket]);
1570
1571	INSIST(entry->refcnt > 0);
1572	entry->refcnt--;
1573
1574	destroy_entry = ISC_FALSE;
1575	if (entry->refcnt == 0 &&
1576	    (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
1577	     (entry->flags & ENTRY_IS_DEAD) != 0)) {
1578		destroy_entry = ISC_TRUE;
1579		result = unlink_entry(adb, entry);
1580	}
1581
1582	if (lock)
1583		UNLOCK(&adb->entrylocks[bucket]);
1584
1585	if (!destroy_entry)
1586		return (result);
1587
1588	entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1589
1590	free_adbentry(adb, &entry);
1591	if (result)
1592		result = dec_adb_irefcnt(adb);
1593
1594	return (result);
1595}
1596
1597static inline dns_adbname_t *
1598new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
1599	dns_adbname_t *name;
1600
1601	name = isc_mempool_get(adb->nmp);
1602	if (name == NULL)
1603		return (NULL);
1604
1605	dns_name_init(&name->name, NULL);
1606	if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
1607		isc_mempool_put(adb->nmp, name);
1608		return (NULL);
1609	}
1610	dns_name_init(&name->target, NULL);
1611	name->magic = DNS_ADBNAME_MAGIC;
1612	name->adb = adb;
1613	name->partial_result = 0;
1614	name->flags = 0;
1615	name->expire_v4 = INT_MAX;
1616	name->expire_v6 = INT_MAX;
1617	name->expire_target = INT_MAX;
1618	name->chains = 0;
1619	name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1620	ISC_LIST_INIT(name->v4);
1621	ISC_LIST_INIT(name->v6);
1622	name->fetch_a = NULL;
1623	name->fetch_aaaa = NULL;
1624	name->fetch_err = FIND_ERR_UNEXPECTED;
1625	name->fetch6_err = FIND_ERR_UNEXPECTED;
1626	ISC_LIST_INIT(name->finds);
1627	ISC_LINK_INIT(name, plink);
1628
1629	LOCK(&adb->namescntlock);
1630	adb->namescnt++;
1631	if (!adb->grownames_sent && adb->excl != NULL &&
1632	    adb->namescnt > (adb->nnames * 8))
1633	{
1634		isc_event_t *event = &adb->grownames;
1635		inc_adb_irefcnt(adb);
1636		isc_task_send(adb->excl, &event);
1637		adb->grownames_sent = ISC_TRUE;
1638	}
1639	UNLOCK(&adb->namescntlock);
1640
1641	return (name);
1642}
1643
1644static inline void
1645free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
1646	dns_adbname_t *n;
1647
1648	INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
1649	n = *name;
1650	*name = NULL;
1651
1652	INSIST(!NAME_HAS_V4(n));
1653	INSIST(!NAME_HAS_V6(n));
1654	INSIST(!NAME_FETCH(n));
1655	INSIST(ISC_LIST_EMPTY(n->finds));
1656	INSIST(!ISC_LINK_LINKED(n, plink));
1657	INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
1658	INSIST(n->adb == adb);
1659
1660	n->magic = 0;
1661	dns_name_free(&n->name, adb->mctx);
1662
1663	isc_mempool_put(adb->nmp, n);
1664	LOCK(&adb->namescntlock);
1665	adb->namescnt--;
1666	UNLOCK(&adb->namescntlock);
1667}
1668
1669static inline dns_adbnamehook_t *
1670new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
1671	dns_adbnamehook_t *nh;
1672
1673	nh = isc_mempool_get(adb->nhmp);
1674	if (nh == NULL)
1675		return (NULL);
1676
1677	nh->magic = DNS_ADBNAMEHOOK_MAGIC;
1678	nh->entry = entry;
1679	ISC_LINK_INIT(nh, plink);
1680
1681	return (nh);
1682}
1683
1684static inline void
1685free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
1686	dns_adbnamehook_t *nh;
1687
1688	INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
1689	nh = *namehook;
1690	*namehook = NULL;
1691
1692	INSIST(nh->entry == NULL);
1693	INSIST(!ISC_LINK_LINKED(nh, plink));
1694
1695	nh->magic = 0;
1696	isc_mempool_put(adb->nhmp, nh);
1697}
1698
1699static inline dns_adblameinfo_t *
1700new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
1701	dns_adblameinfo_t *li;
1702
1703	li = isc_mempool_get(adb->limp);
1704	if (li == NULL)
1705		return (NULL);
1706
1707	dns_name_init(&li->qname, NULL);
1708	if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
1709		isc_mempool_put(adb->limp, li);
1710		return (NULL);
1711	}
1712	li->magic = DNS_ADBLAMEINFO_MAGIC;
1713	li->lame_timer = 0;
1714	li->qtype = qtype;
1715	ISC_LINK_INIT(li, plink);
1716
1717	return (li);
1718}
1719
1720static inline void
1721free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
1722	dns_adblameinfo_t *li;
1723
1724	INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
1725	li = *lameinfo;
1726	*lameinfo = NULL;
1727
1728	INSIST(!ISC_LINK_LINKED(li, plink));
1729
1730	dns_name_free(&li->qname, adb->mctx);
1731
1732	li->magic = 0;
1733
1734	isc_mempool_put(adb->limp, li);
1735}
1736
1737static inline dns_adbentry_t *
1738new_adbentry(dns_adb_t *adb) {
1739	dns_adbentry_t *e;
1740	isc_uint32_t r;
1741
1742	e = isc_mempool_get(adb->emp);
1743	if (e == NULL)
1744		return (NULL);
1745
1746	e->magic = DNS_ADBENTRY_MAGIC;
1747	e->lock_bucket = DNS_ADB_INVALIDBUCKET;
1748	e->refcnt = 0;
1749	e->flags = 0;
1750	isc_random_get(&r);
1751	e->srtt = (r & 0x1f) + 1;
1752	e->expires = 0;
1753	ISC_LIST_INIT(e->lameinfo);
1754	ISC_LINK_INIT(e, plink);
1755	LOCK(&adb->entriescntlock);
1756	adb->entriescnt++;
1757	if (!adb->growentries_sent && adb->growentries_sent &&
1758	    adb->entriescnt > (adb->nentries * 8))
1759	{
1760		isc_event_t *event = &adb->growentries;
1761		inc_adb_irefcnt(adb);
1762		isc_task_send(adb->task, &event);
1763		adb->growentries_sent = ISC_TRUE;
1764	}
1765	UNLOCK(&adb->entriescntlock);
1766
1767	return (e);
1768}
1769
1770static inline void
1771free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
1772	dns_adbentry_t *e;
1773	dns_adblameinfo_t *li;
1774
1775	INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
1776	e = *entry;
1777	*entry = NULL;
1778
1779	INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
1780	INSIST(e->refcnt == 0);
1781	INSIST(!ISC_LINK_LINKED(e, plink));
1782
1783	e->magic = 0;
1784
1785	li = ISC_LIST_HEAD(e->lameinfo);
1786	while (li != NULL) {
1787		ISC_LIST_UNLINK(e->lameinfo, li, plink);
1788		free_adblameinfo(adb, &li);
1789		li = ISC_LIST_HEAD(e->lameinfo);
1790	}
1791
1792	isc_mempool_put(adb->emp, e);
1793	LOCK(&adb->entriescntlock);
1794	adb->entriescnt--;
1795	UNLOCK(&adb->entriescntlock);
1796}
1797
1798static inline dns_adbfind_t *
1799new_adbfind(dns_adb_t *adb) {
1800	dns_adbfind_t *h;
1801	isc_result_t result;
1802
1803	h = isc_mempool_get(adb->ahmp);
1804	if (h == NULL)
1805		return (NULL);
1806
1807	/*
1808	 * Public members.
1809	 */
1810	h->magic = 0;
1811	h->adb = adb;
1812	h->partial_result = 0;
1813	h->options = 0;
1814	h->flags = 0;
1815	h->result_v4 = ISC_R_UNEXPECTED;
1816	h->result_v6 = ISC_R_UNEXPECTED;
1817	ISC_LINK_INIT(h, publink);
1818	ISC_LINK_INIT(h, plink);
1819	ISC_LIST_INIT(h->list);
1820	h->adbname = NULL;
1821	h->name_bucket = DNS_ADB_INVALIDBUCKET;
1822
1823	/*
1824	 * private members
1825	 */
1826	result = isc_mutex_init(&h->lock);
1827	if (result != ISC_R_SUCCESS) {
1828		isc_mempool_put(adb->ahmp, h);
1829		return (NULL);
1830	}
1831
1832	ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
1833		       NULL, NULL, h);
1834
1835	inc_adb_irefcnt(adb);
1836	h->magic = DNS_ADBFIND_MAGIC;
1837	return (h);
1838}
1839
1840static inline dns_adbfetch_t *
1841new_adbfetch(dns_adb_t *adb) {
1842	dns_adbfetch_t *f;
1843
1844	f = isc_mempool_get(adb->afmp);
1845	if (f == NULL)
1846		return (NULL);
1847
1848	f->magic = 0;
1849	f->fetch = NULL;
1850
1851	dns_rdataset_init(&f->rdataset);
1852
1853	f->magic = DNS_ADBFETCH_MAGIC;
1854
1855	return (f);
1856}
1857
1858static inline void
1859free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
1860	dns_adbfetch_t *f;
1861
1862	INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
1863	f = *fetch;
1864	*fetch = NULL;
1865
1866	f->magic = 0;
1867
1868	if (dns_rdataset_isassociated(&f->rdataset))
1869		dns_rdataset_disassociate(&f->rdataset);
1870
1871	isc_mempool_put(adb->afmp, f);
1872}
1873
1874static inline isc_boolean_t
1875free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
1876	dns_adbfind_t *find;
1877
1878	INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
1879	find = *findp;
1880	*findp = NULL;
1881
1882	INSIST(!FIND_HAS_ADDRS(find));
1883	INSIST(!ISC_LINK_LINKED(find, publink));
1884	INSIST(!ISC_LINK_LINKED(find, plink));
1885	INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
1886	INSIST(find->adbname == NULL);
1887
1888	find->magic = 0;
1889
1890	DESTROYLOCK(&find->lock);
1891	isc_mempool_put(adb->ahmp, find);
1892	return (dec_adb_irefcnt(adb));
1893}
1894
1895/*
1896 * Copy bits from the entry into the newly allocated addrinfo.  The entry
1897 * must be locked, and the reference count must be bumped up by one
1898 * if this function returns a valid pointer.
1899 */
1900static inline dns_adbaddrinfo_t *
1901new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
1902	dns_adbaddrinfo_t *ai;
1903
1904	ai = isc_mempool_get(adb->aimp);
1905	if (ai == NULL)
1906		return (NULL);
1907
1908	ai->magic = DNS_ADBADDRINFO_MAGIC;
1909	ai->sockaddr = entry->sockaddr;
1910	isc_sockaddr_setport(&ai->sockaddr, port);
1911	ai->srtt = entry->srtt;
1912	ai->flags = entry->flags;
1913	ai->entry = entry;
1914	ISC_LINK_INIT(ai, publink);
1915
1916	return (ai);
1917}
1918
1919static inline void
1920free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
1921	dns_adbaddrinfo_t *ai;
1922
1923	INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
1924	ai = *ainfo;
1925	*ainfo = NULL;
1926
1927	INSIST(ai->entry == NULL);
1928	INSIST(!ISC_LINK_LINKED(ai, publink));
1929
1930	ai->magic = 0;
1931
1932	isc_mempool_put(adb->aimp, ai);
1933}
1934
1935/*
1936 * Search for the name.  NOTE:  The bucket is kept locked on both
1937 * success and failure, so it must always be unlocked by the caller!
1938 *
1939 * On the first call to this function, *bucketp must be set to
1940 * DNS_ADB_INVALIDBUCKET.
1941 */
1942static inline dns_adbname_t *
1943find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
1944		   unsigned int options, int *bucketp)
1945{
1946	dns_adbname_t *adbname;
1947	int bucket;
1948
1949	bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
1950
1951	if (*bucketp == DNS_ADB_INVALIDBUCKET) {
1952		LOCK(&adb->namelocks[bucket]);
1953		*bucketp = bucket;
1954	} else if (*bucketp != bucket) {
1955		UNLOCK(&adb->namelocks[*bucketp]);
1956		LOCK(&adb->namelocks[bucket]);
1957		*bucketp = bucket;
1958	}
1959
1960	adbname = ISC_LIST_HEAD(adb->names[bucket]);
1961	while (adbname != NULL) {
1962		if (!NAME_DEAD(adbname)) {
1963			if (dns_name_equal(name, &adbname->name)
1964			    && GLUEHINT_OK(adbname, options)
1965			    && STARTATZONE_MATCHES(adbname, options))
1966				return (adbname);
1967		}
1968		adbname = ISC_LIST_NEXT(adbname, plink);
1969	}
1970
1971	return (NULL);
1972}
1973
1974/*
1975 * Search for the address.  NOTE:  The bucket is kept locked on both
1976 * success and failure, so it must always be unlocked by the caller.
1977 *
1978 * On the first call to this function, *bucketp must be set to
1979 * DNS_ADB_INVALIDBUCKET.  This will cause a lock to occur.  On
1980 * later calls (within the same "lock path") it can be left alone, so
1981 * if this function is called multiple times locking is only done if
1982 * the bucket changes.
1983 */
1984static inline dns_adbentry_t *
1985find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
1986	isc_stdtime_t now)
1987{
1988	dns_adbentry_t *entry, *entry_next;
1989	int bucket;
1990
1991	bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
1992
1993	if (*bucketp == DNS_ADB_INVALIDBUCKET) {
1994		LOCK(&adb->entrylocks[bucket]);
1995		*bucketp = bucket;
1996	} else if (*bucketp != bucket) {
1997		UNLOCK(&adb->entrylocks[*bucketp]);
1998		LOCK(&adb->entrylocks[bucket]);
1999		*bucketp = bucket;
2000	}
2001
2002	/* Search the list, while cleaning up expired entries. */
2003	for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
2004	     entry != NULL;
2005	     entry = entry_next) {
2006		entry_next = ISC_LIST_NEXT(entry, plink);
2007		(void)check_expire_entry(adb, &entry, now);
2008		if (entry != NULL &&
2009		    isc_sockaddr_equal(addr, &entry->sockaddr)) {
2010			ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
2011			ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
2012			return (entry);
2013		}
2014	}
2015
2016	return (NULL);
2017}
2018
2019/*
2020 * Entry bucket MUST be locked!
2021 */
2022static isc_boolean_t
2023entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
2024	      dns_rdatatype_t qtype, isc_stdtime_t now)
2025{
2026	dns_adblameinfo_t *li, *next_li;
2027	isc_boolean_t is_bad;
2028
2029	is_bad = ISC_FALSE;
2030
2031	li = ISC_LIST_HEAD(entry->lameinfo);
2032	if (li == NULL)
2033		return (ISC_FALSE);
2034	while (li != NULL) {
2035		next_li = ISC_LIST_NEXT(li, plink);
2036
2037		/*
2038		 * Has the entry expired?
2039		 */
2040		if (li->lame_timer < now) {
2041			ISC_LIST_UNLINK(entry->lameinfo, li, plink);
2042			free_adblameinfo(adb, &li);
2043		}
2044
2045		/*
2046		 * Order tests from least to most expensive.
2047		 *
2048		 * We do not break out of the main loop here as
2049		 * we use the loop for house keeping.
2050		 */
2051		if (li != NULL && !is_bad && li->qtype == qtype &&
2052		    dns_name_equal(qname, &li->qname))
2053			is_bad = ISC_TRUE;
2054
2055		li = next_li;
2056	}
2057
2058	return (is_bad);
2059}
2060
2061static void
2062copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
2063		    dns_rdatatype_t qtype, dns_adbname_t *name,
2064		    isc_stdtime_t now)
2065{
2066	dns_adbnamehook_t *namehook;
2067	dns_adbaddrinfo_t *addrinfo;
2068	dns_adbentry_t *entry;
2069	int bucket;
2070
2071	bucket = DNS_ADB_INVALIDBUCKET;
2072
2073	if (find->options & DNS_ADBFIND_INET) {
2074		namehook = ISC_LIST_HEAD(name->v4);
2075		while (namehook != NULL) {
2076			entry = namehook->entry;
2077			bucket = entry->lock_bucket;
2078			LOCK(&adb->entrylocks[bucket]);
2079
2080			if (!FIND_RETURNLAME(find)
2081			    && entry_is_lame(adb, entry, qname, qtype, now)) {
2082				find->options |= DNS_ADBFIND_LAMEPRUNED;
2083				goto nextv4;
2084			}
2085			addrinfo = new_adbaddrinfo(adb, entry, find->port);
2086			if (addrinfo == NULL) {
2087				find->partial_result |= DNS_ADBFIND_INET;
2088				goto out;
2089			}
2090			/*
2091			 * Found a valid entry.  Add it to the find's list.
2092			 */
2093			inc_entry_refcnt(adb, entry, ISC_FALSE);
2094			ISC_LIST_APPEND(find->list, addrinfo, publink);
2095			addrinfo = NULL;
2096		nextv4:
2097			UNLOCK(&adb->entrylocks[bucket]);
2098			bucket = DNS_ADB_INVALIDBUCKET;
2099			namehook = ISC_LIST_NEXT(namehook, plink);
2100		}
2101	}
2102
2103	if (find->options & DNS_ADBFIND_INET6) {
2104		namehook = ISC_LIST_HEAD(name->v6);
2105		while (namehook != NULL) {
2106			entry = namehook->entry;
2107			bucket = entry->lock_bucket;
2108			LOCK(&adb->entrylocks[bucket]);
2109
2110			if (!FIND_RETURNLAME(find)
2111			    && entry_is_lame(adb, entry, qname, qtype, now)) {
2112				find->options |= DNS_ADBFIND_LAMEPRUNED;
2113				goto nextv6;
2114			}
2115			addrinfo = new_adbaddrinfo(adb, entry, find->port);
2116			if (addrinfo == NULL) {
2117				find->partial_result |= DNS_ADBFIND_INET6;
2118				goto out;
2119			}
2120			/*
2121			 * Found a valid entry.  Add it to the find's list.
2122			 */
2123			inc_entry_refcnt(adb, entry, ISC_FALSE);
2124			ISC_LIST_APPEND(find->list, addrinfo, publink);
2125			addrinfo = NULL;
2126		nextv6:
2127			UNLOCK(&adb->entrylocks[bucket]);
2128			bucket = DNS_ADB_INVALIDBUCKET;
2129			namehook = ISC_LIST_NEXT(namehook, plink);
2130		}
2131	}
2132
2133 out:
2134	if (bucket != DNS_ADB_INVALIDBUCKET)
2135		UNLOCK(&adb->entrylocks[bucket]);
2136}
2137
2138static void
2139shutdown_task(isc_task_t *task, isc_event_t *ev) {
2140	dns_adb_t *adb;
2141
2142	UNUSED(task);
2143
2144	adb = ev->ev_arg;
2145	INSIST(DNS_ADB_VALID(adb));
2146
2147	isc_event_free(&ev);
2148	/*
2149	 * Wait for lock around check_exit() call to be released.
2150	 */
2151	LOCK(&adb->lock);
2152	UNLOCK(&adb->lock);
2153	destroy(adb);
2154}
2155
2156/*
2157 * Name bucket must be locked; adb may be locked; no other locks held.
2158 */
2159static isc_boolean_t
2160check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
2161	dns_adbname_t *name;
2162	isc_boolean_t result = ISC_FALSE;
2163
2164	INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
2165	name = *namep;
2166
2167	if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
2168		return (result);
2169	if (NAME_FETCH(name))
2170		return (result);
2171	if (!EXPIRE_OK(name->expire_v4, now))
2172		return (result);
2173	if (!EXPIRE_OK(name->expire_v6, now))
2174		return (result);
2175	if (!EXPIRE_OK(name->expire_target, now))
2176		return (result);
2177
2178	/*
2179	 * The name is empty.  Delete it.
2180	 */
2181	result = kill_name(&name, DNS_EVENT_ADBEXPIRED);
2182	*namep = NULL;
2183
2184	/*
2185	 * Our caller, or one of its callers, will be calling check_exit() at
2186	 * some point, so we don't need to do it here.
2187	 */
2188	return (result);
2189}
2190
2191/*%
2192 * Examine the tail entry of the LRU list to see if it expires or is stale
2193 * (unused for some period); if so, the name entry will be freed.  If the ADB
2194 * is in the overmem condition, the tail and the next to tail entries
2195 * will be unconditionally removed (unless they have an outstanding fetch).
2196 * We don't care about a race on 'overmem' at the risk of causing some
2197 * collateral damage or a small delay in starting cleanup, so we don't bother
2198 * to lock ADB (if it's not locked).
2199 *
2200 * Name bucket must be locked; adb may be locked; no other locks held.
2201 */
2202static void
2203check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2204	int victims, max_victims;
2205	dns_adbname_t *victim, *next_victim;
2206	isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
2207	int scans = 0;
2208
2209	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2210
2211	max_victims = overmem ? 2 : 1;
2212
2213	/*
2214	 * We limit the number of scanned entries to 10 (arbitrary choice)
2215	 * in order to avoid examining too many entries when there are many
2216	 * tail entries that have fetches (this should be rare, but could
2217	 * happen).
2218	 */
2219	victim = ISC_LIST_TAIL(adb->names[bucket]);
2220	for (victims = 0;
2221	     victim != NULL && victims < max_victims && scans < 10;
2222	     victim = next_victim) {
2223		INSIST(!NAME_DEAD(victim));
2224		scans++;
2225		next_victim = ISC_LIST_PREV(victim, plink);
2226		(void)check_expire_name(&victim, now);
2227		if (victim == NULL) {
2228			victims++;
2229			goto next;
2230		}
2231
2232		if (!NAME_FETCH(victim) &&
2233		    (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
2234			RUNTIME_CHECK(kill_name(&victim,
2235						DNS_EVENT_ADBCANCELED) ==
2236				      ISC_FALSE);
2237			victims++;
2238		}
2239
2240	next:
2241		if (!overmem)
2242			break;
2243	}
2244}
2245
2246/*
2247 * Entry bucket must be locked; adb may be locked; no other locks held.
2248 */
2249static isc_boolean_t
2250check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
2251{
2252	dns_adbentry_t *entry;
2253	isc_boolean_t result = ISC_FALSE;
2254
2255	INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
2256	entry = *entryp;
2257
2258	if (entry->refcnt != 0)
2259		return (result);
2260
2261	if (entry->expires == 0 || entry->expires > now)
2262		return (result);
2263
2264	/*
2265	 * The entry is not in use.  Delete it.
2266	 */
2267	DP(DEF_LEVEL, "killing entry %p", entry);
2268	INSIST(ISC_LINK_LINKED(entry, plink));
2269	result = unlink_entry(adb, entry);
2270	free_adbentry(adb, &entry);
2271	if (result)
2272		dec_adb_irefcnt(adb);
2273	*entryp = NULL;
2274	return (result);
2275}
2276
2277/*
2278 * ADB must be locked, and no other locks held.
2279 */
2280static isc_boolean_t
2281cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2282	dns_adbname_t *name;
2283	dns_adbname_t *next_name;
2284	isc_boolean_t result = ISC_FALSE;
2285
2286	DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
2287
2288	LOCK(&adb->namelocks[bucket]);
2289	if (adb->name_sd[bucket]) {
2290		UNLOCK(&adb->namelocks[bucket]);
2291		return (result);
2292	}
2293
2294	name = ISC_LIST_HEAD(adb->names[bucket]);
2295	while (name != NULL) {
2296		next_name = ISC_LIST_NEXT(name, plink);
2297		INSIST(result == ISC_FALSE);
2298		result = check_expire_namehooks(name, now);
2299		if (!result)
2300			result = check_expire_name(&name, now);
2301		name = next_name;
2302	}
2303	UNLOCK(&adb->namelocks[bucket]);
2304	return (result);
2305}
2306
2307/*
2308 * ADB must be locked, and no other locks held.
2309 */
2310static isc_boolean_t
2311cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
2312	dns_adbentry_t *entry, *next_entry;
2313	isc_boolean_t result = ISC_FALSE;
2314
2315	DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
2316
2317	LOCK(&adb->entrylocks[bucket]);
2318	entry = ISC_LIST_HEAD(adb->entries[bucket]);
2319	while (entry != NULL) {
2320		next_entry = ISC_LIST_NEXT(entry, plink);
2321		INSIST(result == ISC_FALSE);
2322		result = check_expire_entry(adb, &entry, now);
2323		entry = next_entry;
2324	}
2325	UNLOCK(&adb->entrylocks[bucket]);
2326	return (result);
2327}
2328
2329static void
2330destroy(dns_adb_t *adb) {
2331	adb->magic = 0;
2332
2333	isc_task_detach(&adb->task);
2334	isc_task_detach(&adb->excl);
2335
2336	isc_mempool_destroy(&adb->nmp);
2337	isc_mempool_destroy(&adb->nhmp);
2338	isc_mempool_destroy(&adb->limp);
2339	isc_mempool_destroy(&adb->emp);
2340	isc_mempool_destroy(&adb->ahmp);
2341	isc_mempool_destroy(&adb->aimp);
2342	isc_mempool_destroy(&adb->afmp);
2343
2344	DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2345	isc_mem_put(adb->mctx, adb->entries,
2346		    sizeof(*adb->entries) * adb->nentries);
2347	isc_mem_put(adb->mctx, adb->deadentries,
2348		    sizeof(*adb->deadentries) * adb->nentries);
2349	isc_mem_put(adb->mctx, adb->entrylocks,
2350		    sizeof(*adb->entrylocks) * adb->nentries);
2351	isc_mem_put(adb->mctx, adb->entry_sd,
2352		    sizeof(*adb->entry_sd) * adb->nentries);
2353	isc_mem_put(adb->mctx, adb->entry_refcnt,
2354		    sizeof(*adb->entry_refcnt) * adb->nentries);
2355
2356	DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2357	isc_mem_put(adb->mctx, adb->names,
2358		    sizeof(*adb->names) * adb->nnames);
2359	isc_mem_put(adb->mctx, adb->deadnames,
2360		    sizeof(*adb->deadnames) * adb->nnames);
2361	isc_mem_put(adb->mctx, adb->namelocks,
2362		    sizeof(*adb->namelocks) * adb->nnames);
2363	isc_mem_put(adb->mctx, adb->name_sd,
2364		    sizeof(*adb->name_sd) * adb->nnames);
2365	isc_mem_put(adb->mctx, adb->name_refcnt,
2366		    sizeof(*adb->name_refcnt) * adb->nnames);
2367
2368	DESTROYLOCK(&adb->reflock);
2369	DESTROYLOCK(&adb->lock);
2370	DESTROYLOCK(&adb->mplock);
2371	DESTROYLOCK(&adb->overmemlock);
2372	DESTROYLOCK(&adb->entriescntlock);
2373	DESTROYLOCK(&adb->namescntlock);
2374
2375	isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2376}
2377
2378
2379/*
2380 * Public functions.
2381 */
2382
2383isc_result_t
2384dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
2385	       isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
2386{
2387	dns_adb_t *adb;
2388	isc_result_t result;
2389	unsigned int i;
2390
2391	REQUIRE(mem != NULL);
2392	REQUIRE(view != NULL);
2393	REQUIRE(timermgr != NULL); /* this is actually unused */
2394	REQUIRE(taskmgr != NULL);
2395	REQUIRE(newadb != NULL && *newadb == NULL);
2396
2397	UNUSED(timermgr);
2398
2399	adb = isc_mem_get(mem, sizeof(dns_adb_t));
2400	if (adb == NULL)
2401		return (ISC_R_NOMEMORY);
2402
2403	/*
2404	 * Initialize things here that cannot fail, and especially things
2405	 * that must be NULL for the error return to work properly.
2406	 */
2407	adb->magic = 0;
2408	adb->erefcnt = 1;
2409	adb->irefcnt = 0;
2410	adb->nmp = NULL;
2411	adb->nhmp = NULL;
2412	adb->limp = NULL;
2413	adb->emp = NULL;
2414	adb->ahmp = NULL;
2415	adb->aimp = NULL;
2416	adb->afmp = NULL;
2417	adb->task = NULL;
2418	adb->excl = NULL;
2419	adb->mctx = NULL;
2420	adb->view = view;
2421	adb->taskmgr = taskmgr;
2422	adb->next_cleanbucket = 0;
2423	ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
2424		       DNS_EVENT_ADBCONTROL, shutdown_task, adb,
2425		       adb, NULL, NULL);
2426	adb->cevent_sent = ISC_FALSE;
2427	adb->shutting_down = ISC_FALSE;
2428	ISC_LIST_INIT(adb->whenshutdown);
2429
2430	adb->nentries = nbuckets[0];
2431	adb->entriescnt = 0;
2432	adb->entries = NULL;
2433	adb->deadentries = NULL;
2434	adb->entry_sd = NULL;
2435	adb->entry_refcnt = NULL;
2436	adb->entrylocks = NULL;
2437	ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
2438		       DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
2439		       adb, NULL, NULL);
2440	adb->growentries_sent = ISC_FALSE;
2441
2442	adb->nnames = nbuckets[0];
2443	adb->namescnt = 0;
2444	adb->names = NULL;
2445	adb->deadnames = NULL;
2446	adb->name_sd = NULL;
2447	adb->name_refcnt = NULL;
2448	adb->namelocks = NULL;
2449	ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
2450		       DNS_EVENT_ADBGROWNAMES, grow_names, adb,
2451		       adb, NULL, NULL);
2452	adb->grownames_sent = ISC_FALSE;
2453
2454	result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
2455	if (result != ISC_R_SUCCESS) {
2456		DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, "
2457				 "intializing table sizes to %u\n",
2458				 nbuckets[11]);
2459		adb->nentries = nbuckets[11];
2460		adb->nnames= nbuckets[11];
2461
2462	}
2463
2464	isc_mem_attach(mem, &adb->mctx);
2465
2466	result = isc_mutex_init(&adb->lock);
2467	if (result != ISC_R_SUCCESS)
2468		goto fail0b;
2469
2470	result = isc_mutex_init(&adb->mplock);
2471	if (result != ISC_R_SUCCESS)
2472		goto fail0c;
2473
2474	result = isc_mutex_init(&adb->reflock);
2475	if (result != ISC_R_SUCCESS)
2476		goto fail0d;
2477
2478	result = isc_mutex_init(&adb->overmemlock);
2479	if (result != ISC_R_SUCCESS)
2480		goto fail0e;
2481
2482	result = isc_mutex_init(&adb->entriescntlock);
2483	if (result != ISC_R_SUCCESS)
2484		goto fail0f;
2485
2486	result = isc_mutex_init(&adb->namescntlock);
2487	if (result != ISC_R_SUCCESS)
2488		goto fail0g;
2489
2490#define ALLOCENTRY(adb, el) \
2491	do { \
2492		(adb)->el = isc_mem_get((adb)->mctx, \
2493				     sizeof(*(adb)->el) * (adb)->nentries); \
2494		if ((adb)->el == NULL) { \
2495			result = ISC_R_NOMEMORY; \
2496			goto fail1; \
2497		}\
2498	} while (0)
2499	ALLOCENTRY(adb, entries);
2500	ALLOCENTRY(adb, deadentries);
2501	ALLOCENTRY(adb, entrylocks);
2502	ALLOCENTRY(adb, entry_sd);
2503	ALLOCENTRY(adb, entry_refcnt);
2504#undef ALLOCENTRY
2505
2506#define ALLOCNAME(adb, el) \
2507	do { \
2508		(adb)->el = isc_mem_get((adb)->mctx, \
2509				     sizeof(*(adb)->el) * (adb)->nnames); \
2510		if ((adb)->el == NULL) { \
2511			result = ISC_R_NOMEMORY; \
2512			goto fail1; \
2513		}\
2514	} while (0)
2515	ALLOCNAME(adb, names);
2516	ALLOCNAME(adb, deadnames);
2517	ALLOCNAME(adb, namelocks);
2518	ALLOCNAME(adb, name_sd);
2519	ALLOCNAME(adb, name_refcnt);
2520#undef ALLOCNAME
2521
2522	/*
2523	 * Initialize the bucket locks for names and elements.
2524	 * May as well initialize the list heads, too.
2525	 */
2526	result = isc_mutexblock_init(adb->namelocks, adb->nnames);
2527	if (result != ISC_R_SUCCESS)
2528		goto fail1;
2529	for (i = 0; i < adb->nnames; i++) {
2530		ISC_LIST_INIT(adb->names[i]);
2531		ISC_LIST_INIT(adb->deadnames[i]);
2532		adb->name_sd[i] = ISC_FALSE;
2533		adb->name_refcnt[i] = 0;
2534		adb->irefcnt++;
2535	}
2536	for (i = 0; i < adb->nentries; i++) {
2537		ISC_LIST_INIT(adb->entries[i]);
2538		ISC_LIST_INIT(adb->deadentries[i]);
2539		adb->entry_sd[i] = ISC_FALSE;
2540		adb->entry_refcnt[i] = 0;
2541		adb->irefcnt++;
2542	}
2543	result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
2544	if (result != ISC_R_SUCCESS)
2545		goto fail2;
2546
2547	/*
2548	 * Memory pools
2549	 */
2550#define MPINIT(t, p, n) do { \
2551	result = isc_mempool_create(mem, sizeof(t), &(p)); \
2552	if (result != ISC_R_SUCCESS) \
2553		goto fail3; \
2554	isc_mempool_setfreemax((p), FREE_ITEMS); \
2555	isc_mempool_setfillcount((p), FILL_COUNT); \
2556	isc_mempool_setname((p), n); \
2557	isc_mempool_associatelock((p), &adb->mplock); \
2558} while (0)
2559
2560	MPINIT(dns_adbname_t, adb->nmp, "adbname");
2561	MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
2562	MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
2563	MPINIT(dns_adbentry_t, adb->emp, "adbentry");
2564	MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
2565	MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
2566	MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
2567
2568#undef MPINIT
2569
2570	/*
2571	 * Allocate an internal task.
2572	 */
2573	result = isc_task_create(adb->taskmgr, 0, &adb->task);
2574	if (result != ISC_R_SUCCESS)
2575		goto fail3;
2576
2577	isc_task_setname(adb->task, "ADB", adb);
2578
2579	/*
2580	 * Normal return.
2581	 */
2582	adb->magic = DNS_ADB_MAGIC;
2583	*newadb = adb;
2584	return (ISC_R_SUCCESS);
2585
2586 fail3:
2587	if (adb->task != NULL)
2588		isc_task_detach(&adb->task);
2589
2590	/* clean up entrylocks */
2591	DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
2592
2593 fail2: /* clean up namelocks */
2594	DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
2595
2596 fail1: /* clean up only allocated memory */
2597	if (adb->entries != NULL)
2598		isc_mem_put(adb->mctx, adb->entries,
2599			    sizeof(*adb->entries) * adb->nentries);
2600	if (adb->deadentries != NULL)
2601		isc_mem_put(adb->mctx, adb->deadentries,
2602			    sizeof(*adb->deadentries) * adb->nentries);
2603	if (adb->entrylocks != NULL)
2604		isc_mem_put(adb->mctx, adb->entrylocks,
2605			    sizeof(*adb->entrylocks) * adb->nentries);
2606	if (adb->entry_sd != NULL)
2607		isc_mem_put(adb->mctx, adb->entry_sd,
2608			    sizeof(*adb->entry_sd) * adb->nentries);
2609	if (adb->entry_refcnt != NULL)
2610		isc_mem_put(adb->mctx, adb->entry_refcnt,
2611			    sizeof(*adb->entry_refcnt) * adb->nentries);
2612	if (adb->names != NULL)
2613		isc_mem_put(adb->mctx, adb->names,
2614			    sizeof(*adb->names) * adb->nnames);
2615	if (adb->deadnames != NULL)
2616		isc_mem_put(adb->mctx, adb->deadnames,
2617			    sizeof(*adb->deadnames) * adb->nnames);
2618	if (adb->namelocks != NULL)
2619		isc_mem_put(adb->mctx, adb->namelocks,
2620			    sizeof(*adb->namelocks) * adb->nnames);
2621	if (adb->name_sd != NULL)
2622		isc_mem_put(adb->mctx, adb->name_sd,
2623			    sizeof(*adb->name_sd) * adb->nnames);
2624	if (adb->name_refcnt != NULL)
2625		isc_mem_put(adb->mctx, adb->name_refcnt,
2626			    sizeof(*adb->name_refcnt) * adb->nnames);
2627	if (adb->nmp != NULL)
2628		isc_mempool_destroy(&adb->nmp);
2629	if (adb->nhmp != NULL)
2630		isc_mempool_destroy(&adb->nhmp);
2631	if (adb->limp != NULL)
2632		isc_mempool_destroy(&adb->limp);
2633	if (adb->emp != NULL)
2634		isc_mempool_destroy(&adb->emp);
2635	if (adb->ahmp != NULL)
2636		isc_mempool_destroy(&adb->ahmp);
2637	if (adb->aimp != NULL)
2638		isc_mempool_destroy(&adb->aimp);
2639	if (adb->afmp != NULL)
2640		isc_mempool_destroy(&adb->afmp);
2641
2642	DESTROYLOCK(&adb->namescntlock);
2643 fail0g:
2644	DESTROYLOCK(&adb->entriescntlock);
2645 fail0f:
2646	DESTROYLOCK(&adb->overmemlock);
2647 fail0e:
2648	DESTROYLOCK(&adb->reflock);
2649 fail0d:
2650	DESTROYLOCK(&adb->mplock);
2651 fail0c:
2652	DESTROYLOCK(&adb->lock);
2653 fail0b:
2654	isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
2655
2656	return (result);
2657}
2658
2659void
2660dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
2661
2662	REQUIRE(DNS_ADB_VALID(adb));
2663	REQUIRE(adbx != NULL && *adbx == NULL);
2664
2665	inc_adb_erefcnt(adb);
2666	*adbx = adb;
2667}
2668
2669void
2670dns_adb_detach(dns_adb_t **adbx) {
2671	dns_adb_t *adb;
2672	isc_boolean_t need_exit_check;
2673
2674	REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
2675
2676	adb = *adbx;
2677	*adbx = NULL;
2678
2679	INSIST(adb->erefcnt > 0);
2680
2681	LOCK(&adb->reflock);
2682	adb->erefcnt--;
2683	need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
2684	UNLOCK(&adb->reflock);
2685
2686	if (need_exit_check) {
2687		LOCK(&adb->lock);
2688		INSIST(adb->shutting_down);
2689		check_exit(adb);
2690		UNLOCK(&adb->lock);
2691	}
2692}
2693
2694void
2695dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
2696	isc_task_t *clone;
2697	isc_event_t *event;
2698	isc_boolean_t zeroirefcnt = ISC_FALSE;
2699
2700	/*
2701	 * Send '*eventp' to 'task' when 'adb' has shutdown.
2702	 */
2703
2704	REQUIRE(DNS_ADB_VALID(adb));
2705	REQUIRE(eventp != NULL);
2706
2707	event = *eventp;
2708	*eventp = NULL;
2709
2710	LOCK(&adb->lock);
2711
2712	LOCK(&adb->reflock);
2713	zeroirefcnt = ISC_TF(adb->irefcnt == 0);
2714
2715	if (adb->shutting_down && zeroirefcnt &&
2716	    isc_mempool_getallocated(adb->ahmp) == 0) {
2717		/*
2718		 * We're already shutdown.  Send the event.
2719		 */
2720		event->ev_sender = adb;
2721		isc_task_send(task, &event);
2722	} else {
2723		clone = NULL;
2724		isc_task_attach(task, &clone);
2725		event->ev_sender = clone;
2726		ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
2727	}
2728
2729	UNLOCK(&adb->reflock);
2730	UNLOCK(&adb->lock);
2731}
2732
2733void
2734dns_adb_shutdown(dns_adb_t *adb) {
2735	isc_boolean_t need_check_exit;
2736
2737	/*
2738	 * Shutdown 'adb'.
2739	 */
2740
2741	LOCK(&adb->lock);
2742
2743	if (!adb->shutting_down) {
2744		adb->shutting_down = ISC_TRUE;
2745		isc_mem_setwater(adb->mctx, water, adb, 0, 0);
2746		need_check_exit = shutdown_names(adb);
2747		if (!need_check_exit)
2748			need_check_exit = shutdown_entries(adb);
2749		if (need_check_exit)
2750			check_exit(adb);
2751	}
2752
2753	UNLOCK(&adb->lock);
2754}
2755
2756isc_result_t
2757dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
2758		   void *arg, dns_name_t *name, dns_name_t *qname,
2759		   dns_rdatatype_t qtype, unsigned int options,
2760		   isc_stdtime_t now, dns_name_t *target,
2761		   in_port_t port, dns_adbfind_t **findp)
2762{
2763	dns_adbfind_t *find;
2764	dns_adbname_t *adbname;
2765	int bucket;
2766	isc_boolean_t want_event, start_at_zone, alias, have_address;
2767	isc_result_t result;
2768	unsigned int wanted_addresses;
2769	unsigned int wanted_fetches;
2770	unsigned int query_pending;
2771
2772	REQUIRE(DNS_ADB_VALID(adb));
2773	if (task != NULL) {
2774		REQUIRE(action != NULL);
2775	}
2776	REQUIRE(name != NULL);
2777	REQUIRE(qname != NULL);
2778	REQUIRE(findp != NULL && *findp == NULL);
2779	REQUIRE(target == NULL || dns_name_hasbuffer(target));
2780
2781	REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
2782
2783	result = ISC_R_UNEXPECTED;
2784	POST(result);
2785	wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
2786	wanted_fetches = 0;
2787	query_pending = 0;
2788	want_event = ISC_FALSE;
2789	start_at_zone = ISC_FALSE;
2790	alias = ISC_FALSE;
2791
2792	if (now == 0)
2793		isc_stdtime_get(&now);
2794
2795	/*
2796	 * XXXMLG  Move this comment somewhere else!
2797	 *
2798	 * Look up the name in our internal database.
2799	 *
2800	 * Possibilities:  Note that these are not always exclusive.
2801	 *
2802	 *      No name found.  In this case, allocate a new name header and
2803	 *      an initial namehook or two.  If any of these allocations
2804	 *      fail, clean up and return ISC_R_NOMEMORY.
2805	 *
2806	 *      Name found, valid addresses present.  Allocate one addrinfo
2807	 *      structure for each found and append it to the linked list
2808	 *      of addresses for this header.
2809	 *
2810	 *      Name found, queries pending.  In this case, if a task was
2811	 *      passed in, allocate a job id, attach it to the name's job
2812	 *      list and remember to tell the caller that there will be
2813	 *      more info coming later.
2814	 */
2815
2816	find = new_adbfind(adb);
2817	if (find == NULL)
2818		return (ISC_R_NOMEMORY);
2819
2820	find->port = port;
2821
2822	/*
2823	 * Remember what types of addresses we are interested in.
2824	 */
2825	find->options = options;
2826	find->flags |= wanted_addresses;
2827	if (FIND_WANTEVENT(find)) {
2828		REQUIRE(task != NULL);
2829	}
2830
2831	/*
2832	 * Try to see if we know anything about this name at all.
2833	 */
2834	bucket = DNS_ADB_INVALIDBUCKET;
2835	adbname = find_name_and_lock(adb, name, find->options, &bucket);
2836	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
2837	if (adb->name_sd[bucket]) {
2838		DP(DEF_LEVEL,
2839		   "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
2840		RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2841		result = ISC_R_SHUTTINGDOWN;
2842		goto out;
2843	}
2844
2845	/*
2846	 * Nothing found.  Allocate a new adbname structure for this name.
2847	 */
2848	if (adbname == NULL) {
2849		/*
2850		 * See if there is any stale name at the end of list, and purge
2851		 * it if so.
2852		 */
2853		check_stale_name(adb, bucket, now);
2854
2855		adbname = new_adbname(adb, name);
2856		if (adbname == NULL) {
2857			RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
2858			result = ISC_R_NOMEMORY;
2859			goto out;
2860		}
2861		link_name(adb, bucket, adbname);
2862		if (FIND_HINTOK(find))
2863			adbname->flags |= NAME_HINT_OK;
2864		if (FIND_GLUEOK(find))
2865			adbname->flags |= NAME_GLUE_OK;
2866		if (FIND_STARTATZONE(find))
2867			adbname->flags |= NAME_STARTATZONE;
2868	} else {
2869		/* Move this name forward in the LRU list */
2870		ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
2871		ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
2872	}
2873	adbname->last_used = now;
2874
2875	/*
2876	 * Expire old entries, etc.
2877	 */
2878	RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
2879
2880	/*
2881	 * Do we know that the name is an alias?
2882	 */
2883	if (!EXPIRE_OK(adbname->expire_target, now)) {
2884		/*
2885		 * Yes, it is.
2886		 */
2887		DP(DEF_LEVEL,
2888		   "dns_adb_createfind: name %p is an alias (cached)",
2889		   adbname);
2890		alias = ISC_TRUE;
2891		goto post_copy;
2892	}
2893
2894	/*
2895	 * Try to populate the name from the database and/or
2896	 * start fetches.  First try looking for an A record
2897	 * in the database.
2898	 */
2899	if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
2900	    && WANT_INET(wanted_addresses)) {
2901		result = dbfind_name(adbname, now, dns_rdatatype_a);
2902		if (result == ISC_R_SUCCESS) {
2903			DP(DEF_LEVEL,
2904			   "dns_adb_createfind: found A for name %p in db",
2905			   adbname);
2906			goto v6;
2907		}
2908
2909		/*
2910		 * Did we get a CNAME or DNAME?
2911		 */
2912		if (result == DNS_R_ALIAS) {
2913			DP(DEF_LEVEL,
2914			   "dns_adb_createfind: name %p is an alias",
2915			   adbname);
2916			alias = ISC_TRUE;
2917			goto post_copy;
2918		}
2919
2920		/*
2921		 * If the name doesn't exist at all, don't bother with
2922		 * v6 queries; they won't work.
2923		 *
2924		 * If the name does exist but we didn't get our data, go
2925		 * ahead and try AAAA.
2926		 *
2927		 * If the result is neither of these, try a fetch for A.
2928		 */
2929		if (NXDOMAIN_RESULT(result))
2930			goto fetch;
2931		else if (NXRRSET_RESULT(result))
2932			goto v6;
2933
2934		if (!NAME_FETCH_V4(adbname))
2935			wanted_fetches |= DNS_ADBFIND_INET;
2936	}
2937
2938 v6:
2939	if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
2940	    && WANT_INET6(wanted_addresses)) {
2941		result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
2942		if (result == ISC_R_SUCCESS) {
2943			DP(DEF_LEVEL,
2944			   "dns_adb_createfind: found AAAA for name %p",
2945			   adbname);
2946			goto fetch;
2947		}
2948
2949		/*
2950		 * Did we get a CNAME or DNAME?
2951		 */
2952		if (result == DNS_R_ALIAS) {
2953			DP(DEF_LEVEL,
2954			   "dns_adb_createfind: name %p is an alias",
2955			   adbname);
2956			alias = ISC_TRUE;
2957			goto post_copy;
2958		}
2959
2960		/*
2961		 * Listen to negative cache hints, and don't start
2962		 * another query.
2963		 */
2964		if (NCACHE_RESULT(result) || AUTH_NX(result))
2965			goto fetch;
2966
2967		if (!NAME_FETCH_V6(adbname))
2968			wanted_fetches |= DNS_ADBFIND_INET6;
2969	}
2970
2971 fetch:
2972	if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
2973	    (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
2974		have_address = ISC_TRUE;
2975	else
2976		have_address = ISC_FALSE;
2977	if (wanted_fetches != 0 &&
2978	    ! (FIND_AVOIDFETCHES(find) && have_address)) {
2979		/*
2980		 * We're missing at least one address family.  Either the
2981		 * caller hasn't instructed us to avoid fetches, or we don't
2982		 * know anything about any of the address families that would
2983		 * be acceptable so we have to launch fetches.
2984		 */
2985
2986		if (FIND_STARTATZONE(find))
2987			start_at_zone = ISC_TRUE;
2988
2989		/*
2990		 * Start V4.
2991		 */
2992		if (WANT_INET(wanted_fetches) &&
2993		    fetch_name(adbname, start_at_zone,
2994			       dns_rdatatype_a) == ISC_R_SUCCESS) {
2995			DP(DEF_LEVEL,
2996			   "dns_adb_createfind: started A fetch for name %p",
2997			   adbname);
2998		}
2999
3000		/*
3001		 * Start V6.
3002		 */
3003		if (WANT_INET6(wanted_fetches) &&
3004		    fetch_name(adbname, start_at_zone,
3005			       dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
3006			DP(DEF_LEVEL,
3007			   "dns_adb_createfind: "
3008			   "started AAAA fetch for name %p",
3009			   adbname);
3010		}
3011	}
3012
3013	/*
3014	 * Run through the name and copy out the bits we are
3015	 * interested in.
3016	 */
3017	copy_namehook_lists(adb, find, qname, qtype, adbname, now);
3018
3019 post_copy:
3020	if (NAME_FETCH_V4(adbname))
3021		query_pending |= DNS_ADBFIND_INET;
3022	if (NAME_FETCH_V6(adbname))
3023		query_pending |= DNS_ADBFIND_INET6;
3024
3025	/*
3026	 * Attach to the name's query list if there are queries
3027	 * already running, and we have been asked to.
3028	 */
3029	want_event = ISC_TRUE;
3030	if (!FIND_WANTEVENT(find))
3031		want_event = ISC_FALSE;
3032	if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
3033		want_event = ISC_FALSE;
3034	if ((wanted_addresses & query_pending) == 0)
3035		want_event = ISC_FALSE;
3036	if (alias)
3037		want_event = ISC_FALSE;
3038	if (want_event) {
3039		find->adbname = adbname;
3040		find->name_bucket = bucket;
3041		ISC_LIST_APPEND(adbname->finds, find, plink);
3042		find->query_pending = (query_pending & wanted_addresses);
3043		find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3044		find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
3045		DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
3046		   find, adbname);
3047	} else {
3048		/*
3049		 * Remove the flag so the caller knows there will never
3050		 * be an event, and set internal flags to fake that
3051		 * the event was sent and freed, so dns_adb_destroyfind() will
3052		 * do the right thing.
3053		 */
3054		find->query_pending = (query_pending & wanted_addresses);
3055		find->options &= ~DNS_ADBFIND_WANTEVENT;
3056		find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
3057		find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
3058	}
3059
3060	find->partial_result |= (adbname->partial_result & wanted_addresses);
3061	if (alias) {
3062		if (target != NULL) {
3063			result = dns_name_copy(&adbname->target, target, NULL);
3064			if (result != ISC_R_SUCCESS)
3065				goto out;
3066		}
3067		result = DNS_R_ALIAS;
3068	} else
3069		result = ISC_R_SUCCESS;
3070
3071	/*
3072	 * Copy out error flags from the name structure into the find.
3073	 */
3074	find->result_v4 = find_err_map[adbname->fetch_err];
3075	find->result_v6 = find_err_map[adbname->fetch6_err];
3076
3077 out:
3078	if (find != NULL) {
3079		*findp = find;
3080
3081		if (want_event) {
3082			isc_task_t *taskp;
3083
3084			INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
3085			taskp = NULL;
3086			isc_task_attach(task, &taskp);
3087			find->event.ev_sender = taskp;
3088			find->event.ev_action = action;
3089			find->event.ev_arg = arg;
3090		}
3091	}
3092
3093	UNLOCK(&adb->namelocks[bucket]);
3094
3095	return (result);
3096}
3097
3098void
3099dns_adb_destroyfind(dns_adbfind_t **findp) {
3100	dns_adbfind_t *find;
3101	dns_adbentry_t *entry;
3102	dns_adbaddrinfo_t *ai;
3103	int bucket;
3104	dns_adb_t *adb;
3105	isc_boolean_t overmem;
3106
3107	REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
3108	find = *findp;
3109	*findp = NULL;
3110
3111	LOCK(&find->lock);
3112
3113	DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
3114
3115	adb = find->adb;
3116	REQUIRE(DNS_ADB_VALID(adb));
3117
3118	REQUIRE(FIND_EVENTFREED(find));
3119
3120	bucket = find->name_bucket;
3121	INSIST(bucket == DNS_ADB_INVALIDBUCKET);
3122
3123	UNLOCK(&find->lock);
3124
3125	/*
3126	 * The find doesn't exist on any list, and nothing is locked.
3127	 * Return the find to the memory pool, and decrement the adb's
3128	 * reference count.
3129	 */
3130	overmem = isc_mem_isovermem(adb->mctx);
3131	ai = ISC_LIST_HEAD(find->list);
3132	while (ai != NULL) {
3133		ISC_LIST_UNLINK(find->list, ai, publink);
3134		entry = ai->entry;
3135		ai->entry = NULL;
3136		INSIST(DNS_ADBENTRY_VALID(entry));
3137		RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
3138			      ISC_FALSE);
3139		free_adbaddrinfo(adb, &ai);
3140		ai = ISC_LIST_HEAD(find->list);
3141	}
3142
3143	/*
3144	 * WARNING:  The find is freed with the adb locked.  This is done
3145	 * to avoid a race condition where we free the find, some other
3146	 * thread tests to see if it should be destroyed, detects it should
3147	 * be, destroys it, and then we try to lock it for our check, but the
3148	 * lock is destroyed.
3149	 */
3150	LOCK(&adb->lock);
3151	if (free_adbfind(adb, &find))
3152		check_exit(adb);
3153	UNLOCK(&adb->lock);
3154}
3155
3156void
3157dns_adb_cancelfind(dns_adbfind_t *find) {
3158	isc_event_t *ev;
3159	isc_task_t *task;
3160	dns_adb_t *adb;
3161	int bucket;
3162	int unlock_bucket;
3163
3164	LOCK(&find->lock);
3165
3166	DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
3167
3168	adb = find->adb;
3169	REQUIRE(DNS_ADB_VALID(adb));
3170
3171	REQUIRE(!FIND_EVENTFREED(find));
3172	REQUIRE(FIND_WANTEVENT(find));
3173
3174	bucket = find->name_bucket;
3175	if (bucket == DNS_ADB_INVALIDBUCKET)
3176		goto cleanup;
3177
3178	/*
3179	 * We need to get the adbname's lock to unlink the find.
3180	 */
3181	unlock_bucket = bucket;
3182	violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
3183	bucket = find->name_bucket;
3184	if (bucket != DNS_ADB_INVALIDBUCKET) {
3185		ISC_LIST_UNLINK(find->adbname->finds, find, plink);
3186		find->adbname = NULL;
3187		find->name_bucket = DNS_ADB_INVALIDBUCKET;
3188	}
3189	UNLOCK(&adb->namelocks[unlock_bucket]);
3190	bucket = DNS_ADB_INVALIDBUCKET;
3191	POST(bucket);
3192
3193 cleanup:
3194
3195	if (!FIND_EVENTSENT(find)) {
3196		ev = &find->event;
3197		task = ev->ev_sender;
3198		ev->ev_sender = find;
3199		ev->ev_type = DNS_EVENT_ADBCANCELED;
3200		ev->ev_destroy = event_free;
3201		ev->ev_destroy_arg = find;
3202		find->result_v4 = ISC_R_CANCELED;
3203		find->result_v6 = ISC_R_CANCELED;
3204
3205		DP(DEF_LEVEL, "sending event %p to task %p for find %p",
3206		   ev, task, find);
3207
3208		isc_task_sendanddetach(&task, (isc_event_t **)&ev);
3209	}
3210
3211	UNLOCK(&find->lock);
3212}
3213
3214void
3215dns_adb_dump(dns_adb_t *adb, FILE *f) {
3216	unsigned int i;
3217	isc_stdtime_t now;
3218
3219	REQUIRE(DNS_ADB_VALID(adb));
3220	REQUIRE(f != NULL);
3221
3222	/*
3223	 * Lock the adb itself, lock all the name buckets, then lock all
3224	 * the entry buckets.  This should put the adb into a state where
3225	 * nothing can change, so we can iterate through everything and
3226	 * print at our leisure.
3227	 */
3228
3229	LOCK(&adb->lock);
3230	isc_stdtime_get(&now);
3231
3232	for (i = 0; i < adb->nnames; i++)
3233		RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
3234	for (i = 0; i < adb->nentries; i++)
3235		RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
3236
3237	dump_adb(adb, f, ISC_FALSE, now);
3238	UNLOCK(&adb->lock);
3239}
3240
3241static void
3242dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
3243	if (value == INT_MAX)
3244		return;
3245	fprintf(f, " [%s TTL %d]", legend, value - now);
3246}
3247
3248static void
3249dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
3250	unsigned int i;
3251	dns_adbname_t *name;
3252	dns_adbentry_t *entry;
3253
3254	fprintf(f, ";\n; Address database dump\n;\n");
3255	if (debug)
3256		fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
3257			adb, adb->erefcnt, adb->irefcnt,
3258			isc_mempool_getallocated(adb->nhmp));
3259
3260	for (i = 0; i < adb->nnames; i++)
3261		LOCK(&adb->namelocks[i]);
3262	for (i = 0; i < adb->nentries; i++)
3263		LOCK(&adb->entrylocks[i]);
3264
3265	/*
3266	 * Dump the names
3267	 */
3268	for (i = 0; i < adb->nnames; i++) {
3269		name = ISC_LIST_HEAD(adb->names[i]);
3270		if (name == NULL)
3271			continue;
3272		if (debug)
3273			fprintf(f, "; bucket %d\n", i);
3274		for (;
3275		     name != NULL;
3276		     name = ISC_LIST_NEXT(name, plink))
3277		{
3278			if (debug)
3279				fprintf(f, "; name %p (flags %08x)\n",
3280					name, name->flags);
3281
3282			fprintf(f, "; ");
3283			print_dns_name(f, &name->name);
3284			if (dns_name_countlabels(&name->target) > 0) {
3285				fprintf(f, " alias ");
3286				print_dns_name(f, &name->target);
3287			}
3288
3289			dump_ttl(f, "v4", name->expire_v4, now);
3290			dump_ttl(f, "v6", name->expire_v6, now);
3291			dump_ttl(f, "target", name->expire_target, now);
3292
3293			fprintf(f, " [v4 %s] [v6 %s]",
3294				errnames[name->fetch_err],
3295				errnames[name->fetch6_err]);
3296
3297			fprintf(f, "\n");
3298
3299			print_namehook_list(f, "v4", &name->v4, debug, now);
3300			print_namehook_list(f, "v6", &name->v6, debug, now);
3301
3302			if (debug)
3303				print_fetch_list(f, name);
3304			if (debug)
3305				print_find_list(f, name);
3306
3307		}
3308	}
3309
3310	fprintf(f, ";\n; Unassociated entries\n;\n");
3311
3312	for (i = 0; i < adb->nentries; i++) {
3313		entry = ISC_LIST_HEAD(adb->entries[i]);
3314		while (entry != NULL) {
3315			if (entry->refcnt == 0)
3316				dump_entry(f, entry, debug, now);
3317			entry = ISC_LIST_NEXT(entry, plink);
3318		}
3319	}
3320
3321	/*
3322	 * Unlock everything
3323	 */
3324	for (i = 0; i < adb->nentries; i++)
3325		UNLOCK(&adb->entrylocks[i]);
3326	for (i = 0; i < adb->nnames; i++)
3327		UNLOCK(&adb->namelocks[i]);
3328}
3329
3330static void
3331dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
3332	   isc_stdtime_t now)
3333{
3334	char addrbuf[ISC_NETADDR_FORMATSIZE];
3335	char typebuf[DNS_RDATATYPE_FORMATSIZE];
3336	isc_netaddr_t netaddr;
3337	dns_adblameinfo_t *li;
3338
3339	isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
3340	isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
3341
3342	if (debug)
3343		fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
3344
3345	fprintf(f, ";\t%s [srtt %u] [flags %08x]",
3346		addrbuf, entry->srtt, entry->flags);
3347	if (entry->expires != 0)
3348		fprintf(f, " [ttl %d]", entry->expires - now);
3349	fprintf(f, "\n");
3350	for (li = ISC_LIST_HEAD(entry->lameinfo);
3351	     li != NULL;
3352	     li = ISC_LIST_NEXT(li, plink)) {
3353		fprintf(f, ";\t\t");
3354		print_dns_name(f, &li->qname);
3355		dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
3356		fprintf(f, " %s [lame TTL %d]\n", typebuf,
3357			li->lame_timer - now);
3358	}
3359}
3360
3361void
3362dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
3363	char tmp[512];
3364	const char *tmpp;
3365	dns_adbaddrinfo_t *ai;
3366	isc_sockaddr_t *sa;
3367
3368	/*
3369	 * Not used currently, in the API Just In Case we
3370	 * want to dump out the name and/or entries too.
3371	 */
3372
3373	LOCK(&find->lock);
3374
3375	fprintf(f, ";Find %p\n", find);
3376	fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
3377		find->query_pending, find->partial_result,
3378		find->options, find->flags);
3379	fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
3380		find->name_bucket, find->adbname, find->event.ev_sender);
3381
3382	ai = ISC_LIST_HEAD(find->list);
3383	if (ai != NULL)
3384		fprintf(f, "\tAddresses:\n");
3385	while (ai != NULL) {
3386		sa = &ai->sockaddr;
3387		switch (sa->type.sa.sa_family) {
3388		case AF_INET:
3389			tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
3390					 tmp, sizeof(tmp));
3391			break;
3392		case AF_INET6:
3393			tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
3394					 tmp, sizeof(tmp));
3395			break;
3396		default:
3397			tmpp = "UnkFamily";
3398		}
3399
3400		if (tmpp == NULL)
3401			tmpp = "BadAddress";
3402
3403		fprintf(f, "\t\tentry %p, flags %08x"
3404			" srtt %u addr %s\n",
3405			ai->entry, ai->flags, ai->srtt, tmpp);
3406
3407		ai = ISC_LIST_NEXT(ai, publink);
3408	}
3409
3410	UNLOCK(&find->lock);
3411}
3412
3413static void
3414print_dns_name(FILE *f, dns_name_t *name) {
3415	char buf[DNS_NAME_FORMATSIZE];
3416
3417	INSIST(f != NULL);
3418
3419	dns_name_format(name, buf, sizeof(buf));
3420	fprintf(f, "%s", buf);
3421}
3422
3423static void
3424print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
3425		    isc_boolean_t debug, isc_stdtime_t now)
3426{
3427	dns_adbnamehook_t *nh;
3428
3429	for (nh = ISC_LIST_HEAD(*list);
3430	     nh != NULL;
3431	     nh = ISC_LIST_NEXT(nh, plink))
3432	{
3433		if (debug)
3434			fprintf(f, ";\tHook(%s) %p\n", legend, nh);
3435		dump_entry(f, nh->entry, debug, now);
3436	}
3437}
3438
3439static inline void
3440print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
3441	fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
3442		type, ft, ft->fetch);
3443}
3444
3445static void
3446print_fetch_list(FILE *f, dns_adbname_t *n) {
3447	if (NAME_FETCH_A(n))
3448		print_fetch(f, n->fetch_a, "A");
3449	if (NAME_FETCH_AAAA(n))
3450		print_fetch(f, n->fetch_aaaa, "AAAA");
3451}
3452
3453static void
3454print_find_list(FILE *f, dns_adbname_t *name) {
3455	dns_adbfind_t *find;
3456
3457	find = ISC_LIST_HEAD(name->finds);
3458	while (find != NULL) {
3459		dns_adb_dumpfind(find, f);
3460		find = ISC_LIST_NEXT(find, plink);
3461	}
3462}
3463
3464static isc_result_t
3465dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
3466{
3467	isc_result_t result;
3468	dns_rdataset_t rdataset;
3469	dns_adb_t *adb;
3470	dns_fixedname_t foundname;
3471	dns_name_t *fname;
3472
3473	INSIST(DNS_ADBNAME_VALID(adbname));
3474	adb = adbname->adb;
3475	INSIST(DNS_ADB_VALID(adb));
3476	INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
3477
3478	dns_fixedname_init(&foundname);
3479	fname = dns_fixedname_name(&foundname);
3480	dns_rdataset_init(&rdataset);
3481
3482	if (rdtype == dns_rdatatype_a)
3483		adbname->fetch_err = FIND_ERR_UNEXPECTED;
3484	else
3485		adbname->fetch6_err = FIND_ERR_UNEXPECTED;
3486
3487	/*
3488	 * We need to specify whether to search static-stub zones (if
3489	 * configured) depending on whether this is a "start at zone" lookup,
3490	 * i.e., whether it's a "bailiwick" glue.  If it's bailiwick (in which
3491	 * case NAME_STARTATZONE is set) we need to stop the search at any
3492	 * matching static-stub zone without looking into the cache to honor
3493	 * the configuration on which server we should send queries to.
3494	 */
3495	result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
3496				NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
3497				ISC_TF(NAME_HINTOK(adbname)),
3498				(adbname->flags & NAME_STARTATZONE) != 0 ?
3499				ISC_TRUE : ISC_FALSE,
3500				NULL, NULL, fname, &rdataset, NULL);
3501
3502	/* XXXVIX this switch statement is too sparse to gen a jump table. */
3503	switch (result) {
3504	case DNS_R_GLUE:
3505	case DNS_R_HINT:
3506	case ISC_R_SUCCESS:
3507		/*
3508		 * Found in the database.  Even if we can't copy out
3509		 * any information, return success, or else a fetch
3510		 * will be made, which will only make things worse.
3511		 */
3512		if (rdtype == dns_rdatatype_a)
3513			adbname->fetch_err = FIND_ERR_SUCCESS;
3514		else
3515			adbname->fetch6_err = FIND_ERR_SUCCESS;
3516		result = import_rdataset(adbname, &rdataset, now);
3517		break;
3518	case DNS_R_NXDOMAIN:
3519	case DNS_R_NXRRSET:
3520		/*
3521		 * We're authoritative and the data doesn't exist.
3522		 * Make up a negative cache entry so we don't ask again
3523		 * for a while.
3524		 *
3525		 * XXXRTH  What time should we use?  I'm putting in 30 seconds
3526		 * for now.
3527		 */
3528		if (rdtype == dns_rdatatype_a) {
3529			adbname->expire_v4 = now + 30;
3530			DP(NCACHE_LEVEL,
3531			   "adb name %p: Caching auth negative entry for A",
3532			   adbname);
3533			if (result == DNS_R_NXDOMAIN)
3534				adbname->fetch_err = FIND_ERR_NXDOMAIN;
3535			else
3536				adbname->fetch_err = FIND_ERR_NXRRSET;
3537		} else {
3538			DP(NCACHE_LEVEL,
3539			   "adb name %p: Caching auth negative entry for AAAA",
3540			   adbname);
3541			adbname->expire_v6 = now + 30;
3542			if (result == DNS_R_NXDOMAIN)
3543				adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3544			else
3545				adbname->fetch6_err = FIND_ERR_NXRRSET;
3546		}
3547		break;
3548	case DNS_R_NCACHENXDOMAIN:
3549	case DNS_R_NCACHENXRRSET:
3550		/*
3551		 * We found a negative cache entry.  Pull the TTL from it
3552		 * so we won't ask again for a while.
3553		 */
3554		rdataset.ttl = ttlclamp(rdataset.ttl);
3555		if (rdtype == dns_rdatatype_a) {
3556			adbname->expire_v4 = rdataset.ttl + now;
3557			if (result == DNS_R_NCACHENXDOMAIN)
3558				adbname->fetch_err = FIND_ERR_NXDOMAIN;
3559			else
3560				adbname->fetch_err = FIND_ERR_NXRRSET;
3561			DP(NCACHE_LEVEL,
3562			  "adb name %p: Caching negative entry for A (ttl %u)",
3563			   adbname, rdataset.ttl);
3564		} else {
3565			DP(NCACHE_LEVEL,
3566		       "adb name %p: Caching negative entry for AAAA (ttl %u)",
3567			   adbname, rdataset.ttl);
3568			adbname->expire_v6 = rdataset.ttl + now;
3569			if (result == DNS_R_NCACHENXDOMAIN)
3570				adbname->fetch6_err = FIND_ERR_NXDOMAIN;
3571			else
3572				adbname->fetch6_err = FIND_ERR_NXRRSET;
3573		}
3574		break;
3575	case DNS_R_CNAME:
3576	case DNS_R_DNAME:
3577		/*
3578		 * Clear the hint and glue flags, so this will match
3579		 * more often.
3580		 */
3581		adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
3582
3583		rdataset.ttl = ttlclamp(rdataset.ttl);
3584		clean_target(adb, &adbname->target);
3585		adbname->expire_target = INT_MAX;
3586		result = set_target(adb, &adbname->name, fname, &rdataset,
3587				    &adbname->target);
3588		if (result == ISC_R_SUCCESS) {
3589			result = DNS_R_ALIAS;
3590			DP(NCACHE_LEVEL,
3591			   "adb name %p: caching alias target",
3592			   adbname);
3593			adbname->expire_target = rdataset.ttl + now;
3594		}
3595		if (rdtype == dns_rdatatype_a)
3596			adbname->fetch_err = FIND_ERR_SUCCESS;
3597		else
3598			adbname->fetch6_err = FIND_ERR_SUCCESS;
3599		break;
3600	}
3601
3602	if (dns_rdataset_isassociated(&rdataset))
3603		dns_rdataset_disassociate(&rdataset);
3604
3605	return (result);
3606}
3607
3608static void
3609fetch_callback(isc_task_t *task, isc_event_t *ev) {
3610	dns_fetchevent_t *dev;
3611	dns_adbname_t *name;
3612	dns_adb_t *adb;
3613	dns_adbfetch_t *fetch;
3614	int bucket;
3615	isc_eventtype_t ev_status;
3616	isc_stdtime_t now;
3617	isc_result_t result;
3618	unsigned int address_type;
3619	isc_boolean_t want_check_exit = ISC_FALSE;
3620
3621	UNUSED(task);
3622
3623	INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
3624	dev = (dns_fetchevent_t *)ev;
3625	name = ev->ev_arg;
3626	INSIST(DNS_ADBNAME_VALID(name));
3627	adb = name->adb;
3628	INSIST(DNS_ADB_VALID(adb));
3629
3630	bucket = name->lock_bucket;
3631	LOCK(&adb->namelocks[bucket]);
3632
3633	INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
3634	address_type = 0;
3635	if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
3636		address_type = DNS_ADBFIND_INET;
3637		fetch = name->fetch_a;
3638		name->fetch_a = NULL;
3639	} else if (NAME_FETCH_AAAA(name)
3640		   && (name->fetch_aaaa->fetch == dev->fetch)) {
3641		address_type = DNS_ADBFIND_INET6;
3642		fetch = name->fetch_aaaa;
3643		name->fetch_aaaa = NULL;
3644	} else
3645		fetch = NULL;
3646
3647	INSIST(address_type != 0 && fetch != NULL);
3648
3649	dns_resolver_destroyfetch(&fetch->fetch);
3650	dev->fetch = NULL;
3651
3652	ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
3653
3654	/*
3655	 * Cleanup things we don't care about.
3656	 */
3657	if (dev->node != NULL)
3658		dns_db_detachnode(dev->db, &dev->node);
3659	if (dev->db != NULL)
3660		dns_db_detach(&dev->db);
3661
3662	/*
3663	 * If this name is marked as dead, clean up, throwing away
3664	 * potentially good data.
3665	 */
3666	if (NAME_DEAD(name)) {
3667		free_adbfetch(adb, &fetch);
3668		isc_event_free(&ev);
3669
3670		want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED);
3671
3672		UNLOCK(&adb->namelocks[bucket]);
3673
3674		if (want_check_exit) {
3675			LOCK(&adb->lock);
3676			check_exit(adb);
3677			UNLOCK(&adb->lock);
3678		}
3679
3680		return;
3681	}
3682
3683	isc_stdtime_get(&now);
3684
3685	/*
3686	 * If we got a negative cache response, remember it.
3687	 */
3688	if (NCACHE_RESULT(dev->result)) {
3689		dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3690		if (address_type == DNS_ADBFIND_INET) {
3691			DP(NCACHE_LEVEL, "adb fetch name %p: "
3692			   "caching negative entry for A (ttl %u)",
3693			   name, dev->rdataset->ttl);
3694			name->expire_v4 = ISC_MIN(name->expire_v4,
3695						  dev->rdataset->ttl + now);
3696			if (dev->result == DNS_R_NCACHENXDOMAIN)
3697				name->fetch_err = FIND_ERR_NXDOMAIN;
3698			else
3699				name->fetch_err = FIND_ERR_NXRRSET;
3700			inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3701		} else {
3702			DP(NCACHE_LEVEL, "adb fetch name %p: "
3703			   "caching negative entry for AAAA (ttl %u)",
3704			   name, dev->rdataset->ttl);
3705			name->expire_v6 = ISC_MIN(name->expire_v6,
3706						  dev->rdataset->ttl + now);
3707			if (dev->result == DNS_R_NCACHENXDOMAIN)
3708				name->fetch6_err = FIND_ERR_NXDOMAIN;
3709			else
3710				name->fetch6_err = FIND_ERR_NXRRSET;
3711			inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3712		}
3713		goto out;
3714	}
3715
3716	/*
3717	 * Handle CNAME/DNAME.
3718	 */
3719	if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
3720		dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
3721		clean_target(adb, &name->target);
3722		name->expire_target = INT_MAX;
3723		result = set_target(adb, &name->name,
3724				    dns_fixedname_name(&dev->foundname),
3725				    dev->rdataset,
3726				    &name->target);
3727		if (result == ISC_R_SUCCESS) {
3728			DP(NCACHE_LEVEL,
3729			   "adb fetch name %p: caching alias target",
3730			   name);
3731			name->expire_target = dev->rdataset->ttl + now;
3732		}
3733		goto check_result;
3734	}
3735
3736	/*
3737	 * Did we get back junk?  If so, and there are no more fetches
3738	 * sitting out there, tell all the finds about it.
3739	 */
3740	if (dev->result != ISC_R_SUCCESS) {
3741		char buf[DNS_NAME_FORMATSIZE];
3742
3743		dns_name_format(&name->name, buf, sizeof(buf));
3744		DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
3745		   buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
3746		   dns_result_totext(dev->result));
3747		/* XXXMLG Don't pound on bad servers. */
3748		if (address_type == DNS_ADBFIND_INET) {
3749			name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
3750			name->fetch_err = FIND_ERR_FAILURE;
3751			inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
3752		} else {
3753			name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
3754			name->fetch6_err = FIND_ERR_FAILURE;
3755			inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
3756		}
3757		goto out;
3758	}
3759
3760	/*
3761	 * We got something potentially useful.
3762	 */
3763	result = import_rdataset(name, &fetch->rdataset, now);
3764
3765 check_result:
3766	if (result == ISC_R_SUCCESS) {
3767		ev_status = DNS_EVENT_ADBMOREADDRESSES;
3768		if (address_type == DNS_ADBFIND_INET)
3769			name->fetch_err = FIND_ERR_SUCCESS;
3770		else
3771			name->fetch6_err = FIND_ERR_SUCCESS;
3772	}
3773
3774 out:
3775	free_adbfetch(adb, &fetch);
3776	isc_event_free(&ev);
3777
3778	clean_finds_at_name(name, ev_status, address_type);
3779
3780	UNLOCK(&adb->namelocks[bucket]);
3781}
3782
3783static isc_result_t
3784fetch_name(dns_adbname_t *adbname,
3785	   isc_boolean_t start_at_zone,
3786	   dns_rdatatype_t type)
3787{
3788	isc_result_t result;
3789	dns_adbfetch_t *fetch = NULL;
3790	dns_adb_t *adb;
3791	dns_fixedname_t fixed;
3792	dns_name_t *name;
3793	dns_rdataset_t rdataset;
3794	dns_rdataset_t *nameservers;
3795	unsigned int options;
3796
3797	INSIST(DNS_ADBNAME_VALID(adbname));
3798	adb = adbname->adb;
3799	INSIST(DNS_ADB_VALID(adb));
3800
3801	INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
3802	       (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
3803
3804	adbname->fetch_err = FIND_ERR_NOTFOUND;
3805
3806	name = NULL;
3807	nameservers = NULL;
3808	dns_rdataset_init(&rdataset);
3809
3810	options = DNS_FETCHOPT_NOVALIDATE;
3811	if (start_at_zone) {
3812		DP(ENTER_LEVEL,
3813		   "fetch_name: starting at zone for name %p",
3814		   adbname);
3815		dns_fixedname_init(&fixed);
3816		name = dns_fixedname_name(&fixed);
3817		result = dns_view_findzonecut2(adb->view, &adbname->name, name,
3818					       0, 0, ISC_TRUE, ISC_FALSE,
3819					       &rdataset, NULL);
3820		if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
3821			goto cleanup;
3822		nameservers = &rdataset;
3823		options |= DNS_FETCHOPT_UNSHARED;
3824	}
3825
3826	fetch = new_adbfetch(adb);
3827	if (fetch == NULL) {
3828		result = ISC_R_NOMEMORY;
3829		goto cleanup;
3830	}
3831
3832	result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
3833					  type, name, nameservers, NULL,
3834					  options, adb->task, fetch_callback,
3835					  adbname, &fetch->rdataset, NULL,
3836					  &fetch->fetch);
3837	if (result != ISC_R_SUCCESS)
3838		goto cleanup;
3839
3840	if (type == dns_rdatatype_a) {
3841		adbname->fetch_a = fetch;
3842		inc_stats(adb, dns_resstatscounter_gluefetchv4);
3843	} else {
3844		adbname->fetch_aaaa = fetch;
3845		inc_stats(adb, dns_resstatscounter_gluefetchv6);
3846	}
3847	fetch = NULL;  /* Keep us from cleaning this up below. */
3848
3849 cleanup:
3850	if (fetch != NULL)
3851		free_adbfetch(adb, &fetch);
3852	if (dns_rdataset_isassociated(&rdataset))
3853		dns_rdataset_disassociate(&rdataset);
3854
3855	return (result);
3856}
3857
3858/*
3859 * XXXMLG Needs to take a find argument and an address info, no zone or adb,
3860 * since these can be extracted from the find itself.
3861 */
3862isc_result_t
3863dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
3864		 dns_rdatatype_t qtype, isc_stdtime_t expire_time)
3865{
3866	dns_adblameinfo_t *li;
3867	int bucket;
3868	isc_result_t result = ISC_R_SUCCESS;
3869
3870	REQUIRE(DNS_ADB_VALID(adb));
3871	REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3872	REQUIRE(qname != NULL);
3873
3874	bucket = addr->entry->lock_bucket;
3875	LOCK(&adb->entrylocks[bucket]);
3876	li = ISC_LIST_HEAD(addr->entry->lameinfo);
3877	while (li != NULL &&
3878	       (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
3879		li = ISC_LIST_NEXT(li, plink);
3880	if (li != NULL) {
3881		if (expire_time > li->lame_timer)
3882			li->lame_timer = expire_time;
3883		goto unlock;
3884	}
3885	li = new_adblameinfo(adb, qname, qtype);
3886	if (li == NULL) {
3887		result = ISC_R_NOMEMORY;
3888		goto unlock;
3889	}
3890
3891	li->lame_timer = expire_time;
3892
3893	ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
3894 unlock:
3895	UNLOCK(&adb->entrylocks[bucket]);
3896
3897	return (result);
3898}
3899
3900void
3901dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3902		   unsigned int rtt, unsigned int factor)
3903{
3904	int bucket;
3905	unsigned int new_srtt;
3906	isc_stdtime_t now;
3907
3908	REQUIRE(DNS_ADB_VALID(adb));
3909	REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3910	REQUIRE(factor <= 10);
3911
3912	bucket = addr->entry->lock_bucket;
3913	LOCK(&adb->entrylocks[bucket]);
3914
3915	if (factor == DNS_ADB_RTTADJAGE)
3916		new_srtt = addr->entry->srtt * 98 / 100;
3917	else
3918		new_srtt = (addr->entry->srtt / 10 * factor)
3919			+ (rtt / 10 * (10 - factor));
3920
3921	addr->entry->srtt = new_srtt;
3922	addr->srtt = new_srtt;
3923
3924	if (addr->entry->expires == 0) {
3925		isc_stdtime_get(&now);
3926		addr->entry->expires = now + ADB_ENTRY_WINDOW;
3927	}
3928
3929	UNLOCK(&adb->entrylocks[bucket]);
3930}
3931
3932void
3933dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3934		    unsigned int bits, unsigned int mask)
3935{
3936	int bucket;
3937	isc_stdtime_t now;
3938
3939	REQUIRE(DNS_ADB_VALID(adb));
3940	REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3941
3942	bucket = addr->entry->lock_bucket;
3943	LOCK(&adb->entrylocks[bucket]);
3944
3945	addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
3946	if (addr->entry->expires == 0) {
3947		isc_stdtime_get(&now);
3948		addr->entry->expires = now + ADB_ENTRY_WINDOW;
3949	}
3950
3951	/*
3952	 * Note that we do not update the other bits in addr->flags with
3953	 * the most recent values from addr->entry->flags.
3954	 */
3955	addr->flags = (addr->flags & ~mask) | (bits & mask);
3956
3957	UNLOCK(&adb->entrylocks[bucket]);
3958}
3959
3960isc_result_t
3961dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
3962		     dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
3963{
3964	int bucket;
3965	dns_adbentry_t *entry;
3966	dns_adbaddrinfo_t *addr;
3967	isc_result_t result;
3968	in_port_t port;
3969
3970	REQUIRE(DNS_ADB_VALID(adb));
3971	REQUIRE(addrp != NULL && *addrp == NULL);
3972
3973	UNUSED(now);
3974
3975	result = ISC_R_SUCCESS;
3976	bucket = DNS_ADB_INVALIDBUCKET;
3977	entry = find_entry_and_lock(adb, sa, &bucket, now);
3978	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
3979	if (adb->entry_sd[bucket]) {
3980		result = ISC_R_SHUTTINGDOWN;
3981		goto unlock;
3982	}
3983	if (entry == NULL) {
3984		/*
3985		 * We don't know anything about this address.
3986		 */
3987		entry = new_adbentry(adb);
3988		if (entry == NULL) {
3989			result = ISC_R_NOMEMORY;
3990			goto unlock;
3991		}
3992		entry->sockaddr = *sa;
3993		link_entry(adb, bucket, entry);
3994		DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
3995	} else
3996		DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
3997
3998	port = isc_sockaddr_getport(sa);
3999	addr = new_adbaddrinfo(adb, entry, port);
4000	if (addr == NULL) {
4001		result = ISC_R_NOMEMORY;
4002	} else {
4003		inc_entry_refcnt(adb, entry, ISC_FALSE);
4004		*addrp = addr;
4005	}
4006
4007 unlock:
4008	UNLOCK(&adb->entrylocks[bucket]);
4009
4010	return (result);
4011}
4012
4013void
4014dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
4015	dns_adbaddrinfo_t *addr;
4016	dns_adbentry_t *entry;
4017	int bucket;
4018	isc_stdtime_t now;
4019	isc_boolean_t want_check_exit = ISC_FALSE;
4020	isc_boolean_t overmem;
4021
4022	REQUIRE(DNS_ADB_VALID(adb));
4023	REQUIRE(addrp != NULL);
4024	addr = *addrp;
4025	REQUIRE(DNS_ADBADDRINFO_VALID(addr));
4026	entry = addr->entry;
4027	REQUIRE(DNS_ADBENTRY_VALID(entry));
4028
4029	*addrp = NULL;
4030	overmem = isc_mem_isovermem(adb->mctx);
4031
4032	bucket = addr->entry->lock_bucket;
4033	LOCK(&adb->entrylocks[bucket]);
4034
4035	if (entry->expires == 0) {
4036		isc_stdtime_get(&now);
4037		entry->expires = now + ADB_ENTRY_WINDOW;
4038	}
4039
4040	want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
4041
4042	UNLOCK(&adb->entrylocks[bucket]);
4043
4044	addr->entry = NULL;
4045	free_adbaddrinfo(adb, &addr);
4046
4047	if (want_check_exit) {
4048		LOCK(&adb->lock);
4049		check_exit(adb);
4050		UNLOCK(&adb->lock);
4051	}
4052}
4053
4054void
4055dns_adb_flush(dns_adb_t *adb) {
4056	unsigned int i;
4057
4058	INSIST(DNS_ADB_VALID(adb));
4059
4060	LOCK(&adb->lock);
4061
4062	/*
4063	 * Call our cleanup routines.
4064	 */
4065	for (i = 0; i < adb->nnames; i++)
4066		RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
4067	for (i = 0; i < adb->nentries; i++)
4068		RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
4069
4070#ifdef DUMP_ADB_AFTER_CLEANING
4071	dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
4072#endif
4073
4074	UNLOCK(&adb->lock);
4075}
4076
4077void
4078dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
4079	dns_adbname_t *adbname;
4080	dns_adbname_t *nextname;
4081	int bucket;
4082
4083	INSIST(DNS_ADB_VALID(adb));
4084
4085	LOCK(&adb->lock);
4086	bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
4087	LOCK(&adb->namelocks[bucket]);
4088	adbname = ISC_LIST_HEAD(adb->names[bucket]);
4089	while (adbname != NULL) {
4090		nextname = ISC_LIST_NEXT(adbname, plink);
4091		if (!NAME_DEAD(adbname) &&
4092		    dns_name_equal(name, &adbname->name)) {
4093			RUNTIME_CHECK(kill_name(&adbname,
4094						DNS_EVENT_ADBCANCELED) ==
4095				      ISC_FALSE);
4096		}
4097		adbname = nextname;
4098	}
4099	UNLOCK(&adb->namelocks[bucket]);
4100	UNLOCK(&adb->lock);
4101}
4102
4103static void
4104water(void *arg, int mark) {
4105	/*
4106	 * We're going to change the way to handle overmem condition: use
4107	 * isc_mem_isovermem() instead of storing the state via this callback,
4108	 * since the latter way tends to cause race conditions.
4109	 * To minimize the change, and in case we re-enable the callback
4110	 * approach, however, keep this function at the moment.
4111	 */
4112
4113	dns_adb_t *adb = arg;
4114	isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
4115
4116	REQUIRE(DNS_ADB_VALID(adb));
4117
4118	DP(ISC_LOG_DEBUG(1),
4119	   "adb reached %s water mark", overmem ? "high" : "low");
4120}
4121
4122void
4123dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) {
4124	isc_uint32_t hiwater;
4125	isc_uint32_t lowater;
4126
4127	INSIST(DNS_ADB_VALID(adb));
4128
4129	if (size != 0 && size < DNS_ADB_MINADBSIZE)
4130		size = DNS_ADB_MINADBSIZE;
4131
4132	hiwater = size - (size >> 3);   /* Approximately 7/8ths. */
4133	lowater = size - (size >> 2);   /* Approximately 3/4ths. */
4134
4135	if (size == 0 || hiwater == 0 || lowater == 0)
4136		isc_mem_setwater(adb->mctx, water, adb, 0, 0);
4137	else
4138		isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
4139}
4140