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