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