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