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