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