/contrib/bind9/lib/dns/adb.c
C | 4113 lines | 2943 code | 573 blank | 597 comment | 770 complexity | 4b87144099769830b153bfe500bfa4ea MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/* 2 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/*! \file 21 * 22 * \note 23 * In finds, if task == NULL, no events will be generated, and no events 24 * have been sent. If task != NULL but taskaction == NULL, an event has been 25 * posted but not yet freed. If neither are NULL, no event was posted. 26 * 27 */ 28 29#include <config.h> 30 31#include <limits.h> 32 33#include <isc/mutexblock.h> 34#include <isc/netaddr.h> 35#include <isc/random.h> 36#include <isc/stats.h> 37#include <isc/string.h> /* Required for HP/UX (and others?) */ 38#include <isc/task.h> 39#include <isc/util.h> 40 41#include <dns/adb.h> 42#include <dns/db.h> 43#include <dns/events.h> 44#include <dns/log.h> 45#include <dns/rdata.h> 46#include <dns/rdataset.h> 47#include <dns/rdatastruct.h> 48#include <dns/rdatatype.h> 49#include <dns/resolver.h> 50#include <dns/result.h> 51#include <dns/stats.h> 52 53#define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b') 54#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC) 55#define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N') 56#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC) 57#define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H') 58#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC) 59#define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z') 60#define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC) 61#define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E') 62#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC) 63#define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4') 64#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC) 65#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6') 66#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC) 67 68/*! 69 * For type 3 negative cache entries, we will remember that the address is 70 * broken for this long. XXXMLG This is also used for actual addresses, too. 71 * The intent is to keep us from constantly asking about A/AAAA records 72 * if the zone has extremely low TTLs. 73 */ 74#define ADB_CACHE_MINIMUM 10 /*%< seconds */ 75#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */ 76#define ADB_ENTRY_WINDOW 1800 /*%< seconds */ 77 78/*% 79 * The period in seconds after which an ADB name entry is regarded as stale 80 * and forced to be cleaned up. 81 * TODO: This should probably be configurable at run-time. 82 */ 83#ifndef ADB_STALE_MARGIN 84#define ADB_STALE_MARGIN 1800 85#endif 86 87#define FREE_ITEMS 64 /*%< free count for memory pools */ 88#define FILL_COUNT 16 /*%< fill count for memory pools */ 89 90#define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */ 91 92#define DNS_ADB_MINADBSIZE (1024*1024) /*%< 1 Megabyte */ 93 94typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t; 95typedef struct dns_adbnamehook dns_adbnamehook_t; 96typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t; 97typedef struct dns_adblameinfo dns_adblameinfo_t; 98typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t; 99typedef struct dns_adbfetch dns_adbfetch_t; 100typedef struct dns_adbfetch6 dns_adbfetch6_t; 101 102/*% dns adb structure */ 103struct dns_adb { 104 unsigned int magic; 105 106 isc_mutex_t lock; 107 isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */ 108 isc_mutex_t overmemlock; /*%< Covers overmem */ 109 isc_mem_t *mctx; 110 dns_view_t *view; 111 112 isc_taskmgr_t *taskmgr; 113 isc_task_t *task; 114 115 isc_interval_t tick_interval; 116 int next_cleanbucket; 117 118 unsigned int irefcnt; 119 unsigned int erefcnt; 120 121 isc_mutex_t mplock; 122 isc_mempool_t *nmp; /*%< dns_adbname_t */ 123 isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */ 124 isc_mempool_t *limp; /*%< dns_adblameinfo_t */ 125 isc_mempool_t *emp; /*%< dns_adbentry_t */ 126 isc_mempool_t *ahmp; /*%< dns_adbfind_t */ 127 isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */ 128 isc_mempool_t *afmp; /*%< dns_adbfetch_t */ 129 130 /*! 131 * Bucketized locks and lists for names. 132 * 133 * XXXRTH Have a per-bucket structure that contains all of these? 134 */ 135 unsigned int nnames; 136 isc_mutex_t namescntlock; 137 unsigned int namescnt; 138 dns_adbnamelist_t *names; 139 dns_adbnamelist_t *deadnames; 140 isc_mutex_t *namelocks; 141 isc_boolean_t *name_sd; 142 unsigned int *name_refcnt; 143 144 /*! 145 * Bucketized locks and lists for entries. 146 * 147 * XXXRTH Have a per-bucket structure that contains all of these? 148 */ 149 unsigned int nentries; 150 isc_mutex_t entriescntlock; 151 unsigned int entriescnt; 152 dns_adbentrylist_t *entries; 153 dns_adbentrylist_t *deadentries; 154 isc_mutex_t *entrylocks; 155 isc_boolean_t *entry_sd; /*%< shutting down */ 156 unsigned int *entry_refcnt; 157 158 isc_event_t cevent; 159 isc_boolean_t cevent_sent; 160 isc_boolean_t shutting_down; 161 isc_eventlist_t whenshutdown; 162 isc_event_t growentries; 163 isc_boolean_t growentries_sent; 164 isc_event_t grownames; 165 isc_boolean_t grownames_sent; 166}; 167 168/* 169 * XXXMLG Document these structures. 170 */ 171 172/*% dns_adbname structure */ 173struct dns_adbname { 174 unsigned int magic; 175 dns_name_t name; 176 dns_adb_t *adb; 177 unsigned int partial_result; 178 unsigned int flags; 179 int lock_bucket; 180 dns_name_t target; 181 isc_stdtime_t expire_target; 182 isc_stdtime_t expire_v4; 183 isc_stdtime_t expire_v6; 184 unsigned int chains; 185 dns_adbnamehooklist_t v4; 186 dns_adbnamehooklist_t v6; 187 dns_adbfetch_t *fetch_a; 188 dns_adbfetch_t *fetch_aaaa; 189 unsigned int fetch_err; 190 unsigned int fetch6_err; 191 dns_adbfindlist_t finds; 192 /* for LRU-based management */ 193 isc_stdtime_t last_used; 194 195 ISC_LINK(dns_adbname_t) plink; 196}; 197 198/*% The adbfetch structure */ 199struct dns_adbfetch { 200 unsigned int magic; 201 dns_fetch_t *fetch; 202 dns_rdataset_t rdataset; 203}; 204 205/*% 206 * This is a small widget that dangles off a dns_adbname_t. It contains a 207 * pointer to the address information about this host, and a link to the next 208 * namehook that will contain the next address this host has. 209 */ 210struct dns_adbnamehook { 211 unsigned int magic; 212 dns_adbentry_t *entry; 213 ISC_LINK(dns_adbnamehook_t) plink; 214}; 215 216/*% 217 * This is a small widget that holds qname-specific information about an 218 * address. Currently limited to lameness, but could just as easily be 219 * extended to other types of information about zones. 220 */ 221struct dns_adblameinfo { 222 unsigned int magic; 223 224 dns_name_t qname; 225 dns_rdatatype_t qtype; 226 isc_stdtime_t lame_timer; 227 228 ISC_LINK(dns_adblameinfo_t) plink; 229}; 230 231/*% 232 * An address entry. It holds quite a bit of information about addresses, 233 * including edns state (in "flags"), rtt, and of course the address of 234 * the host. 235 */ 236struct dns_adbentry { 237 unsigned int magic; 238 239 int lock_bucket; 240 unsigned int refcnt; 241 242 unsigned int flags; 243 unsigned int srtt; 244 isc_sockaddr_t sockaddr; 245 246 isc_stdtime_t expires; 247 /*%< 248 * A nonzero 'expires' field indicates that the entry should 249 * persist until that time. This allows entries found 250 * using dns_adb_findaddrinfo() to persist for a limited time 251 * even though they are not necessarily associated with a 252 * name. 253 */ 254 255 ISC_LIST(dns_adblameinfo_t) lameinfo; 256 ISC_LINK(dns_adbentry_t) plink; 257 258}; 259 260/* 261 * Internal functions (and prototypes). 262 */ 263static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *); 264static inline void free_adbname(dns_adb_t *, dns_adbname_t **); 265static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *, 266 dns_adbentry_t *); 267static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **); 268static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *, 269 dns_rdatatype_t); 270static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **); 271static inline dns_adbentry_t *new_adbentry(dns_adb_t *); 272static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **); 273static inline dns_adbfind_t *new_adbfind(dns_adb_t *); 274static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **); 275static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *, 276 in_port_t); 277static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *); 278static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **); 279static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *, 280 unsigned int, int *); 281static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *, 282 isc_sockaddr_t *, int *, 283 isc_stdtime_t); 284static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t); 285static void print_dns_name(FILE *, dns_name_t *); 286static void print_namehook_list(FILE *, const char *legend, 287 dns_adbnamehooklist_t *list, 288 isc_boolean_t debug, 289 isc_stdtime_t now); 290static void print_find_list(FILE *, dns_adbname_t *); 291static void print_fetch_list(FILE *, dns_adbname_t *); 292static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *); 293static inline void inc_adb_irefcnt(dns_adb_t *); 294static inline void inc_adb_erefcnt(dns_adb_t *); 295static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *, 296 isc_boolean_t); 297static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t, 298 dns_adbentry_t *, isc_boolean_t); 299static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); 300static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); 301static void clean_target(dns_adb_t *, dns_name_t *); 302static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, 303 unsigned int); 304static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); 305static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, 306 isc_stdtime_t); 307static void cancel_fetches_at_name(dns_adbname_t *); 308static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, 309 dns_rdatatype_t); 310static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, 311 dns_rdatatype_t); 312static inline void check_exit(dns_adb_t *); 313static void destroy(dns_adb_t *); 314static isc_boolean_t shutdown_names(dns_adb_t *); 315static isc_boolean_t shutdown_entries(dns_adb_t *); 316static inline void link_name(dns_adb_t *, int, dns_adbname_t *); 317static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *); 318static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *); 319static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); 320static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); 321static void water(void *, int); 322static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); 323 324/* 325 * MUST NOT overlap DNS_ADBFIND_* flags! 326 */ 327#define FIND_EVENT_SENT 0x40000000 328#define FIND_EVENT_FREED 0x80000000 329#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0) 330#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0) 331 332#define NAME_NEEDS_POKE 0x80000000 333#define NAME_IS_DEAD 0x40000000 334#define NAME_HINT_OK DNS_ADBFIND_HINTOK 335#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK 336#define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE 337#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0) 338#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0) 339#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0) 340#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0) 341 342/* 343 * Private flag(s) for entries. 344 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0. 345 */ 346#define ENTRY_IS_DEAD 0x80000000 347 348/* 349 * To the name, address classes are all that really exist. If it has a 350 * V6 address it doesn't care if it came from a AAAA query. 351 */ 352#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4)) 353#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6)) 354#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n)) 355 356/* 357 * Fetches are broken out into A and AAAA types. In some cases, 358 * however, it makes more sense to test for a particular class of fetches, 359 * like V4 or V6 above. 360 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA 361 * are now equal to FETCH_V4 and FETCH_V6, respectively. 362 */ 363#define NAME_FETCH_A(n) ((n)->fetch_a != NULL) 364#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL) 365#define NAME_FETCH_V4(n) (NAME_FETCH_A(n)) 366#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n)) 367#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n)) 368 369/* 370 * Find options and tests to see if there are addresses on the list. 371 */ 372#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0) 373#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0) 374#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \ 375 != 0) 376#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \ 377 != 0) 378#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0) 379#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0) 380#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list)) 381#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0) 382 383/* 384 * These are currently used on simple unsigned ints, so they are 385 * not really associated with any particular type. 386 */ 387#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0) 388#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0) 389 390#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now)) 391 392/* 393 * Find out if the flags on a name (nf) indicate if it is a hint or 394 * glue, and compare this to the appropriate bits set in o, to see if 395 * this is ok. 396 */ 397#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0)) 398#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0)) 399#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o)) 400#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \ 401 ((o) & DNS_ADBFIND_STARTATZONE)) 402 403#define ENTER_LEVEL ISC_LOG_DEBUG(50) 404#define EXIT_LEVEL ENTER_LEVEL 405#define CLEAN_LEVEL ISC_LOG_DEBUG(100) 406#define DEF_LEVEL ISC_LOG_DEBUG(5) 407#define NCACHE_LEVEL ISC_LOG_DEBUG(20) 408 409#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \ 410 (r) == DNS_R_NCACHENXRRSET) 411#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \ 412 (r) == DNS_R_NXRRSET) 413#define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \ 414 (r) == DNS_R_NCACHENXDOMAIN) 415#define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \ 416 (r) == DNS_R_NXRRSET || \ 417 (r) == DNS_R_HINTNXRRSET) 418 419/* 420 * Error state rankings. 421 */ 422 423#define FIND_ERR_SUCCESS 0 /* highest rank */ 424#define FIND_ERR_CANCELED 1 425#define FIND_ERR_FAILURE 2 426#define FIND_ERR_NXDOMAIN 3 427#define FIND_ERR_NXRRSET 4 428#define FIND_ERR_UNEXPECTED 5 429#define FIND_ERR_NOTFOUND 6 430#define FIND_ERR_MAX 7 431 432static const char *errnames[] = { 433 "success", 434 "canceled", 435 "failure", 436 "nxdomain", 437 "nxrrset", 438 "unexpected", 439 "not_found" 440}; 441 442#define NEWERR(old, new) (ISC_MIN((old), (new))) 443 444static isc_result_t find_err_map[FIND_ERR_MAX] = { 445 ISC_R_SUCCESS, 446 ISC_R_CANCELED, 447 ISC_R_FAILURE, 448 DNS_R_NXDOMAIN, 449 DNS_R_NXRRSET, 450 ISC_R_UNEXPECTED, 451 ISC_R_NOTFOUND /* not YET found */ 452}; 453 454static void 455DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); 456 457static void 458DP(int level, const char *format, ...) { 459 va_list args; 460 461 va_start(args, format); 462 isc_log_vwrite(dns_lctx, 463 DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, 464 level, format, args); 465 va_end(args); 466} 467 468/*% 469 * Increment resolver-related statistics counters. 470 */ 471static inline void 472inc_stats(dns_adb_t *adb, isc_statscounter_t counter) { 473 if (adb->view->resstats != NULL) 474 isc_stats_increment(adb->view->resstats, counter); 475} 476 477static inline dns_ttl_t 478ttlclamp(dns_ttl_t ttl) { 479 if (ttl < ADB_CACHE_MINIMUM) 480 ttl = ADB_CACHE_MINIMUM; 481 if (ttl > ADB_CACHE_MAXIMUM) 482 ttl = ADB_CACHE_MAXIMUM; 483 484 return (ttl); 485} 486 487/* 488 * Hashing is most efficient if the number of buckets is prime. 489 * The sequence below is the closest previous primes to 2^n and 490 * 1.5 * 2^n, for values of n from 10 to 28. (The tables will 491 * no longer grow beyond 2^28 entries.) 492 */ 493static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143, 494 8191, 12281, 16381, 24571, 32749, 495 49193, 65521, 98299, 131071, 199603, 496 262139, 393209, 524287, 768431, 1048573, 497 1572853, 2097143, 3145721, 4194301, 498 6291449, 8388593, 12582893, 16777213, 499 25165813, 33554393, 50331599, 67108859, 500 100663291, 134217689, 201326557, 501 268535431, 0 }; 502 503static void 504grow_entries(isc_task_t *task, isc_event_t *ev) { 505 dns_adb_t *adb; 506 dns_adbentry_t *e; 507 dns_adbentrylist_t *newdeadentries = NULL; 508 dns_adbentrylist_t *newentries = NULL; 509 isc_boolean_t *newentry_sd = NULL; 510 isc_mutex_t *newentrylocks = NULL; 511 isc_result_t result; 512 unsigned int *newentry_refcnt = NULL; 513 unsigned int i, n, bucket; 514 515 adb = ev->ev_arg; 516 INSIST(DNS_ADB_VALID(adb)); 517 518 isc_event_free(&ev); 519 520 isc_task_beginexclusive(task); 521 522 i = 0; 523 while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i]) 524 i++; 525 if (nbuckets[i] != 0) 526 n = nbuckets[i]; 527 else 528 goto done; 529 530 DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n); 531 532 /* 533 * Are we shutting down? 534 */ 535 for (i = 0; i < adb->nentries; i++) 536 if (adb->entry_sd[i]) 537 goto cleanup; 538 539 /* 540 * Grab all the resources we need. 541 */ 542 newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n); 543 newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n); 544 newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n); 545 newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n); 546 newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n); 547 if (newentries == NULL || newdeadentries == NULL || 548 newentrylocks == NULL || newentry_sd == NULL || 549 newentry_refcnt == NULL) 550 goto cleanup; 551 552 /* 553 * Initialise the new resources. 554 */ 555 result = isc_mutexblock_init(newentrylocks, n); 556 if (result != ISC_R_SUCCESS) 557 goto cleanup; 558 559 for (i = 0; i < n; i++) { 560 ISC_LIST_INIT(newentries[i]); 561 ISC_LIST_INIT(newdeadentries[i]); 562 newentry_sd[i] = ISC_FALSE; 563 newentry_refcnt[i] = 0; 564 adb->irefcnt++; 565 } 566 567 /* 568 * Move entries to new arrays. 569 */ 570 for (i = 0; i < adb->nentries; i++) { 571 e = ISC_LIST_HEAD(adb->entries[i]); 572 while (e != NULL) { 573 ISC_LIST_UNLINK(adb->entries[i], e, plink); 574 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n; 575 e->lock_bucket = bucket; 576 ISC_LIST_APPEND(newentries[bucket], e, plink); 577 INSIST(adb->entry_refcnt[i] > 0); 578 adb->entry_refcnt[i]--; 579 newentry_refcnt[bucket]++; 580 e = ISC_LIST_HEAD(adb->entries[i]); 581 } 582 e = ISC_LIST_HEAD(adb->deadentries[i]); 583 while (e != NULL) { 584 ISC_LIST_UNLINK(adb->deadentries[i], e, plink); 585 bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n; 586 e->lock_bucket = bucket; 587 ISC_LIST_APPEND(newdeadentries[bucket], e, plink); 588 INSIST(adb->entry_refcnt[i] > 0); 589 adb->entry_refcnt[i]--; 590 newentry_refcnt[bucket]++; 591 e = ISC_LIST_HEAD(adb->deadentries[i]); 592 } 593 INSIST(adb->entry_refcnt[i] == 0); 594 adb->irefcnt--; 595 } 596 597 /* 598 * Cleanup old resources. 599 */ 600 DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries); 601 isc_mem_put(adb->mctx, adb->entries, 602 sizeof(*adb->entries) * adb->nentries); 603 isc_mem_put(adb->mctx, adb->deadentries, 604 sizeof(*adb->deadentries) * adb->nentries); 605 isc_mem_put(adb->mctx, adb->entrylocks, 606 sizeof(*adb->entrylocks) * adb->nentries); 607 isc_mem_put(adb->mctx, adb->entry_sd, 608 sizeof(*adb->entry_sd) * adb->nentries); 609 isc_mem_put(adb->mctx, adb->entry_refcnt, 610 sizeof(*adb->entry_refcnt) * adb->nentries); 611 612 /* 613 * Install new resources. 614 */ 615 adb->entries = newentries; 616 adb->deadentries = newdeadentries; 617 adb->entrylocks = newentrylocks; 618 adb->entry_sd = newentry_sd; 619 adb->entry_refcnt = newentry_refcnt; 620 adb->nentries = n; 621 622 /* 623 * Only on success do we set adb->growentries_sent to ISC_FALSE. 624 * This will prevent us being continuously being called on error. 625 */ 626 adb->growentries_sent = ISC_FALSE; 627 goto done; 628 629 cleanup: 630 if (newentries != NULL) 631 isc_mem_put(adb->mctx, newentries, 632 sizeof(*newentries) * n); 633 if (newdeadentries != NULL) 634 isc_mem_put(adb->mctx, newdeadentries, 635 sizeof(*newdeadentries) * n); 636 if (newentrylocks != NULL) 637 isc_mem_put(adb->mctx, newentrylocks, 638 sizeof(*newentrylocks) * n); 639 if (newentry_sd != NULL) 640 isc_mem_put(adb->mctx, newentry_sd, 641 sizeof(*newentry_sd) * n); 642 if (newentry_refcnt != NULL) 643 isc_mem_put(adb->mctx, newentry_refcnt, 644 sizeof(*newentry_refcnt) * n); 645 done: 646 isc_task_endexclusive(task); 647 648 LOCK(&adb->lock); 649 if (dec_adb_irefcnt(adb)) 650 check_exit(adb); 651 UNLOCK(&adb->lock); 652 DP(ISC_LOG_INFO, "adb: grow_entries finished"); 653} 654 655static void 656grow_names(isc_task_t *task, isc_event_t *ev) { 657 dns_adb_t *adb; 658 dns_adbname_t *name; 659 dns_adbnamelist_t *newdeadnames = NULL; 660 dns_adbnamelist_t *newnames = NULL; 661 isc_boolean_t *newname_sd = NULL; 662 isc_mutex_t *newnamelocks = NULL; 663 isc_result_t result; 664 unsigned int *newname_refcnt = NULL; 665 unsigned int i, n, bucket; 666 667 adb = ev->ev_arg; 668 INSIST(DNS_ADB_VALID(adb)); 669 670 isc_event_free(&ev); 671 672 isc_task_beginexclusive(task); 673 674 i = 0; 675 while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i]) 676 i++; 677 if (nbuckets[i] != 0) 678 n = nbuckets[i]; 679 else 680 goto done; 681 682 DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n); 683 684 /* 685 * Are we shutting down? 686 */ 687 for (i = 0; i < adb->nnames; i++) 688 if (adb->name_sd[i]) 689 goto cleanup; 690 691 /* 692 * Grab all the resources we need. 693 */ 694 newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n); 695 newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n); 696 newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n); 697 newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n); 698 newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n); 699 if (newnames == NULL || newdeadnames == NULL || 700 newnamelocks == NULL || newname_sd == NULL || 701 newname_refcnt == NULL) 702 goto cleanup; 703 704 /* 705 * Initialise the new resources. 706 */ 707 result = isc_mutexblock_init(newnamelocks, n); 708 if (result != ISC_R_SUCCESS) 709 goto cleanup; 710 711 for (i = 0; i < n; i++) { 712 ISC_LIST_INIT(newnames[i]); 713 ISC_LIST_INIT(newdeadnames[i]); 714 newname_sd[i] = ISC_FALSE; 715 newname_refcnt[i] = 0; 716 adb->irefcnt++; 717 } 718 719 /* 720 * Move names to new arrays. 721 */ 722 for (i = 0; i < adb->nnames; i++) { 723 name = ISC_LIST_HEAD(adb->names[i]); 724 while (name != NULL) { 725 ISC_LIST_UNLINK(adb->names[i], name, plink); 726 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n; 727 name->lock_bucket = bucket; 728 ISC_LIST_APPEND(newnames[bucket], name, plink); 729 INSIST(adb->name_refcnt[i] > 0); 730 adb->name_refcnt[i]--; 731 newname_refcnt[bucket]++; 732 name = ISC_LIST_HEAD(adb->names[i]); 733 } 734 name = ISC_LIST_HEAD(adb->deadnames[i]); 735 while (name != NULL) { 736 ISC_LIST_UNLINK(adb->deadnames[i], name, plink); 737 bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n; 738 name->lock_bucket = bucket; 739 ISC_LIST_APPEND(newdeadnames[bucket], name, plink); 740 INSIST(adb->name_refcnt[i] > 0); 741 adb->name_refcnt[i]--; 742 newname_refcnt[bucket]++; 743 name = ISC_LIST_HEAD(adb->deadnames[i]); 744 } 745 INSIST(adb->name_refcnt[i] == 0); 746 adb->irefcnt--; 747 } 748 749 /* 750 * Cleanup old resources. 751 */ 752 DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames); 753 isc_mem_put(adb->mctx, adb->names, 754 sizeof(*adb->names) * adb->nnames); 755 isc_mem_put(adb->mctx, adb->deadnames, 756 sizeof(*adb->deadnames) * adb->nnames); 757 isc_mem_put(adb->mctx, adb->namelocks, 758 sizeof(*adb->namelocks) * adb->nnames); 759 isc_mem_put(adb->mctx, adb->name_sd, 760 sizeof(*adb->name_sd) * adb->nnames); 761 isc_mem_put(adb->mctx, adb->name_refcnt, 762 sizeof(*adb->name_refcnt) * adb->nnames); 763 764 /* 765 * Install new resources. 766 */ 767 adb->names = newnames; 768 adb->deadnames = newdeadnames; 769 adb->namelocks = newnamelocks; 770 adb->name_sd = newname_sd; 771 adb->name_refcnt = newname_refcnt; 772 adb->nnames = n; 773 774 /* 775 * Only on success do we set adb->grownames_sent to ISC_FALSE. 776 * This will prevent us being continuously being called on error. 777 */ 778 adb->grownames_sent = ISC_FALSE; 779 goto done; 780 781 cleanup: 782 if (newnames != NULL) 783 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n); 784 if (newdeadnames != NULL) 785 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n); 786 if (newnamelocks != NULL) 787 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n); 788 if (newname_sd != NULL) 789 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n); 790 if (newname_refcnt != NULL) 791 isc_mem_put(adb->mctx, newname_refcnt, 792 sizeof(*newname_refcnt) * n); 793 done: 794 isc_task_endexclusive(task); 795 796 LOCK(&adb->lock); 797 if (dec_adb_irefcnt(adb)) 798 check_exit(adb); 799 UNLOCK(&adb->lock); 800 DP(ISC_LOG_INFO, "adb: grow_names finished"); 801} 802 803/* 804 * Requires the adbname bucket be locked and that no entry buckets be locked. 805 * 806 * This code handles A and AAAA rdatasets only. 807 */ 808static isc_result_t 809import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset, 810 isc_stdtime_t now) 811{ 812 isc_result_t result; 813 dns_adb_t *adb; 814 dns_adbnamehook_t *nh; 815 dns_adbnamehook_t *anh; 816 dns_rdata_t rdata = DNS_RDATA_INIT; 817 struct in_addr ina; 818 struct in6_addr in6a; 819 isc_sockaddr_t sockaddr; 820 dns_adbentry_t *foundentry; /* NO CLEAN UP! */ 821 int addr_bucket; 822 isc_boolean_t new_addresses_added; 823 dns_rdatatype_t rdtype; 824 unsigned int findoptions; 825 dns_adbnamehooklist_t *hookhead; 826 827 INSIST(DNS_ADBNAME_VALID(adbname)); 828 adb = adbname->adb; 829 INSIST(DNS_ADB_VALID(adb)); 830 831 rdtype = rdataset->type; 832 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa)); 833 if (rdtype == dns_rdatatype_a) 834 findoptions = DNS_ADBFIND_INET; 835 else 836 findoptions = DNS_ADBFIND_INET6; 837 838 addr_bucket = DNS_ADB_INVALIDBUCKET; 839 new_addresses_added = ISC_FALSE; 840 841 nh = NULL; 842 result = dns_rdataset_first(rdataset); 843 while (result == ISC_R_SUCCESS) { 844 dns_rdata_reset(&rdata); 845 dns_rdataset_current(rdataset, &rdata); 846 if (rdtype == dns_rdatatype_a) { 847 INSIST(rdata.length == 4); 848 memcpy(&ina.s_addr, rdata.data, 4); 849 isc_sockaddr_fromin(&sockaddr, &ina, 0); 850 hookhead = &adbname->v4; 851 } else { 852 INSIST(rdata.length == 16); 853 memcpy(in6a.s6_addr, rdata.data, 16); 854 isc_sockaddr_fromin6(&sockaddr, &in6a, 0); 855 hookhead = &adbname->v6; 856 } 857 858 INSIST(nh == NULL); 859 nh = new_adbnamehook(adb, NULL); 860 if (nh == NULL) { 861 adbname->partial_result |= findoptions; 862 result = ISC_R_NOMEMORY; 863 goto fail; 864 } 865 866 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket, 867 now); 868 if (foundentry == NULL) { 869 dns_adbentry_t *entry; 870 871 entry = new_adbentry(adb); 872 if (entry == NULL) { 873 adbname->partial_result |= findoptions; 874 result = ISC_R_NOMEMORY; 875 goto fail; 876 } 877 878 entry->sockaddr = sockaddr; 879 entry->refcnt = 1; 880 881 nh->entry = entry; 882 883 link_entry(adb, addr_bucket, entry); 884 } else { 885 for (anh = ISC_LIST_HEAD(*hookhead); 886 anh != NULL; 887 anh = ISC_LIST_NEXT(anh, plink)) 888 if (anh->entry == foundentry) 889 break; 890 if (anh == NULL) { 891 foundentry->refcnt++; 892 nh->entry = foundentry; 893 } else 894 free_adbnamehook(adb, &nh); 895 } 896 897 new_addresses_added = ISC_TRUE; 898 if (nh != NULL) 899 ISC_LIST_APPEND(*hookhead, nh, plink); 900 nh = NULL; 901 result = dns_rdataset_next(rdataset); 902 } 903 904 fail: 905 if (nh != NULL) 906 free_adbnamehook(adb, &nh); 907 908 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 909 UNLOCK(&adb->entrylocks[addr_bucket]); 910 911 if (rdataset->trust == dns_trust_glue || 912 rdataset->trust == dns_trust_additional) 913 rdataset->ttl = ADB_CACHE_MINIMUM; 914 else if (rdataset->trust == dns_trust_ultimate) 915 rdataset->ttl = 0; 916 else 917 rdataset->ttl = ttlclamp(rdataset->ttl); 918 919 if (rdtype == dns_rdatatype_a) { 920 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset", 921 adbname->expire_v4, now + rdataset->ttl); 922 adbname->expire_v4 = ISC_MIN(adbname->expire_v4, 923 now + rdataset->ttl); 924 } else { 925 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset", 926 adbname->expire_v6, now + rdataset->ttl); 927 adbname->expire_v6 = ISC_MIN(adbname->expire_v6, 928 now + rdataset->ttl); 929 } 930 931 if (new_addresses_added) { 932 /* 933 * Lie a little here. This is more or less so code that cares 934 * can find out if any new information was added or not. 935 */ 936 return (ISC_R_SUCCESS); 937 } 938 939 return (result); 940} 941 942/* 943 * Requires the name's bucket be locked. 944 */ 945static isc_boolean_t 946kill_name(dns_adbname_t **n, isc_eventtype_t ev) { 947 dns_adbname_t *name; 948 isc_boolean_t result = ISC_FALSE; 949 isc_boolean_t result4, result6; 950 int bucket; 951 dns_adb_t *adb; 952 953 INSIST(n != NULL); 954 name = *n; 955 *n = NULL; 956 INSIST(DNS_ADBNAME_VALID(name)); 957 adb = name->adb; 958 INSIST(DNS_ADB_VALID(adb)); 959 960 DP(DEF_LEVEL, "killing name %p", name); 961 962 /* 963 * If we're dead already, just check to see if we should go 964 * away now or not. 965 */ 966 if (NAME_DEAD(name) && !NAME_FETCH(name)) { 967 result = unlink_name(adb, name); 968 free_adbname(adb, &name); 969 if (result) 970 result = dec_adb_irefcnt(adb); 971 return (result); 972 } 973 974 /* 975 * Clean up the name's various lists. These two are destructive 976 * in that they will always empty the list. 977 */ 978 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); 979 result4 = clean_namehooks(adb, &name->v4); 980 result6 = clean_namehooks(adb, &name->v6); 981 clean_target(adb, &name->target); 982 result = ISC_TF(result4 || result6); 983 984 /* 985 * If fetches are running, cancel them. If none are running, we can 986 * just kill the name here. 987 */ 988 if (!NAME_FETCH(name)) { 989 INSIST(result == ISC_FALSE); 990 result = unlink_name(adb, name); 991 free_adbname(adb, &name); 992 if (result) 993 result = dec_adb_irefcnt(adb); 994 } else { 995 cancel_fetches_at_name(name); 996 if (!NAME_DEAD(name)) { 997 bucket = name->lock_bucket; 998 ISC_LIST_UNLINK(adb->names[bucket], name, plink); 999 ISC_LIST_APPEND(adb->deadnames[bucket], name, plink); 1000 name->flags |= NAME_IS_DEAD; 1001 } 1002 } 1003 return (result); 1004} 1005 1006/* 1007 * Requires the name's bucket be locked and no entry buckets be locked. 1008 */ 1009static isc_boolean_t 1010check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) { 1011 dns_adb_t *adb; 1012 isc_boolean_t result4 = ISC_FALSE; 1013 isc_boolean_t result6 = ISC_FALSE; 1014 1015 INSIST(DNS_ADBNAME_VALID(name)); 1016 adb = name->adb; 1017 INSIST(DNS_ADB_VALID(adb)); 1018 1019 /* 1020 * Check to see if we need to remove the v4 addresses 1021 */ 1022 if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) { 1023 if (NAME_HAS_V4(name)) { 1024 DP(DEF_LEVEL, "expiring v4 for name %p", name); 1025 result4 = clean_namehooks(adb, &name->v4); 1026 name->partial_result &= ~DNS_ADBFIND_INET; 1027 } 1028 name->expire_v4 = INT_MAX; 1029 name->fetch_err = FIND_ERR_UNEXPECTED; 1030 } 1031 1032 /* 1033 * Check to see if we need to remove the v6 addresses 1034 */ 1035 if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) { 1036 if (NAME_HAS_V6(name)) { 1037 DP(DEF_LEVEL, "expiring v6 for name %p", name); 1038 result6 = clean_namehooks(adb, &name->v6); 1039 name->partial_result &= ~DNS_ADBFIND_INET6; 1040 } 1041 name->expire_v6 = INT_MAX; 1042 name->fetch6_err = FIND_ERR_UNEXPECTED; 1043 } 1044 1045 /* 1046 * Check to see if we need to remove the alias target. 1047 */ 1048 if (EXPIRE_OK(name->expire_target, now)) { 1049 clean_target(adb, &name->target); 1050 name->expire_target = INT_MAX; 1051 } 1052 return (ISC_TF(result4 || result6)); 1053} 1054 1055/* 1056 * Requires the name's bucket be locked. 1057 */ 1058static inline void 1059link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) { 1060 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET); 1061 1062 ISC_LIST_PREPEND(adb->names[bucket], name, plink); 1063 name->lock_bucket = bucket; 1064 adb->name_refcnt[bucket]++; 1065} 1066 1067/* 1068 * Requires the name's bucket be locked. 1069 */ 1070static inline isc_boolean_t 1071unlink_name(dns_adb_t *adb, dns_adbname_t *name) { 1072 int bucket; 1073 isc_boolean_t result = ISC_FALSE; 1074 1075 bucket = name->lock_bucket; 1076 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 1077 1078 if (NAME_DEAD(name)) 1079 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink); 1080 else 1081 ISC_LIST_UNLINK(adb->names[bucket], name, plink); 1082 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 1083 INSIST(adb->name_refcnt[bucket] > 0); 1084 adb->name_refcnt[bucket]--; 1085 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) 1086 result = ISC_TRUE; 1087 return (result); 1088} 1089 1090/* 1091 * Requires the entry's bucket be locked. 1092 */ 1093static inline void 1094link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) { 1095 int i; 1096 dns_adbentry_t *e; 1097 1098 if (isc_mem_isovermem(adb->mctx)) { 1099 for (i = 0; i < 2; i++) { 1100 e = ISC_LIST_TAIL(adb->entries[bucket]); 1101 if (e == NULL) 1102 break; 1103 if (e->refcnt == 0) { 1104 unlink_entry(adb, e); 1105 free_adbentry(adb, &e); 1106 continue; 1107 } 1108 INSIST((e->flags & ENTRY_IS_DEAD) == 0); 1109 e->flags |= ENTRY_IS_DEAD; 1110 ISC_LIST_UNLINK(adb->entries[bucket], e, plink); 1111 ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink); 1112 } 1113 } 1114 1115 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink); 1116 entry->lock_bucket = bucket; 1117 adb->entry_refcnt[bucket]++; 1118} 1119 1120/* 1121 * Requires the entry's bucket be locked. 1122 */ 1123static inline isc_boolean_t 1124unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) { 1125 int bucket; 1126 isc_boolean_t result = ISC_FALSE; 1127 1128 bucket = entry->lock_bucket; 1129 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 1130 1131 if ((entry->flags & ENTRY_IS_DEAD) != 0) 1132 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink); 1133 else 1134 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink); 1135 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 1136 INSIST(adb->entry_refcnt[bucket] > 0); 1137 adb->entry_refcnt[bucket]--; 1138 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0) 1139 result = ISC_TRUE; 1140 return (result); 1141} 1142 1143static inline void 1144violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) { 1145 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) { 1146 UNLOCK(have); 1147 LOCK(want); 1148 LOCK(have); 1149 } 1150} 1151 1152/* 1153 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 1154 * checked after calling this function. 1155 */ 1156static isc_boolean_t 1157shutdown_names(dns_adb_t *adb) { 1158 unsigned int bucket; 1159 isc_boolean_t result = ISC_FALSE; 1160 dns_adbname_t *name; 1161 dns_adbname_t *next_name; 1162 1163 for (bucket = 0; bucket < adb->nnames; bucket++) { 1164 LOCK(&adb->namelocks[bucket]); 1165 adb->name_sd[bucket] = ISC_TRUE; 1166 1167 name = ISC_LIST_HEAD(adb->names[bucket]); 1168 if (name == NULL) { 1169 /* 1170 * This bucket has no names. We must decrement the 1171 * irefcnt ourselves, since it will not be 1172 * automatically triggered by a name being unlinked. 1173 */ 1174 INSIST(result == ISC_FALSE); 1175 result = dec_adb_irefcnt(adb); 1176 } else { 1177 /* 1178 * Run through the list. For each name, clean up finds 1179 * found there, and cancel any fetches running. When 1180 * all the fetches are canceled, the name will destroy 1181 * itself. 1182 */ 1183 while (name != NULL) { 1184 next_name = ISC_LIST_NEXT(name, plink); 1185 INSIST(result == ISC_FALSE); 1186 result = kill_name(&name, 1187 DNS_EVENT_ADBSHUTDOWN); 1188 name = next_name; 1189 } 1190 } 1191 1192 UNLOCK(&adb->namelocks[bucket]); 1193 } 1194 return (result); 1195} 1196 1197/* 1198 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 1199 * checked after calling this function. 1200 */ 1201static isc_boolean_t 1202shutdown_entries(dns_adb_t *adb) { 1203 unsigned int bucket; 1204 isc_boolean_t result = ISC_FALSE; 1205 dns_adbentry_t *entry; 1206 dns_adbentry_t *next_entry; 1207 1208 for (bucket = 0; bucket < adb->nentries; bucket++) { 1209 LOCK(&adb->entrylocks[bucket]); 1210 adb->entry_sd[bucket] = ISC_TRUE; 1211 1212 entry = ISC_LIST_HEAD(adb->entries[bucket]); 1213 if (adb->entry_refcnt[bucket] == 0) { 1214 /* 1215 * This bucket has no entries. We must decrement the 1216 * irefcnt ourselves, since it will not be 1217 * automatically triggered by an entry being unlinked. 1218 */ 1219 result = dec_adb_irefcnt(adb); 1220 } else { 1221 /* 1222 * Run through the list. Cleanup any entries not 1223 * associated with names, and which are not in use. 1224 */ 1225 while (entry != NULL) { 1226 next_entry = ISC_LIST_NEXT(entry, plink); 1227 if (entry->refcnt == 0 && 1228 entry->expires != 0) { 1229 result = unlink_entry(adb, entry); 1230 free_adbentry(adb, &entry); 1231 if (result) 1232 result = dec_adb_irefcnt(adb); 1233 } 1234 entry = next_entry; 1235 } 1236 } 1237 1238 UNLOCK(&adb->entrylocks[bucket]); 1239 } 1240 return (result); 1241} 1242 1243/* 1244 * Name bucket must be locked 1245 */ 1246static void 1247cancel_fetches_at_name(dns_adbname_t *name) { 1248 if (NAME_FETCH_A(name)) 1249 dns_resolver_cancelfetch(name->fetch_a->fetch); 1250 1251 if (NAME_FETCH_AAAA(name)) 1252 dns_resolver_cancelfetch(name->fetch_aaaa->fetch); 1253} 1254 1255/* 1256 * Assumes the name bucket is locked. 1257 */ 1258static isc_boolean_t 1259clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { 1260 dns_adbentry_t *entry; 1261 dns_adbnamehook_t *namehook; 1262 int addr_bucket; 1263 isc_boolean_t result = ISC_FALSE; 1264 isc_boolean_t overmem = isc_mem_isovermem(adb->mctx); 1265 1266 addr_bucket = DNS_ADB_INVALIDBUCKET; 1267 namehook = ISC_LIST_HEAD(*namehooks); 1268 while (namehook != NULL) { 1269 INSIST(DNS_ADBNAMEHOOK_VALID(namehook)); 1270 1271 /* 1272 * Clean up the entry if needed. 1273 */ 1274 entry = namehook->entry; 1275 if (entry != NULL) { 1276 INSIST(DNS_ADBENTRY_VALID(entry)); 1277 1278 if (addr_bucket != entry->lock_bucket) { 1279 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 1280 UNLOCK(&adb->entrylocks[addr_bucket]); 1281 addr_bucket = entry->lock_bucket; 1282 LOCK(&adb->entrylocks[addr_bucket]); 1283 } 1284 1285 result = dec_entry_refcnt(adb, overmem, entry, 1286 ISC_FALSE); 1287 } 1288 1289 /* 1290 * Free the namehook 1291 */ 1292 namehook->entry = NULL; 1293 ISC_LIST_UNLINK(*namehooks, namehook, plink); 1294 free_adbnamehook(adb, &namehook); 1295 1296 namehook = ISC_LIST_HEAD(*namehooks); 1297 } 1298 1299 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 1300 UNLOCK(&adb->entrylocks[addr_bucket]); 1301 return (result); 1302} 1303 1304static void 1305clean_target(dns_adb_t *adb, dns_name_t *target) { 1306 if (dns_name_countlabels(target) > 0) { 1307 dns_name_free(target, adb->mctx); 1308 dns_name_init(target, NULL); 1309 } 1310} 1311 1312static isc_result_t 1313set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname, 1314 dns_rdataset_t *rdataset, dns_name_t *target) 1315{ 1316 isc_result_t result; 1317 dns_namereln_t namereln; 1318 unsigned int nlabels; 1319 int order; 1320 dns_rdata_t rdata = DNS_RDATA_INIT; 1321 dns_fixedname_t fixed1, fixed2; 1322 dns_name_t *prefix, *new_target; 1323 1324 REQUIRE(dns_name_countlabels(target) == 0); 1325 1326 if (rdataset->type == dns_rdatatype_cname) { 1327 dns_rdata_cname_t cname; 1328 1329 /* 1330 * Copy the CNAME's target into the target name. 1331 */ 1332 result = dns_rdataset_first(rdataset); 1333 if (result != ISC_R_SUCCESS) 1334 return (result); 1335 dns_rdataset_current(rdataset, &rdata); 1336 result = dns_rdata_tostruct(&rdata, &cname, NULL); 1337 if (result != ISC_R_SUCCESS) 1338 return (result); 1339 result = dns_name_dup(&cname.cname, adb->mctx, target); 1340 dns_rdata_freestruct(&cname); 1341 if (result != ISC_R_SUCCESS) 1342 return (result); 1343 } else { 1344 dns_rdata_dname_t dname; 1345 1346 INSIST(rdataset->type == dns_rdatatype_dname); 1347 namereln = dns_name_fullcompare(name, fname, &order, &nlabels); 1348 INSIST(namereln == dns_namereln_subdomain); 1349 /* 1350 * Get the target name of the DNAME. 1351 */ 1352 result = dns_rdataset_first(rdataset); 1353 if (result != ISC_R_SUCCESS) 1354 return (result); 1355 dns_rdataset_current(rdataset, &rdata); 1356 result = dns_rdata_tostruct(&rdata, &dname, NULL); 1357 if (result != ISC_R_SUCCESS) 1358 return (result); 1359 /* 1360 * Construct the new target name. 1361 */ 1362 dns_fixedname_init(&fixed1); 1363 prefix = dns_fixedname_name(&fixed1); 1364 dns_fixedname_init(&fixed2); 1365 new_target = dns_fixedname_name(&fixed2); 1366 dns_name_split(name, nlabels, prefix, NULL); 1367 result = dns_name_concatenate(prefix, &dname.dname, new_target, 1368 NULL); 1369 dns_rdata_freestruct(&dname); 1370 if (result != ISC_R_SUCCESS) 1371 return (result); 1372 result = dns_name_dup(new_target, adb->mctx, target); 1373 if (result != ISC_R_SUCCESS) 1374 return (result); 1375 } 1376 1377 return (ISC_R_SUCCESS); 1378} 1379 1380/* 1381 * Assumes nothing is locked, since this is called by the client. 1382 */ 1383static void 1384event_free(isc_event_t *event) { 1385 dns_adbfind_t *find; 1386 1387 INSIST(event != NULL); 1388 find = event->ev_destroy_arg; 1389 INSIST(DNS_ADBFIND_VALID(find)); 1390 1391 LOCK(&find->lock); 1392 find->flags |= FIND_EVENT_FREED; 1393 event->ev_destroy_arg = NULL; 1394 UNLOCK(&find->lock); 1395} 1396 1397/* 1398 * Assumes the name bucket is locked. 1399 */ 1400static void 1401clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, 1402 unsigned int addrs) 1403{ 1404 isc_event_t *ev; 1405 isc_task_t *task; 1406 dns_adbfind_t *find; 1407 dns_adbfind_t *next_find; 1408 isc_boolean_t process; 1409 unsigned int wanted, notify; 1410 1411 DP(ENTER_LEVEL, 1412 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x", 1413 name, evtype, addrs); 1414 1415 find = ISC_LIST_HEAD(name->finds); 1416 while (find != NULL) { 1417 LOCK(&find->lock); 1418 next_find = ISC_LIST_NEXT(find, plink); 1419 1420 process = ISC_FALSE; 1421 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1422 notify = wanted & addrs; 1423 1424 switch (evtype) { 1425 case DNS_EVENT_ADBMOREADDRESSES: 1426 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES"); 1427 if ((notify) != 0) { 1428 find->flags &= ~addrs; 1429 process = ISC_TRUE; 1430 } 1431 break; 1432 case DNS_EVENT_ADBNOMOREADDRESSES: 1433 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES"); 1434 find->flags &= ~addrs; 1435 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1436 if (wanted == 0) 1437 process = ISC_TRUE; 1438 break; 1439 default: 1440 find->flags &= ~addrs; 1441 process = ISC_TRUE; 1442 } 1443 1444 if (process) { 1445 DP(DEF_LEVEL, "cfan: processing find %p", find); 1446 /* 1447 * Unlink the find from the name, letting the caller 1448 * call dns_adb_destroyfind() on it to clean it up 1449 * later. 1450 */ 1451 ISC_LIST_UNLINK(name->finds, find, plink); 1452 find->adbname = NULL; 1453 find->name_bucket = DNS_ADB_INVALIDBUCKET; 1454 1455 INSIST(!FIND_EVENTSENT(find)); 1456 1457 ev = &find->event; 1458 task = ev->ev_sender; 1459 ev->ev_sender = find; 1460 find->result_v4 = find_err_map[name->fetch_err]; 1461 find->result_v6 = find_err_map[name->fetch6_err]; 1462 ev->ev_type = evtype; 1463 ev->ev_destroy = event_free; 1464 ev->ev_destroy_arg = find; 1465 1466 DP(DEF_LEVEL, 1467 "sending event %p to task %p for find %p", 1468 ev, task, find); 1469 1470 isc_task_sendanddetach(&task, (isc_event_t **)&ev); 1471 } else { 1472 DP(DEF_LEVEL, "cfan: skipping find %p", find); 1473 } 1474 1475 UNLOCK(&find->lock); 1476 find = next_find; 1477 } 1478 1479 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name); 1480} 1481 1482static inline void 1483check_exit(dns_adb_t *adb) { 1484 isc_event_t *event; 1485 /* 1486 * The caller must be holding the adb lock. 1487 */ 1488 if (adb->shutting_down) { 1489 /* 1490 * If there aren't any external references either, we're 1491 * done. Send the control event to initiate shutdown. 1492 */ 1493 INSIST(!adb->cevent_sent); /* Sanity check. */ 1494 event = &adb->cevent; 1495 isc_task_send(adb->task, &event); 1496 adb->cevent_sent = ISC_TRUE; 1497 } 1498} 1499 1500static inline isc_boolean_t 1501dec_adb_irefcnt(dns_adb_t *adb) { 1502 isc_event_t *event; 1503 isc_task_t *etask; 1504 isc_boolean_t result = ISC_FALSE; 1505 1506 LOCK(&adb->reflock); 1507 1508 INSIST(adb->irefcnt > 0); 1509 adb->irefcnt--; 1510 1511 if (adb->irefcnt == 0) { 1512 event = ISC_LIST_HEAD(adb->whenshutdown); 1513 while (event != NULL) { 1514 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link); 1515 etask = event->ev_sender; 1516 event->ev_sender = adb; 1517 isc_task_sendanddetach(&etask, &event); 1518 event = ISC_LIST_HEAD(adb->whenshutdown); 1519 } 1520 } 1521 1522 if (adb->irefcnt == 0 && adb->erefcnt == 0) 1523 result = ISC_TRUE; 1524 UNLOCK(&adb->reflock); 1525 return (result); 1526} 1527 1528static inline void 1529inc_adb_irefcnt(dns_adb_t *adb) { 1530 LOCK(&adb->reflock); 1531 adb->irefcnt++; 1532 UNLOCK(&adb->reflock); 1533} 1534 1535static inline void 1536inc_adb_erefcnt(dns_adb_t *adb) { 1537 LOCK(&adb->reflock); 1538 adb->erefcnt++; 1539 UNLOCK(&adb->reflock); 1540} 1541 1542static inline void 1543inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { 1544 int bucket; 1545 1546 bucket = entry->lock_bucket; 1547 1548 if (lock) 1549 LOCK(&adb->entrylocks[bucket]); 1550 1551 entry->refcnt++; 1552 1553 if (lock) 1554 UNLOCK(&adb->entrylocks[bucket]); 1555} 1556 1557static inline isc_boolean_t 1558dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry, 1559 isc_boolean_t lock) 1560{ 1561 int bucket; 1562 isc_boolean_t destroy_entry; 1563 isc_boolean_t result = ISC_FALSE; 1564 1565 bucket = entry->lock_bucket; 1566 1567 if (lock) 1568 LOCK(&adb->entrylocks[bucket]); 1569 1570 INSIST(entry->refcnt > 0); 1571 entry->refcnt--; 1572 1573 destroy_entry = ISC_FALSE; 1574 if (entry->refcnt == 0 && 1575 (adb->entry_sd[bucket] || entry->expires == 0 || overmem || 1576 (entry->flags & ENTRY_IS_DEAD) != 0)) { 1577 destroy_entry = ISC_TRUE; 1578 result = unlink_entry(adb, entry); 1579 } 1580 1581 if (lock) 1582 UNLOCK(&adb->entrylocks[bucket]); 1583 1584 if (!destroy_entry) 1585 return (result); 1586 1587 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 1588 1589 free_adbentry(adb, &entry); 1590 if (result) 1591 result = dec_adb_irefcnt(adb); 1592 1593 return (result); 1594} 1595 1596static inline dns_adbname_t * 1597new_adbname(dns_adb_t *adb, dns_name_t *dnsname) { 1598 dns_adbname_t *name; 1599 1600 name = isc_mempool_get(adb->nmp); 1601 if (name == NULL) 1602 return (NULL); 1603 1604 dns_name_init(&name->name, NULL); 1605 if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) { 1606 isc_mempool_put(adb->nmp, name); 1607 return (NULL); 1608 } 1609 dns_name_init(&name->target, NULL); 1610 name->magic = DNS_ADBNAME_MAGIC; 1611 name->adb = adb; 1612 name->partial_result = 0; 1613 name->flags = 0; 1614 name->expire_v4 = INT_MAX; 1615 name->expire_v6 = INT_MAX; 1616 name->expire_target = INT_MAX; 1617 name->chains = 0; 1618 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 1619 ISC_LIST_INIT(name->v4); 1620 ISC_LIST_INIT(name->v6); 1621 name->fetch_a = NULL; 1622 name->fetch_aaaa = NULL; 1623 name->fetch_err = FIND_ERR_UNEXPECTED; 1624 name->fetch6_err = FIND_ERR_UNEXPECTED; 1625 ISC_LIST_INIT(name->finds); 1626 ISC_LINK_INIT(name, plink); 1627 1628 LOCK(&adb->namescntlock); 1629 adb->namescnt++; 1630 if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) { 1631 isc_event_t *event = &adb->grownames; 1632 inc_adb_irefcnt(adb); 1633 isc_task_send(adb->task, &event); 1634 adb->grownames_sent = ISC_TRUE; 1635 } 1636 UNLOCK(&adb->namescntlock); 1637 1638 return (name); 1639} 1640 1641static inline void 1642free_adbname(dns_adb_t *adb, dns_adbname_t **name) { 1643 dns_adbname_t *n; 1644 1645 INSIST(name != NULL && DNS_ADBNAME_VALID(*name)); 1646 n = *name; 1647 *name = NULL; 1648 1649 INSIST(!NAME_HAS_V4(n)); 1650 INSIST(!NAME_HAS_V6(n)); 1651 INSIST(!NAME_FETCH(n)); 1652 INSIST(ISC_LIST_EMPTY(n->finds)); 1653 INSIST(!ISC_LINK_LINKED(n, plink)); 1654 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET); 1655 INSIST(n->adb == adb); 1656 1657 n->magic = 0; 1658 dns_name_free(&n->name, adb->mctx); 1659 1660 isc_mempool_put(adb->nmp, n); 1661 LOCK(&adb->namescntlock); 1662 adb->namescnt--; 1663 UNLOCK(&adb->namescntlock); 1664} 1665 1666static inline dns_adbnamehook_t * 1667new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) { 1668 dns_adbnamehook_t *nh; 1669 1670 nh = isc_mempool_get(adb->nhmp); 1671 if (nh == NULL) 1672 return (NULL); 1673 1674 nh->magic = DNS_ADBNAMEHOOK_MAGIC; 1675 nh->entry = entry; 1676 ISC_LINK_INIT(nh, plink); 1677 1678 return (nh); 1679} 1680 1681static inline void 1682free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) { 1683 dns_adbnamehook_t *nh; 1684 1685 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook)); 1686 nh = *namehook; 1687 *namehook = NULL; 1688 1689 INSIST(nh->entry == NULL); 1690 INSIST(!ISC_LINK_LINKED(nh, plink)); 1691 1692 nh->magic = 0; 1693 isc_mempool_put(adb->nhmp, nh); 1694} 1695 1696static inline dns_adblameinfo_t * 1697new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) { 1698 dns_adblameinfo_t *li; 1699 1700 li = isc_mempool_get(adb->limp); 1701 if (li == NULL) 1702 return (NULL); 1703 1704 dns_name_init(&li->qname, NULL); 1705 if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) { 1706 isc_mempool_put(adb->limp, li); 1707 return (NULL); 1708 } 1709 li->magic = DNS_ADBLAMEINFO_MAGIC; 1710 li->lame_timer = 0; 1711 li->qtype = qtype; 1712 ISC_LINK_INIT(li, plink); 1713 1714 return (li); 1715} 1716 1717static inline void 1718free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) { 1719 dns_adblameinfo_t *li; 1720 1721 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo)); 1722 li = *lameinfo; 1723 *lameinfo = NULL; 1724 1725 INSIST(!ISC_LINK_LINKED(li, plink)); 1726 1727 dns_name_free(&li->qname, adb->mctx); 1728 1729 li->magic = 0; 1730 1731 isc_mempool_put(adb->limp, li); 1732} 1733 1734static inline dns_adbentry_t * 1735new_adbentry(dns_adb_t *adb) { 1736 dns_adbentry_t *e; 1737 isc_uint32_t r; 1738 1739 e = isc_mempool_get(adb->emp); 1740 if (e == NULL) 1741 return (NULL); 1742 1743 e->magic = DNS_ADBENTRY_MAGIC; 1744 e->lock_bucket = DNS_ADB_INVALIDBUCKET; 1745 e->refcnt = 0; 1746 e->flags = 0; 1747 isc_random_get(&r); 1748 e->srtt = (r & 0x1f) + 1; 1749 e->expires = 0; 1750 ISC_LIST_INIT(e->lameinfo); 1751 ISC_LINK_INIT(e, plink); 1752 LOCK(&adb->entriescntlock); 1753 adb->entriescnt++; 1754 if (!adb->growentries_sent && 1755 adb->entriescnt > (adb->nentries * 8)) { 1756 isc_event_t *event = &adb->growentries; 1757 inc_adb_irefcnt(adb); 1758 isc_task_send(adb->task, …
Large files files are truncated, but you can click here to view the full file