1 /* $NetBSD: adb.c,v 1.11 2015/07/08 17:28:58 christos Exp $ */
4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
23 * In finds, if task == NULL, no events will be generated, and no events
24 * have been sent. If task != NULL but taskaction == NULL, an event has been
25 * posted but not yet freed. If neither are NULL, no event was posted.
33 #include <isc/mutexblock.h>
34 #include <isc/netaddr.h>
35 #include <isc/random.h>
36 #include <isc/stats.h>
37 #include <isc/string.h> /* Required for HP/UX (and others?) */
43 #include <dns/events.h>
45 #include <dns/rdata.h>
46 #include <dns/rdataset.h>
47 #include <dns/rdatastruct.h>
48 #include <dns/rdatatype.h>
49 #include <dns/resolver.h>
50 #include <dns/result.h>
51 #include <dns/stats.h>
53 #define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
54 #define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
55 #define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
56 #define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
57 #define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
58 #define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
59 #define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
60 #define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
61 #define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
62 #define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
63 #define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
64 #define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
65 #define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
66 #define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
69 * For type 3 negative cache entries, we will remember that the address is
70 * broken for this long. XXXMLG This is also used for actual addresses, too.
71 * The intent is to keep us from constantly asking about A/AAAA records
72 * if the zone has extremely low TTLs.
74 #define ADB_CACHE_MINIMUM 10 /*%< seconds */
75 #define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
76 #define ADB_ENTRY_WINDOW 1800 /*%< seconds */
79 * The period in seconds after which an ADB name entry is regarded as stale
80 * and forced to be cleaned up.
81 * TODO: This should probably be configurable at run-time.
83 #ifndef ADB_STALE_MARGIN
84 #define ADB_STALE_MARGIN 1800
87 #define FREE_ITEMS 64 /*%< free count for memory pools */
88 #define FILL_COUNT 16 /*%< fill count for memory pools */
90 #define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
92 #define DNS_ADB_MINADBSIZE (1024U*1024U) /*%< 1 Megabyte */
94 typedef ISC_LIST(dns_adbname_t
) dns_adbnamelist_t
;
95 typedef struct dns_adbnamehook dns_adbnamehook_t
;
96 typedef ISC_LIST(dns_adbnamehook_t
) dns_adbnamehooklist_t
;
97 typedef struct dns_adblameinfo dns_adblameinfo_t
;
98 typedef ISC_LIST(dns_adbentry_t
) dns_adbentrylist_t
;
99 typedef struct dns_adbfetch dns_adbfetch_t
;
100 typedef struct dns_adbfetch6 dns_adbfetch6_t
;
102 /*% dns adb structure */
107 isc_mutex_t reflock
; /*%< Covers irefcnt, erefcnt */
108 isc_mutex_t overmemlock
; /*%< Covers overmem */
112 isc_taskmgr_t
*taskmgr
;
116 isc_interval_t tick_interval
;
117 int next_cleanbucket
;
119 unsigned int irefcnt
;
120 unsigned int erefcnt
;
123 isc_mempool_t
*nmp
; /*%< dns_adbname_t */
124 isc_mempool_t
*nhmp
; /*%< dns_adbnamehook_t */
125 isc_mempool_t
*limp
; /*%< dns_adblameinfo_t */
126 isc_mempool_t
*emp
; /*%< dns_adbentry_t */
127 isc_mempool_t
*ahmp
; /*%< dns_adbfind_t */
128 isc_mempool_t
*aimp
; /*%< dns_adbaddrinfo_t */
129 isc_mempool_t
*afmp
; /*%< dns_adbfetch_t */
132 * Bucketized locks and lists for names.
134 * XXXRTH Have a per-bucket structure that contains all of these?
137 isc_mutex_t namescntlock
;
138 unsigned int namescnt
;
139 dns_adbnamelist_t
*names
;
140 dns_adbnamelist_t
*deadnames
;
141 isc_mutex_t
*namelocks
;
142 isc_boolean_t
*name_sd
;
143 unsigned int *name_refcnt
;
146 * Bucketized locks and lists for entries.
148 * XXXRTH Have a per-bucket structure that contains all of these?
150 unsigned int nentries
;
151 isc_mutex_t entriescntlock
;
152 unsigned int entriescnt
;
153 dns_adbentrylist_t
*entries
;
154 dns_adbentrylist_t
*deadentries
;
155 isc_mutex_t
*entrylocks
;
156 isc_boolean_t
*entry_sd
; /*%< shutting down */
157 unsigned int *entry_refcnt
;
160 isc_boolean_t cevent_out
;
161 isc_boolean_t shutting_down
;
162 isc_eventlist_t whenshutdown
;
163 isc_event_t growentries
;
164 isc_boolean_t growentries_sent
;
165 isc_event_t grownames
;
166 isc_boolean_t grownames_sent
;
170 * XXXMLG Document these structures.
173 /*% dns_adbname structure */
178 unsigned int partial_result
;
182 isc_stdtime_t expire_target
;
183 isc_stdtime_t expire_v4
;
184 isc_stdtime_t expire_v6
;
186 dns_adbnamehooklist_t v4
;
187 dns_adbnamehooklist_t v6
;
188 dns_adbfetch_t
*fetch_a
;
189 dns_adbfetch_t
*fetch_aaaa
;
190 unsigned int fetch_err
;
191 unsigned int fetch6_err
;
192 dns_adbfindlist_t finds
;
193 /* for LRU-based management */
194 isc_stdtime_t last_used
;
196 ISC_LINK(dns_adbname_t
) plink
;
199 /*% The adbfetch structure */
200 struct dns_adbfetch
{
203 dns_rdataset_t rdataset
;
208 * This is a small widget that dangles off a dns_adbname_t. It contains a
209 * pointer to the address information about this host, and a link to the next
210 * namehook that will contain the next address this host has.
212 struct dns_adbnamehook
{
214 dns_adbentry_t
*entry
;
215 ISC_LINK(dns_adbnamehook_t
) plink
;
219 * This is a small widget that holds qname-specific information about an
220 * address. Currently limited to lameness, but could just as easily be
221 * extended to other types of information about zones.
223 struct dns_adblameinfo
{
227 dns_rdatatype_t qtype
;
228 isc_stdtime_t lame_timer
;
230 ISC_LINK(dns_adblameinfo_t
) plink
;
234 * An address entry. It holds quite a bit of information about addresses,
235 * including edns state (in "flags"), rtt, and of course the address of
238 struct dns_adbentry
{
246 isc_uint16_t udpsize
;
248 unsigned char plainto
;
250 unsigned char to4096
; /* Our max. */
252 * Allow for encapsulated IPv4/IPv6 UDP packet over ethernet.
253 * Ethernet 1500 - IP(20) - IP6(40) - UDP(8) = 1432.
255 unsigned char to1432
; /* Ethernet */
256 unsigned char to1232
; /* IPv6 nofrag */
257 unsigned char to512
; /* plain DNS */
258 isc_sockaddr_t sockaddr
;
262 isc_stdtime_t expires
;
263 isc_stdtime_t lastage
;
265 * A nonzero 'expires' field indicates that the entry should
266 * persist until that time. This allows entries found
267 * using dns_adb_findaddrinfo() to persist for a limited time
268 * even though they are not necessarily associated with a
272 ISC_LIST(dns_adblameinfo_t
) lameinfo
;
273 ISC_LINK(dns_adbentry_t
) plink
;
277 * Internal functions (and prototypes).
279 static inline dns_adbname_t
*new_adbname(dns_adb_t
*, dns_name_t
*);
280 static inline void free_adbname(dns_adb_t
*, dns_adbname_t
**);
281 static inline dns_adbnamehook_t
*new_adbnamehook(dns_adb_t
*,
283 static inline void free_adbnamehook(dns_adb_t
*, dns_adbnamehook_t
**);
284 static inline dns_adblameinfo_t
*new_adblameinfo(dns_adb_t
*, dns_name_t
*,
286 static inline void free_adblameinfo(dns_adb_t
*, dns_adblameinfo_t
**);
287 static inline dns_adbentry_t
*new_adbentry(dns_adb_t
*);
288 static inline void free_adbentry(dns_adb_t
*, dns_adbentry_t
**);
289 static inline dns_adbfind_t
*new_adbfind(dns_adb_t
*);
290 static inline isc_boolean_t
free_adbfind(dns_adb_t
*, dns_adbfind_t
**);
291 static inline dns_adbaddrinfo_t
*new_adbaddrinfo(dns_adb_t
*, dns_adbentry_t
*,
293 static inline dns_adbfetch_t
*new_adbfetch(dns_adb_t
*);
294 static inline void free_adbfetch(dns_adb_t
*, dns_adbfetch_t
**);
295 static inline dns_adbname_t
*find_name_and_lock(dns_adb_t
*, dns_name_t
*,
296 unsigned int, int *);
297 static inline dns_adbentry_t
*find_entry_and_lock(dns_adb_t
*,
298 isc_sockaddr_t
*, int *,
300 static void dump_adb(dns_adb_t
*, FILE *, isc_boolean_t debug
, isc_stdtime_t
);
301 static void print_dns_name(FILE *, dns_name_t
*);
302 static void print_namehook_list(FILE *, const char *legend
,
303 dns_adbnamehooklist_t
*list
,
306 static void print_find_list(FILE *, dns_adbname_t
*);
307 static void print_fetch_list(FILE *, dns_adbname_t
*);
308 static inline isc_boolean_t
dec_adb_irefcnt(dns_adb_t
*);
309 static inline void inc_adb_irefcnt(dns_adb_t
*);
310 static inline void inc_adb_erefcnt(dns_adb_t
*);
311 static inline void inc_entry_refcnt(dns_adb_t
*, dns_adbentry_t
*,
313 static inline isc_boolean_t
dec_entry_refcnt(dns_adb_t
*, isc_boolean_t
,
314 dns_adbentry_t
*, isc_boolean_t
);
315 static inline void violate_locking_hierarchy(isc_mutex_t
*, isc_mutex_t
*);
316 static isc_boolean_t
clean_namehooks(dns_adb_t
*, dns_adbnamehooklist_t
*);
317 static void clean_target(dns_adb_t
*, dns_name_t
*);
318 static void clean_finds_at_name(dns_adbname_t
*, isc_eventtype_t
, unsigned int);
319 static isc_boolean_t
check_expire_namehooks(dns_adbname_t
*, isc_stdtime_t
);
320 static isc_boolean_t
check_expire_entry(dns_adb_t
*, dns_adbentry_t
**,
322 static void cancel_fetches_at_name(dns_adbname_t
*);
323 static isc_result_t
dbfind_name(dns_adbname_t
*, isc_stdtime_t
,
325 static isc_result_t
fetch_name(dns_adbname_t
*, isc_boolean_t
,
326 unsigned int, isc_counter_t
*qc
,
328 static inline void check_exit(dns_adb_t
*);
329 static void destroy(dns_adb_t
*);
330 static isc_boolean_t
shutdown_names(dns_adb_t
*);
331 static isc_boolean_t
shutdown_entries(dns_adb_t
*);
332 static inline void link_name(dns_adb_t
*, int, dns_adbname_t
*);
333 static inline isc_boolean_t
unlink_name(dns_adb_t
*, dns_adbname_t
*);
334 static inline void link_entry(dns_adb_t
*, int, dns_adbentry_t
*);
335 static inline isc_boolean_t
unlink_entry(dns_adb_t
*, dns_adbentry_t
*);
336 static isc_boolean_t
kill_name(dns_adbname_t
**, isc_eventtype_t
);
337 static void water(void *, int);
338 static void dump_entry(FILE *, dns_adbentry_t
*, isc_boolean_t
, isc_stdtime_t
);
339 static void adjustsrtt(dns_adbaddrinfo_t
*addr
, unsigned int rtt
,
340 unsigned int factor
, isc_stdtime_t now
);
341 static void shutdown_task(isc_task_t
*task
, isc_event_t
*ev
);
344 * MUST NOT overlap DNS_ADBFIND_* flags!
346 #define FIND_EVENT_SENT 0x40000000
347 #define FIND_EVENT_FREED 0x80000000
348 #define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
349 #define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
351 #define NAME_NEEDS_POKE 0x80000000
352 #define NAME_IS_DEAD 0x40000000
353 #define NAME_HINT_OK DNS_ADBFIND_HINTOK
354 #define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
355 #define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
356 #define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
357 #define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
358 #define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
359 #define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
362 * Private flag(s) for entries.
363 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
365 #define ENTRY_IS_DEAD 0x00400000
368 * To the name, address classes are all that really exist. If it has a
369 * V6 address it doesn't care if it came from a AAAA query.
371 #define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
372 #define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
373 #define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
376 * Fetches are broken out into A and AAAA types. In some cases,
377 * however, it makes more sense to test for a particular class of fetches,
378 * like V4 or V6 above.
379 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
380 * are now equal to FETCH_V4 and FETCH_V6, respectively.
382 #define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
383 #define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
384 #define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
385 #define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
386 #define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
389 * Find options and tests to see if there are addresses on the list.
391 #define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
392 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
393 #define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
395 #define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
397 #define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
398 #define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
399 #define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
400 #define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
403 * These are currently used on simple unsigned ints, so they are
404 * not really associated with any particular type.
406 #define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
407 #define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
409 #define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
412 * Find out if the flags on a name (nf) indicate if it is a hint or
413 * glue, and compare this to the appropriate bits set in o, to see if
416 #define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
417 #define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
418 #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
419 #define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
420 ((o) & DNS_ADBFIND_STARTATZONE))
422 #define ENTER_LEVEL ISC_LOG_DEBUG(50)
423 #define EXIT_LEVEL ENTER_LEVEL
424 #define CLEAN_LEVEL ISC_LOG_DEBUG(100)
425 #define DEF_LEVEL ISC_LOG_DEBUG(5)
426 #define NCACHE_LEVEL ISC_LOG_DEBUG(20)
428 #define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
429 (r) == DNS_R_NCACHENXRRSET)
430 #define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
431 (r) == DNS_R_NXRRSET)
432 #define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
433 (r) == DNS_R_NCACHENXDOMAIN)
434 #define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
435 (r) == DNS_R_NXRRSET || \
436 (r) == DNS_R_HINTNXRRSET)
439 * Error state rankings.
442 #define FIND_ERR_SUCCESS 0 /* highest rank */
443 #define FIND_ERR_CANCELED 1
444 #define FIND_ERR_FAILURE 2
445 #define FIND_ERR_NXDOMAIN 3
446 #define FIND_ERR_NXRRSET 4
447 #define FIND_ERR_UNEXPECTED 5
448 #define FIND_ERR_NOTFOUND 6
449 #define FIND_ERR_MAX 7
451 static const char *errnames
[] = {
461 #define NEWERR(old, new) (ISC_MIN((old), (new)))
463 static isc_result_t find_err_map
[FIND_ERR_MAX
] = {
470 ISC_R_NOTFOUND
/* not YET found */
474 DP(int level
, const char *format
, ...) ISC_FORMAT_PRINTF(2, 3);
477 DP(int level
, const char *format
, ...) {
480 va_start(args
, format
);
481 isc_log_vwrite(dns_lctx
,
482 DNS_LOGCATEGORY_DATABASE
, DNS_LOGMODULE_ADB
,
483 level
, format
, args
);
488 * Increment resolver-related statistics counters.
491 inc_stats(dns_adb_t
*adb
, isc_statscounter_t counter
) {
492 if (adb
->view
->resstats
!= NULL
)
493 isc_stats_increment(adb
->view
->resstats
, counter
);
497 * Set adb-related statistics counters.
500 set_adbstat(dns_adb_t
*adb
, isc_uint64_t val
, isc_statscounter_t counter
) {
501 if (adb
->view
->adbstats
!= NULL
)
502 isc_stats_set(adb
->view
->adbstats
, val
, counter
);
506 dec_adbstats(dns_adb_t
*adb
, isc_statscounter_t counter
) {
507 if (adb
->view
->adbstats
!= NULL
)
508 isc_stats_decrement(adb
->view
->adbstats
, counter
);
512 inc_adbstats(dns_adb_t
*adb
, isc_statscounter_t counter
) {
513 if (adb
->view
->adbstats
!= NULL
)
514 isc_stats_increment(adb
->view
->adbstats
, counter
);
517 static inline dns_ttl_t
518 ttlclamp(dns_ttl_t ttl
) {
519 if (ttl
< ADB_CACHE_MINIMUM
)
520 ttl
= ADB_CACHE_MINIMUM
;
521 if (ttl
> ADB_CACHE_MAXIMUM
)
522 ttl
= ADB_CACHE_MAXIMUM
;
528 * Hashing is most efficient if the number of buckets is prime.
529 * The sequence below is the closest previous primes to 2^n and
530 * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
531 * no longer grow beyond 2^28 entries.)
533 static const unsigned nbuckets
[] = { 1021, 1531, 2039, 3067, 4093, 6143,
534 8191, 12281, 16381, 24571, 32749,
535 49193, 65521, 98299, 131071, 199603,
536 262139, 393209, 524287, 768431, 1048573,
537 1572853, 2097143, 3145721, 4194301,
538 6291449, 8388593, 12582893, 16777213,
539 25165813, 33554393, 50331599, 67108859,
540 100663291, 134217689, 201326557,
544 grow_entries(isc_task_t
*task
, isc_event_t
*ev
) {
547 dns_adbentrylist_t
*newdeadentries
= NULL
;
548 dns_adbentrylist_t
*newentries
= NULL
;
549 isc_boolean_t
*newentry_sd
= NULL
;
550 isc_mutex_t
*newentrylocks
= NULL
;
552 unsigned int *newentry_refcnt
= NULL
;
553 unsigned int i
, n
, bucket
;
556 INSIST(DNS_ADB_VALID(adb
));
560 result
= isc_task_beginexclusive(task
);
561 if (result
!= ISC_R_SUCCESS
)
565 while (nbuckets
[i
] != 0 && adb
->nentries
>= nbuckets
[i
])
567 if (nbuckets
[i
] != 0)
572 DP(ISC_LOG_INFO
, "adb: grow_entries to %u starting", n
);
575 * Are we shutting down?
577 for (i
= 0; i
< adb
->nentries
; i
++)
578 if (adb
->entry_sd
[i
])
582 * Grab all the resources we need.
584 newentries
= isc_mem_get(adb
->mctx
, sizeof(*newentries
) * n
);
585 newdeadentries
= isc_mem_get(adb
->mctx
, sizeof(*newdeadentries
) * n
);
586 newentrylocks
= isc_mem_get(adb
->mctx
, sizeof(*newentrylocks
) * n
);
587 newentry_sd
= isc_mem_get(adb
->mctx
, sizeof(*newentry_sd
) * n
);
588 newentry_refcnt
= isc_mem_get(adb
->mctx
, sizeof(*newentry_refcnt
) * n
);
589 if (newentries
== NULL
|| newdeadentries
== NULL
||
590 newentrylocks
== NULL
|| newentry_sd
== NULL
||
591 newentry_refcnt
== NULL
)
595 * Initialise the new resources.
597 result
= isc_mutexblock_init(newentrylocks
, n
);
598 if (result
!= ISC_R_SUCCESS
)
601 for (i
= 0; i
< n
; i
++) {
602 ISC_LIST_INIT(newentries
[i
]);
603 ISC_LIST_INIT(newdeadentries
[i
]);
604 newentry_sd
[i
] = ISC_FALSE
;
605 newentry_refcnt
[i
] = 0;
610 * Move entries to new arrays.
612 for (i
= 0; i
< adb
->nentries
; i
++) {
613 e
= ISC_LIST_HEAD(adb
->entries
[i
]);
615 ISC_LIST_UNLINK(adb
->entries
[i
], e
, plink
);
616 bucket
= isc_sockaddr_hash(&e
->sockaddr
, ISC_TRUE
) % n
;
617 e
->lock_bucket
= bucket
;
618 ISC_LIST_APPEND(newentries
[bucket
], e
, plink
);
619 INSIST(adb
->entry_refcnt
[i
] > 0);
620 adb
->entry_refcnt
[i
]--;
621 newentry_refcnt
[bucket
]++;
622 e
= ISC_LIST_HEAD(adb
->entries
[i
]);
624 e
= ISC_LIST_HEAD(adb
->deadentries
[i
]);
626 ISC_LIST_UNLINK(adb
->deadentries
[i
], e
, plink
);
627 bucket
= isc_sockaddr_hash(&e
->sockaddr
, ISC_TRUE
) % n
;
628 e
->lock_bucket
= bucket
;
629 ISC_LIST_APPEND(newdeadentries
[bucket
], e
, plink
);
630 INSIST(adb
->entry_refcnt
[i
] > 0);
631 adb
->entry_refcnt
[i
]--;
632 newentry_refcnt
[bucket
]++;
633 e
= ISC_LIST_HEAD(adb
->deadentries
[i
]);
635 INSIST(adb
->entry_refcnt
[i
] == 0);
640 * Cleanup old resources.
642 DESTROYMUTEXBLOCK(adb
->entrylocks
, adb
->nentries
);
643 isc_mem_put(adb
->mctx
, adb
->entries
,
644 sizeof(*adb
->entries
) * adb
->nentries
);
645 isc_mem_put(adb
->mctx
, adb
->deadentries
,
646 sizeof(*adb
->deadentries
) * adb
->nentries
);
647 isc_mem_put(adb
->mctx
, adb
->entrylocks
,
648 sizeof(*adb
->entrylocks
) * adb
->nentries
);
649 isc_mem_put(adb
->mctx
, adb
->entry_sd
,
650 sizeof(*adb
->entry_sd
) * adb
->nentries
);
651 isc_mem_put(adb
->mctx
, adb
->entry_refcnt
,
652 sizeof(*adb
->entry_refcnt
) * adb
->nentries
);
655 * Install new resources.
657 adb
->entries
= newentries
;
658 adb
->deadentries
= newdeadentries
;
659 adb
->entrylocks
= newentrylocks
;
660 adb
->entry_sd
= newentry_sd
;
661 adb
->entry_refcnt
= newentry_refcnt
;
664 set_adbstat(adb
, adb
->nentries
, dns_adbstats_nentries
);
667 * Only on success do we set adb->growentries_sent to ISC_FALSE.
668 * This will prevent us being continuously being called on error.
670 adb
->growentries_sent
= ISC_FALSE
;
674 if (newentries
!= NULL
)
675 isc_mem_put(adb
->mctx
, newentries
,
676 sizeof(*newentries
) * n
);
677 if (newdeadentries
!= NULL
)
678 isc_mem_put(adb
->mctx
, newdeadentries
,
679 sizeof(*newdeadentries
) * n
);
680 if (newentrylocks
!= NULL
)
681 isc_mem_put(adb
->mctx
, newentrylocks
,
682 sizeof(*newentrylocks
) * n
);
683 if (newentry_sd
!= NULL
)
684 isc_mem_put(adb
->mctx
, newentry_sd
,
685 sizeof(*newentry_sd
) * n
);
686 if (newentry_refcnt
!= NULL
)
687 isc_mem_put(adb
->mctx
, newentry_refcnt
,
688 sizeof(*newentry_refcnt
) * n
);
690 isc_task_endexclusive(task
);
694 if (dec_adb_irefcnt(adb
))
697 DP(ISC_LOG_INFO
, "adb: grow_entries finished");
701 grow_names(isc_task_t
*task
, isc_event_t
*ev
) {
704 dns_adbnamelist_t
*newdeadnames
= NULL
;
705 dns_adbnamelist_t
*newnames
= NULL
;
706 isc_boolean_t
*newname_sd
= NULL
;
707 isc_mutex_t
*newnamelocks
= NULL
;
709 unsigned int *newname_refcnt
= NULL
;
710 unsigned int i
, n
, bucket
;
713 INSIST(DNS_ADB_VALID(adb
));
717 result
= isc_task_beginexclusive(task
);
718 if (result
!= ISC_R_SUCCESS
)
722 while (nbuckets
[i
] != 0 && adb
->nnames
>= nbuckets
[i
])
724 if (nbuckets
[i
] != 0)
729 DP(ISC_LOG_INFO
, "adb: grow_names to %u starting", n
);
732 * Are we shutting down?
734 for (i
= 0; i
< adb
->nnames
; i
++)
739 * Grab all the resources we need.
741 newnames
= isc_mem_get(adb
->mctx
, sizeof(*newnames
) * n
);
742 newdeadnames
= isc_mem_get(adb
->mctx
, sizeof(*newdeadnames
) * n
);
743 newnamelocks
= isc_mem_get(adb
->mctx
, sizeof(*newnamelocks
) * n
);
744 newname_sd
= isc_mem_get(adb
->mctx
, sizeof(*newname_sd
) * n
);
745 newname_refcnt
= isc_mem_get(adb
->mctx
, sizeof(*newname_refcnt
) * n
);
746 if (newnames
== NULL
|| newdeadnames
== NULL
||
747 newnamelocks
== NULL
|| newname_sd
== NULL
||
748 newname_refcnt
== NULL
)
752 * Initialise the new resources.
754 result
= isc_mutexblock_init(newnamelocks
, n
);
755 if (result
!= ISC_R_SUCCESS
)
758 for (i
= 0; i
< n
; i
++) {
759 ISC_LIST_INIT(newnames
[i
]);
760 ISC_LIST_INIT(newdeadnames
[i
]);
761 newname_sd
[i
] = ISC_FALSE
;
762 newname_refcnt
[i
] = 0;
767 * Move names to new arrays.
769 for (i
= 0; i
< adb
->nnames
; i
++) {
770 name
= ISC_LIST_HEAD(adb
->names
[i
]);
771 while (name
!= NULL
) {
772 ISC_LIST_UNLINK(adb
->names
[i
], name
, plink
);
773 bucket
= dns_name_fullhash(&name
->name
, ISC_TRUE
) % n
;
774 name
->lock_bucket
= bucket
;
775 ISC_LIST_APPEND(newnames
[bucket
], name
, plink
);
776 INSIST(adb
->name_refcnt
[i
] > 0);
777 adb
->name_refcnt
[i
]--;
778 newname_refcnt
[bucket
]++;
779 name
= ISC_LIST_HEAD(adb
->names
[i
]);
781 name
= ISC_LIST_HEAD(adb
->deadnames
[i
]);
782 while (name
!= NULL
) {
783 ISC_LIST_UNLINK(adb
->deadnames
[i
], name
, plink
);
784 bucket
= dns_name_fullhash(&name
->name
, ISC_TRUE
) % n
;
785 name
->lock_bucket
= bucket
;
786 ISC_LIST_APPEND(newdeadnames
[bucket
], name
, plink
);
787 INSIST(adb
->name_refcnt
[i
] > 0);
788 adb
->name_refcnt
[i
]--;
789 newname_refcnt
[bucket
]++;
790 name
= ISC_LIST_HEAD(adb
->deadnames
[i
]);
792 INSIST(adb
->name_refcnt
[i
] == 0);
797 * Cleanup old resources.
799 DESTROYMUTEXBLOCK(adb
->namelocks
, adb
->nnames
);
800 isc_mem_put(adb
->mctx
, adb
->names
,
801 sizeof(*adb
->names
) * adb
->nnames
);
802 isc_mem_put(adb
->mctx
, adb
->deadnames
,
803 sizeof(*adb
->deadnames
) * adb
->nnames
);
804 isc_mem_put(adb
->mctx
, adb
->namelocks
,
805 sizeof(*adb
->namelocks
) * adb
->nnames
);
806 isc_mem_put(adb
->mctx
, adb
->name_sd
,
807 sizeof(*adb
->name_sd
) * adb
->nnames
);
808 isc_mem_put(adb
->mctx
, adb
->name_refcnt
,
809 sizeof(*adb
->name_refcnt
) * adb
->nnames
);
812 * Install new resources.
814 adb
->names
= newnames
;
815 adb
->deadnames
= newdeadnames
;
816 adb
->namelocks
= newnamelocks
;
817 adb
->name_sd
= newname_sd
;
818 adb
->name_refcnt
= newname_refcnt
;
821 set_adbstat(adb
, adb
->nnames
, dns_adbstats_nnames
);
824 * Only on success do we set adb->grownames_sent to ISC_FALSE.
825 * This will prevent us being continuously being called on error.
827 adb
->grownames_sent
= ISC_FALSE
;
831 if (newnames
!= NULL
)
832 isc_mem_put(adb
->mctx
, newnames
, sizeof(*newnames
) * n
);
833 if (newdeadnames
!= NULL
)
834 isc_mem_put(adb
->mctx
, newdeadnames
, sizeof(*newdeadnames
) * n
);
835 if (newnamelocks
!= NULL
)
836 isc_mem_put(adb
->mctx
, newnamelocks
, sizeof(*newnamelocks
) * n
);
837 if (newname_sd
!= NULL
)
838 isc_mem_put(adb
->mctx
, newname_sd
, sizeof(*newname_sd
) * n
);
839 if (newname_refcnt
!= NULL
)
840 isc_mem_put(adb
->mctx
, newname_refcnt
,
841 sizeof(*newname_refcnt
) * n
);
843 isc_task_endexclusive(task
);
847 if (dec_adb_irefcnt(adb
))
850 DP(ISC_LOG_INFO
, "adb: grow_names finished");
854 * Requires the adbname bucket be locked and that no entry buckets be locked.
856 * This code handles A and AAAA rdatasets only.
859 import_rdataset(dns_adbname_t
*adbname
, dns_rdataset_t
*rdataset
,
864 dns_adbnamehook_t
*nh
;
865 dns_adbnamehook_t
*anh
;
866 dns_rdata_t rdata
= DNS_RDATA_INIT
;
868 struct in6_addr in6a
;
869 isc_sockaddr_t sockaddr
;
870 dns_adbentry_t
*foundentry
; /* NO CLEAN UP! */
872 isc_boolean_t new_addresses_added
;
873 dns_rdatatype_t rdtype
;
874 unsigned int findoptions
;
875 dns_adbnamehooklist_t
*hookhead
;
877 INSIST(DNS_ADBNAME_VALID(adbname
));
879 INSIST(DNS_ADB_VALID(adb
));
881 rdtype
= rdataset
->type
;
882 INSIST((rdtype
== dns_rdatatype_a
) || (rdtype
== dns_rdatatype_aaaa
));
883 if (rdtype
== dns_rdatatype_a
)
884 findoptions
= DNS_ADBFIND_INET
;
886 findoptions
= DNS_ADBFIND_INET6
;
888 addr_bucket
= DNS_ADB_INVALIDBUCKET
;
889 new_addresses_added
= ISC_FALSE
;
892 result
= dns_rdataset_first(rdataset
);
893 while (result
== ISC_R_SUCCESS
) {
894 dns_rdata_reset(&rdata
);
895 dns_rdataset_current(rdataset
, &rdata
);
896 if (rdtype
== dns_rdatatype_a
) {
897 INSIST(rdata
.length
== 4);
898 memmove(&ina
.s_addr
, rdata
.data
, 4);
899 isc_sockaddr_fromin(&sockaddr
, &ina
, 0);
900 hookhead
= &adbname
->v4
;
902 INSIST(rdata
.length
== 16);
903 memmove(in6a
.s6_addr
, rdata
.data
, 16);
904 isc_sockaddr_fromin6(&sockaddr
, &in6a
, 0);
905 hookhead
= &adbname
->v6
;
909 nh
= new_adbnamehook(adb
, NULL
);
911 adbname
->partial_result
|= findoptions
;
912 result
= ISC_R_NOMEMORY
;
916 foundentry
= find_entry_and_lock(adb
, &sockaddr
, &addr_bucket
,
918 if (foundentry
== NULL
) {
919 dns_adbentry_t
*entry
;
921 entry
= new_adbentry(adb
);
923 adbname
->partial_result
|= findoptions
;
924 result
= ISC_R_NOMEMORY
;
928 entry
->sockaddr
= sockaddr
;
933 link_entry(adb
, addr_bucket
, entry
);
935 for (anh
= ISC_LIST_HEAD(*hookhead
);
937 anh
= ISC_LIST_NEXT(anh
, plink
))
938 if (anh
->entry
== foundentry
)
941 foundentry
->refcnt
++;
942 nh
->entry
= foundentry
;
944 free_adbnamehook(adb
, &nh
);
947 new_addresses_added
= ISC_TRUE
;
949 ISC_LIST_APPEND(*hookhead
, nh
, plink
);
951 result
= dns_rdataset_next(rdataset
);
956 free_adbnamehook(adb
, &nh
);
958 if (addr_bucket
!= DNS_ADB_INVALIDBUCKET
)
959 UNLOCK(&adb
->entrylocks
[addr_bucket
]);
961 if (rdataset
->trust
== dns_trust_glue
||
962 rdataset
->trust
== dns_trust_additional
)
963 rdataset
->ttl
= ADB_CACHE_MINIMUM
;
964 else if (rdataset
->trust
== dns_trust_ultimate
)
967 rdataset
->ttl
= ttlclamp(rdataset
->ttl
);
969 if (rdtype
== dns_rdatatype_a
) {
970 DP(NCACHE_LEVEL
, "expire_v4 set to MIN(%u,%u) import_rdataset",
971 adbname
->expire_v4
, now
+ rdataset
->ttl
);
972 adbname
->expire_v4
= ISC_MIN(adbname
->expire_v4
,
973 ISC_MIN(now
+ ADB_ENTRY_WINDOW
,
974 now
+ rdataset
->ttl
));
976 DP(NCACHE_LEVEL
, "expire_v6 set to MIN(%u,%u) import_rdataset",
977 adbname
->expire_v6
, now
+ rdataset
->ttl
);
978 adbname
->expire_v6
= ISC_MIN(adbname
->expire_v6
,
979 ISC_MIN(now
+ ADB_ENTRY_WINDOW
,
980 now
+ rdataset
->ttl
));
983 if (new_addresses_added
) {
985 * Lie a little here. This is more or less so code that cares
986 * can find out if any new information was added or not.
988 return (ISC_R_SUCCESS
);
995 * Requires the name's bucket be locked.
998 kill_name(dns_adbname_t
**n
, isc_eventtype_t ev
) {
1000 isc_boolean_t result
= ISC_FALSE
;
1001 isc_boolean_t result4
, result6
;
1008 INSIST(DNS_ADBNAME_VALID(name
));
1010 INSIST(DNS_ADB_VALID(adb
));
1012 DP(DEF_LEVEL
, "killing name %p", name
);
1015 * If we're dead already, just check to see if we should go
1018 if (NAME_DEAD(name
) && !NAME_FETCH(name
)) {
1019 result
= unlink_name(adb
, name
);
1020 free_adbname(adb
, &name
);
1022 result
= dec_adb_irefcnt(adb
);
1027 * Clean up the name's various lists. These two are destructive
1028 * in that they will always empty the list.
1030 clean_finds_at_name(name
, ev
, DNS_ADBFIND_ADDRESSMASK
);
1031 result4
= clean_namehooks(adb
, &name
->v4
);
1032 result6
= clean_namehooks(adb
, &name
->v6
);
1033 clean_target(adb
, &name
->target
);
1034 result
= ISC_TF(result4
|| result6
);
1037 * If fetches are running, cancel them. If none are running, we can
1038 * just kill the name here.
1040 if (!NAME_FETCH(name
)) {
1041 INSIST(result
== ISC_FALSE
);
1042 result
= unlink_name(adb
, name
);
1043 free_adbname(adb
, &name
);
1045 result
= dec_adb_irefcnt(adb
);
1047 cancel_fetches_at_name(name
);
1048 if (!NAME_DEAD(name
)) {
1049 bucket
= name
->lock_bucket
;
1050 ISC_LIST_UNLINK(adb
->names
[bucket
], name
, plink
);
1051 ISC_LIST_APPEND(adb
->deadnames
[bucket
], name
, plink
);
1052 name
->flags
|= NAME_IS_DEAD
;
1059 * Requires the name's bucket be locked and no entry buckets be locked.
1061 static isc_boolean_t
1062 check_expire_namehooks(dns_adbname_t
*name
, isc_stdtime_t now
) {
1064 isc_boolean_t result4
= ISC_FALSE
;
1065 isc_boolean_t result6
= ISC_FALSE
;
1067 INSIST(DNS_ADBNAME_VALID(name
));
1069 INSIST(DNS_ADB_VALID(adb
));
1072 * Check to see if we need to remove the v4 addresses
1074 if (!NAME_FETCH_V4(name
) && EXPIRE_OK(name
->expire_v4
, now
)) {
1075 if (NAME_HAS_V4(name
)) {
1076 DP(DEF_LEVEL
, "expiring v4 for name %p", name
);
1077 result4
= clean_namehooks(adb
, &name
->v4
);
1078 name
->partial_result
&= ~DNS_ADBFIND_INET
;
1080 name
->expire_v4
= INT_MAX
;
1081 name
->fetch_err
= FIND_ERR_UNEXPECTED
;
1085 * Check to see if we need to remove the v6 addresses
1087 if (!NAME_FETCH_V6(name
) && EXPIRE_OK(name
->expire_v6
, now
)) {
1088 if (NAME_HAS_V6(name
)) {
1089 DP(DEF_LEVEL
, "expiring v6 for name %p", name
);
1090 result6
= clean_namehooks(adb
, &name
->v6
);
1091 name
->partial_result
&= ~DNS_ADBFIND_INET6
;
1093 name
->expire_v6
= INT_MAX
;
1094 name
->fetch6_err
= FIND_ERR_UNEXPECTED
;
1098 * Check to see if we need to remove the alias target.
1100 if (EXPIRE_OK(name
->expire_target
, now
)) {
1101 clean_target(adb
, &name
->target
);
1102 name
->expire_target
= INT_MAX
;
1104 return (ISC_TF(result4
|| result6
));
1108 * Requires the name's bucket be locked.
1111 link_name(dns_adb_t
*adb
, int bucket
, dns_adbname_t
*name
) {
1112 INSIST(name
->lock_bucket
== DNS_ADB_INVALIDBUCKET
);
1114 ISC_LIST_PREPEND(adb
->names
[bucket
], name
, plink
);
1115 name
->lock_bucket
= bucket
;
1116 adb
->name_refcnt
[bucket
]++;
1120 * Requires the name's bucket be locked.
1122 static inline isc_boolean_t
1123 unlink_name(dns_adb_t
*adb
, dns_adbname_t
*name
) {
1125 isc_boolean_t result
= ISC_FALSE
;
1127 bucket
= name
->lock_bucket
;
1128 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
1130 if (NAME_DEAD(name
))
1131 ISC_LIST_UNLINK(adb
->deadnames
[bucket
], name
, plink
);
1133 ISC_LIST_UNLINK(adb
->names
[bucket
], name
, plink
);
1134 name
->lock_bucket
= DNS_ADB_INVALIDBUCKET
;
1135 INSIST(adb
->name_refcnt
[bucket
] > 0);
1136 adb
->name_refcnt
[bucket
]--;
1137 if (adb
->name_sd
[bucket
] && adb
->name_refcnt
[bucket
] == 0)
1143 * Requires the entry's bucket be locked.
1146 link_entry(dns_adb_t
*adb
, int bucket
, dns_adbentry_t
*entry
) {
1150 if (isc_mem_isovermem(adb
->mctx
)) {
1151 for (i
= 0; i
< 2; i
++) {
1152 e
= ISC_LIST_TAIL(adb
->entries
[bucket
]);
1155 if (e
->refcnt
== 0) {
1156 unlink_entry(adb
, e
);
1157 free_adbentry(adb
, &e
);
1160 INSIST((e
->flags
& ENTRY_IS_DEAD
) == 0);
1161 e
->flags
|= ENTRY_IS_DEAD
;
1162 ISC_LIST_UNLINK(adb
->entries
[bucket
], e
, plink
);
1163 ISC_LIST_PREPEND(adb
->deadentries
[bucket
], e
, plink
);
1167 ISC_LIST_PREPEND(adb
->entries
[bucket
], entry
, plink
);
1168 entry
->lock_bucket
= bucket
;
1169 adb
->entry_refcnt
[bucket
]++;
1173 * Requires the entry's bucket be locked.
1175 static inline isc_boolean_t
1176 unlink_entry(dns_adb_t
*adb
, dns_adbentry_t
*entry
) {
1178 isc_boolean_t result
= ISC_FALSE
;
1180 bucket
= entry
->lock_bucket
;
1181 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
1183 if ((entry
->flags
& ENTRY_IS_DEAD
) != 0)
1184 ISC_LIST_UNLINK(adb
->deadentries
[bucket
], entry
, plink
);
1186 ISC_LIST_UNLINK(adb
->entries
[bucket
], entry
, plink
);
1187 entry
->lock_bucket
= DNS_ADB_INVALIDBUCKET
;
1188 INSIST(adb
->entry_refcnt
[bucket
] > 0);
1189 adb
->entry_refcnt
[bucket
]--;
1190 if (adb
->entry_sd
[bucket
] && adb
->entry_refcnt
[bucket
] == 0)
1196 violate_locking_hierarchy(isc_mutex_t
*have
, isc_mutex_t
*want
) {
1197 if (isc_mutex_trylock(want
) != ISC_R_SUCCESS
) {
1205 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1206 * checked after calling this function.
1208 static isc_boolean_t
1209 shutdown_names(dns_adb_t
*adb
) {
1210 unsigned int bucket
;
1211 isc_boolean_t result
= ISC_FALSE
;
1212 dns_adbname_t
*name
;
1213 dns_adbname_t
*next_name
;
1215 for (bucket
= 0; bucket
< adb
->nnames
; bucket
++) {
1216 LOCK(&adb
->namelocks
[bucket
]);
1217 adb
->name_sd
[bucket
] = ISC_TRUE
;
1219 name
= ISC_LIST_HEAD(adb
->names
[bucket
]);
1222 * This bucket has no names. We must decrement the
1223 * irefcnt ourselves, since it will not be
1224 * automatically triggered by a name being unlinked.
1226 INSIST(result
== ISC_FALSE
);
1227 result
= dec_adb_irefcnt(adb
);
1230 * Run through the list. For each name, clean up finds
1231 * found there, and cancel any fetches running. When
1232 * all the fetches are canceled, the name will destroy
1235 while (name
!= NULL
) {
1236 next_name
= ISC_LIST_NEXT(name
, plink
);
1237 INSIST(result
== ISC_FALSE
);
1238 result
= kill_name(&name
,
1239 DNS_EVENT_ADBSHUTDOWN
);
1244 UNLOCK(&adb
->namelocks
[bucket
]);
1250 * The ADB _MUST_ be locked before calling. Also, exit conditions must be
1251 * checked after calling this function.
1253 static isc_boolean_t
1254 shutdown_entries(dns_adb_t
*adb
) {
1255 unsigned int bucket
;
1256 isc_boolean_t result
= ISC_FALSE
;
1257 dns_adbentry_t
*entry
;
1258 dns_adbentry_t
*next_entry
;
1260 for (bucket
= 0; bucket
< adb
->nentries
; bucket
++) {
1261 LOCK(&adb
->entrylocks
[bucket
]);
1262 adb
->entry_sd
[bucket
] = ISC_TRUE
;
1264 entry
= ISC_LIST_HEAD(adb
->entries
[bucket
]);
1265 if (adb
->entry_refcnt
[bucket
] == 0) {
1267 * This bucket has no entries. We must decrement the
1268 * irefcnt ourselves, since it will not be
1269 * automatically triggered by an entry being unlinked.
1271 result
= dec_adb_irefcnt(adb
);
1274 * Run through the list. Cleanup any entries not
1275 * associated with names, and which are not in use.
1277 while (entry
!= NULL
) {
1278 next_entry
= ISC_LIST_NEXT(entry
, plink
);
1279 if (entry
->refcnt
== 0 &&
1280 entry
->expires
!= 0) {
1281 result
= unlink_entry(adb
, entry
);
1282 free_adbentry(adb
, &entry
);
1284 result
= dec_adb_irefcnt(adb
);
1290 UNLOCK(&adb
->entrylocks
[bucket
]);
1296 * Name bucket must be locked
1299 cancel_fetches_at_name(dns_adbname_t
*name
) {
1300 if (NAME_FETCH_A(name
))
1301 dns_resolver_cancelfetch(name
->fetch_a
->fetch
);
1303 if (NAME_FETCH_AAAA(name
))
1304 dns_resolver_cancelfetch(name
->fetch_aaaa
->fetch
);
1308 * Assumes the name bucket is locked.
1310 static isc_boolean_t
1311 clean_namehooks(dns_adb_t
*adb
, dns_adbnamehooklist_t
*namehooks
) {
1312 dns_adbentry_t
*entry
;
1313 dns_adbnamehook_t
*namehook
;
1315 isc_boolean_t result
= ISC_FALSE
;
1316 isc_boolean_t overmem
= isc_mem_isovermem(adb
->mctx
);
1318 addr_bucket
= DNS_ADB_INVALIDBUCKET
;
1319 namehook
= ISC_LIST_HEAD(*namehooks
);
1320 while (namehook
!= NULL
) {
1321 INSIST(DNS_ADBNAMEHOOK_VALID(namehook
));
1324 * Clean up the entry if needed.
1326 entry
= namehook
->entry
;
1327 if (entry
!= NULL
) {
1328 INSIST(DNS_ADBENTRY_VALID(entry
));
1330 if (addr_bucket
!= entry
->lock_bucket
) {
1331 if (addr_bucket
!= DNS_ADB_INVALIDBUCKET
)
1332 UNLOCK(&adb
->entrylocks
[addr_bucket
]);
1333 addr_bucket
= entry
->lock_bucket
;
1334 INSIST(addr_bucket
!= DNS_ADB_INVALIDBUCKET
);
1335 LOCK(&adb
->entrylocks
[addr_bucket
]);
1338 result
= dec_entry_refcnt(adb
, overmem
, entry
,
1345 namehook
->entry
= NULL
;
1346 ISC_LIST_UNLINK(*namehooks
, namehook
, plink
);
1347 free_adbnamehook(adb
, &namehook
);
1349 namehook
= ISC_LIST_HEAD(*namehooks
);
1352 if (addr_bucket
!= DNS_ADB_INVALIDBUCKET
)
1353 UNLOCK(&adb
->entrylocks
[addr_bucket
]);
1358 clean_target(dns_adb_t
*adb
, dns_name_t
*target
) {
1359 if (dns_name_countlabels(target
) > 0) {
1360 dns_name_free(target
, adb
->mctx
);
1361 dns_name_init(target
, NULL
);
1366 set_target(dns_adb_t
*adb
, dns_name_t
*name
, dns_name_t
*fname
,
1367 dns_rdataset_t
*rdataset
, dns_name_t
*target
)
1369 isc_result_t result
;
1370 dns_namereln_t namereln
;
1371 unsigned int nlabels
;
1373 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1374 dns_fixedname_t fixed1
, fixed2
;
1375 dns_name_t
*prefix
, *new_target
;
1377 REQUIRE(dns_name_countlabels(target
) == 0);
1379 if (rdataset
->type
== dns_rdatatype_cname
) {
1380 dns_rdata_cname_t cname
;
1383 * Copy the CNAME's target into the target name.
1385 result
= dns_rdataset_first(rdataset
);
1386 if (result
!= ISC_R_SUCCESS
)
1388 dns_rdataset_current(rdataset
, &rdata
);
1389 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
1390 if (result
!= ISC_R_SUCCESS
)
1392 result
= dns_name_dup(&cname
.cname
, adb
->mctx
, target
);
1393 dns_rdata_freestruct(&cname
);
1394 if (result
!= ISC_R_SUCCESS
)
1397 dns_rdata_dname_t dname
;
1399 INSIST(rdataset
->type
== dns_rdatatype_dname
);
1400 namereln
= dns_name_fullcompare(name
, fname
, &order
, &nlabels
);
1401 INSIST(namereln
== dns_namereln_subdomain
);
1403 * Get the target name of the DNAME.
1405 result
= dns_rdataset_first(rdataset
);
1406 if (result
!= ISC_R_SUCCESS
)
1408 dns_rdataset_current(rdataset
, &rdata
);
1409 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
1410 if (result
!= ISC_R_SUCCESS
)
1413 * Construct the new target name.
1415 dns_fixedname_init(&fixed1
);
1416 prefix
= dns_fixedname_name(&fixed1
);
1417 dns_fixedname_init(&fixed2
);
1418 new_target
= dns_fixedname_name(&fixed2
);
1419 dns_name_split(name
, nlabels
, prefix
, NULL
);
1420 result
= dns_name_concatenate(prefix
, &dname
.dname
, new_target
,
1422 dns_rdata_freestruct(&dname
);
1423 if (result
!= ISC_R_SUCCESS
)
1425 result
= dns_name_dup(new_target
, adb
->mctx
, target
);
1426 if (result
!= ISC_R_SUCCESS
)
1430 return (ISC_R_SUCCESS
);
1434 * Assumes nothing is locked, since this is called by the client.
1437 event_free(isc_event_t
*event
) {
1438 dns_adbfind_t
*find
;
1440 INSIST(event
!= NULL
);
1441 find
= event
->ev_destroy_arg
;
1442 INSIST(DNS_ADBFIND_VALID(find
));
1445 find
->flags
|= FIND_EVENT_FREED
;
1446 event
->ev_destroy_arg
= NULL
;
1447 UNLOCK(&find
->lock
);
1451 * Assumes the name bucket is locked.
1454 clean_finds_at_name(dns_adbname_t
*name
, isc_eventtype_t evtype
,
1459 dns_adbfind_t
*find
;
1460 dns_adbfind_t
*next_find
;
1461 isc_boolean_t process
;
1462 unsigned int wanted
, notify
;
1465 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1466 name
, evtype
, addrs
);
1468 find
= ISC_LIST_HEAD(name
->finds
);
1469 while (find
!= NULL
) {
1471 next_find
= ISC_LIST_NEXT(find
, plink
);
1473 process
= ISC_FALSE
;
1474 wanted
= find
->flags
& DNS_ADBFIND_ADDRESSMASK
;
1475 notify
= wanted
& addrs
;
1478 case DNS_EVENT_ADBMOREADDRESSES
:
1479 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1480 if ((notify
) != 0) {
1481 find
->flags
&= ~addrs
;
1485 case DNS_EVENT_ADBNOMOREADDRESSES
:
1486 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1487 find
->flags
&= ~addrs
;
1488 wanted
= find
->flags
& DNS_ADBFIND_ADDRESSMASK
;
1493 find
->flags
&= ~addrs
;
1498 DP(DEF_LEVEL
, "cfan: processing find %p", find
);
1500 * Unlink the find from the name, letting the caller
1501 * call dns_adb_destroyfind() on it to clean it up
1504 ISC_LIST_UNLINK(name
->finds
, find
, plink
);
1505 find
->adbname
= NULL
;
1506 find
->name_bucket
= DNS_ADB_INVALIDBUCKET
;
1508 INSIST(!FIND_EVENTSENT(find
));
1511 task
= ev
->ev_sender
;
1512 ev
->ev_sender
= find
;
1513 find
->result_v4
= find_err_map
[name
->fetch_err
];
1514 find
->result_v6
= find_err_map
[name
->fetch6_err
];
1515 ev
->ev_type
= evtype
;
1516 ev
->ev_destroy
= event_free
;
1517 ev
->ev_destroy_arg
= find
;
1520 "sending event %p to task %p for find %p",
1523 isc_task_sendanddetach(&task
, (isc_event_t
**)&ev
);
1525 DP(DEF_LEVEL
, "cfan: skipping find %p", find
);
1528 UNLOCK(&find
->lock
);
1532 DP(ENTER_LEVEL
, "EXIT clean_finds_at_name, name %p", name
);
1536 check_exit(dns_adb_t
*adb
) {
1539 * The caller must be holding the adb lock.
1541 if (adb
->shutting_down
) {
1543 * If there aren't any external references either, we're
1544 * done. Send the control event to initiate shutdown.
1546 INSIST(!adb
->cevent_out
); /* Sanity check. */
1547 ISC_EVENT_INIT(&adb
->cevent
, sizeof(adb
->cevent
), 0, NULL
,
1548 DNS_EVENT_ADBCONTROL
, shutdown_task
, adb
,
1550 event
= &adb
->cevent
;
1551 isc_task_send(adb
->task
, &event
);
1552 adb
->cevent_out
= ISC_TRUE
;
1556 static inline isc_boolean_t
1557 dec_adb_irefcnt(dns_adb_t
*adb
) {
1560 isc_boolean_t result
= ISC_FALSE
;
1562 LOCK(&adb
->reflock
);
1564 INSIST(adb
->irefcnt
> 0);
1567 if (adb
->irefcnt
== 0) {
1568 event
= ISC_LIST_HEAD(adb
->whenshutdown
);
1569 while (event
!= NULL
) {
1570 ISC_LIST_UNLINK(adb
->whenshutdown
, event
, ev_link
);
1571 etask
= event
->ev_sender
;
1572 event
->ev_sender
= adb
;
1573 isc_task_sendanddetach(&etask
, &event
);
1574 event
= ISC_LIST_HEAD(adb
->whenshutdown
);
1578 if (adb
->irefcnt
== 0 && adb
->erefcnt
== 0)
1580 UNLOCK(&adb
->reflock
);
1585 inc_adb_irefcnt(dns_adb_t
*adb
) {
1586 LOCK(&adb
->reflock
);
1588 UNLOCK(&adb
->reflock
);
1592 inc_adb_erefcnt(dns_adb_t
*adb
) {
1593 LOCK(&adb
->reflock
);
1595 UNLOCK(&adb
->reflock
);
1599 inc_entry_refcnt(dns_adb_t
*adb
, dns_adbentry_t
*entry
, isc_boolean_t lock
) {
1602 bucket
= entry
->lock_bucket
;
1605 LOCK(&adb
->entrylocks
[bucket
]);
1610 UNLOCK(&adb
->entrylocks
[bucket
]);
1613 static inline isc_boolean_t
1614 dec_entry_refcnt(dns_adb_t
*adb
, isc_boolean_t overmem
, dns_adbentry_t
*entry
,
1618 isc_boolean_t destroy_entry
;
1619 isc_boolean_t result
= ISC_FALSE
;
1621 bucket
= entry
->lock_bucket
;
1624 LOCK(&adb
->entrylocks
[bucket
]);
1626 INSIST(entry
->refcnt
> 0);
1629 destroy_entry
= ISC_FALSE
;
1630 if (entry
->refcnt
== 0 &&
1631 (adb
->entry_sd
[bucket
] || entry
->expires
== 0 || overmem
||
1632 (entry
->flags
& ENTRY_IS_DEAD
) != 0)) {
1633 destroy_entry
= ISC_TRUE
;
1634 result
= unlink_entry(adb
, entry
);
1638 UNLOCK(&adb
->entrylocks
[bucket
]);
1643 entry
->lock_bucket
= DNS_ADB_INVALIDBUCKET
;
1645 free_adbentry(adb
, &entry
);
1647 result
= dec_adb_irefcnt(adb
);
1652 static inline dns_adbname_t
*
1653 new_adbname(dns_adb_t
*adb
, dns_name_t
*dnsname
) {
1654 dns_adbname_t
*name
;
1656 name
= isc_mempool_get(adb
->nmp
);
1660 dns_name_init(&name
->name
, NULL
);
1661 if (dns_name_dup(dnsname
, adb
->mctx
, &name
->name
) != ISC_R_SUCCESS
) {
1662 isc_mempool_put(adb
->nmp
, name
);
1665 dns_name_init(&name
->target
, NULL
);
1666 name
->magic
= DNS_ADBNAME_MAGIC
;
1668 name
->partial_result
= 0;
1670 name
->expire_v4
= INT_MAX
;
1671 name
->expire_v6
= INT_MAX
;
1672 name
->expire_target
= INT_MAX
;
1674 name
->lock_bucket
= DNS_ADB_INVALIDBUCKET
;
1675 ISC_LIST_INIT(name
->v4
);
1676 ISC_LIST_INIT(name
->v6
);
1677 name
->fetch_a
= NULL
;
1678 name
->fetch_aaaa
= NULL
;
1679 name
->fetch_err
= FIND_ERR_UNEXPECTED
;
1680 name
->fetch6_err
= FIND_ERR_UNEXPECTED
;
1681 ISC_LIST_INIT(name
->finds
);
1682 ISC_LINK_INIT(name
, plink
);
1684 LOCK(&adb
->namescntlock
);
1686 inc_adbstats(adb
, dns_adbstats_namescnt
);
1687 if (!adb
->grownames_sent
&& adb
->excl
!= NULL
&&
1688 adb
->namescnt
> (adb
->nnames
* 8))
1690 isc_event_t
*event
= &adb
->grownames
;
1691 inc_adb_irefcnt(adb
);
1692 isc_task_send(adb
->excl
, &event
);
1693 adb
->grownames_sent
= ISC_TRUE
;
1695 UNLOCK(&adb
->namescntlock
);
1701 free_adbname(dns_adb_t
*adb
, dns_adbname_t
**name
) {
1704 INSIST(name
!= NULL
&& DNS_ADBNAME_VALID(*name
));
1708 INSIST(!NAME_HAS_V4(n
));
1709 INSIST(!NAME_HAS_V6(n
));
1710 INSIST(!NAME_FETCH(n
));
1711 INSIST(ISC_LIST_EMPTY(n
->finds
));
1712 INSIST(!ISC_LINK_LINKED(n
, plink
));
1713 INSIST(n
->lock_bucket
== DNS_ADB_INVALIDBUCKET
);
1714 INSIST(n
->adb
== adb
);
1717 dns_name_free(&n
->name
, adb
->mctx
);
1719 isc_mempool_put(adb
->nmp
, n
);
1720 LOCK(&adb
->namescntlock
);
1722 dec_adbstats(adb
, dns_adbstats_namescnt
);
1723 UNLOCK(&adb
->namescntlock
);
1726 static inline dns_adbnamehook_t
*
1727 new_adbnamehook(dns_adb_t
*adb
, dns_adbentry_t
*entry
) {
1728 dns_adbnamehook_t
*nh
;
1730 nh
= isc_mempool_get(adb
->nhmp
);
1734 nh
->magic
= DNS_ADBNAMEHOOK_MAGIC
;
1736 ISC_LINK_INIT(nh
, plink
);
1742 free_adbnamehook(dns_adb_t
*adb
, dns_adbnamehook_t
**namehook
) {
1743 dns_adbnamehook_t
*nh
;
1745 INSIST(namehook
!= NULL
&& DNS_ADBNAMEHOOK_VALID(*namehook
));
1749 INSIST(nh
->entry
== NULL
);
1750 INSIST(!ISC_LINK_LINKED(nh
, plink
));
1753 isc_mempool_put(adb
->nhmp
, nh
);
1756 static inline dns_adblameinfo_t
*
1757 new_adblameinfo(dns_adb_t
*adb
, dns_name_t
*qname
, dns_rdatatype_t qtype
) {
1758 dns_adblameinfo_t
*li
;
1760 li
= isc_mempool_get(adb
->limp
);
1764 dns_name_init(&li
->qname
, NULL
);
1765 if (dns_name_dup(qname
, adb
->mctx
, &li
->qname
) != ISC_R_SUCCESS
) {
1766 isc_mempool_put(adb
->limp
, li
);
1769 li
->magic
= DNS_ADBLAMEINFO_MAGIC
;
1772 ISC_LINK_INIT(li
, plink
);
1778 free_adblameinfo(dns_adb_t
*adb
, dns_adblameinfo_t
**lameinfo
) {
1779 dns_adblameinfo_t
*li
;
1781 INSIST(lameinfo
!= NULL
&& DNS_ADBLAMEINFO_VALID(*lameinfo
));
1785 INSIST(!ISC_LINK_LINKED(li
, plink
));
1787 dns_name_free(&li
->qname
, adb
->mctx
);
1791 isc_mempool_put(adb
->limp
, li
);
1794 static inline dns_adbentry_t
*
1795 new_adbentry(dns_adb_t
*adb
) {
1799 e
= isc_mempool_get(adb
->emp
);
1803 e
->magic
= DNS_ADBENTRY_MAGIC
;
1804 e
->lock_bucket
= DNS_ADB_INVALIDBUCKET
;
1818 e
->srtt
= (r
& 0x1f) + 1;
1821 ISC_LIST_INIT(e
->lameinfo
);
1822 ISC_LINK_INIT(e
, plink
);
1823 LOCK(&adb
->entriescntlock
);
1825 inc_adbstats(adb
, dns_adbstats_entriescnt
);
1826 if (!adb
->growentries_sent
&& adb
->excl
!= NULL
&&
1827 adb
->entriescnt
> (adb
->nentries
* 8))
1829 isc_event_t
*event
= &adb
->growentries
;
1830 inc_adb_irefcnt(adb
);
1831 isc_task_send(adb
->excl
, &event
);
1832 adb
->growentries_sent
= ISC_TRUE
;
1834 UNLOCK(&adb
->entriescntlock
);
1840 free_adbentry(dns_adb_t
*adb
, dns_adbentry_t
**entry
) {
1842 dns_adblameinfo_t
*li
;
1844 INSIST(entry
!= NULL
&& DNS_ADBENTRY_VALID(*entry
));
1848 INSIST(e
->lock_bucket
== DNS_ADB_INVALIDBUCKET
);
1849 INSIST(e
->refcnt
== 0);
1850 INSIST(!ISC_LINK_LINKED(e
, plink
));
1855 isc_mem_put(adb
->mctx
, e
->sit
, e
->sitlen
);
1857 li
= ISC_LIST_HEAD(e
->lameinfo
);
1858 while (li
!= NULL
) {
1859 ISC_LIST_UNLINK(e
->lameinfo
, li
, plink
);
1860 free_adblameinfo(adb
, &li
);
1861 li
= ISC_LIST_HEAD(e
->lameinfo
);
1864 isc_mempool_put(adb
->emp
, e
);
1865 LOCK(&adb
->entriescntlock
);
1867 dec_adbstats(adb
, dns_adbstats_entriescnt
);
1868 UNLOCK(&adb
->entriescntlock
);
1871 static inline dns_adbfind_t
*
1872 new_adbfind(dns_adb_t
*adb
) {
1874 isc_result_t result
;
1876 h
= isc_mempool_get(adb
->ahmp
);
1885 h
->partial_result
= 0;
1888 h
->result_v4
= ISC_R_UNEXPECTED
;
1889 h
->result_v6
= ISC_R_UNEXPECTED
;
1890 ISC_LINK_INIT(h
, publink
);
1891 ISC_LINK_INIT(h
, plink
);
1892 ISC_LIST_INIT(h
->list
);
1894 h
->name_bucket
= DNS_ADB_INVALIDBUCKET
;
1899 result
= isc_mutex_init(&h
->lock
);
1900 if (result
!= ISC_R_SUCCESS
) {
1901 isc_mempool_put(adb
->ahmp
, h
);
1905 ISC_EVENT_INIT(&h
->event
, sizeof(isc_event_t
), 0, 0, 0, NULL
, NULL
,
1908 inc_adb_irefcnt(adb
);
1909 h
->magic
= DNS_ADBFIND_MAGIC
;
1913 static inline dns_adbfetch_t
*
1914 new_adbfetch(dns_adb_t
*adb
) {
1917 f
= isc_mempool_get(adb
->afmp
);
1924 dns_rdataset_init(&f
->rdataset
);
1926 f
->magic
= DNS_ADBFETCH_MAGIC
;
1932 free_adbfetch(dns_adb_t
*adb
, dns_adbfetch_t
**fetch
) {
1935 INSIST(fetch
!= NULL
&& DNS_ADBFETCH_VALID(*fetch
));
1941 if (dns_rdataset_isassociated(&f
->rdataset
))
1942 dns_rdataset_disassociate(&f
->rdataset
);
1944 isc_mempool_put(adb
->afmp
, f
);
1947 static inline isc_boolean_t
1948 free_adbfind(dns_adb_t
*adb
, dns_adbfind_t
**findp
) {
1949 dns_adbfind_t
*find
;
1951 INSIST(findp
!= NULL
&& DNS_ADBFIND_VALID(*findp
));
1955 INSIST(!FIND_HAS_ADDRS(find
));
1956 INSIST(!ISC_LINK_LINKED(find
, publink
));
1957 INSIST(!ISC_LINK_LINKED(find
, plink
));
1958 INSIST(find
->name_bucket
== DNS_ADB_INVALIDBUCKET
);
1959 INSIST(find
->adbname
== NULL
);
1963 DESTROYLOCK(&find
->lock
);
1964 isc_mempool_put(adb
->ahmp
, find
);
1965 return (dec_adb_irefcnt(adb
));
1969 * Copy bits from the entry into the newly allocated addrinfo. The entry
1970 * must be locked, and the reference count must be bumped up by one
1971 * if this function returns a valid pointer.
1973 static inline dns_adbaddrinfo_t
*
1974 new_adbaddrinfo(dns_adb_t
*adb
, dns_adbentry_t
*entry
, in_port_t port
) {
1975 dns_adbaddrinfo_t
*ai
;
1977 ai
= isc_mempool_get(adb
->aimp
);
1981 ai
->magic
= DNS_ADBADDRINFO_MAGIC
;
1982 ai
->sockaddr
= entry
->sockaddr
;
1983 isc_sockaddr_setport(&ai
->sockaddr
, port
);
1984 ai
->srtt
= entry
->srtt
;
1985 ai
->flags
= entry
->flags
;
1988 ISC_LINK_INIT(ai
, publink
);
1994 free_adbaddrinfo(dns_adb_t
*adb
, dns_adbaddrinfo_t
**ainfo
) {
1995 dns_adbaddrinfo_t
*ai
;
1997 INSIST(ainfo
!= NULL
&& DNS_ADBADDRINFO_VALID(*ainfo
));
2001 INSIST(ai
->entry
== NULL
);
2002 INSIST(!ISC_LINK_LINKED(ai
, publink
));
2006 isc_mempool_put(adb
->aimp
, ai
);
2010 * Search for the name. NOTE: The bucket is kept locked on both
2011 * success and failure, so it must always be unlocked by the caller!
2013 * On the first call to this function, *bucketp must be set to
2014 * DNS_ADB_INVALIDBUCKET.
2016 static inline dns_adbname_t
*
2017 find_name_and_lock(dns_adb_t
*adb
, dns_name_t
*name
,
2018 unsigned int options
, int *bucketp
)
2020 dns_adbname_t
*adbname
;
2023 bucket
= dns_name_fullhash(name
, ISC_FALSE
) % adb
->nnames
;
2025 if (*bucketp
== DNS_ADB_INVALIDBUCKET
) {
2026 LOCK(&adb
->namelocks
[bucket
]);
2028 } else if (*bucketp
!= bucket
) {
2029 UNLOCK(&adb
->namelocks
[*bucketp
]);
2030 LOCK(&adb
->namelocks
[bucket
]);
2034 adbname
= ISC_LIST_HEAD(adb
->names
[bucket
]);
2035 while (adbname
!= NULL
) {
2036 if (!NAME_DEAD(adbname
)) {
2037 if (dns_name_equal(name
, &adbname
->name
)
2038 && GLUEHINT_OK(adbname
, options
)
2039 && STARTATZONE_MATCHES(adbname
, options
))
2042 adbname
= ISC_LIST_NEXT(adbname
, plink
);
2049 * Search for the address. NOTE: The bucket is kept locked on both
2050 * success and failure, so it must always be unlocked by the caller.
2052 * On the first call to this function, *bucketp must be set to
2053 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
2054 * later calls (within the same "lock path") it can be left alone, so
2055 * if this function is called multiple times locking is only done if
2056 * the bucket changes.
2058 static inline dns_adbentry_t
*
2059 find_entry_and_lock(dns_adb_t
*adb
, isc_sockaddr_t
*addr
, int *bucketp
,
2062 dns_adbentry_t
*entry
, *entry_next
;
2065 bucket
= isc_sockaddr_hash(addr
, ISC_TRUE
) % adb
->nentries
;
2067 if (*bucketp
== DNS_ADB_INVALIDBUCKET
) {
2068 LOCK(&adb
->entrylocks
[bucket
]);
2070 } else if (*bucketp
!= bucket
) {
2071 UNLOCK(&adb
->entrylocks
[*bucketp
]);
2072 LOCK(&adb
->entrylocks
[bucket
]);
2076 /* Search the list, while cleaning up expired entries. */
2077 for (entry
= ISC_LIST_HEAD(adb
->entries
[bucket
]);
2079 entry
= entry_next
) {
2080 entry_next
= ISC_LIST_NEXT(entry
, plink
);
2081 (void)check_expire_entry(adb
, &entry
, now
);
2082 if (entry
!= NULL
&&
2083 (entry
->expires
== 0 || entry
->expires
> now
) &&
2084 isc_sockaddr_equal(addr
, &entry
->sockaddr
)) {
2085 ISC_LIST_UNLINK(adb
->entries
[bucket
], entry
, plink
);
2086 ISC_LIST_PREPEND(adb
->entries
[bucket
], entry
, plink
);
2095 * Entry bucket MUST be locked!
2097 static isc_boolean_t
2098 entry_is_lame(dns_adb_t
*adb
, dns_adbentry_t
*entry
, dns_name_t
*qname
,
2099 dns_rdatatype_t qtype
, isc_stdtime_t now
)
2101 dns_adblameinfo_t
*li
, *next_li
;
2102 isc_boolean_t is_bad
;
2106 li
= ISC_LIST_HEAD(entry
->lameinfo
);
2109 while (li
!= NULL
) {
2110 next_li
= ISC_LIST_NEXT(li
, plink
);
2113 * Has the entry expired?
2115 if (li
->lame_timer
< now
) {
2116 ISC_LIST_UNLINK(entry
->lameinfo
, li
, plink
);
2117 free_adblameinfo(adb
, &li
);
2121 * Order tests from least to most expensive.
2123 * We do not break out of the main loop here as
2124 * we use the loop for house keeping.
2126 if (li
!= NULL
&& !is_bad
&& li
->qtype
== qtype
&&
2127 dns_name_equal(qname
, &li
->qname
))
2137 copy_namehook_lists(dns_adb_t
*adb
, dns_adbfind_t
*find
, dns_name_t
*qname
,
2138 dns_rdatatype_t qtype
, dns_adbname_t
*name
,
2141 dns_adbnamehook_t
*namehook
;
2142 dns_adbaddrinfo_t
*addrinfo
;
2143 dns_adbentry_t
*entry
;
2146 bucket
= DNS_ADB_INVALIDBUCKET
;
2148 if (find
->options
& DNS_ADBFIND_INET
) {
2149 namehook
= ISC_LIST_HEAD(name
->v4
);
2150 while (namehook
!= NULL
) {
2151 entry
= namehook
->entry
;
2152 bucket
= entry
->lock_bucket
;
2153 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
2154 LOCK(&adb
->entrylocks
[bucket
]);
2156 if (!FIND_RETURNLAME(find
)
2157 && entry_is_lame(adb
, entry
, qname
, qtype
, now
)) {
2158 find
->options
|= DNS_ADBFIND_LAMEPRUNED
;
2161 addrinfo
= new_adbaddrinfo(adb
, entry
, find
->port
);
2162 if (addrinfo
== NULL
) {
2163 find
->partial_result
|= DNS_ADBFIND_INET
;
2167 * Found a valid entry. Add it to the find's list.
2169 inc_entry_refcnt(adb
, entry
, ISC_FALSE
);
2170 ISC_LIST_APPEND(find
->list
, addrinfo
, publink
);
2173 UNLOCK(&adb
->entrylocks
[bucket
]);
2174 bucket
= DNS_ADB_INVALIDBUCKET
;
2175 namehook
= ISC_LIST_NEXT(namehook
, plink
);
2179 if (find
->options
& DNS_ADBFIND_INET6
) {
2180 namehook
= ISC_LIST_HEAD(name
->v6
);
2181 while (namehook
!= NULL
) {
2182 entry
= namehook
->entry
;
2183 bucket
= entry
->lock_bucket
;
2184 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
2185 LOCK(&adb
->entrylocks
[bucket
]);
2187 if (!FIND_RETURNLAME(find
)
2188 && entry_is_lame(adb
, entry
, qname
, qtype
, now
)) {
2189 find
->options
|= DNS_ADBFIND_LAMEPRUNED
;
2192 addrinfo
= new_adbaddrinfo(adb
, entry
, find
->port
);
2193 if (addrinfo
== NULL
) {
2194 find
->partial_result
|= DNS_ADBFIND_INET6
;
2198 * Found a valid entry. Add it to the find's list.
2200 inc_entry_refcnt(adb
, entry
, ISC_FALSE
);
2201 ISC_LIST_APPEND(find
->list
, addrinfo
, publink
);
2204 UNLOCK(&adb
->entrylocks
[bucket
]);
2205 bucket
= DNS_ADB_INVALIDBUCKET
;
2206 namehook
= ISC_LIST_NEXT(namehook
, plink
);
2211 if (bucket
!= DNS_ADB_INVALIDBUCKET
)
2212 UNLOCK(&adb
->entrylocks
[bucket
]);
2216 shutdown_task(isc_task_t
*task
, isc_event_t
*ev
) {
2222 INSIST(DNS_ADB_VALID(adb
));
2224 isc_event_free(&ev
);
2226 * Wait for lock around check_exit() call to be released.
2234 * Name bucket must be locked; adb may be locked; no other locks held.
2236 static isc_boolean_t
2237 check_expire_name(dns_adbname_t
**namep
, isc_stdtime_t now
) {
2238 dns_adbname_t
*name
;
2239 isc_boolean_t result
= ISC_FALSE
;
2241 INSIST(namep
!= NULL
&& DNS_ADBNAME_VALID(*namep
));
2244 if (NAME_HAS_V4(name
) || NAME_HAS_V6(name
))
2246 if (NAME_FETCH(name
))
2248 if (!EXPIRE_OK(name
->expire_v4
, now
))
2250 if (!EXPIRE_OK(name
->expire_v6
, now
))
2252 if (!EXPIRE_OK(name
->expire_target
, now
))
2256 * The name is empty. Delete it.
2258 result
= kill_name(&name
, DNS_EVENT_ADBEXPIRED
);
2262 * Our caller, or one of its callers, will be calling check_exit() at
2263 * some point, so we don't need to do it here.
2269 * Examine the tail entry of the LRU list to see if it expires or is stale
2270 * (unused for some period); if so, the name entry will be freed. If the ADB
2271 * is in the overmem condition, the tail and the next to tail entries
2272 * will be unconditionally removed (unless they have an outstanding fetch).
2273 * We don't care about a race on 'overmem' at the risk of causing some
2274 * collateral damage or a small delay in starting cleanup, so we don't bother
2275 * to lock ADB (if it's not locked).
2277 * Name bucket must be locked; adb may be locked; no other locks held.
2280 check_stale_name(dns_adb_t
*adb
, int bucket
, isc_stdtime_t now
) {
2281 int victims
, max_victims
;
2282 dns_adbname_t
*victim
, *next_victim
;
2283 isc_boolean_t overmem
= isc_mem_isovermem(adb
->mctx
);
2286 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
2288 max_victims
= overmem
? 2 : 1;
2291 * We limit the number of scanned entries to 10 (arbitrary choice)
2292 * in order to avoid examining too many entries when there are many
2293 * tail entries that have fetches (this should be rare, but could
2296 victim
= ISC_LIST_TAIL(adb
->names
[bucket
]);
2298 victim
!= NULL
&& victims
< max_victims
&& scans
< 10;
2299 victim
= next_victim
) {
2300 INSIST(!NAME_DEAD(victim
));
2302 next_victim
= ISC_LIST_PREV(victim
, plink
);
2303 (void)check_expire_name(&victim
, now
);
2304 if (victim
== NULL
) {
2309 if (!NAME_FETCH(victim
) &&
2310 (overmem
|| victim
->last_used
+ ADB_STALE_MARGIN
<= now
)) {
2311 RUNTIME_CHECK(kill_name(&victim
,
2312 DNS_EVENT_ADBCANCELED
) ==
2324 * Entry bucket must be locked; adb may be locked; no other locks held.
2326 static isc_boolean_t
2327 check_expire_entry(dns_adb_t
*adb
, dns_adbentry_t
**entryp
, isc_stdtime_t now
)
2329 dns_adbentry_t
*entry
;
2330 isc_boolean_t result
= ISC_FALSE
;
2332 INSIST(entryp
!= NULL
&& DNS_ADBENTRY_VALID(*entryp
));
2335 if (entry
->refcnt
!= 0)
2338 if (entry
->expires
== 0 || entry
->expires
> now
)
2342 * The entry is not in use. Delete it.
2344 DP(DEF_LEVEL
, "killing entry %p", entry
);
2345 INSIST(ISC_LINK_LINKED(entry
, plink
));
2346 result
= unlink_entry(adb
, entry
);
2347 free_adbentry(adb
, &entry
);
2349 dec_adb_irefcnt(adb
);
2355 * ADB must be locked, and no other locks held.
2357 static isc_boolean_t
2358 cleanup_names(dns_adb_t
*adb
, int bucket
, isc_stdtime_t now
) {
2359 dns_adbname_t
*name
;
2360 dns_adbname_t
*next_name
;
2361 isc_boolean_t result
= ISC_FALSE
;
2363 DP(CLEAN_LEVEL
, "cleaning name bucket %d", bucket
);
2365 LOCK(&adb
->namelocks
[bucket
]);
2366 if (adb
->name_sd
[bucket
]) {
2367 UNLOCK(&adb
->namelocks
[bucket
]);
2371 name
= ISC_LIST_HEAD(adb
->names
[bucket
]);
2372 while (name
!= NULL
) {
2373 next_name
= ISC_LIST_NEXT(name
, plink
);
2374 INSIST(result
== ISC_FALSE
);
2375 result
= check_expire_namehooks(name
, now
);
2377 result
= check_expire_name(&name
, now
);
2380 UNLOCK(&adb
->namelocks
[bucket
]);
2385 * ADB must be locked, and no other locks held.
2387 static isc_boolean_t
2388 cleanup_entries(dns_adb_t
*adb
, int bucket
, isc_stdtime_t now
) {
2389 dns_adbentry_t
*entry
, *next_entry
;
2390 isc_boolean_t result
= ISC_FALSE
;
2392 DP(CLEAN_LEVEL
, "cleaning entry bucket %d", bucket
);
2394 LOCK(&adb
->entrylocks
[bucket
]);
2395 entry
= ISC_LIST_HEAD(adb
->entries
[bucket
]);
2396 while (entry
!= NULL
) {
2397 next_entry
= ISC_LIST_NEXT(entry
, plink
);
2398 INSIST(result
== ISC_FALSE
);
2399 result
= check_expire_entry(adb
, &entry
, now
);
2402 UNLOCK(&adb
->entrylocks
[bucket
]);
2407 destroy(dns_adb_t
*adb
) {
2410 isc_task_detach(&adb
->task
);
2411 if (adb
->excl
!= NULL
)
2412 isc_task_detach(&adb
->excl
);
2414 isc_mempool_destroy(&adb
->nmp
);
2415 isc_mempool_destroy(&adb
->nhmp
);
2416 isc_mempool_destroy(&adb
->limp
);
2417 isc_mempool_destroy(&adb
->emp
);
2418 isc_mempool_destroy(&adb
->ahmp
);
2419 isc_mempool_destroy(&adb
->aimp
);
2420 isc_mempool_destroy(&adb
->afmp
);
2422 DESTROYMUTEXBLOCK(adb
->entrylocks
, adb
->nentries
);
2423 isc_mem_put(adb
->mctx
, adb
->entries
,
2424 sizeof(*adb
->entries
) * adb
->nentries
);
2425 isc_mem_put(adb
->mctx
, adb
->deadentries
,
2426 sizeof(*adb
->deadentries
) * adb
->nentries
);
2427 isc_mem_put(adb
->mctx
, adb
->entrylocks
,
2428 sizeof(*adb
->entrylocks
) * adb
->nentries
);
2429 isc_mem_put(adb
->mctx
, adb
->entry_sd
,
2430 sizeof(*adb
->entry_sd
) * adb
->nentries
);
2431 isc_mem_put(adb
->mctx
, adb
->entry_refcnt
,
2432 sizeof(*adb
->entry_refcnt
) * adb
->nentries
);
2434 DESTROYMUTEXBLOCK(adb
->namelocks
, adb
->nnames
);
2435 isc_mem_put(adb
->mctx
, adb
->names
,
2436 sizeof(*adb
->names
) * adb
->nnames
);
2437 isc_mem_put(adb
->mctx
, adb
->deadnames
,
2438 sizeof(*adb
->deadnames
) * adb
->nnames
);
2439 isc_mem_put(adb
->mctx
, adb
->namelocks
,
2440 sizeof(*adb
->namelocks
) * adb
->nnames
);
2441 isc_mem_put(adb
->mctx
, adb
->name_sd
,
2442 sizeof(*adb
->name_sd
) * adb
->nnames
);
2443 isc_mem_put(adb
->mctx
, adb
->name_refcnt
,
2444 sizeof(*adb
->name_refcnt
) * adb
->nnames
);
2446 DESTROYLOCK(&adb
->reflock
);
2447 DESTROYLOCK(&adb
->lock
);
2448 DESTROYLOCK(&adb
->mplock
);
2449 DESTROYLOCK(&adb
->overmemlock
);
2450 DESTROYLOCK(&adb
->entriescntlock
);
2451 DESTROYLOCK(&adb
->namescntlock
);
2453 isc_mem_putanddetach(&adb
->mctx
, adb
, sizeof(dns_adb_t
));
2462 dns_adb_create(isc_mem_t
*mem
, dns_view_t
*view
, isc_timermgr_t
*timermgr
,
2463 isc_taskmgr_t
*taskmgr
, dns_adb_t
**newadb
)
2466 isc_result_t result
;
2469 REQUIRE(mem
!= NULL
);
2470 REQUIRE(view
!= NULL
);
2471 REQUIRE(timermgr
!= NULL
); /* this is actually unused */
2472 REQUIRE(taskmgr
!= NULL
);
2473 REQUIRE(newadb
!= NULL
&& *newadb
== NULL
);
2477 adb
= isc_mem_get(mem
, sizeof(dns_adb_t
));
2479 return (ISC_R_NOMEMORY
);
2482 * Initialize things here that cannot fail, and especially things
2483 * that must be NULL for the error return to work properly.
2499 adb
->taskmgr
= taskmgr
;
2500 adb
->next_cleanbucket
= 0;
2501 ISC_EVENT_INIT(&adb
->cevent
, sizeof(adb
->cevent
),
2502 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
, NULL
);
2503 adb
->cevent_out
= ISC_FALSE
;
2504 adb
->shutting_down
= ISC_FALSE
;
2505 ISC_LIST_INIT(adb
->whenshutdown
);
2507 adb
->nentries
= nbuckets
[0];
2508 adb
->entriescnt
= 0;
2509 adb
->entries
= NULL
;
2510 adb
->deadentries
= NULL
;
2511 adb
->entry_sd
= NULL
;
2512 adb
->entry_refcnt
= NULL
;
2513 adb
->entrylocks
= NULL
;
2514 ISC_EVENT_INIT(&adb
->growentries
, sizeof(adb
->growentries
), 0, NULL
,
2515 DNS_EVENT_ADBGROWENTRIES
, grow_entries
, adb
,
2517 adb
->growentries_sent
= ISC_FALSE
;
2519 adb
->nnames
= nbuckets
[0];
2522 adb
->deadnames
= NULL
;
2523 adb
->name_sd
= NULL
;
2524 adb
->name_refcnt
= NULL
;
2525 adb
->namelocks
= NULL
;
2526 ISC_EVENT_INIT(&adb
->grownames
, sizeof(adb
->grownames
), 0, NULL
,
2527 DNS_EVENT_ADBGROWNAMES
, grow_names
, adb
,
2529 adb
->grownames_sent
= ISC_FALSE
;
2531 result
= isc_taskmgr_excltask(adb
->taskmgr
, &adb
->excl
);
2532 if (result
!= ISC_R_SUCCESS
) {
2533 DP(DEF_LEVEL
, "adb: task-exclusive mode unavailable, "
2534 "intializing table sizes to %u\n",
2536 adb
->nentries
= nbuckets
[11];
2537 adb
->nnames
= nbuckets
[11];
2541 isc_mem_attach(mem
, &adb
->mctx
);
2543 result
= isc_mutex_init(&adb
->lock
);
2544 if (result
!= ISC_R_SUCCESS
)
2547 result
= isc_mutex_init(&adb
->mplock
);
2548 if (result
!= ISC_R_SUCCESS
)
2551 result
= isc_mutex_init(&adb
->reflock
);
2552 if (result
!= ISC_R_SUCCESS
)
2555 result
= isc_mutex_init(&adb
->overmemlock
);
2556 if (result
!= ISC_R_SUCCESS
)
2559 result
= isc_mutex_init(&adb
->entriescntlock
);
2560 if (result
!= ISC_R_SUCCESS
)
2563 result
= isc_mutex_init(&adb
->namescntlock
);
2564 if (result
!= ISC_R_SUCCESS
)
2567 #define ALLOCENTRY(adb, el) \
2569 (adb)->el = isc_mem_get((adb)->mctx, \
2570 sizeof(*(adb)->el) * (adb)->nentries); \
2571 if ((adb)->el == NULL) { \
2572 result = ISC_R_NOMEMORY; \
2575 } while (/*CONSTCOND*/0)
2576 ALLOCENTRY(adb
, entries
);
2577 ALLOCENTRY(adb
, deadentries
);
2578 ALLOCENTRY(adb
, entrylocks
);
2579 ALLOCENTRY(adb
, entry_sd
);
2580 ALLOCENTRY(adb
, entry_refcnt
);
2583 #define ALLOCNAME(adb, el) \
2585 (adb)->el = isc_mem_get((adb)->mctx, \
2586 sizeof(*(adb)->el) * (adb)->nnames); \
2587 if ((adb)->el == NULL) { \
2588 result = ISC_R_NOMEMORY; \
2591 } while (/*CONSTCOND*/0)
2592 ALLOCNAME(adb
, names
);
2593 ALLOCNAME(adb
, deadnames
);
2594 ALLOCNAME(adb
, namelocks
);
2595 ALLOCNAME(adb
, name_sd
);
2596 ALLOCNAME(adb
, name_refcnt
);
2600 * Initialize the bucket locks for names and elements.
2601 * May as well initialize the list heads, too.
2603 result
= isc_mutexblock_init(adb
->namelocks
, adb
->nnames
);
2604 if (result
!= ISC_R_SUCCESS
)
2606 for (i
= 0; i
< adb
->nnames
; i
++) {
2607 ISC_LIST_INIT(adb
->names
[i
]);
2608 ISC_LIST_INIT(adb
->deadnames
[i
]);
2609 adb
->name_sd
[i
] = ISC_FALSE
;
2610 adb
->name_refcnt
[i
] = 0;
2613 for (i
= 0; i
< adb
->nentries
; i
++) {
2614 ISC_LIST_INIT(adb
->entries
[i
]);
2615 ISC_LIST_INIT(adb
->deadentries
[i
]);
2616 adb
->entry_sd
[i
] = ISC_FALSE
;
2617 adb
->entry_refcnt
[i
] = 0;
2620 result
= isc_mutexblock_init(adb
->entrylocks
, adb
->nentries
);
2621 if (result
!= ISC_R_SUCCESS
)
2627 #define MPINIT(t, p, n) do { \
2628 result = isc_mempool_create(mem, sizeof(t), &(p)); \
2629 if (result != ISC_R_SUCCESS) \
2631 isc_mempool_setfreemax((p), FREE_ITEMS); \
2632 isc_mempool_setfillcount((p), FILL_COUNT); \
2633 isc_mempool_setname((p), n); \
2634 isc_mempool_associatelock((p), &adb->mplock); \
2635 } while (/*CONSTCOND*/0)
2637 MPINIT(dns_adbname_t
, adb
->nmp
, "adbname");
2638 MPINIT(dns_adbnamehook_t
, adb
->nhmp
, "adbnamehook");
2639 MPINIT(dns_adblameinfo_t
, adb
->limp
, "adblameinfo");
2640 MPINIT(dns_adbentry_t
, adb
->emp
, "adbentry");
2641 MPINIT(dns_adbfind_t
, adb
->ahmp
, "adbfind");
2642 MPINIT(dns_adbaddrinfo_t
, adb
->aimp
, "adbaddrinfo");
2643 MPINIT(dns_adbfetch_t
, adb
->afmp
, "adbfetch");
2648 * Allocate an internal task.
2650 result
= isc_task_create(adb
->taskmgr
, 0, &adb
->task
);
2651 if (result
!= ISC_R_SUCCESS
)
2654 isc_task_setname(adb
->task
, "ADB", adb
);
2656 result
= isc_stats_create(adb
->mctx
, &view
->adbstats
, dns_adbstats_max
);
2657 if (result
!= ISC_R_SUCCESS
)
2660 set_adbstat(adb
, adb
->nentries
, dns_adbstats_nentries
);
2661 set_adbstat(adb
, adb
->nnames
, dns_adbstats_nnames
);
2666 adb
->magic
= DNS_ADB_MAGIC
;
2668 return (ISC_R_SUCCESS
);
2671 if (adb
->task
!= NULL
)
2672 isc_task_detach(&adb
->task
);
2674 /* clean up entrylocks */
2675 DESTROYMUTEXBLOCK(adb
->entrylocks
, adb
->nentries
);
2677 fail2
: /* clean up namelocks */
2678 DESTROYMUTEXBLOCK(adb
->namelocks
, adb
->nnames
);
2680 fail1
: /* clean up only allocated memory */
2681 if (adb
->entries
!= NULL
)
2682 isc_mem_put(adb
->mctx
, adb
->entries
,
2683 sizeof(*adb
->entries
) * adb
->nentries
);
2684 if (adb
->deadentries
!= NULL
)
2685 isc_mem_put(adb
->mctx
, adb
->deadentries
,
2686 sizeof(*adb
->deadentries
) * adb
->nentries
);
2687 if (adb
->entrylocks
!= NULL
)
2688 isc_mem_put(adb
->mctx
, adb
->entrylocks
,
2689 sizeof(*adb
->entrylocks
) * adb
->nentries
);
2690 if (adb
->entry_sd
!= NULL
)
2691 isc_mem_put(adb
->mctx
, adb
->entry_sd
,
2692 sizeof(*adb
->entry_sd
) * adb
->nentries
);
2693 if (adb
->entry_refcnt
!= NULL
)
2694 isc_mem_put(adb
->mctx
, adb
->entry_refcnt
,
2695 sizeof(*adb
->entry_refcnt
) * adb
->nentries
);
2696 if (adb
->names
!= NULL
)
2697 isc_mem_put(adb
->mctx
, adb
->names
,
2698 sizeof(*adb
->names
) * adb
->nnames
);
2699 if (adb
->deadnames
!= NULL
)
2700 isc_mem_put(adb
->mctx
, adb
->deadnames
,
2701 sizeof(*adb
->deadnames
) * adb
->nnames
);
2702 if (adb
->namelocks
!= NULL
)
2703 isc_mem_put(adb
->mctx
, adb
->namelocks
,
2704 sizeof(*adb
->namelocks
) * adb
->nnames
);
2705 if (adb
->name_sd
!= NULL
)
2706 isc_mem_put(adb
->mctx
, adb
->name_sd
,
2707 sizeof(*adb
->name_sd
) * adb
->nnames
);
2708 if (adb
->name_refcnt
!= NULL
)
2709 isc_mem_put(adb
->mctx
, adb
->name_refcnt
,
2710 sizeof(*adb
->name_refcnt
) * adb
->nnames
);
2711 if (adb
->nmp
!= NULL
)
2712 isc_mempool_destroy(&adb
->nmp
);
2713 if (adb
->nhmp
!= NULL
)
2714 isc_mempool_destroy(&adb
->nhmp
);
2715 if (adb
->limp
!= NULL
)
2716 isc_mempool_destroy(&adb
->limp
);
2717 if (adb
->emp
!= NULL
)
2718 isc_mempool_destroy(&adb
->emp
);
2719 if (adb
->ahmp
!= NULL
)
2720 isc_mempool_destroy(&adb
->ahmp
);
2721 if (adb
->aimp
!= NULL
)
2722 isc_mempool_destroy(&adb
->aimp
);
2723 if (adb
->afmp
!= NULL
)
2724 isc_mempool_destroy(&adb
->afmp
);
2726 DESTROYLOCK(&adb
->namescntlock
);
2728 DESTROYLOCK(&adb
->entriescntlock
);
2730 DESTROYLOCK(&adb
->overmemlock
);
2732 DESTROYLOCK(&adb
->reflock
);
2734 DESTROYLOCK(&adb
->mplock
);
2736 DESTROYLOCK(&adb
->lock
);
2738 isc_mem_putanddetach(&adb
->mctx
, adb
, sizeof(dns_adb_t
));
2744 dns_adb_attach(dns_adb_t
*adb
, dns_adb_t
**adbx
) {
2746 REQUIRE(DNS_ADB_VALID(adb
));
2747 REQUIRE(adbx
!= NULL
&& *adbx
== NULL
);
2749 inc_adb_erefcnt(adb
);
2754 dns_adb_detach(dns_adb_t
**adbx
) {
2756 isc_boolean_t need_exit_check
;
2758 REQUIRE(adbx
!= NULL
&& DNS_ADB_VALID(*adbx
));
2763 INSIST(adb
->erefcnt
> 0);
2765 LOCK(&adb
->reflock
);
2767 need_exit_check
= ISC_TF(adb
->erefcnt
== 0 && adb
->irefcnt
== 0);
2768 UNLOCK(&adb
->reflock
);
2770 if (need_exit_check
) {
2772 INSIST(adb
->shutting_down
);
2779 dns_adb_whenshutdown(dns_adb_t
*adb
, isc_task_t
*task
, isc_event_t
**eventp
) {
2782 isc_boolean_t zeroirefcnt
= ISC_FALSE
;
2785 * Send '*eventp' to 'task' when 'adb' has shutdown.
2788 REQUIRE(DNS_ADB_VALID(adb
));
2789 REQUIRE(eventp
!= NULL
);
2796 LOCK(&adb
->reflock
);
2797 zeroirefcnt
= ISC_TF(adb
->irefcnt
== 0);
2799 if (adb
->shutting_down
&& zeroirefcnt
&&
2800 isc_mempool_getallocated(adb
->ahmp
) == 0) {
2802 * We're already shutdown. Send the event.
2804 event
->ev_sender
= adb
;
2805 isc_task_send(task
, &event
);
2808 isc_task_attach(task
, &clone
);
2809 event
->ev_sender
= clone
;
2810 ISC_LIST_APPEND(adb
->whenshutdown
, event
, ev_link
);
2813 UNLOCK(&adb
->reflock
);
2818 shutdown_stage2(isc_task_t
*task
, isc_event_t
*event
) {
2823 adb
= event
->ev_arg
;
2824 INSIST(DNS_ADB_VALID(adb
));
2827 INSIST(adb
->shutting_down
);
2828 adb
->cevent_out
= ISC_FALSE
;
2829 (void)shutdown_names(adb
);
2830 (void)shutdown_entries(adb
);
2831 if (dec_adb_irefcnt(adb
))
2837 dns_adb_shutdown(dns_adb_t
*adb
) {
2846 if (!adb
->shutting_down
) {
2847 adb
->shutting_down
= ISC_TRUE
;
2848 isc_mem_setwater(adb
->mctx
, water
, adb
, 0, 0);
2850 * Isolate shutdown_names and shutdown_entries calls.
2852 inc_adb_irefcnt(adb
);
2853 ISC_EVENT_INIT(&adb
->cevent
, sizeof(adb
->cevent
), 0, NULL
,
2854 DNS_EVENT_ADBCONTROL
, shutdown_stage2
, adb
,
2856 adb
->cevent_out
= ISC_TRUE
;
2857 event
= &adb
->cevent
;
2858 isc_task_send(adb
->task
, &event
);
2865 dns_adb_createfind(dns_adb_t
*adb
, isc_task_t
*task
, isc_taskaction_t action
,
2866 void *arg
, dns_name_t
*name
, dns_name_t
*qname
,
2867 dns_rdatatype_t qtype
, unsigned int options
,
2868 isc_stdtime_t now
, dns_name_t
*target
,
2869 in_port_t port
, dns_adbfind_t
**findp
)
2871 return (dns_adb_createfind2(adb
, task
, action
, arg
, name
,
2872 qname
, qtype
, options
, now
,
2873 target
, port
, 0, NULL
, findp
));
2877 dns_adb_createfind2(dns_adb_t
*adb
, isc_task_t
*task
, isc_taskaction_t action
,
2878 void *arg
, dns_name_t
*name
, dns_name_t
*qname
,
2879 dns_rdatatype_t qtype
, unsigned int options
,
2880 isc_stdtime_t now
, dns_name_t
*target
,
2881 in_port_t port
, unsigned int depth
, isc_counter_t
*qc
,
2882 dns_adbfind_t
**findp
)
2884 dns_adbfind_t
*find
;
2885 dns_adbname_t
*adbname
;
2887 isc_boolean_t want_event
, start_at_zone
, alias
, have_address
;
2888 isc_result_t result
;
2889 unsigned int wanted_addresses
;
2890 unsigned int wanted_fetches
;
2891 unsigned int query_pending
;
2892 char namebuf
[DNS_NAME_FORMATSIZE
];
2894 REQUIRE(DNS_ADB_VALID(adb
));
2896 REQUIRE(action
!= NULL
);
2898 REQUIRE(name
!= NULL
);
2899 REQUIRE(qname
!= NULL
);
2900 REQUIRE(findp
!= NULL
&& *findp
== NULL
);
2901 REQUIRE(target
== NULL
|| dns_name_hasbuffer(target
));
2903 REQUIRE((options
& DNS_ADBFIND_ADDRESSMASK
) != 0);
2905 result
= ISC_R_UNEXPECTED
;
2907 wanted_addresses
= (options
& DNS_ADBFIND_ADDRESSMASK
);
2910 want_event
= ISC_FALSE
;
2911 start_at_zone
= ISC_FALSE
;
2915 isc_stdtime_get(&now
);
2918 * XXXMLG Move this comment somewhere else!
2920 * Look up the name in our internal database.
2922 * Possibilities: Note that these are not always exclusive.
2924 * No name found. In this case, allocate a new name header and
2925 * an initial namehook or two. If any of these allocations
2926 * fail, clean up and return ISC_R_NOMEMORY.
2928 * Name found, valid addresses present. Allocate one addrinfo
2929 * structure for each found and append it to the linked list
2930 * of addresses for this header.
2932 * Name found, queries pending. In this case, if a task was
2933 * passed in, allocate a job id, attach it to the name's job
2934 * list and remember to tell the caller that there will be
2935 * more info coming later.
2938 find
= new_adbfind(adb
);
2940 return (ISC_R_NOMEMORY
);
2945 * Remember what types of addresses we are interested in.
2947 find
->options
= options
;
2948 find
->flags
|= wanted_addresses
;
2949 if (FIND_WANTEVENT(find
)) {
2950 REQUIRE(task
!= NULL
);
2953 if (isc_log_wouldlog(dns_lctx
, DEF_LEVEL
))
2954 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2959 * Try to see if we know anything about this name at all.
2961 bucket
= DNS_ADB_INVALIDBUCKET
;
2962 adbname
= find_name_and_lock(adb
, name
, find
->options
, &bucket
);
2963 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
2964 if (adb
->name_sd
[bucket
]) {
2966 "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
2967 RUNTIME_CHECK(free_adbfind(adb
, &find
) == ISC_FALSE
);
2968 result
= ISC_R_SHUTTINGDOWN
;
2973 * Nothing found. Allocate a new adbname structure for this name.
2975 if (adbname
== NULL
) {
2977 * See if there is any stale name at the end of list, and purge
2980 check_stale_name(adb
, bucket
, now
);
2982 adbname
= new_adbname(adb
, name
);
2983 if (adbname
== NULL
) {
2984 RUNTIME_CHECK(free_adbfind(adb
, &find
) == ISC_FALSE
);
2985 result
= ISC_R_NOMEMORY
;
2988 link_name(adb
, bucket
, adbname
);
2989 if (FIND_HINTOK(find
))
2990 adbname
->flags
|= NAME_HINT_OK
;
2991 if (FIND_GLUEOK(find
))
2992 adbname
->flags
|= NAME_GLUE_OK
;
2993 if (FIND_STARTATZONE(find
))
2994 adbname
->flags
|= NAME_STARTATZONE
;
2996 /* Move this name forward in the LRU list */
2997 ISC_LIST_UNLINK(adb
->names
[bucket
], adbname
, plink
);
2998 ISC_LIST_PREPEND(adb
->names
[bucket
], adbname
, plink
);
3000 adbname
->last_used
= now
;
3003 * Expire old entries, etc.
3005 RUNTIME_CHECK(check_expire_namehooks(adbname
, now
) == ISC_FALSE
);
3008 * Do we know that the name is an alias?
3010 if (!EXPIRE_OK(adbname
->expire_target
, now
)) {
3015 "dns_adb_createfind: name %s (%p) is an alias (cached)",
3022 * Try to populate the name from the database and/or
3023 * start fetches. First try looking for an A record
3026 if (!NAME_HAS_V4(adbname
) && EXPIRE_OK(adbname
->expire_v4
, now
)
3027 && WANT_INET(wanted_addresses
)) {
3028 result
= dbfind_name(adbname
, now
, dns_rdatatype_a
);
3029 if (result
== ISC_R_SUCCESS
) {
3031 "dns_adb_createfind: found A for name %s (%p) in db",
3037 * Did we get a CNAME or DNAME?
3039 if (result
== DNS_R_ALIAS
) {
3041 "dns_adb_createfind: name %s (%p) is an alias",
3048 * If the name doesn't exist at all, don't bother with
3049 * v6 queries; they won't work.
3051 * If the name does exist but we didn't get our data, go
3052 * ahead and try AAAA.
3054 * If the result is neither of these, try a fetch for A.
3056 if (NXDOMAIN_RESULT(result
))
3058 else if (NXRRSET_RESULT(result
))
3061 if (!NAME_FETCH_V4(adbname
))
3062 wanted_fetches
|= DNS_ADBFIND_INET
;
3066 if (!NAME_HAS_V6(adbname
) && EXPIRE_OK(adbname
->expire_v6
, now
)
3067 && WANT_INET6(wanted_addresses
)) {
3068 result
= dbfind_name(adbname
, now
, dns_rdatatype_aaaa
);
3069 if (result
== ISC_R_SUCCESS
) {
3071 "dns_adb_createfind: found AAAA for name %s (%p)",
3077 * Did we get a CNAME or DNAME?
3079 if (result
== DNS_R_ALIAS
) {
3081 "dns_adb_createfind: name %s (%p) is an alias",
3088 * Listen to negative cache hints, and don't start
3091 if (NCACHE_RESULT(result
) || AUTH_NX(result
))
3094 if (!NAME_FETCH_V6(adbname
))
3095 wanted_fetches
|= DNS_ADBFIND_INET6
;
3099 if ((WANT_INET(wanted_addresses
) && NAME_HAS_V4(adbname
)) ||
3100 (WANT_INET6(wanted_addresses
) && NAME_HAS_V6(adbname
)))
3101 have_address
= ISC_TRUE
;
3103 have_address
= ISC_FALSE
;
3104 if (wanted_fetches
!= 0 &&
3105 ! (FIND_AVOIDFETCHES(find
) && have_address
)) {
3107 * We're missing at least one address family. Either the
3108 * caller hasn't instructed us to avoid fetches, or we don't
3109 * know anything about any of the address families that would
3110 * be acceptable so we have to launch fetches.
3113 if (FIND_STARTATZONE(find
))
3114 start_at_zone
= ISC_TRUE
;
3119 if (WANT_INET(wanted_fetches
) &&
3120 fetch_name(adbname
, start_at_zone
, depth
, qc
,
3121 dns_rdatatype_a
) == ISC_R_SUCCESS
) {
3122 DP(DEF_LEVEL
, "dns_adb_createfind: "
3123 "started A fetch for name %s (%p)",
3130 if (WANT_INET6(wanted_fetches
) &&
3131 fetch_name(adbname
, start_at_zone
, depth
, qc
,
3132 dns_rdatatype_aaaa
) == ISC_R_SUCCESS
) {
3133 DP(DEF_LEVEL
, "dns_adb_createfind: "
3134 "started AAAA fetch for name %s (%p)",
3140 * Run through the name and copy out the bits we are
3143 copy_namehook_lists(adb
, find
, qname
, qtype
, adbname
, now
);
3146 if (NAME_FETCH_V4(adbname
))
3147 query_pending
|= DNS_ADBFIND_INET
;
3148 if (NAME_FETCH_V6(adbname
))
3149 query_pending
|= DNS_ADBFIND_INET6
;
3152 * Attach to the name's query list if there are queries
3153 * already running, and we have been asked to.
3155 want_event
= ISC_TRUE
;
3156 if (!FIND_WANTEVENT(find
))
3157 want_event
= ISC_FALSE
;
3158 if (FIND_WANTEMPTYEVENT(find
) && FIND_HAS_ADDRS(find
))
3159 want_event
= ISC_FALSE
;
3160 if ((wanted_addresses
& query_pending
) == 0)
3161 want_event
= ISC_FALSE
;
3163 want_event
= ISC_FALSE
;
3165 find
->adbname
= adbname
;
3166 find
->name_bucket
= bucket
;
3167 ISC_LIST_APPEND(adbname
->finds
, find
, plink
);
3168 find
->query_pending
= (query_pending
& wanted_addresses
);
3169 find
->flags
&= ~DNS_ADBFIND_ADDRESSMASK
;
3170 find
->flags
|= (find
->query_pending
& DNS_ADBFIND_ADDRESSMASK
);
3171 DP(DEF_LEVEL
, "createfind: attaching find %p to adbname %p",
3175 * Remove the flag so the caller knows there will never
3176 * be an event, and set internal flags to fake that
3177 * the event was sent and freed, so dns_adb_destroyfind() will
3178 * do the right thing.
3180 find
->query_pending
= (query_pending
& wanted_addresses
);
3181 find
->options
&= ~DNS_ADBFIND_WANTEVENT
;
3182 find
->flags
|= (FIND_EVENT_SENT
| FIND_EVENT_FREED
);
3183 find
->flags
&= ~DNS_ADBFIND_ADDRESSMASK
;
3186 find
->partial_result
|= (adbname
->partial_result
& wanted_addresses
);
3188 if (target
!= NULL
) {
3189 result
= dns_name_copy(&adbname
->target
, target
, NULL
);
3190 if (result
!= ISC_R_SUCCESS
)
3193 result
= DNS_R_ALIAS
;
3195 result
= ISC_R_SUCCESS
;
3198 * Copy out error flags from the name structure into the find.
3200 find
->result_v4
= find_err_map
[adbname
->fetch_err
];
3201 find
->result_v6
= find_err_map
[adbname
->fetch6_err
];
3210 INSIST((find
->flags
& DNS_ADBFIND_ADDRESSMASK
) != 0);
3212 isc_task_attach(task
, &taskp
);
3213 find
->event
.ev_sender
= taskp
;
3214 find
->event
.ev_action
= action
;
3215 find
->event
.ev_arg
= arg
;
3219 UNLOCK(&adb
->namelocks
[bucket
]);
3225 dns_adb_destroyfind(dns_adbfind_t
**findp
) {
3226 dns_adbfind_t
*find
;
3227 dns_adbentry_t
*entry
;
3228 dns_adbaddrinfo_t
*ai
;
3231 isc_boolean_t overmem
;
3233 REQUIRE(findp
!= NULL
&& DNS_ADBFIND_VALID(*findp
));
3239 DP(DEF_LEVEL
, "dns_adb_destroyfind on find %p", find
);
3242 REQUIRE(DNS_ADB_VALID(adb
));
3244 REQUIRE(FIND_EVENTFREED(find
));
3246 bucket
= find
->name_bucket
;
3247 INSIST(bucket
== DNS_ADB_INVALIDBUCKET
);
3249 UNLOCK(&find
->lock
);
3252 * The find doesn't exist on any list, and nothing is locked.
3253 * Return the find to the memory pool, and decrement the adb's
3256 overmem
= isc_mem_isovermem(adb
->mctx
);
3257 ai
= ISC_LIST_HEAD(find
->list
);
3258 while (ai
!= NULL
) {
3259 ISC_LIST_UNLINK(find
->list
, ai
, publink
);
3262 INSIST(DNS_ADBENTRY_VALID(entry
));
3263 RUNTIME_CHECK(dec_entry_refcnt(adb
, overmem
, entry
, ISC_TRUE
) ==
3265 free_adbaddrinfo(adb
, &ai
);
3266 ai
= ISC_LIST_HEAD(find
->list
);
3270 * WARNING: The find is freed with the adb locked. This is done
3271 * to avoid a race condition where we free the find, some other
3272 * thread tests to see if it should be destroyed, detects it should
3273 * be, destroys it, and then we try to lock it for our check, but the
3274 * lock is destroyed.
3277 if (free_adbfind(adb
, &find
))
3283 dns_adb_cancelfind(dns_adbfind_t
*find
) {
3292 DP(DEF_LEVEL
, "dns_adb_cancelfind on find %p", find
);
3295 REQUIRE(DNS_ADB_VALID(adb
));
3297 REQUIRE(!FIND_EVENTFREED(find
));
3298 REQUIRE(FIND_WANTEVENT(find
));
3300 bucket
= find
->name_bucket
;
3301 if (bucket
== DNS_ADB_INVALIDBUCKET
)
3305 * We need to get the adbname's lock to unlink the find.
3307 unlock_bucket
= bucket
;
3308 violate_locking_hierarchy(&find
->lock
, &adb
->namelocks
[unlock_bucket
]);
3309 bucket
= find
->name_bucket
;
3310 if (bucket
!= DNS_ADB_INVALIDBUCKET
) {
3311 ISC_LIST_UNLINK(find
->adbname
->finds
, find
, plink
);
3312 find
->adbname
= NULL
;
3313 find
->name_bucket
= DNS_ADB_INVALIDBUCKET
;
3315 UNLOCK(&adb
->namelocks
[unlock_bucket
]);
3316 bucket
= DNS_ADB_INVALIDBUCKET
;
3321 if (!FIND_EVENTSENT(find
)) {
3323 task
= ev
->ev_sender
;
3324 ev
->ev_sender
= find
;
3325 ev
->ev_type
= DNS_EVENT_ADBCANCELED
;
3326 ev
->ev_destroy
= event_free
;
3327 ev
->ev_destroy_arg
= find
;
3328 find
->result_v4
= ISC_R_CANCELED
;
3329 find
->result_v6
= ISC_R_CANCELED
;
3331 DP(DEF_LEVEL
, "sending event %p to task %p for find %p",
3334 isc_task_sendanddetach(&task
, (isc_event_t
**)&ev
);
3337 UNLOCK(&find
->lock
);
3341 dns_adb_dump(dns_adb_t
*adb
, FILE *f
) {
3345 REQUIRE(DNS_ADB_VALID(adb
));
3349 * Lock the adb itself, lock all the name buckets, then lock all
3350 * the entry buckets. This should put the adb into a state where
3351 * nothing can change, so we can iterate through everything and
3352 * print at our leisure.
3356 isc_stdtime_get(&now
);
3358 for (i
= 0; i
< adb
->nnames
; i
++)
3359 RUNTIME_CHECK(cleanup_names(adb
, i
, now
) == ISC_FALSE
);
3360 for (i
= 0; i
< adb
->nentries
; i
++)
3361 RUNTIME_CHECK(cleanup_entries(adb
, i
, now
) == ISC_FALSE
);
3363 dump_adb(adb
, f
, ISC_FALSE
, now
);
3368 dump_ttl(FILE *f
, const char *legend
, isc_stdtime_t value
, isc_stdtime_t now
) {
3369 if (value
== INT_MAX
)
3371 fprintf(f
, " [%s TTL %d]", legend
, value
- now
);
3375 dump_adb(dns_adb_t
*adb
, FILE *f
, isc_boolean_t debug
, isc_stdtime_t now
) {
3377 dns_adbname_t
*name
;
3378 dns_adbentry_t
*entry
;
3380 fprintf(f
, ";\n; Address database dump\n;\n");
3381 fprintf(f
, "; [edns success/4096 timeout/1432 timeout/1232 timeout/"
3383 fprintf(f
, "; [plain success/timeout]\n;\n");
3385 fprintf(f
, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
3386 adb
, adb
->erefcnt
, adb
->irefcnt
,
3387 isc_mempool_getallocated(adb
->nhmp
));
3389 for (i
= 0; i
< adb
->nnames
; i
++)
3390 LOCK(&adb
->namelocks
[i
]);
3391 for (i
= 0; i
< adb
->nentries
; i
++)
3392 LOCK(&adb
->entrylocks
[i
]);
3397 for (i
= 0; i
< adb
->nnames
; i
++) {
3398 name
= ISC_LIST_HEAD(adb
->names
[i
]);
3402 fprintf(f
, "; bucket %d\n", i
);
3405 name
= ISC_LIST_NEXT(name
, plink
))
3408 fprintf(f
, "; name %p (flags %08x)\n",
3412 print_dns_name(f
, &name
->name
);
3413 if (dns_name_countlabels(&name
->target
) > 0) {
3414 fprintf(f
, " alias ");
3415 print_dns_name(f
, &name
->target
);
3418 dump_ttl(f
, "v4", name
->expire_v4
, now
);
3419 dump_ttl(f
, "v6", name
->expire_v6
, now
);
3420 dump_ttl(f
, "target", name
->expire_target
, now
);
3422 fprintf(f
, " [v4 %s] [v6 %s]",
3423 errnames
[name
->fetch_err
],
3424 errnames
[name
->fetch6_err
]);
3428 print_namehook_list(f
, "v4", &name
->v4
, debug
, now
);
3429 print_namehook_list(f
, "v6", &name
->v6
, debug
, now
);
3432 print_fetch_list(f
, name
);
3434 print_find_list(f
, name
);
3439 fprintf(f
, ";\n; Unassociated entries\n;\n");
3441 for (i
= 0; i
< adb
->nentries
; i
++) {
3442 entry
= ISC_LIST_HEAD(adb
->entries
[i
]);
3443 while (entry
!= NULL
) {
3444 if (entry
->refcnt
== 0)
3445 dump_entry(f
, entry
, debug
, now
);
3446 entry
= ISC_LIST_NEXT(entry
, plink
);
3453 for (i
= 0; i
< adb
->nentries
; i
++)
3454 UNLOCK(&adb
->entrylocks
[i
]);
3455 for (i
= 0; i
< adb
->nnames
; i
++)
3456 UNLOCK(&adb
->namelocks
[i
]);
3460 dump_entry(FILE *f
, dns_adbentry_t
*entry
, isc_boolean_t debug
,
3463 char addrbuf
[ISC_NETADDR_FORMATSIZE
];
3464 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3465 isc_netaddr_t netaddr
;
3466 dns_adblameinfo_t
*li
;
3468 isc_netaddr_fromsockaddr(&netaddr
, &entry
->sockaddr
);
3469 isc_netaddr_format(&netaddr
, addrbuf
, sizeof(addrbuf
));
3472 fprintf(f
, ";\t%p: refcnt %u\n", entry
, entry
->refcnt
);
3474 fprintf(f
, ";\t%s [srtt %u] [flags %08x] [edns %u/%u/%u/%u/%u] "
3475 "[plain %u/%u]", addrbuf
, entry
->srtt
, entry
->flags
,
3476 entry
->edns
, entry
->to4096
, entry
->to1432
, entry
->to1232
,
3477 entry
->to512
, entry
->plain
, entry
->plainto
);
3478 if (entry
->udpsize
!= 0U)
3479 fprintf(f
, " [udpsize %u]", entry
->udpsize
);
3480 #ifdef ISC_PLATFORM_USESIT
3481 if (entry
->sit
!= NULL
) {
3483 fprintf(f
, " [sit=");
3484 for (i
= 0; i
< entry
->sitlen
; i
++)
3485 fprintf(f
, "%02x", entry
->sit
[i
]);
3490 if (entry
->expires
!= 0)
3491 fprintf(f
, " [ttl %d]", entry
->expires
- now
);
3493 for (li
= ISC_LIST_HEAD(entry
->lameinfo
);
3495 li
= ISC_LIST_NEXT(li
, plink
)) {
3496 fprintf(f
, ";\t\t");
3497 print_dns_name(f
, &li
->qname
);
3498 dns_rdatatype_format(li
->qtype
, typebuf
, sizeof(typebuf
));
3499 fprintf(f
, " %s [lame TTL %d]\n", typebuf
,
3500 li
->lame_timer
- now
);
3505 dns_adb_dumpfind(dns_adbfind_t
*find
, FILE *f
) {
3508 dns_adbaddrinfo_t
*ai
;
3512 * Not used currently, in the API Just In Case we
3513 * want to dump out the name and/or entries too.
3518 fprintf(f
, ";Find %p\n", find
);
3519 fprintf(f
, ";\tqpending %08x partial %08x options %08x flags %08x\n",
3520 find
->query_pending
, find
->partial_result
,
3521 find
->options
, find
->flags
);
3522 fprintf(f
, ";\tname_bucket %d, name %p, event sender %p\n",
3523 find
->name_bucket
, find
->adbname
, find
->event
.ev_sender
);
3525 ai
= ISC_LIST_HEAD(find
->list
);
3527 fprintf(f
, "\tAddresses:\n");
3528 while (ai
!= NULL
) {
3530 switch (sa
->type
.sa
.sa_family
) {
3532 tmpp
= inet_ntop(AF_INET
, &sa
->type
.sin
.sin_addr
,
3536 tmpp
= inet_ntop(AF_INET6
, &sa
->type
.sin6
.sin6_addr
,
3544 tmpp
= "BadAddress";
3546 fprintf(f
, "\t\tentry %p, flags %08x"
3547 " srtt %u addr %s\n",
3548 ai
->entry
, ai
->flags
, ai
->srtt
, tmpp
);
3550 ai
= ISC_LIST_NEXT(ai
, publink
);
3553 UNLOCK(&find
->lock
);
3557 print_dns_name(FILE *f
, dns_name_t
*name
) {
3558 char buf
[DNS_NAME_FORMATSIZE
];
3562 dns_name_format(name
, buf
, sizeof(buf
));
3563 fprintf(f
, "%s", buf
);
3567 print_namehook_list(FILE *f
, const char *legend
, dns_adbnamehooklist_t
*list
,
3568 isc_boolean_t debug
, isc_stdtime_t now
)
3570 dns_adbnamehook_t
*nh
;
3572 for (nh
= ISC_LIST_HEAD(*list
);
3574 nh
= ISC_LIST_NEXT(nh
, plink
))
3577 fprintf(f
, ";\tHook(%s) %p\n", legend
, nh
);
3578 dump_entry(f
, nh
->entry
, debug
, now
);
3583 print_fetch(FILE *f
, dns_adbfetch_t
*ft
, const char *type
) {
3584 fprintf(f
, "\t\tFetch(%s): %p -> { fetch %p }\n",
3585 type
, ft
, ft
->fetch
);
3589 print_fetch_list(FILE *f
, dns_adbname_t
*n
) {
3590 if (NAME_FETCH_A(n
))
3591 print_fetch(f
, n
->fetch_a
, "A");
3592 if (NAME_FETCH_AAAA(n
))
3593 print_fetch(f
, n
->fetch_aaaa
, "AAAA");
3597 print_find_list(FILE *f
, dns_adbname_t
*name
) {
3598 dns_adbfind_t
*find
;
3600 find
= ISC_LIST_HEAD(name
->finds
);
3601 while (find
!= NULL
) {
3602 dns_adb_dumpfind(find
, f
);
3603 find
= ISC_LIST_NEXT(find
, plink
);
3608 dbfind_name(dns_adbname_t
*adbname
, isc_stdtime_t now
, dns_rdatatype_t rdtype
)
3610 isc_result_t result
;
3611 dns_rdataset_t rdataset
;
3613 dns_fixedname_t foundname
;
3616 INSIST(DNS_ADBNAME_VALID(adbname
));
3618 INSIST(DNS_ADB_VALID(adb
));
3619 INSIST(rdtype
== dns_rdatatype_a
|| rdtype
== dns_rdatatype_aaaa
);
3621 dns_fixedname_init(&foundname
);
3622 fname
= dns_fixedname_name(&foundname
);
3623 dns_rdataset_init(&rdataset
);
3625 if (rdtype
== dns_rdatatype_a
)
3626 adbname
->fetch_err
= FIND_ERR_UNEXPECTED
;
3628 adbname
->fetch6_err
= FIND_ERR_UNEXPECTED
;
3631 * We need to specify whether to search static-stub zones (if
3632 * configured) depending on whether this is a "start at zone" lookup,
3633 * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
3634 * case NAME_STARTATZONE is set) we need to stop the search at any
3635 * matching static-stub zone without looking into the cache to honor
3636 * the configuration on which server we should send queries to.
3638 result
= dns_view_find2(adb
->view
, &adbname
->name
, rdtype
, now
,
3639 NAME_GLUEOK(adbname
) ? DNS_DBFIND_GLUEOK
: 0,
3640 ISC_TF(NAME_HINTOK(adbname
)),
3641 (adbname
->flags
& NAME_STARTATZONE
) != 0 ?
3642 ISC_TRUE
: ISC_FALSE
,
3643 NULL
, NULL
, fname
, &rdataset
, NULL
);
3645 /* XXXVIX this switch statement is too sparse to gen a jump table. */
3651 * Found in the database. Even if we can't copy out
3652 * any information, return success, or else a fetch
3653 * will be made, which will only make things worse.
3655 if (rdtype
== dns_rdatatype_a
)
3656 adbname
->fetch_err
= FIND_ERR_SUCCESS
;
3658 adbname
->fetch6_err
= FIND_ERR_SUCCESS
;
3659 result
= import_rdataset(adbname
, &rdataset
, now
);
3661 case DNS_R_NXDOMAIN
:
3664 * We're authoritative and the data doesn't exist.
3665 * Make up a negative cache entry so we don't ask again
3668 * XXXRTH What time should we use? I'm putting in 30 seconds
3671 if (rdtype
== dns_rdatatype_a
) {
3672 adbname
->expire_v4
= now
+ 30;
3674 "adb name %p: Caching auth negative entry for A",
3676 if (result
== DNS_R_NXDOMAIN
)
3677 adbname
->fetch_err
= FIND_ERR_NXDOMAIN
;
3679 adbname
->fetch_err
= FIND_ERR_NXRRSET
;
3682 "adb name %p: Caching auth negative entry for AAAA",
3684 adbname
->expire_v6
= now
+ 30;
3685 if (result
== DNS_R_NXDOMAIN
)
3686 adbname
->fetch6_err
= FIND_ERR_NXDOMAIN
;
3688 adbname
->fetch6_err
= FIND_ERR_NXRRSET
;
3691 case DNS_R_NCACHENXDOMAIN
:
3692 case DNS_R_NCACHENXRRSET
:
3694 * We found a negative cache entry. Pull the TTL from it
3695 * so we won't ask again for a while.
3697 rdataset
.ttl
= ttlclamp(rdataset
.ttl
);
3698 if (rdtype
== dns_rdatatype_a
) {
3699 adbname
->expire_v4
= rdataset
.ttl
+ now
;
3700 if (result
== DNS_R_NCACHENXDOMAIN
)
3701 adbname
->fetch_err
= FIND_ERR_NXDOMAIN
;
3703 adbname
->fetch_err
= FIND_ERR_NXRRSET
;
3705 "adb name %p: Caching negative entry for A (ttl %u)",
3706 adbname
, rdataset
.ttl
);
3709 "adb name %p: Caching negative entry for AAAA (ttl %u)",
3710 adbname
, rdataset
.ttl
);
3711 adbname
->expire_v6
= rdataset
.ttl
+ now
;
3712 if (result
== DNS_R_NCACHENXDOMAIN
)
3713 adbname
->fetch6_err
= FIND_ERR_NXDOMAIN
;
3715 adbname
->fetch6_err
= FIND_ERR_NXRRSET
;
3721 * Clear the hint and glue flags, so this will match
3724 adbname
->flags
&= ~(DNS_ADBFIND_GLUEOK
| DNS_ADBFIND_HINTOK
);
3726 rdataset
.ttl
= ttlclamp(rdataset
.ttl
);
3727 clean_target(adb
, &adbname
->target
);
3728 adbname
->expire_target
= INT_MAX
;
3729 result
= set_target(adb
, &adbname
->name
, fname
, &rdataset
,
3731 if (result
== ISC_R_SUCCESS
) {
3732 result
= DNS_R_ALIAS
;
3734 "adb name %p: caching alias target",
3736 adbname
->expire_target
= rdataset
.ttl
+ now
;
3738 if (rdtype
== dns_rdatatype_a
)
3739 adbname
->fetch_err
= FIND_ERR_SUCCESS
;
3741 adbname
->fetch6_err
= FIND_ERR_SUCCESS
;
3745 if (dns_rdataset_isassociated(&rdataset
))
3746 dns_rdataset_disassociate(&rdataset
);
3752 fetch_callback(isc_task_t
*task
, isc_event_t
*ev
) {
3753 dns_fetchevent_t
*dev
;
3754 dns_adbname_t
*name
;
3756 dns_adbfetch_t
*fetch
;
3758 isc_eventtype_t ev_status
;
3760 isc_result_t result
;
3761 unsigned int address_type
;
3762 isc_boolean_t want_check_exit
= ISC_FALSE
;
3766 INSIST(ev
->ev_type
== DNS_EVENT_FETCHDONE
);
3767 dev
= (dns_fetchevent_t
*)ev
;
3769 INSIST(DNS_ADBNAME_VALID(name
));
3771 INSIST(DNS_ADB_VALID(adb
));
3773 bucket
= name
->lock_bucket
;
3774 LOCK(&adb
->namelocks
[bucket
]);
3776 INSIST(NAME_FETCH_A(name
) || NAME_FETCH_AAAA(name
));
3778 if (NAME_FETCH_A(name
) && (name
->fetch_a
->fetch
== dev
->fetch
)) {
3779 address_type
= DNS_ADBFIND_INET
;
3780 fetch
= name
->fetch_a
;
3781 name
->fetch_a
= NULL
;
3782 } else if (NAME_FETCH_AAAA(name
)
3783 && (name
->fetch_aaaa
->fetch
== dev
->fetch
)) {
3784 address_type
= DNS_ADBFIND_INET6
;
3785 fetch
= name
->fetch_aaaa
;
3786 name
->fetch_aaaa
= NULL
;
3790 INSIST(address_type
!= 0 && fetch
!= NULL
);
3792 dns_resolver_destroyfetch(&fetch
->fetch
);
3795 ev_status
= DNS_EVENT_ADBNOMOREADDRESSES
;
3798 * Cleanup things we don't care about.
3800 if (dev
->node
!= NULL
)
3801 dns_db_detachnode(dev
->db
, &dev
->node
);
3802 if (dev
->db
!= NULL
)
3803 dns_db_detach(&dev
->db
);
3806 * If this name is marked as dead, clean up, throwing away
3807 * potentially good data.
3809 if (NAME_DEAD(name
)) {
3810 free_adbfetch(adb
, &fetch
);
3811 isc_event_free(&ev
);
3813 want_check_exit
= kill_name(&name
, DNS_EVENT_ADBCANCELED
);
3815 UNLOCK(&adb
->namelocks
[bucket
]);
3817 if (want_check_exit
) {
3826 isc_stdtime_get(&now
);
3829 * If we got a negative cache response, remember it.
3831 if (NCACHE_RESULT(dev
->result
)) {
3832 dev
->rdataset
->ttl
= ttlclamp(dev
->rdataset
->ttl
);
3833 if (address_type
== DNS_ADBFIND_INET
) {
3834 DP(NCACHE_LEVEL
, "adb fetch name %p: "
3835 "caching negative entry for A (ttl %u)",
3836 name
, dev
->rdataset
->ttl
);
3837 name
->expire_v4
= ISC_MIN(name
->expire_v4
,
3838 dev
->rdataset
->ttl
+ now
);
3839 if (dev
->result
== DNS_R_NCACHENXDOMAIN
)
3840 name
->fetch_err
= FIND_ERR_NXDOMAIN
;
3842 name
->fetch_err
= FIND_ERR_NXRRSET
;
3843 inc_stats(adb
, dns_resstatscounter_gluefetchv4fail
);
3845 DP(NCACHE_LEVEL
, "adb fetch name %p: "
3846 "caching negative entry for AAAA (ttl %u)",
3847 name
, dev
->rdataset
->ttl
);
3848 name
->expire_v6
= ISC_MIN(name
->expire_v6
,
3849 dev
->rdataset
->ttl
+ now
);
3850 if (dev
->result
== DNS_R_NCACHENXDOMAIN
)
3851 name
->fetch6_err
= FIND_ERR_NXDOMAIN
;
3853 name
->fetch6_err
= FIND_ERR_NXRRSET
;
3854 inc_stats(adb
, dns_resstatscounter_gluefetchv6fail
);
3860 * Handle CNAME/DNAME.
3862 if (dev
->result
== DNS_R_CNAME
|| dev
->result
== DNS_R_DNAME
) {
3863 dev
->rdataset
->ttl
= ttlclamp(dev
->rdataset
->ttl
);
3864 clean_target(adb
, &name
->target
);
3865 name
->expire_target
= INT_MAX
;
3866 result
= set_target(adb
, &name
->name
,
3867 dns_fixedname_name(&dev
->foundname
),
3870 if (result
== ISC_R_SUCCESS
) {
3872 "adb fetch name %p: caching alias target",
3874 name
->expire_target
= dev
->rdataset
->ttl
+ now
;
3880 * Did we get back junk? If so, and there are no more fetches
3881 * sitting out there, tell all the finds about it.
3883 if (dev
->result
!= ISC_R_SUCCESS
) {
3884 char buf
[DNS_NAME_FORMATSIZE
];
3886 dns_name_format(&name
->name
, buf
, sizeof(buf
));
3887 DP(DEF_LEVEL
, "adb: fetch of '%s' %s failed: %s",
3888 buf
, address_type
== DNS_ADBFIND_INET
? "A" : "AAAA",
3889 dns_result_totext(dev
->result
));
3891 * Don't record a failure unless this is the initial
3894 if (fetch
->depth
> 1)
3896 /* XXXMLG Don't pound on bad servers. */
3897 if (address_type
== DNS_ADBFIND_INET
) {
3898 name
->expire_v4
= ISC_MIN(name
->expire_v4
, now
+ 10);
3899 name
->fetch_err
= FIND_ERR_FAILURE
;
3900 inc_stats(adb
, dns_resstatscounter_gluefetchv4fail
);
3902 name
->expire_v6
= ISC_MIN(name
->expire_v6
, now
+ 10);
3903 name
->fetch6_err
= FIND_ERR_FAILURE
;
3904 inc_stats(adb
, dns_resstatscounter_gluefetchv6fail
);
3910 * We got something potentially useful.
3912 result
= import_rdataset(name
, &fetch
->rdataset
, now
);
3915 if (result
== ISC_R_SUCCESS
) {
3916 ev_status
= DNS_EVENT_ADBMOREADDRESSES
;
3917 if (address_type
== DNS_ADBFIND_INET
)
3918 name
->fetch_err
= FIND_ERR_SUCCESS
;
3920 name
->fetch6_err
= FIND_ERR_SUCCESS
;
3924 free_adbfetch(adb
, &fetch
);
3925 isc_event_free(&ev
);
3927 clean_finds_at_name(name
, ev_status
, address_type
);
3929 UNLOCK(&adb
->namelocks
[bucket
]);
3933 fetch_name(dns_adbname_t
*adbname
, isc_boolean_t start_at_zone
,
3934 unsigned int depth
, isc_counter_t
*qc
, dns_rdatatype_t type
)
3936 isc_result_t result
;
3937 dns_adbfetch_t
*fetch
= NULL
;
3939 dns_fixedname_t fixed
;
3941 dns_rdataset_t rdataset
;
3942 dns_rdataset_t
*nameservers
;
3943 unsigned int options
;
3945 INSIST(DNS_ADBNAME_VALID(adbname
));
3947 INSIST(DNS_ADB_VALID(adb
));
3949 INSIST((type
== dns_rdatatype_a
&& !NAME_FETCH_V4(adbname
)) ||
3950 (type
== dns_rdatatype_aaaa
&& !NAME_FETCH_V6(adbname
)));
3952 adbname
->fetch_err
= FIND_ERR_NOTFOUND
;
3956 dns_rdataset_init(&rdataset
);
3958 options
= DNS_FETCHOPT_NOVALIDATE
;
3959 if (start_at_zone
) {
3961 "fetch_name: starting at zone for name %p",
3963 dns_fixedname_init(&fixed
);
3964 name
= dns_fixedname_name(&fixed
);
3965 result
= dns_view_findzonecut2(adb
->view
, &adbname
->name
, name
,
3966 0, 0, ISC_TRUE
, ISC_FALSE
,
3968 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_HINT
)
3970 nameservers
= &rdataset
;
3971 options
|= DNS_FETCHOPT_UNSHARED
;
3974 fetch
= new_adbfetch(adb
);
3975 if (fetch
== NULL
) {
3976 result
= ISC_R_NOMEMORY
;
3979 fetch
->depth
= depth
;
3981 result
= dns_resolver_createfetch3(adb
->view
->resolver
, &adbname
->name
,
3982 type
, name
, nameservers
, NULL
,
3983 NULL
, 0, options
, depth
, qc
,
3984 adb
->task
, fetch_callback
, adbname
,
3985 &fetch
->rdataset
, NULL
,
3987 if (result
!= ISC_R_SUCCESS
)
3990 if (type
== dns_rdatatype_a
) {
3991 adbname
->fetch_a
= fetch
;
3992 inc_stats(adb
, dns_resstatscounter_gluefetchv4
);
3994 adbname
->fetch_aaaa
= fetch
;
3995 inc_stats(adb
, dns_resstatscounter_gluefetchv6
);
3997 fetch
= NULL
; /* Keep us from cleaning this up below. */
4001 free_adbfetch(adb
, &fetch
);
4002 if (dns_rdataset_isassociated(&rdataset
))
4003 dns_rdataset_disassociate(&rdataset
);
4009 * XXXMLG Needs to take a find argument and an address info, no zone or adb,
4010 * since these can be extracted from the find itself.
4013 dns_adb_marklame(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
, dns_name_t
*qname
,
4014 dns_rdatatype_t qtype
, isc_stdtime_t expire_time
)
4016 dns_adblameinfo_t
*li
;
4018 isc_result_t result
= ISC_R_SUCCESS
;
4020 REQUIRE(DNS_ADB_VALID(adb
));
4021 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4022 REQUIRE(qname
!= NULL
);
4024 bucket
= addr
->entry
->lock_bucket
;
4025 LOCK(&adb
->entrylocks
[bucket
]);
4026 li
= ISC_LIST_HEAD(addr
->entry
->lameinfo
);
4027 while (li
!= NULL
&&
4028 (li
->qtype
!= qtype
|| !dns_name_equal(qname
, &li
->qname
)))
4029 li
= ISC_LIST_NEXT(li
, plink
);
4031 if (expire_time
> li
->lame_timer
)
4032 li
->lame_timer
= expire_time
;
4035 li
= new_adblameinfo(adb
, qname
, qtype
);
4037 result
= ISC_R_NOMEMORY
;
4041 li
->lame_timer
= expire_time
;
4043 ISC_LIST_PREPEND(addr
->entry
->lameinfo
, li
, plink
);
4045 UNLOCK(&adb
->entrylocks
[bucket
]);
4051 dns_adb_adjustsrtt(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
,
4052 unsigned int rtt
, unsigned int factor
)
4055 isc_stdtime_t now
= 0;
4057 REQUIRE(DNS_ADB_VALID(adb
));
4058 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4059 REQUIRE(factor
<= 10);
4061 bucket
= addr
->entry
->lock_bucket
;
4062 LOCK(&adb
->entrylocks
[bucket
]);
4064 if (addr
->entry
->expires
== 0 || factor
== DNS_ADB_RTTADJAGE
)
4065 isc_stdtime_get(&now
);
4066 adjustsrtt(addr
, rtt
, factor
, now
);
4068 UNLOCK(&adb
->entrylocks
[bucket
]);
4072 dns_adb_agesrtt(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
, isc_stdtime_t now
) {
4075 REQUIRE(DNS_ADB_VALID(adb
));
4076 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4078 bucket
= addr
->entry
->lock_bucket
;
4079 LOCK(&adb
->entrylocks
[bucket
]);
4081 adjustsrtt(addr
, 0, DNS_ADB_RTTADJAGE
, now
);
4083 UNLOCK(&adb
->entrylocks
[bucket
]);
4087 adjustsrtt(dns_adbaddrinfo_t
*addr
, unsigned int rtt
, unsigned int factor
,
4090 isc_uint64_t new_srtt
;
4092 if (factor
== DNS_ADB_RTTADJAGE
) {
4093 if (addr
->entry
->lastage
!= now
) {
4094 new_srtt
= addr
->entry
->srtt
;
4096 new_srtt
-= addr
->entry
->srtt
;
4098 addr
->entry
->lastage
= now
;
4100 new_srtt
= addr
->entry
->srtt
;
4102 new_srtt
= ((isc_uint64_t
)addr
->entry
->srtt
/ 10 * factor
)
4103 + ((isc_uint64_t
)rtt
/ 10 * (10 - factor
));
4105 addr
->entry
->srtt
= (unsigned int) new_srtt
;
4106 addr
->srtt
= (unsigned int) new_srtt
;
4108 if (addr
->entry
->expires
== 0)
4109 addr
->entry
->expires
= now
+ ADB_ENTRY_WINDOW
;
4113 dns_adb_changeflags(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
,
4114 unsigned int bits
, unsigned int mask
)
4119 REQUIRE(DNS_ADB_VALID(adb
));
4120 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4122 REQUIRE((bits
& ENTRY_IS_DEAD
) == 0);
4123 REQUIRE((mask
& ENTRY_IS_DEAD
) == 0);
4125 bucket
= addr
->entry
->lock_bucket
;
4126 LOCK(&adb
->entrylocks
[bucket
]);
4128 addr
->entry
->flags
= (addr
->entry
->flags
& ~mask
) | (bits
& mask
);
4129 if (addr
->entry
->expires
== 0) {
4130 isc_stdtime_get(&now
);
4131 addr
->entry
->expires
= now
+ ADB_ENTRY_WINDOW
;
4135 * Note that we do not update the other bits in addr->flags with
4136 * the most recent values from addr->entry->flags.
4138 addr
->flags
= (addr
->flags
& ~mask
) | (bits
& mask
);
4140 UNLOCK(&adb
->entrylocks
[bucket
]);
4145 dns_adb_noedns(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
) {
4147 isc_boolean_t noedns
= ISC_FALSE
;
4149 REQUIRE(DNS_ADB_VALID(adb
));
4150 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4152 bucket
= addr
->entry
->lock_bucket
;
4153 LOCK(&adb
->entrylocks
[bucket
]);
4154 if (addr
->entry
->edns
== 0U &&
4155 (addr
->entry
->plain
> EDNSTOS
|| addr
->entry
->to4096
> EDNSTOS
)) {
4156 if (((addr
->entry
->plain
+ addr
->entry
->to4096
) & 0x3f) != 0) {
4160 * Increment plain so we don't get stuck.
4162 addr
->entry
->plain
++;
4163 if (addr
->entry
->plain
== 0xff) {
4164 addr
->entry
->edns
>>= 1;
4165 addr
->entry
->to4096
>>= 1;
4166 addr
->entry
->to1432
>>= 1;
4167 addr
->entry
->to1232
>>= 1;
4168 addr
->entry
->to512
>>= 1;
4169 addr
->entry
->plain
>>= 1;
4170 addr
->entry
->plainto
>>= 1;
4174 UNLOCK(&adb
->entrylocks
[bucket
]);
4179 dns_adb_plainresponse(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
) {
4182 REQUIRE(DNS_ADB_VALID(adb
));
4183 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4185 bucket
= addr
->entry
->lock_bucket
;
4186 LOCK(&adb
->entrylocks
[bucket
]);
4188 addr
->entry
->plain
++;
4189 if (addr
->entry
->plain
== 0xff) {
4190 addr
->entry
->edns
>>= 1;
4191 addr
->entry
->to4096
>>= 1;
4192 addr
->entry
->to1432
>>= 1;
4193 addr
->entry
->to1232
>>= 1;
4194 addr
->entry
->to512
>>= 1;
4195 addr
->entry
->plain
>>= 1;
4196 addr
->entry
->plainto
>>= 1;
4198 UNLOCK(&adb
->entrylocks
[bucket
]);
4202 dns_adb_timeout(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
) {
4205 REQUIRE(DNS_ADB_VALID(adb
));
4206 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4208 bucket
= addr
->entry
->lock_bucket
;
4209 LOCK(&adb
->entrylocks
[bucket
]);
4211 * If we have not had a successful query then clear all
4212 * edns timeout information.
4214 if (addr
->entry
->edns
== 0 && addr
->entry
->plain
== 0) {
4215 addr
->entry
->to512
= 0;
4216 addr
->entry
->to1232
= 0;
4217 addr
->entry
->to1432
= 0;
4218 addr
->entry
->to4096
= 0;
4220 addr
->entry
->to512
>>= 1;
4221 addr
->entry
->to1232
>>= 1;
4222 addr
->entry
->to1432
>>= 1;
4223 addr
->entry
->to4096
>>= 1;
4225 addr
->entry
->plainto
++;
4226 if (addr
->entry
->plainto
== 0xff) {
4227 addr
->entry
->edns
>>= 1;
4228 addr
->entry
->plain
>>= 1;
4229 addr
->entry
->plainto
>>= 1;
4231 UNLOCK(&adb
->entrylocks
[bucket
]);
4235 dns_adb_ednsto(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
, unsigned int size
) {
4238 REQUIRE(DNS_ADB_VALID(adb
));
4239 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4241 bucket
= addr
->entry
->lock_bucket
;
4242 LOCK(&adb
->entrylocks
[bucket
]);
4245 if (addr
->entry
->to512
<= EDNSTOS
) {
4246 addr
->entry
->to512
++;
4247 addr
->entry
->to1232
++;
4248 addr
->entry
->to1432
++;
4249 addr
->entry
->to4096
++;
4251 } else if (size
<= 1232U) {
4252 if (addr
->entry
->to1232
<= EDNSTOS
) {
4253 addr
->entry
->to1232
++;
4254 addr
->entry
->to1432
++;
4255 addr
->entry
->to4096
++;
4257 } else if (size
<= 1432U) {
4258 if (addr
->entry
->to1432
<= EDNSTOS
) {
4259 addr
->entry
->to1432
++;
4260 addr
->entry
->to4096
++;
4263 if (addr
->entry
->to4096
<= EDNSTOS
)
4264 addr
->entry
->to4096
++;
4267 if (addr
->entry
->to4096
== 0xff) {
4268 addr
->entry
->edns
>>= 1;
4269 addr
->entry
->to4096
>>= 1;
4270 addr
->entry
->to1432
>>= 1;
4271 addr
->entry
->to1232
>>= 1;
4272 addr
->entry
->to512
>>= 1;
4273 addr
->entry
->plain
>>= 1;
4274 addr
->entry
->plainto
>>= 1;
4276 UNLOCK(&adb
->entrylocks
[bucket
]);
4280 dns_adb_setudpsize(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
, unsigned int size
) {
4283 REQUIRE(DNS_ADB_VALID(adb
));
4284 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4286 bucket
= addr
->entry
->lock_bucket
;
4287 LOCK(&adb
->entrylocks
[bucket
]);
4290 if (size
> addr
->entry
->udpsize
)
4291 addr
->entry
->udpsize
= size
;
4292 addr
->entry
->edns
++;
4293 if (addr
->entry
->edns
== 0xff) {
4294 addr
->entry
->edns
>>= 1;
4295 addr
->entry
->to4096
>>= 1;
4296 addr
->entry
->to1432
>>= 1;
4297 addr
->entry
->to1232
>>= 1;
4298 addr
->entry
->to512
>>= 1;
4299 addr
->entry
->plain
>>= 1;
4300 addr
->entry
->plainto
>>= 1;
4302 UNLOCK(&adb
->entrylocks
[bucket
]);
4306 dns_adb_getudpsize(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
) {
4310 REQUIRE(DNS_ADB_VALID(adb
));
4311 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4313 bucket
= addr
->entry
->lock_bucket
;
4314 LOCK(&adb
->entrylocks
[bucket
]);
4315 size
= addr
->entry
->udpsize
;
4316 UNLOCK(&adb
->entrylocks
[bucket
]);
4322 dns_adb_probesize(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
) {
4323 return dns_adb_probesize2(adb
, addr
, 0);
4327 dns_adb_probesize2(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
, int lookups
) {
4331 REQUIRE(DNS_ADB_VALID(adb
));
4332 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4334 bucket
= addr
->entry
->lock_bucket
;
4335 LOCK(&adb
->entrylocks
[bucket
]);
4336 if (addr
->entry
->to1232
> EDNSTOS
|| lookups
>= 2)
4338 else if (addr
->entry
->to1432
> EDNSTOS
|| lookups
>= 1)
4340 else if (addr
->entry
->to4096
> EDNSTOS
)
4345 * Don't shrink probe size below what we have seen due to multiple
4349 size
< addr
->entry
->udpsize
&& addr
->entry
->udpsize
< 4096)
4350 size
= addr
->entry
->udpsize
;
4351 UNLOCK(&adb
->entrylocks
[bucket
]);
4357 dns_adb_setsit(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
,
4358 const unsigned char *sit
, size_t len
)
4362 REQUIRE(DNS_ADB_VALID(adb
));
4363 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4365 bucket
= addr
->entry
->lock_bucket
;
4366 LOCK(&adb
->entrylocks
[bucket
]);
4368 if (addr
->entry
->sit
!= NULL
&&
4369 (sit
== NULL
|| len
!= addr
->entry
->sitlen
)) {
4370 isc_mem_put(adb
->mctx
, addr
->entry
->sit
, addr
->entry
->sitlen
);
4371 addr
->entry
->sit
= NULL
;
4372 addr
->entry
->sitlen
= 0;
4375 if (addr
->entry
->sit
== NULL
&& sit
!= NULL
&& len
!= 0U) {
4376 addr
->entry
->sit
= isc_mem_get(adb
->mctx
, len
);
4377 if (addr
->entry
->sit
!= NULL
)
4378 addr
->entry
->sitlen
= (isc_uint16_t
)len
;
4381 if (addr
->entry
->sit
!= NULL
)
4382 memmove(addr
->entry
->sit
, sit
, len
);
4383 UNLOCK(&adb
->entrylocks
[bucket
]);
4387 dns_adb_getsit(dns_adb_t
*adb
, dns_adbaddrinfo_t
*addr
,
4388 unsigned char *sit
, size_t len
)
4392 REQUIRE(DNS_ADB_VALID(adb
));
4393 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4395 bucket
= addr
->entry
->lock_bucket
;
4396 LOCK(&adb
->entrylocks
[bucket
]);
4397 if (sit
!= NULL
&& addr
->entry
->sit
!= NULL
&&
4398 len
>= addr
->entry
->sitlen
)
4400 memmove(sit
, addr
->entry
->sit
, addr
->entry
->sitlen
);
4401 len
= addr
->entry
->sitlen
;
4404 UNLOCK(&adb
->entrylocks
[bucket
]);
4410 dns_adb_findaddrinfo(dns_adb_t
*adb
, isc_sockaddr_t
*sa
,
4411 dns_adbaddrinfo_t
**addrp
, isc_stdtime_t now
)
4414 dns_adbentry_t
*entry
;
4415 dns_adbaddrinfo_t
*addr
;
4416 isc_result_t result
;
4419 REQUIRE(DNS_ADB_VALID(adb
));
4420 REQUIRE(addrp
!= NULL
&& *addrp
== NULL
);
4424 result
= ISC_R_SUCCESS
;
4425 bucket
= DNS_ADB_INVALIDBUCKET
;
4426 entry
= find_entry_and_lock(adb
, sa
, &bucket
, now
);
4427 INSIST(bucket
!= DNS_ADB_INVALIDBUCKET
);
4428 if (adb
->entry_sd
[bucket
]) {
4429 result
= ISC_R_SHUTTINGDOWN
;
4432 if (entry
== NULL
) {
4434 * We don't know anything about this address.
4436 entry
= new_adbentry(adb
);
4437 if (entry
== NULL
) {
4438 result
= ISC_R_NOMEMORY
;
4441 entry
->sockaddr
= *sa
;
4442 link_entry(adb
, bucket
, entry
);
4443 DP(ENTER_LEVEL
, "findaddrinfo: new entry %p", entry
);
4445 DP(ENTER_LEVEL
, "findaddrinfo: found entry %p", entry
);
4447 port
= isc_sockaddr_getport(sa
);
4448 addr
= new_adbaddrinfo(adb
, entry
, port
);
4450 result
= ISC_R_NOMEMORY
;
4452 inc_entry_refcnt(adb
, entry
, ISC_FALSE
);
4457 UNLOCK(&adb
->entrylocks
[bucket
]);
4463 dns_adb_freeaddrinfo(dns_adb_t
*adb
, dns_adbaddrinfo_t
**addrp
) {
4464 dns_adbaddrinfo_t
*addr
;
4465 dns_adbentry_t
*entry
;
4468 isc_boolean_t want_check_exit
= ISC_FALSE
;
4469 isc_boolean_t overmem
;
4471 REQUIRE(DNS_ADB_VALID(adb
));
4472 REQUIRE(addrp
!= NULL
);
4474 REQUIRE(DNS_ADBADDRINFO_VALID(addr
));
4475 entry
= addr
->entry
;
4476 REQUIRE(DNS_ADBENTRY_VALID(entry
));
4479 overmem
= isc_mem_isovermem(adb
->mctx
);
4481 bucket
= addr
->entry
->lock_bucket
;
4482 LOCK(&adb
->entrylocks
[bucket
]);
4484 if (entry
->expires
== 0) {
4485 isc_stdtime_get(&now
);
4486 entry
->expires
= now
+ ADB_ENTRY_WINDOW
;
4489 want_check_exit
= dec_entry_refcnt(adb
, overmem
, entry
, ISC_FALSE
);
4491 UNLOCK(&adb
->entrylocks
[bucket
]);
4494 free_adbaddrinfo(adb
, &addr
);
4496 if (want_check_exit
) {
4504 dns_adb_flush(dns_adb_t
*adb
) {
4507 INSIST(DNS_ADB_VALID(adb
));
4512 * Call our cleanup routines.
4514 for (i
= 0; i
< adb
->nnames
; i
++)
4515 RUNTIME_CHECK(cleanup_names(adb
, i
, INT_MAX
) == ISC_FALSE
);
4516 for (i
= 0; i
< adb
->nentries
; i
++)
4517 RUNTIME_CHECK(cleanup_entries(adb
, i
, INT_MAX
) == ISC_FALSE
);
4519 #ifdef DUMP_ADB_AFTER_CLEANING
4520 dump_adb(adb
, stdout
, ISC_TRUE
, INT_MAX
);
4527 dns_adb_flushname(dns_adb_t
*adb
, dns_name_t
*name
) {
4528 dns_adbname_t
*adbname
;
4529 dns_adbname_t
*nextname
;
4532 REQUIRE(DNS_ADB_VALID(adb
));
4533 REQUIRE(name
!= NULL
);
4536 bucket
= dns_name_hash(name
, ISC_FALSE
) % adb
->nnames
;
4537 LOCK(&adb
->namelocks
[bucket
]);
4538 adbname
= ISC_LIST_HEAD(adb
->names
[bucket
]);
4539 while (adbname
!= NULL
) {
4540 nextname
= ISC_LIST_NEXT(adbname
, plink
);
4541 if (!NAME_DEAD(adbname
) &&
4542 dns_name_equal(name
, &adbname
->name
)) {
4543 RUNTIME_CHECK(kill_name(&adbname
,
4544 DNS_EVENT_ADBCANCELED
) ==
4549 UNLOCK(&adb
->namelocks
[bucket
]);
4554 dns_adb_flushnames(dns_adb_t
*adb
, dns_name_t
*name
) {
4555 dns_adbname_t
*adbname
, *nextname
;
4558 REQUIRE(DNS_ADB_VALID(adb
));
4559 REQUIRE(name
!= NULL
);
4562 for (i
= 0; i
< adb
->nnames
; i
++) {
4563 LOCK(&adb
->namelocks
[i
]);
4564 adbname
= ISC_LIST_HEAD(adb
->names
[i
]);
4565 while (adbname
!= NULL
) {
4567 nextname
= ISC_LIST_NEXT(adbname
, plink
);
4568 if (!NAME_DEAD(adbname
) &&
4569 dns_name_issubdomain(&adbname
->name
, name
))
4571 ret
= kill_name(&adbname
,
4572 DNS_EVENT_ADBCANCELED
);
4573 RUNTIME_CHECK(ret
== ISC_FALSE
);
4577 UNLOCK(&adb
->namelocks
[i
]);
4583 water(void *arg
, int mark
) {
4585 * We're going to change the way to handle overmem condition: use
4586 * isc_mem_isovermem() instead of storing the state via this callback,
4587 * since the latter way tends to cause race conditions.
4588 * To minimize the change, and in case we re-enable the callback
4589 * approach, however, keep this function at the moment.
4592 dns_adb_t
*adb
= arg
;
4593 isc_boolean_t overmem
= ISC_TF(mark
== ISC_MEM_HIWATER
);
4595 REQUIRE(DNS_ADB_VALID(adb
));
4597 DP(ISC_LOG_DEBUG(1),
4598 "adb reached %s water mark", overmem
? "high" : "low");
4602 dns_adb_setadbsize(dns_adb_t
*adb
, size_t size
) {
4603 size_t hiwater
, lowater
;
4605 INSIST(DNS_ADB_VALID(adb
));
4607 if (size
!= 0U && size
< DNS_ADB_MINADBSIZE
)
4608 size
= DNS_ADB_MINADBSIZE
;
4610 hiwater
= size
- (size
>> 3); /* Approximately 7/8ths. */
4611 lowater
= size
- (size
>> 2); /* Approximately 3/4ths. */
4613 if (size
== 0U || hiwater
== 0U || lowater
== 0U)
4614 isc_mem_setwater(adb
->mctx
, water
, adb
, 0, 0);
4616 isc_mem_setwater(adb
->mctx
, water
, adb
, hiwater
, lowater
);