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