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