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