PageRenderTime 122ms CodeModel.GetById 30ms app.highlight 76ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/lib/dns/adb.c

https://bitbucket.org/freebsd/freebsd-head/
C | 4113 lines | 2943 code | 573 blank | 597 comment | 770 complexity | 4b87144099769830b153bfe500bfa4ea MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2004-2012  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$ */
  19
  20/*! \file
  21 *
  22 * \note
  23 * In finds, if task == NULL, no events will be generated, and no events
  24 * have been sent.  If task != NULL but taskaction == NULL, an event has been
  25 * posted but not yet freed.  If neither are NULL, no event was posted.
  26 *
  27 */
  28
  29#include <config.h>
  30
  31#include <limits.h>
  32
  33#include <isc/mutexblock.h>
  34#include <isc/netaddr.h>
  35#include <isc/random.h>
  36#include <isc/stats.h>
  37#include <isc/string.h>         /* Required for HP/UX (and others?) */
  38#include <isc/task.h>
  39#include <isc/util.h>
  40
  41#include <dns/adb.h>
  42#include <dns/db.h>
  43#include <dns/events.h>
  44#include <dns/log.h>
  45#include <dns/rdata.h>
  46#include <dns/rdataset.h>
  47#include <dns/rdatastruct.h>
  48#include <dns/rdatatype.h>
  49#include <dns/resolver.h>
  50#include <dns/result.h>
  51#include <dns/stats.h>
  52
  53#define DNS_ADB_MAGIC             ISC_MAGIC('D', 'a', 'd', 'b')
  54#define DNS_ADB_VALID(x)          ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
  55#define DNS_ADBNAME_MAGIC         ISC_MAGIC('a', 'd', 'b', 'N')
  56#define DNS_ADBNAME_VALID(x)      ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
  57#define DNS_ADBNAMEHOOK_MAGIC     ISC_MAGIC('a', 'd', 'N', 'H')
  58#define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
  59#define DNS_ADBLAMEINFO_MAGIC     ISC_MAGIC('a', 'd', 'b', 'Z')
  60#define DNS_ADBLAMEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
  61#define DNS_ADBENTRY_MAGIC        ISC_MAGIC('a', 'd', 'b', 'E')
  62#define DNS_ADBENTRY_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
  63#define DNS_ADBFETCH_MAGIC        ISC_MAGIC('a', 'd', 'F', '4')
  64#define DNS_ADBFETCH_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
  65#define DNS_ADBFETCH6_MAGIC       ISC_MAGIC('a', 'd', 'F', '6')
  66#define DNS_ADBFETCH6_VALID(x)    ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
  67
  68/*!
  69 * For type 3 negative cache entries, we will remember that the address is
  70 * broken for this long.  XXXMLG This is also used for actual addresses, too.
  71 * The intent is to keep us from constantly asking about A/AAAA records
  72 * if the zone has extremely low TTLs.
  73 */
  74#define ADB_CACHE_MINIMUM       10      /*%< seconds */
  75#define ADB_CACHE_MAXIMUM       86400   /*%< seconds (86400 = 24 hours) */
  76#define ADB_ENTRY_WINDOW        1800    /*%< seconds */
  77
  78/*%
  79 * The period in seconds after which an ADB name entry is regarded as stale
  80 * and forced to be cleaned up.
  81 * TODO: This should probably be configurable at run-time.
  82 */
  83#ifndef ADB_STALE_MARGIN
  84#define ADB_STALE_MARGIN        1800
  85#endif
  86
  87#define FREE_ITEMS              64      /*%< free count for memory pools */
  88#define FILL_COUNT              16      /*%< fill count for memory pools */
  89
  90#define DNS_ADB_INVALIDBUCKET (-1)      /*%< invalid bucket address */
  91
  92#define DNS_ADB_MINADBSIZE      (1024*1024)     /*%< 1 Megabyte */
  93
  94typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
  95typedef struct dns_adbnamehook dns_adbnamehook_t;
  96typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
  97typedef struct dns_adblameinfo dns_adblameinfo_t;
  98typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
  99typedef struct dns_adbfetch dns_adbfetch_t;
 100typedef struct dns_adbfetch6 dns_adbfetch6_t;
 101
 102/*% dns adb structure */
 103struct dns_adb {
 104	unsigned int                    magic;
 105
 106	isc_mutex_t                     lock;
 107	isc_mutex_t                     reflock; /*%< Covers irefcnt, erefcnt */
 108	isc_mutex_t                     overmemlock; /*%< Covers overmem */
 109	isc_mem_t                      *mctx;
 110	dns_view_t                     *view;
 111
 112	isc_taskmgr_t                  *taskmgr;
 113	isc_task_t                     *task;
 114
 115	isc_interval_t                  tick_interval;
 116	int                             next_cleanbucket;
 117
 118	unsigned int                    irefcnt;
 119	unsigned int                    erefcnt;
 120
 121	isc_mutex_t                     mplock;
 122	isc_mempool_t                  *nmp;    /*%< dns_adbname_t */
 123	isc_mempool_t                  *nhmp;   /*%< dns_adbnamehook_t */
 124	isc_mempool_t                  *limp;   /*%< dns_adblameinfo_t */
 125	isc_mempool_t                  *emp;    /*%< dns_adbentry_t */
 126	isc_mempool_t                  *ahmp;   /*%< dns_adbfind_t */
 127	isc_mempool_t                  *aimp;   /*%< dns_adbaddrinfo_t */
 128	isc_mempool_t                  *afmp;   /*%< dns_adbfetch_t */
 129
 130	/*!
 131	 * Bucketized locks and lists for names.
 132	 *
 133	 * XXXRTH  Have a per-bucket structure that contains all of these?
 134	 */
 135	unsigned int			nnames;
 136	isc_mutex_t                     namescntlock;
 137	unsigned int			namescnt;
 138	dns_adbnamelist_t               *names;
 139	dns_adbnamelist_t               *deadnames;
 140	isc_mutex_t                     *namelocks;
 141	isc_boolean_t                   *name_sd;
 142	unsigned int                    *name_refcnt;
 143
 144	/*!
 145	 * Bucketized locks and lists for entries.
 146	 *
 147	 * XXXRTH  Have a per-bucket structure that contains all of these?
 148	 */
 149	unsigned int			nentries;
 150	isc_mutex_t                     entriescntlock;
 151	unsigned int			entriescnt;
 152	dns_adbentrylist_t              *entries;
 153	dns_adbentrylist_t              *deadentries;
 154	isc_mutex_t                     *entrylocks;
 155	isc_boolean_t                   *entry_sd; /*%< shutting down */
 156	unsigned int                    *entry_refcnt;
 157
 158	isc_event_t                     cevent;
 159	isc_boolean_t                   cevent_sent;
 160	isc_boolean_t                   shutting_down;
 161	isc_eventlist_t                 whenshutdown;
 162	isc_event_t			growentries;
 163	isc_boolean_t			growentries_sent;
 164	isc_event_t			grownames;
 165	isc_boolean_t			grownames_sent;
 166};
 167
 168/*
 169 * XXXMLG  Document these structures.
 170 */
 171
 172/*% dns_adbname structure */
 173struct dns_adbname {
 174	unsigned int                    magic;
 175	dns_name_t                      name;
 176	dns_adb_t                      *adb;
 177	unsigned int                    partial_result;
 178	unsigned int                    flags;
 179	int                             lock_bucket;
 180	dns_name_t                      target;
 181	isc_stdtime_t                   expire_target;
 182	isc_stdtime_t                   expire_v4;
 183	isc_stdtime_t                   expire_v6;
 184	unsigned int                    chains;
 185	dns_adbnamehooklist_t           v4;
 186	dns_adbnamehooklist_t           v6;
 187	dns_adbfetch_t                 *fetch_a;
 188	dns_adbfetch_t                 *fetch_aaaa;
 189	unsigned int                    fetch_err;
 190	unsigned int                    fetch6_err;
 191	dns_adbfindlist_t               finds;
 192	/* for LRU-based management */
 193	isc_stdtime_t                   last_used;
 194
 195	ISC_LINK(dns_adbname_t)         plink;
 196};
 197
 198/*% The adbfetch structure */
 199struct dns_adbfetch {
 200	unsigned int                    magic;
 201	dns_fetch_t                    *fetch;
 202	dns_rdataset_t                  rdataset;
 203};
 204
 205/*%
 206 * This is a small widget that dangles off a dns_adbname_t.  It contains a
 207 * pointer to the address information about this host, and a link to the next
 208 * namehook that will contain the next address this host has.
 209 */
 210struct dns_adbnamehook {
 211	unsigned int                    magic;
 212	dns_adbentry_t                 *entry;
 213	ISC_LINK(dns_adbnamehook_t)     plink;
 214};
 215
 216/*%
 217 * This is a small widget that holds qname-specific information about an
 218 * address.  Currently limited to lameness, but could just as easily be
 219 * extended to other types of information about zones.
 220 */
 221struct dns_adblameinfo {
 222	unsigned int                    magic;
 223
 224	dns_name_t                      qname;
 225	dns_rdatatype_t                 qtype;
 226	isc_stdtime_t                   lame_timer;
 227
 228	ISC_LINK(dns_adblameinfo_t)     plink;
 229};
 230
 231/*%
 232 * An address entry.  It holds quite a bit of information about addresses,
 233 * including edns state (in "flags"), rtt, and of course the address of
 234 * the host.
 235 */
 236struct dns_adbentry {
 237	unsigned int                    magic;
 238
 239	int                             lock_bucket;
 240	unsigned int                    refcnt;
 241
 242	unsigned int                    flags;
 243	unsigned int                    srtt;
 244	isc_sockaddr_t                  sockaddr;
 245
 246	isc_stdtime_t                   expires;
 247	/*%<
 248	 * A nonzero 'expires' field indicates that the entry should
 249	 * persist until that time.  This allows entries found
 250	 * using dns_adb_findaddrinfo() to persist for a limited time
 251	 * even though they are not necessarily associated with a
 252	 * name.
 253	 */
 254
 255	ISC_LIST(dns_adblameinfo_t)     lameinfo;
 256	ISC_LINK(dns_adbentry_t)        plink;
 257
 258};
 259
 260/*
 261 * Internal functions (and prototypes).
 262 */
 263static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
 264static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
 265static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
 266						 dns_adbentry_t *);
 267static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
 268static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
 269						 dns_rdatatype_t);
 270static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
 271static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
 272static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
 273static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
 274static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
 275static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
 276						 in_port_t);
 277static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
 278static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
 279static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
 280						unsigned int, int *);
 281static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
 282						  isc_sockaddr_t *, int *,
 283						  isc_stdtime_t);
 284static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
 285static void print_dns_name(FILE *, dns_name_t *);
 286static void print_namehook_list(FILE *, const char *legend,
 287				dns_adbnamehooklist_t *list,
 288				isc_boolean_t debug,
 289				isc_stdtime_t now);
 290static void print_find_list(FILE *, dns_adbname_t *);
 291static void print_fetch_list(FILE *, dns_adbname_t *);
 292static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
 293static inline void inc_adb_irefcnt(dns_adb_t *);
 294static inline void inc_adb_erefcnt(dns_adb_t *);
 295static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
 296				    isc_boolean_t);
 297static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
 298					     dns_adbentry_t *, isc_boolean_t);
 299static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
 300static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
 301static void clean_target(dns_adb_t *, dns_name_t *);
 302static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
 303				unsigned int);
 304static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
 305static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
 306					isc_stdtime_t);
 307static void cancel_fetches_at_name(dns_adbname_t *);
 308static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
 309				dns_rdatatype_t);
 310static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
 311			       dns_rdatatype_t);
 312static inline void check_exit(dns_adb_t *);
 313static void destroy(dns_adb_t *);
 314static isc_boolean_t shutdown_names(dns_adb_t *);
 315static isc_boolean_t shutdown_entries(dns_adb_t *);
 316static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
 317static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
 318static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
 319static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
 320static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
 321static void water(void *, int);
 322static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
 323
 324/*
 325 * MUST NOT overlap DNS_ADBFIND_* flags!
 326 */
 327#define FIND_EVENT_SENT         0x40000000
 328#define FIND_EVENT_FREED        0x80000000
 329#define FIND_EVENTSENT(h)       (((h)->flags & FIND_EVENT_SENT) != 0)
 330#define FIND_EVENTFREED(h)      (((h)->flags & FIND_EVENT_FREED) != 0)
 331
 332#define NAME_NEEDS_POKE         0x80000000
 333#define NAME_IS_DEAD            0x40000000
 334#define NAME_HINT_OK            DNS_ADBFIND_HINTOK
 335#define NAME_GLUE_OK            DNS_ADBFIND_GLUEOK
 336#define NAME_STARTATZONE        DNS_ADBFIND_STARTATZONE
 337#define NAME_DEAD(n)            (((n)->flags & NAME_IS_DEAD) != 0)
 338#define NAME_NEEDSPOKE(n)       (((n)->flags & NAME_NEEDS_POKE) != 0)
 339#define NAME_GLUEOK(n)          (((n)->flags & NAME_GLUE_OK) != 0)
 340#define NAME_HINTOK(n)          (((n)->flags & NAME_HINT_OK) != 0)
 341
 342/*
 343 * Private flag(s) for entries.
 344 * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
 345 */
 346#define ENTRY_IS_DEAD		0x80000000
 347
 348/*
 349 * To the name, address classes are all that really exist.  If it has a
 350 * V6 address it doesn't care if it came from a AAAA query.
 351 */
 352#define NAME_HAS_V4(n)          (!ISC_LIST_EMPTY((n)->v4))
 353#define NAME_HAS_V6(n)          (!ISC_LIST_EMPTY((n)->v6))
 354#define NAME_HAS_ADDRS(n)       (NAME_HAS_V4(n) || NAME_HAS_V6(n))
 355
 356/*
 357 * Fetches are broken out into A and AAAA types.  In some cases,
 358 * however, it makes more sense to test for a particular class of fetches,
 359 * like V4 or V6 above.
 360 * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
 361 * are now equal to FETCH_V4 and FETCH_V6, respectively.
 362 */
 363#define NAME_FETCH_A(n)         ((n)->fetch_a != NULL)
 364#define NAME_FETCH_AAAA(n)      ((n)->fetch_aaaa != NULL)
 365#define NAME_FETCH_V4(n)        (NAME_FETCH_A(n))
 366#define NAME_FETCH_V6(n)        (NAME_FETCH_AAAA(n))
 367#define NAME_FETCH(n)           (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
 368
 369/*
 370 * Find options and tests to see if there are addresses on the list.
 371 */
 372#define FIND_WANTEVENT(fn)      (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
 373#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
 374#define FIND_AVOIDFETCHES(fn)   (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
 375				 != 0)
 376#define FIND_STARTATZONE(fn)    (((fn)->options & DNS_ADBFIND_STARTATZONE) \
 377				 != 0)
 378#define FIND_HINTOK(fn)         (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
 379#define FIND_GLUEOK(fn)         (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
 380#define FIND_HAS_ADDRS(fn)      (!ISC_LIST_EMPTY((fn)->list))
 381#define FIND_RETURNLAME(fn)     (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
 382
 383/*
 384 * These are currently used on simple unsigned ints, so they are
 385 * not really associated with any particular type.
 386 */
 387#define WANT_INET(x)            (((x) & DNS_ADBFIND_INET) != 0)
 388#define WANT_INET6(x)           (((x) & DNS_ADBFIND_INET6) != 0)
 389
 390#define EXPIRE_OK(exp, now)     ((exp == INT_MAX) || (exp < now))
 391
 392/*
 393 * Find out if the flags on a name (nf) indicate if it is a hint or
 394 * glue, and compare this to the appropriate bits set in o, to see if
 395 * this is ok.
 396 */
 397#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
 398#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
 399#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
 400#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
 401				    ((o) & DNS_ADBFIND_STARTATZONE))
 402
 403#define ENTER_LEVEL             ISC_LOG_DEBUG(50)
 404#define EXIT_LEVEL              ENTER_LEVEL
 405#define CLEAN_LEVEL             ISC_LOG_DEBUG(100)
 406#define DEF_LEVEL               ISC_LOG_DEBUG(5)
 407#define NCACHE_LEVEL            ISC_LOG_DEBUG(20)
 408
 409#define NCACHE_RESULT(r)        ((r) == DNS_R_NCACHENXDOMAIN || \
 410				 (r) == DNS_R_NCACHENXRRSET)
 411#define AUTH_NX(r)              ((r) == DNS_R_NXDOMAIN || \
 412				 (r) == DNS_R_NXRRSET)
 413#define NXDOMAIN_RESULT(r)      ((r) == DNS_R_NXDOMAIN || \
 414				 (r) == DNS_R_NCACHENXDOMAIN)
 415#define NXRRSET_RESULT(r)       ((r) == DNS_R_NCACHENXRRSET || \
 416				 (r) == DNS_R_NXRRSET || \
 417				 (r) == DNS_R_HINTNXRRSET)
 418
 419/*
 420 * Error state rankings.
 421 */
 422
 423#define FIND_ERR_SUCCESS                0  /* highest rank */
 424#define FIND_ERR_CANCELED               1
 425#define FIND_ERR_FAILURE                2
 426#define FIND_ERR_NXDOMAIN               3
 427#define FIND_ERR_NXRRSET                4
 428#define FIND_ERR_UNEXPECTED             5
 429#define FIND_ERR_NOTFOUND               6
 430#define FIND_ERR_MAX                    7
 431
 432static const char *errnames[] = {
 433	"success",
 434	"canceled",
 435	"failure",
 436	"nxdomain",
 437	"nxrrset",
 438	"unexpected",
 439	"not_found"
 440};
 441
 442#define NEWERR(old, new)        (ISC_MIN((old), (new)))
 443
 444static isc_result_t find_err_map[FIND_ERR_MAX] = {
 445	ISC_R_SUCCESS,
 446	ISC_R_CANCELED,
 447	ISC_R_FAILURE,
 448	DNS_R_NXDOMAIN,
 449	DNS_R_NXRRSET,
 450	ISC_R_UNEXPECTED,
 451	ISC_R_NOTFOUND          /* not YET found */
 452};
 453
 454static void
 455DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
 456
 457static void
 458DP(int level, const char *format, ...) {
 459	va_list args;
 460
 461	va_start(args, format);
 462	isc_log_vwrite(dns_lctx,
 463		       DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
 464		       level, format, args);
 465	va_end(args);
 466}
 467
 468/*%
 469 * Increment resolver-related statistics counters.
 470 */
 471static inline void
 472inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
 473	if (adb->view->resstats != NULL)
 474		isc_stats_increment(adb->view->resstats, counter);
 475}
 476
 477static inline dns_ttl_t
 478ttlclamp(dns_ttl_t ttl) {
 479	if (ttl < ADB_CACHE_MINIMUM)
 480		ttl = ADB_CACHE_MINIMUM;
 481	if (ttl > ADB_CACHE_MAXIMUM)
 482		ttl = ADB_CACHE_MAXIMUM;
 483
 484	return (ttl);
 485}
 486
 487/*
 488 * Hashing is most efficient if the number of buckets is prime.
 489 * The sequence below is the closest previous primes to 2^n and
 490 * 1.5 * 2^n, for values of n from 10 to 28.  (The tables will
 491 * no longer grow beyond 2^28 entries.)
 492 */
 493static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
 494				     8191, 12281, 16381, 24571, 32749,
 495				     49193, 65521, 98299, 131071, 199603,
 496				     262139, 393209, 524287, 768431, 1048573,
 497				     1572853, 2097143, 3145721, 4194301,
 498				     6291449, 8388593, 12582893, 16777213,
 499				     25165813, 33554393, 50331599, 67108859,
 500				     100663291, 134217689, 201326557,
 501				     268535431, 0 };
 502
 503static void
 504grow_entries(isc_task_t *task, isc_event_t *ev) {
 505	dns_adb_t *adb;
 506	dns_adbentry_t *e;
 507	dns_adbentrylist_t *newdeadentries = NULL;
 508	dns_adbentrylist_t *newentries = NULL;
 509	isc_boolean_t *newentry_sd = NULL;
 510	isc_mutex_t *newentrylocks = NULL;
 511	isc_result_t result;
 512	unsigned int *newentry_refcnt = NULL;
 513	unsigned int i, n, bucket;
 514
 515	adb = ev->ev_arg;
 516	INSIST(DNS_ADB_VALID(adb));
 517
 518	isc_event_free(&ev);
 519
 520	isc_task_beginexclusive(task);
 521
 522	i = 0;
 523	while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
 524		i++;
 525	if (nbuckets[i] != 0)
 526		n = nbuckets[i];
 527	else
 528		goto done;
 529
 530	DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
 531
 532	/*
 533	 * Are we shutting down?
 534	 */
 535	for (i = 0; i < adb->nentries; i++)
 536		if (adb->entry_sd[i])
 537			goto cleanup;
 538
 539	/*
 540	 * Grab all the resources we need.
 541	 */
 542	newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
 543	newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
 544	newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
 545	newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
 546	newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
 547	if (newentries == NULL || newdeadentries == NULL ||
 548	    newentrylocks == NULL || newentry_sd == NULL ||
 549	    newentry_refcnt == NULL)
 550		goto cleanup;
 551
 552	/*
 553	 * Initialise the new resources.
 554	 */
 555	result = isc_mutexblock_init(newentrylocks, n);
 556	if (result != ISC_R_SUCCESS)
 557		goto cleanup;
 558
 559	for (i = 0; i < n; i++) {
 560		ISC_LIST_INIT(newentries[i]);
 561		ISC_LIST_INIT(newdeadentries[i]);
 562		newentry_sd[i] = ISC_FALSE;
 563		newentry_refcnt[i] = 0;
 564		adb->irefcnt++;
 565	}
 566
 567	/*
 568	 * Move entries to new arrays.
 569	 */
 570	for (i = 0; i < adb->nentries; i++) {
 571		e = ISC_LIST_HEAD(adb->entries[i]);
 572		while (e != NULL) {
 573			ISC_LIST_UNLINK(adb->entries[i], e, plink);
 574			bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
 575			e->lock_bucket = bucket;
 576			ISC_LIST_APPEND(newentries[bucket], e, plink);
 577			INSIST(adb->entry_refcnt[i] > 0);
 578			adb->entry_refcnt[i]--;
 579			newentry_refcnt[bucket]++;
 580			e = ISC_LIST_HEAD(adb->entries[i]);
 581		}
 582		e = ISC_LIST_HEAD(adb->deadentries[i]);
 583		while (e != NULL) {
 584			ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
 585			bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
 586			e->lock_bucket = bucket;
 587			ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
 588			INSIST(adb->entry_refcnt[i] > 0);
 589			adb->entry_refcnt[i]--;
 590			newentry_refcnt[bucket]++;
 591			e = ISC_LIST_HEAD(adb->deadentries[i]);
 592		}
 593		INSIST(adb->entry_refcnt[i] == 0);
 594		adb->irefcnt--;
 595	}
 596
 597	/*
 598	 * Cleanup old resources.
 599	 */
 600	DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
 601	isc_mem_put(adb->mctx, adb->entries,
 602		    sizeof(*adb->entries) * adb->nentries);
 603	isc_mem_put(adb->mctx, adb->deadentries,
 604		    sizeof(*adb->deadentries) * adb->nentries);
 605	isc_mem_put(adb->mctx, adb->entrylocks,
 606		    sizeof(*adb->entrylocks) * adb->nentries);
 607	isc_mem_put(adb->mctx, adb->entry_sd,
 608		    sizeof(*adb->entry_sd) * adb->nentries);
 609	isc_mem_put(adb->mctx, adb->entry_refcnt,
 610		    sizeof(*adb->entry_refcnt) * adb->nentries);
 611
 612	/*
 613	 * Install new resources.
 614	 */
 615	adb->entries = newentries;
 616	adb->deadentries = newdeadentries;
 617	adb->entrylocks = newentrylocks;
 618	adb->entry_sd = newentry_sd;
 619	adb->entry_refcnt = newentry_refcnt;
 620	adb->nentries = n;
 621
 622	/*
 623	 * Only on success do we set adb->growentries_sent to ISC_FALSE.
 624	 * This will prevent us being continuously being called on error.
 625	 */
 626	adb->growentries_sent = ISC_FALSE;
 627	goto done;
 628
 629 cleanup:
 630	if (newentries != NULL)
 631		isc_mem_put(adb->mctx, newentries,
 632			    sizeof(*newentries) * n);
 633	if (newdeadentries != NULL)
 634		isc_mem_put(adb->mctx, newdeadentries,
 635			    sizeof(*newdeadentries) * n);
 636	if (newentrylocks != NULL)
 637		isc_mem_put(adb->mctx, newentrylocks,
 638			    sizeof(*newentrylocks) * n);
 639	if (newentry_sd != NULL)
 640		isc_mem_put(adb->mctx, newentry_sd,
 641			    sizeof(*newentry_sd) * n);
 642	if (newentry_refcnt != NULL)
 643		isc_mem_put(adb->mctx, newentry_refcnt,
 644			     sizeof(*newentry_refcnt) * n);
 645 done:
 646	isc_task_endexclusive(task);
 647
 648	LOCK(&adb->lock);
 649	if (dec_adb_irefcnt(adb))
 650		check_exit(adb);
 651	UNLOCK(&adb->lock);
 652	DP(ISC_LOG_INFO, "adb: grow_entries finished");
 653}
 654
 655static void
 656grow_names(isc_task_t *task, isc_event_t *ev) {
 657	dns_adb_t *adb;
 658	dns_adbname_t *name;
 659	dns_adbnamelist_t *newdeadnames = NULL;
 660	dns_adbnamelist_t *newnames = NULL;
 661	isc_boolean_t *newname_sd = NULL;
 662	isc_mutex_t *newnamelocks = NULL;
 663	isc_result_t result;
 664	unsigned int *newname_refcnt = NULL;
 665	unsigned int i, n, bucket;
 666
 667	adb = ev->ev_arg;
 668	INSIST(DNS_ADB_VALID(adb));
 669
 670	isc_event_free(&ev);
 671
 672	isc_task_beginexclusive(task);
 673
 674	i = 0;
 675	while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
 676		i++;
 677	if (nbuckets[i] != 0)
 678		n = nbuckets[i];
 679	else
 680		goto done;
 681
 682	DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
 683
 684	/*
 685	 * Are we shutting down?
 686	 */
 687	for (i = 0; i < adb->nnames; i++)
 688		if (adb->name_sd[i])
 689			goto cleanup;
 690
 691	/*
 692	 * Grab all the resources we need.
 693	 */
 694	newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
 695	newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
 696	newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
 697	newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
 698	newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
 699	if (newnames == NULL || newdeadnames == NULL ||
 700	    newnamelocks == NULL || newname_sd == NULL ||
 701	    newname_refcnt == NULL)
 702		goto cleanup;
 703
 704	/*
 705	 * Initialise the new resources.
 706	 */
 707	result = isc_mutexblock_init(newnamelocks, n);
 708	if (result != ISC_R_SUCCESS)
 709		goto cleanup;
 710
 711	for (i = 0; i < n; i++) {
 712		ISC_LIST_INIT(newnames[i]);
 713		ISC_LIST_INIT(newdeadnames[i]);
 714		newname_sd[i] = ISC_FALSE;
 715		newname_refcnt[i] = 0;
 716		adb->irefcnt++;
 717	}
 718
 719	/*
 720	 * Move names to new arrays.
 721	 */
 722	for (i = 0; i < adb->nnames; i++) {
 723		name = ISC_LIST_HEAD(adb->names[i]);
 724		while (name != NULL) {
 725			ISC_LIST_UNLINK(adb->names[i], name, plink);
 726			bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
 727			name->lock_bucket = bucket;
 728			ISC_LIST_APPEND(newnames[bucket], name, plink);
 729			INSIST(adb->name_refcnt[i] > 0);
 730			adb->name_refcnt[i]--;
 731			newname_refcnt[bucket]++;
 732			name = ISC_LIST_HEAD(adb->names[i]);
 733		}
 734		name = ISC_LIST_HEAD(adb->deadnames[i]);
 735		while (name != NULL) {
 736			ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
 737			bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
 738			name->lock_bucket = bucket;
 739			ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
 740			INSIST(adb->name_refcnt[i] > 0);
 741			adb->name_refcnt[i]--;
 742			newname_refcnt[bucket]++;
 743			name = ISC_LIST_HEAD(adb->deadnames[i]);
 744		}
 745		INSIST(adb->name_refcnt[i] == 0);
 746		adb->irefcnt--;
 747	}
 748
 749	/*
 750	 * Cleanup old resources.
 751	 */
 752	DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
 753	isc_mem_put(adb->mctx, adb->names,
 754		    sizeof(*adb->names) * adb->nnames);
 755	isc_mem_put(adb->mctx, adb->deadnames,
 756		    sizeof(*adb->deadnames) * adb->nnames);
 757	isc_mem_put(adb->mctx, adb->namelocks,
 758		    sizeof(*adb->namelocks) * adb->nnames);
 759	isc_mem_put(adb->mctx, adb->name_sd,
 760		    sizeof(*adb->name_sd) * adb->nnames);
 761	isc_mem_put(adb->mctx, adb->name_refcnt,
 762		    sizeof(*adb->name_refcnt) * adb->nnames);
 763
 764	/*
 765	 * Install new resources.
 766	 */
 767	adb->names = newnames;
 768	adb->deadnames = newdeadnames;
 769	adb->namelocks = newnamelocks;
 770	adb->name_sd = newname_sd;
 771	adb->name_refcnt = newname_refcnt;
 772	adb->nnames = n;
 773
 774	/*
 775	 * Only on success do we set adb->grownames_sent to ISC_FALSE.
 776	 * This will prevent us being continuously being called on error.
 777	 */
 778	adb->grownames_sent = ISC_FALSE;
 779	goto done;
 780
 781 cleanup:
 782	if (newnames != NULL)
 783		isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
 784	if (newdeadnames != NULL)
 785		isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
 786	if (newnamelocks != NULL)
 787		isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
 788	if (newname_sd != NULL)
 789		isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
 790	if (newname_refcnt != NULL)
 791		isc_mem_put(adb->mctx, newname_refcnt,
 792			     sizeof(*newname_refcnt) * n);
 793 done:
 794	isc_task_endexclusive(task);
 795
 796	LOCK(&adb->lock);
 797	if (dec_adb_irefcnt(adb))
 798		check_exit(adb);
 799	UNLOCK(&adb->lock);
 800	DP(ISC_LOG_INFO, "adb: grow_names finished");
 801}
 802
 803/*
 804 * Requires the adbname bucket be locked and that no entry buckets be locked.
 805 *
 806 * This code handles A and AAAA rdatasets only.
 807 */
 808static isc_result_t
 809import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
 810		isc_stdtime_t now)
 811{
 812	isc_result_t result;
 813	dns_adb_t *adb;
 814	dns_adbnamehook_t *nh;
 815	dns_adbnamehook_t *anh;
 816	dns_rdata_t rdata = DNS_RDATA_INIT;
 817	struct in_addr ina;
 818	struct in6_addr in6a;
 819	isc_sockaddr_t sockaddr;
 820	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
 821	int addr_bucket;
 822	isc_boolean_t new_addresses_added;
 823	dns_rdatatype_t rdtype;
 824	unsigned int findoptions;
 825	dns_adbnamehooklist_t *hookhead;
 826
 827	INSIST(DNS_ADBNAME_VALID(adbname));
 828	adb = adbname->adb;
 829	INSIST(DNS_ADB_VALID(adb));
 830
 831	rdtype = rdataset->type;
 832	INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
 833	if (rdtype == dns_rdatatype_a)
 834		findoptions = DNS_ADBFIND_INET;
 835	else
 836		findoptions = DNS_ADBFIND_INET6;
 837
 838	addr_bucket = DNS_ADB_INVALIDBUCKET;
 839	new_addresses_added = ISC_FALSE;
 840
 841	nh = NULL;
 842	result = dns_rdataset_first(rdataset);
 843	while (result == ISC_R_SUCCESS) {
 844		dns_rdata_reset(&rdata);
 845		dns_rdataset_current(rdataset, &rdata);
 846		if (rdtype == dns_rdatatype_a) {
 847			INSIST(rdata.length == 4);
 848			memcpy(&ina.s_addr, rdata.data, 4);
 849			isc_sockaddr_fromin(&sockaddr, &ina, 0);
 850			hookhead = &adbname->v4;
 851		} else {
 852			INSIST(rdata.length == 16);
 853			memcpy(in6a.s6_addr, rdata.data, 16);
 854			isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
 855			hookhead = &adbname->v6;
 856		}
 857
 858		INSIST(nh == NULL);
 859		nh = new_adbnamehook(adb, NULL);
 860		if (nh == NULL) {
 861			adbname->partial_result |= findoptions;
 862			result = ISC_R_NOMEMORY;
 863			goto fail;
 864		}
 865
 866		foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
 867						 now);
 868		if (foundentry == NULL) {
 869			dns_adbentry_t *entry;
 870
 871			entry = new_adbentry(adb);
 872			if (entry == NULL) {
 873				adbname->partial_result |= findoptions;
 874				result = ISC_R_NOMEMORY;
 875				goto fail;
 876			}
 877
 878			entry->sockaddr = sockaddr;
 879			entry->refcnt = 1;
 880
 881			nh->entry = entry;
 882
 883			link_entry(adb, addr_bucket, entry);
 884		} else {
 885			for (anh = ISC_LIST_HEAD(*hookhead);
 886			     anh != NULL;
 887			     anh = ISC_LIST_NEXT(anh, plink))
 888				if (anh->entry == foundentry)
 889					break;
 890			if (anh == NULL) {
 891				foundentry->refcnt++;
 892				nh->entry = foundentry;
 893			} else
 894				free_adbnamehook(adb, &nh);
 895		}
 896
 897		new_addresses_added = ISC_TRUE;
 898		if (nh != NULL)
 899			ISC_LIST_APPEND(*hookhead, nh, plink);
 900		nh = NULL;
 901		result = dns_rdataset_next(rdataset);
 902	}
 903
 904 fail:
 905	if (nh != NULL)
 906		free_adbnamehook(adb, &nh);
 907
 908	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
 909		UNLOCK(&adb->entrylocks[addr_bucket]);
 910
 911	if (rdataset->trust == dns_trust_glue ||
 912	    rdataset->trust == dns_trust_additional)
 913		rdataset->ttl = ADB_CACHE_MINIMUM;
 914	else if (rdataset->trust == dns_trust_ultimate)
 915		rdataset->ttl = 0;
 916	else
 917		rdataset->ttl = ttlclamp(rdataset->ttl);
 918
 919	if (rdtype == dns_rdatatype_a) {
 920		DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
 921		   adbname->expire_v4, now + rdataset->ttl);
 922		adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
 923					     now + rdataset->ttl);
 924	} else {
 925		DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
 926		   adbname->expire_v6, now + rdataset->ttl);
 927		adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
 928					     now + rdataset->ttl);
 929	}
 930
 931	if (new_addresses_added) {
 932		/*
 933		 * Lie a little here.  This is more or less so code that cares
 934		 * can find out if any new information was added or not.
 935		 */
 936		return (ISC_R_SUCCESS);
 937	}
 938
 939	return (result);
 940}
 941
 942/*
 943 * Requires the name's bucket be locked.
 944 */
 945static isc_boolean_t
 946kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
 947	dns_adbname_t *name;
 948	isc_boolean_t result = ISC_FALSE;
 949	isc_boolean_t result4, result6;
 950	int bucket;
 951	dns_adb_t *adb;
 952
 953	INSIST(n != NULL);
 954	name = *n;
 955	*n = NULL;
 956	INSIST(DNS_ADBNAME_VALID(name));
 957	adb = name->adb;
 958	INSIST(DNS_ADB_VALID(adb));
 959
 960	DP(DEF_LEVEL, "killing name %p", name);
 961
 962	/*
 963	 * If we're dead already, just check to see if we should go
 964	 * away now or not.
 965	 */
 966	if (NAME_DEAD(name) && !NAME_FETCH(name)) {
 967		result = unlink_name(adb, name);
 968		free_adbname(adb, &name);
 969		if (result)
 970			result = dec_adb_irefcnt(adb);
 971		return (result);
 972	}
 973
 974	/*
 975	 * Clean up the name's various lists.  These two are destructive
 976	 * in that they will always empty the list.
 977	 */
 978	clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
 979	result4 = clean_namehooks(adb, &name->v4);
 980	result6 = clean_namehooks(adb, &name->v6);
 981	clean_target(adb, &name->target);
 982	result = ISC_TF(result4 || result6);
 983
 984	/*
 985	 * If fetches are running, cancel them.  If none are running, we can
 986	 * just kill the name here.
 987	 */
 988	if (!NAME_FETCH(name)) {
 989		INSIST(result == ISC_FALSE);
 990		result = unlink_name(adb, name);
 991		free_adbname(adb, &name);
 992		if (result)
 993			result = dec_adb_irefcnt(adb);
 994	} else {
 995		cancel_fetches_at_name(name);
 996		if (!NAME_DEAD(name)) {
 997			bucket = name->lock_bucket;
 998			ISC_LIST_UNLINK(adb->names[bucket], name, plink);
 999			ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
1000			name->flags |= NAME_IS_DEAD;
1001		}
1002	}
1003	return (result);
1004}
1005
1006/*
1007 * Requires the name's bucket be locked and no entry buckets be locked.
1008 */
1009static isc_boolean_t
1010check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
1011	dns_adb_t *adb;
1012	isc_boolean_t result4 = ISC_FALSE;
1013	isc_boolean_t result6 = ISC_FALSE;
1014
1015	INSIST(DNS_ADBNAME_VALID(name));
1016	adb = name->adb;
1017	INSIST(DNS_ADB_VALID(adb));
1018
1019	/*
1020	 * Check to see if we need to remove the v4 addresses
1021	 */
1022	if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
1023		if (NAME_HAS_V4(name)) {
1024			DP(DEF_LEVEL, "expiring v4 for name %p", name);
1025			result4 = clean_namehooks(adb, &name->v4);
1026			name->partial_result &= ~DNS_ADBFIND_INET;
1027		}
1028		name->expire_v4 = INT_MAX;
1029		name->fetch_err = FIND_ERR_UNEXPECTED;
1030	}
1031
1032	/*
1033	 * Check to see if we need to remove the v6 addresses
1034	 */
1035	if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
1036		if (NAME_HAS_V6(name)) {
1037			DP(DEF_LEVEL, "expiring v6 for name %p", name);
1038			result6 = clean_namehooks(adb, &name->v6);
1039			name->partial_result &= ~DNS_ADBFIND_INET6;
1040		}
1041		name->expire_v6 = INT_MAX;
1042		name->fetch6_err = FIND_ERR_UNEXPECTED;
1043	}
1044
1045	/*
1046	 * Check to see if we need to remove the alias target.
1047	 */
1048	if (EXPIRE_OK(name->expire_target, now)) {
1049		clean_target(adb, &name->target);
1050		name->expire_target = INT_MAX;
1051	}
1052	return (ISC_TF(result4 || result6));
1053}
1054
1055/*
1056 * Requires the name's bucket be locked.
1057 */
1058static inline void
1059link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
1060	INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
1061
1062	ISC_LIST_PREPEND(adb->names[bucket], name, plink);
1063	name->lock_bucket = bucket;
1064	adb->name_refcnt[bucket]++;
1065}
1066
1067/*
1068 * Requires the name's bucket be locked.
1069 */
1070static inline isc_boolean_t
1071unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
1072	int bucket;
1073	isc_boolean_t result = ISC_FALSE;
1074
1075	bucket = name->lock_bucket;
1076	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1077
1078	if (NAME_DEAD(name))
1079		ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
1080	else
1081		ISC_LIST_UNLINK(adb->names[bucket], name, plink);
1082	name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1083	INSIST(adb->name_refcnt[bucket] > 0);
1084	adb->name_refcnt[bucket]--;
1085	if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
1086		result = ISC_TRUE;
1087	return (result);
1088}
1089
1090/*
1091 * Requires the entry's bucket be locked.
1092 */
1093static inline void
1094link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
1095	int i;
1096	dns_adbentry_t *e;
1097
1098	if (isc_mem_isovermem(adb->mctx)) {
1099		for (i = 0; i < 2; i++) {
1100			e = ISC_LIST_TAIL(adb->entries[bucket]);
1101			if (e == NULL)
1102				break;
1103			if (e->refcnt == 0) {
1104				unlink_entry(adb, e);
1105				free_adbentry(adb, &e);
1106				continue;
1107			}
1108			INSIST((e->flags & ENTRY_IS_DEAD) == 0);
1109			e->flags |= ENTRY_IS_DEAD;
1110			ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
1111			ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
1112		}
1113	}
1114
1115	ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
1116	entry->lock_bucket = bucket;
1117	adb->entry_refcnt[bucket]++;
1118}
1119
1120/*
1121 * Requires the entry's bucket be locked.
1122 */
1123static inline isc_boolean_t
1124unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
1125	int bucket;
1126	isc_boolean_t result = ISC_FALSE;
1127
1128	bucket = entry->lock_bucket;
1129	INSIST(bucket != DNS_ADB_INVALIDBUCKET);
1130
1131	if ((entry->flags & ENTRY_IS_DEAD) != 0)
1132		ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
1133	else
1134		ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
1135	entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1136	INSIST(adb->entry_refcnt[bucket] > 0);
1137	adb->entry_refcnt[bucket]--;
1138	if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
1139		result = ISC_TRUE;
1140	return (result);
1141}
1142
1143static inline void
1144violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
1145	if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
1146		UNLOCK(have);
1147		LOCK(want);
1148		LOCK(have);
1149	}
1150}
1151
1152/*
1153 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
1154 * checked after calling this function.
1155 */
1156static isc_boolean_t
1157shutdown_names(dns_adb_t *adb) {
1158	unsigned int bucket;
1159	isc_boolean_t result = ISC_FALSE;
1160	dns_adbname_t *name;
1161	dns_adbname_t *next_name;
1162
1163	for (bucket = 0; bucket < adb->nnames; bucket++) {
1164		LOCK(&adb->namelocks[bucket]);
1165		adb->name_sd[bucket] = ISC_TRUE;
1166
1167		name = ISC_LIST_HEAD(adb->names[bucket]);
1168		if (name == NULL) {
1169			/*
1170			 * This bucket has no names.  We must decrement the
1171			 * irefcnt ourselves, since it will not be
1172			 * automatically triggered by a name being unlinked.
1173			 */
1174			INSIST(result == ISC_FALSE);
1175			result = dec_adb_irefcnt(adb);
1176		} else {
1177			/*
1178			 * Run through the list.  For each name, clean up finds
1179			 * found there, and cancel any fetches running.  When
1180			 * all the fetches are canceled, the name will destroy
1181			 * itself.
1182			 */
1183			while (name != NULL) {
1184				next_name = ISC_LIST_NEXT(name, plink);
1185				INSIST(result == ISC_FALSE);
1186				result = kill_name(&name,
1187						   DNS_EVENT_ADBSHUTDOWN);
1188				name = next_name;
1189			}
1190		}
1191
1192		UNLOCK(&adb->namelocks[bucket]);
1193	}
1194	return (result);
1195}
1196
1197/*
1198 * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
1199 * checked after calling this function.
1200 */
1201static isc_boolean_t
1202shutdown_entries(dns_adb_t *adb) {
1203	unsigned int bucket;
1204	isc_boolean_t result = ISC_FALSE;
1205	dns_adbentry_t *entry;
1206	dns_adbentry_t *next_entry;
1207
1208	for (bucket = 0; bucket < adb->nentries; bucket++) {
1209		LOCK(&adb->entrylocks[bucket]);
1210		adb->entry_sd[bucket] = ISC_TRUE;
1211
1212		entry = ISC_LIST_HEAD(adb->entries[bucket]);
1213		if (adb->entry_refcnt[bucket] == 0) {
1214			/*
1215			 * This bucket has no entries.  We must decrement the
1216			 * irefcnt ourselves, since it will not be
1217			 * automatically triggered by an entry being unlinked.
1218			 */
1219			result = dec_adb_irefcnt(adb);
1220		} else {
1221			/*
1222			 * Run through the list.  Cleanup any entries not
1223			 * associated with names, and which are not in use.
1224			 */
1225			while (entry != NULL) {
1226				next_entry = ISC_LIST_NEXT(entry, plink);
1227				if (entry->refcnt == 0 &&
1228				    entry->expires != 0) {
1229					result = unlink_entry(adb, entry);
1230					free_adbentry(adb, &entry);
1231					if (result)
1232						result = dec_adb_irefcnt(adb);
1233				}
1234				entry = next_entry;
1235			}
1236		}
1237
1238		UNLOCK(&adb->entrylocks[bucket]);
1239	}
1240	return (result);
1241}
1242
1243/*
1244 * Name bucket must be locked
1245 */
1246static void
1247cancel_fetches_at_name(dns_adbname_t *name) {
1248	if (NAME_FETCH_A(name))
1249	    dns_resolver_cancelfetch(name->fetch_a->fetch);
1250
1251	if (NAME_FETCH_AAAA(name))
1252	    dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
1253}
1254
1255/*
1256 * Assumes the name bucket is locked.
1257 */
1258static isc_boolean_t
1259clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
1260	dns_adbentry_t *entry;
1261	dns_adbnamehook_t *namehook;
1262	int addr_bucket;
1263	isc_boolean_t result = ISC_FALSE;
1264	isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
1265
1266	addr_bucket = DNS_ADB_INVALIDBUCKET;
1267	namehook = ISC_LIST_HEAD(*namehooks);
1268	while (namehook != NULL) {
1269		INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
1270
1271		/*
1272		 * Clean up the entry if needed.
1273		 */
1274		entry = namehook->entry;
1275		if (entry != NULL) {
1276			INSIST(DNS_ADBENTRY_VALID(entry));
1277
1278			if (addr_bucket != entry->lock_bucket) {
1279				if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1280					UNLOCK(&adb->entrylocks[addr_bucket]);
1281				addr_bucket = entry->lock_bucket;
1282				LOCK(&adb->entrylocks[addr_bucket]);
1283			}
1284
1285			result = dec_entry_refcnt(adb, overmem, entry,
1286						  ISC_FALSE);
1287		}
1288
1289		/*
1290		 * Free the namehook
1291		 */
1292		namehook->entry = NULL;
1293		ISC_LIST_UNLINK(*namehooks, namehook, plink);
1294		free_adbnamehook(adb, &namehook);
1295
1296		namehook = ISC_LIST_HEAD(*namehooks);
1297	}
1298
1299	if (addr_bucket != DNS_ADB_INVALIDBUCKET)
1300		UNLOCK(&adb->entrylocks[addr_bucket]);
1301	return (result);
1302}
1303
1304static void
1305clean_target(dns_adb_t *adb, dns_name_t *target) {
1306	if (dns_name_countlabels(target) > 0) {
1307		dns_name_free(target, adb->mctx);
1308		dns_name_init(target, NULL);
1309	}
1310}
1311
1312static isc_result_t
1313set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
1314	   dns_rdataset_t *rdataset, dns_name_t *target)
1315{
1316	isc_result_t result;
1317	dns_namereln_t namereln;
1318	unsigned int nlabels;
1319	int order;
1320	dns_rdata_t rdata = DNS_RDATA_INIT;
1321	dns_fixedname_t fixed1, fixed2;
1322	dns_name_t *prefix, *new_target;
1323
1324	REQUIRE(dns_name_countlabels(target) == 0);
1325
1326	if (rdataset->type == dns_rdatatype_cname) {
1327		dns_rdata_cname_t cname;
1328
1329		/*
1330		 * Copy the CNAME's target into the target name.
1331		 */
1332		result = dns_rdataset_first(rdataset);
1333		if (result != ISC_R_SUCCESS)
1334			return (result);
1335		dns_rdataset_current(rdataset, &rdata);
1336		result = dns_rdata_tostruct(&rdata, &cname, NULL);
1337		if (result != ISC_R_SUCCESS)
1338			return (result);
1339		result = dns_name_dup(&cname.cname, adb->mctx, target);
1340		dns_rdata_freestruct(&cname);
1341		if (result != ISC_R_SUCCESS)
1342			return (result);
1343	} else {
1344		dns_rdata_dname_t dname;
1345
1346		INSIST(rdataset->type == dns_rdatatype_dname);
1347		namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
1348		INSIST(namereln == dns_namereln_subdomain);
1349		/*
1350		 * Get the target name of the DNAME.
1351		 */
1352		result = dns_rdataset_first(rdataset);
1353		if (result != ISC_R_SUCCESS)
1354			return (result);
1355		dns_rdataset_current(rdataset, &rdata);
1356		result = dns_rdata_tostruct(&rdata, &dname, NULL);
1357		if (result != ISC_R_SUCCESS)
1358			return (result);
1359		/*
1360		 * Construct the new target name.
1361		 */
1362		dns_fixedname_init(&fixed1);
1363		prefix = dns_fixedname_name(&fixed1);
1364		dns_fixedname_init(&fixed2);
1365		new_target = dns_fixedname_name(&fixed2);
1366		dns_name_split(name, nlabels, prefix, NULL);
1367		result = dns_name_concatenate(prefix, &dname.dname, new_target,
1368					      NULL);
1369		dns_rdata_freestruct(&dname);
1370		if (result != ISC_R_SUCCESS)
1371			return (result);
1372		result = dns_name_dup(new_target, adb->mctx, target);
1373		if (result != ISC_R_SUCCESS)
1374			return (result);
1375	}
1376
1377	return (ISC_R_SUCCESS);
1378}
1379
1380/*
1381 * Assumes nothing is locked, since this is called by the client.
1382 */
1383static void
1384event_free(isc_event_t *event) {
1385	dns_adbfind_t *find;
1386
1387	INSIST(event != NULL);
1388	find = event->ev_destroy_arg;
1389	INSIST(DNS_ADBFIND_VALID(find));
1390
1391	LOCK(&find->lock);
1392	find->flags |= FIND_EVENT_FREED;
1393	event->ev_destroy_arg = NULL;
1394	UNLOCK(&find->lock);
1395}
1396
1397/*
1398 * Assumes the name bucket is locked.
1399 */
1400static void
1401clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
1402		    unsigned int addrs)
1403{
1404	isc_event_t *ev;
1405	isc_task_t *task;
1406	dns_adbfind_t *find;
1407	dns_adbfind_t *next_find;
1408	isc_boolean_t process;
1409	unsigned int wanted, notify;
1410
1411	DP(ENTER_LEVEL,
1412	   "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
1413	   name, evtype, addrs);
1414
1415	find = ISC_LIST_HEAD(name->finds);
1416	while (find != NULL) {
1417		LOCK(&find->lock);
1418		next_find = ISC_LIST_NEXT(find, plink);
1419
1420		process = ISC_FALSE;
1421		wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1422		notify = wanted & addrs;
1423
1424		switch (evtype) {
1425		case DNS_EVENT_ADBMOREADDRESSES:
1426			DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
1427			if ((notify) != 0) {
1428				find->flags &= ~addrs;
1429				process = ISC_TRUE;
1430			}
1431			break;
1432		case DNS_EVENT_ADBNOMOREADDRESSES:
1433			DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
1434			find->flags &= ~addrs;
1435			wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
1436			if (wanted == 0)
1437				process = ISC_TRUE;
1438			break;
1439		default:
1440			find->flags &= ~addrs;
1441			process = ISC_TRUE;
1442		}
1443
1444		if (process) {
1445			DP(DEF_LEVEL, "cfan: processing find %p", find);
1446			/*
1447			 * Unlink the find from the name, letting the caller
1448			 * call dns_adb_destroyfind() on it to clean it up
1449			 * later.
1450			 */
1451			ISC_LIST_UNLINK(name->finds, find, plink);
1452			find->adbname = NULL;
1453			find->name_bucket = DNS_ADB_INVALIDBUCKET;
1454
1455			INSIST(!FIND_EVENTSENT(find));
1456
1457			ev = &find->event;
1458			task = ev->ev_sender;
1459			ev->ev_sender = find;
1460			find->result_v4 = find_err_map[name->fetch_err];
1461			find->result_v6 = find_err_map[name->fetch6_err];
1462			ev->ev_type = evtype;
1463			ev->ev_destroy = event_free;
1464			ev->ev_destroy_arg = find;
1465
1466			DP(DEF_LEVEL,
1467			   "sending event %p to task %p for find %p",
1468			   ev, task, find);
1469
1470			isc_task_sendanddetach(&task, (isc_event_t **)&ev);
1471		} else {
1472			DP(DEF_LEVEL, "cfan: skipping find %p", find);
1473		}
1474
1475		UNLOCK(&find->lock);
1476		find = next_find;
1477	}
1478
1479	DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
1480}
1481
1482static inline void
1483check_exit(dns_adb_t *adb) {
1484	isc_event_t *event;
1485	/*
1486	 * The caller must be holding the adb lock.
1487	 */
1488	if (adb->shutting_down) {
1489		/*
1490		 * If there aren't any external references either, we're
1491		 * done.  Send the control event to initiate shutdown.
1492		 */
1493		INSIST(!adb->cevent_sent);      /* Sanity check. */
1494		event = &adb->cevent;
1495		isc_task_send(adb->task, &event);
1496		adb->cevent_sent = ISC_TRUE;
1497	}
1498}
1499
1500static inline isc_boolean_t
1501dec_adb_irefcnt(dns_adb_t *adb) {
1502	isc_event_t *event;
1503	isc_task_t *etask;
1504	isc_boolean_t result = ISC_FALSE;
1505
1506	LOCK(&adb->reflock);
1507
1508	INSIST(adb->irefcnt > 0);
1509	adb->irefcnt--;
1510
1511	if (adb->irefcnt == 0) {
1512		event = ISC_LIST_HEAD(adb->whenshutdown);
1513		while (event != NULL) {
1514			ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
1515			etask = event->ev_sender;
1516			event->ev_sender = adb;
1517			isc_task_sendanddetach(&etask, &event);
1518			event = ISC_LIST_HEAD(adb->whenshutdown);
1519		}
1520	}
1521
1522	if (adb->irefcnt == 0 && adb->erefcnt == 0)
1523		result = ISC_TRUE;
1524	UNLOCK(&adb->reflock);
1525	return (result);
1526}
1527
1528static inline void
1529inc_adb_irefcnt(dns_adb_t *adb) {
1530	LOCK(&adb->reflock);
1531	adb->irefcnt++;
1532	UNLOCK(&adb->reflock);
1533}
1534
1535static inline void
1536inc_adb_erefcnt(dns_adb_t *adb) {
1537	LOCK(&adb->reflock);
1538	adb->erefcnt++;
1539	UNLOCK(&adb->reflock);
1540}
1541
1542static inline void
1543inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
1544	int bucket;
1545
1546	bucket = entry->lock_bucket;
1547
1548	if (lock)
1549		LOCK(&adb->entrylocks[bucket]);
1550
1551	entry->refcnt++;
1552
1553	if (lock)
1554		UNLOCK(&adb->entrylocks[bucket]);
1555}
1556
1557static inline isc_boolean_t
1558dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
1559		 isc_boolean_t lock)
1560{
1561	int bucket;
1562	isc_boolean_t destroy_entry;
1563	isc_boolean_t result = ISC_FALSE;
1564
1565	bucket = entry->lock_bucket;
1566
1567	if (lock)
1568		LOCK(&adb->entrylocks[bucket]);
1569
1570	INSIST(entry->refcnt > 0);
1571	entry->refcnt--;
1572
1573	destroy_entry = ISC_FALSE;
1574	if (entry->refcnt == 0 &&
1575	    (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
1576	     (entry->flags & ENTRY_IS_DEAD) != 0)) {
1577		destroy_entry = ISC_TRUE;
1578		result = unlink_entry(adb, entry);
1579	}
1580
1581	if (lock)
1582		UNLOCK(&adb->entrylocks[bucket]);
1583
1584	if (!destroy_entry)
1585		return (result);
1586
1587	entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
1588
1589	free_adbentry(adb, &entry);
1590	if (result)
1591		result = dec_adb_irefcnt(adb);
1592
1593	return (result);
1594}
1595
1596static inline dns_adbname_t *
1597new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
1598	dns_adbname_t *name;
1599
1600	name = isc_mempool_get(adb->nmp);
1601	if (name == NULL)
1602		return (NULL);
1603
1604	dns_name_init(&name->name, NULL);
1605	if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
1606		isc_mempool_put(adb->nmp, name);
1607		return (NULL);
1608	}
1609	dns_name_init(&name->target, NULL);
1610	name->magic = DNS_ADBNAME_MAGIC;
1611	name->adb = adb;
1612	name->partial_result = 0;
1613	name->flags = 0;
1614	name->expire_v4 = INT_MAX;
1615	name->expire_v6 = INT_MAX;
1616	name->expire_target = INT_MAX;
1617	name->chains = 0;
1618	name->lock_bucket = DNS_ADB_INVALIDBUCKET;
1619	ISC_LIST_INIT(name->v4);
1620	ISC_LIST_INIT(name->v6);
1621	name->fetch_a = NULL;
1622	name->fetch_aaaa = NULL;
1623	name->fetch_err = FIND_ERR_UNEXPECTED;
1624	name->fetch6_err = FIND_ERR_UNEXPECTED;
1625	ISC_LIST_INIT(name->finds);
1626	ISC_LINK_INIT(name, plink);
1627
1628	LOCK(&adb->namescntlock);
1629	adb->namescnt++;
1630	if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) {
1631		isc_event_t *event = &adb->grownames;
1632		inc_adb_irefcnt(adb);
1633		isc_task_send(adb->task, &event);
1634		adb->grownames_sent = ISC_TRUE;
1635	}
1636	UNLOCK(&adb->namescntlock);
1637
1638	return (name);
1639}
1640
1641static inline void
1642free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
1643	dns_adbname_t *n;
1644
1645	INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
1646	n = *name;
1647	*name = NULL;
1648
1649	INSIST(!NAME_HAS_V4(n));
1650	INSIST(!NAME_HAS_V6(n));
1651	INSIST(!NAME_FETCH(n));
1652	INSIST(ISC_LIST_EMPTY(n->finds));
1653	INSIST(!ISC_LINK_LINKED(n, plink));
1654	INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
1655	INSIST(n->adb == adb);
1656
1657	n->magic = 0;
1658	dns_name_free(&n->name, adb->mctx);
1659
1660	isc_mempool_put(adb->nmp, n);
1661	LOCK(&adb->namescntlock);
1662	adb->namescnt--;
1663	UNLOCK(&adb->namescntlock);
1664}
1665
1666static inline dns_adbnamehook_t *
1667new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
1668	dns_adbnamehook_t *nh;
1669
1670	nh = isc_mempool_get(adb->nhmp);
1671	if (nh == NULL)
1672		return (NULL);
1673
1674	nh->magic = DNS_ADBNAMEHOOK_MAGIC;
1675	nh->entry = entry;
1676	ISC_LINK_INIT(nh, plink);
1677
1678	return (nh);
1679}
1680
1681static inline void
1682free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
1683	dns_adbnamehook_t *nh;
1684
1685	INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
1686	nh = *namehook;
1687	*namehook = NULL;
1688
1689	INSIST(nh->entry == NULL);
1690	INSIST(!ISC_LINK_LINKED(nh, plink));
1691
1692	nh->magic = 0;
1693	isc_mempool_put(adb->nhmp, nh);
1694}
1695
1696static inline dns_adblameinfo_t *
1697new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
1698	dns_adblameinfo_t *li;
1699
1700	li = isc_mempool_get(adb->limp);
1701	if (li == NULL)
1702		return (NULL);
1703
1704	dns_name_init(&li->qname, NULL);
1705	if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
1706		isc_mempool_put(adb->limp, li);
1707		return (NULL);
1708	}
1709	li->magic = DNS_ADBLAMEINFO_MAGIC;
1710	li->lame_timer = 0;
1711	li->qtype = qtype;
1712	ISC_LINK_INIT(li, plink);
1713
1714	return (li);
1715}
1716
1717static inline void
1718free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
1719	dns_adblameinfo_t *li;
1720
1721	INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
1722	li = *lameinfo;
1723	*lameinfo = NULL;
1724
1725	INSIST(!ISC_LINK_LINKED(li, plink));
1726
1727	dns_name_free(&li->qname, adb->mctx);
1728
1729	li->magic = 0;
1730
1731	isc_mempool_put(adb->limp, li);
1732}
1733
1734static inline dns_adbentry_t *
1735new_adbentry(dns_adb_t *adb) {
1736	dns_adbentry_t *e;
1737	isc_uint32_t r;
1738
1739	e = isc_mempool_get(adb->emp);
1740	if (e == NULL)
1741		return (NULL);
1742
1743	e->magic = DNS_ADBENTRY_MAGIC;
1744	e->lock_bucket = DNS_ADB_INVALIDBUCKET;
1745	e->refcnt = 0;
1746	e->flags = 0;
1747	isc_random_get(&r);
1748	e->srtt = (r & 0x1f) + 1;
1749	e->expires = 0;
1750	ISC_LIST_INIT(e->lameinfo);
1751	ISC_LINK_INIT(e, plink);
1752	LOCK(&adb->entriescntlock);
1753	adb->entriescnt++;
1754	if (!adb->growentries_sent &&
1755	    adb->entriescnt > (adb->nentries * 8)) {
1756		isc_event_t *event = &adb->growentries;
1757		inc_adb_irefcnt(adb);
1758		isc_task_send(adb->task, 

Large files files are truncated, but you can click here to view the full file