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