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