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