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