1 /* $NetBSD: adb.c,v 1.5 2020/05/24 19:46:22 christos 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 http://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, bucket; 762 763 adb = ev->ev_arg; 764 INSIST(DNS_ADB_VALID(adb)); 765 766 isc_event_free(&ev); 767 768 result = isc_task_beginexclusive(task); 769 if (result != ISC_R_SUCCESS) { 770 goto check_exit; 771 } 772 773 i = 0; 774 while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i]) { 775 i++; 776 } 777 if (nbuckets[i] != 0) { 778 n = nbuckets[i]; 779 } else { 780 goto done; 781 } 782 783 DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n); 784 785 /* 786 * Are we shutting down? 787 */ 788 for (i = 0; i < adb->nnames; i++) { 789 if (adb->name_sd[i]) { 790 goto cleanup; 791 792 /* 793 * Grab all the resources we need. 794 */ 795 } 796 } 797 798 /* 799 * Grab all the resources we need. 800 */ 801 newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n); 802 newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n); 803 newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n); 804 newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n); 805 newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n); 806 if (newnames == NULL || newdeadnames == NULL || newnamelocks == NULL || 807 newname_sd == NULL || newname_refcnt == NULL) 808 { 809 goto cleanup; 810 } 811 812 /* 813 * Initialise the new resources. 814 */ 815 isc_mutexblock_init(newnamelocks, n); 816 817 for (i = 0; i < n; i++) { 818 ISC_LIST_INIT(newnames[i]); 819 ISC_LIST_INIT(newdeadnames[i]); 820 newname_sd[i] = false; 821 newname_refcnt[i] = 0; 822 adb->irefcnt++; 823 } 824 825 /* 826 * Move names to new arrays. 827 */ 828 for (i = 0; i < adb->nnames; i++) { 829 name = ISC_LIST_HEAD(adb->names[i]); 830 while (name != NULL) { 831 ISC_LIST_UNLINK(adb->names[i], name, plink); 832 bucket = dns_name_fullhash(&name->name, true) % n; 833 name->lock_bucket = bucket; 834 ISC_LIST_APPEND(newnames[bucket], name, plink); 835 INSIST(adb->name_refcnt[i] > 0); 836 adb->name_refcnt[i]--; 837 newname_refcnt[bucket]++; 838 name = ISC_LIST_HEAD(adb->names[i]); 839 } 840 name = ISC_LIST_HEAD(adb->deadnames[i]); 841 while (name != NULL) { 842 ISC_LIST_UNLINK(adb->deadnames[i], name, plink); 843 bucket = dns_name_fullhash(&name->name, true) % n; 844 name->lock_bucket = bucket; 845 ISC_LIST_APPEND(newdeadnames[bucket], name, plink); 846 INSIST(adb->name_refcnt[i] > 0); 847 adb->name_refcnt[i]--; 848 newname_refcnt[bucket]++; 849 name = ISC_LIST_HEAD(adb->deadnames[i]); 850 } 851 INSIST(adb->name_refcnt[i] == 0); 852 adb->irefcnt--; 853 } 854 855 /* 856 * Cleanup old resources. 857 */ 858 isc_mutexblock_destroy(adb->namelocks, adb->nnames); 859 isc_mem_put(adb->mctx, adb->names, sizeof(*adb->names) * adb->nnames); 860 isc_mem_put(adb->mctx, adb->deadnames, 861 sizeof(*adb->deadnames) * adb->nnames); 862 isc_mem_put(adb->mctx, adb->namelocks, 863 sizeof(*adb->namelocks) * adb->nnames); 864 isc_mem_put(adb->mctx, adb->name_sd, 865 sizeof(*adb->name_sd) * adb->nnames); 866 isc_mem_put(adb->mctx, adb->name_refcnt, 867 sizeof(*adb->name_refcnt) * adb->nnames); 868 869 /* 870 * Install new resources. 871 */ 872 adb->names = newnames; 873 adb->deadnames = newdeadnames; 874 adb->namelocks = newnamelocks; 875 adb->name_sd = newname_sd; 876 adb->name_refcnt = newname_refcnt; 877 adb->nnames = n; 878 879 set_adbstat(adb, adb->nnames, dns_adbstats_nnames); 880 881 /* 882 * Only on success do we set adb->grownames_sent to false. 883 * This will prevent us being continuously being called on error. 884 */ 885 adb->grownames_sent = false; 886 goto done; 887 888 cleanup: 889 if (newnames != NULL) { 890 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n); 891 } 892 if (newdeadnames != NULL) { 893 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n); 894 } 895 if (newnamelocks != NULL) { 896 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n); 897 } 898 if (newname_sd != NULL) { 899 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n); 900 } 901 if (newname_refcnt != NULL) { 902 isc_mem_put(adb->mctx, newname_refcnt, 903 sizeof(*newname_refcnt) * n); 904 } 905 done: 906 isc_task_endexclusive(task); 907 908 check_exit: 909 LOCK(&adb->lock); 910 if (dec_adb_irefcnt(adb)) { 911 check_exit(adb); 912 } 913 UNLOCK(&adb->lock); 914 DP(ISC_LOG_INFO, "adb: grow_names finished"); 915 } 916 917 /* 918 * Requires the adbname bucket be locked and that no entry buckets be locked. 919 * 920 * This code handles A and AAAA rdatasets only. 921 */ 922 static isc_result_t 923 import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset, 924 isc_stdtime_t now) { 925 isc_result_t result; 926 dns_adb_t *adb; 927 dns_adbnamehook_t *nh; 928 dns_adbnamehook_t *anh; 929 dns_rdata_t rdata = DNS_RDATA_INIT; 930 struct in_addr ina; 931 struct in6_addr in6a; 932 isc_sockaddr_t sockaddr; 933 dns_adbentry_t *foundentry; /* NO CLEAN UP! */ 934 int addr_bucket; 935 bool new_addresses_added; 936 dns_rdatatype_t rdtype; 937 unsigned int findoptions; 938 dns_adbnamehooklist_t *hookhead; 939 940 INSIST(DNS_ADBNAME_VALID(adbname)); 941 adb = adbname->adb; 942 INSIST(DNS_ADB_VALID(adb)); 943 944 rdtype = rdataset->type; 945 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa)); 946 if (rdtype == dns_rdatatype_a) { 947 findoptions = DNS_ADBFIND_INET; 948 } else { 949 findoptions = DNS_ADBFIND_INET6; 950 } 951 952 addr_bucket = DNS_ADB_INVALIDBUCKET; 953 new_addresses_added = false; 954 955 nh = NULL; 956 result = dns_rdataset_first(rdataset); 957 while (result == ISC_R_SUCCESS) { 958 dns_rdata_reset(&rdata); 959 dns_rdataset_current(rdataset, &rdata); 960 if (rdtype == dns_rdatatype_a) { 961 INSIST(rdata.length == 4); 962 memmove(&ina.s_addr, rdata.data, 4); 963 isc_sockaddr_fromin(&sockaddr, &ina, 0); 964 hookhead = &adbname->v4; 965 } else { 966 INSIST(rdata.length == 16); 967 memmove(in6a.s6_addr, rdata.data, 16); 968 isc_sockaddr_fromin6(&sockaddr, &in6a, 0); 969 hookhead = &adbname->v6; 970 } 971 972 INSIST(nh == NULL); 973 nh = new_adbnamehook(adb, NULL); 974 if (nh == NULL) { 975 adbname->partial_result |= findoptions; 976 result = ISC_R_NOMEMORY; 977 goto fail; 978 } 979 980 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket, 981 now); 982 if (foundentry == NULL) { 983 dns_adbentry_t *entry; 984 985 entry = new_adbentry(adb); 986 if (entry == NULL) { 987 adbname->partial_result |= findoptions; 988 result = ISC_R_NOMEMORY; 989 goto fail; 990 } 991 992 entry->sockaddr = sockaddr; 993 entry->refcnt = 1; 994 entry->nh = 1; 995 996 nh->entry = entry; 997 998 link_entry(adb, addr_bucket, entry); 999 } else { 1000 for (anh = ISC_LIST_HEAD(*hookhead); anh != NULL; 1001 anh = ISC_LIST_NEXT(anh, plink)) 1002 { 1003 if (anh->entry == foundentry) { 1004 break; 1005 } 1006 } 1007 if (anh == NULL) { 1008 foundentry->refcnt++; 1009 foundentry->nh++; 1010 nh->entry = foundentry; 1011 } else { 1012 free_adbnamehook(adb, &nh); 1013 } 1014 } 1015 1016 new_addresses_added = true; 1017 if (nh != NULL) { 1018 ISC_LIST_APPEND(*hookhead, nh, plink); 1019 } 1020 nh = NULL; 1021 result = dns_rdataset_next(rdataset); 1022 } 1023 1024 fail: 1025 if (nh != NULL) { 1026 free_adbnamehook(adb, &nh); 1027 } 1028 1029 if (addr_bucket != DNS_ADB_INVALIDBUCKET) { 1030 UNLOCK(&adb->entrylocks[addr_bucket]); 1031 } 1032 1033 if (rdataset->trust == dns_trust_glue || 1034 rdataset->trust == dns_trust_additional) 1035 { 1036 rdataset->ttl = ADB_CACHE_MINIMUM; 1037 } else if (rdataset->trust == dns_trust_ultimate) { 1038 rdataset->ttl = 0; 1039 } else { 1040 rdataset->ttl = ttlclamp(rdataset->ttl); 1041 } 1042 1043 if (rdtype == dns_rdatatype_a) { 1044 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset", 1045 adbname->expire_v4, now + rdataset->ttl); 1046 adbname->expire_v4 = ISC_MIN( 1047 adbname->expire_v4, 1048 ISC_MIN(now + ADB_ENTRY_WINDOW, now + rdataset->ttl)); 1049 } else { 1050 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset", 1051 adbname->expire_v6, now + rdataset->ttl); 1052 adbname->expire_v6 = ISC_MIN( 1053 adbname->expire_v6, 1054 ISC_MIN(now + ADB_ENTRY_WINDOW, now + rdataset->ttl)); 1055 } 1056 1057 if (new_addresses_added) { 1058 /* 1059 * Lie a little here. This is more or less so code that cares 1060 * can find out if any new information was added or not. 1061 */ 1062 return (ISC_R_SUCCESS); 1063 } 1064 1065 return (result); 1066 } 1067 1068 /* 1069 * Requires the name's bucket be locked. 1070 */ 1071 static bool 1072 kill_name(dns_adbname_t **n, isc_eventtype_t ev) { 1073 dns_adbname_t *name; 1074 bool result = false; 1075 bool result4, result6; 1076 int bucket; 1077 dns_adb_t *adb; 1078 1079 INSIST(n != NULL); 1080 name = *n; 1081 *n = NULL; 1082 INSIST(DNS_ADBNAME_VALID(name)); 1083 adb = name->adb; 1084 INSIST(DNS_ADB_VALID(adb)); 1085 1086 DP(DEF_LEVEL, "killing name %p", name); 1087 1088 /* 1089 * If we're dead already, just check to see if we should go 1090 * away now or not. 1091 */ 1092 if (NAME_DEAD(name) && !NAME_FETCH(name)) { 1093 result = unlink_name(adb, name); 1094 free_adbname(adb, &name); 1095 if (result) { 1096 result = dec_adb_irefcnt(adb); 1097 } 1098 return (result); 1099 } 1100 1101 /* 1102 * Clean up the name's various lists. These two are destructive 1103 * in that they will always empty the list. 1104 */ 1105 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); 1106 result4 = clean_namehooks(adb, &name->v4); 1107 result6 = clean_namehooks(adb, &name->v6); 1108 clean_target(adb, &name->target); 1109 result = (result4 || result6); 1110 1111 /* 1112 * If fetches are running, cancel them. If none are running, we can 1113 * just kill the name here. 1114 */ 1115 if (!NAME_FETCH(name)) { 1116 INSIST(result == false); 1117 result = unlink_name(adb, name); 1118 free_adbname(adb, &name); 1119 if (result) { 1120 result = dec_adb_irefcnt(adb); 1121 } 1122 } else { 1123 cancel_fetches_at_name(name); 1124 if (!NAME_DEAD(name)) { 1125 bucket = name->lock_bucket; 1126 ISC_LIST_UNLINK(adb->names[bucket], name, plink); 1127 ISC_LIST_APPEND(adb->deadnames[bucket], name, plink); 1128 name->flags |= NAME_IS_DEAD; 1129 } 1130 } 1131 return (result); 1132 } 1133 1134 /* 1135 * Requires the name's bucket be locked and no entry buckets be locked. 1136 */ 1137 static bool 1138 check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) { 1139 dns_adb_t *adb; 1140 bool result4 = false; 1141 bool result6 = false; 1142 1143 INSIST(DNS_ADBNAME_VALID(name)); 1144 adb = name->adb; 1145 INSIST(DNS_ADB_VALID(adb)); 1146 1147 /* 1148 * Check to see if we need to remove the v4 addresses 1149 */ 1150 if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) { 1151 if (NAME_HAS_V4(name)) { 1152 DP(DEF_LEVEL, "expiring v4 for name %p", name); 1153 result4 = clean_namehooks(adb, &name->v4); 1154 name->partial_result &= ~DNS_ADBFIND_INET; 1155 } 1156 name->expire_v4 = INT_MAX; 1157 name->fetch_err = FIND_ERR_UNEXPECTED; 1158 } 1159 1160 /* 1161 * Check to see if we need to remove the v6 addresses 1162 */ 1163 if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) { 1164 if (NAME_HAS_V6(name)) { 1165 DP(DEF_LEVEL, "expiring v6 for name %p", name); 1166 result6 = clean_namehooks(adb, &name->v6); 1167 name->partial_result &= ~DNS_ADBFIND_INET6; 1168 } 1169 name->expire_v6 = INT_MAX; 1170 name->fetch6_err = FIND_ERR_UNEXPECTED; 1171 } 1172 1173 /* 1174 * Check to see if we need to remove the alias target. 1175 */ 1176 if (EXPIRE_OK(name->expire_target, now)) { 1177 clean_target(adb, &name->target); 1178 name->expire_target = INT_MAX; 1179 } 1180 return (result4 || result6); 1181 } 1182 1183 /* 1184 * Requires the name's bucket be locked. 1185 */ 1186 static inline void 1187 link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) { 1188 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET); 1189 1190 ISC_LIST_PREPEND(adb->names[bucket], name, plink); 1191 name->lock_bucket = bucket; 1192 adb->name_refcnt[bucket]++; 1193 } 1194 1195 /* 1196 * Requires the name's bucket be locked. 1197 */ 1198 static inline bool 1199 unlink_name(dns_adb_t *adb, dns_adbname_t *name) { 1200 int bucket; 1201 bool result = false; 1202 1203 bucket = name->lock_bucket; 1204 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 1205 1206 if (NAME_DEAD(name)) { 1207 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink); 1208 } else { 1209 ISC_LIST_UNLINK(adb->names[bucket], name, plink); 1210 } 1211 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 1212 INSIST(adb->name_refcnt[bucket] > 0); 1213 adb->name_refcnt[bucket]--; 1214 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) { 1215 result = true; 1216 } 1217 return (result); 1218 } 1219 1220 /* 1221 * Requires the entry's bucket be locked. 1222 */ 1223 static inline void 1224 link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) { 1225 int i; 1226 dns_adbentry_t *e; 1227 1228 if (isc_mem_isovermem(adb->mctx)) { 1229 for (i = 0; i < 2; i++) { 1230 e = ISC_LIST_TAIL(adb->entries[bucket]); 1231 if (e == NULL) { 1232 break; 1233 } 1234 if (e->refcnt == 0) { 1235 unlink_entry(adb, e); 1236 free_adbentry(adb, &e); 1237 continue; 1238 } 1239 INSIST((e->flags & ENTRY_IS_DEAD) == 0); 1240 e->flags |= ENTRY_IS_DEAD; 1241 ISC_LIST_UNLINK(adb->entries[bucket], e, plink); 1242 ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink); 1243 } 1244 } 1245 1246 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink); 1247 entry->lock_bucket = bucket; 1248 adb->entry_refcnt[bucket]++; 1249 } 1250 1251 /* 1252 * Requires the entry's bucket be locked. 1253 */ 1254 static inline bool 1255 unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) { 1256 int bucket; 1257 bool result = false; 1258 1259 bucket = entry->lock_bucket; 1260 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 1261 1262 if ((entry->flags & ENTRY_IS_DEAD) != 0) { 1263 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink); 1264 } else { 1265 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink); 1266 } 1267 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 1268 INSIST(adb->entry_refcnt[bucket] > 0); 1269 adb->entry_refcnt[bucket]--; 1270 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0) { 1271 result = true; 1272 } 1273 return (result); 1274 } 1275 1276 static inline void 1277 violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) { 1278 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) { 1279 UNLOCK(have); 1280 LOCK(want); 1281 LOCK(have); 1282 } 1283 } 1284 1285 /* 1286 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 1287 * checked after calling this function. 1288 */ 1289 static bool 1290 shutdown_names(dns_adb_t *adb) { 1291 unsigned int bucket; 1292 bool result = false; 1293 dns_adbname_t *name; 1294 dns_adbname_t *next_name; 1295 1296 for (bucket = 0; bucket < adb->nnames; bucket++) { 1297 LOCK(&adb->namelocks[bucket]); 1298 adb->name_sd[bucket] = true; 1299 1300 name = ISC_LIST_HEAD(adb->names[bucket]); 1301 if (name == NULL) { 1302 /* 1303 * This bucket has no names. We must decrement the 1304 * irefcnt ourselves, since it will not be 1305 * automatically triggered by a name being unlinked. 1306 */ 1307 INSIST(result == false); 1308 result = dec_adb_irefcnt(adb); 1309 } else { 1310 /* 1311 * Run through the list. For each name, clean up finds 1312 * found there, and cancel any fetches running. When 1313 * all the fetches are canceled, the name will destroy 1314 * itself. 1315 */ 1316 while (name != NULL) { 1317 next_name = ISC_LIST_NEXT(name, plink); 1318 INSIST(result == false); 1319 result = kill_name(&name, 1320 DNS_EVENT_ADBSHUTDOWN); 1321 name = next_name; 1322 } 1323 } 1324 1325 UNLOCK(&adb->namelocks[bucket]); 1326 } 1327 return (result); 1328 } 1329 1330 /* 1331 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 1332 * checked after calling this function. 1333 */ 1334 static bool 1335 shutdown_entries(dns_adb_t *adb) { 1336 unsigned int bucket; 1337 bool result = false; 1338 dns_adbentry_t *entry; 1339 dns_adbentry_t *next_entry; 1340 1341 for (bucket = 0; bucket < adb->nentries; bucket++) { 1342 LOCK(&adb->entrylocks[bucket]); 1343 adb->entry_sd[bucket] = true; 1344 1345 entry = ISC_LIST_HEAD(adb->entries[bucket]); 1346 if (adb->entry_refcnt[bucket] == 0) { 1347 /* 1348 * This bucket has no entries. We must decrement the 1349 * irefcnt ourselves, since it will not be 1350 * automatically triggered by an entry being unlinked. 1351 */ 1352 result = dec_adb_irefcnt(adb); 1353 } else { 1354 /* 1355 * Run through the list. Cleanup any entries not 1356 * associated with names, and which are not in use. 1357 */ 1358 while (entry != NULL) { 1359 next_entry = ISC_LIST_NEXT(entry, plink); 1360 if (entry->refcnt == 0 && entry->expires != 0) { 1361 result = unlink_entry(adb, entry); 1362 free_adbentry(adb, &entry); 1363 if (result) { 1364 result = dec_adb_irefcnt(adb); 1365 } 1366 } 1367 entry = next_entry; 1368 } 1369 } 1370 1371 UNLOCK(&adb->entrylocks[bucket]); 1372 } 1373 return (result); 1374 } 1375 1376 /* 1377 * Name bucket must be locked 1378 */ 1379 static void 1380 cancel_fetches_at_name(dns_adbname_t *name) { 1381 if (NAME_FETCH_A(name)) { 1382 dns_resolver_cancelfetch(name->fetch_a->fetch); 1383 } 1384 1385 if (NAME_FETCH_AAAA(name)) { 1386 dns_resolver_cancelfetch(name->fetch_aaaa->fetch); 1387 } 1388 } 1389 1390 /* 1391 * Assumes the name bucket is locked. 1392 */ 1393 static bool 1394 clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { 1395 dns_adbentry_t *entry; 1396 dns_adbnamehook_t *namehook; 1397 int addr_bucket; 1398 bool result = false; 1399 bool overmem = isc_mem_isovermem(adb->mctx); 1400 1401 addr_bucket = DNS_ADB_INVALIDBUCKET; 1402 namehook = ISC_LIST_HEAD(*namehooks); 1403 while (namehook != NULL) { 1404 INSIST(DNS_ADBNAMEHOOK_VALID(namehook)); 1405 1406 /* 1407 * Clean up the entry if needed. 1408 */ 1409 entry = namehook->entry; 1410 if (entry != NULL) { 1411 INSIST(DNS_ADBENTRY_VALID(entry)); 1412 1413 if (addr_bucket != entry->lock_bucket) { 1414 if (addr_bucket != DNS_ADB_INVALIDBUCKET) { 1415 UNLOCK(&adb->entrylocks[addr_bucket]); 1416 } 1417 addr_bucket = entry->lock_bucket; 1418 INSIST(addr_bucket != DNS_ADB_INVALIDBUCKET); 1419 LOCK(&adb->entrylocks[addr_bucket]); 1420 } 1421 1422 entry->nh--; 1423 result = dec_entry_refcnt(adb, overmem, entry, false); 1424 } 1425 1426 /* 1427 * Free the namehook 1428 */ 1429 namehook->entry = NULL; 1430 ISC_LIST_UNLINK(*namehooks, namehook, plink); 1431 free_adbnamehook(adb, &namehook); 1432 1433 namehook = ISC_LIST_HEAD(*namehooks); 1434 } 1435 1436 if (addr_bucket != DNS_ADB_INVALIDBUCKET) { 1437 UNLOCK(&adb->entrylocks[addr_bucket]); 1438 } 1439 return (result); 1440 } 1441 1442 static void 1443 clean_target(dns_adb_t *adb, dns_name_t *target) { 1444 if (dns_name_countlabels(target) > 0) { 1445 dns_name_free(target, adb->mctx); 1446 dns_name_init(target, NULL); 1447 } 1448 } 1449 1450 static isc_result_t 1451 set_target(dns_adb_t *adb, const dns_name_t *name, const dns_name_t *fname, 1452 dns_rdataset_t *rdataset, dns_name_t *target) { 1453 isc_result_t result; 1454 dns_namereln_t namereln; 1455 unsigned int nlabels; 1456 int order; 1457 dns_rdata_t rdata = DNS_RDATA_INIT; 1458 dns_fixedname_t fixed1, fixed2; 1459 dns_name_t *prefix, *new_target; 1460 1461 REQUIRE(dns_name_countlabels(target) == 0); 1462 1463 if (rdataset->type == dns_rdatatype_cname) { 1464 dns_rdata_cname_t cname; 1465 1466 /* 1467 * Copy the CNAME's target into the target name. 1468 */ 1469 result = dns_rdataset_first(rdataset); 1470 if (result != ISC_R_SUCCESS) { 1471 return (result); 1472 } 1473 dns_rdataset_current(rdataset, &rdata); 1474 result = dns_rdata_tostruct(&rdata, &cname, NULL); 1475 if (result != ISC_R_SUCCESS) { 1476 return (result); 1477 } 1478 dns_name_dup(&cname.cname, adb->mctx, target); 1479 dns_rdata_freestruct(&cname); 1480 } else { 1481 dns_rdata_dname_t dname; 1482 1483 INSIST(rdataset->type == dns_rdatatype_dname); 1484 namereln = dns_name_fullcompare(name, fname, &order, &nlabels); 1485 INSIST(namereln == dns_namereln_subdomain); 1486 /* 1487 * Get the target name of the DNAME. 1488 */ 1489 result = dns_rdataset_first(rdataset); 1490 if (result != ISC_R_SUCCESS) { 1491 return (result); 1492 } 1493 dns_rdataset_current(rdataset, &rdata); 1494 result = dns_rdata_tostruct(&rdata, &dname, NULL); 1495 if (result != ISC_R_SUCCESS) { 1496 return (result); 1497 } 1498 /* 1499 * Construct the new target name. 1500 */ 1501 prefix = dns_fixedname_initname(&fixed1); 1502 new_target = dns_fixedname_initname(&fixed2); 1503 dns_name_split(name, nlabels, prefix, NULL); 1504 result = dns_name_concatenate(prefix, &dname.dname, new_target, 1505 NULL); 1506 dns_rdata_freestruct(&dname); 1507 if (result != ISC_R_SUCCESS) { 1508 return (result); 1509 } 1510 dns_name_dup(new_target, adb->mctx, target); 1511 } 1512 1513 return (ISC_R_SUCCESS); 1514 } 1515 1516 /* 1517 * Assumes nothing is locked, since this is called by the client. 1518 */ 1519 static void 1520 event_free(isc_event_t *event) { 1521 dns_adbfind_t *find; 1522 1523 INSIST(event != NULL); 1524 find = event->ev_destroy_arg; 1525 INSIST(DNS_ADBFIND_VALID(find)); 1526 1527 LOCK(&find->lock); 1528 find->flags |= FIND_EVENT_FREED; 1529 event->ev_destroy_arg = NULL; 1530 UNLOCK(&find->lock); 1531 } 1532 1533 /* 1534 * Assumes the name bucket is locked. 1535 */ 1536 static void 1537 clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, 1538 unsigned int addrs) { 1539 isc_event_t *ev; 1540 isc_task_t *task; 1541 dns_adbfind_t *find; 1542 dns_adbfind_t *next_find; 1543 bool process; 1544 unsigned int wanted, notify; 1545 1546 DP(ENTER_LEVEL, 1547 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x", name, 1548 evtype, addrs); 1549 1550 find = ISC_LIST_HEAD(name->finds); 1551 while (find != NULL) { 1552 LOCK(&find->lock); 1553 next_find = ISC_LIST_NEXT(find, plink); 1554 1555 process = false; 1556 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1557 notify = wanted & addrs; 1558 1559 switch (evtype) { 1560 case DNS_EVENT_ADBMOREADDRESSES: 1561 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES"); 1562 if ((notify) != 0) { 1563 find->flags &= ~addrs; 1564 process = true; 1565 } 1566 break; 1567 case DNS_EVENT_ADBNOMOREADDRESSES: 1568 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES"); 1569 find->flags &= ~addrs; 1570 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1571 if (wanted == 0) { 1572 process = true; 1573 } 1574 break; 1575 default: 1576 find->flags &= ~addrs; 1577 process = true; 1578 } 1579 1580 if (process) { 1581 DP(DEF_LEVEL, "cfan: processing find %p", find); 1582 /* 1583 * Unlink the find from the name, letting the caller 1584 * call dns_adb_destroyfind() on it to clean it up 1585 * later. 1586 */ 1587 ISC_LIST_UNLINK(name->finds, find, plink); 1588 find->adbname = NULL; 1589 find->name_bucket = DNS_ADB_INVALIDBUCKET; 1590 1591 INSIST(!FIND_EVENTSENT(find)); 1592 1593 ev = &find->event; 1594 task = ev->ev_sender; 1595 ev->ev_sender = find; 1596 find->result_v4 = find_err_map[name->fetch_err]; 1597 find->result_v6 = find_err_map[name->fetch6_err]; 1598 ev->ev_type = evtype; 1599 ev->ev_destroy = event_free; 1600 ev->ev_destroy_arg = find; 1601 1602 DP(DEF_LEVEL, "sending event %p to task %p for find %p", 1603 ev, task, find); 1604 1605 isc_task_sendanddetach(&task, (isc_event_t **)&ev); 1606 find->flags |= FIND_EVENT_SENT; 1607 } else { 1608 DP(DEF_LEVEL, "cfan: skipping find %p", find); 1609 } 1610 1611 UNLOCK(&find->lock); 1612 find = next_find; 1613 } 1614 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name); 1615 } 1616 1617 static inline void 1618 check_exit(dns_adb_t *adb) { 1619 isc_event_t *event; 1620 /* 1621 * The caller must be holding the adb lock. 1622 */ 1623 if (adb->shutting_down) { 1624 /* 1625 * If there aren't any external references either, we're 1626 * done. Send the control event to initiate shutdown. 1627 */ 1628 INSIST(!adb->cevent_out); /* Sanity check. */ 1629 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, 1630 DNS_EVENT_ADBCONTROL, shutdown_task, adb, adb, 1631 NULL, NULL); 1632 event = &adb->cevent; 1633 isc_task_send(adb->task, &event); 1634 adb->cevent_out = true; 1635 } 1636 } 1637 1638 static inline bool 1639 dec_adb_irefcnt(dns_adb_t *adb) { 1640 isc_event_t *event; 1641 isc_task_t *etask; 1642 bool result = false; 1643 1644 LOCK(&adb->reflock); 1645 1646 INSIST(adb->irefcnt > 0); 1647 adb->irefcnt--; 1648 1649 if (adb->irefcnt == 0) { 1650 event = ISC_LIST_HEAD(adb->whenshutdown); 1651 while (event != NULL) { 1652 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link); 1653 etask = event->ev_sender; 1654 event->ev_sender = adb; 1655 isc_task_sendanddetach(&etask, &event); 1656 event = ISC_LIST_HEAD(adb->whenshutdown); 1657 } 1658 } 1659 1660 if (adb->irefcnt == 0 && adb->erefcnt == 0) { 1661 result = true; 1662 } 1663 UNLOCK(&adb->reflock); 1664 return (result); 1665 } 1666 1667 static inline void 1668 inc_adb_irefcnt(dns_adb_t *adb) { 1669 LOCK(&adb->reflock); 1670 adb->irefcnt++; 1671 UNLOCK(&adb->reflock); 1672 } 1673 1674 static inline void 1675 inc_adb_erefcnt(dns_adb_t *adb) { 1676 LOCK(&adb->reflock); 1677 adb->erefcnt++; 1678 UNLOCK(&adb->reflock); 1679 } 1680 1681 static inline void 1682 inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, bool lock) { 1683 int bucket; 1684 1685 bucket = entry->lock_bucket; 1686 1687 if (lock) { 1688 LOCK(&adb->entrylocks[bucket]); 1689 } 1690 1691 entry->refcnt++; 1692 1693 if (lock) { 1694 UNLOCK(&adb->entrylocks[bucket]); 1695 } 1696 } 1697 1698 static inline bool 1699 dec_entry_refcnt(dns_adb_t *adb, bool overmem, dns_adbentry_t *entry, 1700 bool lock) { 1701 int bucket; 1702 bool destroy_entry; 1703 bool result = false; 1704 1705 bucket = entry->lock_bucket; 1706 1707 if (lock) { 1708 LOCK(&adb->entrylocks[bucket]); 1709 } 1710 1711 INSIST(entry->refcnt > 0); 1712 entry->refcnt--; 1713 1714 destroy_entry = false; 1715 if (entry->refcnt == 0 && 1716 (adb->entry_sd[bucket] || entry->expires == 0 || overmem || 1717 (entry->flags & ENTRY_IS_DEAD) != 0)) 1718 { 1719 destroy_entry = true; 1720 result = unlink_entry(adb, entry); 1721 } 1722 1723 if (lock) { 1724 UNLOCK(&adb->entrylocks[bucket]); 1725 } 1726 1727 if (!destroy_entry) { 1728 return (result); 1729 } 1730 1731 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 1732 1733 free_adbentry(adb, &entry); 1734 if (result) { 1735 result = dec_adb_irefcnt(adb); 1736 } 1737 1738 return (result); 1739 } 1740 1741 static inline dns_adbname_t * 1742 new_adbname(dns_adb_t *adb, const dns_name_t *dnsname) { 1743 dns_adbname_t *name; 1744 1745 name = isc_mempool_get(adb->nmp); 1746 if (name == NULL) { 1747 return (NULL); 1748 } 1749 1750 dns_name_init(&name->name, NULL); 1751 dns_name_dup(dnsname, adb->mctx, &name->name); 1752 dns_name_init(&name->target, NULL); 1753 name->magic = DNS_ADBNAME_MAGIC; 1754 name->adb = adb; 1755 name->partial_result = 0; 1756 name->flags = 0; 1757 name->expire_v4 = INT_MAX; 1758 name->expire_v6 = INT_MAX; 1759 name->expire_target = INT_MAX; 1760 name->chains = 0; 1761 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 1762 ISC_LIST_INIT(name->v4); 1763 ISC_LIST_INIT(name->v6); 1764 name->fetch_a = NULL; 1765 name->fetch_aaaa = NULL; 1766 name->fetch_err = FIND_ERR_UNEXPECTED; 1767 name->fetch6_err = FIND_ERR_UNEXPECTED; 1768 ISC_LIST_INIT(name->finds); 1769 ISC_LINK_INIT(name, plink); 1770 1771 LOCK(&adb->namescntlock); 1772 adb->namescnt++; 1773 inc_adbstats(adb, dns_adbstats_namescnt); 1774 if (!adb->grownames_sent && adb->excl != NULL && 1775 adb->namescnt > (adb->nnames * 8)) 1776 { 1777 isc_event_t *event = &adb->grownames; 1778 inc_adb_irefcnt(adb); 1779 isc_task_send(adb->excl, &event); 1780 adb->grownames_sent = true; 1781 } 1782 UNLOCK(&adb->namescntlock); 1783 1784 return (name); 1785 } 1786 1787 static inline void 1788 free_adbname(dns_adb_t *adb, dns_adbname_t **name) { 1789 dns_adbname_t *n; 1790 1791 INSIST(name != NULL && DNS_ADBNAME_VALID(*name)); 1792 n = *name; 1793 *name = NULL; 1794 1795 INSIST(!NAME_HAS_V4(n)); 1796 INSIST(!NAME_HAS_V6(n)); 1797 INSIST(!NAME_FETCH(n)); 1798 INSIST(ISC_LIST_EMPTY(n->finds)); 1799 INSIST(!ISC_LINK_LINKED(n, plink)); 1800 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET); 1801 INSIST(n->adb == adb); 1802 1803 n->magic = 0; 1804 dns_name_free(&n->name, adb->mctx); 1805 1806 isc_mempool_put(adb->nmp, n); 1807 LOCK(&adb->namescntlock); 1808 adb->namescnt--; 1809 dec_adbstats(adb, dns_adbstats_namescnt); 1810 UNLOCK(&adb->namescntlock); 1811 } 1812 1813 static inline dns_adbnamehook_t * 1814 new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) { 1815 dns_adbnamehook_t *nh; 1816 1817 nh = isc_mempool_get(adb->nhmp); 1818 if (nh == NULL) { 1819 return (NULL); 1820 } 1821 1822 nh->magic = DNS_ADBNAMEHOOK_MAGIC; 1823 nh->entry = entry; 1824 ISC_LINK_INIT(nh, plink); 1825 1826 return (nh); 1827 } 1828 1829 static inline void 1830 free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) { 1831 dns_adbnamehook_t *nh; 1832 1833 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook)); 1834 nh = *namehook; 1835 *namehook = NULL; 1836 1837 INSIST(nh->entry == NULL); 1838 INSIST(!ISC_LINK_LINKED(nh, plink)); 1839 1840 nh->magic = 0; 1841 isc_mempool_put(adb->nhmp, nh); 1842 } 1843 1844 static inline dns_adblameinfo_t * 1845 new_adblameinfo(dns_adb_t *adb, const dns_name_t *qname, 1846 dns_rdatatype_t qtype) { 1847 dns_adblameinfo_t *li; 1848 1849 li = isc_mempool_get(adb->limp); 1850 if (li == NULL) { 1851 return (NULL); 1852 } 1853 1854 dns_name_init(&li->qname, NULL); 1855 dns_name_dup(qname, adb->mctx, &li->qname); 1856 li->magic = DNS_ADBLAMEINFO_MAGIC; 1857 li->lame_timer = 0; 1858 li->qtype = qtype; 1859 ISC_LINK_INIT(li, plink); 1860 1861 return (li); 1862 } 1863 1864 static inline void 1865 free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) { 1866 dns_adblameinfo_t *li; 1867 1868 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo)); 1869 li = *lameinfo; 1870 *lameinfo = NULL; 1871 1872 INSIST(!ISC_LINK_LINKED(li, plink)); 1873 1874 dns_name_free(&li->qname, adb->mctx); 1875 1876 li->magic = 0; 1877 1878 isc_mempool_put(adb->limp, li); 1879 } 1880 1881 static inline dns_adbentry_t * 1882 new_adbentry(dns_adb_t *adb) { 1883 dns_adbentry_t *e; 1884 1885 e = isc_mempool_get(adb->emp); 1886 if (e == NULL) { 1887 return (NULL); 1888 } 1889 1890 e->magic = DNS_ADBENTRY_MAGIC; 1891 e->lock_bucket = DNS_ADB_INVALIDBUCKET; 1892 e->refcnt = 0; 1893 e->nh = 0; 1894 e->flags = 0; 1895 e->udpsize = 0; 1896 e->edns = 0; 1897 e->completed = 0; 1898 e->timeouts = 0; 1899 e->plain = 0; 1900 e->plainto = 0; 1901 e->to4096 = 0; 1902 e->to1432 = 0; 1903 e->to1232 = 0; 1904 e->to512 = 0; 1905 e->cookie = NULL; 1906 e->cookielen = 0; 1907 e->srtt = (isc_random_uniform(0x1f)) + 1; 1908 e->lastage = 0; 1909 e->expires = 0; 1910 atomic_init(&e->active, 0); 1911 e->mode = 0; 1912 atomic_init(&e->quota, adb->quota); 1913 e->atr = 0.0; 1914 ISC_LIST_INIT(e->lameinfo); 1915 ISC_LINK_INIT(e, plink); 1916 LOCK(&adb->entriescntlock); 1917 adb->entriescnt++; 1918 inc_adbstats(adb, dns_adbstats_entriescnt); 1919 if (!adb->growentries_sent && adb->excl != NULL && 1920 adb->entriescnt > (adb->nentries * 8)) 1921 { 1922 isc_event_t *event = &adb->growentries; 1923 inc_adb_irefcnt(adb); 1924 isc_task_send(adb->excl, &event); 1925 adb->growentries_sent = true; 1926 } 1927 UNLOCK(&adb->entriescntlock); 1928 1929 return (e); 1930 } 1931 1932 static inline void 1933 free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) { 1934 dns_adbentry_t *e; 1935 dns_adblameinfo_t *li; 1936 1937 INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry)); 1938 e = *entry; 1939 *entry = NULL; 1940 1941 INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET); 1942 INSIST(e->refcnt == 0); 1943 INSIST(!ISC_LINK_LINKED(e, plink)); 1944 1945 e->magic = 0; 1946 1947 if (e->cookie != NULL) { 1948 isc_mem_put(adb->mctx, e->cookie, e->cookielen); 1949 } 1950 1951 li = ISC_LIST_HEAD(e->lameinfo); 1952 while (li != NULL) { 1953 ISC_LIST_UNLINK(e->lameinfo, li, plink); 1954 free_adblameinfo(adb, &li); 1955 li = ISC_LIST_HEAD(e->lameinfo); 1956 } 1957 1958 isc_mempool_put(adb->emp, e); 1959 LOCK(&adb->entriescntlock); 1960 adb->entriescnt--; 1961 dec_adbstats(adb, dns_adbstats_entriescnt); 1962 UNLOCK(&adb->entriescntlock); 1963 } 1964 1965 static inline dns_adbfind_t * 1966 new_adbfind(dns_adb_t *adb) { 1967 dns_adbfind_t *h; 1968 1969 h = isc_mempool_get(adb->ahmp); 1970 if (h == NULL) { 1971 return (NULL); 1972 } 1973 1974 /* 1975 * Public members. 1976 */ 1977 h->magic = 0; 1978 h->adb = adb; 1979 h->partial_result = 0; 1980 h->options = 0; 1981 h->flags = 0; 1982 h->result_v4 = ISC_R_UNEXPECTED; 1983 h->result_v6 = ISC_R_UNEXPECTED; 1984 ISC_LINK_INIT(h, publink); 1985 ISC_LINK_INIT(h, plink); 1986 ISC_LIST_INIT(h->list); 1987 h->adbname = NULL; 1988 h->name_bucket = DNS_ADB_INVALIDBUCKET; 1989 1990 /* 1991 * private members 1992 */ 1993 isc_mutex_init(&h->lock); 1994 1995 ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL, 1996 NULL, NULL, h); 1997 1998 inc_adb_irefcnt(adb); 1999 h->magic = DNS_ADBFIND_MAGIC; 2000 return (h); 2001 } 2002 2003 static inline dns_adbfetch_t * 2004 new_adbfetch(dns_adb_t *adb) { 2005 dns_adbfetch_t *f; 2006 2007 f = isc_mempool_get(adb->afmp); 2008 if (f == NULL) { 2009 return (NULL); 2010 } 2011 2012 f->magic = 0; 2013 f->fetch = NULL; 2014 2015 dns_rdataset_init(&f->rdataset); 2016 2017 f->magic = DNS_ADBFETCH_MAGIC; 2018 2019 return (f); 2020 } 2021 2022 static inline void 2023 free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) { 2024 dns_adbfetch_t *f; 2025 2026 INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch)); 2027 f = *fetch; 2028 *fetch = NULL; 2029 2030 f->magic = 0; 2031 2032 if (dns_rdataset_isassociated(&f->rdataset)) { 2033 dns_rdataset_disassociate(&f->rdataset); 2034 } 2035 2036 isc_mempool_put(adb->afmp, f); 2037 } 2038 2039 static inline bool 2040 free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) { 2041 dns_adbfind_t *find; 2042 2043 INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp)); 2044 find = *findp; 2045 *findp = NULL; 2046 2047 INSIST(!FIND_HAS_ADDRS(find)); 2048 INSIST(!ISC_LINK_LINKED(find, publink)); 2049 INSIST(!ISC_LINK_LINKED(find, plink)); 2050 INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET); 2051 INSIST(find->adbname == NULL); 2052 2053 find->magic = 0; 2054 2055 isc_mutex_destroy(&find->lock); 2056 isc_mempool_put(adb->ahmp, find); 2057 return (dec_adb_irefcnt(adb)); 2058 } 2059 2060 /* 2061 * Copy bits from the entry into the newly allocated addrinfo. The entry 2062 * must be locked, and the reference count must be bumped up by one 2063 * if this function returns a valid pointer. 2064 */ 2065 static inline dns_adbaddrinfo_t * 2066 new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) { 2067 dns_adbaddrinfo_t *ai; 2068 2069 ai = isc_mempool_get(adb->aimp); 2070 if (ai == NULL) { 2071 return (NULL); 2072 } 2073 2074 ai->magic = DNS_ADBADDRINFO_MAGIC; 2075 ai->sockaddr = entry->sockaddr; 2076 isc_sockaddr_setport(&ai->sockaddr, port); 2077 ai->srtt = entry->srtt; 2078 ai->flags = entry->flags; 2079 ai->entry = entry; 2080 ai->dscp = -1; 2081 ISC_LINK_INIT(ai, publink); 2082 2083 return (ai); 2084 } 2085 2086 static inline void 2087 free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) { 2088 dns_adbaddrinfo_t *ai; 2089 2090 INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo)); 2091 ai = *ainfo; 2092 *ainfo = NULL; 2093 2094 INSIST(ai->entry == NULL); 2095 INSIST(!ISC_LINK_LINKED(ai, publink)); 2096 2097 ai->magic = 0; 2098 2099 isc_mempool_put(adb->aimp, ai); 2100 } 2101 2102 /* 2103 * Search for the name. NOTE: The bucket is kept locked on both 2104 * success and failure, so it must always be unlocked by the caller! 2105 * 2106 * On the first call to this function, *bucketp must be set to 2107 * DNS_ADB_INVALIDBUCKET. 2108 */ 2109 static inline dns_adbname_t * 2110 find_name_and_lock(dns_adb_t *adb, const dns_name_t *name, unsigned int options, 2111 int *bucketp) { 2112 dns_adbname_t *adbname; 2113 int bucket; 2114 2115 bucket = dns_name_fullhash(name, false) % adb->nnames; 2116 2117 if (*bucketp == DNS_ADB_INVALIDBUCKET) { 2118 LOCK(&adb->namelocks[bucket]); 2119 *bucketp = bucket; 2120 } else if (*bucketp != bucket) { 2121 UNLOCK(&adb->namelocks[*bucketp]); 2122 LOCK(&adb->namelocks[bucket]); 2123 *bucketp = bucket; 2124 } 2125 2126 adbname = ISC_LIST_HEAD(adb->names[bucket]); 2127 while (adbname != NULL) { 2128 if (!NAME_DEAD(adbname)) { 2129 if (dns_name_equal(name, &adbname->name) && 2130 GLUEHINT_OK(adbname, options) && 2131 STARTATZONE_MATCHES(adbname, options)) 2132 { 2133 return (adbname); 2134 } 2135 } 2136 adbname = ISC_LIST_NEXT(adbname, plink); 2137 } 2138 2139 return (NULL); 2140 } 2141 2142 /* 2143 * Search for the address. NOTE: The bucket is kept locked on both 2144 * success and failure, so it must always be unlocked by the caller. 2145 * 2146 * On the first call to this function, *bucketp must be set to 2147 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On 2148 * later calls (within the same "lock path") it can be left alone, so 2149 * if this function is called multiple times locking is only done if 2150 * the bucket changes. 2151 */ 2152 static inline dns_adbentry_t * 2153 find_entry_and_lock(dns_adb_t *adb, const isc_sockaddr_t *addr, int *bucketp, 2154 isc_stdtime_t now) { 2155 dns_adbentry_t *entry, *entry_next; 2156 int bucket; 2157 2158 bucket = isc_sockaddr_hash(addr, true) % adb->nentries; 2159 2160 if (*bucketp == DNS_ADB_INVALIDBUCKET) { 2161 LOCK(&adb->entrylocks[bucket]); 2162 *bucketp = bucket; 2163 } else if (*bucketp != bucket) { 2164 UNLOCK(&adb->entrylocks[*bucketp]); 2165 LOCK(&adb->entrylocks[bucket]); 2166 *bucketp = bucket; 2167 } 2168 2169 /* Search the list, while cleaning up expired entries. */ 2170 for (entry = ISC_LIST_HEAD(adb->entries[bucket]); entry != NULL; 2171 entry = entry_next) 2172 { 2173 entry_next = ISC_LIST_NEXT(entry, plink); 2174 (void)check_expire_entry(adb, &entry, now); 2175 if (entry != NULL && 2176 (entry->expires == 0 || entry->expires > now) && 2177 isc_sockaddr_equal(addr, &entry->sockaddr)) 2178 { 2179 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink); 2180 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink); 2181 return (entry); 2182 } 2183 } 2184 2185 return (NULL); 2186 } 2187 2188 /* 2189 * Entry bucket MUST be locked! 2190 */ 2191 static bool 2192 entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, const dns_name_t *qname, 2193 dns_rdatatype_t qtype, isc_stdtime_t now) { 2194 dns_adblameinfo_t *li, *next_li; 2195 bool is_bad; 2196 2197 is_bad = false; 2198 2199 li = ISC_LIST_HEAD(entry->lameinfo); 2200 if (li == NULL) { 2201 return (false); 2202 } 2203 while (li != NULL) { 2204 next_li = ISC_LIST_NEXT(li, plink); 2205 2206 /* 2207 * Has the entry expired? 2208 */ 2209 if (li->lame_timer < now) { 2210 ISC_LIST_UNLINK(entry->lameinfo, li, plink); 2211 free_adblameinfo(adb, &li); 2212 } 2213 2214 /* 2215 * Order tests from least to most expensive. 2216 * 2217 * We do not break out of the main loop here as 2218 * we use the loop for house keeping. 2219 */ 2220 if (li != NULL && !is_bad && li->qtype == qtype && 2221 dns_name_equal(qname, &li->qname)) 2222 { 2223 is_bad = true; 2224 } 2225 2226 li = next_li; 2227 } 2228 2229 return (is_bad); 2230 } 2231 2232 static void 2233 log_quota(dns_adbentry_t *entry, const char *fmt, ...) { 2234 va_list ap; 2235 char msgbuf[2048]; 2236 char addrbuf[ISC_NETADDR_FORMATSIZE]; 2237 isc_netaddr_t netaddr; 2238 2239 va_start(ap, fmt); 2240 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 2241 va_end(ap); 2242 2243 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr); 2244 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); 2245 2246 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, 2247 ISC_LOG_INFO, 2248 "adb: quota %s (%" PRIuFAST32 "/%" PRIuFAST32 "): %s", 2249 addrbuf, atomic_load_relaxed(&entry->active), 2250 atomic_load_relaxed(&entry->quota), msgbuf); 2251 } 2252 2253 static void 2254 copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, 2255 const dns_name_t *qname, dns_rdatatype_t qtype, 2256 dns_adbname_t *name, isc_stdtime_t now) { 2257 dns_adbnamehook_t *namehook; 2258 dns_adbaddrinfo_t *addrinfo; 2259 dns_adbentry_t *entry; 2260 int bucket; 2261 2262 bucket = DNS_ADB_INVALIDBUCKET; 2263 2264 if ((find->options & DNS_ADBFIND_INET) != 0) { 2265 namehook = ISC_LIST_HEAD(name->v4); 2266 while (namehook != NULL) { 2267 entry = namehook->entry; 2268 bucket = entry->lock_bucket; 2269 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 2270 LOCK(&adb->entrylocks[bucket]); 2271 2272 if (dns_adbentry_overquota(entry)) { 2273 find->options |= (DNS_ADBFIND_LAMEPRUNED | 2274 DNS_ADBFIND_OVERQUOTA); 2275 goto nextv4; 2276 } 2277 2278 if (!FIND_RETURNLAME(find) && 2279 entry_is_lame(adb, entry, qname, qtype, now)) { 2280 find->options |= DNS_ADBFIND_LAMEPRUNED; 2281 goto nextv4; 2282 } 2283 addrinfo = new_adbaddrinfo(adb, entry, find->port); 2284 if (addrinfo == NULL) { 2285 find->partial_result |= DNS_ADBFIND_INET; 2286 goto out; 2287 } 2288 /* 2289 * Found a valid entry. Add it to the find's list. 2290 */ 2291 inc_entry_refcnt(adb, entry, false); 2292 ISC_LIST_APPEND(find->list, addrinfo, publink); 2293 addrinfo = NULL; 2294 nextv4: 2295 UNLOCK(&adb->entrylocks[bucket]); 2296 bucket = DNS_ADB_INVALIDBUCKET; 2297 namehook = ISC_LIST_NEXT(namehook, plink); 2298 } 2299 } 2300 2301 if ((find->options & DNS_ADBFIND_INET6) != 0) { 2302 namehook = ISC_LIST_HEAD(name->v6); 2303 while (namehook != NULL) { 2304 entry = namehook->entry; 2305 bucket = entry->lock_bucket; 2306 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 2307 LOCK(&adb->entrylocks[bucket]); 2308 2309 if (dns_adbentry_overquota(entry)) { 2310 find->options |= (DNS_ADBFIND_LAMEPRUNED | 2311 DNS_ADBFIND_OVERQUOTA); 2312 goto nextv6; 2313 } 2314 2315 if (!FIND_RETURNLAME(find) && 2316 entry_is_lame(adb, entry, qname, qtype, now)) { 2317 find->options |= DNS_ADBFIND_LAMEPRUNED; 2318 goto nextv6; 2319 } 2320 addrinfo = new_adbaddrinfo(adb, entry, find->port); 2321 if (addrinfo == NULL) { 2322 find->partial_result |= DNS_ADBFIND_INET6; 2323 goto out; 2324 } 2325 /* 2326 * Found a valid entry. Add it to the find's list. 2327 */ 2328 inc_entry_refcnt(adb, entry, false); 2329 ISC_LIST_APPEND(find->list, addrinfo, publink); 2330 addrinfo = NULL; 2331 nextv6: 2332 UNLOCK(&adb->entrylocks[bucket]); 2333 bucket = DNS_ADB_INVALIDBUCKET; 2334 namehook = ISC_LIST_NEXT(namehook, plink); 2335 } 2336 } 2337 2338 out: 2339 if (bucket != DNS_ADB_INVALIDBUCKET) { 2340 UNLOCK(&adb->entrylocks[bucket]); 2341 } 2342 } 2343 2344 static void 2345 shutdown_task(isc_task_t *task, isc_event_t *ev) { 2346 dns_adb_t *adb; 2347 2348 UNUSED(task); 2349 2350 adb = ev->ev_arg; 2351 INSIST(DNS_ADB_VALID(adb)); 2352 2353 isc_event_free(&ev); 2354 /* 2355 * Wait for lock around check_exit() call to be released. 2356 */ 2357 LOCK(&adb->lock); 2358 UNLOCK(&adb->lock); 2359 destroy(adb); 2360 } 2361 2362 /* 2363 * Name bucket must be locked; adb may be locked; no other locks held. 2364 */ 2365 static bool 2366 check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) { 2367 dns_adbname_t *name; 2368 bool result = false; 2369 2370 INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep)); 2371 name = *namep; 2372 2373 if (NAME_HAS_V4(name) || NAME_HAS_V6(name)) { 2374 return (result); 2375 } 2376 if (NAME_FETCH(name)) { 2377 return (result); 2378 } 2379 if (!EXPIRE_OK(name->expire_v4, now)) { 2380 return (result); 2381 } 2382 if (!EXPIRE_OK(name->expire_v6, now)) { 2383 return (result); 2384 } 2385 if (!EXPIRE_OK(name->expire_target, now)) { 2386 return (result); 2387 } 2388 2389 /* 2390 * The name is empty. Delete it. 2391 */ 2392 *namep = NULL; 2393 result = kill_name(&name, DNS_EVENT_ADBEXPIRED); 2394 2395 /* 2396 * Our caller, or one of its callers, will be calling check_exit() at 2397 * some point, so we don't need to do it here. 2398 */ 2399 return (result); 2400 } 2401 2402 /*% 2403 * Examine the tail entry of the LRU list to see if it expires or is stale 2404 * (unused for some period); if so, the name entry will be freed. If the ADB 2405 * is in the overmem condition, the tail and the next to tail entries 2406 * will be unconditionally removed (unless they have an outstanding fetch). 2407 * We don't care about a race on 'overmem' at the risk of causing some 2408 * collateral damage or a small delay in starting cleanup, so we don't bother 2409 * to lock ADB (if it's not locked). 2410 * 2411 * Name bucket must be locked; adb may be locked; no other locks held. 2412 */ 2413 static void 2414 check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) { 2415 int victims, max_victims; 2416 dns_adbname_t *victim, *next_victim; 2417 bool overmem = isc_mem_isovermem(adb->mctx); 2418 int scans = 0; 2419 2420 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 2421 2422 max_victims = overmem ? 2 : 1; 2423 2424 /* 2425 * We limit the number of scanned entries to 10 (arbitrary choice) 2426 * in order to avoid examining too many entries when there are many 2427 * tail entries that have fetches (this should be rare, but could 2428 * happen). 2429 */ 2430 victim = ISC_LIST_TAIL(adb->names[bucket]); 2431 for (victims = 0; victim != NULL && victims < max_victims && scans < 10; 2432 victim = next_victim) 2433 { 2434 INSIST(!NAME_DEAD(victim)); 2435 scans++; 2436 next_victim = ISC_LIST_PREV(victim, plink); 2437 (void)check_expire_name(&victim, now); 2438 if (victim == NULL) { 2439 victims++; 2440 goto next; 2441 } 2442 2443 if (!NAME_FETCH(victim) && 2444 (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) 2445 { 2446 RUNTIME_CHECK( 2447 kill_name(&victim, DNS_EVENT_ADBCANCELED) == 2448 false); 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 == false); 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 == false); 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 (/*CONSTCOND*/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 (/*CONSTCOND*/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 (/*CONSTCOND*/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) == false); 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) == false); 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) == false); 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 false); 3415 free_adbaddrinfo(adb, &ai); 3416 ai = ISC_LIST_HEAD(find->list); 3417 } 3418 3419 /* 3420 * WARNING: The find is freed with the adb locked. This is done 3421 * to avoid a race condition where we free the find, some other 3422 * thread tests to see if it should be destroyed, detects it should 3423 * be, destroys it, and then we try to lock it for our check, but the 3424 * lock is destroyed. 3425 */ 3426 LOCK(&adb->lock); 3427 if (free_adbfind(adb, &find)) { 3428 check_exit(adb); 3429 } 3430 UNLOCK(&adb->lock); 3431 } 3432 3433 void 3434 dns_adb_cancelfind(dns_adbfind_t *find) { 3435 isc_event_t *ev; 3436 isc_task_t *task; 3437 dns_adb_t *adb; 3438 int bucket; 3439 int unlock_bucket; 3440 3441 LOCK(&find->lock); 3442 3443 DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find); 3444 3445 adb = find->adb; 3446 REQUIRE(DNS_ADB_VALID(adb)); 3447 3448 REQUIRE(!FIND_EVENTFREED(find)); 3449 REQUIRE(FIND_WANTEVENT(find)); 3450 3451 bucket = find->name_bucket; 3452 if (bucket == DNS_ADB_INVALIDBUCKET) { 3453 goto cleanup; 3454 } 3455 3456 /* 3457 * We need to get the adbname's lock to unlink the find. 3458 */ 3459 unlock_bucket = bucket; 3460 violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]); 3461 bucket = find->name_bucket; 3462 if (bucket != DNS_ADB_INVALIDBUCKET) { 3463 ISC_LIST_UNLINK(find->adbname->finds, find, plink); 3464 find->adbname = NULL; 3465 find->name_bucket = DNS_ADB_INVALIDBUCKET; 3466 } 3467 UNLOCK(&adb->namelocks[unlock_bucket]); 3468 bucket = DNS_ADB_INVALIDBUCKET; 3469 POST(bucket); 3470 3471 cleanup: 3472 3473 if (!FIND_EVENTSENT(find)) { 3474 ev = &find->event; 3475 task = ev->ev_sender; 3476 ev->ev_sender = find; 3477 ev->ev_type = DNS_EVENT_ADBCANCELED; 3478 ev->ev_destroy = event_free; 3479 ev->ev_destroy_arg = find; 3480 find->result_v4 = ISC_R_CANCELED; 3481 find->result_v6 = ISC_R_CANCELED; 3482 3483 DP(DEF_LEVEL, "sending event %p to task %p for find %p", ev, 3484 task, find); 3485 3486 isc_task_sendanddetach(&task, (isc_event_t **)&ev); 3487 } 3488 3489 UNLOCK(&find->lock); 3490 } 3491 3492 void 3493 dns_adb_dump(dns_adb_t *adb, FILE *f) { 3494 unsigned int i; 3495 isc_stdtime_t now; 3496 3497 REQUIRE(DNS_ADB_VALID(adb)); 3498 REQUIRE(f != NULL); 3499 3500 /* 3501 * Lock the adb itself, lock all the name buckets, then lock all 3502 * the entry buckets. This should put the adb into a state where 3503 * nothing can change, so we can iterate through everything and 3504 * print at our leisure. 3505 */ 3506 3507 LOCK(&adb->lock); 3508 isc_stdtime_get(&now); 3509 3510 for (i = 0; i < adb->nnames; i++) { 3511 RUNTIME_CHECK(cleanup_names(adb, i, now) == false); 3512 } 3513 for (i = 0; i < adb->nentries; i++) { 3514 RUNTIME_CHECK(cleanup_entries(adb, i, now) == false); 3515 } 3516 3517 dump_adb(adb, f, false, now); 3518 UNLOCK(&adb->lock); 3519 } 3520 3521 static void 3522 dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) { 3523 if (value == INT_MAX) { 3524 return; 3525 } 3526 fprintf(f, " [%s TTL %d]", legend, (int)(value - now)); 3527 } 3528 3529 static void 3530 dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) { 3531 dns_adbname_t *name; 3532 dns_adbentry_t *entry; 3533 3534 fprintf(f, ";\n; Address database dump\n;\n"); 3535 fprintf(f, "; [edns success/4096 timeout/1432 timeout/1232 timeout/" 3536 "512 timeout]\n"); 3537 fprintf(f, "; [plain success/timeout]\n;\n"); 3538 if (debug) { 3539 LOCK(&adb->reflock); 3540 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n", 3541 adb, adb->erefcnt, adb->irefcnt, 3542 isc_mempool_getallocated(adb->nhmp)); 3543 UNLOCK(&adb->reflock); 3544 } 3545 3546 /* 3547 * In TSAN mode we need to lock the locks individually, as TSAN 3548 * can't handle more than 64 locks locked by one thread. 3549 * In regular mode we want a consistent dump so we need to 3550 * lock everything. 3551 */ 3552 #ifndef __SANITIZE_THREAD__ 3553 for (size_t i = 0; i < adb->nnames; i++) { 3554 LOCK(&adb->namelocks[i]); 3555 } 3556 for (size_t i = 0; i < adb->nentries; i++) { 3557 LOCK(&adb->entrylocks[i]); 3558 } 3559 #endif /* ifndef __SANITIZE_THREAD__ */ 3560 3561 /* 3562 * Dump the names 3563 */ 3564 for (size_t i = 0; i < adb->nnames; i++) { 3565 #ifdef __SANITIZE_THREAD__ 3566 LOCK(&adb->namelocks[i]); 3567 #endif /* ifdef __SANITIZE_THREAD__ */ 3568 name = ISC_LIST_HEAD(adb->names[i]); 3569 if (name == NULL) { 3570 #ifdef __SANITIZE_THREAD__ 3571 UNLOCK(&adb->namelocks[i]); 3572 #endif /* ifdef __SANITIZE_THREAD__ */ 3573 continue; 3574 } 3575 if (debug) { 3576 fprintf(f, "; bucket %zu\n", i); 3577 } 3578 for (; name != NULL; name = ISC_LIST_NEXT(name, plink)) { 3579 if (debug) { 3580 fprintf(f, "; name %p (flags %08x)\n", name, 3581 name->flags); 3582 } 3583 fprintf(f, "; "); 3584 print_dns_name(f, &name->name); 3585 if (dns_name_countlabels(&name->target) > 0) { 3586 fprintf(f, " alias "); 3587 print_dns_name(f, &name->target); 3588 } 3589 3590 dump_ttl(f, "v4", name->expire_v4, now); 3591 dump_ttl(f, "v6", name->expire_v6, now); 3592 dump_ttl(f, "target", name->expire_target, now); 3593 3594 fprintf(f, " [v4 %s] [v6 %s]", 3595 errnames[name->fetch_err], 3596 errnames[name->fetch6_err]); 3597 3598 fprintf(f, "\n"); 3599 3600 print_namehook_list(f, "v4", adb, &name->v4, debug, 3601 now); 3602 print_namehook_list(f, "v6", adb, &name->v6, debug, 3603 now); 3604 3605 if (debug) { 3606 print_fetch_list(f, name); 3607 print_find_list(f, name); 3608 } 3609 } 3610 #ifdef __SANITIZE_THREAD__ 3611 UNLOCK(&adb->namelocks[i]); 3612 #endif /* ifdef __SANITIZE_THREAD__ */ 3613 } 3614 3615 fprintf(f, ";\n; Unassociated entries\n;\n"); 3616 3617 for (size_t i = 0; i < adb->nentries; i++) { 3618 #ifdef __SANITIZE_THREAD__ 3619 LOCK(&adb->entrylocks[i]); 3620 #endif /* ifdef __SANITIZE_THREAD__ */ 3621 entry = ISC_LIST_HEAD(adb->entries[i]); 3622 while (entry != NULL) { 3623 if (entry->nh == 0) { 3624 dump_entry(f, adb, entry, debug, now); 3625 } 3626 entry = ISC_LIST_NEXT(entry, plink); 3627 } 3628 #ifdef __SANITIZE_THREAD__ 3629 UNLOCK(&adb->entrylocks[i]); 3630 #endif /* ifdef __SANITIZE_THREAD__ */ 3631 } 3632 3633 #ifndef __SANITIZE_THREAD__ 3634 /* 3635 * Unlock everything 3636 */ 3637 for (ssize_t i = adb->nentries - 1; i >= 0; i--) { 3638 UNLOCK(&adb->entrylocks[i]); 3639 } 3640 for (ssize_t i = adb->nnames - 1; i >= 0; i--) { 3641 UNLOCK(&adb->namelocks[i]); 3642 } 3643 #endif /* ifndef __SANITIZE_THREAD__ */ 3644 } 3645 3646 static void 3647 dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry, bool debug, 3648 isc_stdtime_t now) { 3649 char addrbuf[ISC_NETADDR_FORMATSIZE]; 3650 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3651 isc_netaddr_t netaddr; 3652 dns_adblameinfo_t *li; 3653 3654 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr); 3655 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); 3656 3657 if (debug) { 3658 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt); 3659 } 3660 3661 fprintf(f, 3662 ";\t%s [srtt %u] [flags %08x] [edns %u/%u/%u/%u/%u] " 3663 "[plain %u/%u]", 3664 addrbuf, entry->srtt, entry->flags, entry->edns, entry->to4096, 3665 entry->to1432, entry->to1232, entry->to512, entry->plain, 3666 entry->plainto); 3667 if (entry->udpsize != 0U) { 3668 fprintf(f, " [udpsize %u]", entry->udpsize); 3669 } 3670 if (entry->cookie != NULL) { 3671 unsigned int i; 3672 fprintf(f, " [cookie="); 3673 for (i = 0; i < entry->cookielen; i++) { 3674 fprintf(f, "%02x", entry->cookie[i]); 3675 } 3676 fprintf(f, "]"); 3677 } 3678 if (entry->expires != 0) { 3679 fprintf(f, " [ttl %d]", (int)(entry->expires - now)); 3680 } 3681 3682 if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) { 3683 uint_fast32_t quota = atomic_load_relaxed(&entry->quota); 3684 fprintf(f, " [atr %0.2f] [quota %" PRIuFAST32 "]", entry->atr, 3685 quota); 3686 } 3687 3688 fprintf(f, "\n"); 3689 for (li = ISC_LIST_HEAD(entry->lameinfo); li != NULL; 3690 li = ISC_LIST_NEXT(li, plink)) 3691 { 3692 fprintf(f, ";\t\t"); 3693 print_dns_name(f, &li->qname); 3694 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf)); 3695 fprintf(f, " %s [lame TTL %d]\n", typebuf, 3696 (int)(li->lame_timer - now)); 3697 } 3698 } 3699 3700 void 3701 dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) { 3702 char tmp[512]; 3703 const char *tmpp; 3704 dns_adbaddrinfo_t *ai; 3705 isc_sockaddr_t *sa; 3706 3707 /* 3708 * Not used currently, in the API Just In Case we 3709 * want to dump out the name and/or entries too. 3710 */ 3711 3712 LOCK(&find->lock); 3713 3714 fprintf(f, ";Find %p\n", find); 3715 fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n", 3716 find->query_pending, find->partial_result, find->options, 3717 find->flags); 3718 fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n", 3719 find->name_bucket, find->adbname, find->event.ev_sender); 3720 3721 ai = ISC_LIST_HEAD(find->list); 3722 if (ai != NULL) { 3723 fprintf(f, "\tAddresses:\n"); 3724 } 3725 while (ai != NULL) { 3726 sa = &ai->sockaddr; 3727 switch (sa->type.sa.sa_family) { 3728 case AF_INET: 3729 tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr, tmp, 3730 sizeof(tmp)); 3731 break; 3732 case AF_INET6: 3733 tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr, 3734 tmp, sizeof(tmp)); 3735 break; 3736 default: 3737 tmpp = "UnkFamily"; 3738 } 3739 3740 if (tmpp == NULL) { 3741 tmpp = "BadAddress"; 3742 } 3743 3744 fprintf(f, 3745 "\t\tentry %p, flags %08x" 3746 " srtt %u addr %s\n", 3747 ai->entry, ai->flags, ai->srtt, tmpp); 3748 3749 ai = ISC_LIST_NEXT(ai, publink); 3750 } 3751 3752 UNLOCK(&find->lock); 3753 } 3754 3755 static void 3756 print_dns_name(FILE *f, const dns_name_t *name) { 3757 char buf[DNS_NAME_FORMATSIZE]; 3758 3759 INSIST(f != NULL); 3760 3761 dns_name_format(name, buf, sizeof(buf)); 3762 fprintf(f, "%s", buf); 3763 } 3764 3765 static void 3766 print_namehook_list(FILE *f, const char *legend, dns_adb_t *adb, 3767 dns_adbnamehooklist_t *list, bool debug, 3768 isc_stdtime_t now) { 3769 dns_adbnamehook_t *nh; 3770 3771 for (nh = ISC_LIST_HEAD(*list); nh != NULL; 3772 nh = ISC_LIST_NEXT(nh, plink)) { 3773 if (debug) { 3774 fprintf(f, ";\tHook(%s) %p\n", legend, nh); 3775 } 3776 dump_entry(f, adb, nh->entry, debug, now); 3777 } 3778 } 3779 3780 static inline void 3781 print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) { 3782 fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n", type, ft, ft->fetch); 3783 } 3784 3785 static void 3786 print_fetch_list(FILE *f, dns_adbname_t *n) { 3787 if (NAME_FETCH_A(n)) { 3788 print_fetch(f, n->fetch_a, "A"); 3789 } 3790 if (NAME_FETCH_AAAA(n)) { 3791 print_fetch(f, n->fetch_aaaa, "AAAA"); 3792 } 3793 } 3794 3795 static void 3796 print_find_list(FILE *f, dns_adbname_t *name) { 3797 dns_adbfind_t *find; 3798 3799 find = ISC_LIST_HEAD(name->finds); 3800 while (find != NULL) { 3801 dns_adb_dumpfind(find, f); 3802 find = ISC_LIST_NEXT(find, plink); 3803 } 3804 } 3805 3806 static isc_result_t 3807 dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) { 3808 isc_result_t result; 3809 dns_rdataset_t rdataset; 3810 dns_adb_t *adb; 3811 dns_fixedname_t foundname; 3812 dns_name_t *fname; 3813 3814 INSIST(DNS_ADBNAME_VALID(adbname)); 3815 adb = adbname->adb; 3816 INSIST(DNS_ADB_VALID(adb)); 3817 INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa); 3818 3819 fname = dns_fixedname_initname(&foundname); 3820 dns_rdataset_init(&rdataset); 3821 3822 if (rdtype == dns_rdatatype_a) { 3823 adbname->fetch_err = FIND_ERR_UNEXPECTED; 3824 } else { 3825 adbname->fetch6_err = FIND_ERR_UNEXPECTED; 3826 } 3827 3828 /* 3829 * We need to specify whether to search static-stub zones (if 3830 * configured) depending on whether this is a "start at zone" lookup, 3831 * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which 3832 * case NAME_STARTATZONE is set) we need to stop the search at any 3833 * matching static-stub zone without looking into the cache to honor 3834 * the configuration on which server we should send queries to. 3835 */ 3836 result = dns_view_find(adb->view, &adbname->name, rdtype, now, 3837 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0, 3838 NAME_HINTOK(adbname), 3839 ((adbname->flags & NAME_STARTATZONE) != 0), NULL, 3840 NULL, fname, &rdataset, NULL); 3841 3842 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 3843 switch (result) { 3844 case DNS_R_GLUE: 3845 case DNS_R_HINT: 3846 case ISC_R_SUCCESS: 3847 /* 3848 * Found in the database. Even if we can't copy out 3849 * any information, return success, or else a fetch 3850 * will be made, which will only make things worse. 3851 */ 3852 if (rdtype == dns_rdatatype_a) { 3853 adbname->fetch_err = FIND_ERR_SUCCESS; 3854 } else { 3855 adbname->fetch6_err = FIND_ERR_SUCCESS; 3856 } 3857 result = import_rdataset(adbname, &rdataset, now); 3858 break; 3859 case DNS_R_NXDOMAIN: 3860 case DNS_R_NXRRSET: 3861 /* 3862 * We're authoritative and the data doesn't exist. 3863 * Make up a negative cache entry so we don't ask again 3864 * for a while. 3865 * 3866 * XXXRTH What time should we use? I'm putting in 30 seconds 3867 * for now. 3868 */ 3869 if (rdtype == dns_rdatatype_a) { 3870 adbname->expire_v4 = now + 30; 3871 DP(NCACHE_LEVEL, 3872 "adb name %p: Caching auth negative entry for A", 3873 adbname); 3874 if (result == DNS_R_NXDOMAIN) { 3875 adbname->fetch_err = FIND_ERR_NXDOMAIN; 3876 } else { 3877 adbname->fetch_err = FIND_ERR_NXRRSET; 3878 } 3879 } else { 3880 DP(NCACHE_LEVEL, 3881 "adb name %p: Caching auth negative entry for AAAA", 3882 adbname); 3883 adbname->expire_v6 = now + 30; 3884 if (result == DNS_R_NXDOMAIN) { 3885 adbname->fetch6_err = FIND_ERR_NXDOMAIN; 3886 } else { 3887 adbname->fetch6_err = FIND_ERR_NXRRSET; 3888 } 3889 } 3890 break; 3891 case DNS_R_NCACHENXDOMAIN: 3892 case DNS_R_NCACHENXRRSET: 3893 /* 3894 * We found a negative cache entry. Pull the TTL from it 3895 * so we won't ask again for a while. 3896 */ 3897 rdataset.ttl = ttlclamp(rdataset.ttl); 3898 if (rdtype == dns_rdatatype_a) { 3899 adbname->expire_v4 = rdataset.ttl + now; 3900 if (result == DNS_R_NCACHENXDOMAIN) { 3901 adbname->fetch_err = FIND_ERR_NXDOMAIN; 3902 } else { 3903 adbname->fetch_err = FIND_ERR_NXRRSET; 3904 } 3905 DP(NCACHE_LEVEL, 3906 "adb name %p: Caching negative entry for A (ttl %u)", 3907 adbname, rdataset.ttl); 3908 } else { 3909 DP(NCACHE_LEVEL, 3910 "adb name %p: Caching negative entry for AAAA (ttl " 3911 "%u)", 3912 adbname, rdataset.ttl); 3913 adbname->expire_v6 = rdataset.ttl + now; 3914 if (result == DNS_R_NCACHENXDOMAIN) { 3915 adbname->fetch6_err = FIND_ERR_NXDOMAIN; 3916 } else { 3917 adbname->fetch6_err = FIND_ERR_NXRRSET; 3918 } 3919 } 3920 break; 3921 case DNS_R_CNAME: 3922 case DNS_R_DNAME: 3923 /* 3924 * Clear the hint and glue flags, so this will match 3925 * more often. 3926 */ 3927 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK); 3928 3929 rdataset.ttl = ttlclamp(rdataset.ttl); 3930 clean_target(adb, &adbname->target); 3931 adbname->expire_target = INT_MAX; 3932 result = set_target(adb, &adbname->name, fname, &rdataset, 3933 &adbname->target); 3934 if (result == ISC_R_SUCCESS) { 3935 result = DNS_R_ALIAS; 3936 DP(NCACHE_LEVEL, "adb name %p: caching alias target", 3937 adbname); 3938 adbname->expire_target = rdataset.ttl + now; 3939 } 3940 if (rdtype == dns_rdatatype_a) { 3941 adbname->fetch_err = FIND_ERR_SUCCESS; 3942 } else { 3943 adbname->fetch6_err = FIND_ERR_SUCCESS; 3944 } 3945 break; 3946 } 3947 3948 if (dns_rdataset_isassociated(&rdataset)) { 3949 dns_rdataset_disassociate(&rdataset); 3950 } 3951 3952 return (result); 3953 } 3954 3955 static void 3956 fetch_callback(isc_task_t *task, isc_event_t *ev) { 3957 dns_fetchevent_t *dev; 3958 dns_adbname_t *name; 3959 dns_adb_t *adb; 3960 dns_adbfetch_t *fetch; 3961 int bucket; 3962 isc_eventtype_t ev_status; 3963 isc_stdtime_t now; 3964 isc_result_t result; 3965 unsigned int address_type; 3966 bool want_check_exit = false; 3967 3968 UNUSED(task); 3969 3970 INSIST(ev->ev_type == DNS_EVENT_FETCHDONE); 3971 dev = (dns_fetchevent_t *)ev; 3972 name = ev->ev_arg; 3973 INSIST(DNS_ADBNAME_VALID(name)); 3974 adb = name->adb; 3975 INSIST(DNS_ADB_VALID(adb)); 3976 3977 bucket = name->lock_bucket; 3978 LOCK(&adb->namelocks[bucket]); 3979 3980 INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name)); 3981 address_type = 0; 3982 if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) { 3983 address_type = DNS_ADBFIND_INET; 3984 fetch = name->fetch_a; 3985 name->fetch_a = NULL; 3986 } else if (NAME_FETCH_AAAA(name) && 3987 (name->fetch_aaaa->fetch == dev->fetch)) { 3988 address_type = DNS_ADBFIND_INET6; 3989 fetch = name->fetch_aaaa; 3990 name->fetch_aaaa = NULL; 3991 } else { 3992 fetch = NULL; 3993 } 3994 3995 INSIST(address_type != 0 && fetch != NULL); 3996 3997 dns_resolver_destroyfetch(&fetch->fetch); 3998 dev->fetch = NULL; 3999 4000 ev_status = DNS_EVENT_ADBNOMOREADDRESSES; 4001 4002 /* 4003 * Cleanup things we don't care about. 4004 */ 4005 if (dev->node != NULL) { 4006 dns_db_detachnode(dev->db, &dev->node); 4007 } 4008 if (dev->db != NULL) { 4009 dns_db_detach(&dev->db); 4010 } 4011 4012 /* 4013 * If this name is marked as dead, clean up, throwing away 4014 * potentially good data. 4015 */ 4016 if (NAME_DEAD(name)) { 4017 free_adbfetch(adb, &fetch); 4018 isc_event_free(&ev); 4019 4020 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED); 4021 4022 UNLOCK(&adb->namelocks[bucket]); 4023 4024 if (want_check_exit) { 4025 LOCK(&adb->lock); 4026 check_exit(adb); 4027 UNLOCK(&adb->lock); 4028 } 4029 4030 return; 4031 } 4032 4033 isc_stdtime_get(&now); 4034 4035 /* 4036 * If we got a negative cache response, remember it. 4037 */ 4038 if (NCACHE_RESULT(dev->result)) { 4039 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl); 4040 if (address_type == DNS_ADBFIND_INET) { 4041 DP(NCACHE_LEVEL, 4042 "adb fetch name %p: " 4043 "caching negative entry for A (ttl %u)", 4044 name, dev->rdataset->ttl); 4045 name->expire_v4 = ISC_MIN(name->expire_v4, 4046 dev->rdataset->ttl + now); 4047 if (dev->result == DNS_R_NCACHENXDOMAIN) { 4048 name->fetch_err = FIND_ERR_NXDOMAIN; 4049 } else { 4050 name->fetch_err = FIND_ERR_NXRRSET; 4051 } 4052 inc_stats(adb, dns_resstatscounter_gluefetchv4fail); 4053 } else { 4054 DP(NCACHE_LEVEL, 4055 "adb fetch name %p: " 4056 "caching negative entry for AAAA (ttl %u)", 4057 name, dev->rdataset->ttl); 4058 name->expire_v6 = ISC_MIN(name->expire_v6, 4059 dev->rdataset->ttl + now); 4060 if (dev->result == DNS_R_NCACHENXDOMAIN) { 4061 name->fetch6_err = FIND_ERR_NXDOMAIN; 4062 } else { 4063 name->fetch6_err = FIND_ERR_NXRRSET; 4064 } 4065 inc_stats(adb, dns_resstatscounter_gluefetchv6fail); 4066 } 4067 goto out; 4068 } 4069 4070 /* 4071 * Handle CNAME/DNAME. 4072 */ 4073 if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) { 4074 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl); 4075 clean_target(adb, &name->target); 4076 name->expire_target = INT_MAX; 4077 result = set_target(adb, &name->name, 4078 dns_fixedname_name(&dev->foundname), 4079 dev->rdataset, &name->target); 4080 if (result == ISC_R_SUCCESS) { 4081 DP(NCACHE_LEVEL, 4082 "adb fetch name %p: caching alias target", name); 4083 name->expire_target = dev->rdataset->ttl + now; 4084 } 4085 goto check_result; 4086 } 4087 4088 /* 4089 * Did we get back junk? If so, and there are no more fetches 4090 * sitting out there, tell all the finds about it. 4091 */ 4092 if (dev->result != ISC_R_SUCCESS) { 4093 char buf[DNS_NAME_FORMATSIZE]; 4094 4095 dns_name_format(&name->name, buf, sizeof(buf)); 4096 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", buf, 4097 address_type == DNS_ADBFIND_INET ? "A" : "AAAA", 4098 dns_result_totext(dev->result)); 4099 /* 4100 * Don't record a failure unless this is the initial 4101 * fetch of a chain. 4102 */ 4103 if (fetch->depth > 1) { 4104 goto out; 4105 } 4106 /* XXXMLG Don't pound on bad servers. */ 4107 if (address_type == DNS_ADBFIND_INET) { 4108 name->expire_v4 = ISC_MIN(name->expire_v4, now + 10); 4109 name->fetch_err = FIND_ERR_FAILURE; 4110 inc_stats(adb, dns_resstatscounter_gluefetchv4fail); 4111 } else { 4112 name->expire_v6 = ISC_MIN(name->expire_v6, now + 10); 4113 name->fetch6_err = FIND_ERR_FAILURE; 4114 inc_stats(adb, dns_resstatscounter_gluefetchv6fail); 4115 } 4116 goto out; 4117 } 4118 4119 /* 4120 * We got something potentially useful. 4121 */ 4122 result = import_rdataset(name, &fetch->rdataset, now); 4123 4124 check_result: 4125 if (result == ISC_R_SUCCESS) { 4126 ev_status = DNS_EVENT_ADBMOREADDRESSES; 4127 if (address_type == DNS_ADBFIND_INET) { 4128 name->fetch_err = FIND_ERR_SUCCESS; 4129 } else { 4130 name->fetch6_err = FIND_ERR_SUCCESS; 4131 } 4132 } 4133 4134 out: 4135 free_adbfetch(adb, &fetch); 4136 isc_event_free(&ev); 4137 4138 clean_finds_at_name(name, ev_status, address_type); 4139 4140 UNLOCK(&adb->namelocks[bucket]); 4141 } 4142 4143 static isc_result_t 4144 fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth, 4145 isc_counter_t *qc, dns_rdatatype_t type) { 4146 isc_result_t result; 4147 dns_adbfetch_t *fetch = NULL; 4148 dns_adb_t *adb; 4149 dns_fixedname_t fixed; 4150 dns_name_t *name; 4151 dns_rdataset_t rdataset; 4152 dns_rdataset_t *nameservers; 4153 unsigned int options; 4154 4155 INSIST(DNS_ADBNAME_VALID(adbname)); 4156 adb = adbname->adb; 4157 INSIST(DNS_ADB_VALID(adb)); 4158 4159 INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) || 4160 (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname))); 4161 4162 adbname->fetch_err = FIND_ERR_NOTFOUND; 4163 4164 name = NULL; 4165 nameservers = NULL; 4166 dns_rdataset_init(&rdataset); 4167 4168 options = DNS_FETCHOPT_NOVALIDATE; 4169 if (start_at_zone) { 4170 DP(ENTER_LEVEL, "fetch_name: starting at zone for name %p", 4171 adbname); 4172 name = dns_fixedname_initname(&fixed); 4173 result = dns_view_findzonecut(adb->view, &adbname->name, name, 4174 NULL, 0, 0, true, false, 4175 &rdataset, NULL); 4176 if (result != ISC_R_SUCCESS && result != DNS_R_HINT) { 4177 goto cleanup; 4178 } 4179 nameservers = &rdataset; 4180 options |= DNS_FETCHOPT_UNSHARED; 4181 } 4182 4183 fetch = new_adbfetch(adb); 4184 if (fetch == NULL) { 4185 result = ISC_R_NOMEMORY; 4186 goto cleanup; 4187 } 4188 fetch->depth = depth; 4189 4190 /* 4191 * We're not minimizing this query, as nothing user-related should 4192 * be leaked here. 4193 * However, if we'd ever want to change it we'd have to modify 4194 * createfetch to find deepest cached name when we're providing 4195 * domain and nameservers. 4196 */ 4197 result = dns_resolver_createfetch( 4198 adb->view->resolver, &adbname->name, type, name, nameservers, 4199 NULL, NULL, 0, options, depth, qc, adb->task, fetch_callback, 4200 adbname, &fetch->rdataset, NULL, &fetch->fetch); 4201 if (result != ISC_R_SUCCESS) { 4202 DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s", 4203 isc_result_totext(result)); 4204 goto cleanup; 4205 } 4206 4207 if (type == dns_rdatatype_a) { 4208 adbname->fetch_a = fetch; 4209 inc_stats(adb, dns_resstatscounter_gluefetchv4); 4210 } else { 4211 adbname->fetch_aaaa = fetch; 4212 inc_stats(adb, dns_resstatscounter_gluefetchv6); 4213 } 4214 fetch = NULL; /* Keep us from cleaning this up below. */ 4215 4216 cleanup: 4217 if (fetch != NULL) { 4218 free_adbfetch(adb, &fetch); 4219 } 4220 if (dns_rdataset_isassociated(&rdataset)) { 4221 dns_rdataset_disassociate(&rdataset); 4222 } 4223 4224 return (result); 4225 } 4226 4227 /* 4228 * XXXMLG Needs to take a find argument and an address info, no zone or adb, 4229 * since these can be extracted from the find itself. 4230 */ 4231 isc_result_t 4232 dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, 4233 const dns_name_t *qname, dns_rdatatype_t qtype, 4234 isc_stdtime_t expire_time) { 4235 dns_adblameinfo_t *li; 4236 int bucket; 4237 isc_result_t result = ISC_R_SUCCESS; 4238 4239 REQUIRE(DNS_ADB_VALID(adb)); 4240 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4241 REQUIRE(qname != NULL); 4242 4243 bucket = addr->entry->lock_bucket; 4244 LOCK(&adb->entrylocks[bucket]); 4245 li = ISC_LIST_HEAD(addr->entry->lameinfo); 4246 while (li != NULL && 4247 (li->qtype != qtype || !dns_name_equal(qname, &li->qname))) { 4248 li = ISC_LIST_NEXT(li, plink); 4249 } 4250 if (li != NULL) { 4251 if (expire_time > li->lame_timer) { 4252 li->lame_timer = expire_time; 4253 } 4254 goto unlock; 4255 } 4256 li = new_adblameinfo(adb, qname, qtype); 4257 if (li == NULL) { 4258 result = ISC_R_NOMEMORY; 4259 goto unlock; 4260 } 4261 4262 li->lame_timer = expire_time; 4263 4264 ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink); 4265 unlock: 4266 UNLOCK(&adb->entrylocks[bucket]); 4267 4268 return (result); 4269 } 4270 4271 void 4272 dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int rtt, 4273 unsigned int factor) { 4274 int bucket; 4275 isc_stdtime_t now = 0; 4276 4277 REQUIRE(DNS_ADB_VALID(adb)); 4278 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4279 REQUIRE(factor <= 10); 4280 4281 bucket = addr->entry->lock_bucket; 4282 LOCK(&adb->entrylocks[bucket]); 4283 4284 if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE) { 4285 isc_stdtime_get(&now); 4286 } 4287 adjustsrtt(addr, rtt, factor, now); 4288 4289 UNLOCK(&adb->entrylocks[bucket]); 4290 } 4291 4292 void 4293 dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) { 4294 int bucket; 4295 4296 REQUIRE(DNS_ADB_VALID(adb)); 4297 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4298 4299 bucket = addr->entry->lock_bucket; 4300 LOCK(&adb->entrylocks[bucket]); 4301 4302 adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now); 4303 4304 UNLOCK(&adb->entrylocks[bucket]); 4305 } 4306 4307 static void 4308 adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor, 4309 isc_stdtime_t now) { 4310 uint64_t new_srtt; 4311 4312 if (factor == DNS_ADB_RTTADJAGE) { 4313 if (addr->entry->lastage != now) { 4314 new_srtt = addr->entry->srtt; 4315 new_srtt <<= 9; 4316 new_srtt -= addr->entry->srtt; 4317 new_srtt >>= 9; 4318 addr->entry->lastage = now; 4319 } else { 4320 new_srtt = addr->entry->srtt; 4321 } 4322 } else { 4323 new_srtt = ((uint64_t)addr->entry->srtt / 10 * factor) + 4324 ((uint64_t)rtt / 10 * (10 - factor)); 4325 } 4326 4327 addr->entry->srtt = (unsigned int)new_srtt; 4328 addr->srtt = (unsigned int)new_srtt; 4329 4330 if (addr->entry->expires == 0) { 4331 addr->entry->expires = now + ADB_ENTRY_WINDOW; 4332 } 4333 } 4334 4335 void 4336 dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits, 4337 unsigned int mask) { 4338 int bucket; 4339 isc_stdtime_t now; 4340 4341 REQUIRE(DNS_ADB_VALID(adb)); 4342 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4343 4344 REQUIRE((bits & ENTRY_IS_DEAD) == 0); 4345 REQUIRE((mask & ENTRY_IS_DEAD) == 0); 4346 4347 bucket = addr->entry->lock_bucket; 4348 LOCK(&adb->entrylocks[bucket]); 4349 4350 addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask); 4351 if (addr->entry->expires == 0) { 4352 isc_stdtime_get(&now); 4353 addr->entry->expires = now + ADB_ENTRY_WINDOW; 4354 } 4355 4356 /* 4357 * Note that we do not update the other bits in addr->flags with 4358 * the most recent values from addr->entry->flags. 4359 */ 4360 addr->flags = (addr->flags & ~mask) | (bits & mask); 4361 4362 UNLOCK(&adb->entrylocks[bucket]); 4363 } 4364 4365 /* 4366 * The polynomial backoff curve (10000 / ((10 + n) / 10)^(3/2)) <0..99> drops 4367 * fairly aggressively at first, then slows down and tails off at around 2-3%. 4368 * 4369 * These will be used to make quota adjustments. 4370 */ 4371 static int quota_adj[] = { 4372 10000, 8668, 7607, 6747, 6037, 5443, 4941, 4512, 4141, 3818, 3536, 4373 3286, 3065, 2867, 2690, 2530, 2385, 2254, 2134, 2025, 1925, 1832, 4374 1747, 1668, 1595, 1527, 1464, 1405, 1350, 1298, 1250, 1205, 1162, 4375 1121, 1083, 1048, 1014, 981, 922, 894, 868, 843, 820, 797, 4376 775, 755, 735, 716, 698, 680, 664, 648, 632, 618, 603, 4377 590, 577, 564, 552, 540, 529, 518, 507, 497, 487, 477, 4378 468, 459, 450, 442, 434, 426, 418, 411, 404, 397, 390, 4379 383, 377, 370, 364, 358, 353, 347, 342, 336, 331, 326, 4380 321, 316, 312, 307, 303, 298, 294, 290, 286, 282, 278 4381 }; 4382 4383 #define QUOTA_ADJ_SIZE (sizeof(quota_adj) / sizeof(quota_adj[0])) 4384 4385 /* 4386 * Caller must hold adbentry lock 4387 */ 4388 static void 4389 maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bool timeout) { 4390 double tr; 4391 4392 UNUSED(adb); 4393 4394 if (adb->quota == 0 || adb->atr_freq == 0) { 4395 return; 4396 } 4397 4398 if (timeout) { 4399 addr->entry->timeouts++; 4400 } 4401 4402 if (addr->entry->completed++ <= adb->atr_freq) { 4403 return; 4404 } 4405 4406 /* 4407 * Calculate an exponential rolling average of the timeout ratio 4408 * 4409 * XXX: Integer arithmetic might be better than floating point 4410 */ 4411 tr = (double)addr->entry->timeouts / addr->entry->completed; 4412 addr->entry->timeouts = addr->entry->completed = 0; 4413 INSIST(addr->entry->atr >= 0.0); 4414 INSIST(addr->entry->atr <= 1.0); 4415 INSIST(adb->atr_discount >= 0.0); 4416 INSIST(adb->atr_discount <= 1.0); 4417 addr->entry->atr *= 1.0 - adb->atr_discount; 4418 addr->entry->atr += tr * adb->atr_discount; 4419 addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0); 4420 4421 if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) { 4422 uint_fast32_t new_quota = 4423 adb->quota * quota_adj[--addr->entry->mode] / 10000; 4424 atomic_store_release(&addr->entry->quota, 4425 ISC_MIN(1, new_quota)); 4426 log_quota(addr->entry, 4427 "atr %0.2f, quota increased to %" PRIuFAST32, 4428 addr->entry->atr, new_quota); 4429 } else if (addr->entry->atr > adb->atr_high && 4430 addr->entry->mode < (QUOTA_ADJ_SIZE - 1)) 4431 { 4432 uint_fast32_t new_quota = 4433 adb->quota * quota_adj[++addr->entry->mode] / 10000; 4434 atomic_store_release(&addr->entry->quota, 4435 ISC_MIN(1, new_quota)); 4436 log_quota(addr->entry, 4437 "atr %0.2f, quota decreased to %" PRIuFAST32, 4438 addr->entry->atr, new_quota); 4439 } 4440 } 4441 4442 #define EDNSTOS 3U 4443 bool 4444 dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4445 int bucket; 4446 bool noedns = false; 4447 4448 REQUIRE(DNS_ADB_VALID(adb)); 4449 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4450 4451 bucket = addr->entry->lock_bucket; 4452 LOCK(&adb->entrylocks[bucket]); 4453 4454 if (addr->entry->edns == 0U && 4455 (addr->entry->plain > EDNSTOS || addr->entry->to4096 > EDNSTOS)) 4456 { 4457 if (((addr->entry->plain + addr->entry->to4096) & 0x3f) != 0) { 4458 noedns = true; 4459 } else { 4460 /* 4461 * Increment plain so we don't get stuck. 4462 */ 4463 addr->entry->plain++; 4464 if (addr->entry->plain == 0xff) { 4465 addr->entry->edns >>= 1; 4466 addr->entry->to4096 >>= 1; 4467 addr->entry->to1432 >>= 1; 4468 addr->entry->to1232 >>= 1; 4469 addr->entry->to512 >>= 1; 4470 addr->entry->plain >>= 1; 4471 addr->entry->plainto >>= 1; 4472 } 4473 } 4474 } 4475 UNLOCK(&adb->entrylocks[bucket]); 4476 return (noedns); 4477 } 4478 4479 void 4480 dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4481 int bucket; 4482 4483 REQUIRE(DNS_ADB_VALID(adb)); 4484 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4485 4486 bucket = addr->entry->lock_bucket; 4487 LOCK(&adb->entrylocks[bucket]); 4488 4489 maybe_adjust_quota(adb, addr, false); 4490 4491 addr->entry->plain++; 4492 if (addr->entry->plain == 0xff) { 4493 addr->entry->edns >>= 1; 4494 addr->entry->to4096 >>= 1; 4495 addr->entry->to1432 >>= 1; 4496 addr->entry->to1232 >>= 1; 4497 addr->entry->to512 >>= 1; 4498 addr->entry->plain >>= 1; 4499 addr->entry->plainto >>= 1; 4500 } 4501 UNLOCK(&adb->entrylocks[bucket]); 4502 } 4503 4504 void 4505 dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4506 int bucket; 4507 4508 REQUIRE(DNS_ADB_VALID(adb)); 4509 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4510 4511 bucket = addr->entry->lock_bucket; 4512 LOCK(&adb->entrylocks[bucket]); 4513 4514 maybe_adjust_quota(adb, addr, true); 4515 4516 /* 4517 * If we have not had a successful query then clear all 4518 * edns timeout information. 4519 */ 4520 if (addr->entry->edns == 0 && addr->entry->plain == 0) { 4521 addr->entry->to512 = 0; 4522 addr->entry->to1232 = 0; 4523 addr->entry->to1432 = 0; 4524 addr->entry->to4096 = 0; 4525 } else { 4526 addr->entry->to512 >>= 1; 4527 addr->entry->to1232 >>= 1; 4528 addr->entry->to1432 >>= 1; 4529 addr->entry->to4096 >>= 1; 4530 } 4531 4532 addr->entry->plainto++; 4533 if (addr->entry->plainto == 0xff) { 4534 addr->entry->edns >>= 1; 4535 addr->entry->plain >>= 1; 4536 addr->entry->plainto >>= 1; 4537 } 4538 UNLOCK(&adb->entrylocks[bucket]); 4539 } 4540 4541 void 4542 dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) { 4543 int bucket; 4544 4545 REQUIRE(DNS_ADB_VALID(adb)); 4546 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4547 4548 bucket = addr->entry->lock_bucket; 4549 LOCK(&adb->entrylocks[bucket]); 4550 4551 maybe_adjust_quota(adb, addr, true); 4552 4553 if (size <= 512U) { 4554 if (addr->entry->to512 <= EDNSTOS) { 4555 addr->entry->to512++; 4556 addr->entry->to1232++; 4557 addr->entry->to1432++; 4558 addr->entry->to4096++; 4559 } 4560 } else if (size <= 1232U) { 4561 if (addr->entry->to1232 <= EDNSTOS) { 4562 addr->entry->to1232++; 4563 addr->entry->to1432++; 4564 addr->entry->to4096++; 4565 } 4566 } else if (size <= 1432U) { 4567 if (addr->entry->to1432 <= EDNSTOS) { 4568 addr->entry->to1432++; 4569 addr->entry->to4096++; 4570 } 4571 } else { 4572 if (addr->entry->to4096 <= EDNSTOS) { 4573 addr->entry->to4096++; 4574 } 4575 } 4576 4577 if (addr->entry->to4096 == 0xff) { 4578 addr->entry->edns >>= 1; 4579 addr->entry->to4096 >>= 1; 4580 addr->entry->to1432 >>= 1; 4581 addr->entry->to1232 >>= 1; 4582 addr->entry->to512 >>= 1; 4583 addr->entry->plain >>= 1; 4584 addr->entry->plainto >>= 1; 4585 } 4586 UNLOCK(&adb->entrylocks[bucket]); 4587 } 4588 4589 void 4590 dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) { 4591 int bucket; 4592 4593 REQUIRE(DNS_ADB_VALID(adb)); 4594 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4595 4596 bucket = addr->entry->lock_bucket; 4597 LOCK(&adb->entrylocks[bucket]); 4598 if (size < 512U) { 4599 size = 512U; 4600 } 4601 if (size > addr->entry->udpsize) { 4602 addr->entry->udpsize = size; 4603 } 4604 4605 maybe_adjust_quota(adb, addr, false); 4606 4607 addr->entry->edns++; 4608 if (addr->entry->edns == 0xff) { 4609 addr->entry->edns >>= 1; 4610 addr->entry->to4096 >>= 1; 4611 addr->entry->to1432 >>= 1; 4612 addr->entry->to1232 >>= 1; 4613 addr->entry->to512 >>= 1; 4614 addr->entry->plain >>= 1; 4615 addr->entry->plainto >>= 1; 4616 } 4617 UNLOCK(&adb->entrylocks[bucket]); 4618 } 4619 4620 unsigned int 4621 dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4622 int bucket; 4623 unsigned int size; 4624 4625 REQUIRE(DNS_ADB_VALID(adb)); 4626 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4627 4628 bucket = addr->entry->lock_bucket; 4629 LOCK(&adb->entrylocks[bucket]); 4630 size = addr->entry->udpsize; 4631 UNLOCK(&adb->entrylocks[bucket]); 4632 4633 return (size); 4634 } 4635 4636 unsigned int 4637 dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, int lookups) { 4638 int bucket; 4639 unsigned int size; 4640 4641 REQUIRE(DNS_ADB_VALID(adb)); 4642 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4643 4644 bucket = addr->entry->lock_bucket; 4645 LOCK(&adb->entrylocks[bucket]); 4646 if (addr->entry->to1232 > EDNSTOS || lookups >= 2) { 4647 size = 512; 4648 } else if (addr->entry->to1432 > EDNSTOS || lookups >= 1) { 4649 size = 1232; 4650 } else if (addr->entry->to4096 > EDNSTOS) { 4651 size = 1432; 4652 } else { 4653 size = 4096; 4654 } 4655 /* 4656 * Don't shrink probe size below what we have seen due to multiple 4657 * lookups. 4658 */ 4659 if (lookups > 0 && size < addr->entry->udpsize && 4660 addr->entry->udpsize < 4096) { 4661 size = addr->entry->udpsize; 4662 } 4663 UNLOCK(&adb->entrylocks[bucket]); 4664 4665 return (size); 4666 } 4667 4668 void 4669 dns_adb_setcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr, 4670 const unsigned char *cookie, size_t len) { 4671 int bucket; 4672 4673 REQUIRE(DNS_ADB_VALID(adb)); 4674 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4675 4676 bucket = addr->entry->lock_bucket; 4677 LOCK(&adb->entrylocks[bucket]); 4678 4679 if (addr->entry->cookie != NULL && 4680 (cookie == NULL || len != addr->entry->cookielen)) 4681 { 4682 isc_mem_put(adb->mctx, addr->entry->cookie, 4683 addr->entry->cookielen); 4684 addr->entry->cookie = NULL; 4685 addr->entry->cookielen = 0; 4686 } 4687 4688 if (addr->entry->cookie == NULL && cookie != NULL && len != 0U) { 4689 addr->entry->cookie = isc_mem_get(adb->mctx, len); 4690 addr->entry->cookielen = (uint16_t)len; 4691 } 4692 4693 if (addr->entry->cookie != NULL) { 4694 memmove(addr->entry->cookie, cookie, len); 4695 } 4696 UNLOCK(&adb->entrylocks[bucket]); 4697 } 4698 4699 size_t 4700 dns_adb_getcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr, 4701 unsigned char *cookie, size_t len) { 4702 int bucket; 4703 4704 REQUIRE(DNS_ADB_VALID(adb)); 4705 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4706 4707 bucket = addr->entry->lock_bucket; 4708 LOCK(&adb->entrylocks[bucket]); 4709 if (cookie != NULL && addr->entry->cookie != NULL && 4710 len >= addr->entry->cookielen) 4711 { 4712 memmove(cookie, addr->entry->cookie, addr->entry->cookielen); 4713 len = addr->entry->cookielen; 4714 } else { 4715 len = 0; 4716 } 4717 UNLOCK(&adb->entrylocks[bucket]); 4718 4719 return (len); 4720 } 4721 4722 isc_result_t 4723 dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *sa, 4724 dns_adbaddrinfo_t **addrp, isc_stdtime_t now) { 4725 int bucket; 4726 dns_adbentry_t *entry; 4727 dns_adbaddrinfo_t *addr; 4728 isc_result_t result; 4729 in_port_t port; 4730 4731 REQUIRE(DNS_ADB_VALID(adb)); 4732 REQUIRE(addrp != NULL && *addrp == NULL); 4733 4734 UNUSED(now); 4735 4736 result = ISC_R_SUCCESS; 4737 bucket = DNS_ADB_INVALIDBUCKET; 4738 entry = find_entry_and_lock(adb, sa, &bucket, now); 4739 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 4740 if (adb->entry_sd[bucket]) { 4741 result = ISC_R_SHUTTINGDOWN; 4742 goto unlock; 4743 } 4744 if (entry == NULL) { 4745 /* 4746 * We don't know anything about this address. 4747 */ 4748 entry = new_adbentry(adb); 4749 if (entry == NULL) { 4750 result = ISC_R_NOMEMORY; 4751 goto unlock; 4752 } 4753 entry->sockaddr = *sa; 4754 link_entry(adb, bucket, entry); 4755 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry); 4756 } else { 4757 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry); 4758 } 4759 4760 port = isc_sockaddr_getport(sa); 4761 addr = new_adbaddrinfo(adb, entry, port); 4762 if (addr == NULL) { 4763 result = ISC_R_NOMEMORY; 4764 } else { 4765 inc_entry_refcnt(adb, entry, false); 4766 *addrp = addr; 4767 } 4768 4769 unlock: 4770 UNLOCK(&adb->entrylocks[bucket]); 4771 4772 return (result); 4773 } 4774 4775 void 4776 dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) { 4777 dns_adbaddrinfo_t *addr; 4778 dns_adbentry_t *entry; 4779 int bucket; 4780 isc_stdtime_t now; 4781 bool want_check_exit = false; 4782 bool overmem; 4783 4784 REQUIRE(DNS_ADB_VALID(adb)); 4785 REQUIRE(addrp != NULL); 4786 addr = *addrp; 4787 *addrp = NULL; 4788 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4789 entry = addr->entry; 4790 REQUIRE(DNS_ADBENTRY_VALID(entry)); 4791 4792 overmem = isc_mem_isovermem(adb->mctx); 4793 4794 bucket = addr->entry->lock_bucket; 4795 LOCK(&adb->entrylocks[bucket]); 4796 4797 if (entry->expires == 0) { 4798 isc_stdtime_get(&now); 4799 entry->expires = now + ADB_ENTRY_WINDOW; 4800 } 4801 4802 want_check_exit = dec_entry_refcnt(adb, overmem, entry, false); 4803 4804 UNLOCK(&adb->entrylocks[bucket]); 4805 4806 addr->entry = NULL; 4807 free_adbaddrinfo(adb, &addr); 4808 4809 if (want_check_exit) { 4810 LOCK(&adb->lock); 4811 check_exit(adb); 4812 UNLOCK(&adb->lock); 4813 } 4814 } 4815 4816 void 4817 dns_adb_flush(dns_adb_t *adb) { 4818 unsigned int i; 4819 4820 INSIST(DNS_ADB_VALID(adb)); 4821 4822 LOCK(&adb->lock); 4823 4824 /* 4825 * Call our cleanup routines. 4826 */ 4827 for (i = 0; i < adb->nnames; i++) { 4828 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == false); 4829 } 4830 for (i = 0; i < adb->nentries; i++) { 4831 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == false); 4832 } 4833 4834 #ifdef DUMP_ADB_AFTER_CLEANING 4835 dump_adb(adb, stdout, true, INT_MAX); 4836 #endif /* ifdef DUMP_ADB_AFTER_CLEANING */ 4837 4838 UNLOCK(&adb->lock); 4839 } 4840 4841 void 4842 dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) { 4843 dns_adbname_t *adbname; 4844 dns_adbname_t *nextname; 4845 int bucket; 4846 4847 REQUIRE(DNS_ADB_VALID(adb)); 4848 REQUIRE(name != NULL); 4849 4850 LOCK(&adb->lock); 4851 bucket = dns_name_hash(name, false) % adb->nnames; 4852 LOCK(&adb->namelocks[bucket]); 4853 adbname = ISC_LIST_HEAD(adb->names[bucket]); 4854 while (adbname != NULL) { 4855 nextname = ISC_LIST_NEXT(adbname, plink); 4856 if (!NAME_DEAD(adbname) && dns_name_equal(name, &adbname->name)) 4857 { 4858 RUNTIME_CHECK( 4859 kill_name(&adbname, DNS_EVENT_ADBCANCELED) == 4860 false); 4861 } 4862 adbname = nextname; 4863 } 4864 UNLOCK(&adb->namelocks[bucket]); 4865 UNLOCK(&adb->lock); 4866 } 4867 4868 void 4869 dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) { 4870 dns_adbname_t *adbname, *nextname; 4871 unsigned int i; 4872 4873 REQUIRE(DNS_ADB_VALID(adb)); 4874 REQUIRE(name != NULL); 4875 4876 LOCK(&adb->lock); 4877 for (i = 0; i < adb->nnames; i++) { 4878 LOCK(&adb->namelocks[i]); 4879 adbname = ISC_LIST_HEAD(adb->names[i]); 4880 while (adbname != NULL) { 4881 bool ret; 4882 nextname = ISC_LIST_NEXT(adbname, plink); 4883 if (!NAME_DEAD(adbname) && 4884 dns_name_issubdomain(&adbname->name, name)) { 4885 ret = kill_name(&adbname, 4886 DNS_EVENT_ADBCANCELED); 4887 RUNTIME_CHECK(ret == false); 4888 } 4889 adbname = nextname; 4890 } 4891 UNLOCK(&adb->namelocks[i]); 4892 } 4893 UNLOCK(&adb->lock); 4894 } 4895 4896 static void 4897 water(void *arg, int mark) { 4898 /* 4899 * We're going to change the way to handle overmem condition: use 4900 * isc_mem_isovermem() instead of storing the state via this callback, 4901 * since the latter way tends to cause race conditions. 4902 * To minimize the change, and in case we re-enable the callback 4903 * approach, however, keep this function at the moment. 4904 */ 4905 4906 dns_adb_t *adb = arg; 4907 bool overmem = (mark == ISC_MEM_HIWATER); 4908 4909 REQUIRE(DNS_ADB_VALID(adb)); 4910 4911 DP(ISC_LOG_DEBUG(1), "adb reached %s water mark", 4912 overmem ? "high" : "low"); 4913 } 4914 4915 void 4916 dns_adb_setadbsize(dns_adb_t *adb, size_t size) { 4917 size_t hiwater, lowater; 4918 4919 INSIST(DNS_ADB_VALID(adb)); 4920 4921 if (size != 0U && size < DNS_ADB_MINADBSIZE) { 4922 size = DNS_ADB_MINADBSIZE; 4923 } 4924 4925 hiwater = size - (size >> 3); /* Approximately 7/8ths. */ 4926 lowater = size - (size >> 2); /* Approximately 3/4ths. */ 4927 4928 if (size == 0U || hiwater == 0U || lowater == 0U) { 4929 isc_mem_setwater(adb->mctx, water, adb, 0, 0); 4930 } else { 4931 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater); 4932 } 4933 } 4934 4935 void 4936 dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq, double low, 4937 double high, double discount) { 4938 REQUIRE(DNS_ADB_VALID(adb)); 4939 4940 adb->quota = quota; 4941 adb->atr_freq = freq; 4942 adb->atr_low = low; 4943 adb->atr_high = high; 4944 adb->atr_discount = discount; 4945 } 4946 4947 bool 4948 dns_adbentry_overquota(dns_adbentry_t *entry) { 4949 REQUIRE(DNS_ADBENTRY_VALID(entry)); 4950 4951 uint_fast32_t quota = atomic_load_relaxed(&entry->quota); 4952 uint_fast32_t active = atomic_load_acquire(&entry->active); 4953 4954 return (quota != 0 && active >= quota); 4955 } 4956 4957 void 4958 dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4959 REQUIRE(DNS_ADB_VALID(adb)); 4960 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4961 4962 INSIST(atomic_fetch_add_relaxed(&addr->entry->active, 1) != UINT32_MAX); 4963 } 4964 4965 void 4966 dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { 4967 REQUIRE(DNS_ADB_VALID(adb)); 4968 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 4969 4970 INSIST(atomic_fetch_sub_release(&addr->entry->active, 1) != 0); 4971 } 4972