adb.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file
00019  *
00020  * \note
00021  * In finds, if task == NULL, no events will be generated, and no events
00022  * have been sent.  If task != NULL but taskaction == NULL, an event has been
00023  * posted but not yet freed.  If neither are NULL, no event was posted.
00024  *
00025  */
00026 
00027 #include <config.h>
00028 
00029 #include <limits.h>
00030 
00031 #include <isc/mutexblock.h>
00032 #include <isc/netaddr.h>
00033 #include <isc/random.h>
00034 #include <isc/stats.h>
00035 #include <isc/string.h>         /* Required for HP/UX (and others?) */
00036 #include <isc/task.h>
00037 #include <isc/util.h>
00038 
00039 #include <dns/adb.h>
00040 #include <dns/db.h>
00041 #include <dns/events.h>
00042 #include <dns/log.h>
00043 #include <dns/rdata.h>
00044 #include <dns/rdataset.h>
00045 #include <dns/rdatastruct.h>
00046 #include <dns/rdatatype.h>
00047 #include <dns/resolver.h>
00048 #include <dns/result.h>
00049 #include <dns/stats.h>
00050 
00051 #define DNS_ADB_MAGIC             ISC_MAGIC('D', 'a', 'd', 'b')
00052 #define DNS_ADB_VALID(x)          ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
00053 #define DNS_ADBNAME_MAGIC         ISC_MAGIC('a', 'd', 'b', 'N')
00054 #define DNS_ADBNAME_VALID(x)      ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
00055 #define DNS_ADBNAMEHOOK_MAGIC     ISC_MAGIC('a', 'd', 'N', 'H')
00056 #define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
00057 #define DNS_ADBLAMEINFO_MAGIC     ISC_MAGIC('a', 'd', 'b', 'Z')
00058 #define DNS_ADBLAMEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
00059 #define DNS_ADBENTRY_MAGIC        ISC_MAGIC('a', 'd', 'b', 'E')
00060 #define DNS_ADBENTRY_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
00061 #define DNS_ADBFETCH_MAGIC        ISC_MAGIC('a', 'd', 'F', '4')
00062 #define DNS_ADBFETCH_VALID(x)     ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
00063 #define DNS_ADBFETCH6_MAGIC       ISC_MAGIC('a', 'd', 'F', '6')
00064 #define DNS_ADBFETCH6_VALID(x)    ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
00065 
00066 /*!
00067  * For type 3 negative cache entries, we will remember that the address is
00068  * broken for this long.  XXXMLG This is also used for actual addresses, too.
00069  * The intent is to keep us from constantly asking about A/AAAA records
00070  * if the zone has extremely low TTLs.
00071  */
00072 #define ADB_CACHE_MINIMUM       10      /*%< seconds */
00073 #define ADB_CACHE_MAXIMUM       86400   /*%< seconds (86400 = 24 hours) */
00074 #define ADB_ENTRY_WINDOW        1800    /*%< seconds */
00075 
00076 /*%
00077  * The period in seconds after which an ADB name entry is regarded as stale
00078  * and forced to be cleaned up.
00079  * TODO: This should probably be configurable at run-time.
00080  */
00081 #ifndef ADB_STALE_MARGIN
00082 #define ADB_STALE_MARGIN        1800
00083 #endif
00084 
00085 #define FREE_ITEMS              64      /*%< free count for memory pools */
00086 #define FILL_COUNT              16      /*%< fill count for memory pools */
00087 
00088 #define DNS_ADB_INVALIDBUCKET (-1)      /*%< invalid bucket address */
00089 
00090 #define DNS_ADB_MINADBSIZE      (1024U*1024U)     /*%< 1 Megabyte */
00091 
00092 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
00093 typedef struct dns_adbnamehook dns_adbnamehook_t;
00094 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
00095 typedef struct dns_adblameinfo dns_adblameinfo_t;
00096 typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
00097 typedef struct dns_adbfetch dns_adbfetch_t;
00098 typedef struct dns_adbfetch6 dns_adbfetch6_t;
00099 
00100 /*% dns adb structure */
00101 struct dns_adb {
00102         unsigned int                    magic;
00103 
00104         isc_mutex_t                     lock;
00105         isc_mutex_t                     reflock; /*%< Covers irefcnt, erefcnt */
00106         isc_mutex_t                     overmemlock; /*%< Covers overmem */
00107         isc_mem_t                      *mctx;
00108         dns_view_t                     *view;
00109 
00110         isc_taskmgr_t                  *taskmgr;
00111         isc_task_t                     *task;
00112         isc_task_t                     *excl;
00113 
00114         isc_interval_t                  tick_interval;
00115         int                             next_cleanbucket;
00116 
00117         unsigned int                    irefcnt;
00118         unsigned int                    erefcnt;
00119 
00120         isc_mutex_t                     mplock;
00121         isc_mempool_t                  *nmp;    /*%< dns_adbname_t */
00122         isc_mempool_t                  *nhmp;   /*%< dns_adbnamehook_t */
00123         isc_mempool_t                  *limp;   /*%< dns_adblameinfo_t */
00124         isc_mempool_t                  *emp;    /*%< dns_adbentry_t */
00125         isc_mempool_t                  *ahmp;   /*%< dns_adbfind_t */
00126         isc_mempool_t                  *aimp;   /*%< dns_adbaddrinfo_t */
00127         isc_mempool_t                  *afmp;   /*%< dns_adbfetch_t */
00128 
00129         /*!
00130          * Bucketized locks and lists for names.
00131          *
00132          * XXXRTH  Have a per-bucket structure that contains all of these?
00133          */
00134         unsigned int                    nnames;
00135         isc_mutex_t                     namescntlock;
00136         unsigned int                    namescnt;
00137         dns_adbnamelist_t               *names;
00138         dns_adbnamelist_t               *deadnames;
00139         isc_mutex_t                     *namelocks;
00140         isc_boolean_t                   *name_sd;
00141         unsigned int                    *name_refcnt;
00142 
00143         /*!
00144          * Bucketized locks and lists for entries.
00145          *
00146          * XXXRTH  Have a per-bucket structure that contains all of these?
00147          */
00148         unsigned int                    nentries;
00149         isc_mutex_t                     entriescntlock;
00150         unsigned int                    entriescnt;
00151         dns_adbentrylist_t              *entries;
00152         dns_adbentrylist_t              *deadentries;
00153         isc_mutex_t                     *entrylocks;
00154         isc_boolean_t                   *entry_sd; /*%< shutting down */
00155         unsigned int                    *entry_refcnt;
00156 
00157         isc_event_t                     cevent;
00158         isc_boolean_t                   cevent_out;
00159         isc_boolean_t                   shutting_down;
00160         isc_eventlist_t                 whenshutdown;
00161         isc_event_t                     growentries;
00162         isc_boolean_t                   growentries_sent;
00163         isc_event_t                     grownames;
00164         isc_boolean_t                   grownames_sent;
00165 };
00166 
00167 /*
00168  * XXXMLG  Document these structures.
00169  */
00170 
00171 /*% dns_adbname structure */
00172 struct dns_adbname {
00173         unsigned int                    magic;
00174         dns_name_t                      name;
00175         dns_adb_t                      *adb;
00176         unsigned int                    partial_result;
00177         unsigned int                    flags;
00178         int                             lock_bucket;
00179         dns_name_t                      target;
00180         isc_stdtime_t                   expire_target;
00181         isc_stdtime_t                   expire_v4;
00182         isc_stdtime_t                   expire_v6;
00183         unsigned int                    chains;
00184         dns_adbnamehooklist_t           v4;
00185         dns_adbnamehooklist_t           v6;
00186         dns_adbfetch_t                 *fetch_a;
00187         dns_adbfetch_t                 *fetch_aaaa;
00188         unsigned int                    fetch_err;
00189         unsigned int                    fetch6_err;
00190         dns_adbfindlist_t               finds;
00191         /* for LRU-based management */
00192         isc_stdtime_t                   last_used;
00193 
00194         ISC_LINK(dns_adbname_t)         plink;
00195 };
00196 
00197 /*% The adbfetch structure */
00198 struct dns_adbfetch {
00199         unsigned int                    magic;
00200         dns_fetch_t                    *fetch;
00201         dns_rdataset_t                  rdataset;
00202         unsigned int                    depth;
00203 };
00204 
00205 /*%
00206  * This is a small widget that dangles off a dns_adbname_t.  It contains a
00207  * pointer to the address information about this host, and a link to the next
00208  * namehook that will contain the next address this host has.
00209  */
00210 struct dns_adbnamehook {
00211         unsigned int                    magic;
00212         dns_adbentry_t                 *entry;
00213         ISC_LINK(dns_adbnamehook_t)     plink;
00214 };
00215 
00216 /*%
00217  * This is a small widget that holds qname-specific information about an
00218  * address.  Currently limited to lameness, but could just as easily be
00219  * extended to other types of information about zones.
00220  */
00221 struct dns_adblameinfo {
00222         unsigned int                    magic;
00223 
00224         dns_name_t                      qname;
00225         dns_rdatatype_t                 qtype;
00226         isc_stdtime_t                   lame_timer;
00227 
00228         ISC_LINK(dns_adblameinfo_t)     plink;
00229 };
00230 
00231 /*%
00232  * An address entry.  It holds quite a bit of information about addresses,
00233  * including edns state (in "flags"), rtt, and of course the address of
00234  * the host.
00235  */
00236 struct dns_adbentry {
00237         unsigned int                    magic;
00238 
00239         int                             lock_bucket;
00240         unsigned int                    refcnt;
00241 
00242         unsigned int                    flags;
00243         unsigned int                    srtt;
00244         isc_uint16_t                    udpsize;
00245         unsigned char                   plain;
00246         unsigned char                   plainto;
00247         unsigned char                   edns;
00248         unsigned char                   to4096;         /* Our max. */
00249         /*
00250          * Allow for encapsulated IPv4/IPv6 UDP packet over ethernet.
00251          * Ethernet 1500 - IP(20) - IP6(40) - UDP(8) = 1432.
00252          */
00253         unsigned char                   to1432;         /* Ethernet */
00254         unsigned char                   to1232;         /* IPv6 nofrag */
00255         unsigned char                   to512;          /* plain DNS */
00256         isc_sockaddr_t                  sockaddr;
00257         unsigned char *                 sit;
00258         isc_uint16_t                    sitlen;
00259 
00260         isc_stdtime_t                   expires;
00261         isc_stdtime_t                   lastage;
00262         /*%<
00263          * A nonzero 'expires' field indicates that the entry should
00264          * persist until that time.  This allows entries found
00265          * using dns_adb_findaddrinfo() to persist for a limited time
00266          * even though they are not necessarily associated with a
00267          * name.
00268          */
00269 
00270         ISC_LIST(dns_adblameinfo_t)     lameinfo;
00271         ISC_LINK(dns_adbentry_t)        plink;
00272 };
00273 
00274 /*
00275  * Internal functions (and prototypes).
00276  */
00277 static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
00278 static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
00279 static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
00280                                                  dns_adbentry_t *);
00281 static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
00282 static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
00283                                                  dns_rdatatype_t);
00284 static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
00285 static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
00286 static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
00287 static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
00288 static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
00289 static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
00290                                                  in_port_t);
00291 static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
00292 static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
00293 static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
00294                                                 unsigned int, int *);
00295 static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
00296                                                   isc_sockaddr_t *, int *,
00297                                                   isc_stdtime_t);
00298 static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
00299 static void print_dns_name(FILE *, dns_name_t *);
00300 static void print_namehook_list(FILE *, const char *legend,
00301                                 dns_adbnamehooklist_t *list,
00302                                 isc_boolean_t debug,
00303                                 isc_stdtime_t now);
00304 static void print_find_list(FILE *, dns_adbname_t *);
00305 static void print_fetch_list(FILE *, dns_adbname_t *);
00306 static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
00307 static inline void inc_adb_irefcnt(dns_adb_t *);
00308 static inline void inc_adb_erefcnt(dns_adb_t *);
00309 static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
00310                                     isc_boolean_t);
00311 static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
00312                                              dns_adbentry_t *, isc_boolean_t);
00313 static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
00314 static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
00315 static void clean_target(dns_adb_t *, dns_name_t *);
00316 static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
00317 static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
00318 static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
00319                                         isc_stdtime_t);
00320 static void cancel_fetches_at_name(dns_adbname_t *);
00321 static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
00322                                 dns_rdatatype_t);
00323 static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
00324                                unsigned int, isc_counter_t *qc,
00325                                dns_rdatatype_t);
00326 static inline void check_exit(dns_adb_t *);
00327 static void destroy(dns_adb_t *);
00328 static isc_boolean_t shutdown_names(dns_adb_t *);
00329 static isc_boolean_t shutdown_entries(dns_adb_t *);
00330 static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
00331 static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
00332 static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
00333 static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
00334 static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
00335 static void water(void *, int);
00336 static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
00337 static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt,
00338                        unsigned int factor, isc_stdtime_t now);
00339 static void shutdown_task(isc_task_t *task, isc_event_t *ev);
00340 
00341 /*
00342  * MUST NOT overlap DNS_ADBFIND_* flags!
00343  */
00344 #define FIND_EVENT_SENT         0x40000000
00345 #define FIND_EVENT_FREED        0x80000000
00346 #define FIND_EVENTSENT(h)       (((h)->flags & FIND_EVENT_SENT) != 0)
00347 #define FIND_EVENTFREED(h)      (((h)->flags & FIND_EVENT_FREED) != 0)
00348 
00349 #define NAME_NEEDS_POKE         0x80000000
00350 #define NAME_IS_DEAD            0x40000000
00351 #define NAME_HINT_OK            DNS_ADBFIND_HINTOK
00352 #define NAME_GLUE_OK            DNS_ADBFIND_GLUEOK
00353 #define NAME_STARTATZONE        DNS_ADBFIND_STARTATZONE
00354 #define NAME_DEAD(n)            (((n)->flags & NAME_IS_DEAD) != 0)
00355 #define NAME_NEEDSPOKE(n)       (((n)->flags & NAME_NEEDS_POKE) != 0)
00356 #define NAME_GLUEOK(n)          (((n)->flags & NAME_GLUE_OK) != 0)
00357 #define NAME_HINTOK(n)          (((n)->flags & NAME_HINT_OK) != 0)
00358 
00359 /*
00360  * Private flag(s) for entries.
00361  * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
00362  */
00363 #define ENTRY_IS_DEAD           0x00400000
00364 
00365 /*
00366  * To the name, address classes are all that really exist.  If it has a
00367  * V6 address it doesn't care if it came from a AAAA query.
00368  */
00369 #define NAME_HAS_V4(n)          (!ISC_LIST_EMPTY((n)->v4))
00370 #define NAME_HAS_V6(n)          (!ISC_LIST_EMPTY((n)->v6))
00371 #define NAME_HAS_ADDRS(n)       (NAME_HAS_V4(n) || NAME_HAS_V6(n))
00372 
00373 /*
00374  * Fetches are broken out into A and AAAA types.  In some cases,
00375  * however, it makes more sense to test for a particular class of fetches,
00376  * like V4 or V6 above.
00377  * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
00378  * are now equal to FETCH_V4 and FETCH_V6, respectively.
00379  */
00380 #define NAME_FETCH_A(n)         ((n)->fetch_a != NULL)
00381 #define NAME_FETCH_AAAA(n)      ((n)->fetch_aaaa != NULL)
00382 #define NAME_FETCH_V4(n)        (NAME_FETCH_A(n))
00383 #define NAME_FETCH_V6(n)        (NAME_FETCH_AAAA(n))
00384 #define NAME_FETCH(n)           (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
00385 
00386 /*
00387  * Find options and tests to see if there are addresses on the list.
00388  */
00389 #define FIND_WANTEVENT(fn)      (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
00390 #define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
00391 #define FIND_AVOIDFETCHES(fn)   (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
00392                                  != 0)
00393 #define FIND_STARTATZONE(fn)    (((fn)->options & DNS_ADBFIND_STARTATZONE) \
00394                                  != 0)
00395 #define FIND_HINTOK(fn)         (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
00396 #define FIND_GLUEOK(fn)         (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
00397 #define FIND_HAS_ADDRS(fn)      (!ISC_LIST_EMPTY((fn)->list))
00398 #define FIND_RETURNLAME(fn)     (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
00399 
00400 /*
00401  * These are currently used on simple unsigned ints, so they are
00402  * not really associated with any particular type.
00403  */
00404 #define WANT_INET(x)            (((x) & DNS_ADBFIND_INET) != 0)
00405 #define WANT_INET6(x)           (((x) & DNS_ADBFIND_INET6) != 0)
00406 
00407 #define EXPIRE_OK(exp, now)     ((exp == INT_MAX) || (exp < now))
00408 
00409 /*
00410  * Find out if the flags on a name (nf) indicate if it is a hint or
00411  * glue, and compare this to the appropriate bits set in o, to see if
00412  * this is ok.
00413  */
00414 #define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
00415 #define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
00416 #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
00417 #define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
00418                                     ((o) & DNS_ADBFIND_STARTATZONE))
00419 
00420 #define ENTER_LEVEL             ISC_LOG_DEBUG(50)
00421 #define EXIT_LEVEL              ENTER_LEVEL
00422 #define CLEAN_LEVEL             ISC_LOG_DEBUG(100)
00423 #define DEF_LEVEL               ISC_LOG_DEBUG(5)
00424 #define NCACHE_LEVEL            ISC_LOG_DEBUG(20)
00425 
00426 #define NCACHE_RESULT(r)        ((r) == DNS_R_NCACHENXDOMAIN || \
00427                                  (r) == DNS_R_NCACHENXRRSET)
00428 #define AUTH_NX(r)              ((r) == DNS_R_NXDOMAIN || \
00429                                  (r) == DNS_R_NXRRSET)
00430 #define NXDOMAIN_RESULT(r)      ((r) == DNS_R_NXDOMAIN || \
00431                                  (r) == DNS_R_NCACHENXDOMAIN)
00432 #define NXRRSET_RESULT(r)       ((r) == DNS_R_NCACHENXRRSET || \
00433                                  (r) == DNS_R_NXRRSET || \
00434                                  (r) == DNS_R_HINTNXRRSET)
00435 
00436 /*
00437  * Error state rankings.
00438  */
00439 
00440 #define FIND_ERR_SUCCESS                0  /* highest rank */
00441 #define FIND_ERR_CANCELED               1
00442 #define FIND_ERR_FAILURE                2
00443 #define FIND_ERR_NXDOMAIN               3
00444 #define FIND_ERR_NXRRSET                4
00445 #define FIND_ERR_UNEXPECTED             5
00446 #define FIND_ERR_NOTFOUND               6
00447 #define FIND_ERR_MAX                    7
00448 
00449 static const char *errnames[] = {
00450         "success",
00451         "canceled",
00452         "failure",
00453         "nxdomain",
00454         "nxrrset",
00455         "unexpected",
00456         "not_found"
00457 };
00458 
00459 #define NEWERR(old, new)        (ISC_MIN((old), (new)))
00460 
00461 static isc_result_t find_err_map[FIND_ERR_MAX] = {
00462         ISC_R_SUCCESS,
00463         ISC_R_CANCELED,
00464         ISC_R_FAILURE,
00465         DNS_R_NXDOMAIN,
00466         DNS_R_NXRRSET,
00467         ISC_R_UNEXPECTED,
00468         ISC_R_NOTFOUND          /* not YET found */
00469 };
00470 
00471 static void
00472 DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
00473 
00474 static void
00475 DP(int level, const char *format, ...) {
00476         va_list args;
00477 
00478         va_start(args, format);
00479         isc_log_vwrite(dns_lctx,
00480                        DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
00481                        level, format, args);
00482         va_end(args);
00483 }
00484 
00485 /*%
00486  * Increment resolver-related statistics counters.
00487  */
00488 static inline void
00489 inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
00490         if (adb->view->resstats != NULL)
00491                 isc_stats_increment(adb->view->resstats, counter);
00492 }
00493 
00494 /*%
00495  * Set adb-related statistics counters.
00496  */
00497 static inline void
00498 set_adbstat(dns_adb_t *adb, isc_uint64_t val, isc_statscounter_t counter) {
00499         if (adb->view->adbstats != NULL)
00500                 isc_stats_set(adb->view->adbstats, val, counter);
00501 }
00502 
00503 static inline void
00504 dec_adbstats(dns_adb_t *adb, isc_statscounter_t counter) {
00505         if (adb->view->adbstats != NULL)
00506                 isc_stats_decrement(adb->view->adbstats, counter);
00507 }
00508 
00509 static inline void
00510 inc_adbstats(dns_adb_t *adb, isc_statscounter_t counter) {
00511         if (adb->view->adbstats != NULL)
00512                 isc_stats_increment(adb->view->adbstats, counter);
00513 }
00514 
00515 static inline dns_ttl_t
00516 ttlclamp(dns_ttl_t ttl) {
00517         if (ttl < ADB_CACHE_MINIMUM)
00518                 ttl = ADB_CACHE_MINIMUM;
00519         if (ttl > ADB_CACHE_MAXIMUM)
00520                 ttl = ADB_CACHE_MAXIMUM;
00521 
00522         return (ttl);
00523 }
00524 
00525 /*
00526  * Hashing is most efficient if the number of buckets is prime.
00527  * The sequence below is the closest previous primes to 2^n and
00528  * 1.5 * 2^n, for values of n from 10 to 28.  (The tables will
00529  * no longer grow beyond 2^28 entries.)
00530  */
00531 static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
00532                                      8191, 12281, 16381, 24571, 32749,
00533                                      49193, 65521, 98299, 131071, 199603,
00534                                      262139, 393209, 524287, 768431, 1048573,
00535                                      1572853, 2097143, 3145721, 4194301,
00536                                      6291449, 8388593, 12582893, 16777213,
00537                                      25165813, 33554393, 50331599, 67108859,
00538                                      100663291, 134217689, 201326557,
00539                                      268535431, 0 };
00540 
00541 static void
00542 grow_entries(isc_task_t *task, isc_event_t *ev) {
00543         dns_adb_t *adb;
00544         dns_adbentry_t *e;
00545         dns_adbentrylist_t *newdeadentries = NULL;
00546         dns_adbentrylist_t *newentries = NULL;
00547         isc_boolean_t *newentry_sd = NULL;
00548         isc_mutex_t *newentrylocks = NULL;
00549         isc_result_t result;
00550         unsigned int *newentry_refcnt = NULL;
00551         unsigned int i, n, bucket;
00552 
00553         adb = ev->ev_arg;
00554         INSIST(DNS_ADB_VALID(adb));
00555 
00556         isc_event_free(&ev);
00557 
00558         result = isc_task_beginexclusive(task);
00559         if (result != ISC_R_SUCCESS)
00560                 goto check_exit;
00561 
00562         i = 0;
00563         while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
00564                 i++;
00565         if (nbuckets[i] != 0)
00566                 n = nbuckets[i];
00567         else
00568                 goto done;
00569 
00570         DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
00571 
00572         /*
00573          * Are we shutting down?
00574          */
00575         for (i = 0; i < adb->nentries; i++)
00576                 if (adb->entry_sd[i])
00577                         goto cleanup;
00578 
00579         /*
00580          * Grab all the resources we need.
00581          */
00582         newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
00583         newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
00584         newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
00585         newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
00586         newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
00587         if (newentries == NULL || newdeadentries == NULL ||
00588             newentrylocks == NULL || newentry_sd == NULL ||
00589             newentry_refcnt == NULL)
00590                 goto cleanup;
00591 
00592         /*
00593          * Initialise the new resources.
00594          */
00595         result = isc_mutexblock_init(newentrylocks, n);
00596         if (result != ISC_R_SUCCESS)
00597                 goto cleanup;
00598 
00599         for (i = 0; i < n; i++) {
00600                 ISC_LIST_INIT(newentries[i]);
00601                 ISC_LIST_INIT(newdeadentries[i]);
00602                 newentry_sd[i] = ISC_FALSE;
00603                 newentry_refcnt[i] = 0;
00604                 adb->irefcnt++;
00605         }
00606 
00607         /*
00608          * Move entries to new arrays.
00609          */
00610         for (i = 0; i < adb->nentries; i++) {
00611                 e = ISC_LIST_HEAD(adb->entries[i]);
00612                 while (e != NULL) {
00613                         ISC_LIST_UNLINK(adb->entries[i], e, plink);
00614                         bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
00615                         e->lock_bucket = bucket;
00616                         ISC_LIST_APPEND(newentries[bucket], e, plink);
00617                         INSIST(adb->entry_refcnt[i] > 0);
00618                         adb->entry_refcnt[i]--;
00619                         newentry_refcnt[bucket]++;
00620                         e = ISC_LIST_HEAD(adb->entries[i]);
00621                 }
00622                 e = ISC_LIST_HEAD(adb->deadentries[i]);
00623                 while (e != NULL) {
00624                         ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
00625                         bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
00626                         e->lock_bucket = bucket;
00627                         ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
00628                         INSIST(adb->entry_refcnt[i] > 0);
00629                         adb->entry_refcnt[i]--;
00630                         newentry_refcnt[bucket]++;
00631                         e = ISC_LIST_HEAD(adb->deadentries[i]);
00632                 }
00633                 INSIST(adb->entry_refcnt[i] == 0);
00634                 adb->irefcnt--;
00635         }
00636 
00637         /*
00638          * Cleanup old resources.
00639          */
00640         DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
00641         isc_mem_put(adb->mctx, adb->entries,
00642                     sizeof(*adb->entries) * adb->nentries);
00643         isc_mem_put(adb->mctx, adb->deadentries,
00644                     sizeof(*adb->deadentries) * adb->nentries);
00645         isc_mem_put(adb->mctx, adb->entrylocks,
00646                     sizeof(*adb->entrylocks) * adb->nentries);
00647         isc_mem_put(adb->mctx, adb->entry_sd,
00648                     sizeof(*adb->entry_sd) * adb->nentries);
00649         isc_mem_put(adb->mctx, adb->entry_refcnt,
00650                     sizeof(*adb->entry_refcnt) * adb->nentries);
00651 
00652         /*
00653          * Install new resources.
00654          */
00655         adb->entries = newentries;
00656         adb->deadentries = newdeadentries;
00657         adb->entrylocks = newentrylocks;
00658         adb->entry_sd = newentry_sd;
00659         adb->entry_refcnt = newentry_refcnt;
00660         adb->nentries = n;
00661 
00662         set_adbstat(adb, adb->nentries, dns_adbstats_nentries);
00663 
00664         /*
00665          * Only on success do we set adb->growentries_sent to ISC_FALSE.
00666          * This will prevent us being continuously being called on error.
00667          */
00668         adb->growentries_sent = ISC_FALSE;
00669         goto done;
00670 
00671  cleanup:
00672         if (newentries != NULL)
00673                 isc_mem_put(adb->mctx, newentries,
00674                             sizeof(*newentries) * n);
00675         if (newdeadentries != NULL)
00676                 isc_mem_put(adb->mctx, newdeadentries,
00677                             sizeof(*newdeadentries) * n);
00678         if (newentrylocks != NULL)
00679                 isc_mem_put(adb->mctx, newentrylocks,
00680                             sizeof(*newentrylocks) * n);
00681         if (newentry_sd != NULL)
00682                 isc_mem_put(adb->mctx, newentry_sd,
00683                             sizeof(*newentry_sd) * n);
00684         if (newentry_refcnt != NULL)
00685                 isc_mem_put(adb->mctx, newentry_refcnt,
00686                              sizeof(*newentry_refcnt) * n);
00687  done:
00688         isc_task_endexclusive(task);
00689 
00690  check_exit:
00691         LOCK(&adb->lock);
00692         if (dec_adb_irefcnt(adb))
00693                 check_exit(adb);
00694         UNLOCK(&adb->lock);
00695         DP(ISC_LOG_INFO, "adb: grow_entries finished");
00696 }
00697 
00698 static void
00699 grow_names(isc_task_t *task, isc_event_t *ev) {
00700         dns_adb_t *adb;
00701         dns_adbname_t *name;
00702         dns_adbnamelist_t *newdeadnames = NULL;
00703         dns_adbnamelist_t *newnames = NULL;
00704         isc_boolean_t *newname_sd = NULL;
00705         isc_mutex_t *newnamelocks = NULL;
00706         isc_result_t result;
00707         unsigned int *newname_refcnt = NULL;
00708         unsigned int i, n, bucket;
00709 
00710         adb = ev->ev_arg;
00711         INSIST(DNS_ADB_VALID(adb));
00712 
00713         isc_event_free(&ev);
00714 
00715         result = isc_task_beginexclusive(task);
00716         if (result != ISC_R_SUCCESS)
00717                 goto check_exit;
00718 
00719         i = 0;
00720         while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
00721                 i++;
00722         if (nbuckets[i] != 0)
00723                 n = nbuckets[i];
00724         else
00725                 goto done;
00726 
00727         DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
00728 
00729         /*
00730          * Are we shutting down?
00731          */
00732         for (i = 0; i < adb->nnames; i++)
00733                 if (adb->name_sd[i])
00734                         goto cleanup;
00735 
00736         /*
00737          * Grab all the resources we need.
00738          */
00739         newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
00740         newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
00741         newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
00742         newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
00743         newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
00744         if (newnames == NULL || newdeadnames == NULL ||
00745             newnamelocks == NULL || newname_sd == NULL ||
00746             newname_refcnt == NULL)
00747                 goto cleanup;
00748 
00749         /*
00750          * Initialise the new resources.
00751          */
00752         result = isc_mutexblock_init(newnamelocks, n);
00753         if (result != ISC_R_SUCCESS)
00754                 goto cleanup;
00755 
00756         for (i = 0; i < n; i++) {
00757                 ISC_LIST_INIT(newnames[i]);
00758                 ISC_LIST_INIT(newdeadnames[i]);
00759                 newname_sd[i] = ISC_FALSE;
00760                 newname_refcnt[i] = 0;
00761                 adb->irefcnt++;
00762         }
00763 
00764         /*
00765          * Move names to new arrays.
00766          */
00767         for (i = 0; i < adb->nnames; i++) {
00768                 name = ISC_LIST_HEAD(adb->names[i]);
00769                 while (name != NULL) {
00770                         ISC_LIST_UNLINK(adb->names[i], name, plink);
00771                         bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
00772                         name->lock_bucket = bucket;
00773                         ISC_LIST_APPEND(newnames[bucket], name, plink);
00774                         INSIST(adb->name_refcnt[i] > 0);
00775                         adb->name_refcnt[i]--;
00776                         newname_refcnt[bucket]++;
00777                         name = ISC_LIST_HEAD(adb->names[i]);
00778                 }
00779                 name = ISC_LIST_HEAD(adb->deadnames[i]);
00780                 while (name != NULL) {
00781                         ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
00782                         bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
00783                         name->lock_bucket = bucket;
00784                         ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
00785                         INSIST(adb->name_refcnt[i] > 0);
00786                         adb->name_refcnt[i]--;
00787                         newname_refcnt[bucket]++;
00788                         name = ISC_LIST_HEAD(adb->deadnames[i]);
00789                 }
00790                 INSIST(adb->name_refcnt[i] == 0);
00791                 adb->irefcnt--;
00792         }
00793 
00794         /*
00795          * Cleanup old resources.
00796          */
00797         DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
00798         isc_mem_put(adb->mctx, adb->names,
00799                     sizeof(*adb->names) * adb->nnames);
00800         isc_mem_put(adb->mctx, adb->deadnames,
00801                     sizeof(*adb->deadnames) * adb->nnames);
00802         isc_mem_put(adb->mctx, adb->namelocks,
00803                     sizeof(*adb->namelocks) * adb->nnames);
00804         isc_mem_put(adb->mctx, adb->name_sd,
00805                     sizeof(*adb->name_sd) * adb->nnames);
00806         isc_mem_put(adb->mctx, adb->name_refcnt,
00807                     sizeof(*adb->name_refcnt) * adb->nnames);
00808 
00809         /*
00810          * Install new resources.
00811          */
00812         adb->names = newnames;
00813         adb->deadnames = newdeadnames;
00814         adb->namelocks = newnamelocks;
00815         adb->name_sd = newname_sd;
00816         adb->name_refcnt = newname_refcnt;
00817         adb->nnames = n;
00818 
00819         set_adbstat(adb, adb->nnames, dns_adbstats_nnames);
00820 
00821         /*
00822          * Only on success do we set adb->grownames_sent to ISC_FALSE.
00823          * This will prevent us being continuously being called on error.
00824          */
00825         adb->grownames_sent = ISC_FALSE;
00826         goto done;
00827 
00828  cleanup:
00829         if (newnames != NULL)
00830                 isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
00831         if (newdeadnames != NULL)
00832                 isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
00833         if (newnamelocks != NULL)
00834                 isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
00835         if (newname_sd != NULL)
00836                 isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
00837         if (newname_refcnt != NULL)
00838                 isc_mem_put(adb->mctx, newname_refcnt,
00839                              sizeof(*newname_refcnt) * n);
00840  done:
00841         isc_task_endexclusive(task);
00842 
00843  check_exit:
00844         LOCK(&adb->lock);
00845         if (dec_adb_irefcnt(adb))
00846                 check_exit(adb);
00847         UNLOCK(&adb->lock);
00848         DP(ISC_LOG_INFO, "adb: grow_names finished");
00849 }
00850 
00851 /*
00852  * Requires the adbname bucket be locked and that no entry buckets be locked.
00853  *
00854  * This code handles A and AAAA rdatasets only.
00855  */
00856 static isc_result_t
00857 import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
00858                 isc_stdtime_t now)
00859 {
00860         isc_result_t result;
00861         dns_adb_t *adb;
00862         dns_adbnamehook_t *nh;
00863         dns_adbnamehook_t *anh;
00864         dns_rdata_t rdata = DNS_RDATA_INIT;
00865         struct in_addr ina;
00866         struct in6_addr in6a;
00867         isc_sockaddr_t sockaddr;
00868         dns_adbentry_t *foundentry;  /* NO CLEAN UP! */
00869         int addr_bucket;
00870         isc_boolean_t new_addresses_added;
00871         dns_rdatatype_t rdtype;
00872         unsigned int findoptions;
00873         dns_adbnamehooklist_t *hookhead;
00874 
00875         INSIST(DNS_ADBNAME_VALID(adbname));
00876         adb = adbname->adb;
00877         INSIST(DNS_ADB_VALID(adb));
00878 
00879         rdtype = rdataset->type;
00880         INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
00881         if (rdtype == dns_rdatatype_a)
00882                 findoptions = DNS_ADBFIND_INET;
00883         else
00884                 findoptions = DNS_ADBFIND_INET6;
00885 
00886         addr_bucket = DNS_ADB_INVALIDBUCKET;
00887         new_addresses_added = ISC_FALSE;
00888 
00889         nh = NULL;
00890         result = dns_rdataset_first(rdataset);
00891         while (result == ISC_R_SUCCESS) {
00892                 dns_rdata_reset(&rdata);
00893                 dns_rdataset_current(rdataset, &rdata);
00894                 if (rdtype == dns_rdatatype_a) {
00895                         INSIST(rdata.length == 4);
00896                         memmove(&ina.s_addr, rdata.data, 4);
00897                         isc_sockaddr_fromin(&sockaddr, &ina, 0);
00898                         hookhead = &adbname->v4;
00899                 } else {
00900                         INSIST(rdata.length == 16);
00901                         memmove(in6a.s6_addr, rdata.data, 16);
00902                         isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
00903                         hookhead = &adbname->v6;
00904                 }
00905 
00906                 INSIST(nh == NULL);
00907                 nh = new_adbnamehook(adb, NULL);
00908                 if (nh == NULL) {
00909                         adbname->partial_result |= findoptions;
00910                         result = ISC_R_NOMEMORY;
00911                         goto fail;
00912                 }
00913 
00914                 foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
00915                                                  now);
00916                 if (foundentry == NULL) {
00917                         dns_adbentry_t *entry;
00918 
00919                         entry = new_adbentry(adb);
00920                         if (entry == NULL) {
00921                                 adbname->partial_result |= findoptions;
00922                                 result = ISC_R_NOMEMORY;
00923                                 goto fail;
00924                         }
00925 
00926                         entry->sockaddr = sockaddr;
00927                         entry->refcnt = 1;
00928 
00929                         nh->entry = entry;
00930 
00931                         link_entry(adb, addr_bucket, entry);
00932                 } else {
00933                         for (anh = ISC_LIST_HEAD(*hookhead);
00934                              anh != NULL;
00935                              anh = ISC_LIST_NEXT(anh, plink))
00936                                 if (anh->entry == foundentry)
00937                                         break;
00938                         if (anh == NULL) {
00939                                 foundentry->refcnt++;
00940                                 nh->entry = foundentry;
00941                         } else
00942                                 free_adbnamehook(adb, &nh);
00943                 }
00944 
00945                 new_addresses_added = ISC_TRUE;
00946                 if (nh != NULL)
00947                         ISC_LIST_APPEND(*hookhead, nh, plink);
00948                 nh = NULL;
00949                 result = dns_rdataset_next(rdataset);
00950         }
00951 
00952  fail:
00953         if (nh != NULL)
00954                 free_adbnamehook(adb, &nh);
00955 
00956         if (addr_bucket != DNS_ADB_INVALIDBUCKET)
00957                 UNLOCK(&adb->entrylocks[addr_bucket]);
00958 
00959         if (rdataset->trust == dns_trust_glue ||
00960             rdataset->trust == dns_trust_additional)
00961                 rdataset->ttl = ADB_CACHE_MINIMUM;
00962         else if (rdataset->trust == dns_trust_ultimate)
00963                 rdataset->ttl = 0;
00964         else
00965                 rdataset->ttl = ttlclamp(rdataset->ttl);
00966 
00967         if (rdtype == dns_rdatatype_a) {
00968                 DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
00969                    adbname->expire_v4, now + rdataset->ttl);
00970                 adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
00971                                              ISC_MIN(now + ADB_ENTRY_WINDOW,
00972                                                      now + rdataset->ttl));
00973         } else {
00974                 DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
00975                    adbname->expire_v6, now + rdataset->ttl);
00976                 adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
00977                                              ISC_MIN(now + ADB_ENTRY_WINDOW,
00978                                                      now + rdataset->ttl));
00979         }
00980 
00981         if (new_addresses_added) {
00982                 /*
00983                  * Lie a little here.  This is more or less so code that cares
00984                  * can find out if any new information was added or not.
00985                  */
00986                 return (ISC_R_SUCCESS);
00987         }
00988 
00989         return (result);
00990 }
00991 
00992 /*
00993  * Requires the name's bucket be locked.
00994  */
00995 static isc_boolean_t
00996 kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
00997         dns_adbname_t *name;
00998         isc_boolean_t result = ISC_FALSE;
00999         isc_boolean_t result4, result6;
01000         int bucket;
01001         dns_adb_t *adb;
01002 
01003         INSIST(n != NULL);
01004         name = *n;
01005         *n = NULL;
01006         INSIST(DNS_ADBNAME_VALID(name));
01007         adb = name->adb;
01008         INSIST(DNS_ADB_VALID(adb));
01009 
01010         DP(DEF_LEVEL, "killing name %p", name);
01011 
01012         /*
01013          * If we're dead already, just check to see if we should go
01014          * away now or not.
01015          */
01016         if (NAME_DEAD(name) && !NAME_FETCH(name)) {
01017                 result = unlink_name(adb, name);
01018                 free_adbname(adb, &name);
01019                 if (result)
01020                         result = dec_adb_irefcnt(adb);
01021                 return (result);
01022         }
01023 
01024         /*
01025          * Clean up the name's various lists.  These two are destructive
01026          * in that they will always empty the list.
01027          */
01028         clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
01029         result4 = clean_namehooks(adb, &name->v4);
01030         result6 = clean_namehooks(adb, &name->v6);
01031         clean_target(adb, &name->target);
01032         result = ISC_TF(result4 || result6);
01033 
01034         /*
01035          * If fetches are running, cancel them.  If none are running, we can
01036          * just kill the name here.
01037          */
01038         if (!NAME_FETCH(name)) {
01039                 INSIST(result == ISC_FALSE);
01040                 result = unlink_name(adb, name);
01041                 free_adbname(adb, &name);
01042                 if (result)
01043                         result = dec_adb_irefcnt(adb);
01044         } else {
01045                 cancel_fetches_at_name(name);
01046                 if (!NAME_DEAD(name)) {
01047                         bucket = name->lock_bucket;
01048                         ISC_LIST_UNLINK(adb->names[bucket], name, plink);
01049                         ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
01050                         name->flags |= NAME_IS_DEAD;
01051                 }
01052         }
01053         return (result);
01054 }
01055 
01056 /*
01057  * Requires the name's bucket be locked and no entry buckets be locked.
01058  */
01059 static isc_boolean_t
01060 check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
01061         dns_adb_t *adb;
01062         isc_boolean_t result4 = ISC_FALSE;
01063         isc_boolean_t result6 = ISC_FALSE;
01064 
01065         INSIST(DNS_ADBNAME_VALID(name));
01066         adb = name->adb;
01067         INSIST(DNS_ADB_VALID(adb));
01068 
01069         /*
01070          * Check to see if we need to remove the v4 addresses
01071          */
01072         if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
01073                 if (NAME_HAS_V4(name)) {
01074                         DP(DEF_LEVEL, "expiring v4 for name %p", name);
01075                         result4 = clean_namehooks(adb, &name->v4);
01076                         name->partial_result &= ~DNS_ADBFIND_INET;
01077                 }
01078                 name->expire_v4 = INT_MAX;
01079                 name->fetch_err = FIND_ERR_UNEXPECTED;
01080         }
01081 
01082         /*
01083          * Check to see if we need to remove the v6 addresses
01084          */
01085         if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
01086                 if (NAME_HAS_V6(name)) {
01087                         DP(DEF_LEVEL, "expiring v6 for name %p", name);
01088                         result6 = clean_namehooks(adb, &name->v6);
01089                         name->partial_result &= ~DNS_ADBFIND_INET6;
01090                 }
01091                 name->expire_v6 = INT_MAX;
01092                 name->fetch6_err = FIND_ERR_UNEXPECTED;
01093         }
01094 
01095         /*
01096          * Check to see if we need to remove the alias target.
01097          */
01098         if (EXPIRE_OK(name->expire_target, now)) {
01099                 clean_target(adb, &name->target);
01100                 name->expire_target = INT_MAX;
01101         }
01102         return (ISC_TF(result4 || result6));
01103 }
01104 
01105 /*
01106  * Requires the name's bucket be locked.
01107  */
01108 static inline void
01109 link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
01110         INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
01111 
01112         ISC_LIST_PREPEND(adb->names[bucket], name, plink);
01113         name->lock_bucket = bucket;
01114         adb->name_refcnt[bucket]++;
01115 }
01116 
01117 /*
01118  * Requires the name's bucket be locked.
01119  */
01120 static inline isc_boolean_t
01121 unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
01122         int bucket;
01123         isc_boolean_t result = ISC_FALSE;
01124 
01125         bucket = name->lock_bucket;
01126         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
01127 
01128         if (NAME_DEAD(name))
01129                 ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
01130         else
01131                 ISC_LIST_UNLINK(adb->names[bucket], name, plink);
01132         name->lock_bucket = DNS_ADB_INVALIDBUCKET;
01133         INSIST(adb->name_refcnt[bucket] > 0);
01134         adb->name_refcnt[bucket]--;
01135         if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
01136                 result = ISC_TRUE;
01137         return (result);
01138 }
01139 
01140 /*
01141  * Requires the entry's bucket be locked.
01142  */
01143 static inline void
01144 link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
01145         int i;
01146         dns_adbentry_t *e;
01147 
01148         if (isc_mem_isovermem(adb->mctx)) {
01149                 for (i = 0; i < 2; i++) {
01150                         e = ISC_LIST_TAIL(adb->entries[bucket]);
01151                         if (e == NULL)
01152                                 break;
01153                         if (e->refcnt == 0) {
01154                                 unlink_entry(adb, e);
01155                                 free_adbentry(adb, &e);
01156                                 continue;
01157                         }
01158                         INSIST((e->flags & ENTRY_IS_DEAD) == 0);
01159                         e->flags |= ENTRY_IS_DEAD;
01160                         ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
01161                         ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
01162                 }
01163         }
01164 
01165         ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
01166         entry->lock_bucket = bucket;
01167         adb->entry_refcnt[bucket]++;
01168 }
01169 
01170 /*
01171  * Requires the entry's bucket be locked.
01172  */
01173 static inline isc_boolean_t
01174 unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
01175         int bucket;
01176         isc_boolean_t result = ISC_FALSE;
01177 
01178         bucket = entry->lock_bucket;
01179         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
01180 
01181         if ((entry->flags & ENTRY_IS_DEAD) != 0)
01182                 ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
01183         else
01184                 ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
01185         entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
01186         INSIST(adb->entry_refcnt[bucket] > 0);
01187         adb->entry_refcnt[bucket]--;
01188         if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
01189                 result = ISC_TRUE;
01190         return (result);
01191 }
01192 
01193 static inline void
01194 violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
01195         if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
01196                 UNLOCK(have);
01197                 LOCK(want);
01198                 LOCK(have);
01199         }
01200 }
01201 
01202 /*
01203  * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
01204  * checked after calling this function.
01205  */
01206 static isc_boolean_t
01207 shutdown_names(dns_adb_t *adb) {
01208         unsigned int bucket;
01209         isc_boolean_t result = ISC_FALSE;
01210         dns_adbname_t *name;
01211         dns_adbname_t *next_name;
01212 
01213         for (bucket = 0; bucket < adb->nnames; bucket++) {
01214                 LOCK(&adb->namelocks[bucket]);
01215                 adb->name_sd[bucket] = ISC_TRUE;
01216 
01217                 name = ISC_LIST_HEAD(adb->names[bucket]);
01218                 if (name == NULL) {
01219                         /*
01220                          * This bucket has no names.  We must decrement the
01221                          * irefcnt ourselves, since it will not be
01222                          * automatically triggered by a name being unlinked.
01223                          */
01224                         INSIST(result == ISC_FALSE);
01225                         result = dec_adb_irefcnt(adb);
01226                 } else {
01227                         /*
01228                          * Run through the list.  For each name, clean up finds
01229                          * found there, and cancel any fetches running.  When
01230                          * all the fetches are canceled, the name will destroy
01231                          * itself.
01232                          */
01233                         while (name != NULL) {
01234                                 next_name = ISC_LIST_NEXT(name, plink);
01235                                 INSIST(result == ISC_FALSE);
01236                                 result = kill_name(&name,
01237                                                    DNS_EVENT_ADBSHUTDOWN);
01238                                 name = next_name;
01239                         }
01240                 }
01241 
01242                 UNLOCK(&adb->namelocks[bucket]);
01243         }
01244         return (result);
01245 }
01246 
01247 /*
01248  * The ADB _MUST_ be locked before calling.  Also, exit conditions must be
01249  * checked after calling this function.
01250  */
01251 static isc_boolean_t
01252 shutdown_entries(dns_adb_t *adb) {
01253         unsigned int bucket;
01254         isc_boolean_t result = ISC_FALSE;
01255         dns_adbentry_t *entry;
01256         dns_adbentry_t *next_entry;
01257 
01258         for (bucket = 0; bucket < adb->nentries; bucket++) {
01259                 LOCK(&adb->entrylocks[bucket]);
01260                 adb->entry_sd[bucket] = ISC_TRUE;
01261 
01262                 entry = ISC_LIST_HEAD(adb->entries[bucket]);
01263                 if (adb->entry_refcnt[bucket] == 0) {
01264                         /*
01265                          * This bucket has no entries.  We must decrement the
01266                          * irefcnt ourselves, since it will not be
01267                          * automatically triggered by an entry being unlinked.
01268                          */
01269                         result = dec_adb_irefcnt(adb);
01270                 } else {
01271                         /*
01272                          * Run through the list.  Cleanup any entries not
01273                          * associated with names, and which are not in use.
01274                          */
01275                         while (entry != NULL) {
01276                                 next_entry = ISC_LIST_NEXT(entry, plink);
01277                                 if (entry->refcnt == 0 &&
01278                                     entry->expires != 0) {
01279                                         result = unlink_entry(adb, entry);
01280                                         free_adbentry(adb, &entry);
01281                                         if (result)
01282                                                 result = dec_adb_irefcnt(adb);
01283                                 }
01284                                 entry = next_entry;
01285                         }
01286                 }
01287 
01288                 UNLOCK(&adb->entrylocks[bucket]);
01289         }
01290         return (result);
01291 }
01292 
01293 /*
01294  * Name bucket must be locked
01295  */
01296 static void
01297 cancel_fetches_at_name(dns_adbname_t *name) {
01298         if (NAME_FETCH_A(name))
01299             dns_resolver_cancelfetch(name->fetch_a->fetch);
01300 
01301         if (NAME_FETCH_AAAA(name))
01302             dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
01303 }
01304 
01305 /*
01306  * Assumes the name bucket is locked.
01307  */
01308 static isc_boolean_t
01309 clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
01310         dns_adbentry_t *entry;
01311         dns_adbnamehook_t *namehook;
01312         int addr_bucket;
01313         isc_boolean_t result = ISC_FALSE;
01314         isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
01315 
01316         addr_bucket = DNS_ADB_INVALIDBUCKET;
01317         namehook = ISC_LIST_HEAD(*namehooks);
01318         while (namehook != NULL) {
01319                 INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
01320 
01321                 /*
01322                  * Clean up the entry if needed.
01323                  */
01324                 entry = namehook->entry;
01325                 if (entry != NULL) {
01326                         INSIST(DNS_ADBENTRY_VALID(entry));
01327 
01328                         if (addr_bucket != entry->lock_bucket) {
01329                                 if (addr_bucket != DNS_ADB_INVALIDBUCKET)
01330                                         UNLOCK(&adb->entrylocks[addr_bucket]);
01331                                 addr_bucket = entry->lock_bucket;
01332                                 INSIST(addr_bucket != DNS_ADB_INVALIDBUCKET);
01333                                 LOCK(&adb->entrylocks[addr_bucket]);
01334                         }
01335 
01336                         result = dec_entry_refcnt(adb, overmem, entry,
01337                                                   ISC_FALSE);
01338                 }
01339 
01340                 /*
01341                  * Free the namehook
01342                  */
01343                 namehook->entry = NULL;
01344                 ISC_LIST_UNLINK(*namehooks, namehook, plink);
01345                 free_adbnamehook(adb, &namehook);
01346 
01347                 namehook = ISC_LIST_HEAD(*namehooks);
01348         }
01349 
01350         if (addr_bucket != DNS_ADB_INVALIDBUCKET)
01351                 UNLOCK(&adb->entrylocks[addr_bucket]);
01352         return (result);
01353 }
01354 
01355 static void
01356 clean_target(dns_adb_t *adb, dns_name_t *target) {
01357         if (dns_name_countlabels(target) > 0) {
01358                 dns_name_free(target, adb->mctx);
01359                 dns_name_init(target, NULL);
01360         }
01361 }
01362 
01363 static isc_result_t
01364 set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
01365            dns_rdataset_t *rdataset, dns_name_t *target)
01366 {
01367         isc_result_t result;
01368         dns_namereln_t namereln;
01369         unsigned int nlabels;
01370         int order;
01371         dns_rdata_t rdata = DNS_RDATA_INIT;
01372         dns_fixedname_t fixed1, fixed2;
01373         dns_name_t *prefix, *new_target;
01374 
01375         REQUIRE(dns_name_countlabels(target) == 0);
01376 
01377         if (rdataset->type == dns_rdatatype_cname) {
01378                 dns_rdata_cname_t cname;
01379 
01380                 /*
01381                  * Copy the CNAME's target into the target name.
01382                  */
01383                 result = dns_rdataset_first(rdataset);
01384                 if (result != ISC_R_SUCCESS)
01385                         return (result);
01386                 dns_rdataset_current(rdataset, &rdata);
01387                 result = dns_rdata_tostruct(&rdata, &cname, NULL);
01388                 if (result != ISC_R_SUCCESS)
01389                         return (result);
01390                 result = dns_name_dup(&cname.cname, adb->mctx, target);
01391                 dns_rdata_freestruct(&cname);
01392                 if (result != ISC_R_SUCCESS)
01393                         return (result);
01394         } else {
01395                 dns_rdata_dname_t dname;
01396 
01397                 INSIST(rdataset->type == dns_rdatatype_dname);
01398                 namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
01399                 INSIST(namereln == dns_namereln_subdomain);
01400                 /*
01401                  * Get the target name of the DNAME.
01402                  */
01403                 result = dns_rdataset_first(rdataset);
01404                 if (result != ISC_R_SUCCESS)
01405                         return (result);
01406                 dns_rdataset_current(rdataset, &rdata);
01407                 result = dns_rdata_tostruct(&rdata, &dname, NULL);
01408                 if (result != ISC_R_SUCCESS)
01409                         return (result);
01410                 /*
01411                  * Construct the new target name.
01412                  */
01413                 dns_fixedname_init(&fixed1);
01414                 prefix = dns_fixedname_name(&fixed1);
01415                 dns_fixedname_init(&fixed2);
01416                 new_target = dns_fixedname_name(&fixed2);
01417                 dns_name_split(name, nlabels, prefix, NULL);
01418                 result = dns_name_concatenate(prefix, &dname.dname, new_target,
01419                                               NULL);
01420                 dns_rdata_freestruct(&dname);
01421                 if (result != ISC_R_SUCCESS)
01422                         return (result);
01423                 result = dns_name_dup(new_target, adb->mctx, target);
01424                 if (result != ISC_R_SUCCESS)
01425                         return (result);
01426         }
01427 
01428         return (ISC_R_SUCCESS);
01429 }
01430 
01431 /*
01432  * Assumes nothing is locked, since this is called by the client.
01433  */
01434 static void
01435 event_free(isc_event_t *event) {
01436         dns_adbfind_t *find;
01437 
01438         INSIST(event != NULL);
01439         find = event->ev_destroy_arg;
01440         INSIST(DNS_ADBFIND_VALID(find));
01441 
01442         LOCK(&find->lock);
01443         find->flags |= FIND_EVENT_FREED;
01444         event->ev_destroy_arg = NULL;
01445         UNLOCK(&find->lock);
01446 }
01447 
01448 /*
01449  * Assumes the name bucket is locked.
01450  */
01451 static void
01452 clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
01453                     unsigned int addrs)
01454 {
01455         isc_event_t *ev;
01456         isc_task_t *task;
01457         dns_adbfind_t *find;
01458         dns_adbfind_t *next_find;
01459         isc_boolean_t process;
01460         unsigned int wanted, notify;
01461 
01462         DP(ENTER_LEVEL,
01463            "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
01464            name, evtype, addrs);
01465 
01466         find = ISC_LIST_HEAD(name->finds);
01467         while (find != NULL) {
01468                 LOCK(&find->lock);
01469                 next_find = ISC_LIST_NEXT(find, plink);
01470 
01471                 process = ISC_FALSE;
01472                 wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
01473                 notify = wanted & addrs;
01474 
01475                 switch (evtype) {
01476                 case DNS_EVENT_ADBMOREADDRESSES:
01477                         DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
01478                         if ((notify) != 0) {
01479                                 find->flags &= ~addrs;
01480                                 process = ISC_TRUE;
01481                         }
01482                         break;
01483                 case DNS_EVENT_ADBNOMOREADDRESSES:
01484                         DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
01485                         find->flags &= ~addrs;
01486                         wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
01487                         if (wanted == 0)
01488                                 process = ISC_TRUE;
01489                         break;
01490                 default:
01491                         find->flags &= ~addrs;
01492                         process = ISC_TRUE;
01493                 }
01494 
01495                 if (process) {
01496                         DP(DEF_LEVEL, "cfan: processing find %p", find);
01497                         /*
01498                          * Unlink the find from the name, letting the caller
01499                          * call dns_adb_destroyfind() on it to clean it up
01500                          * later.
01501                          */
01502                         ISC_LIST_UNLINK(name->finds, find, plink);
01503                         find->adbname = NULL;
01504                         find->name_bucket = DNS_ADB_INVALIDBUCKET;
01505 
01506                         INSIST(!FIND_EVENTSENT(find));
01507 
01508                         ev = &find->event;
01509                         task = ev->ev_sender;
01510                         ev->ev_sender = find;
01511                         find->result_v4 = find_err_map[name->fetch_err];
01512                         find->result_v6 = find_err_map[name->fetch6_err];
01513                         ev->ev_type = evtype;
01514                         ev->ev_destroy = event_free;
01515                         ev->ev_destroy_arg = find;
01516 
01517                         DP(DEF_LEVEL,
01518                            "sending event %p to task %p for find %p",
01519                            ev, task, find);
01520 
01521                         isc_task_sendanddetach(&task, (isc_event_t **)&ev);
01522                         find->flags |= FIND_EVENT_SENT;
01523                 } else {
01524                         DP(DEF_LEVEL, "cfan: skipping find %p", find);
01525                 }
01526 
01527                 UNLOCK(&find->lock);
01528                 find = next_find;
01529         }
01530 
01531         DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
01532 }
01533 
01534 static inline void
01535 check_exit(dns_adb_t *adb) {
01536         isc_event_t *event;
01537         /*
01538          * The caller must be holding the adb lock.
01539          */
01540         if (adb->shutting_down) {
01541                 /*
01542                  * If there aren't any external references either, we're
01543                  * done.  Send the control event to initiate shutdown.
01544                  */
01545                 INSIST(!adb->cevent_out);      /* Sanity check. */
01546                 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
01547                                DNS_EVENT_ADBCONTROL, shutdown_task, adb,
01548                                adb, NULL, NULL);
01549                 event = &adb->cevent;
01550                 isc_task_send(adb->task, &event);
01551                 adb->cevent_out = ISC_TRUE;
01552         }
01553 }
01554 
01555 static inline isc_boolean_t
01556 dec_adb_irefcnt(dns_adb_t *adb) {
01557         isc_event_t *event;
01558         isc_task_t *etask;
01559         isc_boolean_t result = ISC_FALSE;
01560 
01561         LOCK(&adb->reflock);
01562 
01563         INSIST(adb->irefcnt > 0);
01564         adb->irefcnt--;
01565 
01566         if (adb->irefcnt == 0) {
01567                 event = ISC_LIST_HEAD(adb->whenshutdown);
01568                 while (event != NULL) {
01569                         ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
01570                         etask = event->ev_sender;
01571                         event->ev_sender = adb;
01572                         isc_task_sendanddetach(&etask, &event);
01573                         event = ISC_LIST_HEAD(adb->whenshutdown);
01574                 }
01575         }
01576 
01577         if (adb->irefcnt == 0 && adb->erefcnt == 0)
01578                 result = ISC_TRUE;
01579         UNLOCK(&adb->reflock);
01580         return (result);
01581 }
01582 
01583 static inline void
01584 inc_adb_irefcnt(dns_adb_t *adb) {
01585         LOCK(&adb->reflock);
01586         adb->irefcnt++;
01587         UNLOCK(&adb->reflock);
01588 }
01589 
01590 static inline void
01591 inc_adb_erefcnt(dns_adb_t *adb) {
01592         LOCK(&adb->reflock);
01593         adb->erefcnt++;
01594         UNLOCK(&adb->reflock);
01595 }
01596 
01597 static inline void
01598 inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
01599         int bucket;
01600 
01601         bucket = entry->lock_bucket;
01602 
01603         if (lock)
01604                 LOCK(&adb->entrylocks[bucket]);
01605 
01606         entry->refcnt++;
01607 
01608         if (lock)
01609                 UNLOCK(&adb->entrylocks[bucket]);
01610 }
01611 
01612 static inline isc_boolean_t
01613 dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
01614                  isc_boolean_t lock)
01615 {
01616         int bucket;
01617         isc_boolean_t destroy_entry;
01618         isc_boolean_t result = ISC_FALSE;
01619 
01620         bucket = entry->lock_bucket;
01621 
01622         if (lock)
01623                 LOCK(&adb->entrylocks[bucket]);
01624 
01625         INSIST(entry->refcnt > 0);
01626         entry->refcnt--;
01627 
01628         destroy_entry = ISC_FALSE;
01629         if (entry->refcnt == 0 &&
01630             (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
01631              (entry->flags & ENTRY_IS_DEAD) != 0)) {
01632                 destroy_entry = ISC_TRUE;
01633                 result = unlink_entry(adb, entry);
01634         }
01635 
01636         if (lock)
01637                 UNLOCK(&adb->entrylocks[bucket]);
01638 
01639         if (!destroy_entry)
01640                 return (result);
01641 
01642         entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
01643 
01644         free_adbentry(adb, &entry);
01645         if (result)
01646                 result = dec_adb_irefcnt(adb);
01647 
01648         return (result);
01649 }
01650 
01651 static inline dns_adbname_t *
01652 new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
01653         dns_adbname_t *name;
01654 
01655         name = isc_mempool_get(adb->nmp);
01656         if (name == NULL)
01657                 return (NULL);
01658 
01659         dns_name_init(&name->name, NULL);
01660         if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
01661                 isc_mempool_put(adb->nmp, name);
01662                 return (NULL);
01663         }
01664         dns_name_init(&name->target, NULL);
01665         name->magic = DNS_ADBNAME_MAGIC;
01666         name->adb = adb;
01667         name->partial_result = 0;
01668         name->flags = 0;
01669         name->expire_v4 = INT_MAX;
01670         name->expire_v6 = INT_MAX;
01671         name->expire_target = INT_MAX;
01672         name->chains = 0;
01673         name->lock_bucket = DNS_ADB_INVALIDBUCKET;
01674         ISC_LIST_INIT(name->v4);
01675         ISC_LIST_INIT(name->v6);
01676         name->fetch_a = NULL;
01677         name->fetch_aaaa = NULL;
01678         name->fetch_err = FIND_ERR_UNEXPECTED;
01679         name->fetch6_err = FIND_ERR_UNEXPECTED;
01680         ISC_LIST_INIT(name->finds);
01681         ISC_LINK_INIT(name, plink);
01682 
01683         LOCK(&adb->namescntlock);
01684         adb->namescnt++;
01685         inc_adbstats(adb, dns_adbstats_namescnt);
01686         if (!adb->grownames_sent && adb->excl != NULL &&
01687             adb->namescnt > (adb->nnames * 8))
01688         {
01689                 isc_event_t *event = &adb->grownames;
01690                 inc_adb_irefcnt(adb);
01691                 isc_task_send(adb->excl, &event);
01692                 adb->grownames_sent = ISC_TRUE;
01693         }
01694         UNLOCK(&adb->namescntlock);
01695 
01696         return (name);
01697 }
01698 
01699 static inline void
01700 free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
01701         dns_adbname_t *n;
01702 
01703         INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
01704         n = *name;
01705         *name = NULL;
01706 
01707         INSIST(!NAME_HAS_V4(n));
01708         INSIST(!NAME_HAS_V6(n));
01709         INSIST(!NAME_FETCH(n));
01710         INSIST(ISC_LIST_EMPTY(n->finds));
01711         INSIST(!ISC_LINK_LINKED(n, plink));
01712         INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
01713         INSIST(n->adb == adb);
01714 
01715         n->magic = 0;
01716         dns_name_free(&n->name, adb->mctx);
01717 
01718         isc_mempool_put(adb->nmp, n);
01719         LOCK(&adb->namescntlock);
01720         adb->namescnt--;
01721         dec_adbstats(adb, dns_adbstats_namescnt);
01722         UNLOCK(&adb->namescntlock);
01723 }
01724 
01725 static inline dns_adbnamehook_t *
01726 new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
01727         dns_adbnamehook_t *nh;
01728 
01729         nh = isc_mempool_get(adb->nhmp);
01730         if (nh == NULL)
01731                 return (NULL);
01732 
01733         nh->magic = DNS_ADBNAMEHOOK_MAGIC;
01734         nh->entry = entry;
01735         ISC_LINK_INIT(nh, plink);
01736 
01737         return (nh);
01738 }
01739 
01740 static inline void
01741 free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
01742         dns_adbnamehook_t *nh;
01743 
01744         INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
01745         nh = *namehook;
01746         *namehook = NULL;
01747 
01748         INSIST(nh->entry == NULL);
01749         INSIST(!ISC_LINK_LINKED(nh, plink));
01750 
01751         nh->magic = 0;
01752         isc_mempool_put(adb->nhmp, nh);
01753 }
01754 
01755 static inline dns_adblameinfo_t *
01756 new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
01757         dns_adblameinfo_t *li;
01758 
01759         li = isc_mempool_get(adb->limp);
01760         if (li == NULL)
01761                 return (NULL);
01762 
01763         dns_name_init(&li->qname, NULL);
01764         if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
01765                 isc_mempool_put(adb->limp, li);
01766                 return (NULL);
01767         }
01768         li->magic = DNS_ADBLAMEINFO_MAGIC;
01769         li->lame_timer = 0;
01770         li->qtype = qtype;
01771         ISC_LINK_INIT(li, plink);
01772 
01773         return (li);
01774 }
01775 
01776 static inline void
01777 free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
01778         dns_adblameinfo_t *li;
01779 
01780         INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
01781         li = *lameinfo;
01782         *lameinfo = NULL;
01783 
01784         INSIST(!ISC_LINK_LINKED(li, plink));
01785 
01786         dns_name_free(&li->qname, adb->mctx);
01787 
01788         li->magic = 0;
01789 
01790         isc_mempool_put(adb->limp, li);
01791 }
01792 
01793 static inline dns_adbentry_t *
01794 new_adbentry(dns_adb_t *adb) {
01795         dns_adbentry_t *e;
01796         isc_uint32_t r;
01797 
01798         e = isc_mempool_get(adb->emp);
01799         if (e == NULL)
01800                 return (NULL);
01801 
01802         e->magic = DNS_ADBENTRY_MAGIC;
01803         e->lock_bucket = DNS_ADB_INVALIDBUCKET;
01804         e->refcnt = 0;
01805         e->flags = 0;
01806         e->udpsize = 0;
01807         e->edns = 0;
01808         e->plain = 0;
01809         e->plainto = 0;
01810         e->to4096 = 0;
01811         e->to1432 = 0;
01812         e->to1232 = 0;
01813         e->to512 = 0;
01814         e->sit = NULL;
01815         e->sitlen = 0;
01816         isc_random_get(&r);
01817         e->srtt = (r & 0x1f) + 1;
01818         e->lastage = 0;
01819         e->expires = 0;
01820         ISC_LIST_INIT(e->lameinfo);
01821         ISC_LINK_INIT(e, plink);
01822         LOCK(&adb->entriescntlock);
01823         adb->entriescnt++;
01824         inc_adbstats(adb, dns_adbstats_entriescnt);
01825         if (!adb->growentries_sent && adb->excl != NULL &&
01826             adb->entriescnt > (adb->nentries * 8))
01827         {
01828                 isc_event_t *event = &adb->growentries;
01829                 inc_adb_irefcnt(adb);
01830                 isc_task_send(adb->excl, &event);
01831                 adb->growentries_sent = ISC_TRUE;
01832         }
01833         UNLOCK(&adb->entriescntlock);
01834 
01835         return (e);
01836 }
01837 
01838 static inline void
01839 free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
01840         dns_adbentry_t *e;
01841         dns_adblameinfo_t *li;
01842 
01843         INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
01844         e = *entry;
01845         *entry = NULL;
01846 
01847         INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
01848         INSIST(e->refcnt == 0);
01849         INSIST(!ISC_LINK_LINKED(e, plink));
01850 
01851         e->magic = 0;
01852 
01853         if (e->sit != NULL)
01854                 isc_mem_put(adb->mctx, e->sit, e->sitlen);
01855 
01856         li = ISC_LIST_HEAD(e->lameinfo);
01857         while (li != NULL) {
01858                 ISC_LIST_UNLINK(e->lameinfo, li, plink);
01859                 free_adblameinfo(adb, &li);
01860                 li = ISC_LIST_HEAD(e->lameinfo);
01861         }
01862 
01863         isc_mempool_put(adb->emp, e);
01864         LOCK(&adb->entriescntlock);
01865         adb->entriescnt--;
01866         dec_adbstats(adb, dns_adbstats_entriescnt);
01867         UNLOCK(&adb->entriescntlock);
01868 }
01869 
01870 static inline dns_adbfind_t *
01871 new_adbfind(dns_adb_t *adb) {
01872         dns_adbfind_t *h;
01873         isc_result_t result;
01874 
01875         h = isc_mempool_get(adb->ahmp);
01876         if (h == NULL)
01877                 return (NULL);
01878 
01879         /*
01880          * Public members.
01881          */
01882         h->magic = 0;
01883         h->adb = adb;
01884         h->partial_result = 0;
01885         h->options = 0;
01886         h->flags = 0;
01887         h->result_v4 = ISC_R_UNEXPECTED;
01888         h->result_v6 = ISC_R_UNEXPECTED;
01889         ISC_LINK_INIT(h, publink);
01890         ISC_LINK_INIT(h, plink);
01891         ISC_LIST_INIT(h->list);
01892         h->adbname = NULL;
01893         h->name_bucket = DNS_ADB_INVALIDBUCKET;
01894 
01895         /*
01896          * private members
01897          */
01898         result = isc_mutex_init(&h->lock);
01899         if (result != ISC_R_SUCCESS) {
01900                 isc_mempool_put(adb->ahmp, h);
01901                 return (NULL);
01902         }
01903 
01904         ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
01905                        NULL, NULL, h);
01906 
01907         inc_adb_irefcnt(adb);
01908         h->magic = DNS_ADBFIND_MAGIC;
01909         return (h);
01910 }
01911 
01912 static inline dns_adbfetch_t *
01913 new_adbfetch(dns_adb_t *adb) {
01914         dns_adbfetch_t *f;
01915 
01916         f = isc_mempool_get(adb->afmp);
01917         if (f == NULL)
01918                 return (NULL);
01919 
01920         f->magic = 0;
01921         f->fetch = NULL;
01922 
01923         dns_rdataset_init(&f->rdataset);
01924 
01925         f->magic = DNS_ADBFETCH_MAGIC;
01926 
01927         return (f);
01928 }
01929 
01930 static inline void
01931 free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
01932         dns_adbfetch_t *f;
01933 
01934         INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
01935         f = *fetch;
01936         *fetch = NULL;
01937 
01938         f->magic = 0;
01939 
01940         if (dns_rdataset_isassociated(&f->rdataset))
01941                 dns_rdataset_disassociate(&f->rdataset);
01942 
01943         isc_mempool_put(adb->afmp, f);
01944 }
01945 
01946 static inline isc_boolean_t
01947 free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
01948         dns_adbfind_t *find;
01949 
01950         INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
01951         find = *findp;
01952         *findp = NULL;
01953 
01954         INSIST(!FIND_HAS_ADDRS(find));
01955         INSIST(!ISC_LINK_LINKED(find, publink));
01956         INSIST(!ISC_LINK_LINKED(find, plink));
01957         INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
01958         INSIST(find->adbname == NULL);
01959 
01960         find->magic = 0;
01961 
01962         DESTROYLOCK(&find->lock);
01963         isc_mempool_put(adb->ahmp, find);
01964         return (dec_adb_irefcnt(adb));
01965 }
01966 
01967 /*
01968  * Copy bits from the entry into the newly allocated addrinfo.  The entry
01969  * must be locked, and the reference count must be bumped up by one
01970  * if this function returns a valid pointer.
01971  */
01972 static inline dns_adbaddrinfo_t *
01973 new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
01974         dns_adbaddrinfo_t *ai;
01975 
01976         ai = isc_mempool_get(adb->aimp);
01977         if (ai == NULL)
01978                 return (NULL);
01979 
01980         ai->magic = DNS_ADBADDRINFO_MAGIC;
01981         ai->sockaddr = entry->sockaddr;
01982         isc_sockaddr_setport(&ai->sockaddr, port);
01983         ai->srtt = entry->srtt;
01984         ai->flags = entry->flags;
01985         ai->entry = entry;
01986         ai->dscp = -1;
01987         ISC_LINK_INIT(ai, publink);
01988 
01989         return (ai);
01990 }
01991 
01992 static inline void
01993 free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
01994         dns_adbaddrinfo_t *ai;
01995 
01996         INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
01997         ai = *ainfo;
01998         *ainfo = NULL;
01999 
02000         INSIST(ai->entry == NULL);
02001         INSIST(!ISC_LINK_LINKED(ai, publink));
02002 
02003         ai->magic = 0;
02004 
02005         isc_mempool_put(adb->aimp, ai);
02006 }
02007 
02008 /*
02009  * Search for the name.  NOTE:  The bucket is kept locked on both
02010  * success and failure, so it must always be unlocked by the caller!
02011  *
02012  * On the first call to this function, *bucketp must be set to
02013  * DNS_ADB_INVALIDBUCKET.
02014  */
02015 static inline dns_adbname_t *
02016 find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
02017                    unsigned int options, int *bucketp)
02018 {
02019         dns_adbname_t *adbname;
02020         int bucket;
02021 
02022         bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
02023 
02024         if (*bucketp == DNS_ADB_INVALIDBUCKET) {
02025                 LOCK(&adb->namelocks[bucket]);
02026                 *bucketp = bucket;
02027         } else if (*bucketp != bucket) {
02028                 UNLOCK(&adb->namelocks[*bucketp]);
02029                 LOCK(&adb->namelocks[bucket]);
02030                 *bucketp = bucket;
02031         }
02032 
02033         adbname = ISC_LIST_HEAD(adb->names[bucket]);
02034         while (adbname != NULL) {
02035                 if (!NAME_DEAD(adbname)) {
02036                         if (dns_name_equal(name, &adbname->name)
02037                             && GLUEHINT_OK(adbname, options)
02038                             && STARTATZONE_MATCHES(adbname, options))
02039                                 return (adbname);
02040                 }
02041                 adbname = ISC_LIST_NEXT(adbname, plink);
02042         }
02043 
02044         return (NULL);
02045 }
02046 
02047 /*
02048  * Search for the address.  NOTE:  The bucket is kept locked on both
02049  * success and failure, so it must always be unlocked by the caller.
02050  *
02051  * On the first call to this function, *bucketp must be set to
02052  * DNS_ADB_INVALIDBUCKET.  This will cause a lock to occur.  On
02053  * later calls (within the same "lock path") it can be left alone, so
02054  * if this function is called multiple times locking is only done if
02055  * the bucket changes.
02056  */
02057 static inline dns_adbentry_t *
02058 find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
02059         isc_stdtime_t now)
02060 {
02061         dns_adbentry_t *entry, *entry_next;
02062         int bucket;
02063 
02064         bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
02065 
02066         if (*bucketp == DNS_ADB_INVALIDBUCKET) {
02067                 LOCK(&adb->entrylocks[bucket]);
02068                 *bucketp = bucket;
02069         } else if (*bucketp != bucket) {
02070                 UNLOCK(&adb->entrylocks[*bucketp]);
02071                 LOCK(&adb->entrylocks[bucket]);
02072                 *bucketp = bucket;
02073         }
02074 
02075         /* Search the list, while cleaning up expired entries. */
02076         for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
02077              entry != NULL;
02078              entry = entry_next) {
02079                 entry_next = ISC_LIST_NEXT(entry, plink);
02080                 (void)check_expire_entry(adb, &entry, now);
02081                 if (entry != NULL &&
02082                     (entry->expires == 0 || entry->expires > now) &&
02083                     isc_sockaddr_equal(addr, &entry->sockaddr)) {
02084                         ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
02085                         ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
02086                         return (entry);
02087                 }
02088         }
02089 
02090         return (NULL);
02091 }
02092 
02093 /*
02094  * Entry bucket MUST be locked!
02095  */
02096 static isc_boolean_t
02097 entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
02098               dns_rdatatype_t qtype, isc_stdtime_t now)
02099 {
02100         dns_adblameinfo_t *li, *next_li;
02101         isc_boolean_t is_bad;
02102 
02103         is_bad = ISC_FALSE;
02104 
02105         li = ISC_LIST_HEAD(entry->lameinfo);
02106         if (li == NULL)
02107                 return (ISC_FALSE);
02108         while (li != NULL) {
02109                 next_li = ISC_LIST_NEXT(li, plink);
02110 
02111                 /*
02112                  * Has the entry expired?
02113                  */
02114                 if (li->lame_timer < now) {
02115                         ISC_LIST_UNLINK(entry->lameinfo, li, plink);
02116                         free_adblameinfo(adb, &li);
02117                 }
02118 
02119                 /*
02120                  * Order tests from least to most expensive.
02121                  *
02122                  * We do not break out of the main loop here as
02123                  * we use the loop for house keeping.
02124                  */
02125                 if (li != NULL && !is_bad && li->qtype == qtype &&
02126                     dns_name_equal(qname, &li->qname))
02127                         is_bad = ISC_TRUE;
02128 
02129                 li = next_li;
02130         }
02131 
02132         return (is_bad);
02133 }
02134 
02135 static void
02136 copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
02137                     dns_rdatatype_t qtype, dns_adbname_t *name,
02138                     isc_stdtime_t now)
02139 {
02140         dns_adbnamehook_t *namehook;
02141         dns_adbaddrinfo_t *addrinfo;
02142         dns_adbentry_t *entry;
02143         int bucket;
02144 
02145         bucket = DNS_ADB_INVALIDBUCKET;
02146 
02147         if (find->options & DNS_ADBFIND_INET) {
02148                 namehook = ISC_LIST_HEAD(name->v4);
02149                 while (namehook != NULL) {
02150                         entry = namehook->entry;
02151                         bucket = entry->lock_bucket;
02152                         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
02153                         LOCK(&adb->entrylocks[bucket]);
02154 
02155                         if (!FIND_RETURNLAME(find)
02156                             && entry_is_lame(adb, entry, qname, qtype, now)) {
02157                                 find->options |= DNS_ADBFIND_LAMEPRUNED;
02158                                 goto nextv4;
02159                         }
02160                         addrinfo = new_adbaddrinfo(adb, entry, find->port);
02161                         if (addrinfo == NULL) {
02162                                 find->partial_result |= DNS_ADBFIND_INET;
02163                                 goto out;
02164                         }
02165                         /*
02166                          * Found a valid entry.  Add it to the find's list.
02167                          */
02168                         inc_entry_refcnt(adb, entry, ISC_FALSE);
02169                         ISC_LIST_APPEND(find->list, addrinfo, publink);
02170                         addrinfo = NULL;
02171                 nextv4:
02172                         UNLOCK(&adb->entrylocks[bucket]);
02173                         bucket = DNS_ADB_INVALIDBUCKET;
02174                         namehook = ISC_LIST_NEXT(namehook, plink);
02175                 }
02176         }
02177 
02178         if (find->options & DNS_ADBFIND_INET6) {
02179                 namehook = ISC_LIST_HEAD(name->v6);
02180                 while (namehook != NULL) {
02181                         entry = namehook->entry;
02182                         bucket = entry->lock_bucket;
02183                         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
02184                         LOCK(&adb->entrylocks[bucket]);
02185 
02186                         if (!FIND_RETURNLAME(find)
02187                             && entry_is_lame(adb, entry, qname, qtype, now)) {
02188                                 find->options |= DNS_ADBFIND_LAMEPRUNED;
02189                                 goto nextv6;
02190                         }
02191                         addrinfo = new_adbaddrinfo(adb, entry, find->port);
02192                         if (addrinfo == NULL) {
02193                                 find->partial_result |= DNS_ADBFIND_INET6;
02194                                 goto out;
02195                         }
02196                         /*
02197                          * Found a valid entry.  Add it to the find's list.
02198                          */
02199                         inc_entry_refcnt(adb, entry, ISC_FALSE);
02200                         ISC_LIST_APPEND(find->list, addrinfo, publink);
02201                         addrinfo = NULL;
02202                 nextv6:
02203                         UNLOCK(&adb->entrylocks[bucket]);
02204                         bucket = DNS_ADB_INVALIDBUCKET;
02205                         namehook = ISC_LIST_NEXT(namehook, plink);
02206                 }
02207         }
02208 
02209  out:
02210         if (bucket != DNS_ADB_INVALIDBUCKET)
02211                 UNLOCK(&adb->entrylocks[bucket]);
02212 }
02213 
02214 static void
02215 shutdown_task(isc_task_t *task, isc_event_t *ev) {
02216         dns_adb_t *adb;
02217 
02218         UNUSED(task);
02219 
02220         adb = ev->ev_arg;
02221         INSIST(DNS_ADB_VALID(adb));
02222 
02223         isc_event_free(&ev);
02224         /*
02225          * Wait for lock around check_exit() call to be released.
02226          */
02227         LOCK(&adb->lock);
02228         UNLOCK(&adb->lock);
02229         destroy(adb);
02230 }
02231 
02232 /*
02233  * Name bucket must be locked; adb may be locked; no other locks held.
02234  */
02235 static isc_boolean_t
02236 check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
02237         dns_adbname_t *name;
02238         isc_boolean_t result = ISC_FALSE;
02239 
02240         INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
02241         name = *namep;
02242 
02243         if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
02244                 return (result);
02245         if (NAME_FETCH(name))
02246                 return (result);
02247         if (!EXPIRE_OK(name->expire_v4, now))
02248                 return (result);
02249         if (!EXPIRE_OK(name->expire_v6, now))
02250                 return (result);
02251         if (!EXPIRE_OK(name->expire_target, now))
02252                 return (result);
02253 
02254         /*
02255          * The name is empty.  Delete it.
02256          */
02257         result = kill_name(&name, DNS_EVENT_ADBEXPIRED);
02258         *namep = NULL;
02259 
02260         /*
02261          * Our caller, or one of its callers, will be calling check_exit() at
02262          * some point, so we don't need to do it here.
02263          */
02264         return (result);
02265 }
02266 
02267 /*%
02268  * Examine the tail entry of the LRU list to see if it expires or is stale
02269  * (unused for some period); if so, the name entry will be freed.  If the ADB
02270  * is in the overmem condition, the tail and the next to tail entries
02271  * will be unconditionally removed (unless they have an outstanding fetch).
02272  * We don't care about a race on 'overmem' at the risk of causing some
02273  * collateral damage or a small delay in starting cleanup, so we don't bother
02274  * to lock ADB (if it's not locked).
02275  *
02276  * Name bucket must be locked; adb may be locked; no other locks held.
02277  */
02278 static void
02279 check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
02280         int victims, max_victims;
02281         dns_adbname_t *victim, *next_victim;
02282         isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
02283         int scans = 0;
02284 
02285         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
02286 
02287         max_victims = overmem ? 2 : 1;
02288 
02289         /*
02290          * We limit the number of scanned entries to 10 (arbitrary choice)
02291          * in order to avoid examining too many entries when there are many
02292          * tail entries that have fetches (this should be rare, but could
02293          * happen).
02294          */
02295         victim = ISC_LIST_TAIL(adb->names[bucket]);
02296         for (victims = 0;
02297              victim != NULL && victims < max_victims && scans < 10;
02298              victim = next_victim) {
02299                 INSIST(!NAME_DEAD(victim));
02300                 scans++;
02301                 next_victim = ISC_LIST_PREV(victim, plink);
02302                 (void)check_expire_name(&victim, now);
02303                 if (victim == NULL) {
02304                         victims++;
02305                         goto next;
02306                 }
02307 
02308                 if (!NAME_FETCH(victim) &&
02309                     (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
02310                         RUNTIME_CHECK(kill_name(&victim,
02311                                                 DNS_EVENT_ADBCANCELED) ==
02312                                       ISC_FALSE);
02313                         victims++;
02314                 }
02315 
02316         next:
02317                 if (!overmem)
02318                         break;
02319         }
02320 }
02321 
02322 /*
02323  * Entry bucket must be locked; adb may be locked; no other locks held.
02324  */
02325 static isc_boolean_t
02326 check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
02327 {
02328         dns_adbentry_t *entry;
02329         isc_boolean_t result = ISC_FALSE;
02330 
02331         INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
02332         entry = *entryp;
02333 
02334         if (entry->refcnt != 0)
02335                 return (result);
02336 
02337         if (entry->expires == 0 || entry->expires > now)
02338                 return (result);
02339 
02340         /*
02341          * The entry is not in use.  Delete it.
02342          */
02343         DP(DEF_LEVEL, "killing entry %p", entry);
02344         INSIST(ISC_LINK_LINKED(entry, plink));
02345         result = unlink_entry(adb, entry);
02346         free_adbentry(adb, &entry);
02347         if (result)
02348                 dec_adb_irefcnt(adb);
02349         *entryp = NULL;
02350         return (result);
02351 }
02352 
02353 /*
02354  * ADB must be locked, and no other locks held.
02355  */
02356 static isc_boolean_t
02357 cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
02358         dns_adbname_t *name;
02359         dns_adbname_t *next_name;
02360         isc_boolean_t result = ISC_FALSE;
02361 
02362         DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
02363 
02364         LOCK(&adb->namelocks[bucket]);
02365         if (adb->name_sd[bucket]) {
02366                 UNLOCK(&adb->namelocks[bucket]);
02367                 return (result);
02368         }
02369 
02370         name = ISC_LIST_HEAD(adb->names[bucket]);
02371         while (name != NULL) {
02372                 next_name = ISC_LIST_NEXT(name, plink);
02373                 INSIST(result == ISC_FALSE);
02374                 result = check_expire_namehooks(name, now);
02375                 if (!result)
02376                         result = check_expire_name(&name, now);
02377                 name = next_name;
02378         }
02379         UNLOCK(&adb->namelocks[bucket]);
02380         return (result);
02381 }
02382 
02383 /*
02384  * ADB must be locked, and no other locks held.
02385  */
02386 static isc_boolean_t
02387 cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
02388         dns_adbentry_t *entry, *next_entry;
02389         isc_boolean_t result = ISC_FALSE;
02390 
02391         DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
02392 
02393         LOCK(&adb->entrylocks[bucket]);
02394         entry = ISC_LIST_HEAD(adb->entries[bucket]);
02395         while (entry != NULL) {
02396                 next_entry = ISC_LIST_NEXT(entry, plink);
02397                 INSIST(result == ISC_FALSE);
02398                 result = check_expire_entry(adb, &entry, now);
02399                 entry = next_entry;
02400         }
02401         UNLOCK(&adb->entrylocks[bucket]);
02402         return (result);
02403 }
02404 
02405 static void
02406 destroy(dns_adb_t *adb) {
02407         adb->magic = 0;
02408 
02409         isc_task_detach(&adb->task);
02410         if (adb->excl != NULL)
02411                 isc_task_detach(&adb->excl);
02412 
02413         isc_mempool_destroy(&adb->nmp);
02414         isc_mempool_destroy(&adb->nhmp);
02415         isc_mempool_destroy(&adb->limp);
02416         isc_mempool_destroy(&adb->emp);
02417         isc_mempool_destroy(&adb->ahmp);
02418         isc_mempool_destroy(&adb->aimp);
02419         isc_mempool_destroy(&adb->afmp);
02420 
02421         DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
02422         isc_mem_put(adb->mctx, adb->entries,
02423                     sizeof(*adb->entries) * adb->nentries);
02424         isc_mem_put(adb->mctx, adb->deadentries,
02425                     sizeof(*adb->deadentries) * adb->nentries);
02426         isc_mem_put(adb->mctx, adb->entrylocks,
02427                     sizeof(*adb->entrylocks) * adb->nentries);
02428         isc_mem_put(adb->mctx, adb->entry_sd,
02429                     sizeof(*adb->entry_sd) * adb->nentries);
02430         isc_mem_put(adb->mctx, adb->entry_refcnt,
02431                     sizeof(*adb->entry_refcnt) * adb->nentries);
02432 
02433         DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
02434         isc_mem_put(adb->mctx, adb->names,
02435                     sizeof(*adb->names) * adb->nnames);
02436         isc_mem_put(adb->mctx, adb->deadnames,
02437                     sizeof(*adb->deadnames) * adb->nnames);
02438         isc_mem_put(adb->mctx, adb->namelocks,
02439                     sizeof(*adb->namelocks) * adb->nnames);
02440         isc_mem_put(adb->mctx, adb->name_sd,
02441                     sizeof(*adb->name_sd) * adb->nnames);
02442         isc_mem_put(adb->mctx, adb->name_refcnt,
02443                     sizeof(*adb->name_refcnt) * adb->nnames);
02444 
02445         DESTROYLOCK(&adb->reflock);
02446         DESTROYLOCK(&adb->lock);
02447         DESTROYLOCK(&adb->mplock);
02448         DESTROYLOCK(&adb->overmemlock);
02449         DESTROYLOCK(&adb->entriescntlock);
02450         DESTROYLOCK(&adb->namescntlock);
02451 
02452         isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
02453 }
02454 
02455 
02456 /*
02457  * Public functions.
02458  */
02459 
02460 isc_result_t
02461 dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
02462                isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
02463 {
02464         dns_adb_t *adb;
02465         isc_result_t result;
02466         unsigned int i;
02467 
02468         REQUIRE(mem != NULL);
02469         REQUIRE(view != NULL);
02470         REQUIRE(timermgr != NULL); /* this is actually unused */
02471         REQUIRE(taskmgr != NULL);
02472         REQUIRE(newadb != NULL && *newadb == NULL);
02473 
02474         UNUSED(timermgr);
02475 
02476         adb = isc_mem_get(mem, sizeof(dns_adb_t));
02477         if (adb == NULL)
02478                 return (ISC_R_NOMEMORY);
02479 
02480         /*
02481          * Initialize things here that cannot fail, and especially things
02482          * that must be NULL for the error return to work properly.
02483          */
02484         adb->magic = 0;
02485         adb->erefcnt = 1;
02486         adb->irefcnt = 0;
02487         adb->nmp = NULL;
02488         adb->nhmp = NULL;
02489         adb->limp = NULL;
02490         adb->emp = NULL;
02491         adb->ahmp = NULL;
02492         adb->aimp = NULL;
02493         adb->afmp = NULL;
02494         adb->task = NULL;
02495         adb->excl = NULL;
02496         adb->mctx = NULL;
02497         adb->view = view;
02498         adb->taskmgr = taskmgr;
02499         adb->next_cleanbucket = 0;
02500         ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent),
02501                        0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
02502         adb->cevent_out = ISC_FALSE;
02503         adb->shutting_down = ISC_FALSE;
02504         ISC_LIST_INIT(adb->whenshutdown);
02505 
02506         adb->nentries = nbuckets[0];
02507         adb->entriescnt = 0;
02508         adb->entries = NULL;
02509         adb->deadentries = NULL;
02510         adb->entry_sd = NULL;
02511         adb->entry_refcnt = NULL;
02512         adb->entrylocks = NULL;
02513         ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
02514                        DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
02515                        adb, NULL, NULL);
02516         adb->growentries_sent = ISC_FALSE;
02517 
02518         adb->nnames = nbuckets[0];
02519         adb->namescnt = 0;
02520         adb->names = NULL;
02521         adb->deadnames = NULL;
02522         adb->name_sd = NULL;
02523         adb->name_refcnt = NULL;
02524         adb->namelocks = NULL;
02525         ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
02526                        DNS_EVENT_ADBGROWNAMES, grow_names, adb,
02527                        adb, NULL, NULL);
02528         adb->grownames_sent = ISC_FALSE;
02529 
02530         result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
02531         if (result != ISC_R_SUCCESS) {
02532                 DP(DEF_LEVEL, "adb: task-exclusive mode unavailable, "
02533                               "intializing table sizes to %u\n",
02534                               nbuckets[11]);
02535                 adb->nentries = nbuckets[11];
02536                 adb->nnames = nbuckets[11];
02537         }
02538 
02539         isc_mem_attach(mem, &adb->mctx);
02540 
02541         result = isc_mutex_init(&adb->lock);
02542         if (result != ISC_R_SUCCESS)
02543                 goto fail0b;
02544 
02545         result = isc_mutex_init(&adb->mplock);
02546         if (result != ISC_R_SUCCESS)
02547                 goto fail0c;
02548 
02549         result = isc_mutex_init(&adb->reflock);
02550         if (result != ISC_R_SUCCESS)
02551                 goto fail0d;
02552 
02553         result = isc_mutex_init(&adb->overmemlock);
02554         if (result != ISC_R_SUCCESS)
02555                 goto fail0e;
02556 
02557         result = isc_mutex_init(&adb->entriescntlock);
02558         if (result != ISC_R_SUCCESS)
02559                 goto fail0f;
02560 
02561         result = isc_mutex_init(&adb->namescntlock);
02562         if (result != ISC_R_SUCCESS)
02563                 goto fail0g;
02564 
02565 #define ALLOCENTRY(adb, el) \
02566         do { \
02567                 (adb)->el = isc_mem_get((adb)->mctx, \
02568                                      sizeof(*(adb)->el) * (adb)->nentries); \
02569                 if ((adb)->el == NULL) { \
02570                         result = ISC_R_NOMEMORY; \
02571                         goto fail1; \
02572                 }\
02573         } while (0)
02574         ALLOCENTRY(adb, entries);
02575         ALLOCENTRY(adb, deadentries);
02576         ALLOCENTRY(adb, entrylocks);
02577         ALLOCENTRY(adb, entry_sd);
02578         ALLOCENTRY(adb, entry_refcnt);
02579 #undef ALLOCENTRY
02580 
02581 #define ALLOCNAME(adb, el) \
02582         do { \
02583                 (adb)->el = isc_mem_get((adb)->mctx, \
02584                                      sizeof(*(adb)->el) * (adb)->nnames); \
02585                 if ((adb)->el == NULL) { \
02586                         result = ISC_R_NOMEMORY; \
02587                         goto fail1; \
02588                 }\
02589         } while (0)
02590         ALLOCNAME(adb, names);
02591         ALLOCNAME(adb, deadnames);
02592         ALLOCNAME(adb, namelocks);
02593         ALLOCNAME(adb, name_sd);
02594         ALLOCNAME(adb, name_refcnt);
02595 #undef ALLOCNAME
02596 
02597         /*
02598          * Initialize the bucket locks for names and elements.
02599          * May as well initialize the list heads, too.
02600          */
02601         result = isc_mutexblock_init(adb->namelocks, adb->nnames);
02602         if (result != ISC_R_SUCCESS)
02603                 goto fail1;
02604         for (i = 0; i < adb->nnames; i++) {
02605                 ISC_LIST_INIT(adb->names[i]);
02606                 ISC_LIST_INIT(adb->deadnames[i]);
02607                 adb->name_sd[i] = ISC_FALSE;
02608                 adb->name_refcnt[i] = 0;
02609                 adb->irefcnt++;
02610         }
02611         for (i = 0; i < adb->nentries; i++) {
02612                 ISC_LIST_INIT(adb->entries[i]);
02613                 ISC_LIST_INIT(adb->deadentries[i]);
02614                 adb->entry_sd[i] = ISC_FALSE;
02615                 adb->entry_refcnt[i] = 0;
02616                 adb->irefcnt++;
02617         }
02618         result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
02619         if (result != ISC_R_SUCCESS)
02620                 goto fail2;
02621 
02622         /*
02623          * Memory pools
02624          */
02625 #define MPINIT(t, p, n) do { \
02626         result = isc_mempool_create(mem, sizeof(t), &(p)); \
02627         if (result != ISC_R_SUCCESS) \
02628                 goto fail3; \
02629         isc_mempool_setfreemax((p), FREE_ITEMS); \
02630         isc_mempool_setfillcount((p), FILL_COUNT); \
02631         isc_mempool_setname((p), n); \
02632         isc_mempool_associatelock((p), &adb->mplock); \
02633 } while (0)
02634 
02635         MPINIT(dns_adbname_t, adb->nmp, "adbname");
02636         MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
02637         MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
02638         MPINIT(dns_adbentry_t, adb->emp, "adbentry");
02639         MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
02640         MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
02641         MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
02642 
02643 #undef MPINIT
02644 
02645         /*
02646          * Allocate an internal task.
02647          */
02648         result = isc_task_create(adb->taskmgr, 0, &adb->task);
02649         if (result != ISC_R_SUCCESS)
02650                 goto fail3;
02651 
02652         isc_task_setname(adb->task, "ADB", adb);
02653 
02654         result = isc_stats_create(adb->mctx, &view->adbstats, dns_adbstats_max);
02655         if (result != ISC_R_SUCCESS)
02656                 goto fail3;
02657 
02658         set_adbstat(adb, adb->nentries, dns_adbstats_nentries);
02659         set_adbstat(adb, adb->nnames, dns_adbstats_nnames);
02660 
02661         /*
02662          * Normal return.
02663          */
02664         adb->magic = DNS_ADB_MAGIC;
02665         *newadb = adb;
02666         return (ISC_R_SUCCESS);
02667 
02668  fail3:
02669         if (adb->task != NULL)
02670                 isc_task_detach(&adb->task);
02671 
02672         /* clean up entrylocks */
02673         DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
02674 
02675  fail2: /* clean up namelocks */
02676         DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
02677 
02678  fail1: /* clean up only allocated memory */
02679         if (adb->entries != NULL)
02680                 isc_mem_put(adb->mctx, adb->entries,
02681                             sizeof(*adb->entries) * adb->nentries);
02682         if (adb->deadentries != NULL)
02683                 isc_mem_put(adb->mctx, adb->deadentries,
02684                             sizeof(*adb->deadentries) * adb->nentries);
02685         if (adb->entrylocks != NULL)
02686                 isc_mem_put(adb->mctx, adb->entrylocks,
02687                             sizeof(*adb->entrylocks) * adb->nentries);
02688         if (adb->entry_sd != NULL)
02689                 isc_mem_put(adb->mctx, adb->entry_sd,
02690                             sizeof(*adb->entry_sd) * adb->nentries);
02691         if (adb->entry_refcnt != NULL)
02692                 isc_mem_put(adb->mctx, adb->entry_refcnt,
02693                             sizeof(*adb->entry_refcnt) * adb->nentries);
02694         if (adb->names != NULL)
02695                 isc_mem_put(adb->mctx, adb->names,
02696                             sizeof(*adb->names) * adb->nnames);
02697         if (adb->deadnames != NULL)
02698                 isc_mem_put(adb->mctx, adb->deadnames,
02699                             sizeof(*adb->deadnames) * adb->nnames);
02700         if (adb->namelocks != NULL)
02701                 isc_mem_put(adb->mctx, adb->namelocks,
02702                             sizeof(*adb->namelocks) * adb->nnames);
02703         if (adb->name_sd != NULL)
02704                 isc_mem_put(adb->mctx, adb->name_sd,
02705                             sizeof(*adb->name_sd) * adb->nnames);
02706         if (adb->name_refcnt != NULL)
02707                 isc_mem_put(adb->mctx, adb->name_refcnt,
02708                             sizeof(*adb->name_refcnt) * adb->nnames);
02709         if (adb->nmp != NULL)
02710                 isc_mempool_destroy(&adb->nmp);
02711         if (adb->nhmp != NULL)
02712                 isc_mempool_destroy(&adb->nhmp);
02713         if (adb->limp != NULL)
02714                 isc_mempool_destroy(&adb->limp);
02715         if (adb->emp != NULL)
02716                 isc_mempool_destroy(&adb->emp);
02717         if (adb->ahmp != NULL)
02718                 isc_mempool_destroy(&adb->ahmp);
02719         if (adb->aimp != NULL)
02720                 isc_mempool_destroy(&adb->aimp);
02721         if (adb->afmp != NULL)
02722                 isc_mempool_destroy(&adb->afmp);
02723 
02724         DESTROYLOCK(&adb->namescntlock);
02725  fail0g:
02726         DESTROYLOCK(&adb->entriescntlock);
02727  fail0f:
02728         DESTROYLOCK(&adb->overmemlock);
02729  fail0e:
02730         DESTROYLOCK(&adb->reflock);
02731  fail0d:
02732         DESTROYLOCK(&adb->mplock);
02733  fail0c:
02734         DESTROYLOCK(&adb->lock);
02735  fail0b:
02736         if (adb->excl != NULL)
02737                 isc_task_detach(&adb->excl);
02738         isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
02739 
02740         return (result);
02741 }
02742 
02743 void
02744 dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
02745 
02746         REQUIRE(DNS_ADB_VALID(adb));
02747         REQUIRE(adbx != NULL && *adbx == NULL);
02748 
02749         inc_adb_erefcnt(adb);
02750         *adbx = adb;
02751 }
02752 
02753 void
02754 dns_adb_detach(dns_adb_t **adbx) {
02755         dns_adb_t *adb;
02756         isc_boolean_t need_exit_check;
02757 
02758         REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
02759 
02760         adb = *adbx;
02761         *adbx = NULL;
02762 
02763         INSIST(adb->erefcnt > 0);
02764 
02765         LOCK(&adb->reflock);
02766         adb->erefcnt--;
02767         need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
02768         UNLOCK(&adb->reflock);
02769 
02770         if (need_exit_check) {
02771                 LOCK(&adb->lock);
02772                 INSIST(adb->shutting_down);
02773                 check_exit(adb);
02774                 UNLOCK(&adb->lock);
02775         }
02776 }
02777 
02778 void
02779 dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
02780         isc_task_t *clone;
02781         isc_event_t *event;
02782         isc_boolean_t zeroirefcnt = ISC_FALSE;
02783 
02784         /*
02785          * Send '*eventp' to 'task' when 'adb' has shutdown.
02786          */
02787 
02788         REQUIRE(DNS_ADB_VALID(adb));
02789         REQUIRE(eventp != NULL);
02790 
02791         event = *eventp;
02792         *eventp = NULL;
02793 
02794         LOCK(&adb->lock);
02795 
02796         LOCK(&adb->reflock);
02797         zeroirefcnt = ISC_TF(adb->irefcnt == 0);
02798 
02799         if (adb->shutting_down && zeroirefcnt &&
02800             isc_mempool_getallocated(adb->ahmp) == 0) {
02801                 /*
02802                  * We're already shutdown.  Send the event.
02803                  */
02804                 event->ev_sender = adb;
02805                 isc_task_send(task, &event);
02806         } else {
02807                 clone = NULL;
02808                 isc_task_attach(task, &clone);
02809                 event->ev_sender = clone;
02810                 ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
02811         }
02812 
02813         UNLOCK(&adb->reflock);
02814         UNLOCK(&adb->lock);
02815 }
02816 
02817 static void
02818 shutdown_stage2(isc_task_t *task, isc_event_t *event) {
02819         dns_adb_t *adb;
02820 
02821         UNUSED(task);
02822 
02823         adb = event->ev_arg;
02824         INSIST(DNS_ADB_VALID(adb));
02825 
02826         LOCK(&adb->lock);
02827         INSIST(adb->shutting_down);
02828         adb->cevent_out = ISC_FALSE;
02829         (void)shutdown_names(adb);
02830         (void)shutdown_entries(adb);
02831         if (dec_adb_irefcnt(adb))
02832                 check_exit(adb);
02833         UNLOCK(&adb->lock);
02834 }
02835 
02836 void
02837 dns_adb_shutdown(dns_adb_t *adb) {
02838         isc_event_t *event;
02839 
02840         /*
02841          * Shutdown 'adb'.
02842          */
02843 
02844         LOCK(&adb->lock);
02845 
02846         if (!adb->shutting_down) {
02847                 adb->shutting_down = ISC_TRUE;
02848                 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
02849                 /*
02850                  * Isolate shutdown_names and shutdown_entries calls.
02851                  */
02852                 inc_adb_irefcnt(adb);
02853                 ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
02854                                DNS_EVENT_ADBCONTROL, shutdown_stage2, adb,
02855                                adb, NULL, NULL);
02856                 adb->cevent_out = ISC_TRUE;
02857                 event = &adb->cevent;
02858                 isc_task_send(adb->task, &event);
02859         }
02860 
02861         UNLOCK(&adb->lock);
02862 }
02863 
02864 isc_result_t
02865 dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
02866                    void *arg, dns_name_t *name, dns_name_t *qname,
02867                    dns_rdatatype_t qtype, unsigned int options,
02868                    isc_stdtime_t now, dns_name_t *target,
02869                    in_port_t port, dns_adbfind_t **findp)
02870 {
02871         return (dns_adb_createfind2(adb, task, action, arg, name,
02872                                     qname, qtype, options, now,
02873                                     target, port, 0, NULL, findp));
02874 }
02875 
02876 isc_result_t
02877 dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
02878                     void *arg, dns_name_t *name, dns_name_t *qname,
02879                     dns_rdatatype_t qtype, unsigned int options,
02880                     isc_stdtime_t now, dns_name_t *target,
02881                     in_port_t port, unsigned int depth, isc_counter_t *qc,
02882                     dns_adbfind_t **findp)
02883 {
02884         dns_adbfind_t *find;
02885         dns_adbname_t *adbname;
02886         int bucket;
02887         isc_boolean_t want_event, start_at_zone, alias, have_address;
02888         isc_result_t result;
02889         unsigned int wanted_addresses;
02890         unsigned int wanted_fetches;
02891         unsigned int query_pending;
02892         char namebuf[DNS_NAME_FORMATSIZE];
02893 
02894         REQUIRE(DNS_ADB_VALID(adb));
02895         if (task != NULL) {
02896                 REQUIRE(action != NULL);
02897         }
02898         REQUIRE(name != NULL);
02899         REQUIRE(qname != NULL);
02900         REQUIRE(findp != NULL && *findp == NULL);
02901         REQUIRE(target == NULL || dns_name_hasbuffer(target));
02902 
02903         REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
02904 
02905         result = ISC_R_UNEXPECTED;
02906         POST(result);
02907         wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
02908         wanted_fetches = 0;
02909         query_pending = 0;
02910         want_event = ISC_FALSE;
02911         start_at_zone = ISC_FALSE;
02912         alias = ISC_FALSE;
02913 
02914         if (now == 0)
02915                 isc_stdtime_get(&now);
02916 
02917         /*
02918          * XXXMLG  Move this comment somewhere else!
02919          *
02920          * Look up the name in our internal database.
02921          *
02922          * Possibilities:  Note that these are not always exclusive.
02923          *
02924          *      No name found.  In this case, allocate a new name header and
02925          *      an initial namehook or two.  If any of these allocations
02926          *      fail, clean up and return ISC_R_NOMEMORY.
02927          *
02928          *      Name found, valid addresses present.  Allocate one addrinfo
02929          *      structure for each found and append it to the linked list
02930          *      of addresses for this header.
02931          *
02932          *      Name found, queries pending.  In this case, if a task was
02933          *      passed in, allocate a job id, attach it to the name's job
02934          *      list and remember to tell the caller that there will be
02935          *      more info coming later.
02936          */
02937 
02938         find = new_adbfind(adb);
02939         if (find == NULL)
02940                 return (ISC_R_NOMEMORY);
02941 
02942         find->port = port;
02943 
02944         /*
02945          * Remember what types of addresses we are interested in.
02946          */
02947         find->options = options;
02948         find->flags |= wanted_addresses;
02949         if (FIND_WANTEVENT(find)) {
02950                 REQUIRE(task != NULL);
02951         }
02952 
02953         if (isc_log_wouldlog(dns_lctx, DEF_LEVEL))
02954                 dns_name_format(name, namebuf, sizeof(namebuf));
02955         else
02956                 namebuf[0] = 0;
02957 
02958         /*
02959          * Try to see if we know anything about this name at all.
02960          */
02961         bucket = DNS_ADB_INVALIDBUCKET;
02962         adbname = find_name_and_lock(adb, name, find->options, &bucket);
02963         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
02964         if (adb->name_sd[bucket]) {
02965                 DP(DEF_LEVEL,
02966                    "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
02967                 RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
02968                 result = ISC_R_SHUTTINGDOWN;
02969                 goto out;
02970         }
02971 
02972         /*
02973          * Nothing found.  Allocate a new adbname structure for this name.
02974          */
02975         if (adbname == NULL) {
02976                 /*
02977                  * See if there is any stale name at the end of list, and purge
02978                  * it if so.
02979                  */
02980                 check_stale_name(adb, bucket, now);
02981 
02982                 adbname = new_adbname(adb, name);
02983                 if (adbname == NULL) {
02984                         RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
02985                         result = ISC_R_NOMEMORY;
02986                         goto out;
02987                 }
02988                 link_name(adb, bucket, adbname);
02989                 if (FIND_HINTOK(find))
02990                         adbname->flags |= NAME_HINT_OK;
02991                 if (FIND_GLUEOK(find))
02992                         adbname->flags |= NAME_GLUE_OK;
02993                 if (FIND_STARTATZONE(find))
02994                         adbname->flags |= NAME_STARTATZONE;
02995         } else {
02996                 /* Move this name forward in the LRU list */
02997                 ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
02998                 ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
02999         }
03000         adbname->last_used = now;
03001 
03002         /*
03003          * Expire old entries, etc.
03004          */
03005         RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
03006 
03007         /*
03008          * Do we know that the name is an alias?
03009          */
03010         if (!EXPIRE_OK(adbname->expire_target, now)) {
03011                 /*
03012                  * Yes, it is.
03013                  */
03014                 DP(DEF_LEVEL,
03015                    "dns_adb_createfind: name %s (%p) is an alias (cached)",
03016                    namebuf, adbname);
03017                 alias = ISC_TRUE;
03018                 goto post_copy;
03019         }
03020 
03021         /*
03022          * Try to populate the name from the database and/or
03023          * start fetches.  First try looking for an A record
03024          * in the database.
03025          */
03026         if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
03027             && WANT_INET(wanted_addresses)) {
03028                 result = dbfind_name(adbname, now, dns_rdatatype_a);
03029                 if (result == ISC_R_SUCCESS) {
03030                         DP(DEF_LEVEL,
03031                            "dns_adb_createfind: found A for name %s (%p) in db",
03032                            namebuf, adbname);
03033                         goto v6;
03034                 }
03035 
03036                 /*
03037                  * Did we get a CNAME or DNAME?
03038                  */
03039                 if (result == DNS_R_ALIAS) {
03040                         DP(DEF_LEVEL,
03041                            "dns_adb_createfind: name %s (%p) is an alias",
03042                            namebuf, adbname);
03043                         alias = ISC_TRUE;
03044                         goto post_copy;
03045                 }
03046 
03047                 /*
03048                  * If the name doesn't exist at all, don't bother with
03049                  * v6 queries; they won't work.
03050                  *
03051                  * If the name does exist but we didn't get our data, go
03052                  * ahead and try AAAA.
03053                  *
03054                  * If the result is neither of these, try a fetch for A.
03055                  */
03056                 if (NXDOMAIN_RESULT(result))
03057                         goto fetch;
03058                 else if (NXRRSET_RESULT(result))
03059                         goto v6;
03060 
03061                 if (!NAME_FETCH_V4(adbname))
03062                         wanted_fetches |= DNS_ADBFIND_INET;
03063         }
03064 
03065  v6:
03066         if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
03067             && WANT_INET6(wanted_addresses)) {
03068                 result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
03069                 if (result == ISC_R_SUCCESS) {
03070                         DP(DEF_LEVEL,
03071                            "dns_adb_createfind: found AAAA for name %s (%p)",
03072                            namebuf, adbname);
03073                         goto fetch;
03074                 }
03075 
03076                 /*
03077                  * Did we get a CNAME or DNAME?
03078                  */
03079                 if (result == DNS_R_ALIAS) {
03080                         DP(DEF_LEVEL,
03081                            "dns_adb_createfind: name %s (%p) is an alias",
03082                            namebuf, adbname);
03083                         alias = ISC_TRUE;
03084                         goto post_copy;
03085                 }
03086 
03087                 /*
03088                  * Listen to negative cache hints, and don't start
03089                  * another query.
03090                  */
03091                 if (NCACHE_RESULT(result) || AUTH_NX(result))
03092                         goto fetch;
03093 
03094                 if (!NAME_FETCH_V6(adbname))
03095                         wanted_fetches |= DNS_ADBFIND_INET6;
03096         }
03097 
03098  fetch:
03099         if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
03100             (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
03101                 have_address = ISC_TRUE;
03102         else
03103                 have_address = ISC_FALSE;
03104         if (wanted_fetches != 0 &&
03105             ! (FIND_AVOIDFETCHES(find) && have_address)) {
03106                 /*
03107                  * We're missing at least one address family.  Either the
03108                  * caller hasn't instructed us to avoid fetches, or we don't
03109                  * know anything about any of the address families that would
03110                  * be acceptable so we have to launch fetches.
03111                  */
03112 
03113                 if (FIND_STARTATZONE(find))
03114                         start_at_zone = ISC_TRUE;
03115 
03116                 /*
03117                  * Start V4.
03118                  */
03119                 if (WANT_INET(wanted_fetches) &&
03120                     fetch_name(adbname, start_at_zone, depth, qc,
03121                                dns_rdatatype_a) == ISC_R_SUCCESS) {
03122                         DP(DEF_LEVEL, "dns_adb_createfind: "
03123                            "started A fetch for name %s (%p)",
03124                            namebuf, adbname);
03125                 }
03126 
03127                 /*
03128                  * Start V6.
03129                  */
03130                 if (WANT_INET6(wanted_fetches) &&
03131                     fetch_name(adbname, start_at_zone, depth, qc,
03132                                dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
03133                         DP(DEF_LEVEL, "dns_adb_createfind: "
03134                            "started AAAA fetch for name %s (%p)",
03135                            namebuf, adbname);
03136                 }
03137         }
03138 
03139         /*
03140          * Run through the name and copy out the bits we are
03141          * interested in.
03142          */
03143         copy_namehook_lists(adb, find, qname, qtype, adbname, now);
03144 
03145  post_copy:
03146         if (NAME_FETCH_V4(adbname))
03147                 query_pending |= DNS_ADBFIND_INET;
03148         if (NAME_FETCH_V6(adbname))
03149                 query_pending |= DNS_ADBFIND_INET6;
03150 
03151         /*
03152          * Attach to the name's query list if there are queries
03153          * already running, and we have been asked to.
03154          */
03155         want_event = ISC_TRUE;
03156         if (!FIND_WANTEVENT(find))
03157                 want_event = ISC_FALSE;
03158         if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
03159                 want_event = ISC_FALSE;
03160         if ((wanted_addresses & query_pending) == 0)
03161                 want_event = ISC_FALSE;
03162         if (alias)
03163                 want_event = ISC_FALSE;
03164         if (want_event) {
03165                 find->adbname = adbname;
03166                 find->name_bucket = bucket;
03167                 ISC_LIST_APPEND(adbname->finds, find, plink);
03168                 find->query_pending = (query_pending & wanted_addresses);
03169                 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
03170                 find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
03171                 DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
03172                    find, adbname);
03173         } else {
03174                 /*
03175                  * Remove the flag so the caller knows there will never
03176                  * be an event, and set internal flags to fake that
03177                  * the event was sent and freed, so dns_adb_destroyfind() will
03178                  * do the right thing.
03179                  */
03180                 find->query_pending = (query_pending & wanted_addresses);
03181                 find->options &= ~DNS_ADBFIND_WANTEVENT;
03182                 find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
03183                 find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
03184         }
03185 
03186         find->partial_result |= (adbname->partial_result & wanted_addresses);
03187         if (alias) {
03188                 if (target != NULL) {
03189                         result = dns_name_copy(&adbname->target, target, NULL);
03190                         if (result != ISC_R_SUCCESS)
03191                                 goto out;
03192                 }
03193                 result = DNS_R_ALIAS;
03194         } else
03195                 result = ISC_R_SUCCESS;
03196 
03197         /*
03198          * Copy out error flags from the name structure into the find.
03199          */
03200         find->result_v4 = find_err_map[adbname->fetch_err];
03201         find->result_v6 = find_err_map[adbname->fetch6_err];
03202 
03203  out:
03204         if (find != NULL) {
03205                 *findp = find;
03206 
03207                 if (want_event) {
03208                         isc_task_t *taskp;
03209 
03210                         INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
03211                         taskp = NULL;
03212                         isc_task_attach(task, &taskp);
03213                         find->event.ev_sender = taskp;
03214                         find->event.ev_action = action;
03215                         find->event.ev_arg = arg;
03216                 }
03217         }
03218 
03219         UNLOCK(&adb->namelocks[bucket]);
03220 
03221         return (result);
03222 }
03223 
03224 void
03225 dns_adb_destroyfind(dns_adbfind_t **findp) {
03226         dns_adbfind_t *find;
03227         dns_adbentry_t *entry;
03228         dns_adbaddrinfo_t *ai;
03229         int bucket;
03230         dns_adb_t *adb;
03231         isc_boolean_t overmem;
03232 
03233         REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
03234         find = *findp;
03235         *findp = NULL;
03236 
03237         LOCK(&find->lock);
03238 
03239         DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
03240 
03241         adb = find->adb;
03242         REQUIRE(DNS_ADB_VALID(adb));
03243 
03244         REQUIRE(FIND_EVENTFREED(find));
03245 
03246         bucket = find->name_bucket;
03247         INSIST(bucket == DNS_ADB_INVALIDBUCKET);
03248 
03249         UNLOCK(&find->lock);
03250 
03251         /*
03252          * The find doesn't exist on any list, and nothing is locked.
03253          * Return the find to the memory pool, and decrement the adb's
03254          * reference count.
03255          */
03256         overmem = isc_mem_isovermem(adb->mctx);
03257         ai = ISC_LIST_HEAD(find->list);
03258         while (ai != NULL) {
03259                 ISC_LIST_UNLINK(find->list, ai, publink);
03260                 entry = ai->entry;
03261                 ai->entry = NULL;
03262                 INSIST(DNS_ADBENTRY_VALID(entry));
03263                 RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
03264                               ISC_FALSE);
03265                 free_adbaddrinfo(adb, &ai);
03266                 ai = ISC_LIST_HEAD(find->list);
03267         }
03268 
03269         /*
03270          * WARNING:  The find is freed with the adb locked.  This is done
03271          * to avoid a race condition where we free the find, some other
03272          * thread tests to see if it should be destroyed, detects it should
03273          * be, destroys it, and then we try to lock it for our check, but the
03274          * lock is destroyed.
03275          */
03276         LOCK(&adb->lock);
03277         if (free_adbfind(adb, &find))
03278                 check_exit(adb);
03279         UNLOCK(&adb->lock);
03280 }
03281 
03282 void
03283 dns_adb_cancelfind(dns_adbfind_t *find) {
03284         isc_event_t *ev;
03285         isc_task_t *task;
03286         dns_adb_t *adb;
03287         int bucket;
03288         int unlock_bucket;
03289 
03290         LOCK(&find->lock);
03291 
03292         DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
03293 
03294         adb = find->adb;
03295         REQUIRE(DNS_ADB_VALID(adb));
03296 
03297         REQUIRE(!FIND_EVENTFREED(find));
03298         REQUIRE(FIND_WANTEVENT(find));
03299 
03300         bucket = find->name_bucket;
03301         if (bucket == DNS_ADB_INVALIDBUCKET)
03302                 goto cleanup;
03303 
03304         /*
03305          * We need to get the adbname's lock to unlink the find.
03306          */
03307         unlock_bucket = bucket;
03308         violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
03309         bucket = find->name_bucket;
03310         if (bucket != DNS_ADB_INVALIDBUCKET) {
03311                 ISC_LIST_UNLINK(find->adbname->finds, find, plink);
03312                 find->adbname = NULL;
03313                 find->name_bucket = DNS_ADB_INVALIDBUCKET;
03314         }
03315         UNLOCK(&adb->namelocks[unlock_bucket]);
03316         bucket = DNS_ADB_INVALIDBUCKET;
03317         POST(bucket);
03318 
03319  cleanup:
03320 
03321         if (!FIND_EVENTSENT(find)) {
03322                 ev = &find->event;
03323                 task = ev->ev_sender;
03324                 ev->ev_sender = find;
03325                 ev->ev_type = DNS_EVENT_ADBCANCELED;
03326                 ev->ev_destroy = event_free;
03327                 ev->ev_destroy_arg = find;
03328                 find->result_v4 = ISC_R_CANCELED;
03329                 find->result_v6 = ISC_R_CANCELED;
03330 
03331                 DP(DEF_LEVEL, "sending event %p to task %p for find %p",
03332                    ev, task, find);
03333 
03334                 isc_task_sendanddetach(&task, (isc_event_t **)&ev);
03335         }
03336 
03337         UNLOCK(&find->lock);
03338 }
03339 
03340 void
03341 dns_adb_dump(dns_adb_t *adb, FILE *f) {
03342         unsigned int i;
03343         isc_stdtime_t now;
03344 
03345         REQUIRE(DNS_ADB_VALID(adb));
03346         REQUIRE(f != NULL);
03347 
03348         /*
03349          * Lock the adb itself, lock all the name buckets, then lock all
03350          * the entry buckets.  This should put the adb into a state where
03351          * nothing can change, so we can iterate through everything and
03352          * print at our leisure.
03353          */
03354 
03355         LOCK(&adb->lock);
03356         isc_stdtime_get(&now);
03357 
03358         for (i = 0; i < adb->nnames; i++)
03359                 RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
03360         for (i = 0; i < adb->nentries; i++)
03361                 RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
03362 
03363         dump_adb(adb, f, ISC_FALSE, now);
03364         UNLOCK(&adb->lock);
03365 }
03366 
03367 static void
03368 dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
03369         if (value == INT_MAX)
03370                 return;
03371         fprintf(f, " [%s TTL %d]", legend, value - now);
03372 }
03373 
03374 static void
03375 dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
03376         unsigned int i;
03377         dns_adbname_t *name;
03378         dns_adbentry_t *entry;
03379 
03380         fprintf(f, ";\n; Address database dump\n;\n");
03381         fprintf(f, "; [edns success/4096 timeout/1432 timeout/1232 timeout/"
03382                 "512 timeout]\n");
03383         fprintf(f, "; [plain success/timeout]\n;\n");
03384         if (debug)
03385                 fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
03386                         adb, adb->erefcnt, adb->irefcnt,
03387                         isc_mempool_getallocated(adb->nhmp));
03388 
03389         for (i = 0; i < adb->nnames; i++)
03390                 LOCK(&adb->namelocks[i]);
03391         for (i = 0; i < adb->nentries; i++)
03392                 LOCK(&adb->entrylocks[i]);
03393 
03394         /*
03395          * Dump the names
03396          */
03397         for (i = 0; i < adb->nnames; i++) {
03398                 name = ISC_LIST_HEAD(adb->names[i]);
03399                 if (name == NULL)
03400                         continue;
03401                 if (debug)
03402                         fprintf(f, "; bucket %d\n", i);
03403                 for (;
03404                      name != NULL;
03405                      name = ISC_LIST_NEXT(name, plink))
03406                 {
03407                         if (debug)
03408                                 fprintf(f, "; name %p (flags %08x)\n",
03409                                         name, name->flags);
03410 
03411                         fprintf(f, "; ");
03412                         print_dns_name(f, &name->name);
03413                         if (dns_name_countlabels(&name->target) > 0) {
03414                                 fprintf(f, " alias ");
03415                                 print_dns_name(f, &name->target);
03416                         }
03417 
03418                         dump_ttl(f, "v4", name->expire_v4, now);
03419                         dump_ttl(f, "v6", name->expire_v6, now);
03420                         dump_ttl(f, "target", name->expire_target, now);
03421 
03422                         fprintf(f, " [v4 %s] [v6 %s]",
03423                                 errnames[name->fetch_err],
03424                                 errnames[name->fetch6_err]);
03425 
03426                         fprintf(f, "\n");
03427 
03428                         print_namehook_list(f, "v4", &name->v4, debug, now);
03429                         print_namehook_list(f, "v6", &name->v6, debug, now);
03430 
03431                         if (debug)
03432                                 print_fetch_list(f, name);
03433                         if (debug)
03434                                 print_find_list(f, name);
03435 
03436                 }
03437         }
03438 
03439         fprintf(f, ";\n; Unassociated entries\n;\n");
03440 
03441         for (i = 0; i < adb->nentries; i++) {
03442                 entry = ISC_LIST_HEAD(adb->entries[i]);
03443                 while (entry != NULL) {
03444                         if (entry->refcnt == 0)
03445                                 dump_entry(f, entry, debug, now);
03446                         entry = ISC_LIST_NEXT(entry, plink);
03447                 }
03448         }
03449 
03450         /*
03451          * Unlock everything
03452          */
03453         for (i = 0; i < adb->nentries; i++)
03454                 UNLOCK(&adb->entrylocks[i]);
03455         for (i = 0; i < adb->nnames; i++)
03456                 UNLOCK(&adb->namelocks[i]);
03457 }
03458 
03459 static void
03460 dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
03461            isc_stdtime_t now)
03462 {
03463         char addrbuf[ISC_NETADDR_FORMATSIZE];
03464         char typebuf[DNS_RDATATYPE_FORMATSIZE];
03465         isc_netaddr_t netaddr;
03466         dns_adblameinfo_t *li;
03467 
03468         isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
03469         isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
03470 
03471         if (debug)
03472                 fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
03473 
03474         fprintf(f, ";\t%s [srtt %u] [flags %08x] [edns %u/%u/%u/%u/%u] "
03475                 "[plain %u/%u]", addrbuf, entry->srtt, entry->flags,
03476                 entry->edns, entry->to4096, entry->to1432, entry->to1232,
03477                 entry->to512, entry->plain, entry->plainto);
03478         if (entry->udpsize != 0U)
03479                 fprintf(f, " [udpsize %u]", entry->udpsize);
03480 #ifdef ISC_PLATFORM_USESIT
03481         if (entry->sit != NULL) {
03482                 unsigned int i;
03483                 fprintf(f, " [sit=");
03484                 for (i = 0; i < entry->sitlen; i++)
03485                         fprintf(f, "%02x", entry->sit[i]);
03486                 fprintf(f, "]");
03487         }
03488 #endif
03489 
03490         if (entry->expires != 0)
03491                 fprintf(f, " [ttl %d]", entry->expires - now);
03492         fprintf(f, "\n");
03493         for (li = ISC_LIST_HEAD(entry->lameinfo);
03494              li != NULL;
03495              li = ISC_LIST_NEXT(li, plink)) {
03496                 fprintf(f, ";\t\t");
03497                 print_dns_name(f, &li->qname);
03498                 dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
03499                 fprintf(f, " %s [lame TTL %d]\n", typebuf,
03500                         li->lame_timer - now);
03501         }
03502 }
03503 
03504 void
03505 dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
03506         char tmp[512];
03507         const char *tmpp;
03508         dns_adbaddrinfo_t *ai;
03509         isc_sockaddr_t *sa;
03510 
03511         /*
03512          * Not used currently, in the API Just In Case we
03513          * want to dump out the name and/or entries too.
03514          */
03515 
03516         LOCK(&find->lock);
03517 
03518         fprintf(f, ";Find %p\n", find);
03519         fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
03520                 find->query_pending, find->partial_result,
03521                 find->options, find->flags);
03522         fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
03523                 find->name_bucket, find->adbname, find->event.ev_sender);
03524 
03525         ai = ISC_LIST_HEAD(find->list);
03526         if (ai != NULL)
03527                 fprintf(f, "\tAddresses:\n");
03528         while (ai != NULL) {
03529                 sa = &ai->sockaddr;
03530                 switch (sa->type.sa.sa_family) {
03531                 case AF_INET:
03532                         tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
03533                                          tmp, sizeof(tmp));
03534                         break;
03535                 case AF_INET6:
03536                         tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
03537                                          tmp, sizeof(tmp));
03538                         break;
03539                 default:
03540                         tmpp = "UnkFamily";
03541                 }
03542 
03543                 if (tmpp == NULL)
03544                         tmpp = "BadAddress";
03545 
03546                 fprintf(f, "\t\tentry %p, flags %08x"
03547                         " srtt %u addr %s\n",
03548                         ai->entry, ai->flags, ai->srtt, tmpp);
03549 
03550                 ai = ISC_LIST_NEXT(ai, publink);
03551         }
03552 
03553         UNLOCK(&find->lock);
03554 }
03555 
03556 static void
03557 print_dns_name(FILE *f, dns_name_t *name) {
03558         char buf[DNS_NAME_FORMATSIZE];
03559 
03560         INSIST(f != NULL);
03561 
03562         dns_name_format(name, buf, sizeof(buf));
03563         fprintf(f, "%s", buf);
03564 }
03565 
03566 static void
03567 print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
03568                     isc_boolean_t debug, isc_stdtime_t now)
03569 {
03570         dns_adbnamehook_t *nh;
03571 
03572         for (nh = ISC_LIST_HEAD(*list);
03573              nh != NULL;
03574              nh = ISC_LIST_NEXT(nh, plink))
03575         {
03576                 if (debug)
03577                         fprintf(f, ";\tHook(%s) %p\n", legend, nh);
03578                 dump_entry(f, nh->entry, debug, now);
03579         }
03580 }
03581 
03582 static inline void
03583 print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
03584         fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
03585                 type, ft, ft->fetch);
03586 }
03587 
03588 static void
03589 print_fetch_list(FILE *f, dns_adbname_t *n) {
03590         if (NAME_FETCH_A(n))
03591                 print_fetch(f, n->fetch_a, "A");
03592         if (NAME_FETCH_AAAA(n))
03593                 print_fetch(f, n->fetch_aaaa, "AAAA");
03594 }
03595 
03596 static void
03597 print_find_list(FILE *f, dns_adbname_t *name) {
03598         dns_adbfind_t *find;
03599 
03600         find = ISC_LIST_HEAD(name->finds);
03601         while (find != NULL) {
03602                 dns_adb_dumpfind(find, f);
03603                 find = ISC_LIST_NEXT(find, plink);
03604         }
03605 }
03606 
03607 static isc_result_t
03608 dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
03609 {
03610         isc_result_t result;
03611         dns_rdataset_t rdataset;
03612         dns_adb_t *adb;
03613         dns_fixedname_t foundname;
03614         dns_name_t *fname;
03615 
03616         INSIST(DNS_ADBNAME_VALID(adbname));
03617         adb = adbname->adb;
03618         INSIST(DNS_ADB_VALID(adb));
03619         INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
03620 
03621         dns_fixedname_init(&foundname);
03622         fname = dns_fixedname_name(&foundname);
03623         dns_rdataset_init(&rdataset);
03624 
03625         if (rdtype == dns_rdatatype_a)
03626                 adbname->fetch_err = FIND_ERR_UNEXPECTED;
03627         else
03628                 adbname->fetch6_err = FIND_ERR_UNEXPECTED;
03629 
03630         /*
03631          * We need to specify whether to search static-stub zones (if
03632          * configured) depending on whether this is a "start at zone" lookup,
03633          * i.e., whether it's a "bailiwick" glue.  If it's bailiwick (in which
03634          * case NAME_STARTATZONE is set) we need to stop the search at any
03635          * matching static-stub zone without looking into the cache to honor
03636          * the configuration on which server we should send queries to.
03637          */
03638         result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
03639                                 NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
03640                                 ISC_TF(NAME_HINTOK(adbname)),
03641                                 (adbname->flags & NAME_STARTATZONE) != 0 ?
03642                                 ISC_TRUE : ISC_FALSE,
03643                                 NULL, NULL, fname, &rdataset, NULL);
03644 
03645         /* XXXVIX this switch statement is too sparse to gen a jump table. */
03646         switch (result) {
03647         case DNS_R_GLUE:
03648         case DNS_R_HINT:
03649         case ISC_R_SUCCESS:
03650                 /*
03651                  * Found in the database.  Even if we can't copy out
03652                  * any information, return success, or else a fetch
03653                  * will be made, which will only make things worse.
03654                  */
03655                 if (rdtype == dns_rdatatype_a)
03656                         adbname->fetch_err = FIND_ERR_SUCCESS;
03657                 else
03658                         adbname->fetch6_err = FIND_ERR_SUCCESS;
03659                 result = import_rdataset(adbname, &rdataset, now);
03660                 break;
03661         case DNS_R_NXDOMAIN:
03662         case DNS_R_NXRRSET:
03663                 /*
03664                  * We're authoritative and the data doesn't exist.
03665                  * Make up a negative cache entry so we don't ask again
03666                  * for a while.
03667                  *
03668                  * XXXRTH  What time should we use?  I'm putting in 30 seconds
03669                  * for now.
03670                  */
03671                 if (rdtype == dns_rdatatype_a) {
03672                         adbname->expire_v4 = now + 30;
03673                         DP(NCACHE_LEVEL,
03674                            "adb name %p: Caching auth negative entry for A",
03675                            adbname);
03676                         if (result == DNS_R_NXDOMAIN)
03677                                 adbname->fetch_err = FIND_ERR_NXDOMAIN;
03678                         else
03679                                 adbname->fetch_err = FIND_ERR_NXRRSET;
03680                 } else {
03681                         DP(NCACHE_LEVEL,
03682                            "adb name %p: Caching auth negative entry for AAAA",
03683                            adbname);
03684                         adbname->expire_v6 = now + 30;
03685                         if (result == DNS_R_NXDOMAIN)
03686                                 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
03687                         else
03688                                 adbname->fetch6_err = FIND_ERR_NXRRSET;
03689                 }
03690                 break;
03691         case DNS_R_NCACHENXDOMAIN:
03692         case DNS_R_NCACHENXRRSET:
03693                 /*
03694                  * We found a negative cache entry.  Pull the TTL from it
03695                  * so we won't ask again for a while.
03696                  */
03697                 rdataset.ttl = ttlclamp(rdataset.ttl);
03698                 if (rdtype == dns_rdatatype_a) {
03699                         adbname->expire_v4 = rdataset.ttl + now;
03700                         if (result == DNS_R_NCACHENXDOMAIN)
03701                                 adbname->fetch_err = FIND_ERR_NXDOMAIN;
03702                         else
03703                                 adbname->fetch_err = FIND_ERR_NXRRSET;
03704                         DP(NCACHE_LEVEL,
03705                           "adb name %p: Caching negative entry for A (ttl %u)",
03706                            adbname, rdataset.ttl);
03707                 } else {
03708                         DP(NCACHE_LEVEL,
03709                        "adb name %p: Caching negative entry for AAAA (ttl %u)",
03710                            adbname, rdataset.ttl);
03711                         adbname->expire_v6 = rdataset.ttl + now;
03712                         if (result == DNS_R_NCACHENXDOMAIN)
03713                                 adbname->fetch6_err = FIND_ERR_NXDOMAIN;
03714                         else
03715                                 adbname->fetch6_err = FIND_ERR_NXRRSET;
03716                 }
03717                 break;
03718         case DNS_R_CNAME:
03719         case DNS_R_DNAME:
03720                 /*
03721                  * Clear the hint and glue flags, so this will match
03722                  * more often.
03723                  */
03724                 adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
03725 
03726                 rdataset.ttl = ttlclamp(rdataset.ttl);
03727                 clean_target(adb, &adbname->target);
03728                 adbname->expire_target = INT_MAX;
03729                 result = set_target(adb, &adbname->name, fname, &rdataset,
03730                                     &adbname->target);
03731                 if (result == ISC_R_SUCCESS) {
03732                         result = DNS_R_ALIAS;
03733                         DP(NCACHE_LEVEL,
03734                            "adb name %p: caching alias target",
03735                            adbname);
03736                         adbname->expire_target = rdataset.ttl + now;
03737                 }
03738                 if (rdtype == dns_rdatatype_a)
03739                         adbname->fetch_err = FIND_ERR_SUCCESS;
03740                 else
03741                         adbname->fetch6_err = FIND_ERR_SUCCESS;
03742                 break;
03743         }
03744 
03745         if (dns_rdataset_isassociated(&rdataset))
03746                 dns_rdataset_disassociate(&rdataset);
03747 
03748         return (result);
03749 }
03750 
03751 static void
03752 fetch_callback(isc_task_t *task, isc_event_t *ev) {
03753         dns_fetchevent_t *dev;
03754         dns_adbname_t *name;
03755         dns_adb_t *adb;
03756         dns_adbfetch_t *fetch;
03757         int bucket;
03758         isc_eventtype_t ev_status;
03759         isc_stdtime_t now;
03760         isc_result_t result;
03761         unsigned int address_type;
03762         isc_boolean_t want_check_exit = ISC_FALSE;
03763 
03764         UNUSED(task);
03765 
03766         INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
03767         dev = (dns_fetchevent_t *)ev;
03768         name = ev->ev_arg;
03769         INSIST(DNS_ADBNAME_VALID(name));
03770         adb = name->adb;
03771         INSIST(DNS_ADB_VALID(adb));
03772 
03773         bucket = name->lock_bucket;
03774         LOCK(&adb->namelocks[bucket]);
03775 
03776         INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
03777         address_type = 0;
03778         if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
03779                 address_type = DNS_ADBFIND_INET;
03780                 fetch = name->fetch_a;
03781                 name->fetch_a = NULL;
03782         } else if (NAME_FETCH_AAAA(name)
03783                    && (name->fetch_aaaa->fetch == dev->fetch)) {
03784                 address_type = DNS_ADBFIND_INET6;
03785                 fetch = name->fetch_aaaa;
03786                 name->fetch_aaaa = NULL;
03787         } else
03788                 fetch = NULL;
03789 
03790         INSIST(address_type != 0 && fetch != NULL);
03791 
03792         dns_resolver_destroyfetch(&fetch->fetch);
03793         dev->fetch = NULL;
03794 
03795         ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
03796 
03797         /*
03798          * Cleanup things we don't care about.
03799          */
03800         if (dev->node != NULL)
03801                 dns_db_detachnode(dev->db, &dev->node);
03802         if (dev->db != NULL)
03803                 dns_db_detach(&dev->db);
03804 
03805         /*
03806          * If this name is marked as dead, clean up, throwing away
03807          * potentially good data.
03808          */
03809         if (NAME_DEAD(name)) {
03810                 free_adbfetch(adb, &fetch);
03811                 isc_event_free(&ev);
03812 
03813                 want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED);
03814 
03815                 UNLOCK(&adb->namelocks[bucket]);
03816 
03817                 if (want_check_exit) {
03818                         LOCK(&adb->lock);
03819                         check_exit(adb);
03820                         UNLOCK(&adb->lock);
03821                 }
03822 
03823                 return;
03824         }
03825 
03826         isc_stdtime_get(&now);
03827 
03828         /*
03829          * If we got a negative cache response, remember it.
03830          */
03831         if (NCACHE_RESULT(dev->result)) {
03832                 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
03833                 if (address_type == DNS_ADBFIND_INET) {
03834                         DP(NCACHE_LEVEL, "adb fetch name %p: "
03835                            "caching negative entry for A (ttl %u)",
03836                            name, dev->rdataset->ttl);
03837                         name->expire_v4 = ISC_MIN(name->expire_v4,
03838                                                   dev->rdataset->ttl + now);
03839                         if (dev->result == DNS_R_NCACHENXDOMAIN)
03840                                 name->fetch_err = FIND_ERR_NXDOMAIN;
03841                         else
03842                                 name->fetch_err = FIND_ERR_NXRRSET;
03843                         inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
03844                 } else {
03845                         DP(NCACHE_LEVEL, "adb fetch name %p: "
03846                            "caching negative entry for AAAA (ttl %u)",
03847                            name, dev->rdataset->ttl);
03848                         name->expire_v6 = ISC_MIN(name->expire_v6,
03849                                                   dev->rdataset->ttl + now);
03850                         if (dev->result == DNS_R_NCACHENXDOMAIN)
03851                                 name->fetch6_err = FIND_ERR_NXDOMAIN;
03852                         else
03853                                 name->fetch6_err = FIND_ERR_NXRRSET;
03854                         inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
03855                 }
03856                 goto out;
03857         }
03858 
03859         /*
03860          * Handle CNAME/DNAME.
03861          */
03862         if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
03863                 dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
03864                 clean_target(adb, &name->target);
03865                 name->expire_target = INT_MAX;
03866                 result = set_target(adb, &name->name,
03867                                     dns_fixedname_name(&dev->foundname),
03868                                     dev->rdataset,
03869                                     &name->target);
03870                 if (result == ISC_R_SUCCESS) {
03871                         DP(NCACHE_LEVEL,
03872                            "adb fetch name %p: caching alias target",
03873                            name);
03874                         name->expire_target = dev->rdataset->ttl + now;
03875                 }
03876                 goto check_result;
03877         }
03878 
03879         /*
03880          * Did we get back junk?  If so, and there are no more fetches
03881          * sitting out there, tell all the finds about it.
03882          */
03883         if (dev->result != ISC_R_SUCCESS) {
03884                 char buf[DNS_NAME_FORMATSIZE];
03885 
03886                 dns_name_format(&name->name, buf, sizeof(buf));
03887                 DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
03888                    buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
03889                    dns_result_totext(dev->result));
03890                 /*
03891                  * Don't record a failure unless this is the initial
03892                  * fetch of a chain.
03893                  */
03894                 if (fetch->depth > 1)
03895                         goto out;
03896                 /* XXXMLG Don't pound on bad servers. */
03897                 if (address_type == DNS_ADBFIND_INET) {
03898                         name->expire_v4 = ISC_MIN(name->expire_v4, now + 10);
03899                         name->fetch_err = FIND_ERR_FAILURE;
03900                         inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
03901                 } else {
03902                         name->expire_v6 = ISC_MIN(name->expire_v6, now + 10);
03903                         name->fetch6_err = FIND_ERR_FAILURE;
03904                         inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
03905                 }
03906                 goto out;
03907         }
03908 
03909         /*
03910          * We got something potentially useful.
03911          */
03912         result = import_rdataset(name, &fetch->rdataset, now);
03913 
03914  check_result:
03915         if (result == ISC_R_SUCCESS) {
03916                 ev_status = DNS_EVENT_ADBMOREADDRESSES;
03917                 if (address_type == DNS_ADBFIND_INET)
03918                         name->fetch_err = FIND_ERR_SUCCESS;
03919                 else
03920                         name->fetch6_err = FIND_ERR_SUCCESS;
03921         }
03922 
03923  out:
03924         free_adbfetch(adb, &fetch);
03925         isc_event_free(&ev);
03926 
03927         clean_finds_at_name(name, ev_status, address_type);
03928 
03929         UNLOCK(&adb->namelocks[bucket]);
03930 }
03931 
03932 static isc_result_t
03933 fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
03934            unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
03935 {
03936         isc_result_t result;
03937         dns_adbfetch_t *fetch = NULL;
03938         dns_adb_t *adb;
03939         dns_fixedname_t fixed;
03940         dns_name_t *name;
03941         dns_rdataset_t rdataset;
03942         dns_rdataset_t *nameservers;
03943         unsigned int options;
03944 
03945         INSIST(DNS_ADBNAME_VALID(adbname));
03946         adb = adbname->adb;
03947         INSIST(DNS_ADB_VALID(adb));
03948 
03949         INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
03950                (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
03951 
03952         adbname->fetch_err = FIND_ERR_NOTFOUND;
03953 
03954         name = NULL;
03955         nameservers = NULL;
03956         dns_rdataset_init(&rdataset);
03957 
03958         options = DNS_FETCHOPT_NOVALIDATE;
03959         if (start_at_zone) {
03960                 DP(ENTER_LEVEL,
03961                    "fetch_name: starting at zone for name %p",
03962                    adbname);
03963                 dns_fixedname_init(&fixed);
03964                 name = dns_fixedname_name(&fixed);
03965                 result = dns_view_findzonecut2(adb->view, &adbname->name, name,
03966                                                0, 0, ISC_TRUE, ISC_FALSE,
03967                                                &rdataset, NULL);
03968                 if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
03969                         goto cleanup;
03970                 nameservers = &rdataset;
03971                 options |= DNS_FETCHOPT_UNSHARED;
03972         }
03973 
03974         fetch = new_adbfetch(adb);
03975         if (fetch == NULL) {
03976                 result = ISC_R_NOMEMORY;
03977                 goto cleanup;
03978         }
03979         fetch->depth = depth;
03980 
03981         result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
03982                                            type, name, nameservers, NULL,
03983                                            NULL, 0, options, depth, qc,
03984                                            adb->task, fetch_callback, adbname,
03985                                            &fetch->rdataset, NULL,
03986                                            &fetch->fetch);
03987         if (result != ISC_R_SUCCESS)
03988                 goto cleanup;
03989 
03990         if (type == dns_rdatatype_a) {
03991                 adbname->fetch_a = fetch;
03992                 inc_stats(adb, dns_resstatscounter_gluefetchv4);
03993         } else {
03994                 adbname->fetch_aaaa = fetch;
03995                 inc_stats(adb, dns_resstatscounter_gluefetchv6);
03996         }
03997         fetch = NULL;  /* Keep us from cleaning this up below. */
03998 
03999  cleanup:
04000         if (fetch != NULL)
04001                 free_adbfetch(adb, &fetch);
04002         if (dns_rdataset_isassociated(&rdataset))
04003                 dns_rdataset_disassociate(&rdataset);
04004 
04005         return (result);
04006 }
04007 
04008 /*
04009  * XXXMLG Needs to take a find argument and an address info, no zone or adb,
04010  * since these can be extracted from the find itself.
04011  */
04012 isc_result_t
04013 dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
04014                  dns_rdatatype_t qtype, isc_stdtime_t expire_time)
04015 {
04016         dns_adblameinfo_t *li;
04017         int bucket;
04018         isc_result_t result = ISC_R_SUCCESS;
04019 
04020         REQUIRE(DNS_ADB_VALID(adb));
04021         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04022         REQUIRE(qname != NULL);
04023 
04024         bucket = addr->entry->lock_bucket;
04025         LOCK(&adb->entrylocks[bucket]);
04026         li = ISC_LIST_HEAD(addr->entry->lameinfo);
04027         while (li != NULL &&
04028                (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
04029                 li = ISC_LIST_NEXT(li, plink);
04030         if (li != NULL) {
04031                 if (expire_time > li->lame_timer)
04032                         li->lame_timer = expire_time;
04033                 goto unlock;
04034         }
04035         li = new_adblameinfo(adb, qname, qtype);
04036         if (li == NULL) {
04037                 result = ISC_R_NOMEMORY;
04038                 goto unlock;
04039         }
04040 
04041         li->lame_timer = expire_time;
04042 
04043         ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
04044  unlock:
04045         UNLOCK(&adb->entrylocks[bucket]);
04046 
04047         return (result);
04048 }
04049 
04050 void
04051 dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
04052                    unsigned int rtt, unsigned int factor)
04053 {
04054         int bucket;
04055         isc_stdtime_t now = 0;
04056 
04057         REQUIRE(DNS_ADB_VALID(adb));
04058         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04059         REQUIRE(factor <= 10);
04060 
04061         bucket = addr->entry->lock_bucket;
04062         LOCK(&adb->entrylocks[bucket]);
04063 
04064         if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE)
04065                 isc_stdtime_get(&now);
04066         adjustsrtt(addr, rtt, factor, now);
04067 
04068         UNLOCK(&adb->entrylocks[bucket]);
04069 }
04070 
04071 void
04072 dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) {
04073         int bucket;
04074 
04075         REQUIRE(DNS_ADB_VALID(adb));
04076         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04077 
04078         bucket = addr->entry->lock_bucket;
04079         LOCK(&adb->entrylocks[bucket]);
04080 
04081         adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now);
04082 
04083         UNLOCK(&adb->entrylocks[bucket]);
04084 }
04085 
04086 static void
04087 adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
04088            isc_stdtime_t now)
04089 {
04090         isc_uint64_t new_srtt;
04091 
04092         if (factor == DNS_ADB_RTTADJAGE) {
04093                 if (addr->entry->lastage != now) {
04094                         new_srtt = addr->entry->srtt;
04095                         new_srtt <<= 9;
04096                         new_srtt -= addr->entry->srtt;
04097                         new_srtt >>= 9;
04098                         addr->entry->lastage = now;
04099                 } else
04100                         new_srtt = addr->entry->srtt;
04101         } else
04102                 new_srtt = ((isc_uint64_t)addr->entry->srtt / 10 * factor)
04103                         + ((isc_uint64_t)rtt / 10 * (10 - factor));
04104 
04105         addr->entry->srtt = (unsigned int) new_srtt;
04106         addr->srtt = (unsigned int) new_srtt;
04107 
04108         if (addr->entry->expires == 0)
04109                 addr->entry->expires = now + ADB_ENTRY_WINDOW;
04110 }
04111 
04112 void
04113 dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
04114                     unsigned int bits, unsigned int mask)
04115 {
04116         int bucket;
04117         isc_stdtime_t now;
04118 
04119         REQUIRE(DNS_ADB_VALID(adb));
04120         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04121 
04122         REQUIRE((bits & ENTRY_IS_DEAD) == 0);
04123         REQUIRE((mask & ENTRY_IS_DEAD) == 0);
04124 
04125         bucket = addr->entry->lock_bucket;
04126         LOCK(&adb->entrylocks[bucket]);
04127 
04128         addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
04129         if (addr->entry->expires == 0) {
04130                 isc_stdtime_get(&now);
04131                 addr->entry->expires = now + ADB_ENTRY_WINDOW;
04132         }
04133 
04134         /*
04135          * Note that we do not update the other bits in addr->flags with
04136          * the most recent values from addr->entry->flags.
04137          */
04138         addr->flags = (addr->flags & ~mask) | (bits & mask);
04139 
04140         UNLOCK(&adb->entrylocks[bucket]);
04141 }
04142 
04143 #define EDNSTOS 3U
04144 isc_boolean_t
04145 dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
04146         int bucket;
04147         isc_boolean_t noedns = ISC_FALSE;
04148 
04149         REQUIRE(DNS_ADB_VALID(adb));
04150         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04151 
04152         bucket = addr->entry->lock_bucket;
04153         LOCK(&adb->entrylocks[bucket]);
04154         if (addr->entry->edns == 0U &&
04155             (addr->entry->plain > EDNSTOS || addr->entry->to4096 > EDNSTOS)) {
04156                 if (((addr->entry->plain + addr->entry->to4096) & 0x3f) != 0) {
04157                         noedns = ISC_TRUE;
04158                 } else {
04159                         /*
04160                          * Increment plain so we don't get stuck.
04161                          */
04162                         addr->entry->plain++;
04163                         if (addr->entry->plain == 0xff) {
04164                                 addr->entry->edns >>= 1;
04165                                 addr->entry->to4096 >>= 1;
04166                                 addr->entry->to1432 >>= 1;
04167                                 addr->entry->to1232 >>= 1;
04168                                 addr->entry->to512 >>= 1;
04169                                 addr->entry->plain >>= 1;
04170                                 addr->entry->plainto >>= 1;
04171                         }
04172                  }
04173         }
04174         UNLOCK(&adb->entrylocks[bucket]);
04175         return (noedns);
04176 }
04177 
04178 void
04179 dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
04180         int bucket;
04181 
04182         REQUIRE(DNS_ADB_VALID(adb));
04183         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04184 
04185         bucket = addr->entry->lock_bucket;
04186         LOCK(&adb->entrylocks[bucket]);
04187 
04188         addr->entry->plain++;
04189         if (addr->entry->plain == 0xff) {
04190                 addr->entry->edns >>= 1;
04191                 addr->entry->to4096 >>= 1;
04192                 addr->entry->to1432 >>= 1;
04193                 addr->entry->to1232 >>= 1;
04194                 addr->entry->to512 >>= 1;
04195                 addr->entry->plain >>= 1;
04196                 addr->entry->plainto >>= 1;
04197         }
04198         UNLOCK(&adb->entrylocks[bucket]);
04199 }
04200 
04201 void
04202 dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
04203         int bucket;
04204 
04205         REQUIRE(DNS_ADB_VALID(adb));
04206         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04207 
04208         bucket = addr->entry->lock_bucket;
04209         LOCK(&adb->entrylocks[bucket]);
04210         /*
04211          * If we have not had a successful query then clear all
04212          * edns timeout information.
04213          */
04214         if (addr->entry->edns == 0 && addr->entry->plain == 0) {
04215                 addr->entry->to512 = 0;
04216                 addr->entry->to1232 = 0;
04217                 addr->entry->to1432 = 0;
04218                 addr->entry->to4096 = 0;
04219         } else {
04220                 addr->entry->to512 >>= 1;
04221                 addr->entry->to1232 >>= 1;
04222                 addr->entry->to1432 >>= 1;
04223                 addr->entry->to4096 >>= 1;
04224         }
04225         addr->entry->plainto++;
04226         if (addr->entry->plainto == 0xff) {
04227                 addr->entry->edns >>= 1;
04228                 addr->entry->plain >>= 1;
04229                 addr->entry->plainto >>= 1;
04230         }
04231         UNLOCK(&adb->entrylocks[bucket]);
04232 }
04233 
04234 void
04235 dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
04236         int bucket;
04237 
04238         REQUIRE(DNS_ADB_VALID(adb));
04239         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04240 
04241         bucket = addr->entry->lock_bucket;
04242         LOCK(&adb->entrylocks[bucket]);
04243 
04244         if (size <= 512U) {
04245                 if (addr->entry->to512 <= EDNSTOS) {
04246                         addr->entry->to512++;
04247                         addr->entry->to1232++;
04248                         addr->entry->to1432++;
04249                         addr->entry->to4096++;
04250                 }
04251         } else if (size <= 1232U) {
04252                 if (addr->entry->to1232 <= EDNSTOS) {
04253                         addr->entry->to1232++;
04254                         addr->entry->to1432++;
04255                         addr->entry->to4096++;
04256                 }
04257         } else if (size <= 1432U) {
04258                 if (addr->entry->to1432 <= EDNSTOS) {
04259                         addr->entry->to1432++;
04260                         addr->entry->to4096++;
04261                 }
04262         } else {
04263                 if (addr->entry->to4096 <= EDNSTOS)
04264                         addr->entry->to4096++;
04265         }
04266 
04267         if (addr->entry->to4096 == 0xff) {
04268                 addr->entry->edns >>= 1;
04269                 addr->entry->to4096 >>= 1;
04270                 addr->entry->to1432 >>= 1;
04271                 addr->entry->to1232 >>= 1;
04272                 addr->entry->to512 >>= 1;
04273                 addr->entry->plain >>= 1;
04274                 addr->entry->plainto >>= 1;
04275         }
04276         UNLOCK(&adb->entrylocks[bucket]);
04277 }
04278 
04279 void
04280 dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
04281         int bucket;
04282 
04283         REQUIRE(DNS_ADB_VALID(adb));
04284         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04285 
04286         bucket = addr->entry->lock_bucket;
04287         LOCK(&adb->entrylocks[bucket]);
04288         if (size < 512U)
04289                 size = 512U;
04290         if (size > addr->entry->udpsize)
04291                 addr->entry->udpsize = size;
04292         addr->entry->edns++;
04293         if (addr->entry->edns == 0xff) {
04294                 addr->entry->edns >>= 1;
04295                 addr->entry->to4096 >>= 1;
04296                 addr->entry->to1432 >>= 1;
04297                 addr->entry->to1232 >>= 1;
04298                 addr->entry->to512 >>= 1;
04299                 addr->entry->plain >>= 1;
04300                 addr->entry->plainto >>= 1;
04301         }
04302         UNLOCK(&adb->entrylocks[bucket]);
04303 }
04304 
04305 unsigned int
04306 dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
04307         int bucket;
04308         unsigned int size;
04309 
04310         REQUIRE(DNS_ADB_VALID(adb));
04311         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04312 
04313         bucket = addr->entry->lock_bucket;
04314         LOCK(&adb->entrylocks[bucket]);
04315         size = addr->entry->udpsize;
04316         UNLOCK(&adb->entrylocks[bucket]);
04317 
04318         return (size);
04319 }
04320 
04321 unsigned int
04322 dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
04323         return dns_adb_probesize2(adb, addr, 0);
04324 }
04325 
04326 unsigned int
04327 dns_adb_probesize2(dns_adb_t *adb, dns_adbaddrinfo_t *addr, int lookups) {
04328         int bucket;
04329         unsigned int size;
04330 
04331         REQUIRE(DNS_ADB_VALID(adb));
04332         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04333 
04334         bucket = addr->entry->lock_bucket;
04335         LOCK(&adb->entrylocks[bucket]);
04336         if (addr->entry->to1232 > EDNSTOS || lookups >= 2)
04337                 size = 512;
04338         else if (addr->entry->to1432 > EDNSTOS || lookups >= 1)
04339                 size = 1232;
04340         else if (addr->entry->to4096 > EDNSTOS)
04341                 size = 1432;
04342         else
04343                 size = 4096;
04344         /*
04345          * Don't shrink probe size below what we have seen due to multiple
04346          * lookups.
04347          */
04348         if (lookups > 0 &&
04349             size < addr->entry->udpsize && addr->entry->udpsize < 4096)
04350                 size = addr->entry->udpsize;
04351         UNLOCK(&adb->entrylocks[bucket]);
04352 
04353         return (size);
04354 }
04355 
04356 void
04357 dns_adb_setsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
04358                const unsigned char *sit, size_t len)
04359 {
04360         int bucket;
04361 
04362         REQUIRE(DNS_ADB_VALID(adb));
04363         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04364 
04365         bucket = addr->entry->lock_bucket;
04366         LOCK(&adb->entrylocks[bucket]);
04367 
04368         if (addr->entry->sit != NULL &&
04369             (sit == NULL || len != addr->entry->sitlen)) {
04370                 isc_mem_put(adb->mctx, addr->entry->sit, addr->entry->sitlen);
04371                 addr->entry->sit = NULL;
04372                 addr->entry->sitlen = 0;
04373         }
04374 
04375         if (addr->entry->sit == NULL && sit != NULL && len != 0U) {
04376                 addr->entry->sit = isc_mem_get(adb->mctx, len);
04377                 if (addr->entry->sit != NULL)
04378                         addr->entry->sitlen = (isc_uint16_t)len;
04379         }
04380 
04381         if (addr->entry->sit != NULL)
04382                 memmove(addr->entry->sit, sit, len);
04383         UNLOCK(&adb->entrylocks[bucket]);
04384 }
04385 
04386 size_t
04387 dns_adb_getsit(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
04388                unsigned char *sit, size_t len)
04389 {
04390         int bucket;
04391 
04392         REQUIRE(DNS_ADB_VALID(adb));
04393         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04394 
04395         bucket = addr->entry->lock_bucket;
04396         LOCK(&adb->entrylocks[bucket]);
04397         if (sit != NULL && addr->entry->sit != NULL &&
04398             len >= addr->entry->sitlen)
04399         {
04400                 memmove(sit, addr->entry->sit, addr->entry->sitlen);
04401                 len = addr->entry->sitlen;
04402         } else
04403                 len = 0;
04404         UNLOCK(&adb->entrylocks[bucket]);
04405 
04406         return (len);
04407 }
04408 
04409 isc_result_t
04410 dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
04411                      dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
04412 {
04413         int bucket;
04414         dns_adbentry_t *entry;
04415         dns_adbaddrinfo_t *addr;
04416         isc_result_t result;
04417         in_port_t port;
04418 
04419         REQUIRE(DNS_ADB_VALID(adb));
04420         REQUIRE(addrp != NULL && *addrp == NULL);
04421 
04422         UNUSED(now);
04423 
04424         result = ISC_R_SUCCESS;
04425         bucket = DNS_ADB_INVALIDBUCKET;
04426         entry = find_entry_and_lock(adb, sa, &bucket, now);
04427         INSIST(bucket != DNS_ADB_INVALIDBUCKET);
04428         if (adb->entry_sd[bucket]) {
04429                 result = ISC_R_SHUTTINGDOWN;
04430                 goto unlock;
04431         }
04432         if (entry == NULL) {
04433                 /*
04434                  * We don't know anything about this address.
04435                  */
04436                 entry = new_adbentry(adb);
04437                 if (entry == NULL) {
04438                         result = ISC_R_NOMEMORY;
04439                         goto unlock;
04440                 }
04441                 entry->sockaddr = *sa;
04442                 link_entry(adb, bucket, entry);
04443                 DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
04444         } else
04445                 DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
04446 
04447         port = isc_sockaddr_getport(sa);
04448         addr = new_adbaddrinfo(adb, entry, port);
04449         if (addr == NULL) {
04450                 result = ISC_R_NOMEMORY;
04451         } else {
04452                 inc_entry_refcnt(adb, entry, ISC_FALSE);
04453                 *addrp = addr;
04454         }
04455 
04456  unlock:
04457         UNLOCK(&adb->entrylocks[bucket]);
04458 
04459         return (result);
04460 }
04461 
04462 void
04463 dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
04464         dns_adbaddrinfo_t *addr;
04465         dns_adbentry_t *entry;
04466         int bucket;
04467         isc_stdtime_t now;
04468         isc_boolean_t want_check_exit = ISC_FALSE;
04469         isc_boolean_t overmem;
04470 
04471         REQUIRE(DNS_ADB_VALID(adb));
04472         REQUIRE(addrp != NULL);
04473         addr = *addrp;
04474         REQUIRE(DNS_ADBADDRINFO_VALID(addr));
04475         entry = addr->entry;
04476         REQUIRE(DNS_ADBENTRY_VALID(entry));
04477 
04478         *addrp = NULL;
04479         overmem = isc_mem_isovermem(adb->mctx);
04480 
04481         bucket = addr->entry->lock_bucket;
04482         LOCK(&adb->entrylocks[bucket]);
04483 
04484         if (entry->expires == 0) {
04485                 isc_stdtime_get(&now);
04486                 entry->expires = now + ADB_ENTRY_WINDOW;
04487         }
04488 
04489         want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
04490 
04491         UNLOCK(&adb->entrylocks[bucket]);
04492 
04493         addr->entry = NULL;
04494         free_adbaddrinfo(adb, &addr);
04495 
04496         if (want_check_exit) {
04497                 LOCK(&adb->lock);
04498                 check_exit(adb);
04499                 UNLOCK(&adb->lock);
04500         }
04501 }
04502 
04503 void
04504 dns_adb_flush(dns_adb_t *adb) {
04505         unsigned int i;
04506 
04507         INSIST(DNS_ADB_VALID(adb));
04508 
04509         LOCK(&adb->lock);
04510 
04511         /*
04512          * Call our cleanup routines.
04513          */
04514         for (i = 0; i < adb->nnames; i++)
04515                 RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
04516         for (i = 0; i < adb->nentries; i++)
04517                 RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
04518 
04519 #ifdef DUMP_ADB_AFTER_CLEANING
04520         dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
04521 #endif
04522 
04523         UNLOCK(&adb->lock);
04524 }
04525 
04526 void
04527 dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
04528         dns_adbname_t *adbname;
04529         dns_adbname_t *nextname;
04530         int bucket;
04531 
04532         REQUIRE(DNS_ADB_VALID(adb));
04533         REQUIRE(name != NULL);
04534 
04535         LOCK(&adb->lock);
04536         bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
04537         LOCK(&adb->namelocks[bucket]);
04538         adbname = ISC_LIST_HEAD(adb->names[bucket]);
04539         while (adbname != NULL) {
04540                 nextname = ISC_LIST_NEXT(adbname, plink);
04541                 if (!NAME_DEAD(adbname) &&
04542                     dns_name_equal(name, &adbname->name)) {
04543                         RUNTIME_CHECK(kill_name(&adbname,
04544                                                 DNS_EVENT_ADBCANCELED) ==
04545                                       ISC_FALSE);
04546                 }
04547                 adbname = nextname;
04548         }
04549         UNLOCK(&adb->namelocks[bucket]);
04550         UNLOCK(&adb->lock);
04551 }
04552 
04553 void
04554 dns_adb_flushnames(dns_adb_t *adb, dns_name_t *name) {
04555         dns_adbname_t *adbname, *nextname;
04556         unsigned int i;
04557 
04558         REQUIRE(DNS_ADB_VALID(adb));
04559         REQUIRE(name != NULL);
04560 
04561         LOCK(&adb->lock);
04562         for (i = 0; i < adb->nnames; i++) {
04563                 LOCK(&adb->namelocks[i]);
04564                 adbname = ISC_LIST_HEAD(adb->names[i]);
04565                 while (adbname != NULL) {
04566                         isc_boolean_t ret;
04567                         nextname = ISC_LIST_NEXT(adbname, plink);
04568                         if (!NAME_DEAD(adbname) &&
04569                             dns_name_issubdomain(&adbname->name, name))
04570                         {
04571                                 ret = kill_name(&adbname,
04572                                                 DNS_EVENT_ADBCANCELED);
04573                                 RUNTIME_CHECK(ret == ISC_FALSE);
04574                         }
04575                         adbname = nextname;
04576                 }
04577                 UNLOCK(&adb->namelocks[i]);
04578         }
04579         UNLOCK(&adb->lock);
04580 }
04581 
04582 static void
04583 water(void *arg, int mark) {
04584         /*
04585          * We're going to change the way to handle overmem condition: use
04586          * isc_mem_isovermem() instead of storing the state via this callback,
04587          * since the latter way tends to cause race conditions.
04588          * To minimize the change, and in case we re-enable the callback
04589          * approach, however, keep this function at the moment.
04590          */
04591 
04592         dns_adb_t *adb = arg;
04593         isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
04594 
04595         REQUIRE(DNS_ADB_VALID(adb));
04596 
04597         DP(ISC_LOG_DEBUG(1),
04598            "adb reached %s water mark", overmem ? "high" : "low");
04599 }
04600 
04601 void
04602 dns_adb_setadbsize(dns_adb_t *adb, size_t size) {
04603         size_t hiwater, lowater;
04604 
04605         INSIST(DNS_ADB_VALID(adb));
04606 
04607         if (size != 0U && size < DNS_ADB_MINADBSIZE)
04608                 size = DNS_ADB_MINADBSIZE;
04609 
04610         hiwater = size - (size >> 3);   /* Approximately 7/8ths. */
04611         lowater = size - (size >> 2);   /* Approximately 3/4ths. */
04612 
04613         if (size == 0U || hiwater == 0U || lowater == 0U)
04614                 isc_mem_setwater(adb->mctx, water, adb, 0, 0);
04615         else
04616                 isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
04617 }

Generated on Tue Apr 28 17:40:55 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha