adb.c revision 186462
1/* 2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: adb.c,v 1.215.18.24 2008/10/17 03:35:14 marka Exp $ */ 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/*% 30 * After we have cleaned all buckets, dump the database contents. 31 */ 32#if 0 33#define DUMP_ADB_AFTER_CLEANING 34#endif 35 36#include <config.h> 37 38#include <limits.h> 39 40#include <isc/mutexblock.h> 41#include <isc/netaddr.h> 42#include <isc/random.h> 43#include <isc/string.h> /* Required for HP/UX (and others?) */ 44#include <isc/task.h> 45#include <isc/timer.h> 46#include <isc/util.h> 47 48#include <dns/adb.h> 49#include <dns/db.h> 50#include <dns/events.h> 51#include <dns/log.h> 52#include <dns/rdata.h> 53#include <dns/rdataset.h> 54#include <dns/rdatastruct.h> 55#include <dns/rdatatype.h> 56#include <dns/resolver.h> 57#include <dns/result.h> 58 59#define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b') 60#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC) 61#define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N') 62#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC) 63#define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H') 64#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC) 65#define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z') 66#define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC) 67#define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E') 68#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC) 69#define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4') 70#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC) 71#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6') 72#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC) 73 74/*! 75 * The number of buckets needs to be a prime (for good hashing). 76 * 77 * XXXRTH How many buckets do we need? 78 */ 79#define NBUCKETS 1009 /*%< how many buckets for names/addrs */ 80 81/*! 82 * For type 3 negative cache entries, we will remember that the address is 83 * broken for this long. XXXMLG This is also used for actual addresses, too. 84 * The intent is to keep us from constantly asking about A/AAAA records 85 * if the zone has extremely low TTLs. 86 */ 87#define ADB_CACHE_MINIMUM 10 /*%< seconds */ 88#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */ 89#define ADB_ENTRY_WINDOW 1800 /*%< seconds */ 90 91/*% 92 * Wake up every CLEAN_SECONDS and clean CLEAN_BUCKETS buckets, so that all 93 * buckets are cleaned in CLEAN_PERIOD seconds. 94 */ 95#define CLEAN_PERIOD 3600 96/*% See #CLEAN_PERIOD */ 97#define CLEAN_SECONDS 30 98/*% See #CLEAN_PERIOD */ 99#define CLEAN_BUCKETS ((NBUCKETS * CLEAN_SECONDS) / CLEAN_PERIOD) 100 101#define FREE_ITEMS 64 /*%< free count for memory pools */ 102#define FILL_COUNT 16 /*%< fill count for memory pools */ 103 104#define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */ 105 106#define DNS_ADB_MINADBSIZE (1024*1024) /*%< 1 Megabyte */ 107 108typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t; 109typedef struct dns_adbnamehook dns_adbnamehook_t; 110typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t; 111typedef struct dns_adblameinfo dns_adblameinfo_t; 112typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t; 113typedef struct dns_adbfetch dns_adbfetch_t; 114typedef struct dns_adbfetch6 dns_adbfetch6_t; 115 116/*% dns adb structure */ 117struct dns_adb { 118 unsigned int magic; 119 120 isc_mutex_t lock; 121 isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */ 122 isc_mutex_t overmemlock; /*%< Covers overmem */ 123 isc_mem_t *mctx; 124 dns_view_t *view; 125 isc_timermgr_t *timermgr; 126 isc_timer_t *timer; 127 isc_taskmgr_t *taskmgr; 128 isc_task_t *task; 129 isc_boolean_t overmem; 130 131 isc_interval_t tick_interval; 132 int next_cleanbucket; 133 134 unsigned int irefcnt; 135 unsigned int erefcnt; 136 137 isc_mutex_t mplock; 138 isc_mempool_t *nmp; /*%< dns_adbname_t */ 139 isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */ 140 isc_mempool_t *limp; /*%< dns_adblameinfo_t */ 141 isc_mempool_t *emp; /*%< dns_adbentry_t */ 142 isc_mempool_t *ahmp; /*%< dns_adbfind_t */ 143 isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */ 144 isc_mempool_t *afmp; /*%< dns_adbfetch_t */ 145 146 /*! 147 * Bucketized locks and lists for names. 148 * 149 * XXXRTH Have a per-bucket structure that contains all of these? 150 */ 151 dns_adbnamelist_t names[NBUCKETS]; 152 /*% See dns_adbnamelist_t */ 153 isc_mutex_t namelocks[NBUCKETS]; 154 /*% See dns_adbnamelist_t */ 155 isc_boolean_t name_sd[NBUCKETS]; 156 /*% See dns_adbnamelist_t */ 157 unsigned int name_refcnt[NBUCKETS]; 158 159 /*! 160 * Bucketized locks for entries. 161 * 162 * XXXRTH Have a per-bucket structure that contains all of these? 163 */ 164 dns_adbentrylist_t entries[NBUCKETS]; 165 isc_mutex_t entrylocks[NBUCKETS]; 166 isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */ 167 unsigned int entry_refcnt[NBUCKETS]; 168 169 isc_event_t cevent; 170 isc_boolean_t cevent_sent; 171 isc_boolean_t shutting_down; 172 isc_eventlist_t whenshutdown; 173}; 174 175/* 176 * XXXMLG Document these structures. 177 */ 178 179/*% dns_adbname structure */ 180struct dns_adbname { 181 unsigned int magic; 182 dns_name_t name; 183 dns_adb_t *adb; 184 unsigned int partial_result; 185 unsigned int flags; 186 int lock_bucket; 187 dns_name_t target; 188 isc_stdtime_t expire_target; 189 isc_stdtime_t expire_v4; 190 isc_stdtime_t expire_v6; 191 unsigned int chains; 192 dns_adbnamehooklist_t v4; 193 dns_adbnamehooklist_t v6; 194 dns_adbfetch_t *fetch_a; 195 dns_adbfetch_t *fetch_aaaa; 196 unsigned int fetch_err; 197 unsigned int fetch6_err; 198 dns_adbfindlist_t finds; 199 ISC_LINK(dns_adbname_t) plink; 200}; 201 202/*% The adbfetch structure */ 203struct dns_adbfetch { 204 unsigned int magic; 205 dns_adbnamehook_t *namehook; 206 dns_adbentry_t *entry; 207 dns_fetch_t *fetch; 208 dns_rdataset_t rdataset; 209}; 210 211/*% 212 * This is a small widget that dangles off a dns_adbname_t. It contains a 213 * pointer to the address information about this host, and a link to the next 214 * namehook that will contain the next address this host has. 215 */ 216struct dns_adbnamehook { 217 unsigned int magic; 218 dns_adbentry_t *entry; 219 ISC_LINK(dns_adbnamehook_t) plink; 220}; 221 222/*% 223 * This is a small widget that holds qname-specific information about an 224 * address. Currently limited to lameness, but could just as easily be 225 * extended to other types of information about zones. 226 */ 227struct dns_adblameinfo { 228 unsigned int magic; 229 230 dns_name_t qname; 231 dns_rdatatype_t qtype; 232 isc_stdtime_t lame_timer; 233 234 ISC_LINK(dns_adblameinfo_t) plink; 235}; 236 237/*% 238 * An address entry. It holds quite a bit of information about addresses, 239 * including edns state (in "flags"), rtt, and of course the address of 240 * the host. 241 */ 242struct dns_adbentry { 243 unsigned int magic; 244 245 int lock_bucket; 246 unsigned int refcnt; 247 248 unsigned int flags; 249 unsigned int srtt; 250 isc_sockaddr_t sockaddr; 251 252 isc_stdtime_t expires; 253 /*%< 254 * A nonzero 'expires' field indicates that the entry should 255 * persist until that time. This allows entries found 256 * using dns_adb_findaddrinfo() to persist for a limited time 257 * even though they are not necessarily associated with a 258 * name. 259 */ 260 261 ISC_LIST(dns_adblameinfo_t) lameinfo; 262 ISC_LINK(dns_adbentry_t) plink; 263}; 264 265/* 266 * Internal functions (and prototypes). 267 */ 268static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *); 269static inline void free_adbname(dns_adb_t *, dns_adbname_t **); 270static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *, 271 dns_adbentry_t *); 272static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **); 273static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *, 274 dns_rdatatype_t); 275static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **); 276static inline dns_adbentry_t *new_adbentry(dns_adb_t *); 277static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **); 278static inline dns_adbfind_t *new_adbfind(dns_adb_t *); 279static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **); 280static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *, 281 in_port_t); 282static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *); 283static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **); 284static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *, 285 unsigned int, int *); 286static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *, 287 isc_sockaddr_t *, int *); 288static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t); 289static void print_dns_name(FILE *, dns_name_t *); 290static void print_namehook_list(FILE *, const char *legend, 291 dns_adbnamehooklist_t *list, 292 isc_boolean_t debug, 293 isc_stdtime_t now); 294static void print_find_list(FILE *, dns_adbname_t *); 295static void print_fetch_list(FILE *, dns_adbname_t *); 296static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *); 297static inline void inc_adb_irefcnt(dns_adb_t *); 298static inline void inc_adb_erefcnt(dns_adb_t *); 299static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *, 300 isc_boolean_t); 301static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *, 302 isc_boolean_t); 303static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); 304static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); 305static void clean_target(dns_adb_t *, dns_name_t *); 306static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, 307 unsigned int); 308static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t, 309 isc_boolean_t); 310static void cancel_fetches_at_name(dns_adbname_t *); 311static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, 312 dns_rdatatype_t); 313static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, 314 dns_rdatatype_t); 315static inline void check_exit(dns_adb_t *); 316static void timer_cleanup(isc_task_t *, isc_event_t *); 317static void destroy(dns_adb_t *); 318static isc_boolean_t shutdown_names(dns_adb_t *); 319static isc_boolean_t shutdown_entries(dns_adb_t *); 320static inline void link_name(dns_adb_t *, int, dns_adbname_t *); 321static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *); 322static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *); 323static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); 324static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); 325static void water(void *, int); 326static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); 327 328/* 329 * MUST NOT overlap DNS_ADBFIND_* flags! 330 */ 331#define FIND_EVENT_SENT 0x40000000 332#define FIND_EVENT_FREED 0x80000000 333#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0) 334#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0) 335 336#define NAME_NEEDS_POKE 0x80000000 337#define NAME_IS_DEAD 0x40000000 338#define NAME_HINT_OK DNS_ADBFIND_HINTOK 339#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK 340#define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE 341#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0) 342#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0) 343#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0) 344#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0) 345 346/* 347 * To the name, address classes are all that really exist. If it has a 348 * V6 address it doesn't care if it came from a AAAA query. 349 */ 350#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4)) 351#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6)) 352#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n)) 353 354/* 355 * Fetches are broken out into A and AAAA types. In some cases, 356 * however, it makes more sense to test for a particular class of fetches, 357 * like V4 or V6 above. 358 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA 359 * are now equal to FETCH_V4 and FETCH_V6, respectively. 360 */ 361#define NAME_FETCH_A(n) ((n)->fetch_a != NULL) 362#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL) 363#define NAME_FETCH_V4(n) (NAME_FETCH_A(n)) 364#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n)) 365#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n)) 366 367/* 368 * Find options and tests to see if there are addresses on the list. 369 */ 370#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0) 371#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0) 372#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \ 373 != 0) 374#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \ 375 != 0) 376#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0) 377#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0) 378#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list)) 379#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0) 380 381/* 382 * These are currently used on simple unsigned ints, so they are 383 * not really associated with any particular type. 384 */ 385#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0) 386#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0) 387 388#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now)) 389 390/* 391 * Find out if the flags on a name (nf) indicate if it is a hint or 392 * glue, and compare this to the appropriate bits set in o, to see if 393 * this is ok. 394 */ 395#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0)) 396#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0)) 397#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o)) 398#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \ 399 ((o) & DNS_ADBFIND_STARTATZONE)) 400 401#define ENTER_LEVEL ISC_LOG_DEBUG(50) 402#define EXIT_LEVEL ENTER_LEVEL 403#define CLEAN_LEVEL ISC_LOG_DEBUG(100) 404#define DEF_LEVEL ISC_LOG_DEBUG(5) 405#define NCACHE_LEVEL ISC_LOG_DEBUG(20) 406 407#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \ 408 (r) == DNS_R_NCACHENXRRSET) 409#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \ 410 (r) == DNS_R_NXRRSET) 411#define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \ 412 (r) == DNS_R_NCACHENXDOMAIN) 413#define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \ 414 (r) == DNS_R_NXRRSET || \ 415 (r) == DNS_R_HINTNXRRSET) 416 417/* 418 * Error state rankings. 419 */ 420 421#define FIND_ERR_SUCCESS 0 /* highest rank */ 422#define FIND_ERR_CANCELED 1 423#define FIND_ERR_FAILURE 2 424#define FIND_ERR_NXDOMAIN 3 425#define FIND_ERR_NXRRSET 4 426#define FIND_ERR_UNEXPECTED 5 427#define FIND_ERR_NOTFOUND 6 428#define FIND_ERR_MAX 7 429 430static const char *errnames[] = { 431 "success", 432 "canceled", 433 "failure", 434 "nxdomain", 435 "nxrrset", 436 "unexpected", 437 "not_found" 438}; 439 440#define NEWERR(old, new) (ISC_MIN((old), (new))) 441 442static isc_result_t find_err_map[FIND_ERR_MAX] = { 443 ISC_R_SUCCESS, 444 ISC_R_CANCELED, 445 ISC_R_FAILURE, 446 DNS_R_NXDOMAIN, 447 DNS_R_NXRRSET, 448 ISC_R_UNEXPECTED, 449 ISC_R_NOTFOUND /* not YET found */ 450}; 451 452static void 453DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); 454 455static void 456DP(int level, const char *format, ...) { 457 va_list args; 458 459 va_start(args, format); 460 isc_log_vwrite(dns_lctx, 461 DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, 462 level, format, args); 463 va_end(args); 464} 465 466static inline dns_ttl_t 467ttlclamp(dns_ttl_t ttl) { 468 if (ttl < ADB_CACHE_MINIMUM) 469 ttl = ADB_CACHE_MINIMUM; 470 if (ttl > ADB_CACHE_MAXIMUM) 471 ttl = ADB_CACHE_MAXIMUM; 472 473 return (ttl); 474} 475 476/* 477 * Requires the adbname bucket be locked and that no entry buckets be locked. 478 * 479 * This code handles A and AAAA rdatasets only. 480 */ 481static isc_result_t 482import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset, 483 isc_stdtime_t now) 484{ 485 isc_result_t result; 486 dns_adb_t *adb; 487 dns_adbnamehook_t *nh; 488 dns_adbnamehook_t *anh; 489 dns_rdata_t rdata = DNS_RDATA_INIT; 490 struct in_addr ina; 491 struct in6_addr in6a; 492 isc_sockaddr_t sockaddr; 493 dns_adbentry_t *foundentry; /* NO CLEAN UP! */ 494 int addr_bucket; 495 isc_boolean_t new_addresses_added; 496 dns_rdatatype_t rdtype; 497 unsigned int findoptions; 498 dns_adbnamehooklist_t *hookhead; 499 500 INSIST(DNS_ADBNAME_VALID(adbname)); 501 adb = adbname->adb; 502 INSIST(DNS_ADB_VALID(adb)); 503 504 rdtype = rdataset->type; 505 INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa)); 506 if (rdtype == dns_rdatatype_a) 507 findoptions = DNS_ADBFIND_INET; 508 else 509 findoptions = DNS_ADBFIND_INET6; 510 511 addr_bucket = DNS_ADB_INVALIDBUCKET; 512 new_addresses_added = ISC_FALSE; 513 514 nh = NULL; 515 result = dns_rdataset_first(rdataset); 516 while (result == ISC_R_SUCCESS) { 517 dns_rdata_reset(&rdata); 518 dns_rdataset_current(rdataset, &rdata); 519 if (rdtype == dns_rdatatype_a) { 520 INSIST(rdata.length == 4); 521 memcpy(&ina.s_addr, rdata.data, 4); 522 isc_sockaddr_fromin(&sockaddr, &ina, 0); 523 hookhead = &adbname->v4; 524 } else { 525 INSIST(rdata.length == 16); 526 memcpy(in6a.s6_addr, rdata.data, 16); 527 isc_sockaddr_fromin6(&sockaddr, &in6a, 0); 528 hookhead = &adbname->v6; 529 } 530 531 INSIST(nh == NULL); 532 nh = new_adbnamehook(adb, NULL); 533 if (nh == NULL) { 534 adbname->partial_result |= findoptions; 535 result = ISC_R_NOMEMORY; 536 goto fail; 537 } 538 539 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket); 540 if (foundentry == NULL) { 541 dns_adbentry_t *entry; 542 543 entry = new_adbentry(adb); 544 if (entry == NULL) { 545 adbname->partial_result |= findoptions; 546 result = ISC_R_NOMEMORY; 547 goto fail; 548 } 549 550 entry->sockaddr = sockaddr; 551 entry->refcnt = 1; 552 553 nh->entry = entry; 554 555 link_entry(adb, addr_bucket, entry); 556 } else { 557 for (anh = ISC_LIST_HEAD(*hookhead); 558 anh != NULL; 559 anh = ISC_LIST_NEXT(anh, plink)) 560 if (anh->entry == foundentry) 561 break; 562 if (anh == NULL) { 563 foundentry->refcnt++; 564 nh->entry = foundentry; 565 } else 566 free_adbnamehook(adb, &nh); 567 } 568 569 new_addresses_added = ISC_TRUE; 570 if (nh != NULL) 571 ISC_LIST_APPEND(*hookhead, nh, plink); 572 nh = NULL; 573 result = dns_rdataset_next(rdataset); 574 } 575 576 fail: 577 if (nh != NULL) 578 free_adbnamehook(adb, &nh); 579 580 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 581 UNLOCK(&adb->entrylocks[addr_bucket]); 582 583 if (rdataset->trust == dns_trust_glue || 584 rdataset->trust == dns_trust_additional) 585 rdataset->ttl = ADB_CACHE_MINIMUM; 586 else 587 rdataset->ttl = ttlclamp(rdataset->ttl); 588 589 if (rdtype == dns_rdatatype_a) { 590 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset", 591 adbname->expire_v4, now + rdataset->ttl); 592 adbname->expire_v4 = ISC_MIN(adbname->expire_v4, 593 now + rdataset->ttl); 594 } else { 595 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset", 596 adbname->expire_v6, now + rdataset->ttl); 597 adbname->expire_v6 = ISC_MIN(adbname->expire_v6, 598 now + rdataset->ttl); 599 } 600 601 if (new_addresses_added) { 602 /* 603 * Lie a little here. This is more or less so code that cares 604 * can find out if any new information was added or not. 605 */ 606 return (ISC_R_SUCCESS); 607 } 608 609 return (result); 610} 611 612/* 613 * Requires the name's bucket be locked. 614 */ 615static isc_boolean_t 616kill_name(dns_adbname_t **n, isc_eventtype_t ev) { 617 dns_adbname_t *name; 618 isc_boolean_t result = ISC_FALSE; 619 isc_boolean_t result4, result6; 620 dns_adb_t *adb; 621 622 INSIST(n != NULL); 623 name = *n; 624 *n = NULL; 625 INSIST(DNS_ADBNAME_VALID(name)); 626 adb = name->adb; 627 INSIST(DNS_ADB_VALID(adb)); 628 629 DP(DEF_LEVEL, "killing name %p", name); 630 631 /* 632 * If we're dead already, just check to see if we should go 633 * away now or not. 634 */ 635 if (NAME_DEAD(name) && !NAME_FETCH(name)) { 636 result = unlink_name(adb, name); 637 free_adbname(adb, &name); 638 if (result) 639 result = dec_adb_irefcnt(adb); 640 return (result); 641 } 642 643 /* 644 * Clean up the name's various lists. These two are destructive 645 * in that they will always empty the list. 646 */ 647 clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); 648 result4 = clean_namehooks(adb, &name->v4); 649 result6 = clean_namehooks(adb, &name->v6); 650 clean_target(adb, &name->target); 651 result = ISC_TF(result4 || result6); 652 653 /* 654 * If fetches are running, cancel them. If none are running, we can 655 * just kill the name here. 656 */ 657 if (!NAME_FETCH(name)) { 658 INSIST(result == ISC_FALSE); 659 result = unlink_name(adb, name); 660 free_adbname(adb, &name); 661 if (result) 662 result = dec_adb_irefcnt(adb); 663 } else { 664 name->flags |= NAME_IS_DEAD; 665 cancel_fetches_at_name(name); 666 } 667 return (result); 668} 669 670/* 671 * Requires the name's bucket be locked and no entry buckets be locked. 672 */ 673static isc_boolean_t 674check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now, 675 isc_boolean_t overmem) 676{ 677 dns_adb_t *adb; 678 isc_boolean_t expire; 679 isc_boolean_t result4 = ISC_FALSE; 680 isc_boolean_t result6 = ISC_FALSE; 681 682 INSIST(DNS_ADBNAME_VALID(name)); 683 adb = name->adb; 684 INSIST(DNS_ADB_VALID(adb)); 685 686 if (overmem) { 687 isc_uint32_t val; 688 689 isc_random_get(&val); 690 691 expire = ISC_TF((val % 4) == 0); 692 } else 693 expire = ISC_FALSE; 694 695 /* 696 * Check to see if we need to remove the v4 addresses 697 */ 698 if (!NAME_FETCH_V4(name) && 699 (expire || EXPIRE_OK(name->expire_v4, now))) { 700 if (NAME_HAS_V4(name)) { 701 DP(DEF_LEVEL, "expiring v4 for name %p", name); 702 result4 = clean_namehooks(adb, &name->v4); 703 name->partial_result &= ~DNS_ADBFIND_INET; 704 } 705 name->expire_v4 = INT_MAX; 706 name->fetch_err = FIND_ERR_UNEXPECTED; 707 } 708 709 /* 710 * Check to see if we need to remove the v6 addresses 711 */ 712 if (!NAME_FETCH_V6(name) && 713 (expire || EXPIRE_OK(name->expire_v6, now))) { 714 if (NAME_HAS_V6(name)) { 715 DP(DEF_LEVEL, "expiring v6 for name %p", name); 716 result6 = clean_namehooks(adb, &name->v6); 717 name->partial_result &= ~DNS_ADBFIND_INET6; 718 } 719 name->expire_v6 = INT_MAX; 720 name->fetch6_err = FIND_ERR_UNEXPECTED; 721 } 722 723 /* 724 * Check to see if we need to remove the alias target. 725 */ 726 if (expire || EXPIRE_OK(name->expire_target, now)) { 727 clean_target(adb, &name->target); 728 name->expire_target = INT_MAX; 729 } 730 return (ISC_TF(result4 || result6)); 731} 732 733/* 734 * Requires the name's bucket be locked. 735 */ 736static inline void 737link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) { 738 INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET); 739 740 ISC_LIST_PREPEND(adb->names[bucket], name, plink); 741 name->lock_bucket = bucket; 742 adb->name_refcnt[bucket]++; 743} 744 745/* 746 * Requires the name's bucket be locked. 747 */ 748static inline isc_boolean_t 749unlink_name(dns_adb_t *adb, dns_adbname_t *name) { 750 int bucket; 751 isc_boolean_t result = ISC_FALSE; 752 753 bucket = name->lock_bucket; 754 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 755 756 ISC_LIST_UNLINK(adb->names[bucket], name, plink); 757 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 758 INSIST(adb->name_refcnt[bucket] > 0); 759 adb->name_refcnt[bucket]--; 760 if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) 761 result = ISC_TRUE; 762 return (result); 763} 764 765/* 766 * Requires the entry's bucket be locked. 767 */ 768static inline void 769link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) { 770 ISC_LIST_PREPEND(adb->entries[bucket], entry, plink); 771 entry->lock_bucket = bucket; 772 adb->entry_refcnt[bucket]++; 773} 774 775/* 776 * Requires the entry's bucket be locked. 777 */ 778static inline isc_boolean_t 779unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) { 780 int bucket; 781 isc_boolean_t result = ISC_FALSE; 782 783 bucket = entry->lock_bucket; 784 INSIST(bucket != DNS_ADB_INVALIDBUCKET); 785 786 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink); 787 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 788 INSIST(adb->entry_refcnt[bucket] > 0); 789 adb->entry_refcnt[bucket]--; 790 if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0) 791 result = ISC_TRUE; 792 return (result); 793} 794 795static inline void 796violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) { 797 if (isc_mutex_trylock(want) != ISC_R_SUCCESS) { 798 UNLOCK(have); 799 LOCK(want); 800 LOCK(have); 801 } 802} 803 804/* 805 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 806 * checked after calling this function. 807 */ 808static isc_boolean_t 809shutdown_names(dns_adb_t *adb) { 810 int bucket; 811 isc_boolean_t result = ISC_FALSE; 812 dns_adbname_t *name; 813 dns_adbname_t *next_name; 814 815 for (bucket = 0; bucket < NBUCKETS; bucket++) { 816 LOCK(&adb->namelocks[bucket]); 817 adb->name_sd[bucket] = ISC_TRUE; 818 819 name = ISC_LIST_HEAD(adb->names[bucket]); 820 if (name == NULL) { 821 /* 822 * This bucket has no names. We must decrement the 823 * irefcnt ourselves, since it will not be 824 * automatically triggered by a name being unlinked. 825 */ 826 INSIST(result == ISC_FALSE); 827 result = dec_adb_irefcnt(adb); 828 } else { 829 /* 830 * Run through the list. For each name, clean up finds 831 * found there, and cancel any fetches running. When 832 * all the fetches are canceled, the name will destroy 833 * itself. 834 */ 835 while (name != NULL) { 836 next_name = ISC_LIST_NEXT(name, plink); 837 INSIST(result == ISC_FALSE); 838 result = kill_name(&name, 839 DNS_EVENT_ADBSHUTDOWN); 840 name = next_name; 841 } 842 } 843 844 UNLOCK(&adb->namelocks[bucket]); 845 } 846 return (result); 847} 848 849/* 850 * The ADB _MUST_ be locked before calling. Also, exit conditions must be 851 * checked after calling this function. 852 */ 853static isc_boolean_t 854shutdown_entries(dns_adb_t *adb) { 855 int bucket; 856 isc_boolean_t result = ISC_FALSE; 857 dns_adbentry_t *entry; 858 dns_adbentry_t *next_entry; 859 860 for (bucket = 0; bucket < NBUCKETS; bucket++) { 861 LOCK(&adb->entrylocks[bucket]); 862 adb->entry_sd[bucket] = ISC_TRUE; 863 864 entry = ISC_LIST_HEAD(adb->entries[bucket]); 865 if (entry == NULL) { 866 /* 867 * This bucket has no entries. We must decrement the 868 * irefcnt ourselves, since it will not be 869 * automatically triggered by an entry being unlinked. 870 */ 871 result = dec_adb_irefcnt(adb); 872 } else { 873 /* 874 * Run through the list. Cleanup any entries not 875 * associated with names, and which are not in use. 876 */ 877 while (entry != NULL) { 878 next_entry = ISC_LIST_NEXT(entry, plink); 879 if (entry->refcnt == 0 && 880 entry->expires != 0) { 881 result = unlink_entry(adb, entry); 882 free_adbentry(adb, &entry); 883 if (result) 884 result = dec_adb_irefcnt(adb); 885 } 886 entry = next_entry; 887 } 888 } 889 890 UNLOCK(&adb->entrylocks[bucket]); 891 } 892 return (result); 893} 894 895/* 896 * Name bucket must be locked 897 */ 898static void 899cancel_fetches_at_name(dns_adbname_t *name) { 900 if (NAME_FETCH_A(name)) 901 dns_resolver_cancelfetch(name->fetch_a->fetch); 902 903 if (NAME_FETCH_AAAA(name)) 904 dns_resolver_cancelfetch(name->fetch_aaaa->fetch); 905} 906 907/* 908 * Assumes the name bucket is locked. 909 */ 910static isc_boolean_t 911clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { 912 dns_adbentry_t *entry; 913 dns_adbnamehook_t *namehook; 914 int addr_bucket; 915 isc_boolean_t result = ISC_FALSE; 916 917 addr_bucket = DNS_ADB_INVALIDBUCKET; 918 namehook = ISC_LIST_HEAD(*namehooks); 919 while (namehook != NULL) { 920 INSIST(DNS_ADBNAMEHOOK_VALID(namehook)); 921 922 /* 923 * Clean up the entry if needed. 924 */ 925 entry = namehook->entry; 926 if (entry != NULL) { 927 INSIST(DNS_ADBENTRY_VALID(entry)); 928 929 if (addr_bucket != entry->lock_bucket) { 930 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 931 UNLOCK(&adb->entrylocks[addr_bucket]); 932 addr_bucket = entry->lock_bucket; 933 LOCK(&adb->entrylocks[addr_bucket]); 934 } 935 936 result = dec_entry_refcnt(adb, entry, ISC_FALSE); 937 } 938 939 /* 940 * Free the namehook 941 */ 942 namehook->entry = NULL; 943 ISC_LIST_UNLINK(*namehooks, namehook, plink); 944 free_adbnamehook(adb, &namehook); 945 946 namehook = ISC_LIST_HEAD(*namehooks); 947 } 948 949 if (addr_bucket != DNS_ADB_INVALIDBUCKET) 950 UNLOCK(&adb->entrylocks[addr_bucket]); 951 return (result); 952} 953 954static void 955clean_target(dns_adb_t *adb, dns_name_t *target) { 956 if (dns_name_countlabels(target) > 0) { 957 dns_name_free(target, adb->mctx); 958 dns_name_init(target, NULL); 959 } 960} 961 962static isc_result_t 963set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname, 964 dns_rdataset_t *rdataset, dns_name_t *target) 965{ 966 isc_result_t result; 967 dns_namereln_t namereln; 968 unsigned int nlabels; 969 int order; 970 dns_rdata_t rdata = DNS_RDATA_INIT; 971 dns_fixedname_t fixed1, fixed2; 972 dns_name_t *prefix, *new_target; 973 974 REQUIRE(dns_name_countlabels(target) == 0); 975 976 if (rdataset->type == dns_rdatatype_cname) { 977 dns_rdata_cname_t cname; 978 979 /* 980 * Copy the CNAME's target into the target name. 981 */ 982 result = dns_rdataset_first(rdataset); 983 if (result != ISC_R_SUCCESS) 984 return (result); 985 dns_rdataset_current(rdataset, &rdata); 986 result = dns_rdata_tostruct(&rdata, &cname, NULL); 987 if (result != ISC_R_SUCCESS) 988 return (result); 989 result = dns_name_dup(&cname.cname, adb->mctx, target); 990 dns_rdata_freestruct(&cname); 991 if (result != ISC_R_SUCCESS) 992 return (result); 993 } else { 994 dns_rdata_dname_t dname; 995 996 INSIST(rdataset->type == dns_rdatatype_dname); 997 namereln = dns_name_fullcompare(name, fname, &order, &nlabels); 998 INSIST(namereln == dns_namereln_subdomain); 999 /* 1000 * Get the target name of the DNAME. 1001 */ 1002 result = dns_rdataset_first(rdataset); 1003 if (result != ISC_R_SUCCESS) 1004 return (result); 1005 dns_rdataset_current(rdataset, &rdata); 1006 result = dns_rdata_tostruct(&rdata, &dname, NULL); 1007 if (result != ISC_R_SUCCESS) 1008 return (result); 1009 /* 1010 * Construct the new target name. 1011 */ 1012 dns_fixedname_init(&fixed1); 1013 prefix = dns_fixedname_name(&fixed1); 1014 dns_fixedname_init(&fixed2); 1015 new_target = dns_fixedname_name(&fixed2); 1016 dns_name_split(name, nlabels, prefix, NULL); 1017 result = dns_name_concatenate(prefix, &dname.dname, new_target, 1018 NULL); 1019 dns_rdata_freestruct(&dname); 1020 if (result != ISC_R_SUCCESS) 1021 return (result); 1022 result = dns_name_dup(new_target, adb->mctx, target); 1023 if (result != ISC_R_SUCCESS) 1024 return (result); 1025 } 1026 1027 return (ISC_R_SUCCESS); 1028} 1029 1030/* 1031 * Assumes nothing is locked, since this is called by the client. 1032 */ 1033static void 1034event_free(isc_event_t *event) { 1035 dns_adbfind_t *find; 1036 1037 INSIST(event != NULL); 1038 find = event->ev_destroy_arg; 1039 INSIST(DNS_ADBFIND_VALID(find)); 1040 1041 LOCK(&find->lock); 1042 find->flags |= FIND_EVENT_FREED; 1043 event->ev_destroy_arg = NULL; 1044 UNLOCK(&find->lock); 1045} 1046 1047/* 1048 * Assumes the name bucket is locked. 1049 */ 1050static void 1051clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, 1052 unsigned int addrs) 1053{ 1054 isc_event_t *ev; 1055 isc_task_t *task; 1056 dns_adbfind_t *find; 1057 dns_adbfind_t *next_find; 1058 isc_boolean_t process; 1059 unsigned int wanted, notify; 1060 1061 DP(ENTER_LEVEL, 1062 "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x", 1063 name, evtype, addrs); 1064 1065 find = ISC_LIST_HEAD(name->finds); 1066 while (find != NULL) { 1067 LOCK(&find->lock); 1068 next_find = ISC_LIST_NEXT(find, plink); 1069 1070 process = ISC_FALSE; 1071 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1072 notify = wanted & addrs; 1073 1074 switch (evtype) { 1075 case DNS_EVENT_ADBMOREADDRESSES: 1076 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES"); 1077 if ((notify) != 0) { 1078 find->flags &= ~addrs; 1079 process = ISC_TRUE; 1080 } 1081 break; 1082 case DNS_EVENT_ADBNOMOREADDRESSES: 1083 DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES"); 1084 find->flags &= ~addrs; 1085 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK; 1086 if (wanted == 0) 1087 process = ISC_TRUE; 1088 break; 1089 default: 1090 find->flags &= ~addrs; 1091 process = ISC_TRUE; 1092 } 1093 1094 if (process) { 1095 DP(DEF_LEVEL, "cfan: processing find %p", find); 1096 /* 1097 * Unlink the find from the name, letting the caller 1098 * call dns_adb_destroyfind() on it to clean it up 1099 * later. 1100 */ 1101 ISC_LIST_UNLINK(name->finds, find, plink); 1102 find->adbname = NULL; 1103 find->name_bucket = DNS_ADB_INVALIDBUCKET; 1104 1105 INSIST(!FIND_EVENTSENT(find)); 1106 1107 ev = &find->event; 1108 task = ev->ev_sender; 1109 ev->ev_sender = find; 1110 find->result_v4 = find_err_map[name->fetch_err]; 1111 find->result_v6 = find_err_map[name->fetch6_err]; 1112 ev->ev_type = evtype; 1113 ev->ev_destroy = event_free; 1114 ev->ev_destroy_arg = find; 1115 1116 DP(DEF_LEVEL, 1117 "sending event %p to task %p for find %p", 1118 ev, task, find); 1119 1120 isc_task_sendanddetach(&task, (isc_event_t **)&ev); 1121 } else { 1122 DP(DEF_LEVEL, "cfan: skipping find %p", find); 1123 } 1124 1125 UNLOCK(&find->lock); 1126 find = next_find; 1127 } 1128 1129 DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name); 1130} 1131 1132static inline void 1133check_exit(dns_adb_t *adb) { 1134 isc_event_t *event; 1135 /* 1136 * The caller must be holding the adb lock. 1137 */ 1138 if (adb->shutting_down) { 1139 /* 1140 * If there aren't any external references either, we're 1141 * done. Send the control event to initiate shutdown. 1142 */ 1143 INSIST(!adb->cevent_sent); /* Sanity check. */ 1144 event = &adb->cevent; 1145 isc_task_send(adb->task, &event); 1146 adb->cevent_sent = ISC_TRUE; 1147 } 1148} 1149 1150static inline isc_boolean_t 1151dec_adb_irefcnt(dns_adb_t *adb) { 1152 isc_event_t *event; 1153 isc_task_t *etask; 1154 isc_boolean_t result = ISC_FALSE; 1155 1156 LOCK(&adb->reflock); 1157 1158 INSIST(adb->irefcnt > 0); 1159 adb->irefcnt--; 1160 1161 if (adb->irefcnt == 0) { 1162 event = ISC_LIST_HEAD(adb->whenshutdown); 1163 while (event != NULL) { 1164 ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link); 1165 etask = event->ev_sender; 1166 event->ev_sender = adb; 1167 isc_task_sendanddetach(&etask, &event); 1168 event = ISC_LIST_HEAD(adb->whenshutdown); 1169 } 1170 } 1171 1172 if (adb->irefcnt == 0 && adb->erefcnt == 0) 1173 result = ISC_TRUE; 1174 UNLOCK(&adb->reflock); 1175 return (result); 1176} 1177 1178static inline void 1179inc_adb_irefcnt(dns_adb_t *adb) { 1180 LOCK(&adb->reflock); 1181 adb->irefcnt++; 1182 UNLOCK(&adb->reflock); 1183} 1184 1185static inline void 1186inc_adb_erefcnt(dns_adb_t *adb) { 1187 LOCK(&adb->reflock); 1188 adb->erefcnt++; 1189 UNLOCK(&adb->reflock); 1190} 1191 1192static inline void 1193inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { 1194 int bucket; 1195 1196 bucket = entry->lock_bucket; 1197 1198 if (lock) 1199 LOCK(&adb->entrylocks[bucket]); 1200 1201 entry->refcnt++; 1202 1203 if (lock) 1204 UNLOCK(&adb->entrylocks[bucket]); 1205} 1206 1207static inline isc_boolean_t 1208dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { 1209 int bucket; 1210 isc_boolean_t destroy_entry; 1211 isc_boolean_t result = ISC_FALSE; 1212 1213 bucket = entry->lock_bucket; 1214 1215 if (lock) 1216 LOCK(&adb->entrylocks[bucket]); 1217 1218 INSIST(entry->refcnt > 0); 1219 entry->refcnt--; 1220 1221 destroy_entry = ISC_FALSE; 1222 if (entry->refcnt == 0 && 1223 (adb->entry_sd[bucket] || entry->expires == 0)) { 1224 destroy_entry = ISC_TRUE; 1225 result = unlink_entry(adb, entry); 1226 } 1227 1228 if (lock) 1229 UNLOCK(&adb->entrylocks[bucket]); 1230 1231 if (!destroy_entry) 1232 return (result); 1233 1234 entry->lock_bucket = DNS_ADB_INVALIDBUCKET; 1235 1236 free_adbentry(adb, &entry); 1237 if (result) 1238 result =dec_adb_irefcnt(adb); 1239 1240 return (result); 1241} 1242 1243static inline dns_adbname_t * 1244new_adbname(dns_adb_t *adb, dns_name_t *dnsname) { 1245 dns_adbname_t *name; 1246 1247 name = isc_mempool_get(adb->nmp); 1248 if (name == NULL) 1249 return (NULL); 1250 1251 dns_name_init(&name->name, NULL); 1252 if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) { 1253 isc_mempool_put(adb->nmp, name); 1254 return (NULL); 1255 } 1256 dns_name_init(&name->target, NULL); 1257 name->magic = DNS_ADBNAME_MAGIC; 1258 name->adb = adb; 1259 name->partial_result = 0; 1260 name->flags = 0; 1261 name->expire_v4 = INT_MAX; 1262 name->expire_v6 = INT_MAX; 1263 name->expire_target = INT_MAX; 1264 name->chains = 0; 1265 name->lock_bucket = DNS_ADB_INVALIDBUCKET; 1266 ISC_LIST_INIT(name->v4); 1267 ISC_LIST_INIT(name->v6); 1268 name->fetch_a = NULL; 1269 name->fetch_aaaa = NULL; 1270 name->fetch_err = FIND_ERR_UNEXPECTED; 1271 name->fetch6_err = FIND_ERR_UNEXPECTED; 1272 ISC_LIST_INIT(name->finds); 1273 ISC_LINK_INIT(name, plink); 1274 1275 return (name); 1276} 1277 1278static inline void 1279free_adbname(dns_adb_t *adb, dns_adbname_t **name) { 1280 dns_adbname_t *n; 1281 1282 INSIST(name != NULL && DNS_ADBNAME_VALID(*name)); 1283 n = *name; 1284 *name = NULL; 1285 1286 INSIST(!NAME_HAS_V4(n)); 1287 INSIST(!NAME_HAS_V6(n)); 1288 INSIST(!NAME_FETCH(n)); 1289 INSIST(ISC_LIST_EMPTY(n->finds)); 1290 INSIST(!ISC_LINK_LINKED(n, plink)); 1291 INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET); 1292 INSIST(n->adb == adb); 1293 1294 n->magic = 0; 1295 dns_name_free(&n->name, adb->mctx); 1296 1297 isc_mempool_put(adb->nmp, n); 1298} 1299 1300static inline dns_adbnamehook_t * 1301new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) { 1302 dns_adbnamehook_t *nh; 1303 1304 nh = isc_mempool_get(adb->nhmp); 1305 if (nh == NULL) 1306 return (NULL); 1307 1308 nh->magic = DNS_ADBNAMEHOOK_MAGIC; 1309 nh->entry = entry; 1310 ISC_LINK_INIT(nh, plink); 1311 1312 return (nh); 1313} 1314 1315static inline void 1316free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) { 1317 dns_adbnamehook_t *nh; 1318 1319 INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook)); 1320 nh = *namehook; 1321 *namehook = NULL; 1322 1323 INSIST(nh->entry == NULL); 1324 INSIST(!ISC_LINK_LINKED(nh, plink)); 1325 1326 nh->magic = 0; 1327 isc_mempool_put(adb->nhmp, nh); 1328} 1329 1330static inline dns_adblameinfo_t * 1331new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) { 1332 dns_adblameinfo_t *li; 1333 1334 li = isc_mempool_get(adb->limp); 1335 if (li == NULL) 1336 return (NULL); 1337 1338 dns_name_init(&li->qname, NULL); 1339 if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) { 1340 isc_mempool_put(adb->limp, li); 1341 return (NULL); 1342 } 1343 li->magic = DNS_ADBLAMEINFO_MAGIC; 1344 li->lame_timer = 0; 1345 li->qtype = qtype; 1346 ISC_LINK_INIT(li, plink); 1347 1348 return (li); 1349} 1350 1351static inline void 1352free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) { 1353 dns_adblameinfo_t *li; 1354 1355 INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo)); 1356 li = *lameinfo; 1357 *lameinfo = NULL; 1358 1359 INSIST(!ISC_LINK_LINKED(li, plink)); 1360 1361 dns_name_free(&li->qname, adb->mctx); 1362 1363 li->magic = 0; 1364 1365 isc_mempool_put(adb->limp, li); 1366} 1367 1368static inline dns_adbentry_t * 1369new_adbentry(dns_adb_t *adb) { 1370 dns_adbentry_t *e; 1371 isc_uint32_t r; 1372 1373 e = isc_mempool_get(adb->emp); 1374 if (e == NULL) 1375 return (NULL); 1376 1377 e->magic = DNS_ADBENTRY_MAGIC; 1378 e->lock_bucket = DNS_ADB_INVALIDBUCKET; 1379 e->refcnt = 0; 1380 e->flags = 0; 1381 isc_random_get(&r); 1382 e->srtt = (r & 0x1f) + 1; 1383 e->expires = 0; 1384 ISC_LIST_INIT(e->lameinfo); 1385 ISC_LINK_INIT(e, plink); 1386 1387 return (e); 1388} 1389 1390static inline void 1391free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) { 1392 dns_adbentry_t *e; 1393 dns_adblameinfo_t *li; 1394 1395 INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry)); 1396 e = *entry; 1397 *entry = NULL; 1398 1399 INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET); 1400 INSIST(e->refcnt == 0); 1401 INSIST(!ISC_LINK_LINKED(e, plink)); 1402 1403 e->magic = 0; 1404 1405 li = ISC_LIST_HEAD(e->lameinfo); 1406 while (li != NULL) { 1407 ISC_LIST_UNLINK(e->lameinfo, li, plink); 1408 free_adblameinfo(adb, &li); 1409 li = ISC_LIST_HEAD(e->lameinfo); 1410 } 1411 1412 isc_mempool_put(adb->emp, e); 1413} 1414 1415static inline dns_adbfind_t * 1416new_adbfind(dns_adb_t *adb) { 1417 dns_adbfind_t *h; 1418 isc_result_t result; 1419 1420 h = isc_mempool_get(adb->ahmp); 1421 if (h == NULL) 1422 return (NULL); 1423 1424 /* 1425 * Public members. 1426 */ 1427 h->magic = 0; 1428 h->adb = adb; 1429 h->partial_result = 0; 1430 h->options = 0; 1431 h->flags = 0; 1432 h->result_v4 = ISC_R_UNEXPECTED; 1433 h->result_v6 = ISC_R_UNEXPECTED; 1434 ISC_LINK_INIT(h, publink); 1435 ISC_LINK_INIT(h, plink); 1436 ISC_LIST_INIT(h->list); 1437 h->adbname = NULL; 1438 h->name_bucket = DNS_ADB_INVALIDBUCKET; 1439 1440 /* 1441 * private members 1442 */ 1443 result = isc_mutex_init(&h->lock); 1444 if (result != ISC_R_SUCCESS) { 1445 isc_mempool_put(adb->ahmp, h); 1446 return (NULL); 1447 } 1448 1449 ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL, 1450 NULL, NULL, h); 1451 1452 inc_adb_irefcnt(adb); 1453 h->magic = DNS_ADBFIND_MAGIC; 1454 return (h); 1455} 1456 1457static inline dns_adbfetch_t * 1458new_adbfetch(dns_adb_t *adb) { 1459 dns_adbfetch_t *f; 1460 1461 f = isc_mempool_get(adb->afmp); 1462 if (f == NULL) 1463 return (NULL); 1464 1465 f->magic = 0; 1466 f->namehook = NULL; 1467 f->entry = NULL; 1468 f->fetch = NULL; 1469 1470 f->namehook = new_adbnamehook(adb, NULL); 1471 if (f->namehook == NULL) 1472 goto err; 1473 1474 f->entry = new_adbentry(adb); 1475 if (f->entry == NULL) 1476 goto err; 1477 1478 dns_rdataset_init(&f->rdataset); 1479 1480 f->magic = DNS_ADBFETCH_MAGIC; 1481 1482 return (f); 1483 1484 err: 1485 if (f->namehook != NULL) 1486 free_adbnamehook(adb, &f->namehook); 1487 if (f->entry != NULL) 1488 free_adbentry(adb, &f->entry); 1489 isc_mempool_put(adb->afmp, f); 1490 return (NULL); 1491} 1492 1493static inline void 1494free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) { 1495 dns_adbfetch_t *f; 1496 1497 INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch)); 1498 f = *fetch; 1499 *fetch = NULL; 1500 1501 f->magic = 0; 1502 1503 if (f->namehook != NULL) 1504 free_adbnamehook(adb, &f->namehook); 1505 if (f->entry != NULL) 1506 free_adbentry(adb, &f->entry); 1507 1508 if (dns_rdataset_isassociated(&f->rdataset)) 1509 dns_rdataset_disassociate(&f->rdataset); 1510 1511 isc_mempool_put(adb->afmp, f); 1512} 1513 1514static inline isc_boolean_t 1515free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) { 1516 dns_adbfind_t *find; 1517 1518 INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp)); 1519 find = *findp; 1520 *findp = NULL; 1521 1522 INSIST(!FIND_HAS_ADDRS(find)); 1523 INSIST(!ISC_LINK_LINKED(find, publink)); 1524 INSIST(!ISC_LINK_LINKED(find, plink)); 1525 INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET); 1526 INSIST(find->adbname == NULL); 1527 1528 find->magic = 0; 1529 1530 DESTROYLOCK(&find->lock); 1531 isc_mempool_put(adb->ahmp, find); 1532 return (dec_adb_irefcnt(adb)); 1533} 1534 1535/* 1536 * Copy bits from the entry into the newly allocated addrinfo. The entry 1537 * must be locked, and the reference count must be bumped up by one 1538 * if this function returns a valid pointer. 1539 */ 1540static inline dns_adbaddrinfo_t * 1541new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) { 1542 dns_adbaddrinfo_t *ai; 1543 1544 ai = isc_mempool_get(adb->aimp); 1545 if (ai == NULL) 1546 return (NULL); 1547 1548 ai->magic = DNS_ADBADDRINFO_MAGIC; 1549 ai->sockaddr = entry->sockaddr; 1550 isc_sockaddr_setport(&ai->sockaddr, port); 1551 ai->srtt = entry->srtt; 1552 ai->flags = entry->flags; 1553 ai->entry = entry; 1554 ISC_LINK_INIT(ai, publink); 1555 1556 return (ai); 1557} 1558 1559static inline void 1560free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) { 1561 dns_adbaddrinfo_t *ai; 1562 1563 INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo)); 1564 ai = *ainfo; 1565 *ainfo = NULL; 1566 1567 INSIST(ai->entry == NULL); 1568 INSIST(!ISC_LINK_LINKED(ai, publink)); 1569 1570 ai->magic = 0; 1571 1572 isc_mempool_put(adb->aimp, ai); 1573} 1574 1575/* 1576 * Search for the name. NOTE: The bucket is kept locked on both 1577 * success and failure, so it must always be unlocked by the caller! 1578 * 1579 * On the first call to this function, *bucketp must be set to 1580 * DNS_ADB_INVALIDBUCKET. 1581 */ 1582static inline dns_adbname_t * 1583find_name_and_lock(dns_adb_t *adb, dns_name_t *name, 1584 unsigned int options, int *bucketp) 1585{ 1586 dns_adbname_t *adbname; 1587 int bucket; 1588 1589 bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS; 1590 1591 if (*bucketp == DNS_ADB_INVALIDBUCKET) { 1592 LOCK(&adb->namelocks[bucket]); 1593 *bucketp = bucket; 1594 } else if (*bucketp != bucket) { 1595 UNLOCK(&adb->namelocks[*bucketp]); 1596 LOCK(&adb->namelocks[bucket]); 1597 *bucketp = bucket; 1598 } 1599 1600 adbname = ISC_LIST_HEAD(adb->names[bucket]); 1601 while (adbname != NULL) { 1602 if (!NAME_DEAD(adbname)) { 1603 if (dns_name_equal(name, &adbname->name) 1604 && GLUEHINT_OK(adbname, options) 1605 && STARTATZONE_MATCHES(adbname, options)) 1606 return (adbname); 1607 } 1608 adbname = ISC_LIST_NEXT(adbname, plink); 1609 } 1610 1611 return (NULL); 1612} 1613 1614/* 1615 * Search for the address. NOTE: The bucket is kept locked on both 1616 * success and failure, so it must always be unlocked by the caller. 1617 * 1618 * On the first call to this function, *bucketp must be set to 1619 * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On 1620 * later calls (within the same "lock path") it can be left alone, so 1621 * if this function is called multiple times locking is only done if 1622 * the bucket changes. 1623 */ 1624static inline dns_adbentry_t * 1625find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) { 1626 dns_adbentry_t *entry; 1627 int bucket; 1628 1629 bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS; 1630 1631 if (*bucketp == DNS_ADB_INVALIDBUCKET) { 1632 LOCK(&adb->entrylocks[bucket]); 1633 *bucketp = bucket; 1634 } else if (*bucketp != bucket) { 1635 UNLOCK(&adb->entrylocks[*bucketp]); 1636 LOCK(&adb->entrylocks[bucket]); 1637 *bucketp = bucket; 1638 } 1639 1640 entry = ISC_LIST_HEAD(adb->entries[bucket]); 1641 while (entry != NULL) { 1642 if (isc_sockaddr_equal(addr, &entry->sockaddr)) 1643 return (entry); 1644 entry = ISC_LIST_NEXT(entry, plink); 1645 } 1646 1647 return (NULL); 1648} 1649 1650/* 1651 * Entry bucket MUST be locked! 1652 */ 1653static isc_boolean_t 1654entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname, 1655 dns_rdatatype_t qtype, isc_stdtime_t now) 1656{ 1657 dns_adblameinfo_t *li, *next_li; 1658 isc_boolean_t is_bad; 1659 1660 is_bad = ISC_FALSE; 1661 1662 li = ISC_LIST_HEAD(entry->lameinfo); 1663 if (li == NULL) 1664 return (ISC_FALSE); 1665 while (li != NULL) { 1666 next_li = ISC_LIST_NEXT(li, plink); 1667 1668 /* 1669 * Has the entry expired? 1670 */ 1671 if (li->lame_timer < now) { 1672 ISC_LIST_UNLINK(entry->lameinfo, li, plink); 1673 free_adblameinfo(adb, &li); 1674 } 1675 1676 /* 1677 * Order tests from least to most expensive. 1678 * 1679 * We do not break out of the main loop here as 1680 * we use the loop for house keeping. 1681 */ 1682 if (li != NULL && !is_bad && li->qtype == qtype && 1683 dns_name_equal(qname, &li->qname)) 1684 is_bad = ISC_TRUE; 1685 1686 li = next_li; 1687 } 1688 1689 return (is_bad); 1690} 1691 1692static void 1693copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname, 1694 dns_rdatatype_t qtype, dns_adbname_t *name, 1695 isc_stdtime_t now) 1696{ 1697 dns_adbnamehook_t *namehook; 1698 dns_adbaddrinfo_t *addrinfo; 1699 dns_adbentry_t *entry; 1700 int bucket; 1701 1702 bucket = DNS_ADB_INVALIDBUCKET; 1703 1704 if (find->options & DNS_ADBFIND_INET) { 1705 namehook = ISC_LIST_HEAD(name->v4); 1706 while (namehook != NULL) { 1707 entry = namehook->entry; 1708 bucket = entry->lock_bucket; 1709 LOCK(&adb->entrylocks[bucket]); 1710 1711 if (!FIND_RETURNLAME(find) 1712 && entry_is_lame(adb, entry, qname, qtype, now)) { 1713 find->options |= DNS_ADBFIND_LAMEPRUNED; 1714 goto nextv4; 1715 } 1716 addrinfo = new_adbaddrinfo(adb, entry, find->port); 1717 if (addrinfo == NULL) { 1718 find->partial_result |= DNS_ADBFIND_INET; 1719 goto out; 1720 } 1721 /* 1722 * Found a valid entry. Add it to the find's list. 1723 */ 1724 inc_entry_refcnt(adb, entry, ISC_FALSE); 1725 ISC_LIST_APPEND(find->list, addrinfo, publink); 1726 addrinfo = NULL; 1727 nextv4: 1728 UNLOCK(&adb->entrylocks[bucket]); 1729 bucket = DNS_ADB_INVALIDBUCKET; 1730 namehook = ISC_LIST_NEXT(namehook, plink); 1731 } 1732 } 1733 1734 if (find->options & DNS_ADBFIND_INET6) { 1735 namehook = ISC_LIST_HEAD(name->v6); 1736 while (namehook != NULL) { 1737 entry = namehook->entry; 1738 bucket = entry->lock_bucket; 1739 LOCK(&adb->entrylocks[bucket]); 1740 1741 if (!FIND_RETURNLAME(find) 1742 && entry_is_lame(adb, entry, qname, qtype, now)) { 1743 find->options |= DNS_ADBFIND_LAMEPRUNED; 1744 goto nextv6; 1745 } 1746 addrinfo = new_adbaddrinfo(adb, entry, find->port); 1747 if (addrinfo == NULL) { 1748 find->partial_result |= DNS_ADBFIND_INET6; 1749 goto out; 1750 } 1751 /* 1752 * Found a valid entry. Add it to the find's list. 1753 */ 1754 inc_entry_refcnt(adb, entry, ISC_FALSE); 1755 ISC_LIST_APPEND(find->list, addrinfo, publink); 1756 addrinfo = NULL; 1757 nextv6: 1758 UNLOCK(&adb->entrylocks[bucket]); 1759 bucket = DNS_ADB_INVALIDBUCKET; 1760 namehook = ISC_LIST_NEXT(namehook, plink); 1761 } 1762 } 1763 1764 out: 1765 if (bucket != DNS_ADB_INVALIDBUCKET) 1766 UNLOCK(&adb->entrylocks[bucket]); 1767} 1768 1769static void 1770shutdown_task(isc_task_t *task, isc_event_t *ev) { 1771 dns_adb_t *adb; 1772 1773 UNUSED(task); 1774 1775 adb = ev->ev_arg; 1776 INSIST(DNS_ADB_VALID(adb)); 1777 1778 /* 1779 * Wait for lock around check_exit() call to be released. 1780 */ 1781 LOCK(&adb->lock); 1782 /* 1783 * Kill the timer, and then the ADB itself. Note that this implies 1784 * that this task was the one scheduled to get timer events. If 1785 * this is not true (and it is unfortunate there is no way to INSIST() 1786 * this) badness will occur. 1787 */ 1788 isc_timer_detach(&adb->timer); 1789 UNLOCK(&adb->lock); 1790 isc_event_free(&ev); 1791 destroy(adb); 1792} 1793 1794/* 1795 * Name bucket must be locked; adb may be locked; no other locks held. 1796 */ 1797static isc_boolean_t 1798check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) { 1799 dns_adbname_t *name; 1800 isc_boolean_t result = ISC_FALSE; 1801 1802 INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep)); 1803 name = *namep; 1804 1805 if (NAME_HAS_V4(name) || NAME_HAS_V6(name)) 1806 return (result); 1807 if (NAME_FETCH(name)) 1808 return (result); 1809 if (!EXPIRE_OK(name->expire_v4, now)) 1810 return (result); 1811 if (!EXPIRE_OK(name->expire_v6, now)) 1812 return (result); 1813 if (!EXPIRE_OK(name->expire_target, now)) 1814 return (result); 1815 1816 /* 1817 * The name is empty. Delete it. 1818 */ 1819 result = kill_name(&name, DNS_EVENT_ADBEXPIRED); 1820 *namep = NULL; 1821 1822 /* 1823 * Our caller, or one of its callers, will be calling check_exit() at 1824 * some point, so we don't need to do it here. 1825 */ 1826 return (result); 1827} 1828 1829/* 1830 * Entry bucket must be locked; adb may be locked; no other locks held. 1831 */ 1832static isc_boolean_t 1833check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now) 1834{ 1835 dns_adbentry_t *entry; 1836 isc_boolean_t expire; 1837 isc_boolean_t result = ISC_FALSE; 1838 1839 INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp)); 1840 entry = *entryp; 1841 1842 if (entry->refcnt != 0) 1843 return (result); 1844 1845 if (adb->overmem) { 1846 isc_uint32_t val; 1847 1848 isc_random_get(&val); 1849 1850 expire = ISC_TF((val % 4) == 0); 1851 } else 1852 expire = ISC_FALSE; 1853 1854 if (entry->expires == 0 || (! expire && entry->expires > now)) 1855 return (result); 1856 1857 /* 1858 * The entry is not in use. Delete it. 1859 */ 1860 DP(DEF_LEVEL, "killing entry %p", entry); 1861 INSIST(ISC_LINK_LINKED(entry, plink)); 1862 result = unlink_entry(adb, entry); 1863 free_adbentry(adb, &entry); 1864 if (result) 1865 dec_adb_irefcnt(adb); 1866 *entryp = NULL; 1867 return (result); 1868} 1869 1870/* 1871 * ADB must be locked, and no other locks held. 1872 */ 1873static isc_boolean_t 1874cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) { 1875 dns_adbname_t *name; 1876 dns_adbname_t *next_name; 1877 isc_boolean_t result = ISC_FALSE; 1878 1879 DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket); 1880 1881 LOCK(&adb->namelocks[bucket]); 1882 if (adb->name_sd[bucket]) { 1883 UNLOCK(&adb->namelocks[bucket]); 1884 return (result); 1885 } 1886 1887 name = ISC_LIST_HEAD(adb->names[bucket]); 1888 while (name != NULL) { 1889 next_name = ISC_LIST_NEXT(name, plink); 1890 INSIST(result == ISC_FALSE); 1891 result = check_expire_namehooks(name, now, adb->overmem); 1892 if (!result) 1893 result = check_expire_name(&name, now); 1894 name = next_name; 1895 } 1896 UNLOCK(&adb->namelocks[bucket]); 1897 return (result); 1898} 1899 1900/* 1901 * ADB must be locked, and no other locks held. 1902 */ 1903static isc_boolean_t 1904cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) { 1905 dns_adbentry_t *entry, *next_entry; 1906 isc_boolean_t result = ISC_FALSE; 1907 1908 DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket); 1909 1910 LOCK(&adb->entrylocks[bucket]); 1911 entry = ISC_LIST_HEAD(adb->entries[bucket]); 1912 while (entry != NULL) { 1913 next_entry = ISC_LIST_NEXT(entry, plink); 1914 INSIST(result == ISC_FALSE); 1915 result = check_expire_entry(adb, &entry, now); 1916 entry = next_entry; 1917 } 1918 UNLOCK(&adb->entrylocks[bucket]); 1919 return (result); 1920} 1921 1922static void 1923timer_cleanup(isc_task_t *task, isc_event_t *ev) { 1924 dns_adb_t *adb; 1925 isc_stdtime_t now; 1926 unsigned int i; 1927 isc_interval_t interval; 1928 1929 UNUSED(task); 1930 1931 adb = ev->ev_arg; 1932 INSIST(DNS_ADB_VALID(adb)); 1933 1934 LOCK(&adb->lock); 1935 1936 isc_stdtime_get(&now); 1937 1938 for (i = 0; i < CLEAN_BUCKETS; i++) { 1939 /* 1940 * Call our cleanup routines. 1941 */ 1942 RUNTIME_CHECK(cleanup_names(adb, adb->next_cleanbucket, now) == 1943 ISC_FALSE); 1944 RUNTIME_CHECK(cleanup_entries(adb, adb->next_cleanbucket, now) 1945 == ISC_FALSE); 1946 1947 /* 1948 * Set the next bucket to be cleaned. 1949 */ 1950 adb->next_cleanbucket++; 1951 if (adb->next_cleanbucket >= NBUCKETS) { 1952 adb->next_cleanbucket = 0; 1953#ifdef DUMP_ADB_AFTER_CLEANING 1954 dump_adb(adb, stdout, ISC_TRUE, now); 1955#endif 1956 } 1957 } 1958 1959 /* 1960 * Reset the timer. 1961 * XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or 1962 * ISC_R_NOMEMORY, but it isn't clear what could be done here 1963 * if either one of those things happened. 1964 */ 1965 interval = adb->tick_interval; 1966 if (adb->overmem) 1967 isc_interval_set(&interval, 0, 1); 1968 (void)isc_timer_reset(adb->timer, isc_timertype_once, NULL, 1969 &interval, ISC_FALSE); 1970 1971 UNLOCK(&adb->lock); 1972 1973 isc_event_free(&ev); 1974} 1975 1976static void 1977destroy(dns_adb_t *adb) { 1978 adb->magic = 0; 1979 1980 /* 1981 * The timer is already dead, from the task's shutdown callback. 1982 */ 1983 isc_task_detach(&adb->task); 1984 1985 isc_mempool_destroy(&adb->nmp); 1986 isc_mempool_destroy(&adb->nhmp); 1987 isc_mempool_destroy(&adb->limp); 1988 isc_mempool_destroy(&adb->emp); 1989 isc_mempool_destroy(&adb->ahmp); 1990 isc_mempool_destroy(&adb->aimp); 1991 isc_mempool_destroy(&adb->afmp); 1992 1993 DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS); 1994 DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS); 1995 1996 DESTROYLOCK(&adb->reflock); 1997 DESTROYLOCK(&adb->lock); 1998 DESTROYLOCK(&adb->mplock); 1999 DESTROYLOCK(&adb->overmemlock); 2000 2001 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t)); 2002} 2003 2004 2005/* 2006 * Public functions. 2007 */ 2008 2009isc_result_t 2010dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, 2011 isc_taskmgr_t *taskmgr, dns_adb_t **newadb) 2012{ 2013 dns_adb_t *adb; 2014 isc_result_t result; 2015 int i; 2016 2017 REQUIRE(mem != NULL); 2018 REQUIRE(view != NULL); 2019 REQUIRE(timermgr != NULL); 2020 REQUIRE(taskmgr != NULL); 2021 REQUIRE(newadb != NULL && *newadb == NULL); 2022 2023 adb = isc_mem_get(mem, sizeof(dns_adb_t)); 2024 if (adb == NULL) 2025 return (ISC_R_NOMEMORY); 2026 2027 /* 2028 * Initialize things here that cannot fail, and especially things 2029 * that must be NULL for the error return to work properly. 2030 */ 2031 adb->magic = 0; 2032 adb->erefcnt = 1; 2033 adb->irefcnt = 0; 2034 adb->nmp = NULL; 2035 adb->nhmp = NULL; 2036 adb->limp = NULL; 2037 adb->emp = NULL; 2038 adb->ahmp = NULL; 2039 adb->aimp = NULL; 2040 adb->afmp = NULL; 2041 adb->task = NULL; 2042 adb->timer = NULL; 2043 adb->mctx = NULL; 2044 adb->view = view; 2045 adb->timermgr = timermgr; 2046 adb->taskmgr = taskmgr; 2047 adb->next_cleanbucket = 0; 2048 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, 2049 DNS_EVENT_ADBCONTROL, shutdown_task, adb, 2050 adb, NULL, NULL); 2051 adb->cevent_sent = ISC_FALSE; 2052 adb->shutting_down = ISC_FALSE; 2053 adb->overmem = ISC_FALSE; 2054 ISC_LIST_INIT(adb->whenshutdown); 2055 2056 isc_mem_attach(mem, &adb->mctx); 2057 2058 result = isc_mutex_init(&adb->lock); 2059 if (result != ISC_R_SUCCESS) 2060 goto fail0b; 2061 2062 result = isc_mutex_init(&adb->mplock); 2063 if (result != ISC_R_SUCCESS) 2064 goto fail0c; 2065 2066 result = isc_mutex_init(&adb->reflock); 2067 if (result != ISC_R_SUCCESS) 2068 goto fail0d; 2069 2070 result = isc_mutex_init(&adb->overmemlock); 2071 if (result != ISC_R_SUCCESS) 2072 goto fail0e; 2073 2074 /* 2075 * Initialize the bucket locks for names and elements. 2076 * May as well initialize the list heads, too. 2077 */ 2078 result = isc_mutexblock_init(adb->namelocks, NBUCKETS); 2079 if (result != ISC_R_SUCCESS) 2080 goto fail1; 2081 for (i = 0; i < NBUCKETS; i++) { 2082 ISC_LIST_INIT(adb->names[i]); 2083 adb->name_sd[i] = ISC_FALSE; 2084 adb->name_refcnt[i] = 0; 2085 adb->irefcnt++; 2086 } 2087 for (i = 0; i < NBUCKETS; i++) { 2088 ISC_LIST_INIT(adb->entries[i]); 2089 adb->entry_sd[i] = ISC_FALSE; 2090 adb->entry_refcnt[i] = 0; 2091 adb->irefcnt++; 2092 } 2093 result = isc_mutexblock_init(adb->entrylocks, NBUCKETS); 2094 if (result != ISC_R_SUCCESS) 2095 goto fail2; 2096 2097 /* 2098 * Memory pools 2099 */ 2100#define MPINIT(t, p, n) do { \ 2101 result = isc_mempool_create(mem, sizeof(t), &(p)); \ 2102 if (result != ISC_R_SUCCESS) \ 2103 goto fail3; \ 2104 isc_mempool_setfreemax((p), FREE_ITEMS); \ 2105 isc_mempool_setfillcount((p), FILL_COUNT); \ 2106 isc_mempool_setname((p), n); \ 2107 isc_mempool_associatelock((p), &adb->mplock); \ 2108} while (0) 2109 2110 MPINIT(dns_adbname_t, adb->nmp, "adbname"); 2111 MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook"); 2112 MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo"); 2113 MPINIT(dns_adbentry_t, adb->emp, "adbentry"); 2114 MPINIT(dns_adbfind_t, adb->ahmp, "adbfind"); 2115 MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo"); 2116 MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch"); 2117 2118#undef MPINIT 2119 2120 /* 2121 * Allocate a timer and a task for our periodic cleanup. 2122 */ 2123 result = isc_task_create(adb->taskmgr, 0, &adb->task); 2124 if (result != ISC_R_SUCCESS) 2125 goto fail3; 2126 isc_task_setname(adb->task, "ADB", adb); 2127 /* 2128 * XXXMLG When this is changed to be a config file option, 2129 */ 2130 isc_interval_set(&adb->tick_interval, CLEAN_SECONDS, 0); 2131 result = isc_timer_create(adb->timermgr, isc_timertype_once, 2132 NULL, &adb->tick_interval, adb->task, 2133 timer_cleanup, adb, &adb->timer); 2134 if (result != ISC_R_SUCCESS) 2135 goto fail3; 2136 2137 DP(ISC_LOG_DEBUG(5), "cleaning interval for adb: " 2138 "%u buckets every %u seconds, %u buckets in system, %u cl.interval", 2139 CLEAN_BUCKETS, CLEAN_SECONDS, NBUCKETS, CLEAN_PERIOD); 2140 2141 /* 2142 * Normal return. 2143 */ 2144 adb->magic = DNS_ADB_MAGIC; 2145 *newadb = adb; 2146 return (ISC_R_SUCCESS); 2147 2148 fail3: 2149 if (adb->task != NULL) 2150 isc_task_detach(&adb->task); 2151 if (adb->timer != NULL) 2152 isc_timer_detach(&adb->timer); 2153 2154 /* clean up entrylocks */ 2155 DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS); 2156 2157 fail2: /* clean up namelocks */ 2158 DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS); 2159 2160 fail1: /* clean up only allocated memory */ 2161 if (adb->nmp != NULL) 2162 isc_mempool_destroy(&adb->nmp); 2163 if (adb->nhmp != NULL) 2164 isc_mempool_destroy(&adb->nhmp); 2165 if (adb->limp != NULL) 2166 isc_mempool_destroy(&adb->limp); 2167 if (adb->emp != NULL) 2168 isc_mempool_destroy(&adb->emp); 2169 if (adb->ahmp != NULL) 2170 isc_mempool_destroy(&adb->ahmp); 2171 if (adb->aimp != NULL) 2172 isc_mempool_destroy(&adb->aimp); 2173 if (adb->afmp != NULL) 2174 isc_mempool_destroy(&adb->afmp); 2175 2176 DESTROYLOCK(&adb->overmemlock); 2177 fail0e: 2178 DESTROYLOCK(&adb->reflock); 2179 fail0d: 2180 DESTROYLOCK(&adb->mplock); 2181 fail0c: 2182 DESTROYLOCK(&adb->lock); 2183 fail0b: 2184 isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t)); 2185 2186 return (result); 2187} 2188 2189void 2190dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) { 2191 2192 REQUIRE(DNS_ADB_VALID(adb)); 2193 REQUIRE(adbx != NULL && *adbx == NULL); 2194 2195 inc_adb_erefcnt(adb); 2196 *adbx = adb; 2197} 2198 2199void 2200dns_adb_detach(dns_adb_t **adbx) { 2201 dns_adb_t *adb; 2202 isc_boolean_t need_exit_check; 2203 2204 REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx)); 2205 2206 adb = *adbx; 2207 *adbx = NULL; 2208 2209 INSIST(adb->erefcnt > 0); 2210 2211 LOCK(&adb->reflock); 2212 adb->erefcnt--; 2213 need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0); 2214 UNLOCK(&adb->reflock); 2215 2216 if (need_exit_check) { 2217 LOCK(&adb->lock); 2218 INSIST(adb->shutting_down); 2219 check_exit(adb); 2220 UNLOCK(&adb->lock); 2221 } 2222} 2223 2224void 2225dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { 2226 isc_task_t *clone; 2227 isc_event_t *event; 2228 isc_boolean_t zeroirefcnt = ISC_FALSE; 2229 2230 /* 2231 * Send '*eventp' to 'task' when 'adb' has shutdown. 2232 */ 2233 2234 REQUIRE(DNS_ADB_VALID(adb)); 2235 REQUIRE(eventp != NULL); 2236 2237 event = *eventp; 2238 *eventp = NULL; 2239 2240 LOCK(&adb->lock); 2241 2242 LOCK(&adb->reflock); 2243 zeroirefcnt = ISC_TF(adb->irefcnt == 0); 2244 2245 if (adb->shutting_down && zeroirefcnt && 2246 isc_mempool_getallocated(adb->ahmp) == 0) { 2247 /* 2248 * We're already shutdown. Send the event. 2249 */ 2250 event->ev_sender = adb; 2251 isc_task_send(task, &event); 2252 } else { 2253 clone = NULL; 2254 isc_task_attach(task, &clone); 2255 event->ev_sender = clone; 2256 ISC_LIST_APPEND(adb->whenshutdown, event, ev_link); 2257 } 2258 2259 UNLOCK(&adb->reflock); 2260 UNLOCK(&adb->lock); 2261} 2262 2263void 2264dns_adb_shutdown(dns_adb_t *adb) { 2265 isc_boolean_t need_check_exit; 2266 2267 /* 2268 * Shutdown 'adb'. 2269 */ 2270 2271 LOCK(&adb->lock); 2272 2273 if (!adb->shutting_down) { 2274 adb->shutting_down = ISC_TRUE; 2275 isc_mem_setwater(adb->mctx, water, adb, 0, 0); 2276 need_check_exit = shutdown_names(adb); 2277 if (!need_check_exit) 2278 need_check_exit = shutdown_entries(adb); 2279 if (need_check_exit) 2280 check_exit(adb); 2281 } 2282 2283 UNLOCK(&adb->lock); 2284} 2285 2286isc_result_t 2287dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, 2288 void *arg, dns_name_t *name, dns_name_t *qname, 2289 dns_rdatatype_t qtype, unsigned int options, 2290 isc_stdtime_t now, dns_name_t *target, 2291 in_port_t port, dns_adbfind_t **findp) 2292{ 2293 dns_adbfind_t *find; 2294 dns_adbname_t *adbname; 2295 int bucket; 2296 isc_boolean_t want_event, start_at_zone, alias, have_address; 2297 isc_result_t result; 2298 unsigned int wanted_addresses; 2299 unsigned int wanted_fetches; 2300 unsigned int query_pending; 2301 2302 REQUIRE(DNS_ADB_VALID(adb)); 2303 if (task != NULL) { 2304 REQUIRE(action != NULL); 2305 } 2306 REQUIRE(name != NULL); 2307 REQUIRE(qname != NULL); 2308 REQUIRE(findp != NULL && *findp == NULL); 2309 REQUIRE(target == NULL || dns_name_hasbuffer(target)); 2310 2311 REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0); 2312 2313 result = ISC_R_UNEXPECTED; 2314 wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK); 2315 wanted_fetches = 0; 2316 query_pending = 0; 2317 want_event = ISC_FALSE; 2318 start_at_zone = ISC_FALSE; 2319 alias = ISC_FALSE; 2320 2321 if (now == 0) 2322 isc_stdtime_get(&now); 2323 2324 /* 2325 * XXXMLG Move this comment somewhere else! 2326 * 2327 * Look up the name in our internal database. 2328 * 2329 * Possibilities: Note that these are not always exclusive. 2330 * 2331 * No name found. In this case, allocate a new name header and 2332 * an initial namehook or two. If any of these allocations 2333 * fail, clean up and return ISC_R_NOMEMORY. 2334 * 2335 * Name found, valid addresses present. Allocate one addrinfo 2336 * structure for each found and append it to the linked list 2337 * of addresses for this header. 2338 * 2339 * Name found, queries pending. In this case, if a task was 2340 * passed in, allocate a job id, attach it to the name's job 2341 * list and remember to tell the caller that there will be 2342 * more info coming later. 2343 */ 2344 2345 find = new_adbfind(adb); 2346 if (find == NULL) 2347 return (ISC_R_NOMEMORY); 2348 2349 find->port = port; 2350 2351 /* 2352 * Remember what types of addresses we are interested in. 2353 */ 2354 find->options = options; 2355 find->flags |= wanted_addresses; 2356 if (FIND_WANTEVENT(find)) { 2357 REQUIRE(task != NULL); 2358 } 2359 2360 /* 2361 * Try to see if we know anything about this name at all. 2362 */ 2363 bucket = DNS_ADB_INVALIDBUCKET; 2364 adbname = find_name_and_lock(adb, name, find->options, &bucket); 2365 if (adb->name_sd[bucket]) { 2366 DP(DEF_LEVEL, 2367 "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN"); 2368 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE); 2369 result = ISC_R_SHUTTINGDOWN; 2370 goto out; 2371 } 2372 2373 /* 2374 * Nothing found. Allocate a new adbname structure for this name. 2375 */ 2376 if (adbname == NULL) { 2377 adbname = new_adbname(adb, name); 2378 if (adbname == NULL) { 2379 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE); 2380 result = ISC_R_NOMEMORY; 2381 goto out; 2382 } 2383 link_name(adb, bucket, adbname); 2384 if (FIND_HINTOK(find)) 2385 adbname->flags |= NAME_HINT_OK; 2386 if (FIND_GLUEOK(find)) 2387 adbname->flags |= NAME_GLUE_OK; 2388 if (FIND_STARTATZONE(find)) 2389 adbname->flags |= NAME_STARTATZONE; 2390 } 2391 2392 /* 2393 * Expire old entries, etc. 2394 */ 2395 RUNTIME_CHECK(check_expire_namehooks(adbname, now, adb->overmem) == 2396 ISC_FALSE); 2397 2398 /* 2399 * Do we know that the name is an alias? 2400 */ 2401 if (!EXPIRE_OK(adbname->expire_target, now)) { 2402 /* 2403 * Yes, it is. 2404 */ 2405 DP(DEF_LEVEL, 2406 "dns_adb_createfind: name %p is an alias (cached)", 2407 adbname); 2408 alias = ISC_TRUE; 2409 goto post_copy; 2410 } 2411 2412 /* 2413 * Try to populate the name from the database and/or 2414 * start fetches. First try looking for an A record 2415 * in the database. 2416 */ 2417 if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now) 2418 && WANT_INET(wanted_addresses)) { 2419 result = dbfind_name(adbname, now, dns_rdatatype_a); 2420 if (result == ISC_R_SUCCESS) { 2421 DP(DEF_LEVEL, 2422 "dns_adb_createfind: found A for name %p in db", 2423 adbname); 2424 goto v6; 2425 } 2426 2427 /* 2428 * Did we get a CNAME or DNAME? 2429 */ 2430 if (result == DNS_R_ALIAS) { 2431 DP(DEF_LEVEL, 2432 "dns_adb_createfind: name %p is an alias", 2433 adbname); 2434 alias = ISC_TRUE; 2435 goto post_copy; 2436 } 2437 2438 /* 2439 * If the name doesn't exist at all, don't bother with 2440 * v6 queries; they won't work. 2441 * 2442 * If the name does exist but we didn't get our data, go 2443 * ahead and try AAAA. 2444 * 2445 * If the result is neither of these, try a fetch for A. 2446 */ 2447 if (NXDOMAIN_RESULT(result)) 2448 goto fetch; 2449 else if (NXRRSET_RESULT(result)) 2450 goto v6; 2451 2452 if (!NAME_FETCH_V4(adbname)) 2453 wanted_fetches |= DNS_ADBFIND_INET; 2454 } 2455 2456 v6: 2457 if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now) 2458 && WANT_INET6(wanted_addresses)) { 2459 result = dbfind_name(adbname, now, dns_rdatatype_aaaa); 2460 if (result == ISC_R_SUCCESS) { 2461 DP(DEF_LEVEL, 2462 "dns_adb_createfind: found AAAA for name %p", 2463 adbname); 2464 goto fetch; 2465 } 2466 2467 /* 2468 * Did we get a CNAME or DNAME? 2469 */ 2470 if (result == DNS_R_ALIAS) { 2471 DP(DEF_LEVEL, 2472 "dns_adb_createfind: name %p is an alias", 2473 adbname); 2474 alias = ISC_TRUE; 2475 goto post_copy; 2476 } 2477 2478 /* 2479 * Listen to negative cache hints, and don't start 2480 * another query. 2481 */ 2482 if (NCACHE_RESULT(result) || AUTH_NX(result)) 2483 goto fetch; 2484 2485 if (!NAME_FETCH_V6(adbname)) 2486 wanted_fetches |= DNS_ADBFIND_INET6; 2487 } 2488 2489 fetch: 2490 if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) || 2491 (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname))) 2492 have_address = ISC_TRUE; 2493 else 2494 have_address = ISC_FALSE; 2495 if (wanted_fetches != 0 && 2496 ! (FIND_AVOIDFETCHES(find) && have_address)) { 2497 /* 2498 * We're missing at least one address family. Either the 2499 * caller hasn't instructed us to avoid fetches, or we don't 2500 * know anything about any of the address families that would 2501 * be acceptable so we have to launch fetches. 2502 */ 2503 2504 if (FIND_STARTATZONE(find)) 2505 start_at_zone = ISC_TRUE; 2506 2507 /* 2508 * Start V4. 2509 */ 2510 if (WANT_INET(wanted_fetches) && 2511 fetch_name(adbname, start_at_zone, 2512 dns_rdatatype_a) == ISC_R_SUCCESS) { 2513 DP(DEF_LEVEL, 2514 "dns_adb_createfind: started A fetch for name %p", 2515 adbname); 2516 } 2517 2518 /* 2519 * Start V6. 2520 */ 2521 if (WANT_INET6(wanted_fetches) && 2522 fetch_name(adbname, start_at_zone, 2523 dns_rdatatype_aaaa) == ISC_R_SUCCESS) { 2524 DP(DEF_LEVEL, 2525 "dns_adb_createfind: " 2526 "started AAAA fetch for name %p", 2527 adbname); 2528 } 2529 } 2530 2531 /* 2532 * Run through the name and copy out the bits we are 2533 * interested in. 2534 */ 2535 copy_namehook_lists(adb, find, qname, qtype, adbname, now); 2536 2537 post_copy: 2538 if (NAME_FETCH_V4(adbname)) 2539 query_pending |= DNS_ADBFIND_INET; 2540 if (NAME_FETCH_V6(adbname)) 2541 query_pending |= DNS_ADBFIND_INET6; 2542 2543 /* 2544 * Attach to the name's query list if there are queries 2545 * already running, and we have been asked to. 2546 */ 2547 want_event = ISC_TRUE; 2548 if (!FIND_WANTEVENT(find)) 2549 want_event = ISC_FALSE; 2550 if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find)) 2551 want_event = ISC_FALSE; 2552 if ((wanted_addresses & query_pending) == 0) 2553 want_event = ISC_FALSE; 2554 if (alias) 2555 want_event = ISC_FALSE; 2556 if (want_event) { 2557 find->adbname = adbname; 2558 find->name_bucket = bucket; 2559 ISC_LIST_APPEND(adbname->finds, find, plink); 2560 find->query_pending = (query_pending & wanted_addresses); 2561 find->flags &= ~DNS_ADBFIND_ADDRESSMASK; 2562 find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK); 2563 DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p", 2564 find, adbname); 2565 } else { 2566 /* 2567 * Remove the flag so the caller knows there will never 2568 * be an event, and set internal flags to fake that 2569 * the event was sent and freed, so dns_adb_destroyfind() will 2570 * do the right thing. 2571 */ 2572 find->query_pending = (query_pending & wanted_addresses); 2573 find->options &= ~DNS_ADBFIND_WANTEVENT; 2574 find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED); 2575 find->flags &= ~DNS_ADBFIND_ADDRESSMASK; 2576 } 2577 2578 find->partial_result |= (adbname->partial_result & wanted_addresses); 2579 if (alias) { 2580 if (target != NULL) { 2581 result = dns_name_copy(&adbname->target, target, NULL); 2582 if (result != ISC_R_SUCCESS) 2583 goto out; 2584 } 2585 result = DNS_R_ALIAS; 2586 } else 2587 result = ISC_R_SUCCESS; 2588 2589 /* 2590 * Copy out error flags from the name structure into the find. 2591 */ 2592 find->result_v4 = find_err_map[adbname->fetch_err]; 2593 find->result_v6 = find_err_map[adbname->fetch6_err]; 2594 2595 out: 2596 if (find != NULL) { 2597 *findp = find; 2598 2599 if (want_event) { 2600 isc_task_t *taskp; 2601 2602 INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0); 2603 taskp = NULL; 2604 isc_task_attach(task, &taskp); 2605 find->event.ev_sender = taskp; 2606 find->event.ev_action = action; 2607 find->event.ev_arg = arg; 2608 } 2609 } 2610 2611 UNLOCK(&adb->namelocks[bucket]); 2612 2613 return (result); 2614} 2615 2616void 2617dns_adb_destroyfind(dns_adbfind_t **findp) { 2618 dns_adbfind_t *find; 2619 dns_adbentry_t *entry; 2620 dns_adbaddrinfo_t *ai; 2621 int bucket; 2622 dns_adb_t *adb; 2623 2624 REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp)); 2625 find = *findp; 2626 *findp = NULL; 2627 2628 LOCK(&find->lock); 2629 2630 DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find); 2631 2632 adb = find->adb; 2633 REQUIRE(DNS_ADB_VALID(adb)); 2634 2635 REQUIRE(FIND_EVENTFREED(find)); 2636 2637 bucket = find->name_bucket; 2638 INSIST(bucket == DNS_ADB_INVALIDBUCKET); 2639 2640 UNLOCK(&find->lock); 2641 2642 /* 2643 * The find doesn't exist on any list, and nothing is locked. 2644 * Return the find to the memory pool, and decrement the adb's 2645 * reference count. 2646 */ 2647 ai = ISC_LIST_HEAD(find->list); 2648 while (ai != NULL) { 2649 ISC_LIST_UNLINK(find->list, ai, publink); 2650 entry = ai->entry; 2651 ai->entry = NULL; 2652 INSIST(DNS_ADBENTRY_VALID(entry)); 2653 RUNTIME_CHECK(dec_entry_refcnt(adb, entry, ISC_TRUE) == 2654 ISC_FALSE); 2655 free_adbaddrinfo(adb, &ai); 2656 ai = ISC_LIST_HEAD(find->list); 2657 } 2658 2659 /* 2660 * WARNING: The find is freed with the adb locked. This is done 2661 * to avoid a race condition where we free the find, some other 2662 * thread tests to see if it should be destroyed, detects it should 2663 * be, destroys it, and then we try to lock it for our check, but the 2664 * lock is destroyed. 2665 */ 2666 LOCK(&adb->lock); 2667 if (free_adbfind(adb, &find)) 2668 check_exit(adb); 2669 UNLOCK(&adb->lock); 2670} 2671 2672void 2673dns_adb_cancelfind(dns_adbfind_t *find) { 2674 isc_event_t *ev; 2675 isc_task_t *task; 2676 dns_adb_t *adb; 2677 int bucket; 2678 int unlock_bucket; 2679 2680 LOCK(&find->lock); 2681 2682 DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find); 2683 2684 adb = find->adb; 2685 REQUIRE(DNS_ADB_VALID(adb)); 2686 2687 REQUIRE(!FIND_EVENTFREED(find)); 2688 REQUIRE(FIND_WANTEVENT(find)); 2689 2690 bucket = find->name_bucket; 2691 if (bucket == DNS_ADB_INVALIDBUCKET) 2692 goto cleanup; 2693 2694 /* 2695 * We need to get the adbname's lock to unlink the find. 2696 */ 2697 unlock_bucket = bucket; 2698 violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]); 2699 bucket = find->name_bucket; 2700 if (bucket != DNS_ADB_INVALIDBUCKET) { 2701 ISC_LIST_UNLINK(find->adbname->finds, find, plink); 2702 find->adbname = NULL; 2703 find->name_bucket = DNS_ADB_INVALIDBUCKET; 2704 } 2705 UNLOCK(&adb->namelocks[unlock_bucket]); 2706 bucket = DNS_ADB_INVALIDBUCKET; 2707 2708 cleanup: 2709 2710 if (!FIND_EVENTSENT(find)) { 2711 ev = &find->event; 2712 task = ev->ev_sender; 2713 ev->ev_sender = find; 2714 ev->ev_type = DNS_EVENT_ADBCANCELED; 2715 ev->ev_destroy = event_free; 2716 ev->ev_destroy_arg = find; 2717 find->result_v4 = ISC_R_CANCELED; 2718 find->result_v6 = ISC_R_CANCELED; 2719 2720 DP(DEF_LEVEL, "sending event %p to task %p for find %p", 2721 ev, task, find); 2722 2723 isc_task_sendanddetach(&task, (isc_event_t **)&ev); 2724 } 2725 2726 UNLOCK(&find->lock); 2727} 2728 2729void 2730dns_adb_dump(dns_adb_t *adb, FILE *f) { 2731 int i; 2732 isc_stdtime_t now; 2733 2734 REQUIRE(DNS_ADB_VALID(adb)); 2735 REQUIRE(f != NULL); 2736 2737 /* 2738 * Lock the adb itself, lock all the name buckets, then lock all 2739 * the entry buckets. This should put the adb into a state where 2740 * nothing can change, so we can iterate through everything and 2741 * print at our leisure. 2742 */ 2743 2744 LOCK(&adb->lock); 2745 isc_stdtime_get(&now); 2746 2747 for (i = 0; i < NBUCKETS; i++) 2748 RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE); 2749 for (i = 0; i < NBUCKETS; i++) 2750 RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE); 2751 2752 dump_adb(adb, f, ISC_FALSE, now); 2753 UNLOCK(&adb->lock); 2754} 2755 2756static void 2757dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) { 2758 if (value == INT_MAX) 2759 return; 2760 fprintf(f, " [%s TTL %d]", legend, value - now); 2761} 2762 2763static void 2764dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) { 2765 int i; 2766 dns_adbname_t *name; 2767 dns_adbentry_t *entry; 2768 2769 fprintf(f, ";\n; Address database dump\n;\n"); 2770 if (debug) 2771 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n", 2772 adb, adb->erefcnt, adb->irefcnt, 2773 isc_mempool_getallocated(adb->nhmp)); 2774 2775 for (i = 0; i < NBUCKETS; i++) 2776 LOCK(&adb->namelocks[i]); 2777 for (i = 0; i < NBUCKETS; i++) 2778 LOCK(&adb->entrylocks[i]); 2779 2780 /* 2781 * Dump the names 2782 */ 2783 for (i = 0; i < NBUCKETS; i++) { 2784 name = ISC_LIST_HEAD(adb->names[i]); 2785 if (name == NULL) 2786 continue; 2787 if (debug) 2788 fprintf(f, "; bucket %d\n", i); 2789 for (; 2790 name != NULL; 2791 name = ISC_LIST_NEXT(name, plink)) 2792 { 2793 if (debug) 2794 fprintf(f, "; name %p (flags %08x)\n", 2795 name, name->flags); 2796 2797 fprintf(f, "; "); 2798 print_dns_name(f, &name->name); 2799 if (dns_name_countlabels(&name->target) > 0) { 2800 fprintf(f, " alias "); 2801 print_dns_name(f, &name->target); 2802 } 2803 2804 dump_ttl(f, "v4", name->expire_v4, now); 2805 dump_ttl(f, "v6", name->expire_v6, now); 2806 dump_ttl(f, "target", name->expire_target, now); 2807 2808 fprintf(f, " [v4 %s] [v6 %s]", 2809 errnames[name->fetch_err], 2810 errnames[name->fetch6_err]); 2811 2812 fprintf(f, "\n"); 2813 2814 print_namehook_list(f, "v4", &name->v4, debug, now); 2815 print_namehook_list(f, "v6", &name->v6, debug, now); 2816 2817 if (debug) 2818 print_fetch_list(f, name); 2819 if (debug) 2820 print_find_list(f, name); 2821 2822 } 2823 } 2824 2825 fprintf(f, ";\n; Unassociated entries\n;\n"); 2826 2827 for (i = 0; i < NBUCKETS; i++) { 2828 entry = ISC_LIST_HEAD(adb->entries[i]); 2829 while (entry != NULL) { 2830 if (entry->refcnt == 0) 2831 dump_entry(f, entry, debug, now); 2832 entry = ISC_LIST_NEXT(entry, plink); 2833 } 2834 } 2835 2836 /* 2837 * Unlock everything 2838 */ 2839 for (i = 0; i < NBUCKETS; i++) 2840 UNLOCK(&adb->entrylocks[i]); 2841 for (i = 0; i < NBUCKETS; i++) 2842 UNLOCK(&adb->namelocks[i]); 2843} 2844 2845static void 2846dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug, 2847 isc_stdtime_t now) 2848{ 2849 char addrbuf[ISC_NETADDR_FORMATSIZE]; 2850 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 2851 isc_netaddr_t netaddr; 2852 dns_adblameinfo_t *li; 2853 2854 isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr); 2855 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf)); 2856 2857 if (debug) 2858 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt); 2859 2860 fprintf(f, ";\t%s [srtt %u] [flags %08x]", 2861 addrbuf, entry->srtt, entry->flags); 2862 if (entry->expires != 0) 2863 fprintf(f, " [ttl %d]", entry->expires - now); 2864 fprintf(f, "\n"); 2865 for (li = ISC_LIST_HEAD(entry->lameinfo); 2866 li != NULL; 2867 li = ISC_LIST_NEXT(li, plink)) { 2868 fprintf(f, ";\t\t"); 2869 print_dns_name(f, &li->qname); 2870 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf)); 2871 fprintf(f, " %s [lame TTL %d]\n", typebuf, 2872 li->lame_timer - now); 2873 } 2874} 2875 2876void 2877dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) { 2878 char tmp[512]; 2879 const char *tmpp; 2880 dns_adbaddrinfo_t *ai; 2881 isc_sockaddr_t *sa; 2882 2883 /* 2884 * Not used currently, in the API Just In Case we 2885 * want to dump out the name and/or entries too. 2886 */ 2887 2888 LOCK(&find->lock); 2889 2890 fprintf(f, ";Find %p\n", find); 2891 fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n", 2892 find->query_pending, find->partial_result, 2893 find->options, find->flags); 2894 fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n", 2895 find->name_bucket, find->adbname, find->event.ev_sender); 2896 2897 ai = ISC_LIST_HEAD(find->list); 2898 if (ai != NULL) 2899 fprintf(f, "\tAddresses:\n"); 2900 while (ai != NULL) { 2901 sa = &ai->sockaddr; 2902 switch (sa->type.sa.sa_family) { 2903 case AF_INET: 2904 tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr, 2905 tmp, sizeof(tmp)); 2906 break; 2907 case AF_INET6: 2908 tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr, 2909 tmp, sizeof(tmp)); 2910 break; 2911 default: 2912 tmpp = "UnkFamily"; 2913 } 2914 2915 if (tmpp == NULL) 2916 tmpp = "BadAddress"; 2917 2918 fprintf(f, "\t\tentry %p, flags %08x" 2919 " srtt %u addr %s\n", 2920 ai->entry, ai->flags, ai->srtt, tmpp); 2921 2922 ai = ISC_LIST_NEXT(ai, publink); 2923 } 2924 2925 UNLOCK(&find->lock); 2926} 2927 2928static void 2929print_dns_name(FILE *f, dns_name_t *name) { 2930 char buf[DNS_NAME_FORMATSIZE]; 2931 2932 INSIST(f != NULL); 2933 2934 dns_name_format(name, buf, sizeof(buf)); 2935 fprintf(f, "%s", buf); 2936} 2937 2938static void 2939print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list, 2940 isc_boolean_t debug, isc_stdtime_t now) 2941{ 2942 dns_adbnamehook_t *nh; 2943 2944 for (nh = ISC_LIST_HEAD(*list); 2945 nh != NULL; 2946 nh = ISC_LIST_NEXT(nh, plink)) 2947 { 2948 if (debug) 2949 fprintf(f, ";\tHook(%s) %p\n", legend, nh); 2950 dump_entry(f, nh->entry, debug, now); 2951 } 2952} 2953 2954static inline void 2955print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) { 2956 fprintf(f, "\t\tFetch(%s): %p -> { nh %p, entry %p, fetch %p }\n", 2957 type, ft, ft->namehook, ft->entry, ft->fetch); 2958} 2959 2960static void 2961print_fetch_list(FILE *f, dns_adbname_t *n) { 2962 if (NAME_FETCH_A(n)) 2963 print_fetch(f, n->fetch_a, "A"); 2964 if (NAME_FETCH_AAAA(n)) 2965 print_fetch(f, n->fetch_aaaa, "AAAA"); 2966} 2967 2968static void 2969print_find_list(FILE *f, dns_adbname_t *name) { 2970 dns_adbfind_t *find; 2971 2972 find = ISC_LIST_HEAD(name->finds); 2973 while (find != NULL) { 2974 dns_adb_dumpfind(find, f); 2975 find = ISC_LIST_NEXT(find, plink); 2976 } 2977} 2978 2979static isc_result_t 2980dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) 2981{ 2982 isc_result_t result; 2983 dns_rdataset_t rdataset; 2984 dns_adb_t *adb; 2985 dns_fixedname_t foundname; 2986 dns_name_t *fname; 2987 2988 INSIST(DNS_ADBNAME_VALID(adbname)); 2989 adb = adbname->adb; 2990 INSIST(DNS_ADB_VALID(adb)); 2991 INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa); 2992 2993 dns_fixedname_init(&foundname); 2994 fname = dns_fixedname_name(&foundname); 2995 dns_rdataset_init(&rdataset); 2996 2997 if (rdtype == dns_rdatatype_a) 2998 adbname->fetch_err = FIND_ERR_UNEXPECTED; 2999 else 3000 adbname->fetch6_err = FIND_ERR_UNEXPECTED; 3001 3002 result = dns_view_find(adb->view, &adbname->name, rdtype, now, 3003 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0, 3004 ISC_TF(NAME_HINTOK(adbname)), 3005 NULL, NULL, fname, &rdataset, NULL); 3006 3007 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 3008 switch (result) { 3009 case DNS_R_GLUE: 3010 case DNS_R_HINT: 3011 case ISC_R_SUCCESS: 3012 /* 3013 * Found in the database. Even if we can't copy out 3014 * any information, return success, or else a fetch 3015 * will be made, which will only make things worse. 3016 */ 3017 if (rdtype == dns_rdatatype_a) 3018 adbname->fetch_err = FIND_ERR_SUCCESS; 3019 else 3020 adbname->fetch6_err = FIND_ERR_SUCCESS; 3021 result = import_rdataset(adbname, &rdataset, now); 3022 break; 3023 case DNS_R_NXDOMAIN: 3024 case DNS_R_NXRRSET: 3025 /* 3026 * We're authoritative and the data doesn't exist. 3027 * Make up a negative cache entry so we don't ask again 3028 * for a while. 3029 * 3030 * XXXRTH What time should we use? I'm putting in 30 seconds 3031 * for now. 3032 */ 3033 if (rdtype == dns_rdatatype_a) { 3034 adbname->expire_v4 = now + 30; 3035 DP(NCACHE_LEVEL, 3036 "adb name %p: Caching auth negative entry for A", 3037 adbname); 3038 if (result == DNS_R_NXDOMAIN) 3039 adbname->fetch_err = FIND_ERR_NXDOMAIN; 3040 else 3041 adbname->fetch_err = FIND_ERR_NXRRSET; 3042 } else { 3043 DP(NCACHE_LEVEL, 3044 "adb name %p: Caching auth negative entry for AAAA", 3045 adbname); 3046 adbname->expire_v6 = now + 30; 3047 if (result == DNS_R_NXDOMAIN) 3048 adbname->fetch6_err = FIND_ERR_NXDOMAIN; 3049 else 3050 adbname->fetch6_err = FIND_ERR_NXRRSET; 3051 } 3052 break; 3053 case DNS_R_NCACHENXDOMAIN: 3054 case DNS_R_NCACHENXRRSET: 3055 /* 3056 * We found a negative cache entry. Pull the TTL from it 3057 * so we won't ask again for a while. 3058 */ 3059 rdataset.ttl = ttlclamp(rdataset.ttl); 3060 if (rdtype == dns_rdatatype_a) { 3061 adbname->expire_v4 = rdataset.ttl + now; 3062 if (result == DNS_R_NCACHENXDOMAIN) 3063 adbname->fetch_err = FIND_ERR_NXDOMAIN; 3064 else 3065 adbname->fetch_err = FIND_ERR_NXRRSET; 3066 DP(NCACHE_LEVEL, 3067 "adb name %p: Caching negative entry for A (ttl %u)", 3068 adbname, rdataset.ttl); 3069 } else { 3070 DP(NCACHE_LEVEL, 3071 "adb name %p: Caching negative entry for AAAA (ttl %u)", 3072 adbname, rdataset.ttl); 3073 adbname->expire_v6 = rdataset.ttl + now; 3074 if (result == DNS_R_NCACHENXDOMAIN) 3075 adbname->fetch6_err = FIND_ERR_NXDOMAIN; 3076 else 3077 adbname->fetch6_err = FIND_ERR_NXRRSET; 3078 } 3079 break; 3080 case DNS_R_CNAME: 3081 case DNS_R_DNAME: 3082 /* 3083 * Clear the hint and glue flags, so this will match 3084 * more often. 3085 */ 3086 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK); 3087 3088 rdataset.ttl = ttlclamp(rdataset.ttl); 3089 clean_target(adb, &adbname->target); 3090 adbname->expire_target = INT_MAX; 3091 result = set_target(adb, &adbname->name, fname, &rdataset, 3092 &adbname->target); 3093 if (result == ISC_R_SUCCESS) { 3094 result = DNS_R_ALIAS; 3095 DP(NCACHE_LEVEL, 3096 "adb name %p: caching alias target", 3097 adbname); 3098 adbname->expire_target = rdataset.ttl + now; 3099 } 3100 if (rdtype == dns_rdatatype_a) 3101 adbname->fetch_err = FIND_ERR_SUCCESS; 3102 else 3103 adbname->fetch6_err = FIND_ERR_SUCCESS; 3104 break; 3105 } 3106 3107 if (dns_rdataset_isassociated(&rdataset)) 3108 dns_rdataset_disassociate(&rdataset); 3109 3110 return (result); 3111} 3112 3113static void 3114fetch_callback(isc_task_t *task, isc_event_t *ev) { 3115 dns_fetchevent_t *dev; 3116 dns_adbname_t *name; 3117 dns_adb_t *adb; 3118 dns_adbfetch_t *fetch; 3119 int bucket; 3120 isc_eventtype_t ev_status; 3121 isc_stdtime_t now; 3122 isc_result_t result; 3123 unsigned int address_type; 3124 isc_boolean_t want_check_exit = ISC_FALSE; 3125 3126 UNUSED(task); 3127 3128 INSIST(ev->ev_type == DNS_EVENT_FETCHDONE); 3129 dev = (dns_fetchevent_t *)ev; 3130 name = ev->ev_arg; 3131 INSIST(DNS_ADBNAME_VALID(name)); 3132 adb = name->adb; 3133 INSIST(DNS_ADB_VALID(adb)); 3134 3135 bucket = name->lock_bucket; 3136 LOCK(&adb->namelocks[bucket]); 3137 3138 INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name)); 3139 address_type = 0; 3140 if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) { 3141 address_type = DNS_ADBFIND_INET; 3142 fetch = name->fetch_a; 3143 name->fetch_a = NULL; 3144 } else if (NAME_FETCH_AAAA(name) 3145 && (name->fetch_aaaa->fetch == dev->fetch)) { 3146 address_type = DNS_ADBFIND_INET6; 3147 fetch = name->fetch_aaaa; 3148 name->fetch_aaaa = NULL; 3149 } else 3150 fetch = NULL; 3151 3152 INSIST(address_type != 0 && fetch != NULL); 3153 3154 dns_resolver_destroyfetch(&fetch->fetch); 3155 dev->fetch = NULL; 3156 3157 ev_status = DNS_EVENT_ADBNOMOREADDRESSES; 3158 3159 /* 3160 * Cleanup things we don't care about. 3161 */ 3162 if (dev->node != NULL) 3163 dns_db_detachnode(dev->db, &dev->node); 3164 if (dev->db != NULL) 3165 dns_db_detach(&dev->db); 3166 3167 /* 3168 * If this name is marked as dead, clean up, throwing away 3169 * potentially good data. 3170 */ 3171 if (NAME_DEAD(name)) { 3172 free_adbfetch(adb, &fetch); 3173 isc_event_free(&ev); 3174 3175 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED); 3176 3177 UNLOCK(&adb->namelocks[bucket]); 3178 3179 if (want_check_exit) { 3180 LOCK(&adb->lock); 3181 check_exit(adb); 3182 UNLOCK(&adb->lock); 3183 } 3184 3185 return; 3186 } 3187 3188 isc_stdtime_get(&now); 3189 3190 /* 3191 * If we got a negative cache response, remember it. 3192 */ 3193 if (NCACHE_RESULT(dev->result)) { 3194 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl); 3195 if (address_type == DNS_ADBFIND_INET) { 3196 DP(NCACHE_LEVEL, "adb fetch name %p: " 3197 "caching negative entry for A (ttl %u)", 3198 name, dev->rdataset->ttl); 3199 name->expire_v4 = ISC_MIN(name->expire_v4, 3200 dev->rdataset->ttl + now); 3201 if (dev->result == DNS_R_NCACHENXDOMAIN) 3202 name->fetch_err = FIND_ERR_NXDOMAIN; 3203 else 3204 name->fetch_err = FIND_ERR_NXRRSET; 3205 } else { 3206 DP(NCACHE_LEVEL, "adb fetch name %p: " 3207 "caching negative entry for AAAA (ttl %u)", 3208 name, dev->rdataset->ttl); 3209 name->expire_v6 = ISC_MIN(name->expire_v6, 3210 dev->rdataset->ttl + now); 3211 if (dev->result == DNS_R_NCACHENXDOMAIN) 3212 name->fetch6_err = FIND_ERR_NXDOMAIN; 3213 else 3214 name->fetch6_err = FIND_ERR_NXRRSET; 3215 } 3216 goto out; 3217 } 3218 3219 /* 3220 * Handle CNAME/DNAME. 3221 */ 3222 if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) { 3223 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl); 3224 clean_target(adb, &name->target); 3225 name->expire_target = INT_MAX; 3226 result = set_target(adb, &name->name, 3227 dns_fixedname_name(&dev->foundname), 3228 dev->rdataset, 3229 &name->target); 3230 if (result == ISC_R_SUCCESS) { 3231 DP(NCACHE_LEVEL, 3232 "adb fetch name %p: caching alias target", 3233 name); 3234 name->expire_target = dev->rdataset->ttl + now; 3235 } 3236 goto check_result; 3237 } 3238 3239 /* 3240 * Did we get back junk? If so, and there are no more fetches 3241 * sitting out there, tell all the finds about it. 3242 */ 3243 if (dev->result != ISC_R_SUCCESS) { 3244 char buf[DNS_NAME_FORMATSIZE]; 3245 3246 dns_name_format(&name->name, buf, sizeof(buf)); 3247 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", 3248 buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", 3249 dns_result_totext(dev->result)); 3250 /* XXXMLG Don't pound on bad servers. */ 3251 if (address_type == DNS_ADBFIND_INET) { 3252 name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); 3253 name->fetch_err = FIND_ERR_FAILURE; 3254 } else { 3255 name->expire_v6 = ISC_MIN(name->expire_v6, now + 300); 3256 name->fetch6_err = FIND_ERR_FAILURE; 3257 } 3258 goto out; 3259 } 3260 3261 /* 3262 * We got something potentially useful. 3263 */ 3264 result = import_rdataset(name, &fetch->rdataset, now); 3265 3266 check_result: 3267 if (result == ISC_R_SUCCESS) { 3268 ev_status = DNS_EVENT_ADBMOREADDRESSES; 3269 if (address_type == DNS_ADBFIND_INET) 3270 name->fetch_err = FIND_ERR_SUCCESS; 3271 else 3272 name->fetch6_err = FIND_ERR_SUCCESS; 3273 } 3274 3275 out: 3276 free_adbfetch(adb, &fetch); 3277 isc_event_free(&ev); 3278 3279 clean_finds_at_name(name, ev_status, address_type); 3280 3281 UNLOCK(&adb->namelocks[bucket]); 3282} 3283 3284static isc_result_t 3285fetch_name(dns_adbname_t *adbname, 3286 isc_boolean_t start_at_zone, 3287 dns_rdatatype_t type) 3288{ 3289 isc_result_t result; 3290 dns_adbfetch_t *fetch = NULL; 3291 dns_adb_t *adb; 3292 dns_fixedname_t fixed; 3293 dns_name_t *name; 3294 dns_rdataset_t rdataset; 3295 dns_rdataset_t *nameservers; 3296 unsigned int options; 3297 3298 INSIST(DNS_ADBNAME_VALID(adbname)); 3299 adb = adbname->adb; 3300 INSIST(DNS_ADB_VALID(adb)); 3301 3302 INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) || 3303 (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname))); 3304 3305 adbname->fetch_err = FIND_ERR_NOTFOUND; 3306 3307 name = NULL; 3308 nameservers = NULL; 3309 dns_rdataset_init(&rdataset); 3310 3311 options = DNS_FETCHOPT_NOVALIDATE; 3312 if (start_at_zone) { 3313 DP(ENTER_LEVEL, 3314 "fetch_name: starting at zone for name %p", 3315 adbname); 3316 dns_fixedname_init(&fixed); 3317 name = dns_fixedname_name(&fixed); 3318 result = dns_view_findzonecut2(adb->view, &adbname->name, name, 3319 0, 0, ISC_TRUE, ISC_FALSE, 3320 &rdataset, NULL); 3321 if (result != ISC_R_SUCCESS && result != DNS_R_HINT) 3322 goto cleanup; 3323 nameservers = &rdataset; 3324 options |= DNS_FETCHOPT_UNSHARED; 3325 } 3326 3327 fetch = new_adbfetch(adb); 3328 if (fetch == NULL) { 3329 result = ISC_R_NOMEMORY; 3330 goto cleanup; 3331 } 3332 3333 result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, 3334 type, name, nameservers, NULL, 3335 options, adb->task, fetch_callback, 3336 adbname, &fetch->rdataset, NULL, 3337 &fetch->fetch); 3338 if (result != ISC_R_SUCCESS) 3339 goto cleanup; 3340 3341 if (type == dns_rdatatype_a) 3342 adbname->fetch_a = fetch; 3343 else 3344 adbname->fetch_aaaa = fetch; 3345 fetch = NULL; /* Keep us from cleaning this up below. */ 3346 3347 cleanup: 3348 if (fetch != NULL) 3349 free_adbfetch(adb, &fetch); 3350 if (dns_rdataset_isassociated(&rdataset)) 3351 dns_rdataset_disassociate(&rdataset); 3352 3353 return (result); 3354} 3355 3356/* 3357 * XXXMLG Needs to take a find argument and an address info, no zone or adb, 3358 * since these can be extracted from the find itself. 3359 */ 3360isc_result_t 3361dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname, 3362 dns_rdatatype_t qtype, isc_stdtime_t expire_time) 3363{ 3364 dns_adblameinfo_t *li; 3365 int bucket; 3366 isc_result_t result = ISC_R_SUCCESS; 3367 3368 REQUIRE(DNS_ADB_VALID(adb)); 3369 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 3370 REQUIRE(qname != NULL); 3371 3372 bucket = addr->entry->lock_bucket; 3373 LOCK(&adb->entrylocks[bucket]); 3374 li = ISC_LIST_HEAD(addr->entry->lameinfo); 3375 while (li != NULL && 3376 (li->qtype != qtype || !dns_name_equal(qname, &li->qname))) 3377 li = ISC_LIST_NEXT(li, plink); 3378 if (li != NULL) { 3379 if (expire_time > li->lame_timer) 3380 li->lame_timer = expire_time; 3381 goto unlock; 3382 } 3383 li = new_adblameinfo(adb, qname, qtype); 3384 if (li == NULL) { 3385 result = ISC_R_NOMEMORY; 3386 goto unlock; 3387 } 3388 3389 li->lame_timer = expire_time; 3390 3391 ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink); 3392 unlock: 3393 UNLOCK(&adb->entrylocks[bucket]); 3394 3395 return (result); 3396} 3397 3398void 3399dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, 3400 unsigned int rtt, unsigned int factor) 3401{ 3402 int bucket; 3403 unsigned int new_srtt; 3404 isc_stdtime_t now; 3405 3406 REQUIRE(DNS_ADB_VALID(adb)); 3407 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 3408 REQUIRE(factor <= 10); 3409 3410 bucket = addr->entry->lock_bucket; 3411 LOCK(&adb->entrylocks[bucket]); 3412 3413 if (factor == DNS_ADB_RTTADJAGE) 3414 new_srtt = addr->entry->srtt * 98 / 100; 3415 else 3416 new_srtt = (addr->entry->srtt / 10 * factor) 3417 + (rtt / 10 * (10 - factor)); 3418 3419 addr->entry->srtt = new_srtt; 3420 addr->srtt = new_srtt; 3421 3422 isc_stdtime_get(&now); 3423 addr->entry->expires = now + ADB_ENTRY_WINDOW; 3424 3425 UNLOCK(&adb->entrylocks[bucket]); 3426} 3427 3428void 3429dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, 3430 unsigned int bits, unsigned int mask) 3431{ 3432 int bucket; 3433 3434 REQUIRE(DNS_ADB_VALID(adb)); 3435 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 3436 3437 bucket = addr->entry->lock_bucket; 3438 LOCK(&adb->entrylocks[bucket]); 3439 3440 addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask); 3441 /* 3442 * Note that we do not update the other bits in addr->flags with 3443 * the most recent values from addr->entry->flags. 3444 */ 3445 addr->flags = (addr->flags & ~mask) | (bits & mask); 3446 3447 UNLOCK(&adb->entrylocks[bucket]); 3448} 3449 3450isc_result_t 3451dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa, 3452 dns_adbaddrinfo_t **addrp, isc_stdtime_t now) 3453{ 3454 int bucket; 3455 dns_adbentry_t *entry; 3456 dns_adbaddrinfo_t *addr; 3457 isc_result_t result; 3458 in_port_t port; 3459 3460 REQUIRE(DNS_ADB_VALID(adb)); 3461 REQUIRE(addrp != NULL && *addrp == NULL); 3462 3463 UNUSED(now); 3464 3465 result = ISC_R_SUCCESS; 3466 bucket = DNS_ADB_INVALIDBUCKET; 3467 entry = find_entry_and_lock(adb, sa, &bucket); 3468 if (adb->entry_sd[bucket]) { 3469 result = ISC_R_SHUTTINGDOWN; 3470 goto unlock; 3471 } 3472 if (entry == NULL) { 3473 /* 3474 * We don't know anything about this address. 3475 */ 3476 entry = new_adbentry(adb); 3477 if (entry == NULL) { 3478 result = ISC_R_NOMEMORY; 3479 goto unlock; 3480 } 3481 entry->sockaddr = *sa; 3482 link_entry(adb, bucket, entry); 3483 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry); 3484 } else 3485 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry); 3486 3487 port = isc_sockaddr_getport(sa); 3488 addr = new_adbaddrinfo(adb, entry, port); 3489 if (addr == NULL) { 3490 result = ISC_R_NOMEMORY; 3491 } else { 3492 inc_entry_refcnt(adb, entry, ISC_FALSE); 3493 *addrp = addr; 3494 } 3495 3496 unlock: 3497 UNLOCK(&adb->entrylocks[bucket]); 3498 3499 return (result); 3500} 3501 3502void 3503dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) { 3504 dns_adbaddrinfo_t *addr; 3505 dns_adbentry_t *entry; 3506 int bucket; 3507 isc_stdtime_t now; 3508 isc_boolean_t want_check_exit = ISC_FALSE; 3509 3510 REQUIRE(DNS_ADB_VALID(adb)); 3511 REQUIRE(addrp != NULL); 3512 addr = *addrp; 3513 REQUIRE(DNS_ADBADDRINFO_VALID(addr)); 3514 entry = addr->entry; 3515 REQUIRE(DNS_ADBENTRY_VALID(entry)); 3516 3517 isc_stdtime_get(&now); 3518 3519 *addrp = NULL; 3520 3521 bucket = addr->entry->lock_bucket; 3522 LOCK(&adb->entrylocks[bucket]); 3523 3524 entry->expires = now + ADB_ENTRY_WINDOW; 3525 3526 want_check_exit = dec_entry_refcnt(adb, entry, ISC_FALSE); 3527 3528 UNLOCK(&adb->entrylocks[bucket]); 3529 3530 addr->entry = NULL; 3531 free_adbaddrinfo(adb, &addr); 3532 3533 if (want_check_exit) { 3534 LOCK(&adb->lock); 3535 check_exit(adb); 3536 UNLOCK(&adb->lock); 3537 } 3538} 3539 3540void 3541dns_adb_flush(dns_adb_t *adb) { 3542 unsigned int i; 3543 3544 INSIST(DNS_ADB_VALID(adb)); 3545 3546 LOCK(&adb->lock); 3547 3548 /* 3549 * Call our cleanup routines. 3550 */ 3551 for (i = 0; i < NBUCKETS; i++) 3552 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE); 3553 for (i = 0; i < NBUCKETS; i++) 3554 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE); 3555 3556#ifdef DUMP_ADB_AFTER_CLEANING 3557 dump_adb(adb, stdout, ISC_TRUE, INT_MAX); 3558#endif 3559 3560 UNLOCK(&adb->lock); 3561} 3562 3563void 3564dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) { 3565 dns_adbname_t *adbname; 3566 dns_adbname_t *nextname; 3567 int bucket; 3568 3569 INSIST(DNS_ADB_VALID(adb)); 3570 3571 LOCK(&adb->lock); 3572 bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS; 3573 LOCK(&adb->namelocks[bucket]); 3574 adbname = ISC_LIST_HEAD(adb->names[bucket]); 3575 while (adbname != NULL) { 3576 nextname = ISC_LIST_NEXT(adbname, plink); 3577 if (!NAME_DEAD(adbname) && 3578 dns_name_equal(name, &adbname->name)) { 3579 RUNTIME_CHECK(kill_name(&adbname, 3580 DNS_EVENT_ADBCANCELED) == 3581 ISC_FALSE); 3582 } 3583 adbname = nextname; 3584 } 3585 UNLOCK(&adb->namelocks[bucket]); 3586 UNLOCK(&adb->lock); 3587} 3588 3589static void 3590water(void *arg, int mark) { 3591 dns_adb_t *adb = arg; 3592 isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER); 3593 isc_interval_t interval; 3594 3595 REQUIRE(DNS_ADB_VALID(adb)); 3596 3597 DP(ISC_LOG_DEBUG(1), 3598 "adb reached %s water mark", overmem ? "high" : "low"); 3599 3600 /* 3601 * We can't use adb->lock as there is potential for water 3602 * to be called when adb->lock is held. 3603 */ 3604 LOCK(&adb->overmemlock); 3605 if (adb->overmem != overmem) { 3606 adb->overmem = overmem; 3607 if (overmem) { 3608 isc_interval_set(&interval, 0, 1); 3609 (void)isc_timer_reset(adb->timer, isc_timertype_once, 3610 NULL, &interval, ISC_TRUE); 3611 } 3612 isc_mem_waterack(adb->mctx, mark); 3613 } 3614 UNLOCK(&adb->overmemlock); 3615} 3616 3617void 3618dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) { 3619 isc_uint32_t hiwater; 3620 isc_uint32_t lowater; 3621 3622 INSIST(DNS_ADB_VALID(adb)); 3623 3624 if (size != 0 && size < DNS_ADB_MINADBSIZE) 3625 size = DNS_ADB_MINADBSIZE; 3626 3627 hiwater = size - (size >> 3); /* Approximately 7/8ths. */ 3628 lowater = size - (size >> 2); /* Approximately 3/4ths. */ 3629 3630 if (size == 0 || hiwater == 0 || lowater == 0) 3631 isc_mem_setwater(adb->mctx, water, adb, 0, 0); 3632 else 3633 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater); 3634} 3635