resolver.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 #include <config.h>
00021 #include <ctype.h>
00022 
00023 #include <isc/counter.h>
00024 #include <isc/log.h>
00025 #include <isc/platform.h>
00026 #include <isc/print.h>
00027 #include <isc/string.h>
00028 #include <isc/random.h>
00029 #include <isc/socket.h>
00030 #include <isc/stats.h>
00031 #include <isc/task.h>
00032 #include <isc/timer.h>
00033 #include <isc/util.h>
00034 
00035 #ifdef AES_SIT
00036 #include <isc/aes.h>
00037 #else
00038 #include <isc/hmacsha.h>
00039 #endif
00040 
00041 #include <dns/acl.h>
00042 #include <dns/adb.h>
00043 #include <dns/badcache.h>
00044 #include <dns/cache.h>
00045 #include <dns/db.h>
00046 #include <dns/dispatch.h>
00047 #include <dns/ds.h>
00048 #include <dns/edns.h>
00049 #include <dns/events.h>
00050 #include <dns/forward.h>
00051 #include <dns/keytable.h>
00052 #include <dns/log.h>
00053 #include <dns/message.h>
00054 #include <dns/ncache.h>
00055 #include <dns/nsec.h>
00056 #include <dns/nsec3.h>
00057 #include <dns/opcode.h>
00058 #include <dns/peer.h>
00059 #include <dns/rbt.h>
00060 #include <dns/rcode.h>
00061 #include <dns/rdata.h>
00062 #include <dns/rdataclass.h>
00063 #include <dns/rdatalist.h>
00064 #include <dns/rdataset.h>
00065 #include <dns/rdatastruct.h>
00066 #include <dns/rdatatype.h>
00067 #include <dns/resolver.h>
00068 #include <dns/result.h>
00069 #include <dns/rootns.h>
00070 #include <dns/stats.h>
00071 #include <dns/tsig.h>
00072 #include <dns/validator.h>
00073 
00074 #ifdef WANT_QUERYTRACE
00075 #define RTRACE(m)       isc_log_write(dns_lctx, \
00076                                       DNS_LOGCATEGORY_RESOLVER, \
00077                                       DNS_LOGMODULE_RESOLVER, \
00078                                       ISC_LOG_DEBUG(3), \
00079                                       "res %p: %s", res, (m))
00080 #define RRTRACE(r, m)   isc_log_write(dns_lctx, \
00081                                       DNS_LOGCATEGORY_RESOLVER, \
00082                                       DNS_LOGMODULE_RESOLVER, \
00083                                       ISC_LOG_DEBUG(3), \
00084                                       "res %p: %s", (r), (m))
00085 #define FCTXTRACE(m) \
00086                         isc_log_write(dns_lctx, \
00087                                       DNS_LOGCATEGORY_RESOLVER, \
00088                                       DNS_LOGMODULE_RESOLVER, \
00089                                       ISC_LOG_DEBUG(3), \
00090                                       "fctx %p(%s): %s", \
00091                                       fctx, fctx->info, (m))
00092 #define FCTXTRACE2(m1, m2) \
00093                         isc_log_write(dns_lctx, \
00094                                       DNS_LOGCATEGORY_RESOLVER, \
00095                                       DNS_LOGMODULE_RESOLVER, \
00096                                       ISC_LOG_DEBUG(3), \
00097                                       "fctx %p(%s): %s %s", \
00098                                       fctx, fctx->info, (m1), (m2))
00099 #define FCTXTRACE3(m, res) \
00100                         isc_log_write(dns_lctx, \
00101                                       DNS_LOGCATEGORY_RESOLVER, \
00102                                       DNS_LOGMODULE_RESOLVER, \
00103                                       ISC_LOG_DEBUG(3), \
00104                                       "fctx %p(%s): [result: %s] %s", \
00105                                       fctx, fctx->info, \
00106                                       isc_result_totext(res), (m))
00107 #define FCTXTRACE4(m1, m2, res) \
00108                         isc_log_write(dns_lctx, \
00109                                       DNS_LOGCATEGORY_RESOLVER, \
00110                                       DNS_LOGMODULE_RESOLVER, \
00111                                       ISC_LOG_DEBUG(3), \
00112                                       "fctx %p(%s): [result: %s] %s %s", \
00113                                       fctx, fctx->info, \
00114                                       isc_result_totext(res), (m1), (m2))
00115 #define FTRACE(m)       isc_log_write(dns_lctx, \
00116                                       DNS_LOGCATEGORY_RESOLVER, \
00117                                       DNS_LOGMODULE_RESOLVER, \
00118                                       ISC_LOG_DEBUG(3), \
00119                                       "fetch %p (fctx %p(%s)): %s", \
00120                                       fetch, fetch->private, \
00121                                       fetch->private->info, (m))
00122 #define QTRACE(m)       isc_log_write(dns_lctx, \
00123                                       DNS_LOGCATEGORY_RESOLVER, \
00124                                       DNS_LOGMODULE_RESOLVER, \
00125                                       ISC_LOG_DEBUG(3), \
00126                                       "resquery %p (fctx %p(%s)): %s", \
00127                                       query, query->fctx, \
00128                                       query->fctx->info, (m))
00129 #else
00130 #define RTRACE(m) do { UNUSED(m); } while (0)
00131 #define RRTRACE(r, m) do { UNUSED(r); UNUSED(m); } while (0)
00132 #define FCTXTRACE(m) do { UNUSED(m); } while (0)
00133 #define FCTXTRACE2(m1, m2) do { UNUSED(m1); UNUSED(m2); } while (0)
00134 #define FCTXTRACE3(m1, res) do { UNUSED(m1); UNUSED(res); } while (0)
00135 #define FCTXTRACE4(m1, m2, res) \
00136         do { UNUSED(m1); UNUSED(m2); UNUSED(res); } while (0)
00137 #define FTRACE(m) do { UNUSED(m); } while (0)
00138 #define QTRACE(m) do { UNUSED(m); } while (0)
00139 #endif /* WANT_QUERYTRACE */
00140 
00141 #define US_PER_SEC 1000000U
00142 /*
00143  * The maximum time we will wait for a single query.
00144  */
00145 #define MAX_SINGLE_QUERY_TIMEOUT 9U
00146 #define MAX_SINGLE_QUERY_TIMEOUT_US (MAX_SINGLE_QUERY_TIMEOUT*US_PER_SEC)
00147 
00148 /*
00149  * We need to allow a individual query time to complete / timeout.
00150  */
00151 #define MINIMUM_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1U)
00152 
00153 /* The default time in seconds for the whole query to live. */
00154 #ifndef DEFAULT_QUERY_TIMEOUT
00155 #define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
00156 #endif
00157 
00158 #ifndef MAXIMUM_QUERY_TIMEOUT
00159 #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
00160 #endif
00161 
00162 /* The default maximum number of recursions to follow before giving up. */
00163 #ifndef DEFAULT_RECURSION_DEPTH
00164 #define DEFAULT_RECURSION_DEPTH 7
00165 #endif
00166 
00167 /* The default maximum number of iterative queries to allow before giving up. */
00168 #ifndef DEFAULT_MAX_QUERIES
00169 #define DEFAULT_MAX_QUERIES 75
00170 #endif
00171 
00172 /*%
00173  * Maximum EDNS0 input packet size.
00174  */
00175 #define RECV_BUFFER_SIZE                4096            /* XXXRTH  Constant. */
00176 
00177 /*%
00178  * This defines the maximum number of timeouts we will permit before we
00179  * disable EDNS0 on the query.
00180  */
00181 #define MAX_EDNS0_TIMEOUTS      3
00182 
00183 #define DNS_RESOLVER_BADCACHESIZE 1021
00184 #define DNS_RESOLVER_BADCACHETTL(fctx) \
00185         (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
00186 
00187 typedef struct fetchctx fetchctx_t;
00188 
00189 typedef struct query {
00190         /* Locked by task event serialization. */
00191         unsigned int                    magic;
00192         fetchctx_t *                    fctx;
00193         isc_mem_t *                     mctx;
00194         dns_dispatchmgr_t *             dispatchmgr;
00195         dns_dispatch_t *                dispatch;
00196         isc_boolean_t                   exclusivesocket;
00197         dns_adbaddrinfo_t *             addrinfo;
00198         isc_socket_t *                  tcpsocket;
00199         isc_time_t                      start;
00200         dns_messageid_t                 id;
00201         dns_dispentry_t *               dispentry;
00202         ISC_LINK(struct query)          link;
00203         isc_buffer_t                    buffer;
00204         isc_buffer_t                    *tsig;
00205         dns_tsigkey_t                   *tsigkey;
00206         isc_socketevent_t               sendevent;
00207         isc_dscp_t                      dscp;
00208         int                             ednsversion;
00209         unsigned int                    options;
00210         unsigned int                    attributes;
00211         unsigned int                    sends;
00212         unsigned int                    connects;
00213         unsigned int                    udpsize;
00214         unsigned char                   data[512];
00215 } resquery_t;
00216 
00217 struct tried {
00218         isc_sockaddr_t                  addr;
00219         unsigned int                    count;
00220         ISC_LINK(struct tried)          link;
00221 };
00222 
00223 #define QUERY_MAGIC                     ISC_MAGIC('Q', '!', '!', '!')
00224 #define VALID_QUERY(query)              ISC_MAGIC_VALID(query, QUERY_MAGIC)
00225 
00226 #define RESQUERY_ATTR_CANCELED          0x02
00227 
00228 #define RESQUERY_CONNECTING(q)          ((q)->connects > 0)
00229 #define RESQUERY_CANCELED(q)            (((q)->attributes & \
00230                                           RESQUERY_ATTR_CANCELED) != 0)
00231 #define RESQUERY_SENDING(q)             ((q)->sends > 0)
00232 
00233 typedef enum {
00234         fetchstate_init = 0,            /*%< Start event has not run yet. */
00235         fetchstate_active,
00236         fetchstate_done                 /*%< FETCHDONE events posted. */
00237 } fetchstate;
00238 
00239 typedef enum {
00240         badns_unreachable = 0,
00241         badns_response,
00242         badns_validation
00243 } badnstype_t;
00244 
00245 struct fetchctx {
00246         /*% Not locked. */
00247         unsigned int                    magic;
00248         dns_resolver_t *                res;
00249         dns_name_t                      name;
00250         dns_rdatatype_t                 type;
00251         unsigned int                    options;
00252         unsigned int                    bucketnum;
00253         char *                          info;
00254         isc_mem_t *                     mctx;
00255 
00256         /*% Locked by appropriate bucket lock. */
00257         fetchstate                      state;
00258         isc_boolean_t                   want_shutdown;
00259         isc_boolean_t                   cloned;
00260         isc_boolean_t                   spilled;
00261         unsigned int                    references;
00262         isc_event_t                     control_event;
00263         ISC_LINK(struct fetchctx)       link;
00264         ISC_LIST(dns_fetchevent_t)      events;
00265         /*% Locked by task event serialization. */
00266         dns_name_t                      domain;
00267         dns_rdataset_t                  nameservers;
00268         unsigned int                    attributes;
00269         isc_timer_t *                   timer;
00270         isc_time_t                      expires;
00271         isc_interval_t                  interval;
00272         dns_message_t *                 qmessage;
00273         dns_message_t *                 rmessage;
00274         ISC_LIST(resquery_t)            queries;
00275         dns_adbfindlist_t               finds;
00276         dns_adbfind_t *                 find;
00277         dns_adbfindlist_t               altfinds;
00278         dns_adbfind_t *                 altfind;
00279         dns_adbaddrinfolist_t           forwaddrs;
00280         dns_adbaddrinfolist_t           altaddrs;
00281         dns_forwarderlist_t             forwarders;
00282         dns_fwdpolicy_t                 fwdpolicy;
00283         isc_sockaddrlist_t              bad;
00284         ISC_LIST(struct tried)          edns;
00285         ISC_LIST(struct tried)          edns512;
00286         isc_sockaddrlist_t              bad_edns;
00287         dns_validator_t *               validator;
00288         ISC_LIST(dns_validator_t)       validators;
00289         dns_db_t *                      cache;
00290         dns_adb_t *                     adb;
00291         isc_boolean_t                   ns_ttl_ok;
00292         isc_uint32_t                    ns_ttl;
00293         isc_counter_t *                 qc;
00294 
00295         /*%
00296          * The number of events we're waiting for.
00297          */
00298         unsigned int                    pending;
00299 
00300         /*%
00301          * The number of times we've "restarted" the current
00302          * nameserver set.  This acts as a failsafe to prevent
00303          * us from pounding constantly on a particular set of
00304          * servers that, for whatever reason, are not giving
00305          * us useful responses, but are responding in such a
00306          * way that they are not marked "bad".
00307          */
00308         unsigned int                    restarts;
00309 
00310         /*%
00311          * The number of timeouts that have occurred since we
00312          * last successfully received a response packet.  This
00313          * is used for EDNS0 black hole detection.
00314          */
00315         unsigned int                    timeouts;
00316 
00317         /*%
00318          * Look aside state for DS lookups.
00319          */
00320         dns_name_t                      nsname;
00321         dns_fetch_t *                   nsfetch;
00322         dns_rdataset_t                  nsrrset;
00323 
00324         /*%
00325          * Number of queries that reference this context.
00326          */
00327         unsigned int                    nqueries;
00328 
00329         /*%
00330          * The reason to print when logging a successful
00331          * response to a query.
00332          */
00333         const char *                    reason;
00334 
00335         /*%
00336          * Random numbers to use for mixing up server addresses.
00337          */
00338         isc_uint32_t                    rand_buf;
00339         isc_uint32_t                    rand_bits;
00340 
00341         /*%
00342          * Fetch-local statistics for detailed logging.
00343          */
00344         isc_result_t                    result; /*%< fetch result  */
00345         isc_result_t                    vresult; /*%< validation result  */
00346         int                             exitline;
00347         isc_time_t                      start;
00348         isc_uint64_t                    duration;
00349         isc_boolean_t                   logged;
00350         unsigned int                    querysent;
00351         unsigned int                    referrals;
00352         unsigned int                    lamecount;
00353         unsigned int                    neterr;
00354         unsigned int                    badresp;
00355         unsigned int                    adberr;
00356         unsigned int                    findfail;
00357         unsigned int                    valfail;
00358         isc_boolean_t                   timeout;
00359         dns_adbaddrinfo_t               *addrinfo;
00360         isc_sockaddr_t                  *client;
00361         unsigned int                    depth;
00362 };
00363 
00364 #define FCTX_MAGIC                      ISC_MAGIC('F', '!', '!', '!')
00365 #define VALID_FCTX(fctx)                ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
00366 
00367 #define FCTX_ATTR_HAVEANSWER            0x0001
00368 #define FCTX_ATTR_GLUING                0x0002
00369 #define FCTX_ATTR_ADDRWAIT              0x0004
00370 #define FCTX_ATTR_SHUTTINGDOWN          0x0008
00371 #define FCTX_ATTR_WANTCACHE             0x0010
00372 #define FCTX_ATTR_WANTNCACHE            0x0020
00373 #define FCTX_ATTR_NEEDEDNS0             0x0040
00374 #define FCTX_ATTR_TRIEDFIND             0x0080
00375 #define FCTX_ATTR_TRIEDALT              0x0100
00376 
00377 #define HAVE_ANSWER(f)          (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
00378                                  0)
00379 #define GLUING(f)               (((f)->attributes & FCTX_ATTR_GLUING) != \
00380                                  0)
00381 #define ADDRWAIT(f)             (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
00382                                  0)
00383 #define SHUTTINGDOWN(f)         (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
00384                                  != 0)
00385 #define WANTCACHE(f)            (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
00386 #define WANTNCACHE(f)           (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
00387 #define NEEDEDNS0(f)            (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
00388 #define TRIEDFIND(f)            (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
00389 #define TRIEDALT(f)             (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
00390 
00391 typedef struct {
00392         dns_adbaddrinfo_t *             addrinfo;
00393         fetchctx_t *                    fctx;
00394 } dns_valarg_t;
00395 
00396 struct dns_fetch {
00397         unsigned int                    magic;
00398         isc_mem_t *                     mctx;
00399         fetchctx_t *                    private;
00400 };
00401 
00402 #define DNS_FETCH_MAGIC                 ISC_MAGIC('F', 't', 'c', 'h')
00403 #define DNS_FETCH_VALID(fetch)          ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
00404 
00405 typedef struct fctxbucket {
00406         isc_task_t *                    task;
00407         isc_mutex_t                     lock;
00408         ISC_LIST(fetchctx_t)            fctxs;
00409         isc_boolean_t                   exiting;
00410         isc_mem_t *                     mctx;
00411 } fctxbucket_t;
00412 
00413 typedef struct alternate {
00414         isc_boolean_t                   isaddress;
00415         union   {
00416                 isc_sockaddr_t          addr;
00417                 struct {
00418                         dns_name_t      name;
00419                         in_port_t       port;
00420                 } _n;
00421         } _u;
00422         ISC_LINK(struct alternate)      link;
00423 } alternate_t;
00424 
00425 struct dns_resolver {
00426         /* Unlocked. */
00427         unsigned int                    magic;
00428         isc_mem_t *                     mctx;
00429         isc_mutex_t                     lock;
00430         isc_mutex_t                     nlock;
00431         isc_mutex_t                     primelock;
00432         dns_rdataclass_t                rdclass;
00433         isc_socketmgr_t *               socketmgr;
00434         isc_timermgr_t *                timermgr;
00435         isc_taskmgr_t *                 taskmgr;
00436         dns_view_t *                    view;
00437         isc_boolean_t                   frozen;
00438         unsigned int                    options;
00439         dns_dispatchmgr_t *             dispatchmgr;
00440         dns_dispatchset_t *             dispatches4;
00441         isc_boolean_t                   exclusivev4;
00442         dns_dispatchset_t *             dispatches6;
00443         isc_dscp_t                      querydscp4;
00444         isc_dscp_t                      querydscp6;
00445         isc_boolean_t                   exclusivev6;
00446         unsigned int                    nbuckets;
00447         fctxbucket_t *                  buckets;
00448         isc_uint32_t                    lame_ttl;
00449         ISC_LIST(alternate_t)           alternates;
00450         isc_uint16_t                    udpsize;
00451 #if USE_ALGLOCK
00452         isc_rwlock_t                    alglock;
00453 #endif
00454         dns_rbt_t *                     algorithms;
00455         dns_rbt_t *                     digests;
00456 #if USE_MBSLOCK
00457         isc_rwlock_t                    mbslock;
00458 #endif
00459         dns_rbt_t *                     mustbesecure;
00460         unsigned int                    spillatmax;
00461         unsigned int                    spillatmin;
00462         isc_timer_t *                   spillattimer;
00463         isc_boolean_t                   zero_no_soa_ttl;
00464         unsigned int                    query_timeout;
00465         unsigned int                    maxdepth;
00466         unsigned int                    maxqueries;
00467 
00468         /* Locked by lock. */
00469         unsigned int                    references;
00470         isc_boolean_t                   exiting;
00471         isc_eventlist_t                 whenshutdown;
00472         unsigned int                    activebuckets;
00473         isc_boolean_t                   priming;
00474         unsigned int                    spillat;        /* clients-per-query */
00475 
00476         dns_badcache_t  *               badcache;        /* Bad cache. */
00477 
00478         /* Locked by primelock. */
00479         dns_fetch_t *                   primefetch;
00480         /* Locked by nlock. */
00481         unsigned int                    nfctx;
00482 };
00483 
00484 #define RES_MAGIC                       ISC_MAGIC('R', 'e', 's', '!')
00485 #define VALID_RESOLVER(res)             ISC_MAGIC_VALID(res, RES_MAGIC)
00486 
00487 /*%
00488  * Private addrinfo flags.  These must not conflict with DNS_FETCHOPT_NOEDNS0
00489  * (0x008) which we also use as an addrinfo flag.
00490  */
00491 #define FCTX_ADDRINFO_MARK              0x0001
00492 #define FCTX_ADDRINFO_FORWARDER         0x1000
00493 #define FCTX_ADDRINFO_TRIED             0x2000
00494 #define FCTX_ADDRINFO_EDNSOK            0x4000
00495 #define FCTX_ADDRINFO_NOSIT             0x8000
00496 
00497 #define UNMARKED(a)                     (((a)->flags & FCTX_ADDRINFO_MARK) \
00498                                          == 0)
00499 #define ISFORWARDER(a)                  (((a)->flags & \
00500                                          FCTX_ADDRINFO_FORWARDER) != 0)
00501 #define TRIED(a)                        (((a)->flags & \
00502                                          FCTX_ADDRINFO_TRIED) != 0)
00503 #define NOSIT(a)                        (((a)->flags & \
00504                                          FCTX_ADDRINFO_NOSIT) != 0)
00505 #define EDNSOK(a)                       (((a)->flags & \
00506                                          FCTX_ADDRINFO_EDNSOK) != 0)
00507 
00508 
00509 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
00510 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
00511 
00512 static void destroy(dns_resolver_t *res);
00513 static void empty_bucket(dns_resolver_t *res);
00514 static isc_result_t resquery_send(resquery_t *query);
00515 static void resquery_response(isc_task_t *task, isc_event_t *event);
00516 static void resquery_connected(isc_task_t *task, isc_event_t *event);
00517 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
00518                      isc_boolean_t badcache);
00519 static void fctx_destroy(fetchctx_t *fctx);
00520 static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
00521 static isc_result_t ncache_adderesult(dns_message_t *message,
00522                                       dns_db_t *cache, dns_dbnode_t *node,
00523                                       dns_rdatatype_t covers,
00524                                       isc_stdtime_t now, dns_ttl_t maxttl,
00525                                       isc_boolean_t optout,
00526                                       isc_boolean_t secure,
00527                                       dns_rdataset_t *ardataset,
00528                                       isc_result_t *eresultp);
00529 static void validated(isc_task_t *task, isc_event_t *event);
00530 static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
00531 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
00532                     isc_result_t reason, badnstype_t badtype);
00533 static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
00534                                        dns_rdatatype_t type,
00535                                        dns_name_t **noqname);
00536 static void fctx_increference(fetchctx_t *fctx);
00537 static isc_boolean_t fctx_decreference(fetchctx_t *fctx);
00538 
00539 /*%
00540  * Increment resolver-related statistics counters.
00541  */
00542 static inline void
00543 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
00544         if (res->view->resstats != NULL)
00545                 isc_stats_increment(res->view->resstats, counter);
00546 }
00547 
00548 static inline void
00549 dec_stats(dns_resolver_t *res, isc_statscounter_t counter) {
00550         if (res->view->resstats != NULL)
00551                 isc_stats_decrement(res->view->resstats, counter);
00552 }
00553 
00554 static isc_result_t
00555 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
00556           dns_rdatatype_t type, dns_rdataset_t *rdataset,
00557           dns_rdataset_t *sigrdataset, unsigned int valoptions,
00558           isc_task_t *task)
00559 {
00560         dns_validator_t *validator = NULL;
00561         dns_valarg_t *valarg;
00562         isc_result_t result;
00563 
00564         valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
00565         if (valarg == NULL)
00566                 return (ISC_R_NOMEMORY);
00567 
00568         valarg->fctx = fctx;
00569         valarg->addrinfo = addrinfo;
00570 
00571         if (!ISC_LIST_EMPTY(fctx->validators))
00572                 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
00573 
00574         result = dns_validator_create(fctx->res->view, name, type, rdataset,
00575                                       sigrdataset, fctx->rmessage,
00576                                       valoptions, task, validated, valarg,
00577                                       &validator);
00578         if (result == ISC_R_SUCCESS) {
00579                 inc_stats(fctx->res, dns_resstatscounter_val);
00580                 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
00581                         INSIST(fctx->validator == NULL);
00582                         fctx->validator = validator;
00583                 }
00584                 ISC_LIST_APPEND(fctx->validators, validator, link);
00585         } else
00586                 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
00587         return (result);
00588 }
00589 
00590 static isc_boolean_t
00591 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
00592         dns_namereln_t namereln;
00593         dns_rdata_rrsig_t rrsig;
00594         dns_rdata_t rdata = DNS_RDATA_INIT;
00595         int order;
00596         isc_result_t result;
00597         unsigned int labels;
00598 
00599         for (result = dns_rdataset_first(rdataset);
00600              result == ISC_R_SUCCESS;
00601              result = dns_rdataset_next(rdataset)) {
00602                 dns_rdataset_current(rdataset, &rdata);
00603                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
00604                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00605                 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
00606                                                 &order, &labels);
00607                 if (namereln == dns_namereln_subdomain)
00608                         return (ISC_TRUE);
00609                 dns_rdata_reset(&rdata);
00610         }
00611         return (ISC_FALSE);
00612 }
00613 
00614 static isc_boolean_t
00615 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
00616         dns_name_t *name;
00617         dns_name_t *domain = &fctx->domain;
00618         dns_rdataset_t *rdataset;
00619         dns_rdatatype_t type;
00620         isc_result_t result;
00621         isc_boolean_t keep_auth = ISC_FALSE;
00622 
00623         if (message->rcode == dns_rcode_nxdomain)
00624                 return (ISC_FALSE);
00625 
00626         /*
00627          * A DS RRset can appear anywhere in a zone, even for a delegation-only
00628          * zone.  So a response to an explicit query for this type should be
00629          * excluded from delegation-only fixup.
00630          *
00631          * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
00632          * response to a query for these types can never violate the
00633          * delegation-only assumption: if the query name is below a
00634          * zone cut, the response should normally be a referral, which should
00635          * be accepted; if the query name is below a zone cut but the server
00636          * happens to have authority for the zone of the query name, the
00637          * response is a (non-referral) answer.  But this does not violate
00638          * delegation-only because the query name must be in a different zone
00639          * due to the "apex-only" nature of these types.  Note that if the
00640          * remote server happens to have authority for a child zone of a
00641          * delegation-only zone, we may still incorrectly "fix" the response
00642          * with NXDOMAIN for queries for other types.  Unfortunately it's
00643          * generally impossible to differentiate this case from violation of
00644          * the delegation-only assumption.  Once the resolver learns the
00645          * correct zone cut, possibly via a separate query for an "apex-only"
00646          * type, queries for other types will be resolved correctly.
00647          *
00648          * A query for type ANY will be accepted if it hits an exceptional
00649          * type above in the answer section as it should be from a child
00650          * zone.
00651          *
00652          * Also accept answers with RRSIG records from the child zone.
00653          * Direct queries for RRSIG records should not be answered from
00654          * the parent zone.
00655          */
00656 
00657         if (message->counts[DNS_SECTION_ANSWER] != 0 &&
00658             (fctx->type == dns_rdatatype_ns ||
00659              fctx->type == dns_rdatatype_ds ||
00660              fctx->type == dns_rdatatype_soa ||
00661              fctx->type == dns_rdatatype_any ||
00662              fctx->type == dns_rdatatype_rrsig ||
00663              fctx->type == dns_rdatatype_dnskey)) {
00664                 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
00665                 while (result == ISC_R_SUCCESS) {
00666                         name = NULL;
00667                         dns_message_currentname(message, DNS_SECTION_ANSWER,
00668                                                 &name);
00669                         for (rdataset = ISC_LIST_HEAD(name->list);
00670                              rdataset != NULL;
00671                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
00672                                 if (!dns_name_equal(name, &fctx->name))
00673                                         continue;
00674                                 type = rdataset->type;
00675                                 /*
00676                                  * RRsig from child?
00677                                  */
00678                                 if (type == dns_rdatatype_rrsig &&
00679                                     rrsig_fromchildzone(fctx, rdataset))
00680                                         return (ISC_FALSE);
00681                                 /*
00682                                  * Direct query for apex records or DS.
00683                                  */
00684                                 if (fctx->type == type &&
00685                                     (type == dns_rdatatype_ds ||
00686                                      type == dns_rdatatype_ns ||
00687                                      type == dns_rdatatype_soa ||
00688                                      type == dns_rdatatype_dnskey))
00689                                         return (ISC_FALSE);
00690                                 /*
00691                                  * Indirect query for apex records or DS.
00692                                  */
00693                                 if (fctx->type == dns_rdatatype_any &&
00694                                     (type == dns_rdatatype_ns ||
00695                                      type == dns_rdatatype_ds ||
00696                                      type == dns_rdatatype_soa ||
00697                                      type == dns_rdatatype_dnskey))
00698                                         return (ISC_FALSE);
00699                         }
00700                         result = dns_message_nextname(message,
00701                                                       DNS_SECTION_ANSWER);
00702                 }
00703         }
00704 
00705         /*
00706          * A NODATA response to a DS query?
00707          */
00708         if (fctx->type == dns_rdatatype_ds &&
00709             message->counts[DNS_SECTION_ANSWER] == 0)
00710                 return (ISC_FALSE);
00711 
00712         /* Look for referral or indication of answer from child zone? */
00713         if (message->counts[DNS_SECTION_AUTHORITY] == 0)
00714                 goto munge;
00715 
00716         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
00717         while (result == ISC_R_SUCCESS) {
00718                 name = NULL;
00719                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
00720                 for (rdataset = ISC_LIST_HEAD(name->list);
00721                      rdataset != NULL;
00722                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
00723                         type = rdataset->type;
00724                         if (type == dns_rdatatype_soa &&
00725                             dns_name_equal(name, domain))
00726                                 keep_auth = ISC_TRUE;
00727 
00728                         if (type != dns_rdatatype_ns &&
00729                             type != dns_rdatatype_soa &&
00730                             type != dns_rdatatype_rrsig)
00731                                 continue;
00732 
00733                         if (type == dns_rdatatype_rrsig) {
00734                                 if (rrsig_fromchildzone(fctx, rdataset))
00735                                         return (ISC_FALSE);
00736                                 else
00737                                         continue;
00738                         }
00739 
00740                         /* NS or SOA records. */
00741                         if (dns_name_equal(name, domain)) {
00742                                 /*
00743                                  * If a query for ANY causes a negative
00744                                  * response, we can be sure that this is
00745                                  * an empty node.  For other type of queries
00746                                  * we cannot differentiate an empty node
00747                                  * from a node that just doesn't have that
00748                                  * type of record.  We only accept the former
00749                                  * case.
00750                                  */
00751                                 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
00752                                     fctx->type == dns_rdatatype_any)
00753                                         return (ISC_FALSE);
00754                         } else if (dns_name_issubdomain(name, domain)) {
00755                                 /* Referral or answer from child zone. */
00756                                 return (ISC_FALSE);
00757                         }
00758                 }
00759                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
00760         }
00761 
00762  munge:
00763         message->rcode = dns_rcode_nxdomain;
00764         message->counts[DNS_SECTION_ANSWER] = 0;
00765         if (!keep_auth)
00766                 message->counts[DNS_SECTION_AUTHORITY] = 0;
00767         message->counts[DNS_SECTION_ADDITIONAL] = 0;
00768         return (ISC_TRUE);
00769 }
00770 
00771 static inline isc_result_t
00772 fctx_starttimer(fetchctx_t *fctx) {
00773         /*
00774          * Start the lifetime timer for fctx.
00775          *
00776          * This is also used for stopping the idle timer; in that
00777          * case we must purge events already posted to ensure that
00778          * no further idle events are delivered.
00779          */
00780         return (isc_timer_reset(fctx->timer, isc_timertype_once,
00781                                 &fctx->expires, NULL, ISC_TRUE));
00782 }
00783 
00784 static inline void
00785 fctx_stoptimer(fetchctx_t *fctx) {
00786         isc_result_t result;
00787 
00788         /*
00789          * We don't return a result if resetting the timer to inactive fails
00790          * since there's nothing to be done about it.  Resetting to inactive
00791          * should never fail anyway, since the code as currently written
00792          * cannot fail in that case.
00793          */
00794         result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
00795                                   NULL, NULL, ISC_TRUE);
00796         if (result != ISC_R_SUCCESS) {
00797                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00798                                  "isc_timer_reset(): %s",
00799                                  isc_result_totext(result));
00800         }
00801 }
00802 
00803 
00804 static inline isc_result_t
00805 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
00806         /*
00807          * Start the idle timer for fctx.  The lifetime timer continues
00808          * to be in effect.
00809          */
00810         return (isc_timer_reset(fctx->timer, isc_timertype_once,
00811                                 &fctx->expires, interval, ISC_FALSE));
00812 }
00813 
00814 /*
00815  * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
00816  * we use fctx_stopidletimer for readability in the code below.
00817  */
00818 #define fctx_stopidletimer      fctx_starttimer
00819 
00820 static inline void
00821 resquery_destroy(resquery_t **queryp) {
00822         dns_resolver_t *res;
00823         isc_boolean_t empty;
00824         resquery_t *query;
00825         fetchctx_t *fctx;
00826         unsigned int bucket;
00827 
00828         REQUIRE(queryp != NULL);
00829         query = *queryp;
00830         REQUIRE(!ISC_LINK_LINKED(query, link));
00831 
00832         INSIST(query->tcpsocket == NULL);
00833 
00834         fctx = query->fctx;
00835         res = fctx->res;
00836         bucket = fctx->bucketnum;
00837 
00838         fctx->nqueries--;
00839 
00840         LOCK(&res->buckets[bucket].lock);
00841         empty = fctx_decreference(query->fctx);
00842         UNLOCK(&res->buckets[bucket].lock);
00843 
00844         query->magic = 0;
00845         isc_mem_put(query->mctx, query, sizeof(*query));
00846         *queryp = NULL;
00847 
00848         if (empty)
00849                 empty_bucket(res);
00850 }
00851 
00852 static void
00853 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
00854                  isc_time_t *finish, isc_boolean_t no_response)
00855 {
00856         fetchctx_t *fctx;
00857         resquery_t *query;
00858         unsigned int rtt, rttms;
00859         unsigned int factor;
00860         dns_adbfind_t *find;
00861         dns_adbaddrinfo_t *addrinfo;
00862         isc_socket_t *sock;
00863         isc_stdtime_t now;
00864 
00865         query = *queryp;
00866         fctx = query->fctx;
00867 
00868         FCTXTRACE("cancelquery");
00869 
00870         REQUIRE(!RESQUERY_CANCELED(query));
00871 
00872         query->attributes |= RESQUERY_ATTR_CANCELED;
00873 
00874         /*
00875          * Should we update the RTT?
00876          */
00877         if (finish != NULL || no_response) {
00878                 if (finish != NULL) {
00879                         /*
00880                          * We have both the start and finish times for this
00881                          * packet, so we can compute a real RTT.
00882                          */
00883                         rtt = (unsigned int)isc_time_microdiff(finish,
00884                                                                &query->start);
00885                         factor = DNS_ADB_RTTADJDEFAULT;
00886 
00887                         rttms = rtt / 1000;
00888                         if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
00889                                 inc_stats(fctx->res,
00890                                           dns_resstatscounter_queryrtt0);
00891                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
00892                                 inc_stats(fctx->res,
00893                                           dns_resstatscounter_queryrtt1);
00894                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
00895                                 inc_stats(fctx->res,
00896                                           dns_resstatscounter_queryrtt2);
00897                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
00898                                 inc_stats(fctx->res,
00899                                           dns_resstatscounter_queryrtt3);
00900                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
00901                                 inc_stats(fctx->res,
00902                                           dns_resstatscounter_queryrtt4);
00903                         } else {
00904                                 inc_stats(fctx->res,
00905                                           dns_resstatscounter_queryrtt5);
00906                         }
00907                 } else {
00908                         isc_uint32_t value;
00909                         isc_uint32_t mask;
00910                         /*
00911                          * We don't have an RTT for this query.  Maybe the
00912                          * packet was lost, or maybe this server is very
00913                          * slow.  We don't know.  Increase the RTT.
00914                          */
00915                         INSIST(no_response);
00916                         isc_random_get(&value);
00917                         if (query->addrinfo->srtt > 800000)
00918                                 mask = 0x3fff;
00919                         else if (query->addrinfo->srtt > 400000)
00920                                 mask = 0x7fff;
00921                         else if (query->addrinfo->srtt > 200000)
00922                                 mask = 0xffff;
00923                         else if (query->addrinfo->srtt > 100000)
00924                                 mask = 0x1ffff;
00925                         else if (query->addrinfo->srtt > 50000)
00926                                 mask = 0x3ffff;
00927                         else if (query->addrinfo->srtt > 25000)
00928                                 mask = 0x7ffff;
00929                         else
00930                                 mask = 0xfffff;
00931                         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
00932                                 dns_adb_ednsto(fctx->adb, query->addrinfo,
00933                                                query->udpsize);
00934                         else
00935                                 dns_adb_timeout(fctx->adb, query->addrinfo);
00936 
00937                         /*
00938                          * Don't adjust timeout on EDNS queries unless we have
00939                          * seen a EDNS response.
00940                          */
00941                         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
00942                             !EDNSOK(query->addrinfo)) {
00943                                 mask >>= 2;
00944                         }
00945                         rtt = query->addrinfo->srtt + (value & mask);
00946                         if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
00947                                 rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
00948                         /*
00949                          * Replace the current RTT with our value.
00950                          */
00951                         factor = DNS_ADB_RTTADJREPLACE;
00952                 }
00953                 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
00954         }
00955 
00956         /* Remember that the server has been tried. */
00957         if (!TRIED(query->addrinfo)) {
00958                 dns_adb_changeflags(fctx->adb, query->addrinfo,
00959                                     FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
00960         }
00961 
00962         /*
00963          * Age RTTs of servers not tried.
00964          */
00965         isc_stdtime_get(&now);
00966         if (finish != NULL)
00967                 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
00968                      addrinfo != NULL;
00969                      addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00970                         if (UNMARKED(addrinfo))
00971                                 dns_adb_agesrtt(fctx->adb, addrinfo, now);
00972 
00973         if (finish != NULL && TRIEDFIND(fctx))
00974                 for (find = ISC_LIST_HEAD(fctx->finds);
00975                      find != NULL;
00976                      find = ISC_LIST_NEXT(find, publink))
00977                         for (addrinfo = ISC_LIST_HEAD(find->list);
00978                              addrinfo != NULL;
00979                              addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00980                                 if (UNMARKED(addrinfo))
00981                                         dns_adb_agesrtt(fctx->adb, addrinfo,
00982                                                         now);
00983 
00984         if (finish != NULL && TRIEDALT(fctx)) {
00985                 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
00986                      addrinfo != NULL;
00987                      addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00988                         if (UNMARKED(addrinfo))
00989                                 dns_adb_agesrtt(fctx->adb, addrinfo, now);
00990                 for (find = ISC_LIST_HEAD(fctx->altfinds);
00991                      find != NULL;
00992                      find = ISC_LIST_NEXT(find, publink))
00993                         for (addrinfo = ISC_LIST_HEAD(find->list);
00994                              addrinfo != NULL;
00995                              addrinfo = ISC_LIST_NEXT(addrinfo, publink))
00996                                 if (UNMARKED(addrinfo))
00997                                         dns_adb_agesrtt(fctx->adb, addrinfo,
00998                                                         now);
00999         }
01000 
01001         /*
01002          * Check for any outstanding socket events.  If they exist, cancel
01003          * them and let the event handlers finish the cleanup.  The resolver
01004          * only needs to worry about managing the connect and send events;
01005          * the dispatcher manages the recv events.
01006          */
01007         if (RESQUERY_CONNECTING(query)) {
01008                 /*
01009                  * Cancel the connect.
01010                  */
01011                 if (query->tcpsocket != NULL) {
01012                         isc_socket_cancel(query->tcpsocket, NULL,
01013                                           ISC_SOCKCANCEL_CONNECT);
01014                 } else if (query->dispentry != NULL) {
01015                         INSIST(query->exclusivesocket);
01016                         sock = dns_dispatch_getentrysocket(query->dispentry);
01017                         if (sock != NULL)
01018                                 isc_socket_cancel(sock, NULL,
01019                                                   ISC_SOCKCANCEL_CONNECT);
01020                 }
01021         } else if (RESQUERY_SENDING(query)) {
01022                 /*
01023                  * Cancel the pending send.
01024                  */
01025                 if (query->exclusivesocket && query->dispentry != NULL)
01026                         sock = dns_dispatch_getentrysocket(query->dispentry);
01027                 else
01028                         sock = dns_dispatch_getsocket(query->dispatch);
01029                 if (sock != NULL)
01030                         isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
01031         }
01032 
01033         if (query->dispentry != NULL)
01034                 dns_dispatch_removeresponse(&query->dispentry, deventp);
01035 
01036         ISC_LIST_UNLINK(fctx->queries, query, link);
01037 
01038         if (query->tsig != NULL)
01039                 isc_buffer_free(&query->tsig);
01040 
01041         if (query->tsigkey != NULL)
01042                 dns_tsigkey_detach(&query->tsigkey);
01043 
01044         if (query->dispatch != NULL)
01045                 dns_dispatch_detach(&query->dispatch);
01046 
01047         if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
01048                 /*
01049                  * It's safe to destroy the query now.
01050                  */
01051                 resquery_destroy(&query);
01052 }
01053 
01054 static void
01055 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
01056         resquery_t *query, *next_query;
01057 
01058         FCTXTRACE("cancelqueries");
01059 
01060         for (query = ISC_LIST_HEAD(fctx->queries);
01061              query != NULL;
01062              query = next_query) {
01063                 next_query = ISC_LIST_NEXT(query, link);
01064                 fctx_cancelquery(&query, NULL, NULL, no_response);
01065         }
01066 }
01067 
01068 static void
01069 fctx_cleanupfinds(fetchctx_t *fctx) {
01070         dns_adbfind_t *find, *next_find;
01071 
01072         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01073 
01074         for (find = ISC_LIST_HEAD(fctx->finds);
01075              find != NULL;
01076              find = next_find) {
01077                 next_find = ISC_LIST_NEXT(find, publink);
01078                 ISC_LIST_UNLINK(fctx->finds, find, publink);
01079                 dns_adb_destroyfind(&find);
01080         }
01081         fctx->find = NULL;
01082 }
01083 
01084 static void
01085 fctx_cleanupaltfinds(fetchctx_t *fctx) {
01086         dns_adbfind_t *find, *next_find;
01087 
01088         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01089 
01090         for (find = ISC_LIST_HEAD(fctx->altfinds);
01091              find != NULL;
01092              find = next_find) {
01093                 next_find = ISC_LIST_NEXT(find, publink);
01094                 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
01095                 dns_adb_destroyfind(&find);
01096         }
01097         fctx->altfind = NULL;
01098 }
01099 
01100 static void
01101 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
01102         dns_adbaddrinfo_t *addr, *next_addr;
01103 
01104         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01105 
01106         for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
01107              addr != NULL;
01108              addr = next_addr) {
01109                 next_addr = ISC_LIST_NEXT(addr, publink);
01110                 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
01111                 dns_adb_freeaddrinfo(fctx->adb, &addr);
01112         }
01113 }
01114 
01115 static void
01116 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
01117         dns_adbaddrinfo_t *addr, *next_addr;
01118 
01119         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
01120 
01121         for (addr = ISC_LIST_HEAD(fctx->altaddrs);
01122              addr != NULL;
01123              addr = next_addr) {
01124                 next_addr = ISC_LIST_NEXT(addr, publink);
01125                 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
01126                 dns_adb_freeaddrinfo(fctx->adb, &addr);
01127         }
01128 }
01129 
01130 static inline void
01131 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
01132         FCTXTRACE("stopeverything");
01133         fctx_cancelqueries(fctx, no_response);
01134         fctx_cleanupfinds(fctx);
01135         fctx_cleanupaltfinds(fctx);
01136         fctx_cleanupforwaddrs(fctx);
01137         fctx_cleanupaltaddrs(fctx);
01138         fctx_stoptimer(fctx);
01139 }
01140 
01141 static inline void
01142 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
01143         dns_fetchevent_t *event, *next_event;
01144         isc_task_t *task;
01145         unsigned int count = 0;
01146         isc_interval_t i;
01147         isc_boolean_t logit = ISC_FALSE;
01148         isc_time_t now;
01149         unsigned int old_spillat;
01150         unsigned int new_spillat = 0;   /* initialized to silence
01151                                            compiler warnings */
01152 
01153         /*
01154          * Caller must be holding the appropriate bucket lock.
01155          */
01156         REQUIRE(fctx->state == fetchstate_done);
01157 
01158         FCTXTRACE("sendevents");
01159 
01160         /*
01161          * Keep some record of fetch result for logging later (if required).
01162          */
01163         fctx->result = result;
01164         fctx->exitline = line;
01165         TIME_NOW(&now);
01166         fctx->duration = isc_time_microdiff(&now, &fctx->start);
01167 
01168         for (event = ISC_LIST_HEAD(fctx->events);
01169              event != NULL;
01170              event = next_event) {
01171                 next_event = ISC_LIST_NEXT(event, ev_link);
01172                 ISC_LIST_UNLINK(fctx->events, event, ev_link);
01173                 task = event->ev_sender;
01174                 event->ev_sender = fctx;
01175                 event->vresult = fctx->vresult;
01176                 if (!HAVE_ANSWER(fctx))
01177                         event->result = result;
01178 
01179                 INSIST(result != ISC_R_SUCCESS ||
01180                        dns_rdataset_isassociated(event->rdataset) ||
01181                        fctx->type == dns_rdatatype_any ||
01182                        fctx->type == dns_rdatatype_rrsig ||
01183                        fctx->type == dns_rdatatype_sig);
01184 
01185                 /*
01186                  * Negative results must be indicated in event->result.
01187                  */
01188                 if (dns_rdataset_isassociated(event->rdataset) &&
01189                     NEGATIVE(event->rdataset)) {
01190                         INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
01191                                event->result == DNS_R_NCACHENXRRSET);
01192                 }
01193 
01194                 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
01195                 count++;
01196         }
01197 
01198         if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
01199             fctx->spilled &&
01200             (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
01201                 LOCK(&fctx->res->lock);
01202                 if (count == fctx->res->spillat && !fctx->res->exiting) {
01203                         old_spillat = fctx->res->spillat;
01204                         fctx->res->spillat += 5;
01205                         if (fctx->res->spillat > fctx->res->spillatmax &&
01206                             fctx->res->spillatmax != 0)
01207                                 fctx->res->spillat = fctx->res->spillatmax;
01208                         new_spillat = fctx->res->spillat;
01209                         if (new_spillat != old_spillat) {
01210                                 logit = ISC_TRUE;
01211                         }
01212                         isc_interval_set(&i, 20 * 60, 0);
01213                         result = isc_timer_reset(fctx->res->spillattimer,
01214                                                  isc_timertype_ticker, NULL,
01215                                                  &i, ISC_TRUE);
01216                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
01217                 }
01218                 UNLOCK(&fctx->res->lock);
01219                 if (logit)
01220                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
01221                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
01222                                       "clients-per-query increased to %u",
01223                                       new_spillat);
01224         }
01225 }
01226 
01227 static inline void
01228 log_edns(fetchctx_t *fctx) {
01229         char domainbuf[DNS_NAME_FORMATSIZE];
01230 
01231         if (fctx->reason == NULL)
01232                 return;
01233 
01234         /*
01235          * We do not know if fctx->domain is the actual domain the record
01236          * lives in or a parent domain so we have a '?' after it.
01237          */
01238         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
01239         isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
01240                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
01241                       "success resolving '%s' (in '%s'?) after %s",
01242                       fctx->info, domainbuf, fctx->reason);
01243 
01244         fctx->reason = NULL;
01245 }
01246 
01247 static void
01248 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
01249         dns_resolver_t *res;
01250         isc_boolean_t no_response = ISC_FALSE;
01251 
01252         REQUIRE(line >= 0);
01253 
01254         FCTXTRACE("done");
01255 
01256         res = fctx->res;
01257 
01258         if (result == ISC_R_SUCCESS) {
01259                 /*%
01260                  * Log any deferred EDNS timeout messages.
01261                  */
01262                 log_edns(fctx);
01263                 no_response = ISC_TRUE;
01264         }
01265 
01266         fctx->reason = NULL;
01267         fctx_stopeverything(fctx, no_response);
01268 
01269         LOCK(&res->buckets[fctx->bucketnum].lock);
01270 
01271         fctx->state = fetchstate_done;
01272         fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
01273         fctx_sendevents(fctx, result, line);
01274 
01275         UNLOCK(&res->buckets[fctx->bucketnum].lock);
01276 }
01277 
01278 static void
01279 process_sendevent(resquery_t *query, isc_event_t *event) {
01280         isc_socketevent_t *sevent = (isc_socketevent_t *)event;
01281         isc_boolean_t destroy_query = ISC_FALSE;
01282         isc_boolean_t retry = ISC_FALSE;
01283         isc_result_t result;
01284         fetchctx_t *fctx;
01285 
01286         fctx = query->fctx;
01287 
01288         if (RESQUERY_CANCELED(query)) {
01289                 if (query->sends == 0 && query->connects == 0) {
01290                         /*
01291                          * This query was canceled while the
01292                          * isc_socket_sendto/connect() was in progress.
01293                          */
01294                         if (query->tcpsocket != NULL)
01295                                 isc_socket_detach(&query->tcpsocket);
01296                         destroy_query = ISC_TRUE;
01297                 }
01298         } else {
01299                 switch (sevent->result) {
01300                 case ISC_R_SUCCESS:
01301                         break;
01302 
01303                 case ISC_R_HOSTUNREACH:
01304                 case ISC_R_NETUNREACH:
01305                 case ISC_R_NOPERM:
01306                 case ISC_R_ADDRNOTAVAIL:
01307                 case ISC_R_CONNREFUSED:
01308                         FCTXTRACE3("query canceled in sendevent(): "
01309                                    "no route to host; no response",
01310                                    sevent->result);
01311 
01312                         /*
01313                          * No route to remote.
01314                          */
01315                         add_bad(fctx, query->addrinfo, sevent->result,
01316                                 badns_unreachable);
01317                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
01318                         retry = ISC_TRUE;
01319                         break;
01320 
01321                 default:
01322                         FCTXTRACE3("query canceled in sendevent() due to "
01323                                    "unexpected event result; responding",
01324                                    sevent->result);
01325 
01326                         fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
01327                         break;
01328                 }
01329         }
01330 
01331         if (event->ev_type == ISC_SOCKEVENT_CONNECT)
01332                 isc_event_free(&event);
01333 
01334         if (retry) {
01335                 /*
01336                  * Behave as if the idle timer has expired.  For TCP
01337                  * this may not actually reflect the latest timer.
01338                  */
01339                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
01340                 result = fctx_stopidletimer(fctx);
01341                 if (result != ISC_R_SUCCESS)
01342                         fctx_done(fctx, result, __LINE__);
01343                 else
01344                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
01345         }
01346 
01347         if (destroy_query)
01348                 resquery_destroy(&query);
01349 }
01350 
01351 static void
01352 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
01353         resquery_t *query = event->ev_arg;
01354 
01355         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
01356 
01357         QTRACE("udpconnected");
01358 
01359         UNUSED(task);
01360 
01361         INSIST(RESQUERY_CONNECTING(query));
01362 
01363         query->connects--;
01364 
01365         process_sendevent(query, event);
01366 }
01367 
01368 static void
01369 resquery_senddone(isc_task_t *task, isc_event_t *event) {
01370         resquery_t *query = event->ev_arg;
01371 
01372         REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
01373 
01374         QTRACE("senddone");
01375 
01376         /*
01377          * XXXRTH
01378          *
01379          * Currently we don't wait for the senddone event before retrying
01380          * a query.  This means that if we get really behind, we may end
01381          * up doing extra work!
01382          */
01383 
01384         UNUSED(task);
01385 
01386         INSIST(RESQUERY_SENDING(query));
01387 
01388         query->sends--;
01389 
01390         process_sendevent(query, event);
01391 }
01392 
01393 static inline isc_result_t
01394 fctx_addopt(dns_message_t *message, unsigned int version,
01395             isc_uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count)
01396 {
01397         dns_rdataset_t *rdataset = NULL;
01398         isc_result_t result;
01399 
01400         result = dns_message_buildopt(message, &rdataset, version, udpsize,
01401                                       DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
01402         if (result != ISC_R_SUCCESS)
01403                 return (result);
01404         return (dns_message_setopt(message, rdataset));
01405 }
01406 
01407 static inline void
01408 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
01409         unsigned int seconds;
01410         unsigned int us;
01411 
01412         /*
01413          * We retry every .8 seconds the first two times through the address
01414          * list, and then we do exponential back-off.
01415          */
01416         if (fctx->restarts < 3)
01417                 us = 800000;
01418         else
01419                 us = (800000 << (fctx->restarts - 2));
01420 
01421         /*
01422          * Add a fudge factor to the expected rtt based on the current
01423          * estimate.
01424          */
01425         if (rtt < 50000)
01426                 rtt += 50000;
01427         else if (rtt < 100000)
01428                 rtt += 100000;
01429         else
01430                 rtt += 200000;
01431 
01432         /*
01433          * Always wait for at least the expected rtt.
01434          */
01435         if (us < rtt)
01436                 us = rtt;
01437 
01438         /*
01439          * But don't ever wait for more than 10 seconds.
01440          */
01441         if (us > MAX_SINGLE_QUERY_TIMEOUT_US)
01442                 us = MAX_SINGLE_QUERY_TIMEOUT_US;
01443 
01444         seconds = us / US_PER_SEC;
01445         us -= seconds * US_PER_SEC;
01446         isc_interval_set(&fctx->interval, seconds, us * 1000);
01447 }
01448 
01449 static isc_result_t
01450 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
01451            unsigned int options)
01452 {
01453         dns_resolver_t *res;
01454         isc_task_t *task;
01455         isc_result_t result;
01456         resquery_t *query;
01457         isc_sockaddr_t addr;
01458         isc_boolean_t have_addr = ISC_FALSE;
01459         unsigned int srtt;
01460         isc_dscp_t dscp = -1;
01461 
01462         FCTXTRACE("query");
01463 
01464         res = fctx->res;
01465         task = res->buckets[fctx->bucketnum].task;
01466 
01467         srtt = addrinfo->srtt;
01468 
01469         /*
01470          * A forwarder needs to make multiple queries. Give it at least
01471          * a second to do these in.
01472          */
01473         if (ISFORWARDER(addrinfo) && srtt < 1000000)
01474                 srtt = 1000000;
01475 
01476         fctx_setretryinterval(fctx, srtt);
01477         result = fctx_startidletimer(fctx, &fctx->interval);
01478         if (result != ISC_R_SUCCESS)
01479                 return (result);
01480 
01481         INSIST(ISC_LIST_EMPTY(fctx->validators));
01482 
01483         dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
01484 
01485         query = isc_mem_get(fctx->mctx, sizeof(*query));
01486         if (query == NULL) {
01487                 result = ISC_R_NOMEMORY;
01488                 goto stop_idle_timer;
01489         }
01490         query->mctx = fctx->mctx;
01491         query->options = options;
01492         query->attributes = 0;
01493         query->sends = 0;
01494         query->connects = 0;
01495         query->dscp = addrinfo->dscp;
01496         /*
01497          * Note that the caller MUST guarantee that 'addrinfo' will remain
01498          * valid until this query is canceled.
01499          */
01500         query->addrinfo = addrinfo;
01501         TIME_NOW(&query->start);
01502 
01503         /*
01504          * If this is a TCP query, then we need to make a socket and
01505          * a dispatch for it here.  Otherwise we use the resolver's
01506          * shared dispatch.
01507          */
01508         query->dispatchmgr = res->dispatchmgr;
01509         query->dispatch = NULL;
01510         query->exclusivesocket = ISC_FALSE;
01511         query->tcpsocket = NULL;
01512         if (res->view->peers != NULL) {
01513                 dns_peer_t *peer = NULL;
01514                 isc_netaddr_t dstip;
01515                 isc_boolean_t usetcp = ISC_FALSE;
01516                 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
01517                 result = dns_peerlist_peerbyaddr(res->view->peers,
01518                                                  &dstip, &peer);
01519                 if (result == ISC_R_SUCCESS) {
01520                         result = dns_peer_getquerysource(peer, &addr);
01521                         if (result == ISC_R_SUCCESS)
01522                                 have_addr = ISC_TRUE;
01523                         result = dns_peer_getquerydscp(peer, &dscp);
01524                         if (result == ISC_R_SUCCESS)
01525                                 query->dscp = dscp;
01526                         result = dns_peer_getforcetcp(peer, &usetcp);
01527                         if (result == ISC_R_SUCCESS && usetcp)
01528                                 query->options |= DNS_FETCHOPT_TCP;
01529                 }
01530         }
01531 
01532         dscp = -1;
01533         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01534                 int pf;
01535 
01536                 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
01537                 if (!have_addr) {
01538                         switch (pf) {
01539                         case PF_INET:
01540                                 result = dns_dispatch_getlocaladdress(
01541                                               res->dispatches4->dispatches[0],
01542                                               &addr);
01543                                 dscp = dns_resolver_getquerydscp4(fctx->res);
01544                                 break;
01545                         case PF_INET6:
01546                                 result = dns_dispatch_getlocaladdress(
01547                                               res->dispatches6->dispatches[0],
01548                                               &addr);
01549                                 dscp = dns_resolver_getquerydscp6(fctx->res);
01550                                 break;
01551                         default:
01552                                 result = ISC_R_NOTIMPLEMENTED;
01553                                 break;
01554                         }
01555                         if (result != ISC_R_SUCCESS)
01556                                 goto cleanup_query;
01557                 }
01558                 isc_sockaddr_setport(&addr, 0);
01559                 if (query->dscp == -1)
01560                         query->dscp = dscp;
01561 
01562                 result = isc_socket_create(res->socketmgr, pf,
01563                                            isc_sockettype_tcp,
01564                                            &query->tcpsocket);
01565                 if (result != ISC_R_SUCCESS)
01566                         goto cleanup_query;
01567 
01568 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
01569                 result = isc_socket_bind(query->tcpsocket, &addr, 0);
01570                 if (result != ISC_R_SUCCESS)
01571                         goto cleanup_socket;
01572 #endif
01573                 /*
01574                  * A dispatch will be created once the connect succeeds.
01575                  */
01576         } else {
01577                 if (have_addr) {
01578                         unsigned int attrs, attrmask;
01579                         attrs = DNS_DISPATCHATTR_UDP;
01580                         switch (isc_sockaddr_pf(&addr)) {
01581                         case AF_INET:
01582                                 attrs |= DNS_DISPATCHATTR_IPV4;
01583                                 dscp = dns_resolver_getquerydscp4(fctx->res);
01584                                 break;
01585                         case AF_INET6:
01586                                 attrs |= DNS_DISPATCHATTR_IPV6;
01587                                 dscp = dns_resolver_getquerydscp6(fctx->res);
01588                                 break;
01589                         default:
01590                                 result = ISC_R_NOTIMPLEMENTED;
01591                                 goto cleanup_query;
01592                         }
01593                         attrmask = DNS_DISPATCHATTR_UDP;
01594                         attrmask |= DNS_DISPATCHATTR_TCP;
01595                         attrmask |= DNS_DISPATCHATTR_IPV4;
01596                         attrmask |= DNS_DISPATCHATTR_IPV6;
01597                         result = dns_dispatch_getudp(res->dispatchmgr,
01598                                                      res->socketmgr,
01599                                                      res->taskmgr, &addr,
01600                                                      4096, 20000, 32768, 16411,
01601                                                      16433, attrs, attrmask,
01602                                                      &query->dispatch);
01603                         if (result != ISC_R_SUCCESS)
01604                                 goto cleanup_query;
01605                 } else {
01606                         switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
01607                         case PF_INET:
01608                                 dns_dispatch_attach(
01609                                     dns_resolver_dispatchv4(res),
01610                                     &query->dispatch);
01611                                 query->exclusivesocket = res->exclusivev4;
01612                                 dscp = dns_resolver_getquerydscp4(fctx->res);
01613                                 break;
01614                         case PF_INET6:
01615                                 dns_dispatch_attach(
01616                                     dns_resolver_dispatchv6(res),
01617                                     &query->dispatch);
01618                                 query->exclusivesocket = res->exclusivev6;
01619                                 dscp = dns_resolver_getquerydscp6(fctx->res);
01620                                 break;
01621                         default:
01622                                 result = ISC_R_NOTIMPLEMENTED;
01623                                 goto cleanup_query;
01624                         }
01625                 }
01626 
01627                 if (query->dscp == -1)
01628                         query->dscp = dscp;
01629                 /*
01630                  * We should always have a valid dispatcher here.  If we
01631                  * don't support a protocol family, then its dispatcher
01632                  * will be NULL, but we shouldn't be finding addresses for
01633                  * protocol types we don't support, so the dispatcher
01634                  * we found should never be NULL.
01635                  */
01636                 INSIST(query->dispatch != NULL);
01637         }
01638 
01639         query->dispentry = NULL;
01640         fctx_increference(fctx);
01641         query->fctx = fctx;
01642         query->tsig = NULL;
01643         query->tsigkey = NULL;
01644         ISC_LINK_INIT(query, link);
01645         query->magic = QUERY_MAGIC;
01646 
01647         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01648                 /*
01649                  * Connect to the remote server.
01650                  *
01651                  * XXXRTH  Should we attach to the socket?
01652                  */
01653                 if (query->dscp != -1)
01654                         isc_socket_dscp(query->tcpsocket, query->dscp);
01655                 result = isc_socket_connect(query->tcpsocket,
01656                                             &addrinfo->sockaddr, task,
01657                                             resquery_connected, query);
01658                 if (result != ISC_R_SUCCESS)
01659                         goto cleanup_socket;
01660                 query->connects++;
01661                 QTRACE("connecting via TCP");
01662         } else {
01663                 result = resquery_send(query);
01664                 if (result != ISC_R_SUCCESS)
01665                         goto cleanup_dispatch;
01666         }
01667 
01668         fctx->querysent++;
01669 
01670         ISC_LIST_APPEND(fctx->queries, query, link);
01671         query->fctx->nqueries++;
01672         if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
01673                 inc_stats(res, dns_resstatscounter_queryv4);
01674         else
01675                 inc_stats(res, dns_resstatscounter_queryv6);
01676         if (res->view->resquerystats != NULL)
01677                 dns_rdatatypestats_increment(res->view->resquerystats,
01678                                              fctx->type);
01679 
01680         return (ISC_R_SUCCESS);
01681 
01682  cleanup_socket:
01683         isc_socket_detach(&query->tcpsocket);
01684 
01685  cleanup_dispatch:
01686         if (query->dispatch != NULL)
01687                 dns_dispatch_detach(&query->dispatch);
01688 
01689  cleanup_query:
01690         if (query->connects == 0) {
01691                 query->magic = 0;
01692                 isc_mem_put(fctx->mctx, query, sizeof(*query));
01693         }
01694 
01695  stop_idle_timer:
01696         RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
01697 
01698         return (result);
01699 }
01700 
01701 static isc_boolean_t
01702 bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01703         isc_sockaddr_t *sa;
01704 
01705         for (sa = ISC_LIST_HEAD(fctx->bad_edns);
01706              sa != NULL;
01707              sa = ISC_LIST_NEXT(sa, link)) {
01708                 if (isc_sockaddr_equal(sa, address))
01709                         return (ISC_TRUE);
01710         }
01711 
01712         return (ISC_FALSE);
01713 }
01714 
01715 static void
01716 add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01717         isc_sockaddr_t *sa;
01718 
01719         if (bad_edns(fctx, address))
01720                 return;
01721 
01722         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
01723         if (sa == NULL)
01724                 return;
01725 
01726         *sa = *address;
01727         ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
01728 }
01729 
01730 static struct tried *
01731 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01732         struct tried *tried;
01733 
01734         for (tried = ISC_LIST_HEAD(fctx->edns);
01735              tried != NULL;
01736              tried = ISC_LIST_NEXT(tried, link)) {
01737                 if (isc_sockaddr_equal(&tried->addr, address))
01738                         return (tried);
01739         }
01740 
01741         return (NULL);
01742 }
01743 
01744 static void
01745 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
01746         struct tried *tried;
01747 
01748         tried = triededns(fctx, address);
01749         if (tried != NULL) {
01750                 tried->count++;
01751                 return;
01752         }
01753 
01754         tried = isc_mem_get(fctx->mctx, sizeof(*tried));
01755         if (tried == NULL)
01756                 return;
01757 
01758         tried->addr = *address;
01759         tried->count = 1;
01760         ISC_LIST_INITANDAPPEND(fctx->edns, tried, link);
01761 }
01762 
01763 static struct tried *
01764 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
01765         struct tried *tried;
01766 
01767         for (tried = ISC_LIST_HEAD(fctx->edns512);
01768              tried != NULL;
01769              tried = ISC_LIST_NEXT(tried, link)) {
01770                 if (isc_sockaddr_equal(&tried->addr, address))
01771                         return (tried);
01772         }
01773 
01774         return (NULL);
01775 }
01776 
01777 static void
01778 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
01779         struct tried *tried;
01780 
01781         tried = triededns512(fctx, address);
01782         if (tried != NULL) {
01783                 tried->count++;
01784                 return;
01785         }
01786 
01787         tried = isc_mem_get(fctx->mctx, sizeof(*tried));
01788         if (tried == NULL)
01789                 return;
01790 
01791         tried->addr = *address;
01792         tried->count = 1;
01793         ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
01794 }
01795 
01796 #ifdef ISC_PLATFORM_USESIT
01797 static void
01798 compute_cc(resquery_t *query, unsigned char *sit, size_t len) {
01799 #ifdef AES_SIT
01800         unsigned char digest[ISC_AES_BLOCK_LENGTH];
01801         unsigned char input[16];
01802         isc_netaddr_t netaddr;
01803         unsigned int i;
01804 
01805         INSIST(len >= 8U);
01806 
01807         isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01808         switch (netaddr.family) {
01809         case AF_INET:
01810                 memmove(input, (unsigned char *)&netaddr.type.in, 4);
01811                 memset(input + 4, 0, 12);
01812                 break;
01813         case AF_INET6:
01814                 memmove(input, (unsigned char *)&netaddr.type.in6, 16);
01815                 break;
01816         }
01817         isc_aes128_crypt(query->fctx->res->view->secret, input, digest);
01818         for (i = 0; i < 8; i++)
01819                 digest[i] ^= digest[i + 8];
01820         memmove(sit, digest, 8);
01821 #endif
01822 #ifdef HMAC_SHA1_SIT
01823         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
01824         isc_netaddr_t netaddr;
01825         isc_hmacsha1_t hmacsha1;
01826 
01827         INSIST(len >= 8U);
01828 
01829         isc_hmacsha1_init(&hmacsha1, query->fctx->res->view->secret,
01830                           ISC_SHA1_DIGESTLENGTH);
01831         isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01832         switch (netaddr.family) {
01833         case AF_INET:
01834                 isc_hmacsha1_update(&hmacsha1,
01835                                     (unsigned char *)&netaddr.type.in, 4);
01836                 break;
01837         case AF_INET6:
01838                 isc_hmacsha1_update(&hmacsha1,
01839                                     (unsigned char *)&netaddr.type.in6, 16);
01840                 break;
01841         }
01842         isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest));
01843         memmove(sit, digest, 8);
01844         isc_hmacsha1_invalidate(&hmacsha1);
01845 #endif
01846 #ifdef HMAC_SHA256_SIT
01847         unsigned char digest[ISC_SHA256_DIGESTLENGTH];
01848         isc_netaddr_t netaddr;
01849         isc_hmacsha256_t hmacsha256;
01850 
01851         INSIST(len >= 8U);
01852 
01853         isc_hmacsha256_init(&hmacsha256, query->fctx->res->view->secret,
01854                             ISC_SHA256_DIGESTLENGTH);
01855         isc_netaddr_fromsockaddr(&netaddr, &query->addrinfo->sockaddr);
01856         switch (netaddr.family) {
01857         case AF_INET:
01858                 isc_hmacsha256_update(&hmacsha256,
01859                                       (unsigned char *)&netaddr.type.in, 4);
01860                 break;
01861         case AF_INET6:
01862                 isc_hmacsha256_update(&hmacsha256,
01863                                       (unsigned char *)&netaddr.type.in6, 16);
01864                 break;
01865         }
01866         isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest));
01867         memmove(sit, digest, 8);
01868         isc_hmacsha256_invalidate(&hmacsha256);
01869 #endif
01870 }
01871 #endif
01872 
01873 static isc_result_t
01874 issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
01875                isc_stdtime_t now, isc_boolean_t checknta,
01876                isc_boolean_t *issecure)
01877 {
01878         dns_name_t suffix;
01879         unsigned int labels;
01880 
01881         /*
01882          * For DS variants we need to check fom the parent domain,
01883          * since there may be a negative trust anchor for the name,
01884          * while the enclosing domain where the DS record lives is
01885          * under a secure entry point.
01886          */
01887         labels = dns_name_countlabels(name);
01888         if (dns_rdatatype_atparent(type) && labels > 1) {
01889                 dns_name_init(&suffix, NULL);
01890                 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
01891                 name = &suffix;
01892         }
01893 
01894         return (dns_view_issecuredomain(view, name, now, checknta, issecure));
01895 }
01896 
01897 static isc_boolean_t
01898 wouldvalidate(fetchctx_t *fctx) {
01899         isc_boolean_t secure_domain;
01900         isc_result_t result;
01901         isc_stdtime_t now;
01902 
01903         if (!fctx->res->view->enablevalidation)
01904                 return (ISC_FALSE);
01905 
01906         if (fctx->res->view->dlv != NULL)
01907                 return (ISC_TRUE);
01908 
01909         isc_stdtime_get(&now);
01910         result = dns_view_issecuredomain(fctx->res->view, &fctx->name,
01911                                          now, ISC_TRUE, &secure_domain);
01912         if (result != ISC_R_SUCCESS)
01913                 return (ISC_FALSE);
01914         return (secure_domain);
01915 }
01916 
01917 static isc_result_t
01918 resquery_send(resquery_t *query) {
01919         fetchctx_t *fctx;
01920         isc_result_t result;
01921         dns_name_t *qname = NULL;
01922         dns_rdataset_t *qrdataset = NULL;
01923         isc_region_t r;
01924         dns_resolver_t *res;
01925         isc_task_t *task;
01926         isc_socket_t *sock;
01927         isc_buffer_t tcpbuffer;
01928         isc_sockaddr_t *address;
01929         isc_buffer_t *buffer;
01930         isc_netaddr_t ipaddr;
01931         dns_tsigkey_t *tsigkey = NULL;
01932         dns_peer_t *peer = NULL;
01933         isc_boolean_t useedns;
01934         dns_compress_t cctx;
01935         isc_boolean_t cleanup_cctx = ISC_FALSE;
01936         isc_boolean_t secure_domain;
01937         isc_boolean_t connecting = ISC_FALSE;
01938         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
01939         unsigned ednsopt = 0;
01940         isc_uint16_t hint = 0, udpsize = 0;     /* No EDNS */
01941 
01942         fctx = query->fctx;
01943         QTRACE("send");
01944 
01945         res = fctx->res;
01946         task = res->buckets[fctx->bucketnum].task;
01947         address = NULL;
01948 
01949         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
01950                 /*
01951                  * Reserve space for the TCP message length.
01952                  */
01953                 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
01954                 isc_buffer_init(&query->buffer, query->data + 2,
01955                                 sizeof(query->data) - 2);
01956                 buffer = &tcpbuffer;
01957         } else {
01958                 isc_buffer_init(&query->buffer, query->data,
01959                                 sizeof(query->data));
01960                 buffer = &query->buffer;
01961         }
01962 
01963         result = dns_message_gettempname(fctx->qmessage, &qname);
01964         if (result != ISC_R_SUCCESS)
01965                 goto cleanup_temps;
01966         result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
01967         if (result != ISC_R_SUCCESS)
01968                 goto cleanup_temps;
01969 
01970         /*
01971          * Get a query id from the dispatch.
01972          */
01973         result = dns_dispatch_addresponse2(query->dispatch,
01974                                            &query->addrinfo->sockaddr,
01975                                            task,
01976                                            resquery_response,
01977                                            query,
01978                                            &query->id,
01979                                            &query->dispentry,
01980                                            res->socketmgr);
01981         if (result != ISC_R_SUCCESS)
01982                 goto cleanup_temps;
01983 
01984         fctx->qmessage->opcode = dns_opcode_query;
01985 
01986         /*
01987          * Set up question.
01988          */
01989         dns_name_init(qname, NULL);
01990         dns_name_clone(&fctx->name, qname);
01991         dns_rdataset_init(qrdataset);
01992         dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
01993         ISC_LIST_APPEND(qname->list, qrdataset, link);
01994         dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
01995         qname = NULL;
01996         qrdataset = NULL;
01997 
01998         /*
01999          * Set RD if the client has requested that we do a recursive query,
02000          * or if we're sending to a forwarder.
02001          */
02002         if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
02003             ISFORWARDER(query->addrinfo))
02004                 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
02005 
02006         /*
02007          * Set CD if the client says not to validate, or if the
02008          * question is under a secure entry point and this is a
02009          * recursive/forward query -- unless the client said not to.
02010          */
02011         if ((query->options & DNS_FETCHOPT_NOCDFLAG) != 0)
02012                 /* Do nothing */
02013                 ;
02014         else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0)
02015                 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
02016         else if (res->view->enablevalidation &&
02017                  ((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0))
02018         {
02019                 isc_boolean_t checknta =
02020                         ISC_TF((query->options & DNS_FETCHOPT_NONTA) == 0);
02021                 result = issecuredomain(res->view, &fctx->name, fctx->type,
02022                                         isc_time_seconds(&query->start),
02023                                         checknta, &secure_domain);
02024                 if (result != ISC_R_SUCCESS)
02025                         secure_domain = ISC_FALSE;
02026                 if (res->view->dlv != NULL)
02027                         secure_domain = ISC_TRUE;
02028                 if (secure_domain)
02029                         fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
02030         }
02031 
02032         /*
02033          * We don't have to set opcode because it defaults to query.
02034          */
02035         fctx->qmessage->id = query->id;
02036 
02037         /*
02038          * Convert the question to wire format.
02039          */
02040         result = dns_compress_init(&cctx, -1, fctx->res->mctx);
02041         if (result != ISC_R_SUCCESS)
02042                 goto cleanup_message;
02043         cleanup_cctx = ISC_TRUE;
02044 
02045         result = dns_message_renderbegin(fctx->qmessage, &cctx,
02046                                          &query->buffer);
02047         if (result != ISC_R_SUCCESS)
02048                 goto cleanup_message;
02049 
02050         result = dns_message_rendersection(fctx->qmessage,
02051                                            DNS_SECTION_QUESTION, 0);
02052         if (result != ISC_R_SUCCESS)
02053                 goto cleanup_message;
02054 
02055         peer = NULL;
02056         isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
02057         (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
02058 
02059         /*
02060          * The ADB does not know about servers with "edns no".  Check this,
02061          * and then inform the ADB for future use.
02062          */
02063         if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
02064             peer != NULL &&
02065             dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
02066             !useedns)
02067         {
02068                 query->options |= DNS_FETCHOPT_NOEDNS0;
02069                 dns_adb_changeflags(fctx->adb, query->addrinfo,
02070                                     DNS_FETCHOPT_NOEDNS0,
02071                                     DNS_FETCHOPT_NOEDNS0);
02072         }
02073 
02074         /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
02075         if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
02076                 query->options |= DNS_FETCHOPT_NOEDNS0;
02077 
02078         /* See if response history indicates that EDNS is not supported. */
02079         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
02080             dns_adb_noedns(fctx->adb, query->addrinfo))
02081                 query->options |= DNS_FETCHOPT_NOEDNS0;
02082 
02083         if (fctx->timeout && (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
02084                 isc_sockaddr_t *sockaddr = &query->addrinfo->sockaddr;
02085                 struct tried *tried;
02086 
02087                 if (fctx->timeouts > (MAX_EDNS0_TIMEOUTS * 2) &&
02088                     (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) {
02089                         query->options |= DNS_FETCHOPT_NOEDNS0;
02090                         fctx->reason = "disabling EDNS";
02091                 } else if ((tried = triededns512(fctx, sockaddr)) != NULL &&
02092                     tried->count >= 2U &&
02093                     (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) {
02094                         query->options |= DNS_FETCHOPT_NOEDNS0;
02095                         fctx->reason = "disabling EDNS";
02096                 } else if ((tried = triededns(fctx, sockaddr)) != NULL) {
02097                         if (tried->count == 1U) {
02098                                 hint = dns_adb_getudpsize(fctx->adb,
02099                                                           query->addrinfo);
02100                         } else if (tried->count >= 2U) {
02101                                 query->options |= DNS_FETCHOPT_EDNS512;
02102                                 fctx->reason = "reducing the advertised EDNS "
02103                                                "UDP packet size to 512 octets";
02104                         }
02105                 }
02106         }
02107         fctx->timeout = ISC_FALSE;
02108 
02109         /*
02110          * Use EDNS0, unless the caller doesn't want it, or we know that
02111          * the remote server doesn't like it.
02112          */
02113         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
02114                 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
02115                         unsigned int version = DNS_EDNS_VERSION;
02116                         unsigned int flags = query->addrinfo->flags;
02117                         isc_boolean_t reqnsid = res->view->requestnsid;
02118 #ifdef ISC_PLATFORM_USESIT
02119                         isc_boolean_t reqsit = res->view->requestsit;
02120                         unsigned char sit[64];
02121 #endif
02122 
02123                         if ((flags & FCTX_ADDRINFO_EDNSOK) != 0 &&
02124                             (query->options & DNS_FETCHOPT_EDNS512) == 0) {
02125                                 udpsize = dns_adb_probesize2(fctx->adb,
02126                                                              query->addrinfo,
02127                                                              fctx->timeouts);
02128                                 if (udpsize > res->udpsize)
02129                                         udpsize = res->udpsize;
02130                         }
02131 
02132                         if (peer != NULL)
02133                                 (void)dns_peer_getudpsize(peer, &udpsize);
02134 
02135                         if (udpsize == 0U && res->udpsize == 512U)
02136                                 udpsize = 512;
02137 
02138                         /*
02139                          * Was the size forced to 512 in the configuration?
02140                          */
02141                         if (udpsize == 512U)
02142                             query->options |= DNS_FETCHOPT_EDNS512;
02143 
02144                         /*
02145                          * We have talked to this server before.
02146                          */
02147                         if (hint != 0U)
02148                                 udpsize = hint;
02149 
02150                         /*
02151                          * We know nothing about the peer's capabilities
02152                          * so start with minimal EDNS UDP size.
02153                          */
02154                         if (udpsize == 0U)
02155                                 udpsize = 512;
02156 
02157                         if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
02158                                 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
02159                                 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
02160                         }
02161 
02162                         /* Request NSID/SIT/VERSION for current peer? */
02163                         if (peer != NULL) {
02164                                 isc_uint8_t ednsversion;
02165                                 (void) dns_peer_getrequestnsid(peer, &reqnsid);
02166 #ifdef ISC_PLATFORM_USESIT
02167                                 (void) dns_peer_getrequestsit(peer, &reqsit);
02168 #endif
02169                                 result = dns_peer_getednsversion(peer,
02170                                                                  &ednsversion);
02171                                 if (result == ISC_R_SUCCESS &&
02172                                     ednsversion < version)
02173                                         version = ednsversion;
02174                         }
02175 #ifdef ISC_PLATFORM_USESIT
02176                         if (NOSIT(query->addrinfo))
02177                                 reqsit = ISC_FALSE;
02178 #endif
02179                         if (reqnsid) {
02180                                 INSIST(ednsopt < DNS_EDNSOPTIONS);
02181                                 ednsopts[ednsopt].code = DNS_OPT_NSID;
02182                                 ednsopts[ednsopt].length = 0;
02183                                 ednsopts[ednsopt].value = NULL;
02184                                 ednsopt++;
02185                         }
02186 #ifdef ISC_PLATFORM_USESIT
02187 #if DNS_EDNS_VERSION > 0
02188                         /*
02189                          * Some EDNS(0) servers don't ignore unknown options
02190                          * as it was not a explict requirement of RFC 2671.
02191                          * Only send SIT to EDNS(1) servers.
02192                          */
02193                         if (version < 1)
02194                                 reqsit = ISC_FALSE;
02195 #endif
02196                         if (reqsit) {
02197                                 INSIST(ednsopt < DNS_EDNSOPTIONS);
02198                                 ednsopts[ednsopt].code = DNS_OPT_SIT;
02199                                 ednsopts[ednsopt].length = (isc_uint16_t)
02200                                         dns_adb_getsit(fctx->adb,
02201                                                        query->addrinfo,
02202                                                        sit, sizeof(sit));
02203                                 if (ednsopts[ednsopt].length != 0) {
02204                                         ednsopts[ednsopt].value = sit;
02205                                         inc_stats(fctx->res,
02206                                                   dns_resstatscounter_sitout);
02207                                 } else {
02208                                         compute_cc(query, sit, sizeof(sit));
02209                                         ednsopts[ednsopt].value = sit;
02210                                         ednsopts[ednsopt].length = 8;
02211                                         inc_stats(fctx->res,
02212                                                   dns_resstatscounter_sitcc);
02213                                 }
02214                                 ednsopt++;
02215                         }
02216 #endif
02217                         query->ednsversion = version;
02218                         result = fctx_addopt(fctx->qmessage, version,
02219                                              udpsize, ednsopts, ednsopt);
02220                         if (reqnsid && result == ISC_R_SUCCESS) {
02221                                 query->options |= DNS_FETCHOPT_WANTNSID;
02222                         } else if (result != ISC_R_SUCCESS) {
02223                                 /*
02224                                  * We couldn't add the OPT, but we'll press on.
02225                                  * We're not using EDNS0, so set the NOEDNS0
02226                                  * bit.
02227                                  */
02228                                 query->options |= DNS_FETCHOPT_NOEDNS0;
02229                                 query->ednsversion = -1;
02230                                 udpsize = 0;
02231                         }
02232                 } else {
02233                         /*
02234                          * We know this server doesn't like EDNS0, so we
02235                          * won't use it.  Set the NOEDNS0 bit since we're
02236                          * not using EDNS0.
02237                          */
02238                         query->options |= DNS_FETCHOPT_NOEDNS0;
02239                         query->ednsversion = -1;
02240                 }
02241         } else
02242                 query->ednsversion = -1;
02243 
02244         /*
02245          * Record the UDP EDNS size choosen.
02246          */
02247         query->udpsize = udpsize;
02248 
02249         /*
02250          * If we need EDNS0 to do this query and aren't using it, we lose.
02251          */
02252         if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
02253                 result = DNS_R_SERVFAIL;
02254                 goto cleanup_message;
02255         }
02256 
02257         if (udpsize > 512U)
02258                 add_triededns(fctx, &query->addrinfo->sockaddr);
02259 
02260         if (udpsize == 512U)
02261                 add_triededns512(fctx, &query->addrinfo->sockaddr);
02262 
02263         /*
02264          * Clear CD if EDNS is not in use.
02265          */
02266         if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
02267                 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
02268 
02269         /*
02270          * Add TSIG record tailored to the current recipient.
02271          */
02272         result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
02273         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
02274                 goto cleanup_message;
02275 
02276         if (tsigkey != NULL) {
02277                 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
02278                 dns_tsigkey_detach(&tsigkey);
02279                 if (result != ISC_R_SUCCESS)
02280                         goto cleanup_message;
02281         }
02282 
02283         result = dns_message_rendersection(fctx->qmessage,
02284                                            DNS_SECTION_ADDITIONAL, 0);
02285         if (result != ISC_R_SUCCESS)
02286                 goto cleanup_message;
02287 
02288         result = dns_message_renderend(fctx->qmessage);
02289         if (result != ISC_R_SUCCESS)
02290                 goto cleanup_message;
02291 
02292         dns_compress_invalidate(&cctx);
02293         cleanup_cctx = ISC_FALSE;
02294 
02295         if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
02296                 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
02297                                    &query->tsigkey);
02298                 result = dns_message_getquerytsig(fctx->qmessage,
02299                                                   fctx->res->mctx,
02300                                                   &query->tsig);
02301                 if (result != ISC_R_SUCCESS)
02302                         goto cleanup_message;
02303         }
02304 
02305         /*
02306          * If using TCP, write the length of the message at the beginning
02307          * of the buffer.
02308          */
02309         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
02310                 isc_buffer_usedregion(&query->buffer, &r);
02311                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
02312                 isc_buffer_add(&tcpbuffer, r.length);
02313         }
02314 
02315         /*
02316          * Log the outgoing packet.
02317          */
02318         dns_message_logfmtpacket2(fctx->qmessage, "sending packet to",
02319                                   &query->addrinfo->sockaddr,
02320                                   DNS_LOGCATEGORY_RESOLVER,
02321                                   DNS_LOGMODULE_PACKETS,
02322                                   &dns_master_style_comment,
02323                                   ISC_LOG_DEBUG(11),
02324                                   fctx->res->mctx);
02325 
02326         /*
02327          * We're now done with the query message.
02328          */
02329         dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
02330 
02331         if (query->exclusivesocket)
02332                 sock = dns_dispatch_getentrysocket(query->dispentry);
02333         else
02334                 sock = dns_dispatch_getsocket(query->dispatch);
02335         /*
02336          * Send the query!
02337          */
02338         if ((query->options & DNS_FETCHOPT_TCP) == 0) {
02339                 address = &query->addrinfo->sockaddr;
02340                 if (query->exclusivesocket) {
02341                         result = isc_socket_connect(sock, address, task,
02342                                                     resquery_udpconnected,
02343                                                     query);
02344                         if (result != ISC_R_SUCCESS)
02345                                 goto cleanup_message;
02346                         connecting = ISC_TRUE;
02347                         query->connects++;
02348                 }
02349         }
02350         isc_buffer_usedregion(buffer, &r);
02351 
02352         /*
02353          * XXXRTH  Make sure we don't send to ourselves!  We should probably
02354          *              prune out these addresses when we get them from the ADB.
02355          */
02356         memset(&query->sendevent, 0, sizeof(query->sendevent));
02357         ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL,
02358                        ISC_SOCKEVENT_SENDDONE, resquery_senddone, query,
02359                        NULL, NULL, NULL);
02360 
02361         if (query->dscp == -1) {
02362                 query->sendevent.attributes &= ~ISC_SOCKEVENTATTR_DSCP;
02363                 query->sendevent.dscp = 0;
02364         } else {
02365                 query->sendevent.attributes |= ISC_SOCKEVENTATTR_DSCP;
02366                 query->sendevent.dscp = query->dscp;
02367                 if ((query->options & DNS_FETCHOPT_TCP) != 0)
02368                         isc_socket_dscp(sock, query->dscp);
02369         }
02370 
02371         result = isc_socket_sendto2(sock, &r, task, address, NULL,
02372                                     &query->sendevent, 0);
02373         if (result != ISC_R_SUCCESS) {
02374                 if (connecting) {
02375                         /*
02376                          * This query is still connecting.
02377                          * Mark it as canceled so that it will just be
02378                          * cleaned up when the connected event is received.
02379                          * Keep fctx around until the event is processed.
02380                          */
02381                         query->fctx->nqueries++;
02382                         query->attributes |= RESQUERY_ATTR_CANCELED;
02383                 }
02384                 goto cleanup_message;
02385         }
02386 
02387         query->sends++;
02388 
02389         QTRACE("sent");
02390 
02391         return (ISC_R_SUCCESS);
02392 
02393  cleanup_message:
02394         if (cleanup_cctx)
02395                 dns_compress_invalidate(&cctx);
02396 
02397         dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
02398 
02399         /*
02400          * Stop the dispatcher from listening.
02401          */
02402         dns_dispatch_removeresponse(&query->dispentry, NULL);
02403 
02404  cleanup_temps:
02405         if (qname != NULL)
02406                 dns_message_puttempname(fctx->qmessage, &qname);
02407         if (qrdataset != NULL)
02408                 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
02409 
02410         return (result);
02411 }
02412 
02413 static void
02414 resquery_connected(isc_task_t *task, isc_event_t *event) {
02415         isc_socketevent_t *sevent = (isc_socketevent_t *)event;
02416         resquery_t *query = event->ev_arg;
02417         isc_boolean_t retry = ISC_FALSE;
02418         isc_interval_t interval;
02419         isc_result_t result;
02420         unsigned int attrs;
02421         fetchctx_t *fctx;
02422 
02423         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
02424         REQUIRE(VALID_QUERY(query));
02425 
02426         QTRACE("connected");
02427 
02428         UNUSED(task);
02429 
02430         /*
02431          * XXXRTH
02432          *
02433          * Currently we don't wait for the connect event before retrying
02434          * a query.  This means that if we get really behind, we may end
02435          * up doing extra work!
02436          */
02437 
02438         query->connects--;
02439         fctx = query->fctx;
02440 
02441         if (RESQUERY_CANCELED(query)) {
02442                 /*
02443                  * This query was canceled while the connect() was in
02444                  * progress.
02445                  */
02446                 isc_socket_detach(&query->tcpsocket);
02447                 resquery_destroy(&query);
02448         } else {
02449                 switch (sevent->result) {
02450                 case ISC_R_SUCCESS:
02451 
02452                         /*
02453                          * Extend the idle timer for TCP.  20 seconds
02454                          * should be long enough for a TCP connection to be
02455                          * established, a single DNS request to be sent,
02456                          * and the response received.
02457                          */
02458                         isc_interval_set(&interval, 20, 0);
02459                         result = fctx_startidletimer(query->fctx, &interval);
02460                         if (result != ISC_R_SUCCESS) {
02461                                 FCTXTRACE("query canceled: idle timer failed; "
02462                                           "responding");
02463 
02464                                 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02465                                 fctx_done(fctx, result, __LINE__);
02466                                 break;
02467                         }
02468                         /*
02469                          * We are connected.  Create a dispatcher and
02470                          * send the query.
02471                          */
02472                         attrs = 0;
02473                         attrs |= DNS_DISPATCHATTR_TCP;
02474                         attrs |= DNS_DISPATCHATTR_PRIVATE;
02475                         attrs |= DNS_DISPATCHATTR_CONNECTED;
02476                         if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
02477                             AF_INET)
02478                                 attrs |= DNS_DISPATCHATTR_IPV4;
02479                         else
02480                                 attrs |= DNS_DISPATCHATTR_IPV6;
02481                         attrs |= DNS_DISPATCHATTR_MAKEQUERY;
02482 
02483                         result = dns_dispatch_createtcp(query->dispatchmgr,
02484                                                      query->tcpsocket,
02485                                                      query->fctx->res->taskmgr,
02486                                                      4096, 2, 1, 1, 3, attrs,
02487                                                      &query->dispatch);
02488 
02489                         /*
02490                          * Regardless of whether dns_dispatch_create()
02491                          * succeeded or not, we don't need our reference
02492                          * to the socket anymore.
02493                          */
02494                         isc_socket_detach(&query->tcpsocket);
02495 
02496                         if (result == ISC_R_SUCCESS)
02497                                 result = resquery_send(query);
02498 
02499                         if (result != ISC_R_SUCCESS) {
02500                                 FCTXTRACE("query canceled: "
02501                                           "resquery_send() failed; responding");
02502 
02503                                 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02504                                 fctx_done(fctx, result, __LINE__);
02505                         }
02506                         break;
02507 
02508                 case ISC_R_NETUNREACH:
02509                 case ISC_R_HOSTUNREACH:
02510                 case ISC_R_CONNREFUSED:
02511                 case ISC_R_NOPERM:
02512                 case ISC_R_ADDRNOTAVAIL:
02513                 case ISC_R_CONNECTIONRESET:
02514                         FCTXTRACE3("query canceled in connected(): "
02515                                    "no route to host; no response",
02516                                    sevent->result);
02517 
02518                         /*
02519                          * No route to remote.
02520                          */
02521                         isc_socket_detach(&query->tcpsocket);
02522                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
02523                         retry = ISC_TRUE;
02524                         break;
02525 
02526                 default:
02527                         FCTXTRACE3("query canceled in connected() due to "
02528                                    "unexpected event result; responding",
02529                                    sevent->result);
02530 
02531                         isc_socket_detach(&query->tcpsocket);
02532                         fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
02533                         break;
02534                 }
02535         }
02536 
02537         isc_event_free(&event);
02538 
02539         if (retry) {
02540                 /*
02541                  * Behave as if the idle timer has expired.  For TCP
02542                  * connections this may not actually reflect the latest timer.
02543                  */
02544                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
02545                 result = fctx_stopidletimer(fctx);
02546                 if (result != ISC_R_SUCCESS)
02547                         fctx_done(fctx, result, __LINE__);
02548                 else
02549                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
02550         }
02551 }
02552 
02553 static void
02554 fctx_finddone(isc_task_t *task, isc_event_t *event) {
02555         fetchctx_t *fctx;
02556         dns_adbfind_t *find;
02557         dns_resolver_t *res;
02558         isc_boolean_t want_try = ISC_FALSE;
02559         isc_boolean_t want_done = ISC_FALSE;
02560         isc_boolean_t bucket_empty = ISC_FALSE;
02561         unsigned int bucketnum;
02562         isc_boolean_t dodestroy = ISC_FALSE;
02563 
02564         find = event->ev_sender;
02565         fctx = event->ev_arg;
02566         REQUIRE(VALID_FCTX(fctx));
02567         res = fctx->res;
02568 
02569         UNUSED(task);
02570 
02571         FCTXTRACE("finddone");
02572 
02573         bucketnum = fctx->bucketnum;
02574         LOCK(&res->buckets[bucketnum].lock);
02575 
02576         INSIST(fctx->pending > 0);
02577         fctx->pending--;
02578 
02579         if (ADDRWAIT(fctx)) {
02580                 /*
02581                  * The fetch is waiting for a name to be found.
02582                  */
02583                 INSIST(!SHUTTINGDOWN(fctx));
02584                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
02585                 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
02586                         want_try = ISC_TRUE;
02587                 } else {
02588                         fctx->findfail++;
02589                         if (fctx->pending == 0) {
02590                                 /*
02591                                  * We've got nothing else to wait for and don't
02592                                  * know the answer.  There's nothing to do but
02593                                  * fail the fctx.
02594                                  */
02595                                 want_done = ISC_TRUE;
02596                         }
02597                 }
02598         } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
02599                    fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
02600 
02601                 if (fctx->references == 0) {
02602                         bucket_empty = fctx_unlink(fctx);
02603                         dodestroy = ISC_TRUE;
02604                 }
02605         }
02606         UNLOCK(&res->buckets[bucketnum].lock);
02607 
02608         isc_event_free(&event);
02609         dns_adb_destroyfind(&find);
02610 
02611         if (want_try) {
02612                 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
02613         } else if (want_done) {
02614                 FCTXTRACE("fetch failed in finddone(); return ISC_R_FAILURE");
02615                 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
02616         } else if (dodestroy) {
02617                 fctx_destroy(fctx);
02618                 if (bucket_empty)
02619                         empty_bucket(res);
02620         }
02621 }
02622 
02623 
02624 static inline isc_boolean_t
02625 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
02626         isc_sockaddr_t *sa;
02627 
02628         for (sa = ISC_LIST_HEAD(fctx->bad);
02629              sa != NULL;
02630              sa = ISC_LIST_NEXT(sa, link)) {
02631                 if (isc_sockaddr_equal(sa, address))
02632                         return (ISC_TRUE);
02633         }
02634 
02635         return (ISC_FALSE);
02636 }
02637 
02638 static inline isc_boolean_t
02639 mark_bad(fetchctx_t *fctx) {
02640         dns_adbfind_t *curr;
02641         dns_adbaddrinfo_t *addrinfo;
02642         isc_boolean_t all_bad = ISC_TRUE;
02643 
02644         /*
02645          * Mark all known bad servers, so we don't try to talk to them
02646          * again.
02647          */
02648 
02649         /*
02650          * Mark any bad nameservers.
02651          */
02652         for (curr = ISC_LIST_HEAD(fctx->finds);
02653              curr != NULL;
02654              curr = ISC_LIST_NEXT(curr, publink)) {
02655                 for (addrinfo = ISC_LIST_HEAD(curr->list);
02656                      addrinfo != NULL;
02657                      addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02658                         if (bad_server(fctx, &addrinfo->sockaddr))
02659                                 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02660                         else
02661                                 all_bad = ISC_FALSE;
02662                 }
02663         }
02664 
02665         /*
02666          * Mark any bad forwarders.
02667          */
02668         for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
02669              addrinfo != NULL;
02670              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02671                 if (bad_server(fctx, &addrinfo->sockaddr))
02672                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
02673                 else
02674                         all_bad = ISC_FALSE;
02675         }
02676 
02677         /*
02678          * Mark any bad alternates.
02679          */
02680         for (curr = ISC_LIST_HEAD(fctx->altfinds);
02681              curr != NULL;
02682              curr = ISC_LIST_NEXT(curr, publink)) {
02683                 for (addrinfo = ISC_LIST_HEAD(curr->list);
02684                      addrinfo != NULL;
02685                      addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02686                         if (bad_server(fctx, &addrinfo->sockaddr))
02687                                 addrinfo->flags |= FCTX_ADDRINFO_MARK;
02688                         else
02689                                 all_bad = ISC_FALSE;
02690                 }
02691         }
02692 
02693         for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
02694              addrinfo != NULL;
02695              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
02696                 if (bad_server(fctx, &addrinfo->sockaddr))
02697                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
02698                 else
02699                         all_bad = ISC_FALSE;
02700         }
02701 
02702         return (all_bad);
02703 }
02704 
02705 static void
02706 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
02707         badnstype_t badtype)
02708 {
02709         char namebuf[DNS_NAME_FORMATSIZE];
02710         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
02711         char classbuf[64];
02712         char typebuf[64];
02713         char code[64];
02714         isc_buffer_t b;
02715         isc_sockaddr_t *sa;
02716         const char *spc = "";
02717         isc_sockaddr_t *address = &addrinfo->sockaddr;
02718 
02719         if (reason == DNS_R_LAME)
02720                 fctx->lamecount++;
02721         else {
02722                 switch (badtype) {
02723                 case badns_unreachable:
02724                         fctx->neterr++;
02725                         break;
02726                 case badns_response:
02727                         fctx->badresp++;
02728                         break;
02729                 case badns_validation:
02730                         break;  /* counted as 'valfail' */
02731                 }
02732         }
02733 
02734         if (bad_server(fctx, address)) {
02735                 /*
02736                  * We already know this server is bad.
02737                  */
02738                 return;
02739         }
02740 
02741         FCTXTRACE("add_bad");
02742 
02743         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
02744         if (sa == NULL)
02745                 return;
02746         *sa = *address;
02747         ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
02748 
02749         if (reason == DNS_R_LAME)       /* already logged */
02750                 return;
02751 
02752         if (reason == DNS_R_UNEXPECTEDRCODE &&
02753             fctx->rmessage->rcode == dns_rcode_servfail &&
02754             ISFORWARDER(addrinfo))
02755                 return;
02756 
02757         if (reason == DNS_R_UNEXPECTEDRCODE) {
02758                 isc_buffer_init(&b, code, sizeof(code) - 1);
02759                 dns_rcode_totext(fctx->rmessage->rcode, &b);
02760                 code[isc_buffer_usedlength(&b)] = '\0';
02761                 spc = " ";
02762         } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
02763                 isc_buffer_init(&b, code, sizeof(code) - 1);
02764                 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
02765                 code[isc_buffer_usedlength(&b)] = '\0';
02766                 spc = " ";
02767         } else {
02768                 code[0] = '\0';
02769         }
02770         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
02771         dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
02772         dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
02773         isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
02774         isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
02775                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
02776                       "%s%s%s resolving '%s/%s/%s': %s",
02777                       code, spc, dns_result_totext(reason),
02778                       namebuf, typebuf, classbuf, addrbuf);
02779 }
02780 
02781 /*
02782  * Sort addrinfo list by RTT.
02783  */
02784 static void
02785 sort_adbfind(dns_adbfind_t *find) {
02786         dns_adbaddrinfo_t *best, *curr;
02787         dns_adbaddrinfolist_t sorted;
02788 
02789         /* Lame N^2 bubble sort. */
02790         ISC_LIST_INIT(sorted);
02791         while (!ISC_LIST_EMPTY(find->list)) {
02792                 best = ISC_LIST_HEAD(find->list);
02793                 curr = ISC_LIST_NEXT(best, publink);
02794                 while (curr != NULL) {
02795                         if (curr->srtt < best->srtt)
02796                                 best = curr;
02797                         curr = ISC_LIST_NEXT(curr, publink);
02798                 }
02799                 ISC_LIST_UNLINK(find->list, best, publink);
02800                 ISC_LIST_APPEND(sorted, best, publink);
02801         }
02802         find->list = sorted;
02803 }
02804 
02805 /*
02806  * Sort a list of finds by server RTT.
02807  */
02808 static void
02809 sort_finds(dns_adbfindlist_t *findlist) {
02810         dns_adbfind_t *best, *curr;
02811         dns_adbfindlist_t sorted;
02812         dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
02813 
02814         /* Sort each find's addrinfo list by SRTT. */
02815         for (curr = ISC_LIST_HEAD(*findlist);
02816              curr != NULL;
02817              curr = ISC_LIST_NEXT(curr, publink))
02818                 sort_adbfind(curr);
02819 
02820         /* Lame N^2 bubble sort. */
02821         ISC_LIST_INIT(sorted);
02822         while (!ISC_LIST_EMPTY(*findlist)) {
02823                 best = ISC_LIST_HEAD(*findlist);
02824                 bestaddrinfo = ISC_LIST_HEAD(best->list);
02825                 INSIST(bestaddrinfo != NULL);
02826                 curr = ISC_LIST_NEXT(best, publink);
02827                 while (curr != NULL) {
02828                         addrinfo = ISC_LIST_HEAD(curr->list);
02829                         INSIST(addrinfo != NULL);
02830                         if (addrinfo->srtt < bestaddrinfo->srtt) {
02831                                 best = curr;
02832                                 bestaddrinfo = addrinfo;
02833                         }
02834                         curr = ISC_LIST_NEXT(curr, publink);
02835                 }
02836                 ISC_LIST_UNLINK(*findlist, best, publink);
02837                 ISC_LIST_APPEND(sorted, best, publink);
02838         }
02839         *findlist = sorted;
02840 }
02841 
02842 static void
02843 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
02844          unsigned int options, unsigned int flags, isc_stdtime_t now,
02845          isc_boolean_t *need_alternate)
02846 {
02847         dns_adbaddrinfo_t *ai;
02848         dns_adbfind_t *find;
02849         dns_resolver_t *res;
02850         isc_boolean_t unshared;
02851         isc_result_t result;
02852 
02853         res = fctx->res;
02854         unshared = ISC_TF((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
02855         /*
02856          * If this name is a subdomain of the query domain, tell
02857          * the ADB to start looking using zone/hint data. This keeps us
02858          * from getting stuck if the nameserver is beneath the zone cut
02859          * and we don't know its address (e.g. because the A record has
02860          * expired).
02861          */
02862         if (dns_name_issubdomain(name, &fctx->domain))
02863                 options |= DNS_ADBFIND_STARTATZONE;
02864         options |= DNS_ADBFIND_GLUEOK;
02865         options |= DNS_ADBFIND_HINTOK;
02866 
02867         /*
02868          * See what we know about this address.
02869          */
02870         find = NULL;
02871         result = dns_adb_createfind2(fctx->adb,
02872                                      res->buckets[fctx->bucketnum].task,
02873                                      fctx_finddone, fctx, name,
02874                                      &fctx->name, fctx->type,
02875                                      options, now, NULL,
02876                                      res->view->dstport,
02877                                      fctx->depth + 1, fctx->qc, &find);
02878         if (result != ISC_R_SUCCESS) {
02879                 if (result == DNS_R_ALIAS) {
02880                         char namebuf[DNS_NAME_FORMATSIZE];
02881 
02882                         /*
02883                          * XXXRTH  Follow the CNAME/DNAME chain?
02884                          */
02885                         dns_adb_destroyfind(&find);
02886                         fctx->adberr++;
02887                         dns_name_format(name, namebuf, sizeof(namebuf));
02888                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_CNAME,
02889                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
02890                                       "skipping nameserver '%s' because it "
02891                                       "is a CNAME, while resolving '%s'",
02892                                       namebuf, fctx->info);
02893                 }
02894         } else if (!ISC_LIST_EMPTY(find->list)) {
02895                 /*
02896                  * We have at least some of the addresses for the
02897                  * name.
02898                  */
02899                 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
02900                 if (flags != 0 || port != 0) {
02901                         for (ai = ISC_LIST_HEAD(find->list);
02902                              ai != NULL;
02903                              ai = ISC_LIST_NEXT(ai, publink)) {
02904                                 ai->flags |= flags;
02905                                 if (port != 0)
02906                                         isc_sockaddr_setport(&ai->sockaddr,
02907                                                              port);
02908                         }
02909                 }
02910                 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
02911                         ISC_LIST_APPEND(fctx->altfinds, find, publink);
02912                 else
02913                         ISC_LIST_APPEND(fctx->finds, find, publink);
02914         } else {
02915                 /*
02916                  * We don't know any of the addresses for this
02917                  * name.
02918                  */
02919                 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
02920                         /*
02921                          * We're looking for them and will get an
02922                          * event about it later.
02923                          */
02924                         fctx->pending++;
02925                         /*
02926                          * Bootstrap.
02927                          */
02928                         if (need_alternate != NULL &&
02929                             !*need_alternate && unshared &&
02930                             ((res->dispatches4 == NULL &&
02931                               find->result_v6 != DNS_R_NXDOMAIN) ||
02932                              (res->dispatches6 == NULL &&
02933                               find->result_v4 != DNS_R_NXDOMAIN)))
02934                                 *need_alternate = ISC_TRUE;
02935                 } else {
02936                         if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
02937                                 fctx->lamecount++; /* cached lame server */
02938                         else
02939                                 fctx->adberr++; /* unreachable server, etc. */
02940 
02941                         /*
02942                          * If we know there are no addresses for
02943                          * the family we are using then try to add
02944                          * an alternative server.
02945                          */
02946                         if (need_alternate != NULL && !*need_alternate &&
02947                             ((res->dispatches4 == NULL &&
02948                               find->result_v6 == DNS_R_NXRRSET) ||
02949                              (res->dispatches6 == NULL &&
02950                               find->result_v4 == DNS_R_NXRRSET)))
02951                                 *need_alternate = ISC_TRUE;
02952                         dns_adb_destroyfind(&find);
02953                 }
02954         }
02955 }
02956 
02957 static isc_boolean_t
02958 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
02959         int order;
02960         unsigned int nlabels;
02961         dns_namereln_t namereln;
02962 
02963         namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
02964         return (ISC_TF(namereln == dns_namereln_subdomain));
02965 }
02966 
02967 static isc_result_t
02968 fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
02969         dns_rdata_t rdata = DNS_RDATA_INIT;
02970         isc_result_t result;
02971         dns_resolver_t *res;
02972         isc_stdtime_t now;
02973         unsigned int stdoptions = 0;
02974         dns_forwarder_t *fwd;
02975         dns_adbaddrinfo_t *ai;
02976         isc_boolean_t all_bad;
02977         dns_rdata_ns_t ns;
02978         isc_boolean_t need_alternate = ISC_FALSE;
02979 
02980         FCTXTRACE("getaddresses");
02981 
02982         /*
02983          * Don't pound on remote servers.  (Failsafe!)
02984          */
02985         fctx->restarts++;
02986         if (fctx->restarts > 100) {
02987                 FCTXTRACE("too many restarts");
02988                 return (DNS_R_SERVFAIL);
02989         }
02990 
02991         res = fctx->res;
02992 
02993         if (fctx->depth > res->maxdepth) {
02994                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
02995                               DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
02996                               "too much NS indirection resolving '%s'",
02997                               fctx->info);
02998                 return (DNS_R_SERVFAIL);
02999         }
03000 
03001         /*
03002          * Forwarders.
03003          */
03004 
03005         INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
03006         INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
03007 
03008         /*
03009          * If this fctx has forwarders, use them; otherwise use any
03010          * selective forwarders specified in the view; otherwise use the
03011          * resolver's forwarders (if any).
03012          */
03013         fwd = ISC_LIST_HEAD(fctx->forwarders);
03014         if (fwd == NULL) {
03015                 dns_forwarders_t *forwarders = NULL;
03016                 dns_name_t *name = &fctx->name;
03017                 dns_name_t suffix;
03018                 unsigned int labels;
03019                 dns_fixedname_t fixed;
03020                 dns_name_t *domain;
03021 
03022                 /*
03023                  * DS records are found in the parent server.
03024                  * Strip label to get the correct forwarder (if any).
03025                  */
03026                 if (dns_rdatatype_atparent(fctx->type) &&
03027                     dns_name_countlabels(name) > 1) {
03028                         dns_name_init(&suffix, NULL);
03029                         labels = dns_name_countlabels(name);
03030                         dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
03031                         name = &suffix;
03032                 }
03033 
03034                 dns_fixedname_init(&fixed);
03035                 domain = dns_fixedname_name(&fixed);
03036                 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
03037                                             domain, &forwarders);
03038                 if (result == ISC_R_SUCCESS) {
03039                         fwd = ISC_LIST_HEAD(forwarders->fwdrs);
03040                         fctx->fwdpolicy = forwarders->fwdpolicy;
03041                         if (fctx->fwdpolicy == dns_fwdpolicy_only &&
03042                             isstrictsubdomain(domain, &fctx->domain)) {
03043                                 dns_name_free(&fctx->domain, fctx->mctx);
03044                                 dns_name_init(&fctx->domain, NULL);
03045                                 result = dns_name_dup(domain, fctx->mctx,
03046                                                       &fctx->domain);
03047                                 if (result != ISC_R_SUCCESS)
03048                                         return (result);
03049                         }
03050                 }
03051         }
03052 
03053         while (fwd != NULL) {
03054                 if ((isc_sockaddr_pf(&fwd->addr) == AF_INET &&
03055                          fctx->res->dispatches4 == NULL) ||
03056                     (isc_sockaddr_pf(&fwd->addr) == AF_INET6 &&
03057                         fctx->res->dispatches6 == NULL)) {
03058                                 fwd = ISC_LIST_NEXT(fwd, link);
03059                                 continue;
03060                 }
03061                 ai = NULL;
03062                 result = dns_adb_findaddrinfo(fctx->adb, &fwd->addr, &ai, 0);
03063                 if (result == ISC_R_SUCCESS) {
03064                         dns_adbaddrinfo_t *cur;
03065                         ai->flags |= FCTX_ADDRINFO_FORWARDER;
03066                         ai->dscp = fwd->dscp;
03067                         cur = ISC_LIST_HEAD(fctx->forwaddrs);
03068                         while (cur != NULL && cur->srtt < ai->srtt)
03069                                 cur = ISC_LIST_NEXT(cur, publink);
03070                         if (cur != NULL)
03071                                 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
03072                                                       ai, publink);
03073                         else
03074                                 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
03075                 }
03076                 fwd = ISC_LIST_NEXT(fwd, link);
03077         }
03078 
03079         /*
03080          * If the forwarding policy is "only", we don't need the addresses
03081          * of the nameservers.
03082          */
03083         if (fctx->fwdpolicy == dns_fwdpolicy_only)
03084                 goto out;
03085 
03086         /*
03087          * Normal nameservers.
03088          */
03089 
03090         stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
03091         if (fctx->restarts == 1) {
03092                 /*
03093                  * To avoid sending out a flood of queries likely to
03094                  * result in NXRRSET, we suppress fetches for address
03095                  * families we don't have the first time through,
03096                  * provided that we have addresses in some family we
03097                  * can use.
03098                  *
03099                  * We don't want to set this option all the time, since
03100                  * if fctx->restarts > 1, we've clearly been having trouble
03101                  * with the addresses we had, so getting more could help.
03102                  */
03103                 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
03104         }
03105         if (res->dispatches4 != NULL)
03106                 stdoptions |= DNS_ADBFIND_INET;
03107         if (res->dispatches6 != NULL)
03108                 stdoptions |= DNS_ADBFIND_INET6;
03109 
03110         if ((stdoptions & DNS_ADBFIND_ADDRESSMASK) == 0)
03111                 return (DNS_R_SERVFAIL);
03112 
03113         isc_stdtime_get(&now);
03114 
03115         INSIST(ISC_LIST_EMPTY(fctx->finds));
03116         INSIST(ISC_LIST_EMPTY(fctx->altfinds));
03117 
03118         for (result = dns_rdataset_first(&fctx->nameservers);
03119              result == ISC_R_SUCCESS;
03120              result = dns_rdataset_next(&fctx->nameservers))
03121         {
03122                 dns_rdataset_current(&fctx->nameservers, &rdata);
03123                 /*
03124                  * Extract the name from the NS record.
03125                  */
03126                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
03127                 if (result != ISC_R_SUCCESS)
03128                         continue;
03129 
03130                 findname(fctx, &ns.name, 0, stdoptions, 0, now,
03131                          &need_alternate);
03132                 dns_rdata_reset(&rdata);
03133                 dns_rdata_freestruct(&ns);
03134         }
03135         if (result != ISC_R_NOMORE)
03136                 return (result);
03137 
03138         /*
03139          * Do we need to use 6 to 4?
03140          */
03141         if (need_alternate) {
03142                 int family;
03143                 alternate_t *a;
03144                 family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
03145                 for (a = ISC_LIST_HEAD(fctx->res->alternates);
03146                      a != NULL;
03147                      a = ISC_LIST_NEXT(a, link)) {
03148                         if (!a->isaddress) {
03149                                 findname(fctx, &a->_u._n.name, a->_u._n.port,
03150                                          stdoptions, FCTX_ADDRINFO_FORWARDER,
03151                                          now, NULL);
03152                                 continue;
03153                         }
03154                         if (isc_sockaddr_pf(&a->_u.addr) != family)
03155                                 continue;
03156                         ai = NULL;
03157                         result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
03158                                                       &ai, 0);
03159                         if (result == ISC_R_SUCCESS) {
03160                                 dns_adbaddrinfo_t *cur;
03161                                 ai->flags |= FCTX_ADDRINFO_FORWARDER;
03162                                 cur = ISC_LIST_HEAD(fctx->altaddrs);
03163                                 while (cur != NULL && cur->srtt < ai->srtt)
03164                                         cur = ISC_LIST_NEXT(cur, publink);
03165                                 if (cur != NULL)
03166                                         ISC_LIST_INSERTBEFORE(fctx->altaddrs,
03167                                                               cur, ai, publink);
03168                                 else
03169                                         ISC_LIST_APPEND(fctx->altaddrs, ai,
03170                                                         publink);
03171                         }
03172                 }
03173         }
03174 
03175  out:
03176         /*
03177          * Mark all known bad servers.
03178          */
03179         all_bad = mark_bad(fctx);
03180 
03181         /*
03182          * How are we doing?
03183          */
03184         if (all_bad) {
03185                 /*
03186                  * We've got no addresses.
03187                  */
03188                 if (fctx->pending > 0) {
03189                         /*
03190                          * We're fetching the addresses, but don't have any
03191                          * yet.   Tell the caller to wait for an answer.
03192                          */
03193                         result = DNS_R_WAIT;
03194                 } else {
03195                         isc_time_t expire;
03196                         isc_interval_t i;
03197                         /*
03198                          * We've lost completely.  We don't know any
03199                          * addresses, and the ADB has told us it can't get
03200                          * them.
03201                          */
03202                         FCTXTRACE("no addresses");
03203                         isc_interval_set(&i, DNS_RESOLVER_BADCACHETTL(fctx), 0);
03204                         result = isc_time_nowplusinterval(&expire, &i);
03205                         if (badcache &&
03206                             (fctx->type == dns_rdatatype_dnskey ||
03207                              fctx->type == dns_rdatatype_dlv ||
03208                              fctx->type == dns_rdatatype_ds) &&
03209                              result == ISC_R_SUCCESS)
03210                                 dns_resolver_addbadcache(fctx->res,
03211                                                          &fctx->name,
03212                                                          fctx->type, &expire);
03213                         result = ISC_R_FAILURE;
03214                 }
03215         } else {
03216                 /*
03217                  * We've found some addresses.  We might still be looking
03218                  * for more addresses.
03219                  */
03220                 sort_finds(&fctx->finds);
03221                 sort_finds(&fctx->altfinds);
03222                 result = ISC_R_SUCCESS;
03223         }
03224 
03225         return (result);
03226 }
03227 
03228 static inline void
03229 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
03230         isc_netaddr_t na;
03231         char buf[ISC_NETADDR_FORMATSIZE];
03232         isc_sockaddr_t *sa;
03233         isc_boolean_t aborted = ISC_FALSE;
03234         isc_boolean_t bogus;
03235         dns_acl_t *blackhole;
03236         isc_netaddr_t ipaddr;
03237         dns_peer_t *peer = NULL;
03238         dns_resolver_t *res;
03239         const char *msg = NULL;
03240 
03241         sa = &addr->sockaddr;
03242 
03243         res = fctx->res;
03244         isc_netaddr_fromsockaddr(&ipaddr, sa);
03245         blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
03246         (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
03247 
03248         if (blackhole != NULL) {
03249                 int match;
03250 
03251                 if (dns_acl_match(&ipaddr, NULL, blackhole,
03252                                   &res->view->aclenv,
03253                                   &match, NULL) == ISC_R_SUCCESS &&
03254                     match > 0)
03255                         aborted = ISC_TRUE;
03256         }
03257 
03258         if (peer != NULL &&
03259             dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
03260             bogus)
03261                 aborted = ISC_TRUE;
03262 
03263         if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
03264                 return;
03265 
03266         if (aborted) {
03267                 addr->flags |= FCTX_ADDRINFO_MARK;
03268                 msg = "ignoring blackholed / bogus server: ";
03269         } else if (isc_sockaddr_ismulticast(sa)) {
03270                 addr->flags |= FCTX_ADDRINFO_MARK;
03271                 msg = "ignoring multicast address: ";
03272         } else if (isc_sockaddr_isexperimental(sa)) {
03273                 addr->flags |= FCTX_ADDRINFO_MARK;
03274                 msg = "ignoring experimental address: ";
03275         } else if (sa->type.sa.sa_family != AF_INET6) {
03276                 return;
03277         } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
03278                 addr->flags |= FCTX_ADDRINFO_MARK;
03279                 msg = "ignoring IPv6 mapped IPV4 address: ";
03280         } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
03281                 addr->flags |= FCTX_ADDRINFO_MARK;
03282                 msg = "ignoring IPv6 compatibility IPV4 address: ";
03283         } else
03284                 return;
03285 
03286         isc_netaddr_fromsockaddr(&na, sa);
03287         isc_netaddr_format(&na, buf, sizeof(buf));
03288         FCTXTRACE2(msg, buf);
03289 }
03290 
03291 static inline dns_adbaddrinfo_t *
03292 fctx_nextaddress(fetchctx_t *fctx) {
03293         dns_adbfind_t *find, *start;
03294         dns_adbaddrinfo_t *addrinfo;
03295         dns_adbaddrinfo_t *faddrinfo;
03296 
03297         /*
03298          * Return the next untried address, if any.
03299          */
03300 
03301         /*
03302          * Find the first unmarked forwarder (if any).
03303          */
03304         for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
03305              addrinfo != NULL;
03306              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03307                 if (!UNMARKED(addrinfo))
03308                         continue;
03309                 possibly_mark(fctx, addrinfo);
03310                 if (UNMARKED(addrinfo)) {
03311                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
03312                         fctx->find = NULL;
03313                         return (addrinfo);
03314                 }
03315         }
03316 
03317         /*
03318          * No forwarders.  Move to the next find.
03319          */
03320 
03321         fctx->attributes |= FCTX_ATTR_TRIEDFIND;
03322 
03323         find = fctx->find;
03324         if (find == NULL)
03325                 find = ISC_LIST_HEAD(fctx->finds);
03326         else {
03327                 find = ISC_LIST_NEXT(find, publink);
03328                 if (find == NULL)
03329                         find = ISC_LIST_HEAD(fctx->finds);
03330         }
03331 
03332         /*
03333          * Find the first unmarked addrinfo.
03334          */
03335         addrinfo = NULL;
03336         if (find != NULL) {
03337                 start = find;
03338                 do {
03339                         for (addrinfo = ISC_LIST_HEAD(find->list);
03340                              addrinfo != NULL;
03341                              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03342                                 if (!UNMARKED(addrinfo))
03343                                         continue;
03344                                 possibly_mark(fctx, addrinfo);
03345                                 if (UNMARKED(addrinfo)) {
03346                                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
03347                                         break;
03348                                 }
03349                         }
03350                         if (addrinfo != NULL)
03351                                 break;
03352                         find = ISC_LIST_NEXT(find, publink);
03353                         if (find == NULL)
03354                                 find = ISC_LIST_HEAD(fctx->finds);
03355                 } while (find != start);
03356         }
03357 
03358         fctx->find = find;
03359         if (addrinfo != NULL)
03360                 return (addrinfo);
03361 
03362         /*
03363          * No nameservers left.  Try alternates.
03364          */
03365 
03366         fctx->attributes |= FCTX_ATTR_TRIEDALT;
03367 
03368         find = fctx->altfind;
03369         if (find == NULL)
03370                 find = ISC_LIST_HEAD(fctx->altfinds);
03371         else {
03372                 find = ISC_LIST_NEXT(find, publink);
03373                 if (find == NULL)
03374                         find = ISC_LIST_HEAD(fctx->altfinds);
03375         }
03376 
03377         /*
03378          * Find the first unmarked addrinfo.
03379          */
03380         addrinfo = NULL;
03381         if (find != NULL) {
03382                 start = find;
03383                 do {
03384                         for (addrinfo = ISC_LIST_HEAD(find->list);
03385                              addrinfo != NULL;
03386                              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03387                                 if (!UNMARKED(addrinfo))
03388                                         continue;
03389                                 possibly_mark(fctx, addrinfo);
03390                                 if (UNMARKED(addrinfo)) {
03391                                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
03392                                         break;
03393                                 }
03394                         }
03395                         if (addrinfo != NULL)
03396                                 break;
03397                         find = ISC_LIST_NEXT(find, publink);
03398                         if (find == NULL)
03399                                 find = ISC_LIST_HEAD(fctx->altfinds);
03400                 } while (find != start);
03401         }
03402 
03403         faddrinfo = addrinfo;
03404 
03405         /*
03406          * See if we have a better alternate server by address.
03407          */
03408 
03409         for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
03410              addrinfo != NULL;
03411              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
03412                 if (!UNMARKED(addrinfo))
03413                         continue;
03414                 possibly_mark(fctx, addrinfo);
03415                 if (UNMARKED(addrinfo) &&
03416                     (faddrinfo == NULL ||
03417                      addrinfo->srtt < faddrinfo->srtt)) {
03418                         if (faddrinfo != NULL)
03419                                 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
03420                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
03421                         break;
03422                 }
03423         }
03424 
03425         if (addrinfo == NULL) {
03426                 addrinfo = faddrinfo;
03427                 fctx->altfind = find;
03428         }
03429 
03430         return (addrinfo);
03431 }
03432 
03433 static void
03434 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
03435         isc_result_t result;
03436         dns_adbaddrinfo_t *addrinfo;
03437 
03438         FCTXTRACE("try");
03439 
03440         REQUIRE(!ADDRWAIT(fctx));
03441 
03442         /* We've already exceeded maximum query count */
03443         if (isc_counter_used(fctx->qc) > fctx->res->maxqueries) {
03444                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03445                               DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
03446                               "exceeded max queries resolving '%s'",
03447                               fctx->info);
03448                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03449                 return;
03450         }
03451 
03452         addrinfo = fctx_nextaddress(fctx);
03453         if (addrinfo == NULL) {
03454                 /*
03455                  * We have no more addresses.  Start over.
03456                  */
03457                 fctx_cancelqueries(fctx, ISC_TRUE);
03458                 fctx_cleanupfinds(fctx);
03459                 fctx_cleanupaltfinds(fctx);
03460                 fctx_cleanupforwaddrs(fctx);
03461                 fctx_cleanupaltaddrs(fctx);
03462                 result = fctx_getaddresses(fctx, badcache);
03463                 if (result == DNS_R_WAIT) {
03464                         /*
03465                          * Sleep waiting for addresses.
03466                          */
03467                         FCTXTRACE("addrwait");
03468                         fctx->attributes |= FCTX_ATTR_ADDRWAIT;
03469                         return;
03470                 } else if (result != ISC_R_SUCCESS) {
03471                         /*
03472                          * Something bad happened.
03473                          */
03474                         fctx_done(fctx, result, __LINE__);
03475                         return;
03476                 }
03477 
03478                 addrinfo = fctx_nextaddress(fctx);
03479                 /*
03480                  * While we may have addresses from the ADB, they
03481                  * might be bad ones.  In this case, return SERVFAIL.
03482                  */
03483                 if (addrinfo == NULL) {
03484                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03485                         return;
03486                 }
03487         }
03488 
03489         if (dns_name_countlabels(&fctx->domain) > 2) {
03490                 result = isc_counter_increment(fctx->qc);
03491                 if (result != ISC_R_SUCCESS) {
03492                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03493                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
03494                                       "exceeded max queries resolving '%s'",
03495                                       fctx->info);
03496                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
03497                         return;
03498                 }
03499         }
03500 
03501         result = fctx_query(fctx, addrinfo, fctx->options);
03502         if (result != ISC_R_SUCCESS)
03503                 fctx_done(fctx, result, __LINE__);
03504         else if (retrying)
03505                 inc_stats(fctx->res, dns_resstatscounter_retry);
03506 }
03507 
03508 static isc_boolean_t
03509 fctx_unlink(fetchctx_t *fctx) {
03510         dns_resolver_t *res;
03511         unsigned int bucketnum;
03512 
03513         /*
03514          * Caller must be holding the bucket lock.
03515          */
03516 
03517         REQUIRE(VALID_FCTX(fctx));
03518         REQUIRE(fctx->state == fetchstate_done ||
03519                 fctx->state == fetchstate_init);
03520         REQUIRE(ISC_LIST_EMPTY(fctx->events));
03521         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
03522         REQUIRE(ISC_LIST_EMPTY(fctx->finds));
03523         REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
03524         REQUIRE(fctx->pending == 0);
03525         REQUIRE(fctx->references == 0);
03526         REQUIRE(ISC_LIST_EMPTY(fctx->validators));
03527 
03528         FCTXTRACE("unlink");
03529 
03530         res = fctx->res;
03531         bucketnum = fctx->bucketnum;
03532 
03533         ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
03534 
03535         LOCK(&res->nlock);
03536         res->nfctx--;
03537         UNLOCK(&res->nlock);
03538         dec_stats(res, dns_resstatscounter_nfetch);
03539 
03540         if (res->buckets[bucketnum].exiting &&
03541             ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
03542                 return (ISC_TRUE);
03543 
03544         return (ISC_FALSE);
03545 }
03546 
03547 static void
03548 fctx_destroy(fetchctx_t *fctx) {
03549         isc_sockaddr_t *sa, *next_sa;
03550         struct tried *tried;
03551 
03552         REQUIRE(VALID_FCTX(fctx));
03553         REQUIRE(fctx->state == fetchstate_done ||
03554                 fctx->state == fetchstate_init);
03555         REQUIRE(ISC_LIST_EMPTY(fctx->events));
03556         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
03557         REQUIRE(ISC_LIST_EMPTY(fctx->finds));
03558         REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
03559         REQUIRE(fctx->pending == 0);
03560         REQUIRE(fctx->references == 0);
03561         REQUIRE(ISC_LIST_EMPTY(fctx->validators));
03562         REQUIRE(!ISC_LINK_LINKED(fctx, link));
03563 
03564         FCTXTRACE("destroy");
03565 
03566         /*
03567          * Free bad.
03568          */
03569         for (sa = ISC_LIST_HEAD(fctx->bad);
03570              sa != NULL;
03571              sa = next_sa) {
03572                 next_sa = ISC_LIST_NEXT(sa, link);
03573                 ISC_LIST_UNLINK(fctx->bad, sa, link);
03574                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
03575         }
03576 
03577         for (tried = ISC_LIST_HEAD(fctx->edns);
03578              tried != NULL;
03579              tried = ISC_LIST_HEAD(fctx->edns)) {
03580                 ISC_LIST_UNLINK(fctx->edns, tried, link);
03581                 isc_mem_put(fctx->mctx, tried, sizeof(*tried));
03582         }
03583 
03584         for (tried = ISC_LIST_HEAD(fctx->edns512);
03585              tried != NULL;
03586              tried = ISC_LIST_HEAD(fctx->edns512)) {
03587                 ISC_LIST_UNLINK(fctx->edns512, tried, link);
03588                 isc_mem_put(fctx->mctx, tried, sizeof(*tried));
03589         }
03590 
03591         for (sa = ISC_LIST_HEAD(fctx->bad_edns);
03592              sa != NULL;
03593              sa = next_sa) {
03594                 next_sa = ISC_LIST_NEXT(sa, link);
03595                 ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
03596                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
03597         }
03598 
03599         isc_counter_detach(&fctx->qc);
03600         isc_timer_detach(&fctx->timer);
03601         dns_message_destroy(&fctx->rmessage);
03602         dns_message_destroy(&fctx->qmessage);
03603         if (dns_name_countlabels(&fctx->domain) > 0)
03604                 dns_name_free(&fctx->domain, fctx->mctx);
03605         if (dns_rdataset_isassociated(&fctx->nameservers))
03606                 dns_rdataset_disassociate(&fctx->nameservers);
03607         dns_name_free(&fctx->name, fctx->mctx);
03608         dns_db_detach(&fctx->cache);
03609         dns_adb_detach(&fctx->adb);
03610         isc_mem_free(fctx->mctx, fctx->info);
03611         isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
03612 }
03613 
03614 /*
03615  * Fetch event handlers.
03616  */
03617 
03618 static void
03619 fctx_timeout(isc_task_t *task, isc_event_t *event) {
03620         fetchctx_t *fctx = event->ev_arg;
03621         isc_timerevent_t *tevent = (isc_timerevent_t *)event;
03622         resquery_t *query;
03623 
03624         REQUIRE(VALID_FCTX(fctx));
03625 
03626         UNUSED(task);
03627 
03628         FCTXTRACE("timeout");
03629 
03630         inc_stats(fctx->res, dns_resstatscounter_querytimeout);
03631 
03632         if (event->ev_type == ISC_TIMEREVENT_LIFE) {
03633                 fctx->reason = NULL;
03634                 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
03635         } else {
03636                 isc_result_t result;
03637 
03638                 fctx->timeouts++;
03639                 fctx->timeout = ISC_TRUE;
03640 
03641                 /*
03642                  * We could cancel the running queries here, or we could let
03643                  * them keep going.  Since we normally use separate sockets for
03644                  * different queries, we adopt the former approach to reduce
03645                  * the number of open sockets: cancel the oldest query if it
03646                  * expired after the query had started (this is usually the
03647                  * case but is not always so, depending on the task schedule
03648                  * timing).
03649                  */
03650                 query = ISC_LIST_HEAD(fctx->queries);
03651                 if (query != NULL &&
03652                     isc_time_compare(&tevent->due, &query->start) >= 0)
03653                 {
03654                         FCTXTRACE("query timed out; no response");
03655                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
03656                 }
03657                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
03658 
03659                 /*
03660                  * Our timer has triggered.  Reestablish the fctx lifetime
03661                  * timer.
03662                  */
03663                 result = fctx_starttimer(fctx);
03664                 if (result != ISC_R_SUCCESS)
03665                         fctx_done(fctx, result, __LINE__);
03666                 else
03667                         /*
03668                          * Keep trying.
03669                          */
03670                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
03671         }
03672 
03673         isc_event_free(&event);
03674 }
03675 
03676 static void
03677 fctx_shutdown(fetchctx_t *fctx) {
03678         isc_event_t *cevent;
03679 
03680         /*
03681          * Start the shutdown process for fctx, if it isn't already underway.
03682          */
03683 
03684         FCTXTRACE("shutdown");
03685 
03686         /*
03687          * The caller must be holding the appropriate bucket lock.
03688          */
03689 
03690         if (fctx->want_shutdown)
03691                 return;
03692 
03693         fctx->want_shutdown = ISC_TRUE;
03694 
03695         /*
03696          * Unless we're still initializing (in which case the
03697          * control event is still outstanding), we need to post
03698          * the control event to tell the fetch we want it to
03699          * exit.
03700          */
03701         if (fctx->state != fetchstate_init) {
03702                 cevent = &fctx->control_event;
03703                 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
03704                               &cevent);
03705         }
03706 }
03707 
03708 static void
03709 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
03710         fetchctx_t *fctx = event->ev_arg;
03711         isc_boolean_t bucket_empty = ISC_FALSE;
03712         dns_resolver_t *res;
03713         unsigned int bucketnum;
03714         dns_validator_t *validator;
03715         isc_boolean_t dodestroy = ISC_FALSE;
03716 
03717         REQUIRE(VALID_FCTX(fctx));
03718 
03719         UNUSED(task);
03720 
03721         res = fctx->res;
03722         bucketnum = fctx->bucketnum;
03723 
03724         FCTXTRACE("doshutdown");
03725 
03726         /*
03727          * An fctx that is shutting down is no longer in ADDRWAIT mode.
03728          */
03729         fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
03730 
03731         /*
03732          * Cancel all pending validators.  Note that this must be done
03733          * without the bucket lock held, since that could cause deadlock.
03734          */
03735         validator = ISC_LIST_HEAD(fctx->validators);
03736         while (validator != NULL) {
03737                 dns_validator_cancel(validator);
03738                 validator = ISC_LIST_NEXT(validator, link);
03739         }
03740 
03741         if (fctx->nsfetch != NULL)
03742                 dns_resolver_cancelfetch(fctx->nsfetch);
03743 
03744         /*
03745          * Shut down anything that is still running on behalf of this
03746          * fetch.  To avoid deadlock with the ADB, we must do this
03747          * before we lock the bucket lock.
03748          */
03749         fctx_stopeverything(fctx, ISC_FALSE);
03750 
03751         LOCK(&res->buckets[bucketnum].lock);
03752 
03753         fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
03754 
03755         INSIST(fctx->state == fetchstate_active ||
03756                fctx->state == fetchstate_done);
03757         INSIST(fctx->want_shutdown);
03758 
03759         if (fctx->state != fetchstate_done) {
03760                 fctx->state = fetchstate_done;
03761                 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
03762         }
03763 
03764         if (fctx->references == 0 && fctx->pending == 0 &&
03765             fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
03766                 bucket_empty = fctx_unlink(fctx);
03767                 dodestroy = ISC_TRUE;
03768         }
03769 
03770         UNLOCK(&res->buckets[bucketnum].lock);
03771 
03772         if (dodestroy) {
03773                 fctx_destroy(fctx);
03774                 if (bucket_empty)
03775                         empty_bucket(res);
03776         }
03777 }
03778 
03779 static void
03780 fctx_start(isc_task_t *task, isc_event_t *event) {
03781         fetchctx_t *fctx = event->ev_arg;
03782         isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
03783         dns_resolver_t *res;
03784         unsigned int bucketnum;
03785         isc_boolean_t dodestroy = ISC_FALSE;
03786 
03787         REQUIRE(VALID_FCTX(fctx));
03788 
03789         UNUSED(task);
03790 
03791         res = fctx->res;
03792         bucketnum = fctx->bucketnum;
03793 
03794         FCTXTRACE("start");
03795 
03796         LOCK(&res->buckets[bucketnum].lock);
03797 
03798         INSIST(fctx->state == fetchstate_init);
03799         if (fctx->want_shutdown) {
03800                 /*
03801                  * We haven't started this fctx yet, and we've been requested
03802                  * to shut it down.
03803                  */
03804                 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
03805                 fctx->state = fetchstate_done;
03806                 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
03807                 /*
03808                  * Since we haven't started, we INSIST that we have no
03809                  * pending ADB finds and no pending validations.
03810                  */
03811                 INSIST(fctx->pending == 0);
03812                 INSIST(fctx->nqueries == 0);
03813                 INSIST(ISC_LIST_EMPTY(fctx->validators));
03814                 if (fctx->references == 0) {
03815                         /*
03816                          * It's now safe to destroy this fctx.
03817                          */
03818                         bucket_empty = fctx_unlink(fctx);
03819                         dodestroy = ISC_TRUE;
03820                 }
03821                 done = ISC_TRUE;
03822         } else {
03823                 /*
03824                  * Normal fctx startup.
03825                  */
03826                 fctx->state = fetchstate_active;
03827                 /*
03828                  * Reset the control event for later use in shutting down
03829                  * the fctx.
03830                  */
03831                 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
03832                                DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
03833                                NULL, NULL, NULL);
03834         }
03835 
03836         UNLOCK(&res->buckets[bucketnum].lock);
03837 
03838         if (!done) {
03839                 isc_result_t result;
03840 
03841                 INSIST(!dodestroy);
03842 
03843                 /*
03844                  * All is well.  Start working on the fetch.
03845                  */
03846                 result = fctx_starttimer(fctx);
03847                 if (result != ISC_R_SUCCESS)
03848                         fctx_done(fctx, result, __LINE__);
03849                 else
03850                         fctx_try(fctx, ISC_FALSE, ISC_FALSE);
03851         } else if (dodestroy) {
03852                         fctx_destroy(fctx);
03853                 if (bucket_empty)
03854                         empty_bucket(res);
03855         }
03856 }
03857 
03858 /*
03859  * Fetch Creation, Joining, and Cancelation.
03860  */
03861 
03862 static inline isc_result_t
03863 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
03864           dns_messageid_t id, isc_taskaction_t action, void *arg,
03865           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
03866           dns_fetch_t *fetch)
03867 {
03868         isc_task_t *clone;
03869         dns_fetchevent_t *event;
03870 
03871         FCTXTRACE("join");
03872 
03873         /*
03874          * We store the task we're going to send this event to in the
03875          * sender field.  We'll make the fetch the sender when we actually
03876          * send the event.
03877          */
03878         clone = NULL;
03879         isc_task_attach(task, &clone);
03880         event = (dns_fetchevent_t *)
03881                 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
03882                                    action, arg, sizeof(*event));
03883         if (event == NULL) {
03884                 isc_task_detach(&clone);
03885                 return (ISC_R_NOMEMORY);
03886         }
03887         event->result = DNS_R_SERVFAIL;
03888         event->qtype = fctx->type;
03889         event->db = NULL;
03890         event->node = NULL;
03891         event->rdataset = rdataset;
03892         event->sigrdataset = sigrdataset;
03893         event->fetch = fetch;
03894         event->client = client;
03895         event->id = id;
03896         dns_fixedname_init(&event->foundname);
03897 
03898         /*
03899          * Make sure that we can store the sigrdataset in the
03900          * first event if it is needed by any of the events.
03901          */
03902         if (event->sigrdataset != NULL)
03903                 ISC_LIST_PREPEND(fctx->events, event, ev_link);
03904         else
03905                 ISC_LIST_APPEND(fctx->events, event, ev_link);
03906         fctx->references++;
03907         fctx->client = client;
03908 
03909         fetch->magic = DNS_FETCH_MAGIC;
03910         fetch->private = fctx;
03911 
03912         return (ISC_R_SUCCESS);
03913 }
03914 
03915 static inline void
03916 log_ns_ttl(fetchctx_t *fctx, const char *where) {
03917         char namebuf[DNS_NAME_FORMATSIZE];
03918         char domainbuf[DNS_NAME_FORMATSIZE];
03919 
03920         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
03921         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
03922         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
03923                       DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
03924                       "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
03925                       fctx, where, namebuf, domainbuf,
03926                       fctx->ns_ttl_ok, fctx->ns_ttl);
03927 }
03928 
03929 static isc_result_t
03930 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
03931             dns_name_t *domain, dns_rdataset_t *nameservers,
03932             unsigned int options, unsigned int bucketnum, unsigned int depth,
03933             isc_counter_t *qc, fetchctx_t **fctxp)
03934 {
03935         fetchctx_t *fctx;
03936         isc_result_t result;
03937         isc_result_t iresult;
03938         isc_interval_t interval;
03939         dns_fixedname_t fixed;
03940         unsigned int findoptions = 0;
03941         char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
03942         char typebuf[DNS_RDATATYPE_FORMATSIZE];
03943         isc_mem_t *mctx;
03944 
03945         /*
03946          * Caller must be holding the lock for bucket number 'bucketnum'.
03947          */
03948         REQUIRE(fctxp != NULL && *fctxp == NULL);
03949 
03950         mctx = res->buckets[bucketnum].mctx;
03951         fctx = isc_mem_get(mctx, sizeof(*fctx));
03952         if (fctx == NULL)
03953                 return (ISC_R_NOMEMORY);
03954 
03955         fctx->qc = NULL;
03956         if (qc != NULL) {
03957                 isc_counter_attach(qc, &fctx->qc);
03958         } else {
03959                 result = isc_counter_create(res->mctx,
03960                                             res->maxqueries, &fctx->qc);
03961                 if (result != ISC_R_SUCCESS)
03962                         goto cleanup_fetch;
03963         }
03964 
03965         /*
03966          * Make fctx->info point to a copy of a formatted string
03967          * "name/type".
03968          */
03969         dns_name_format(name, buf, sizeof(buf));
03970         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
03971         strcat(buf, "/");       /* checked */
03972         strcat(buf, typebuf);   /* checked */
03973         fctx->info = isc_mem_strdup(mctx, buf);
03974         if (fctx->info == NULL) {
03975                 result = ISC_R_NOMEMORY;
03976                 goto cleanup_counter;
03977         }
03978 
03979         FCTXTRACE("create");
03980         dns_name_init(&fctx->name, NULL);
03981         result = dns_name_dup(name, mctx, &fctx->name);
03982         if (result != ISC_R_SUCCESS)
03983                 goto cleanup_info;
03984         dns_name_init(&fctx->domain, NULL);
03985         dns_rdataset_init(&fctx->nameservers);
03986 
03987         fctx->type = type;
03988         fctx->options = options;
03989         /*
03990          * Note!  We do not attach to the task.  We are relying on the
03991          * resolver to ensure that this task doesn't go away while we are
03992          * using it.
03993          */
03994         fctx->res = res;
03995         fctx->references = 0;
03996         fctx->bucketnum = bucketnum;
03997         fctx->state = fetchstate_init;
03998         fctx->want_shutdown = ISC_FALSE;
03999         fctx->cloned = ISC_FALSE;
04000         fctx->depth = depth;
04001         ISC_LIST_INIT(fctx->queries);
04002         ISC_LIST_INIT(fctx->finds);
04003         ISC_LIST_INIT(fctx->altfinds);
04004         ISC_LIST_INIT(fctx->forwaddrs);
04005         ISC_LIST_INIT(fctx->altaddrs);
04006         ISC_LIST_INIT(fctx->forwarders);
04007         fctx->fwdpolicy = dns_fwdpolicy_none;
04008         ISC_LIST_INIT(fctx->bad);
04009         ISC_LIST_INIT(fctx->edns);
04010         ISC_LIST_INIT(fctx->edns512);
04011         ISC_LIST_INIT(fctx->bad_edns);
04012         ISC_LIST_INIT(fctx->validators);
04013         fctx->validator = NULL;
04014         fctx->find = NULL;
04015         fctx->altfind = NULL;
04016         fctx->pending = 0;
04017         fctx->restarts = 0;
04018         fctx->querysent = 0;
04019         fctx->referrals = 0;
04020         TIME_NOW(&fctx->start);
04021         fctx->timeouts = 0;
04022         fctx->lamecount = 0;
04023         fctx->adberr = 0;
04024         fctx->neterr = 0;
04025         fctx->badresp = 0;
04026         fctx->findfail = 0;
04027         fctx->valfail = 0;
04028         fctx->result = ISC_R_FAILURE;
04029         fctx->vresult = ISC_R_SUCCESS;
04030         fctx->exitline = -1;    /* sentinel */
04031         fctx->logged = ISC_FALSE;
04032         fctx->attributes = 0;
04033         fctx->spilled = ISC_FALSE;
04034         fctx->nqueries = 0;
04035         fctx->reason = NULL;
04036         fctx->rand_buf = 0;
04037         fctx->rand_bits = 0;
04038         fctx->timeout = ISC_FALSE;
04039         fctx->addrinfo = NULL;
04040         fctx->client = NULL;
04041         fctx->ns_ttl = 0;
04042         fctx->ns_ttl_ok = ISC_FALSE;
04043 
04044         dns_name_init(&fctx->nsname, NULL);
04045         fctx->nsfetch = NULL;
04046         dns_rdataset_init(&fctx->nsrrset);
04047 
04048         if (domain == NULL) {
04049                 dns_forwarders_t *forwarders = NULL;
04050                 unsigned int labels;
04051                 dns_name_t *fwdname = name;
04052                 dns_name_t suffix;
04053 
04054                 /*
04055                  * DS records are found in the parent server. Strip one
04056                  * leading label from the name (to be used in finding
04057                  * the forwarder).
04058                  */
04059                 if (dns_rdatatype_atparent(fctx->type) &&
04060                     dns_name_countlabels(name) > 1) {
04061                         dns_name_init(&suffix, NULL);
04062                         labels = dns_name_countlabels(name);
04063                         dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
04064                         fwdname = &suffix;
04065                 }
04066 
04067                 /* Find the forwarder for this name. */
04068                 dns_fixedname_init(&fixed);
04069                 domain = dns_fixedname_name(&fixed);
04070                 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
04071                                             domain, &forwarders);
04072                 if (result == ISC_R_SUCCESS)
04073                         fctx->fwdpolicy = forwarders->fwdpolicy;
04074 
04075                 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
04076                         /*
04077                          * The caller didn't supply a query domain and
04078                          * nameservers, and we're not in forward-only mode,
04079                          * so find the best nameservers to use.
04080                          */
04081                         if (dns_rdatatype_atparent(fctx->type))
04082                                 findoptions |= DNS_DBFIND_NOEXACT;
04083                         result = dns_view_findzonecut(res->view, name,
04084                                                       domain, 0, findoptions,
04085                                                       ISC_TRUE,
04086                                                       &fctx->nameservers,
04087                                                       NULL);
04088                         if (result != ISC_R_SUCCESS)
04089                                 goto cleanup_name;
04090 
04091                         result = dns_name_dup(domain, mctx, &fctx->domain);
04092                         if (result != ISC_R_SUCCESS) {
04093                                 dns_rdataset_disassociate(&fctx->nameservers);
04094                                 goto cleanup_name;
04095                         }
04096                         fctx->ns_ttl = fctx->nameservers.ttl;
04097                         fctx->ns_ttl_ok = ISC_TRUE;
04098                 } else {
04099                         /*
04100                          * We're in forward-only mode.  Set the query domain.
04101                          */
04102                         result = dns_name_dup(domain, mctx, &fctx->domain);
04103                         if (result != ISC_R_SUCCESS)
04104                                 goto cleanup_name;
04105                 }
04106         } else {
04107                 result = dns_name_dup(domain, mctx, &fctx->domain);
04108                 if (result != ISC_R_SUCCESS)
04109                         goto cleanup_name;
04110                 dns_rdataset_clone(nameservers, &fctx->nameservers);
04111                 fctx->ns_ttl = fctx->nameservers.ttl;
04112                 fctx->ns_ttl_ok = ISC_TRUE;
04113         }
04114 
04115         log_ns_ttl(fctx, "fctx_create");
04116 
04117         INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
04118 
04119         fctx->qmessage = NULL;
04120         result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
04121                                     &fctx->qmessage);
04122 
04123         if (result != ISC_R_SUCCESS)
04124                 goto cleanup_domain;
04125 
04126         fctx->rmessage = NULL;
04127         result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
04128                                     &fctx->rmessage);
04129 
04130         if (result != ISC_R_SUCCESS)
04131                 goto cleanup_qmessage;
04132 
04133         /*
04134          * Compute an expiration time for the entire fetch.
04135          */
04136         isc_interval_set(&interval, res->query_timeout, 0);
04137         iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
04138         if (iresult != ISC_R_SUCCESS) {
04139                 UNEXPECTED_ERROR(__FILE__, __LINE__,
04140                                  "isc_time_nowplusinterval: %s",
04141                                  isc_result_totext(iresult));
04142                 result = ISC_R_UNEXPECTED;
04143                 goto cleanup_rmessage;
04144         }
04145 
04146         /*
04147          * Default retry interval initialization.  We set the interval now
04148          * mostly so it won't be uninitialized.  It will be set to the
04149          * correct value before a query is issued.
04150          */
04151         isc_interval_set(&fctx->interval, 2, 0);
04152 
04153         /*
04154          * Create an inactive timer.  It will be made active when the fetch
04155          * is actually started.
04156          */
04157         fctx->timer = NULL;
04158         iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
04159                                    NULL, NULL,
04160                                    res->buckets[bucketnum].task, fctx_timeout,
04161                                    fctx, &fctx->timer);
04162         if (iresult != ISC_R_SUCCESS) {
04163                 UNEXPECTED_ERROR(__FILE__, __LINE__,
04164                                  "isc_timer_create: %s",
04165                                  isc_result_totext(iresult));
04166                 result = ISC_R_UNEXPECTED;
04167                 goto cleanup_rmessage;
04168         }
04169 
04170         /*
04171          * Attach to the view's cache and adb.
04172          */
04173         fctx->cache = NULL;
04174         dns_db_attach(res->view->cachedb, &fctx->cache);
04175         fctx->adb = NULL;
04176         dns_adb_attach(res->view->adb, &fctx->adb);
04177         fctx->mctx = NULL;
04178         isc_mem_attach(mctx, &fctx->mctx);
04179 
04180         ISC_LIST_INIT(fctx->events);
04181         ISC_LINK_INIT(fctx, link);
04182         fctx->magic = FCTX_MAGIC;
04183 
04184         ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
04185 
04186         LOCK(&res->nlock);
04187         res->nfctx++;
04188         UNLOCK(&res->nlock);
04189         inc_stats(res, dns_resstatscounter_nfetch);
04190 
04191         *fctxp = fctx;
04192 
04193         return (ISC_R_SUCCESS);
04194 
04195  cleanup_rmessage:
04196         dns_message_destroy(&fctx->rmessage);
04197 
04198  cleanup_qmessage:
04199         dns_message_destroy(&fctx->qmessage);
04200 
04201  cleanup_domain:
04202         if (dns_name_countlabels(&fctx->domain) > 0)
04203                 dns_name_free(&fctx->domain, mctx);
04204         if (dns_rdataset_isassociated(&fctx->nameservers))
04205                 dns_rdataset_disassociate(&fctx->nameservers);
04206 
04207  cleanup_name:
04208         dns_name_free(&fctx->name, mctx);
04209 
04210  cleanup_info:
04211         isc_mem_free(mctx, fctx->info);
04212 
04213  cleanup_counter:
04214         isc_counter_detach(&fctx->qc);
04215 
04216  cleanup_fetch:
04217         isc_mem_put(mctx, fctx, sizeof(*fctx));
04218 
04219         return (result);
04220 }
04221 
04222 /*
04223  * Handle Responses
04224  */
04225 static inline isc_boolean_t
04226 is_lame(fetchctx_t *fctx) {
04227         dns_message_t *message = fctx->rmessage;
04228         dns_name_t *name;
04229         dns_rdataset_t *rdataset;
04230         isc_result_t result;
04231 
04232         if (message->rcode != dns_rcode_noerror &&
04233             message->rcode != dns_rcode_nxdomain)
04234                 return (ISC_FALSE);
04235 
04236         if (message->counts[DNS_SECTION_ANSWER] != 0)
04237                 return (ISC_FALSE);
04238 
04239         if (message->counts[DNS_SECTION_AUTHORITY] == 0)
04240                 return (ISC_FALSE);
04241 
04242         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
04243         while (result == ISC_R_SUCCESS) {
04244                 name = NULL;
04245                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
04246                 for (rdataset = ISC_LIST_HEAD(name->list);
04247                      rdataset != NULL;
04248                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
04249                         dns_namereln_t namereln;
04250                         int order;
04251                         unsigned int labels;
04252                         if (rdataset->type != dns_rdatatype_ns)
04253                                 continue;
04254                         namereln = dns_name_fullcompare(name, &fctx->domain,
04255                                                         &order, &labels);
04256                         if (namereln == dns_namereln_equal &&
04257                             (message->flags & DNS_MESSAGEFLAG_AA) != 0)
04258                                 return (ISC_FALSE);
04259                         if (namereln == dns_namereln_subdomain)
04260                                 return (ISC_FALSE);
04261                         return (ISC_TRUE);
04262                 }
04263                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
04264         }
04265 
04266         return (ISC_FALSE);
04267 }
04268 
04269 static inline void
04270 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
04271         char namebuf[DNS_NAME_FORMATSIZE];
04272         char domainbuf[DNS_NAME_FORMATSIZE];
04273         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
04274 
04275         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
04276         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
04277         isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
04278         isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
04279                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
04280                       "lame server resolving '%s' (in '%s'?): %s",
04281                       namebuf, domainbuf, addrbuf);
04282 }
04283 
04284 static inline void
04285 log_formerr(fetchctx_t *fctx, const char *format, ...) {
04286         char nsbuf[ISC_SOCKADDR_FORMATSIZE];
04287         char clbuf[ISC_SOCKADDR_FORMATSIZE];
04288         const char *clmsg = "";
04289         char msgbuf[2048];
04290         va_list args;
04291 
04292         va_start(args, format);
04293         vsnprintf(msgbuf, sizeof(msgbuf), format, args);
04294         va_end(args);
04295 
04296         isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
04297 
04298         if (fctx->client != NULL) {
04299                 clmsg = " for client ";
04300                 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
04301         } else {
04302                 clbuf[0] = '\0';
04303         }
04304 
04305         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
04306                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
04307                       "DNS format error from %s resolving %s%s%s: %s",
04308                       nsbuf, fctx->info, clmsg, clbuf, msgbuf);
04309 }
04310 
04311 static inline isc_result_t
04312 same_question(fetchctx_t *fctx) {
04313         isc_result_t result;
04314         dns_message_t *message = fctx->rmessage;
04315         dns_name_t *name;
04316         dns_rdataset_t *rdataset;
04317 
04318         /*
04319          * Caller must be holding the fctx lock.
04320          */
04321 
04322         /*
04323          * XXXRTH  Currently we support only one question.
04324          */
04325         if (message->counts[DNS_SECTION_QUESTION] != 1) {
04326                 log_formerr(fctx, "too many questions");
04327                 return (DNS_R_FORMERR);
04328         }
04329 
04330         result = dns_message_firstname(message, DNS_SECTION_QUESTION);
04331         if (result != ISC_R_SUCCESS)
04332                 return (result);
04333         name = NULL;
04334         dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
04335         rdataset = ISC_LIST_HEAD(name->list);
04336         INSIST(rdataset != NULL);
04337         INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
04338 
04339         if (fctx->type != rdataset->type ||
04340             fctx->res->rdclass != rdataset->rdclass ||
04341             !dns_name_equal(&fctx->name, name)) {
04342                 char namebuf[DNS_NAME_FORMATSIZE];
04343                 char class[DNS_RDATACLASS_FORMATSIZE];
04344                 char type[DNS_RDATATYPE_FORMATSIZE];
04345 
04346                 dns_name_format(name, namebuf, sizeof(namebuf));
04347                 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
04348                 dns_rdatatype_format(rdataset->type, type, sizeof(type));
04349                 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
04350                             namebuf, class, type);
04351                 return (DNS_R_FORMERR);
04352         }
04353 
04354         return (ISC_R_SUCCESS);
04355 }
04356 
04357 static void
04358 clone_results(fetchctx_t *fctx) {
04359         dns_fetchevent_t *event, *hevent;
04360         isc_result_t result;
04361         dns_name_t *name, *hname;
04362 
04363         FCTXTRACE("clone_results");
04364 
04365         /*
04366          * Set up any other events to have the same data as the first
04367          * event.
04368          *
04369          * Caller must be holding the appropriate lock.
04370          */
04371 
04372         fctx->cloned = ISC_TRUE;
04373         hevent = ISC_LIST_HEAD(fctx->events);
04374         if (hevent == NULL)
04375                 return;
04376         hname = dns_fixedname_name(&hevent->foundname);
04377         for (event = ISC_LIST_NEXT(hevent, ev_link);
04378              event != NULL;
04379              event = ISC_LIST_NEXT(event, ev_link)) {
04380                 name = dns_fixedname_name(&event->foundname);
04381                 result = dns_name_copy(hname, name, NULL);
04382                 if (result != ISC_R_SUCCESS)
04383                         event->result = result;
04384                 else
04385                         event->result = hevent->result;
04386                 dns_db_attach(hevent->db, &event->db);
04387                 dns_db_attachnode(hevent->db, hevent->node, &event->node);
04388                 INSIST(hevent->rdataset != NULL);
04389                 INSIST(event->rdataset != NULL);
04390                 if (dns_rdataset_isassociated(hevent->rdataset))
04391                         dns_rdataset_clone(hevent->rdataset, event->rdataset);
04392                 INSIST(! (hevent->sigrdataset == NULL &&
04393                           event->sigrdataset != NULL));
04394                 if (hevent->sigrdataset != NULL &&
04395                     dns_rdataset_isassociated(hevent->sigrdataset) &&
04396                     event->sigrdataset != NULL)
04397                         dns_rdataset_clone(hevent->sigrdataset,
04398                                            event->sigrdataset);
04399         }
04400 }
04401 
04402 #define CACHE(r)        (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
04403 #define ANSWER(r)       (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
04404 #define ANSWERSIG(r)    (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
04405 #define EXTERNAL(r)     (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
04406 #define CHAINING(r)     (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
04407 #define CHASE(r)        (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
04408 #define CHECKNAMES(r)   (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
04409 
04410 
04411 /*
04412  * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
04413  * no references and is no longer waiting for any events).
04414  *
04415  * Requires:
04416  *      '*fctx' is shutting down.
04417  *
04418  * Returns:
04419  *      true if the resolver is exiting and this is the last fctx in the bucket.
04420  */
04421 static isc_boolean_t
04422 maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
04423         unsigned int bucketnum;
04424         isc_boolean_t bucket_empty = ISC_FALSE;
04425         dns_resolver_t *res = fctx->res;
04426         dns_validator_t *validator, *next_validator;
04427         isc_boolean_t dodestroy = ISC_FALSE;
04428 
04429         REQUIRE(SHUTTINGDOWN(fctx));
04430 
04431         bucketnum = fctx->bucketnum;
04432         if (!locked)
04433                 LOCK(&res->buckets[bucketnum].lock);
04434         if (fctx->pending != 0 || fctx->nqueries != 0)
04435                 goto unlock;
04436 
04437         for (validator = ISC_LIST_HEAD(fctx->validators);
04438              validator != NULL; validator = next_validator) {
04439                 next_validator = ISC_LIST_NEXT(validator, link);
04440                 dns_validator_cancel(validator);
04441         }
04442 
04443         if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
04444                 bucket_empty = fctx_unlink(fctx);
04445                 dodestroy = ISC_TRUE;
04446         }
04447  unlock:
04448         if (!locked)
04449                 UNLOCK(&res->buckets[bucketnum].lock);
04450         if (dodestroy)
04451                 fctx_destroy(fctx);
04452         return (bucket_empty);
04453 }
04454 
04455 /*
04456  * The validator has finished.
04457  */
04458 static void
04459 validated(isc_task_t *task, isc_event_t *event) {
04460         dns_adbaddrinfo_t *addrinfo;
04461         dns_dbnode_t *node = NULL;
04462         dns_dbnode_t *nsnode = NULL;
04463         dns_fetchevent_t *hevent;
04464         dns_name_t *name;
04465         dns_rdataset_t *ardataset = NULL;
04466         dns_rdataset_t *asigrdataset = NULL;
04467         dns_rdataset_t *rdataset;
04468         dns_rdataset_t *sigrdataset;
04469         dns_resolver_t *res;
04470         dns_valarg_t *valarg;
04471         dns_validatorevent_t *vevent;
04472         fetchctx_t *fctx;
04473         isc_boolean_t chaining;
04474         isc_boolean_t negative;
04475         isc_boolean_t sentresponse;
04476         isc_result_t eresult = ISC_R_SUCCESS;
04477         isc_result_t result = ISC_R_SUCCESS;
04478         isc_stdtime_t now;
04479         isc_uint32_t ttl;
04480         unsigned options;
04481         isc_uint32_t bucketnum;
04482 
04483         UNUSED(task); /* for now */
04484 
04485         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
04486         valarg = event->ev_arg;
04487         fctx = valarg->fctx;
04488         res = fctx->res;
04489         addrinfo = valarg->addrinfo;
04490         REQUIRE(VALID_FCTX(fctx));
04491         REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
04492 
04493         vevent = (dns_validatorevent_t *)event;
04494         fctx->vresult = vevent->result;
04495 
04496         FCTXTRACE("received validation completion event");
04497 
04498         bucketnum = fctx->bucketnum;
04499         LOCK(&res->buckets[bucketnum].lock);
04500 
04501         ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
04502         fctx->validator = NULL;
04503 
04504         /*
04505          * Destroy the validator early so that we can
04506          * destroy the fctx if necessary.
04507          */
04508         dns_validator_destroy(&vevent->validator);
04509         isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
04510 
04511         negative = ISC_TF(vevent->rdataset == NULL);
04512 
04513         sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
04514 
04515         /*
04516          * If shutting down, ignore the results.  Check to see if we're
04517          * done waiting for validator completions and ADB pending events; if
04518          * so, destroy the fctx.
04519          */
04520         if (SHUTTINGDOWN(fctx) && !sentresponse) {
04521                 isc_boolean_t bucket_empty;
04522                 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
04523                 UNLOCK(&res->buckets[bucketnum].lock);
04524                 if (bucket_empty)
04525                         empty_bucket(res);
04526                 goto cleanup_event;
04527         }
04528 
04529         isc_stdtime_get(&now);
04530 
04531         /*
04532          * If chaining, we need to make sure that the right result code is
04533          * returned, and that the rdatasets are bound.
04534          */
04535         if (vevent->result == ISC_R_SUCCESS &&
04536             !negative &&
04537             vevent->rdataset != NULL &&
04538             CHAINING(vevent->rdataset))
04539         {
04540                 if (vevent->rdataset->type == dns_rdatatype_cname)
04541                         eresult = DNS_R_CNAME;
04542                 else {
04543                         INSIST(vevent->rdataset->type == dns_rdatatype_dname);
04544                         eresult = DNS_R_DNAME;
04545                 }
04546                 chaining = ISC_TRUE;
04547         } else
04548                 chaining = ISC_FALSE;
04549 
04550         /*
04551          * Either we're not shutting down, or we are shutting down but want
04552          * to cache the result anyway (if this was a validation started by
04553          * a query with cd set)
04554          */
04555 
04556         hevent = ISC_LIST_HEAD(fctx->events);
04557         if (hevent != NULL) {
04558                 if (!negative && !chaining &&
04559                     (fctx->type == dns_rdatatype_any ||
04560                      fctx->type == dns_rdatatype_rrsig ||
04561                      fctx->type == dns_rdatatype_sig)) {
04562                         /*
04563                          * Don't bind rdatasets; the caller
04564                          * will iterate the node.
04565                          */
04566                 } else {
04567                         ardataset = hevent->rdataset;
04568                         asigrdataset = hevent->sigrdataset;
04569                 }
04570         }
04571 
04572         if (vevent->result != ISC_R_SUCCESS) {
04573                 FCTXTRACE("validation failed");
04574                 inc_stats(res, dns_resstatscounter_valfail);
04575                 fctx->valfail++;
04576                 fctx->vresult = vevent->result;
04577                 if (fctx->vresult != DNS_R_BROKENCHAIN) {
04578                         result = ISC_R_NOTFOUND;
04579                         if (vevent->rdataset != NULL)
04580                                 result = dns_db_findnode(fctx->cache,
04581                                                          vevent->name,
04582                                                          ISC_TRUE, &node);
04583                         if (result == ISC_R_SUCCESS)
04584                                 (void)dns_db_deleterdataset(fctx->cache, node,
04585                                                              NULL,
04586                                                             vevent->type, 0);
04587                         if (result == ISC_R_SUCCESS &&
04588                              vevent->sigrdataset != NULL)
04589                                 (void)dns_db_deleterdataset(fctx->cache, node,
04590                                                             NULL,
04591                                                             dns_rdatatype_rrsig,
04592                                                             vevent->type);
04593                         if (result == ISC_R_SUCCESS)
04594                                 dns_db_detachnode(fctx->cache, &node);
04595                 }
04596                 if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
04597                         /*
04598                          * Cache the data as pending for later validation.
04599                          */
04600                         result = ISC_R_NOTFOUND;
04601                         if (vevent->rdataset != NULL)
04602                                 result = dns_db_findnode(fctx->cache,
04603                                                          vevent->name,
04604                                                          ISC_TRUE, &node);
04605                         if (result == ISC_R_SUCCESS) {
04606                                 (void)dns_db_addrdataset(fctx->cache, node,
04607                                                          NULL, now,
04608                                                          vevent->rdataset, 0,
04609                                                          NULL);
04610                         }
04611                         if (result == ISC_R_SUCCESS &&
04612                             vevent->sigrdataset != NULL)
04613                                 (void)dns_db_addrdataset(fctx->cache, node,
04614                                                          NULL, now,
04615                                                          vevent->sigrdataset,
04616                                                          0, NULL);
04617                         if (result == ISC_R_SUCCESS)
04618                                 dns_db_detachnode(fctx->cache, &node);
04619                 }
04620                 result = fctx->vresult;
04621                 add_bad(fctx, addrinfo, result, badns_validation);
04622                 isc_event_free(&event);
04623                 UNLOCK(&res->buckets[bucketnum].lock);
04624                 INSIST(fctx->validator == NULL);
04625                 fctx->validator = ISC_LIST_HEAD(fctx->validators);
04626                 if (fctx->validator != NULL)
04627                         dns_validator_send(fctx->validator);
04628                 else if (sentresponse)
04629                         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
04630                 else if (result == DNS_R_BROKENCHAIN) {
04631                         isc_result_t tresult;
04632                         isc_time_t expire;
04633                         isc_interval_t i;
04634 
04635                         isc_interval_set(&i, DNS_RESOLVER_BADCACHETTL(fctx), 0);
04636                         tresult = isc_time_nowplusinterval(&expire, &i);
04637                         if (negative &&
04638                             (fctx->type == dns_rdatatype_dnskey ||
04639                              fctx->type == dns_rdatatype_dlv ||
04640                              fctx->type == dns_rdatatype_ds) &&
04641                              tresult == ISC_R_SUCCESS)
04642                                 dns_resolver_addbadcache(res, &fctx->name,
04643                                                          fctx->type, &expire);
04644                         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
04645                 } else
04646                         fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
04647                 return;
04648         }
04649 
04650 
04651         if (negative) {
04652                 dns_rdatatype_t covers;
04653                 FCTXTRACE("nonexistence validation OK");
04654 
04655                 inc_stats(res, dns_resstatscounter_valnegsuccess);
04656 
04657                 /*
04658                  * Cache DS NXDOMAIN seperately to other types.
04659                  */
04660                 if (fctx->rmessage->rcode == dns_rcode_nxdomain &&
04661                     fctx->type != dns_rdatatype_ds)
04662                         covers = dns_rdatatype_any;
04663                 else
04664                         covers = fctx->type;
04665 
04666                 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
04667                                          &node);
04668                 if (result != ISC_R_SUCCESS)
04669                         goto noanswer_response;
04670 
04671                 /*
04672                  * If we are asking for a SOA record set the cache time
04673                  * to zero to facilitate locating the containing zone of
04674                  * a arbitrary zone.
04675                  */
04676                 ttl = res->view->maxncachettl;
04677                 if (fctx->type == dns_rdatatype_soa &&
04678                     covers == dns_rdatatype_any && res->zero_no_soa_ttl)
04679                         ttl = 0;
04680 
04681                 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
04682                                            covers, now, ttl, vevent->optout,
04683                                            vevent->secure, ardataset, &eresult);
04684                 if (result != ISC_R_SUCCESS)
04685                         goto noanswer_response;
04686                 goto answer_response;
04687         } else
04688                 inc_stats(res, dns_resstatscounter_valsuccess);
04689 
04690         FCTXTRACE("validation OK");
04691 
04692         if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
04693                 result = dns_rdataset_addnoqname(vevent->rdataset,
04694                                    vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
04695                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04696                 INSIST(vevent->sigrdataset != NULL);
04697                 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
04698                 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
04699                         result = dns_rdataset_addclosest(vevent->rdataset,
04700                                  vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
04701                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
04702                 }
04703         } else if (vevent->rdataset->trust == dns_trust_answer &&
04704                    vevent->rdataset->type != dns_rdatatype_rrsig)
04705         {
04706                 isc_result_t tresult;
04707                 dns_name_t *noqname = NULL;
04708                 tresult = findnoqname(fctx, vevent->name,
04709                                       vevent->rdataset->type, &noqname);
04710                 if (tresult == ISC_R_SUCCESS && noqname != NULL) {
04711                         tresult = dns_rdataset_addnoqname(vevent->rdataset,
04712                                                           noqname);
04713                         RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
04714                 }
04715         }
04716 
04717         /*
04718          * The data was already cached as pending data.
04719          * Re-cache it as secure and bind the cached
04720          * rdatasets to the first event on the fetch
04721          * event list.
04722          */
04723         result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
04724         if (result != ISC_R_SUCCESS)
04725                 goto noanswer_response;
04726 
04727         options = 0;
04728         if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
04729                 options = DNS_DBADD_PREFETCH;
04730         result = dns_db_addrdataset(fctx->cache, node, NULL, now,
04731                                     vevent->rdataset, options, ardataset);
04732         if (result != ISC_R_SUCCESS &&
04733             result != DNS_R_UNCHANGED)
04734                 goto noanswer_response;
04735         if (ardataset != NULL && NEGATIVE(ardataset)) {
04736                 if (NXDOMAIN(ardataset))
04737                         eresult = DNS_R_NCACHENXDOMAIN;
04738                 else
04739                         eresult = DNS_R_NCACHENXRRSET;
04740         } else if (vevent->sigrdataset != NULL) {
04741                 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
04742                                             vevent->sigrdataset, 0,
04743                                             asigrdataset);
04744                 if (result != ISC_R_SUCCESS &&
04745                     result != DNS_R_UNCHANGED)
04746                         goto noanswer_response;
04747         }
04748 
04749         if (sentresponse) {
04750                 isc_boolean_t bucket_empty = ISC_FALSE;
04751                 /*
04752                  * If we only deferred the destroy because we wanted to cache
04753                  * the data, destroy now.
04754                  */
04755                 dns_db_detachnode(fctx->cache, &node);
04756                 if (SHUTTINGDOWN(fctx))
04757                         bucket_empty = maybe_destroy(fctx, ISC_TRUE);
04758                 UNLOCK(&res->buckets[bucketnum].lock);
04759                 if (bucket_empty)
04760                         empty_bucket(res);
04761                 goto cleanup_event;
04762         }
04763 
04764         if (!ISC_LIST_EMPTY(fctx->validators)) {
04765                 INSIST(!negative);
04766                 INSIST(fctx->type == dns_rdatatype_any ||
04767                        fctx->type == dns_rdatatype_rrsig ||
04768                        fctx->type == dns_rdatatype_sig);
04769                 /*
04770                  * Don't send a response yet - we have
04771                  * more rdatasets that still need to
04772                  * be validated.
04773                  */
04774                 dns_db_detachnode(fctx->cache, &node);
04775                 UNLOCK(&res->buckets[bucketnum].lock);
04776                 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
04777                 goto cleanup_event;
04778         }
04779 
04780  answer_response:
04781         /*
04782          * Cache any NS/NSEC records that happened to be validated.
04783          */
04784         result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
04785         while (result == ISC_R_SUCCESS) {
04786                 name = NULL;
04787                 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
04788                                         &name);
04789                 for (rdataset = ISC_LIST_HEAD(name->list);
04790                      rdataset != NULL;
04791                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
04792                         if ((rdataset->type != dns_rdatatype_ns &&
04793                              rdataset->type != dns_rdatatype_nsec) ||
04794                             rdataset->trust != dns_trust_secure)
04795                                 continue;
04796                         for (sigrdataset = ISC_LIST_HEAD(name->list);
04797                              sigrdataset != NULL;
04798                              sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04799                                 if (sigrdataset->type != dns_rdatatype_rrsig ||
04800                                     sigrdataset->covers != rdataset->type)
04801                                         continue;
04802                                 break;
04803                         }
04804                         if (sigrdataset == NULL ||
04805                             sigrdataset->trust != dns_trust_secure)
04806                                 continue;
04807                         result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
04808                                                  &nsnode);
04809                         if (result != ISC_R_SUCCESS)
04810                                 continue;
04811 
04812                         result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
04813                                                     now, rdataset, 0, NULL);
04814                         if (result == ISC_R_SUCCESS)
04815                                 result = dns_db_addrdataset(fctx->cache, nsnode,
04816                                                             NULL, now,
04817                                                             sigrdataset, 0,
04818                                                             NULL);
04819                         dns_db_detachnode(fctx->cache, &nsnode);
04820                         if (result != ISC_R_SUCCESS)
04821                                 continue;
04822                 }
04823                 result = dns_message_nextname(fctx->rmessage,
04824                                               DNS_SECTION_AUTHORITY);
04825         }
04826 
04827         result = ISC_R_SUCCESS;
04828 
04829         /*
04830          * Respond with an answer, positive or negative,
04831          * as opposed to an error.  'node' must be non-NULL.
04832          */
04833 
04834         fctx->attributes |= FCTX_ATTR_HAVEANSWER;
04835 
04836         if (hevent != NULL) {
04837                 /*
04838                  * Negative results must be indicated in event->result.
04839                  */
04840                 if (dns_rdataset_isassociated(hevent->rdataset) &&
04841                     NEGATIVE(hevent->rdataset)) {
04842                         INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
04843                                eresult == DNS_R_NCACHENXRRSET);
04844                 }
04845                 hevent->result = eresult;
04846                 RUNTIME_CHECK(dns_name_copy(vevent->name,
04847                               dns_fixedname_name(&hevent->foundname), NULL)
04848                               == ISC_R_SUCCESS);
04849                 dns_db_attach(fctx->cache, &hevent->db);
04850                 dns_db_transfernode(fctx->cache, &node, &hevent->node);
04851                 clone_results(fctx);
04852         }
04853 
04854  noanswer_response:
04855         if (node != NULL)
04856                 dns_db_detachnode(fctx->cache, &node);
04857 
04858         UNLOCK(&res->buckets[bucketnum].lock);
04859         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
04860 
04861  cleanup_event:
04862         INSIST(node == NULL);
04863         isc_event_free(&event);
04864 }
04865 
04866 static void
04867 fctx_log(void *arg, int level, const char *fmt, ...) {
04868         char msgbuf[2048];
04869         va_list args;
04870         fetchctx_t *fctx = arg;
04871 
04872         va_start(args, fmt);
04873         vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
04874         va_end(args);
04875 
04876         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
04877                       DNS_LOGMODULE_RESOLVER, level,
04878                       "fctx %p(%s): %s", fctx, fctx->info, msgbuf);
04879 }
04880 
04881 static inline isc_result_t
04882 findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
04883             dns_name_t **noqnamep)
04884 {
04885         dns_rdataset_t *nrdataset, *next, *sigrdataset;
04886         dns_rdata_rrsig_t rrsig;
04887         isc_result_t result;
04888         unsigned int labels;
04889         dns_section_t section;
04890         dns_name_t *zonename;
04891         dns_fixedname_t fzonename;
04892         dns_name_t *closest;
04893         dns_fixedname_t fclosest;
04894         dns_name_t *nearest;
04895         dns_fixedname_t fnearest;
04896         dns_rdatatype_t found = dns_rdatatype_none;
04897         dns_name_t *noqname = NULL;
04898 
04899         FCTXTRACE("findnoqname");
04900 
04901         REQUIRE(noqnamep != NULL && *noqnamep == NULL);
04902 
04903         /*
04904          * Find the SIG for this rdataset, if we have it.
04905          */
04906         for (sigrdataset = ISC_LIST_HEAD(name->list);
04907              sigrdataset != NULL;
04908              sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04909                 if (sigrdataset->type == dns_rdatatype_rrsig &&
04910                     sigrdataset->covers == type)
04911                         break;
04912         }
04913 
04914         if (sigrdataset == NULL)
04915                 return (ISC_R_NOTFOUND);
04916 
04917         labels = dns_name_countlabels(name);
04918 
04919         for (result = dns_rdataset_first(sigrdataset);
04920              result == ISC_R_SUCCESS;
04921              result = dns_rdataset_next(sigrdataset)) {
04922                 dns_rdata_t rdata = DNS_RDATA_INIT;
04923                 dns_rdataset_current(sigrdataset, &rdata);
04924                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
04925                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04926                 /* Wildcard has rrsig.labels < labels - 1. */
04927                 if (rrsig.labels + 1U >= labels)
04928                         continue;
04929                 break;
04930         }
04931 
04932         if (result == ISC_R_NOMORE)
04933                 return (ISC_R_NOTFOUND);
04934         if (result != ISC_R_SUCCESS)
04935                 return (result);
04936 
04937         dns_fixedname_init(&fzonename);
04938         zonename = dns_fixedname_name(&fzonename);
04939         dns_fixedname_init(&fclosest);
04940         closest = dns_fixedname_name(&fclosest);
04941         dns_fixedname_init(&fnearest);
04942         nearest = dns_fixedname_name(&fnearest);
04943 
04944 #define NXND(x) ((x) == ISC_R_SUCCESS)
04945 
04946         section = DNS_SECTION_AUTHORITY;
04947         for (result = dns_message_firstname(fctx->rmessage, section);
04948              result == ISC_R_SUCCESS;
04949              result = dns_message_nextname(fctx->rmessage, section)) {
04950                 dns_name_t *nsec = NULL;
04951                 dns_message_currentname(fctx->rmessage, section, &nsec);
04952                 for (nrdataset = ISC_LIST_HEAD(nsec->list);
04953                       nrdataset != NULL; nrdataset = next) {
04954                         isc_boolean_t data = ISC_FALSE, exists = ISC_FALSE;
04955                         isc_boolean_t optout = ISC_FALSE, unknown = ISC_FALSE;
04956                         isc_boolean_t setclosest = ISC_FALSE;
04957                         isc_boolean_t setnearest = ISC_FALSE;
04958 
04959                         next = ISC_LIST_NEXT(nrdataset, link);
04960                         if (nrdataset->type != dns_rdatatype_nsec &&
04961                             nrdataset->type != dns_rdatatype_nsec3)
04962                                 continue;
04963 
04964                         if (nrdataset->type == dns_rdatatype_nsec &&
04965                             NXND(dns_nsec_noexistnodata(type, name, nsec,
04966                                                         nrdataset, &exists,
04967                                                         &data, NULL, fctx_log,
04968                                                         fctx)))
04969                         {
04970                                 if (!exists) {
04971                                         noqname = nsec;
04972                                         found = dns_rdatatype_nsec;
04973                                 }
04974                         }
04975 
04976                         if (nrdataset->type == dns_rdatatype_nsec3 &&
04977                             NXND(dns_nsec3_noexistnodata(type, name, nsec,
04978                                                          nrdataset, zonename,
04979                                                          &exists, &data,
04980                                                          &optout, &unknown,
04981                                                          &setclosest,
04982                                                          &setnearest,
04983                                                          closest, nearest,
04984                                                          fctx_log, fctx)))
04985                         {
04986                                 if (!exists && setnearest) {
04987                                         noqname = nsec;
04988                                         found = dns_rdatatype_nsec3;
04989                                 }
04990                         }
04991                 }
04992         }
04993         if (result == ISC_R_NOMORE)
04994                 result = ISC_R_SUCCESS;
04995         if (noqname != NULL) {
04996                 for (sigrdataset = ISC_LIST_HEAD(noqname->list);
04997                      sigrdataset != NULL;
04998                      sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
04999                         if (sigrdataset->type == dns_rdatatype_rrsig &&
05000                             sigrdataset->covers == found)
05001                                 break;
05002                 }
05003                 if (sigrdataset != NULL)
05004                         *noqnamep = noqname;
05005         }
05006         return (result);
05007 }
05008 
05009 static inline isc_result_t
05010 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
05011            isc_stdtime_t now)
05012 {
05013         dns_rdataset_t *rdataset, *sigrdataset;
05014         dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
05015         dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
05016         dns_dbnode_t *node, **anodep;
05017         dns_db_t **adbp;
05018         dns_name_t *aname;
05019         dns_resolver_t *res;
05020         isc_boolean_t need_validation, secure_domain, have_answer;
05021         isc_result_t result, eresult;
05022         dns_fetchevent_t *event;
05023         unsigned int options;
05024         isc_task_t *task;
05025         isc_boolean_t fail;
05026         unsigned int valoptions = 0;
05027         isc_boolean_t checknta = ISC_TRUE;
05028 
05029         /*
05030          * The appropriate bucket lock must be held.
05031          */
05032 
05033         res = fctx->res;
05034         need_validation = ISC_FALSE;
05035         POST(need_validation);
05036         secure_domain = ISC_FALSE;
05037         have_answer = ISC_FALSE;
05038         eresult = ISC_R_SUCCESS;
05039         task = res->buckets[fctx->bucketnum].task;
05040 
05041         /*
05042          * Is DNSSEC validation required for this name?
05043          */
05044         if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
05045                 valoptions |= DNS_VALIDATOR_NONTA;
05046                 checknta = ISC_FALSE;
05047         }
05048 
05049         if (res->view->enablevalidation) {
05050                 result = issecuredomain(res->view, name, fctx->type,
05051                                         now, checknta, &secure_domain);
05052                 if (result != ISC_R_SUCCESS)
05053                         return (result);
05054 
05055                 if (!secure_domain && res->view->dlv != NULL) {
05056                         valoptions |= DNS_VALIDATOR_DLV;
05057                         secure_domain = ISC_TRUE;
05058                 }
05059         }
05060 
05061         if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0)
05062                 valoptions |= DNS_VALIDATOR_NOCDFLAG;
05063 
05064         if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
05065                 need_validation = ISC_FALSE;
05066         else
05067                 need_validation = secure_domain;
05068 
05069         adbp = NULL;
05070         aname = NULL;
05071         anodep = NULL;
05072         ardataset = NULL;
05073         asigrdataset = NULL;
05074         event = NULL;
05075         if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
05076             !need_validation) {
05077                 have_answer = ISC_TRUE;
05078                 event = ISC_LIST_HEAD(fctx->events);
05079                 if (event != NULL) {
05080                         adbp = &event->db;
05081                         aname = dns_fixedname_name(&event->foundname);
05082                         result = dns_name_copy(name, aname, NULL);
05083                         if (result != ISC_R_SUCCESS)
05084                                 return (result);
05085                         anodep = &event->node;
05086                         /*
05087                          * If this is an ANY, SIG or RRSIG query, we're not
05088                          * going to return any rdatasets, unless we encountered
05089                          * a CNAME or DNAME as "the answer".  In this case,
05090                          * we're going to return DNS_R_CNAME or DNS_R_DNAME
05091                          * and we must set up the rdatasets.
05092                          */
05093                         if ((fctx->type != dns_rdatatype_any &&
05094                              fctx->type != dns_rdatatype_rrsig &&
05095                              fctx->type != dns_rdatatype_sig) ||
05096                             (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
05097                                 ardataset = event->rdataset;
05098                                 asigrdataset = event->sigrdataset;
05099                         }
05100                 }
05101         }
05102 
05103         /*
05104          * Find or create the cache node.
05105          */
05106         node = NULL;
05107         result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
05108         if (result != ISC_R_SUCCESS)
05109                 return (result);
05110 
05111         /*
05112          * Cache or validate each cacheable rdataset.
05113          */
05114         fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
05115         for (rdataset = ISC_LIST_HEAD(name->list);
05116              rdataset != NULL;
05117              rdataset = ISC_LIST_NEXT(rdataset, link)) {
05118                 if (!CACHE(rdataset))
05119                         continue;
05120                 if (CHECKNAMES(rdataset)) {
05121                         char namebuf[DNS_NAME_FORMATSIZE];
05122                         char typebuf[DNS_RDATATYPE_FORMATSIZE];
05123                         char classbuf[DNS_RDATATYPE_FORMATSIZE];
05124 
05125                         dns_name_format(name, namebuf, sizeof(namebuf));
05126                         dns_rdatatype_format(rdataset->type, typebuf,
05127                                              sizeof(typebuf));
05128                         dns_rdataclass_format(rdataset->rdclass, classbuf,
05129                                               sizeof(classbuf));
05130                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
05131                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
05132                                       "check-names %s %s/%s/%s",
05133                                       fail ? "failure" : "warning",
05134                                       namebuf, typebuf, classbuf);
05135                         if (fail) {
05136                                 if (ANSWER(rdataset)) {
05137                                         dns_db_detachnode(fctx->cache, &node);
05138                                         return (DNS_R_BADNAME);
05139                                 }
05140                                 continue;
05141                         }
05142                 }
05143 
05144                 /*
05145                  * Enforce the configure maximum cache TTL.
05146                  */
05147                 if (rdataset->ttl > res->view->maxcachettl)
05148                         rdataset->ttl = res->view->maxcachettl;
05149 
05150                 /*
05151                  * Mark the rdataset as being prefetch eligible.
05152                  */
05153                 if (rdataset->ttl > fctx->res->view->prefetch_eligible)
05154                         rdataset->attributes |= DNS_RDATASETATTR_PREFETCH;
05155 
05156                 /*
05157                  * Find the SIG for this rdataset, if we have it.
05158                  */
05159                 for (sigrdataset = ISC_LIST_HEAD(name->list);
05160                      sigrdataset != NULL;
05161                      sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
05162                         if (sigrdataset->type == dns_rdatatype_rrsig &&
05163                             sigrdataset->covers == rdataset->type)
05164                                 break;
05165                 }
05166 
05167                 /*
05168                  * If this RRset is in a secure domain, is in bailiwick,
05169                  * and is not glue, attempt DNSSEC validation.  (We do not
05170                  * attempt to validate glue or out-of-bailiwick data--even
05171                  * though there might be some performance benefit to doing
05172                  * so--because it makes it simpler and safer to ensure that
05173                  * records from a secure domain are only cached if validated
05174                  * within the context of a query to the domain that owns
05175                  * them.)
05176                  */
05177                 if (secure_domain && rdataset->trust != dns_trust_glue &&
05178                     !EXTERNAL(rdataset)) {
05179                         dns_trust_t trust;
05180 
05181                         /*
05182                          * RRSIGs are validated as part of validating the
05183                          * type they cover.
05184                          */
05185                         if (rdataset->type == dns_rdatatype_rrsig)
05186                                 continue;
05187 
05188                         if (sigrdataset == NULL) {
05189                                 if (!ANSWER(rdataset) && need_validation) {
05190                                         /*
05191                                          * Ignore non-answer rdatasets that
05192                                          * are missing signatures.
05193                                          */
05194                                         continue;
05195                                 }
05196                         }
05197 
05198                         /*
05199                          * Normalize the rdataset and sigrdataset TTLs.
05200                          */
05201                         if (sigrdataset != NULL) {
05202                                 rdataset->ttl = ISC_MIN(rdataset->ttl,
05203                                                         sigrdataset->ttl);
05204                                 sigrdataset->ttl = rdataset->ttl;
05205                         }
05206 
05207                         /*
05208                          * Mark the rdataset as being prefetch eligible.
05209                          */
05210                         if (rdataset->ttl > fctx->res->view->prefetch_eligible)
05211                                 rdataset->attributes |= DNS_RDATASETATTR_PREFETCH;
05212 
05213 
05214                         /*
05215                          * Cache this rdataset/sigrdataset pair as
05216                          * pending data.  Track whether it was additional
05217                          * or not.
05218                          */
05219                         if (rdataset->trust == dns_trust_additional)
05220                                 trust = dns_trust_pending_additional;
05221                         else
05222                                 trust = dns_trust_pending_answer;
05223 
05224                         rdataset->trust = trust;
05225                         if (sigrdataset != NULL)
05226                                 sigrdataset->trust = trust;
05227                         if (!need_validation || !ANSWER(rdataset)) {
05228                                 options = 0;
05229                                 if (ANSWER(rdataset) &&
05230                                    rdataset->type != dns_rdatatype_rrsig) {
05231                                         isc_result_t tresult;
05232                                         dns_name_t *noqname = NULL;
05233                                         tresult = findnoqname(fctx, name,
05234                                                               rdataset->type,
05235                                                               &noqname);
05236                                         if (tresult == ISC_R_SUCCESS &&
05237                                             noqname != NULL) {
05238                                                 tresult =
05239                                                      dns_rdataset_addnoqname(
05240                                                             rdataset, noqname);
05241                                                 RUNTIME_CHECK(tresult ==
05242                                                               ISC_R_SUCCESS);
05243                                         }
05244                                 }
05245                                 if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
05246                                                 options = DNS_DBADD_PREFETCH;
05247                                 addedrdataset = ardataset;
05248                                 result = dns_db_addrdataset(fctx->cache, node,
05249                                                             NULL, now, rdataset,
05250                                                             options,
05251                                                             addedrdataset);
05252                                 if (result == DNS_R_UNCHANGED) {
05253                                         result = ISC_R_SUCCESS;
05254                                         if (!need_validation &&
05255                                             ardataset != NULL &&
05256                                             NEGATIVE(ardataset)) {
05257                                                 /*
05258                                                  * The answer in the cache is
05259                                                  * better than the answer we
05260                                                  * found, and is a negative
05261                                                  * cache entry, so we must set
05262                                                  * eresult appropriately.
05263                                                  */
05264                                                 if (NXDOMAIN(ardataset))
05265                                                         eresult =
05266                                                            DNS_R_NCACHENXDOMAIN;
05267                                                 else
05268                                                         eresult =
05269                                                            DNS_R_NCACHENXRRSET;
05270                                                 /*
05271                                                  * We have a negative response
05272                                                  * from the cache so don't
05273                                                  * attempt to add the RRSIG
05274                                                  * rrset.
05275                                                  */
05276                                                 continue;
05277                                         }
05278                                 }
05279                                 if (result != ISC_R_SUCCESS)
05280                                         break;
05281                                 if (sigrdataset != NULL) {
05282                                         addedrdataset = asigrdataset;
05283                                         result = dns_db_addrdataset(fctx->cache,
05284                                                                 node, NULL, now,
05285                                                                 sigrdataset,
05286                                                                 options,
05287                                                                 addedrdataset);
05288                                         if (result == DNS_R_UNCHANGED)
05289                                                 result = ISC_R_SUCCESS;
05290                                         if (result != ISC_R_SUCCESS)
05291                                                 break;
05292                                 } else if (!ANSWER(rdataset))
05293                                         continue;
05294                         }
05295 
05296                         if (ANSWER(rdataset) && need_validation) {
05297                                 if (fctx->type != dns_rdatatype_any &&
05298                                     fctx->type != dns_rdatatype_rrsig &&
05299                                     fctx->type != dns_rdatatype_sig) {
05300                                         /*
05301                                          * This is The Answer.  We will
05302                                          * validate it, but first we cache
05303                                          * the rest of the response - it may
05304                                          * contain useful keys.
05305                                          */
05306                                         INSIST(valrdataset == NULL &&
05307                                                valsigrdataset == NULL);
05308                                         valrdataset = rdataset;
05309                                         valsigrdataset = sigrdataset;
05310                                 } else {
05311                                         /*
05312                                          * This is one of (potentially)
05313                                          * multiple answers to an ANY
05314                                          * or SIG query.  To keep things
05315                                          * simple, we just start the
05316                                          * validator right away rather
05317                                          * than caching first and
05318                                          * having to remember which
05319                                          * rdatasets needed validation.
05320                                          */
05321                                         result = valcreate(fctx, addrinfo,
05322                                                            name, rdataset->type,
05323                                                            rdataset,
05324                                                            sigrdataset,
05325                                                            valoptions, task);
05326                                         /*
05327                                          * Defer any further validations.
05328                                          * This prevents multiple validators
05329                                          * from manipulating fctx->rmessage
05330                                          * simultaneously.
05331                                          */
05332                                         valoptions |= DNS_VALIDATOR_DEFER;
05333                                 }
05334                         } else if (CHAINING(rdataset)) {
05335                                 if (rdataset->type == dns_rdatatype_cname)
05336                                         eresult = DNS_R_CNAME;
05337                                 else {
05338                                         INSIST(rdataset->type ==
05339                                                dns_rdatatype_dname);
05340                                         eresult = DNS_R_DNAME;
05341                                 }
05342                         }
05343                 } else if (!EXTERNAL(rdataset)) {
05344                         /*
05345                          * It's OK to cache this rdataset now.
05346                          */
05347                         if (ANSWER(rdataset))
05348                                 addedrdataset = ardataset;
05349                         else if (ANSWERSIG(rdataset))
05350                                 addedrdataset = asigrdataset;
05351                         else
05352                                 addedrdataset = NULL;
05353                         if (CHAINING(rdataset)) {
05354                                 if (rdataset->type == dns_rdatatype_cname)
05355                                         eresult = DNS_R_CNAME;
05356                                 else {
05357                                         INSIST(rdataset->type ==
05358                                                dns_rdatatype_dname);
05359                                         eresult = DNS_R_DNAME;
05360                                 }
05361                         }
05362                         if (rdataset->trust == dns_trust_glue &&
05363                             (rdataset->type == dns_rdatatype_ns ||
05364                              (rdataset->type == dns_rdatatype_rrsig &&
05365                               rdataset->covers == dns_rdatatype_ns))) {
05366                                 /*
05367                                  * If the trust level is 'dns_trust_glue'
05368                                  * then we are adding data from a referral
05369                                  * we got while executing the search algorithm.
05370                                  * New referral data always takes precedence
05371                                  * over the existing cache contents.
05372                                  */
05373                                 options = DNS_DBADD_FORCE;
05374                         } else if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
05375                                 options = DNS_DBADD_PREFETCH;
05376                         else
05377                                 options = 0;
05378 
05379                         if (ANSWER(rdataset) &&
05380                            rdataset->type != dns_rdatatype_rrsig) {
05381                                 isc_result_t tresult;
05382                                 dns_name_t *noqname = NULL;
05383                                 tresult = findnoqname(fctx, name,
05384                                                       rdataset->type, &noqname);
05385                                 if (tresult == ISC_R_SUCCESS &&
05386                                     noqname != NULL) {
05387                                         tresult = dns_rdataset_addnoqname(
05388                                                             rdataset, noqname);
05389                                         RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
05390                                 }
05391                         }
05392 
05393                         /*
05394                          * Now we can add the rdataset.
05395                          */
05396                         result = dns_db_addrdataset(fctx->cache,
05397                                                     node, NULL, now,
05398                                                     rdataset,
05399                                                     options,
05400                                                     addedrdataset);
05401 
05402                         if (result == DNS_R_UNCHANGED) {
05403                                 if (ANSWER(rdataset) &&
05404                                     ardataset != NULL &&
05405                                     NEGATIVE(ardataset)) {
05406                                         /*
05407                                          * The answer in the cache is better
05408                                          * than the answer we found, and is
05409                                          * a negative cache entry, so we
05410                                          * must set eresult appropriately.
05411                                          */
05412                                         if (NXDOMAIN(ardataset))
05413                                                 eresult = DNS_R_NCACHENXDOMAIN;
05414                                         else
05415                                                 eresult = DNS_R_NCACHENXRRSET;
05416                                 }
05417                                 result = ISC_R_SUCCESS;
05418                         } else if (result != ISC_R_SUCCESS)
05419                                 break;
05420                 }
05421         }
05422 
05423         if (valrdataset != NULL) {
05424                 dns_rdatatype_t vtype = fctx->type;
05425                 if (CHAINING(valrdataset)) {
05426                         if (valrdataset->type == dns_rdatatype_cname)
05427                                 vtype = dns_rdatatype_cname;
05428                         else
05429                                 vtype = dns_rdatatype_dname;
05430                 }
05431                 result = valcreate(fctx, addrinfo, name, vtype, valrdataset,
05432                                    valsigrdataset, valoptions, task);
05433         }
05434 
05435         if (result == ISC_R_SUCCESS && have_answer) {
05436                 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
05437                 if (event != NULL) {
05438                         /*
05439                          * Negative results must be indicated in event->result.
05440                          */
05441                         if (dns_rdataset_isassociated(event->rdataset) &&
05442                             NEGATIVE(event->rdataset)) {
05443                                 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
05444                                        eresult == DNS_R_NCACHENXRRSET);
05445                         }
05446                         event->result = eresult;
05447                         dns_db_attach(fctx->cache, adbp);
05448                         dns_db_transfernode(fctx->cache, &node, anodep);
05449                         clone_results(fctx);
05450                 }
05451         }
05452 
05453         if (node != NULL)
05454                 dns_db_detachnode(fctx->cache, &node);
05455 
05456         return (result);
05457 }
05458 
05459 static inline isc_result_t
05460 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
05461 {
05462         isc_result_t result;
05463         dns_section_t section;
05464         dns_name_t *name;
05465 
05466         FCTXTRACE("cache_message");
05467 
05468         fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
05469 
05470         LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
05471 
05472         for (section = DNS_SECTION_ANSWER;
05473              section <= DNS_SECTION_ADDITIONAL;
05474              section++) {
05475                 result = dns_message_firstname(fctx->rmessage, section);
05476                 while (result == ISC_R_SUCCESS) {
05477                         name = NULL;
05478                         dns_message_currentname(fctx->rmessage, section,
05479                                                 &name);
05480                         if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
05481                                 result = cache_name(fctx, name, addrinfo, now);
05482                                 if (result != ISC_R_SUCCESS)
05483                                         break;
05484                         }
05485                         result = dns_message_nextname(fctx->rmessage, section);
05486                 }
05487                 if (result != ISC_R_NOMORE)
05488                         break;
05489         }
05490         if (result == ISC_R_NOMORE)
05491                 result = ISC_R_SUCCESS;
05492 
05493         UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
05494 
05495         return (result);
05496 }
05497 
05498 /*
05499  * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
05500  */
05501 static isc_result_t
05502 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
05503                   dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
05504                   isc_boolean_t optout, isc_boolean_t secure,
05505                   dns_rdataset_t *ardataset, isc_result_t *eresultp)
05506 {
05507         isc_result_t result;
05508         dns_rdataset_t rdataset;
05509 
05510         if (ardataset == NULL) {
05511                 dns_rdataset_init(&rdataset);
05512                 ardataset = &rdataset;
05513         }
05514         if (secure)
05515                 result = dns_ncache_addoptout(message, cache, node, covers,
05516                                               now, maxttl, optout, ardataset);
05517         else
05518                 result = dns_ncache_add(message, cache, node, covers, now,
05519                                         maxttl, ardataset);
05520         if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
05521                 /*
05522                  * If the cache now contains a negative entry and we
05523                  * care about whether it is DNS_R_NCACHENXDOMAIN or
05524                  * DNS_R_NCACHENXRRSET then extract it.
05525                  */
05526                 if (NEGATIVE(ardataset)) {
05527                         /*
05528                          * The cache data is a negative cache entry.
05529                          */
05530                         if (NXDOMAIN(ardataset))
05531                                 *eresultp = DNS_R_NCACHENXDOMAIN;
05532                         else
05533                                 *eresultp = DNS_R_NCACHENXRRSET;
05534                 } else {
05535                         /*
05536                          * Either we don't care about the nature of the
05537                          * cache rdataset (because no fetch is interested
05538                          * in the outcome), or the cache rdataset is not
05539                          * a negative cache entry.  Whichever case it is,
05540                          * we can return success.
05541                          *
05542                          * XXXRTH  There's a CNAME/DNAME problem here.
05543                          */
05544                         *eresultp = ISC_R_SUCCESS;
05545                 }
05546                 result = ISC_R_SUCCESS;
05547         }
05548         if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
05549                 dns_rdataset_disassociate(ardataset);
05550 
05551         return (result);
05552 }
05553 
05554 static inline isc_result_t
05555 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
05556                dns_rdatatype_t covers, isc_stdtime_t now)
05557 {
05558         isc_result_t result, eresult;
05559         dns_name_t *name;
05560         dns_resolver_t *res;
05561         dns_db_t **adbp;
05562         dns_dbnode_t *node, **anodep;
05563         dns_rdataset_t *ardataset;
05564         isc_boolean_t need_validation, secure_domain;
05565         dns_name_t *aname;
05566         dns_fetchevent_t *event;
05567         isc_uint32_t ttl;
05568         unsigned int valoptions = 0;
05569         isc_boolean_t checknta = ISC_TRUE;
05570 
05571         FCTXTRACE("ncache_message");
05572 
05573         fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
05574 
05575         res = fctx->res;
05576         need_validation = ISC_FALSE;
05577         POST(need_validation);
05578         secure_domain = ISC_FALSE;
05579         eresult = ISC_R_SUCCESS;
05580         name = &fctx->name;
05581         node = NULL;
05582 
05583         /*
05584          * XXXMPA remove when we follow cnames and adjust the setting
05585          * of FCTX_ATTR_WANTNCACHE in noanswer_response().
05586          */
05587         INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
05588 
05589         /*
05590          * Is DNSSEC validation required for this name?
05591          */
05592         if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) {
05593                 valoptions |= DNS_VALIDATOR_NONTA;
05594                 checknta = ISC_FALSE;
05595         }
05596 
05597         if (fctx->res->view->enablevalidation) {
05598                 result = issecuredomain(res->view, name, fctx->type,
05599                                         now, checknta, &secure_domain);
05600                 if (result != ISC_R_SUCCESS)
05601                         return (result);
05602 
05603                 if (!secure_domain && res->view->dlv != NULL) {
05604                         valoptions |= DNS_VALIDATOR_DLV;
05605                         secure_domain = ISC_TRUE;
05606                 }
05607         }
05608 
05609         if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0)
05610                 valoptions |= DNS_VALIDATOR_NOCDFLAG;
05611 
05612         if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
05613                 need_validation = ISC_FALSE;
05614         else
05615                 need_validation = secure_domain;
05616 
05617         if (secure_domain) {
05618                 /*
05619                  * Mark all rdatasets as pending.
05620                  */
05621                 dns_rdataset_t *trdataset;
05622                 dns_name_t *tname;
05623 
05624                 result = dns_message_firstname(fctx->rmessage,
05625                                                DNS_SECTION_AUTHORITY);
05626                 while (result == ISC_R_SUCCESS) {
05627                         tname = NULL;
05628                         dns_message_currentname(fctx->rmessage,
05629                                                 DNS_SECTION_AUTHORITY,
05630                                                 &tname);
05631                         for (trdataset = ISC_LIST_HEAD(tname->list);
05632                              trdataset != NULL;
05633                              trdataset = ISC_LIST_NEXT(trdataset, link))
05634                                 trdataset->trust = dns_trust_pending_answer;
05635                         result = dns_message_nextname(fctx->rmessage,
05636                                                       DNS_SECTION_AUTHORITY);
05637                 }
05638                 if (result != ISC_R_NOMORE)
05639                         return (result);
05640 
05641         }
05642 
05643         if (need_validation) {
05644                 /*
05645                  * Do negative response validation.
05646                  */
05647                 result = valcreate(fctx, addrinfo, name, fctx->type,
05648                                    NULL, NULL, valoptions,
05649                                    res->buckets[fctx->bucketnum].task);
05650                 /*
05651                  * If validation is necessary, return now.  Otherwise continue
05652                  * to process the message, letting the validation complete
05653                  * in its own good time.
05654                  */
05655                 return (result);
05656         }
05657 
05658         LOCK(&res->buckets[fctx->bucketnum].lock);
05659 
05660         adbp = NULL;
05661         aname = NULL;
05662         anodep = NULL;
05663         ardataset = NULL;
05664         if (!HAVE_ANSWER(fctx)) {
05665                 event = ISC_LIST_HEAD(fctx->events);
05666                 if (event != NULL) {
05667                         adbp = &event->db;
05668                         aname = dns_fixedname_name(&event->foundname);
05669                         result = dns_name_copy(name, aname, NULL);
05670                         if (result != ISC_R_SUCCESS)
05671                                 goto unlock;
05672                         anodep = &event->node;
05673                         ardataset = event->rdataset;
05674                 }
05675         } else
05676                 event = NULL;
05677 
05678         result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
05679         if (result != ISC_R_SUCCESS)
05680                 goto unlock;
05681 
05682         /*
05683          * If we are asking for a SOA record set the cache time
05684          * to zero to facilitate locating the containing zone of
05685          * a arbitrary zone.
05686          */
05687         ttl = fctx->res->view->maxncachettl;
05688         if (fctx->type == dns_rdatatype_soa &&
05689             covers == dns_rdatatype_any &&
05690             fctx->res->zero_no_soa_ttl)
05691                 ttl = 0;
05692 
05693         result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
05694                                    covers, now, ttl, ISC_FALSE,
05695                                    ISC_FALSE, ardataset, &eresult);
05696         if (result != ISC_R_SUCCESS)
05697                 goto unlock;
05698 
05699         if (!HAVE_ANSWER(fctx)) {
05700                 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
05701                 if (event != NULL) {
05702                         event->result = eresult;
05703                         dns_db_attach(fctx->cache, adbp);
05704                         dns_db_transfernode(fctx->cache, &node, anodep);
05705                         clone_results(fctx);
05706                 }
05707         }
05708 
05709  unlock:
05710         UNLOCK(&res->buckets[fctx->bucketnum].lock);
05711 
05712         if (node != NULL)
05713                 dns_db_detachnode(fctx->cache, &node);
05714 
05715         return (result);
05716 }
05717 
05718 static inline void
05719 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
05720              isc_boolean_t external, isc_boolean_t gluing)
05721 {
05722         name->attributes |= DNS_NAMEATTR_CACHE;
05723         if (gluing) {
05724                 rdataset->trust = dns_trust_glue;
05725                 /*
05726                  * Glue with 0 TTL causes problems.  We force the TTL to
05727                  * 1 second to prevent this.
05728                  */
05729                 if (rdataset->ttl == 0)
05730                         rdataset->ttl = 1;
05731         } else
05732                 rdataset->trust = dns_trust_additional;
05733         /*
05734          * Avoid infinite loops by only marking new rdatasets.
05735          */
05736         if (!CACHE(rdataset)) {
05737                 name->attributes |= DNS_NAMEATTR_CHASE;
05738                 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
05739         }
05740         rdataset->attributes |= DNS_RDATASETATTR_CACHE;
05741         if (external)
05742                 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
05743 }
05744 
05745 static isc_result_t
05746 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
05747               dns_section_t section)
05748 {
05749         fetchctx_t *fctx = arg;
05750         isc_result_t result;
05751         dns_name_t *name;
05752         dns_rdataset_t *rdataset;
05753         isc_boolean_t external;
05754         dns_rdatatype_t rtype;
05755         isc_boolean_t gluing;
05756 
05757         REQUIRE(VALID_FCTX(fctx));
05758 
05759 #if CHECK_FOR_GLUE_IN_ANSWER
05760         if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
05761                 return (ISC_R_SUCCESS);
05762 #endif
05763 
05764         if (GLUING(fctx))
05765                 gluing = ISC_TRUE;
05766         else
05767                 gluing = ISC_FALSE;
05768         name = NULL;
05769         rdataset = NULL;
05770         result = dns_message_findname(fctx->rmessage, section, addname,
05771                                       dns_rdatatype_any, 0, &name, NULL);
05772         if (result == ISC_R_SUCCESS) {
05773                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
05774                 if (type == dns_rdatatype_a) {
05775                         for (rdataset = ISC_LIST_HEAD(name->list);
05776                              rdataset != NULL;
05777                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
05778                                 if (rdataset->type == dns_rdatatype_rrsig)
05779                                         rtype = rdataset->covers;
05780                                 else
05781                                         rtype = rdataset->type;
05782                                 if (rtype == dns_rdatatype_a ||
05783                                     rtype == dns_rdatatype_aaaa)
05784                                         mark_related(name, rdataset, external,
05785                                                      gluing);
05786                         }
05787                 } else {
05788                         result = dns_message_findtype(name, type, 0,
05789                                                       &rdataset);
05790                         if (result == ISC_R_SUCCESS) {
05791                                 mark_related(name, rdataset, external, gluing);
05792                                 /*
05793                                  * Do we have its SIG too?
05794                                  */
05795                                 rdataset = NULL;
05796                                 result = dns_message_findtype(name,
05797                                                       dns_rdatatype_rrsig,
05798                                                       type, &rdataset);
05799                                 if (result == ISC_R_SUCCESS)
05800                                         mark_related(name, rdataset, external,
05801                                                      gluing);
05802                         }
05803                 }
05804         }
05805 
05806         return (ISC_R_SUCCESS);
05807 }
05808 
05809 static isc_result_t
05810 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
05811         return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
05812 }
05813 
05814 #ifndef CHECK_FOR_GLUE_IN_ANSWER
05815 #define CHECK_FOR_GLUE_IN_ANSWER 0
05816 #endif
05817 #if CHECK_FOR_GLUE_IN_ANSWER
05818 static isc_result_t
05819 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
05820         return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
05821 }
05822 #endif
05823 
05824 static void
05825 chase_additional(fetchctx_t *fctx) {
05826         isc_boolean_t rescan;
05827         dns_section_t section = DNS_SECTION_ADDITIONAL;
05828         isc_result_t result;
05829 
05830  again:
05831         rescan = ISC_FALSE;
05832 
05833         for (result = dns_message_firstname(fctx->rmessage, section);
05834              result == ISC_R_SUCCESS;
05835              result = dns_message_nextname(fctx->rmessage, section)) {
05836                 dns_name_t *name = NULL;
05837                 dns_rdataset_t *rdataset;
05838                 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
05839                                         &name);
05840                 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
05841                         continue;
05842                 name->attributes &= ~DNS_NAMEATTR_CHASE;
05843                 for (rdataset = ISC_LIST_HEAD(name->list);
05844                      rdataset != NULL;
05845                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
05846                         if (CHASE(rdataset)) {
05847                                 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
05848                                 (void)dns_rdataset_additionaldata(rdataset,
05849                                                                   check_related,
05850                                                                   fctx);
05851                                 rescan = ISC_TRUE;
05852                         }
05853                 }
05854         }
05855         if (rescan)
05856                 goto again;
05857 }
05858 
05859 static inline isc_result_t
05860 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
05861         isc_result_t result;
05862         dns_rdata_t rdata = DNS_RDATA_INIT;
05863         dns_rdata_cname_t cname;
05864 
05865         result = dns_rdataset_first(rdataset);
05866         if (result != ISC_R_SUCCESS)
05867                 return (result);
05868         dns_rdataset_current(rdataset, &rdata);
05869         result = dns_rdata_tostruct(&rdata, &cname, NULL);
05870         if (result != ISC_R_SUCCESS)
05871                 return (result);
05872         dns_name_init(tname, NULL);
05873         dns_name_clone(&cname.cname, tname);
05874         dns_rdata_freestruct(&cname);
05875 
05876         return (ISC_R_SUCCESS);
05877 }
05878 
05879 static inline isc_result_t
05880 dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
05881              dns_name_t *oname, dns_fixedname_t *fixeddname)
05882 {
05883         isc_result_t result;
05884         dns_rdata_t rdata = DNS_RDATA_INIT;
05885         unsigned int nlabels;
05886         int order;
05887         dns_namereln_t namereln;
05888         dns_rdata_dname_t dname;
05889         dns_fixedname_t prefix;
05890 
05891         /*
05892          * Get the target name of the DNAME.
05893          */
05894         result = dns_rdataset_first(rdataset);
05895         if (result != ISC_R_SUCCESS)
05896                 return (result);
05897         dns_rdataset_current(rdataset, &rdata);
05898         result = dns_rdata_tostruct(&rdata, &dname, NULL);
05899         if (result != ISC_R_SUCCESS)
05900                 return (result);
05901 
05902         /*
05903          * Get the prefix of qname.
05904          */
05905         namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
05906         if (namereln != dns_namereln_subdomain) {
05907                 char qbuf[DNS_NAME_FORMATSIZE];
05908                 char obuf[DNS_NAME_FORMATSIZE];
05909 
05910                 dns_rdata_freestruct(&dname);
05911                 dns_name_format(qname, qbuf, sizeof(qbuf));
05912                 dns_name_format(oname, obuf, sizeof(obuf));
05913                 log_formerr(fctx, "unrelated DNAME in answer: "
05914                                    "%s is not in %s", qbuf, obuf);
05915                 return (DNS_R_FORMERR);
05916         }
05917         dns_fixedname_init(&prefix);
05918         dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
05919         dns_fixedname_init(fixeddname);
05920         result = dns_name_concatenate(dns_fixedname_name(&prefix),
05921                                       &dname.dname,
05922                                       dns_fixedname_name(fixeddname), NULL);
05923         dns_rdata_freestruct(&dname);
05924         return (result);
05925 }
05926 
05927 static isc_boolean_t
05928 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
05929                          dns_rdataset_t *rdataset)
05930 {
05931         isc_result_t result;
05932         dns_rdata_t rdata = DNS_RDATA_INIT;
05933         struct in_addr ina;
05934         struct in6_addr in6a;
05935         isc_netaddr_t netaddr;
05936         char addrbuf[ISC_NETADDR_FORMATSIZE];
05937         char namebuf[DNS_NAME_FORMATSIZE];
05938         char classbuf[64];
05939         char typebuf[64];
05940         int match;
05941 
05942         /* By default, we allow any addresses. */
05943         if (view->denyansweracl == NULL)
05944                 return (ISC_TRUE);
05945 
05946         /*
05947          * If the owner name matches one in the exclusion list, either exactly
05948          * or partially, allow it.
05949          */
05950         if (view->answeracl_exclude != NULL) {
05951                 dns_rbtnode_t *node = NULL;
05952 
05953                 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
05954                                           &node, NULL, 0, NULL, NULL);
05955 
05956                 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
05957                         return (ISC_TRUE);
05958         }
05959 
05960         /*
05961          * Otherwise, search the filter list for a match for each address
05962          * record.  If a match is found, the address should be filtered,
05963          * so should the entire answer.
05964          */
05965         for (result = dns_rdataset_first(rdataset);
05966              result == ISC_R_SUCCESS;
05967              result = dns_rdataset_next(rdataset)) {
05968                 dns_rdata_reset(&rdata);
05969                 dns_rdataset_current(rdataset, &rdata);
05970                 if (rdataset->type == dns_rdatatype_a) {
05971                         INSIST(rdata.length == sizeof(ina.s_addr));
05972                         memmove(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
05973                         isc_netaddr_fromin(&netaddr, &ina);
05974                 } else {
05975                         INSIST(rdata.length == sizeof(in6a.s6_addr));
05976                         memmove(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
05977                         isc_netaddr_fromin6(&netaddr, &in6a);
05978                 }
05979 
05980                 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
05981                                        &view->aclenv, &match, NULL);
05982 
05983                 if (result == ISC_R_SUCCESS && match > 0) {
05984                         isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
05985                         dns_name_format(name, namebuf, sizeof(namebuf));
05986                         dns_rdatatype_format(rdataset->type, typebuf,
05987                                              sizeof(typebuf));
05988                         dns_rdataclass_format(rdataset->rdclass, classbuf,
05989                                               sizeof(classbuf));
05990                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
05991                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
05992                                       "answer address %s denied for %s/%s/%s",
05993                                       addrbuf, namebuf, typebuf, classbuf);
05994                         return (ISC_FALSE);
05995                 }
05996         }
05997 
05998         return (ISC_TRUE);
05999 }
06000 
06001 static isc_boolean_t
06002 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
06003                         dns_rdatatype_t type, dns_name_t *tname,
06004                         dns_name_t *domain)
06005 {
06006         isc_result_t result;
06007         dns_rbtnode_t *node = NULL;
06008         char qnamebuf[DNS_NAME_FORMATSIZE];
06009         char tnamebuf[DNS_NAME_FORMATSIZE];
06010         char classbuf[64];
06011         char typebuf[64];
06012 
06013         /* By default, we allow any target name. */
06014         if (view->denyanswernames == NULL)
06015                 return (ISC_TRUE);
06016 
06017         /*
06018          * If the owner name matches one in the exclusion list, either exactly
06019          * or partially, allow it.
06020          */
06021         if (view->answernames_exclude != NULL) {
06022                 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
06023                                           &node, NULL, 0, NULL, NULL);
06024                 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
06025                         return (ISC_TRUE);
06026         }
06027 
06028         /*
06029          * If the target name is a subdomain of the search domain, allow it.
06030          */
06031         if (dns_name_issubdomain(tname, domain))
06032                 return (ISC_TRUE);
06033 
06034         /*
06035          * Otherwise, apply filters.
06036          */
06037         result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
06038                                   NULL, 0, NULL, NULL);
06039         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
06040                 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
06041                 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
06042                 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
06043                 dns_rdataclass_format(view->rdclass, classbuf,
06044                                       sizeof(classbuf));
06045                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
06046                               DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
06047                               "%s target %s denied for %s/%s",
06048                               typebuf, tnamebuf, qnamebuf, classbuf);
06049                 return (ISC_FALSE);
06050         }
06051 
06052         return (ISC_TRUE);
06053 }
06054 
06055 static void
06056 trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
06057         char ns_namebuf[DNS_NAME_FORMATSIZE];
06058         char namebuf[DNS_NAME_FORMATSIZE];
06059         char tbuf[DNS_RDATATYPE_FORMATSIZE];
06060 
06061         if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
06062                 dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
06063                 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
06064                 dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
06065 
06066                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
06067                               DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
06068                               "fctx %p: trimming ttl of %s/NS for %s/%s: "
06069                               "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
06070                               rdataset->ttl, fctx->ns_ttl);
06071                 rdataset->ttl = fctx->ns_ttl;
06072         }
06073 }
06074 
06075 /*
06076  * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
06077  * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
06078  * section for the NS RRset if the query type is NS; if it has
06079  * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
06080  * section for A and AAAA queries.
06081  */
06082 #define LOOK_FOR_NS_IN_ANSWER 0x1
06083 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
06084 
06085 static isc_result_t
06086 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
06087                   unsigned int look_in_options)
06088 {
06089         isc_result_t result;
06090         dns_message_t *message;
06091         dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name, *save_name;
06092         dns_rdataset_t *rdataset, *ns_rdataset;
06093         isc_boolean_t aa, negative_response;
06094         dns_rdatatype_t type, save_type;
06095         dns_section_t section;
06096 
06097         FCTXTRACE("noanswer_response");
06098 
06099         if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
06100                 INSIST(fctx->type == dns_rdatatype_ns);
06101                 section = DNS_SECTION_ANSWER;
06102         } else
06103                 section = DNS_SECTION_AUTHORITY;
06104 
06105         message = fctx->rmessage;
06106 
06107         /*
06108          * Setup qname.
06109          */
06110         if (oqname == NULL) {
06111                 /*
06112                  * We have a normal, non-chained negative response or
06113                  * referral.
06114                  */
06115                 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
06116                         aa = ISC_TRUE;
06117                 else
06118                         aa = ISC_FALSE;
06119                 qname = &fctx->name;
06120         } else {
06121                 /*
06122                  * We're being invoked by answer_response() after it has
06123                  * followed a CNAME/DNAME chain.
06124                  */
06125                 qname = oqname;
06126                 aa = ISC_FALSE;
06127                 /*
06128                  * If the current qname is not a subdomain of the query
06129                  * domain, there's no point in looking at the authority
06130                  * section without doing DNSSEC validation.
06131                  *
06132                  * Until we do that validation, we'll just return success
06133                  * in this case.
06134                  */
06135                 if (!dns_name_issubdomain(qname, &fctx->domain))
06136                         return (ISC_R_SUCCESS);
06137         }
06138 
06139         /*
06140          * We have to figure out if this is a negative response, or a
06141          * referral.
06142          */
06143 
06144         /*
06145          * Sometimes we can tell if its a negative response by looking at
06146          * the message header.
06147          */
06148         negative_response = ISC_FALSE;
06149         if (message->rcode == dns_rcode_nxdomain ||
06150             (message->counts[DNS_SECTION_ANSWER] == 0 &&
06151              message->counts[DNS_SECTION_AUTHORITY] == 0))
06152                 negative_response = ISC_TRUE;
06153 
06154         /*
06155          * Process the authority section.
06156          */
06157         ns_name = NULL;
06158         ns_rdataset = NULL;
06159         soa_name = NULL;
06160         ds_name = NULL;
06161         save_name = NULL;
06162         save_type = dns_rdatatype_none;
06163         result = dns_message_firstname(message, section);
06164         while (result == ISC_R_SUCCESS) {
06165                 name = NULL;
06166                 dns_message_currentname(message, section, &name);
06167                 if (dns_name_issubdomain(name, &fctx->domain)) {
06168                         /*
06169                          * Look for NS/SOA RRsets first.
06170                          */
06171                         for (rdataset = ISC_LIST_HEAD(name->list);
06172                              rdataset != NULL;
06173                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
06174                                 type = rdataset->type;
06175                                 if (type == dns_rdatatype_rrsig)
06176                                         type = rdataset->covers;
06177                                 if (((type == dns_rdatatype_ns ||
06178                                       type == dns_rdatatype_soa) &&
06179                                      !dns_name_issubdomain(qname, name))) {
06180                                         char qbuf[DNS_NAME_FORMATSIZE];
06181                                         char nbuf[DNS_NAME_FORMATSIZE];
06182                                         char tbuf[DNS_RDATATYPE_FORMATSIZE];
06183                                         dns_rdatatype_format(type, tbuf,
06184                                                              sizeof(tbuf));
06185                                         dns_name_format(name, nbuf,
06186                                                              sizeof(nbuf));
06187                                         dns_name_format(qname, qbuf,
06188                                                              sizeof(qbuf));
06189                                         log_formerr(fctx,
06190                                                     "unrelated %s %s in "
06191                                                     "%s authority section",
06192                                                     tbuf, nbuf, qbuf);
06193                                         goto nextname;
06194                                 }
06195                                 if (type == dns_rdatatype_ns) {
06196                                         /*
06197                                          * NS or RRSIG NS.
06198                                          *
06199                                          * Only one set of NS RRs is allowed.
06200                                          */
06201                                         if (rdataset->type ==
06202                                             dns_rdatatype_ns) {
06203                                                 if (ns_name != NULL &&
06204                                                     name != ns_name) {
06205                                                         log_formerr(fctx,
06206                                                                 "multiple NS "
06207                                                                 "RRsets in "
06208                                                                 "authority "
06209                                                                 "section");
06210                                                         return (DNS_R_FORMERR);
06211                                                 }
06212                                                 ns_name = name;
06213                                                 ns_rdataset = rdataset;
06214                                         }
06215                                         name->attributes |=
06216                                                 DNS_NAMEATTR_CACHE;
06217                                         rdataset->attributes |=
06218                                                 DNS_RDATASETATTR_CACHE;
06219                                         rdataset->trust = dns_trust_glue;
06220                                 }
06221                                 if (type == dns_rdatatype_soa) {
06222                                         /*
06223                                          * SOA, or RRSIG SOA.
06224                                          *
06225                                          * Only one SOA is allowed.
06226                                          */
06227                                         if (rdataset->type ==
06228                                             dns_rdatatype_soa) {
06229                                                 if (soa_name != NULL &&
06230                                                     name != soa_name) {
06231                                                         log_formerr(fctx,
06232                                                                 "multiple SOA "
06233                                                                 "RRs in "
06234                                                                 "authority "
06235                                                                 "section");
06236                                                         return (DNS_R_FORMERR);
06237                                                 }
06238                                                 soa_name = name;
06239                                         }
06240                                         name->attributes |=
06241                                                 DNS_NAMEATTR_NCACHE;
06242                                         rdataset->attributes |=
06243                                                 DNS_RDATASETATTR_NCACHE;
06244                                         if (aa)
06245                                                 rdataset->trust =
06246                                                     dns_trust_authauthority;
06247                                         else if (ISFORWARDER(fctx->addrinfo))
06248                                                 rdataset->trust =
06249                                                         dns_trust_answer;
06250                                         else
06251                                                 rdataset->trust =
06252                                                         dns_trust_additional;
06253                                 }
06254                         }
06255                 }
06256  nextname:
06257                 result = dns_message_nextname(message, section);
06258                 if (result == ISC_R_NOMORE)
06259                         break;
06260                 else if (result != ISC_R_SUCCESS)
06261                         return (result);
06262         }
06263 
06264         log_ns_ttl(fctx, "noanswer_response");
06265 
06266         if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
06267             !dns_name_equal(ns_name, dns_rootname))
06268                 trim_ns_ttl(fctx, ns_name, ns_rdataset);
06269 
06270         /*
06271          * A negative response has a SOA record (Type 2)
06272          * and a optional NS RRset (Type 1) or it has neither
06273          * a SOA or a NS RRset (Type 3, handled above) or
06274          * rcode is NXDOMAIN (handled above) in which case
06275          * the NS RRset is allowed (Type 4).
06276          */
06277         if (soa_name != NULL)
06278                 negative_response = ISC_TRUE;
06279 
06280         result = dns_message_firstname(message, section);
06281         while (result == ISC_R_SUCCESS) {
06282                 name = NULL;
06283                 dns_message_currentname(message, section, &name);
06284                 if (dns_name_issubdomain(name, &fctx->domain)) {
06285                         for (rdataset = ISC_LIST_HEAD(name->list);
06286                              rdataset != NULL;
06287                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
06288                                 type = rdataset->type;
06289                                 if (type == dns_rdatatype_rrsig)
06290                                         type = rdataset->covers;
06291                                 if (type == dns_rdatatype_nsec ||
06292                                     type == dns_rdatatype_nsec3) {
06293                                         /*
06294                                          * NSEC or RRSIG NSEC.
06295                                          */
06296                                         if (negative_response) {
06297                                                 name->attributes |=
06298                                                         DNS_NAMEATTR_NCACHE;
06299                                                 rdataset->attributes |=
06300                                                         DNS_RDATASETATTR_NCACHE;
06301                                         } else if (type == dns_rdatatype_nsec) {
06302                                                 name->attributes |=
06303                                                         DNS_NAMEATTR_CACHE;
06304                                                 rdataset->attributes |=
06305                                                         DNS_RDATASETATTR_CACHE;
06306                                         }
06307                                         if (aa)
06308                                                 rdataset->trust =
06309                                                     dns_trust_authauthority;
06310                                         else if (ISFORWARDER(fctx->addrinfo))
06311                                                 rdataset->trust =
06312                                                         dns_trust_answer;
06313                                         else
06314                                                 rdataset->trust =
06315                                                         dns_trust_additional;
06316                                         /*
06317                                          * No additional data needs to be
06318                                          * marked.
06319                                          */
06320                                 } else if (type == dns_rdatatype_ds) {
06321                                         /*
06322                                          * DS or SIG DS.
06323                                          *
06324                                          * These should only be here if
06325                                          * this is a referral, and there
06326                                          * should only be one DS RRset.
06327                                          */
06328                                         if (ns_name == NULL) {
06329                                                 log_formerr(fctx,
06330                                                             "DS with no "
06331                                                             "referral");
06332                                                 return (DNS_R_FORMERR);
06333                                         }
06334                                         if (rdataset->type ==
06335                                             dns_rdatatype_ds) {
06336                                                 if (ds_name != NULL &&
06337                                                     name != ds_name) {
06338                                                         log_formerr(fctx,
06339                                                                 "DS doesn't "
06340                                                                 "match "
06341                                                                 "referral "
06342                                                                 "(NS)");
06343                                                         return (DNS_R_FORMERR);
06344                                                 }
06345                                                 ds_name = name;
06346                                         }
06347                                         name->attributes |=
06348                                                 DNS_NAMEATTR_CACHE;
06349                                         rdataset->attributes |=
06350                                                 DNS_RDATASETATTR_CACHE;
06351                                         if (aa)
06352                                                 rdataset->trust =
06353                                                     dns_trust_authauthority;
06354                                         else if (ISFORWARDER(fctx->addrinfo))
06355                                                 rdataset->trust =
06356                                                         dns_trust_answer;
06357                                         else
06358                                                 rdataset->trust =
06359                                                         dns_trust_additional;
06360                                 }
06361                         }
06362                 } else {
06363                         save_name = name;
06364                         save_type = ISC_LIST_HEAD(name->list)->type;
06365                 }
06366                 result = dns_message_nextname(message, section);
06367                 if (result == ISC_R_NOMORE)
06368                         break;
06369                 else if (result != ISC_R_SUCCESS)
06370                         return (result);
06371         }
06372 
06373         /*
06374          * Trigger lookups for DNS nameservers.
06375          */
06376         if (negative_response && message->rcode == dns_rcode_noerror &&
06377             fctx->type == dns_rdatatype_ds && soa_name != NULL &&
06378             dns_name_equal(soa_name, qname) &&
06379             !dns_name_equal(qname, dns_rootname))
06380                 return (DNS_R_CHASEDSSERVERS);
06381 
06382         /*
06383          * Did we find anything?
06384          */
06385         if (!negative_response && ns_name == NULL) {
06386                 /*
06387                  * Nope.
06388                  */
06389                 if (oqname != NULL) {
06390                         /*
06391                          * We've already got a partial CNAME/DNAME chain,
06392                          * and haven't found else anything useful here, but
06393                          * no error has occurred since we have an answer.
06394                          */
06395                         return (ISC_R_SUCCESS);
06396                 } else {
06397                         /*
06398                          * The responder is insane.
06399                          */
06400                         if (save_name == NULL) {
06401                                 log_formerr(fctx, "invalid response");
06402                                 return (DNS_R_FORMERR);
06403                         }
06404                         if (!dns_name_issubdomain(save_name, &fctx->domain)) {
06405                                 char nbuf[DNS_NAME_FORMATSIZE];
06406                                 char dbuf[DNS_NAME_FORMATSIZE];
06407                                 char tbuf[DNS_RDATATYPE_FORMATSIZE];
06408 
06409                                 dns_rdatatype_format(save_type, tbuf,
06410                                         sizeof(tbuf));
06411                                 dns_name_format(save_name, nbuf, sizeof(nbuf));
06412                                 dns_name_format(&fctx->domain, dbuf,
06413                                         sizeof(dbuf));
06414 
06415                                 log_formerr(fctx, "Name %s (%s) not subdomain"
06416                                         " of zone %s -- invalid response",
06417                                         nbuf, tbuf, dbuf);
06418                         } else {
06419                                 log_formerr(fctx, "invalid response");
06420                         }
06421                         return (DNS_R_FORMERR);
06422                 }
06423         }
06424 
06425         /*
06426          * If we found both NS and SOA, they should be the same name.
06427          */
06428         if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
06429                 log_formerr(fctx, "NS/SOA mismatch");
06430                 return (DNS_R_FORMERR);
06431         }
06432 
06433         /*
06434          * Do we have a referral?  (We only want to follow a referral if
06435          * we're not following a chain.)
06436          */
06437         if (!negative_response && ns_name != NULL && oqname == NULL) {
06438                 /*
06439                  * We already know ns_name is a subdomain of fctx->domain.
06440                  * If ns_name is equal to fctx->domain, we're not making
06441                  * progress.  We return DNS_R_FORMERR so that we'll keep
06442                  * trying other servers.
06443                  */
06444                 if (dns_name_equal(ns_name, &fctx->domain)) {
06445                         log_formerr(fctx, "non-improving referral");
06446                         return (DNS_R_FORMERR);
06447                 }
06448 
06449                 /*
06450                  * If the referral name is not a parent of the query
06451                  * name, consider the responder insane.
06452                  */
06453                 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
06454                         /* Logged twice */
06455                         log_formerr(fctx, "referral to non-parent");
06456                         FCTXTRACE("referral to non-parent");
06457                         return (DNS_R_FORMERR);
06458                 }
06459 
06460                 /*
06461                  * Mark any additional data related to this rdataset.
06462                  * It's important that we do this before we change the
06463                  * query domain.
06464                  */
06465                 INSIST(ns_rdataset != NULL);
06466                 fctx->attributes |= FCTX_ATTR_GLUING;
06467                 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
06468                                                   fctx);
06469 #if CHECK_FOR_GLUE_IN_ANSWER
06470                 /*
06471                  * Look in the answer section for "glue" that is incorrectly
06472                  * returned as a answer.  This is needed if the server also
06473                  * minimizes the response size by not adding records to the
06474                  * additional section that are in the answer section or if
06475                  * the record gets dropped due to message size constraints.
06476                  */
06477                 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
06478                     (fctx->type == dns_rdatatype_aaaa ||
06479                      fctx->type == dns_rdatatype_a))
06480                         (void)dns_rdataset_additionaldata(ns_rdataset,
06481                                                           check_answer, fctx);
06482 #endif
06483                 fctx->attributes &= ~FCTX_ATTR_GLUING;
06484                 /*
06485                  * NS rdatasets with 0 TTL cause problems.
06486                  * dns_view_findzonecut() will not find them when we
06487                  * try to follow the referral, and we'll SERVFAIL
06488                  * because the best nameservers are now above QDOMAIN.
06489                  * We force the TTL to 1 second to prevent this.
06490                  */
06491                 if (ns_rdataset->ttl == 0)
06492                         ns_rdataset->ttl = 1;
06493                 /*
06494                  * Set the current query domain to the referral name.
06495                  *
06496                  * XXXRTH  We should check if we're in forward-only mode, and
06497                  *              if so we should bail out.
06498                  */
06499                 INSIST(dns_name_countlabels(&fctx->domain) > 0);
06500                 dns_name_free(&fctx->domain, fctx->mctx);
06501                 if (dns_rdataset_isassociated(&fctx->nameservers))
06502                         dns_rdataset_disassociate(&fctx->nameservers);
06503                 dns_name_init(&fctx->domain, NULL);
06504                 result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
06505                 if (result != ISC_R_SUCCESS)
06506                         return (result);
06507                 fctx->attributes |= FCTX_ATTR_WANTCACHE;
06508                 fctx->ns_ttl_ok = ISC_FALSE;
06509                 log_ns_ttl(fctx, "DELEGATION");
06510                 return (DNS_R_DELEGATION);
06511         }
06512 
06513         /*
06514          * Since we're not doing a referral, we don't want to cache any
06515          * NS RRs we may have found.
06516          */
06517         if (ns_name != NULL)
06518                 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
06519 
06520         if (negative_response && oqname == NULL)
06521                 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
06522 
06523         return (ISC_R_SUCCESS);
06524 }
06525 
06526 static isc_result_t
06527 answer_response(fetchctx_t *fctx) {
06528         isc_result_t result;
06529         dns_message_t *message;
06530         dns_name_t *name, *qname, tname, *ns_name;
06531         dns_rdataset_t *rdataset, *ns_rdataset;
06532         isc_boolean_t done, external, chaining, aa, found, want_chaining;
06533         isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
06534         unsigned int aflag;
06535         dns_rdatatype_t type;
06536         dns_fixedname_t dname, fqname;
06537         dns_view_t *view;
06538 
06539         FCTXTRACE("answer_response");
06540 
06541         message = fctx->rmessage;
06542 
06543         /*
06544          * Examine the answer section, marking those rdatasets which are
06545          * part of the answer and should be cached.
06546          */
06547 
06548         done = ISC_FALSE;
06549         found_cname = ISC_FALSE;
06550         found_type = ISC_FALSE;
06551         chaining = ISC_FALSE;
06552         have_answer = ISC_FALSE;
06553         want_chaining = ISC_FALSE;
06554         POST(want_chaining);
06555         if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
06556                 aa = ISC_TRUE;
06557         else
06558                 aa = ISC_FALSE;
06559         qname = &fctx->name;
06560         type = fctx->type;
06561         view = fctx->res->view;
06562         result = dns_message_firstname(message, DNS_SECTION_ANSWER);
06563         while (!done && result == ISC_R_SUCCESS) {
06564                 name = NULL;
06565                 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
06566                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
06567                 if (dns_name_equal(name, qname)) {
06568                         wanted_chaining = ISC_FALSE;
06569                         for (rdataset = ISC_LIST_HEAD(name->list);
06570                              rdataset != NULL;
06571                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
06572                                 found = ISC_FALSE;
06573                                 want_chaining = ISC_FALSE;
06574                                 aflag = 0;
06575                                 if (rdataset->type == dns_rdatatype_nsec3) {
06576                                         /*
06577                                          * NSEC3 records are not allowed to
06578                                          * appear in the answer section.
06579                                          */
06580                                         log_formerr(fctx, "NSEC3 in answer");
06581                                         return (DNS_R_FORMERR);
06582                                 }
06583 
06584                                 /*
06585                                  * Apply filters, if given, on answers to reject
06586                                  * a malicious attempt of rebinding.
06587                                  */
06588                                 if ((rdataset->type == dns_rdatatype_a ||
06589                                      rdataset->type == dns_rdatatype_aaaa) &&
06590                                     !is_answeraddress_allowed(view, name,
06591                                                               rdataset)) {
06592                                         return (DNS_R_SERVFAIL);
06593                                 }
06594 
06595                                 if (rdataset->type == type && !found_cname) {
06596                                         /*
06597                                          * We've found an ordinary answer.
06598                                          */
06599                                         found = ISC_TRUE;
06600                                         found_type = ISC_TRUE;
06601                                         done = ISC_TRUE;
06602                                         aflag = DNS_RDATASETATTR_ANSWER;
06603                                 } else if (type == dns_rdatatype_any) {
06604                                         /*
06605                                          * We've found an answer matching
06606                                          * an ANY query.  There may be
06607                                          * more.
06608                                          */
06609                                         found = ISC_TRUE;
06610                                         aflag = DNS_RDATASETATTR_ANSWER;
06611                                 } else if (rdataset->type == dns_rdatatype_rrsig
06612                                            && rdataset->covers == type
06613                                            && !found_cname) {
06614                                         /*
06615                                          * We've found a signature that
06616                                          * covers the type we're looking for.
06617                                          */
06618                                         found = ISC_TRUE;
06619                                         found_type = ISC_TRUE;
06620                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
06621                                 } else if (rdataset->type ==
06622                                            dns_rdatatype_cname
06623                                            && !found_type) {
06624                                         /*
06625                                          * We're looking for something else,
06626                                          * but we found a CNAME.
06627                                          *
06628                                          * Getting a CNAME response for some
06629                                          * query types is an error, see
06630                                          * RFC 4035, Section 2.5.
06631                                          */
06632                                         if (type == dns_rdatatype_rrsig ||
06633                                             type == dns_rdatatype_key ||
06634                                             type == dns_rdatatype_nsec) {
06635                                                 char buf[DNS_RDATATYPE_FORMATSIZE];
06636                                                 dns_rdatatype_format(fctx->type,
06637                                                               buf, sizeof(buf));
06638                                                 log_formerr(fctx,
06639                                                             "CNAME response "
06640                                                             "for %s RR", buf);
06641                                                 return (DNS_R_FORMERR);
06642                                         }
06643                                         found = ISC_TRUE;
06644                                         found_cname = ISC_TRUE;
06645                                         want_chaining = ISC_TRUE;
06646                                         aflag = DNS_RDATASETATTR_ANSWER;
06647                                         result = cname_target(rdataset,
06648                                                               &tname);
06649                                         if (result != ISC_R_SUCCESS)
06650                                                 return (result);
06651                                         /* Apply filters on the target name. */
06652                                         if (!is_answertarget_allowed(view,
06653                                                         name,
06654                                                         rdataset->type,
06655                                                         &tname,
06656                                                         &fctx->domain)) {
06657                                                 return (DNS_R_SERVFAIL);
06658                                         }
06659                                 } else if (rdataset->type == dns_rdatatype_rrsig
06660                                            && rdataset->covers ==
06661                                            dns_rdatatype_cname
06662                                            && !found_type) {
06663                                         /*
06664                                          * We're looking for something else,
06665                                          * but we found a SIG CNAME.
06666                                          */
06667                                         found = ISC_TRUE;
06668                                         found_cname = ISC_TRUE;
06669                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
06670                                 }
06671 
06672                                 if (found) {
06673                                         /*
06674                                          * We've found an answer to our
06675                                          * question.
06676                                          */
06677                                         name->attributes |=
06678                                                 DNS_NAMEATTR_CACHE;
06679                                         rdataset->attributes |=
06680                                                 DNS_RDATASETATTR_CACHE;
06681                                         rdataset->trust = dns_trust_answer;
06682                                         if (!chaining) {
06683                                                 /*
06684                                                  * This data is "the" answer
06685                                                  * to our question only if
06686                                                  * we're not chaining (i.e.
06687                                                  * if we haven't followed
06688                                                  * a CNAME or DNAME).
06689                                                  */
06690                                                 INSIST(!external);
06691                                                 if (aflag ==
06692                                                     DNS_RDATASETATTR_ANSWER)
06693                                                         have_answer = ISC_TRUE;
06694                                                 name->attributes |=
06695                                                         DNS_NAMEATTR_ANSWER;
06696                                                 rdataset->attributes |= aflag;
06697                                                 if (aa)
06698                                                         rdataset->trust =
06699                                                           dns_trust_authanswer;
06700                                         } else if (external) {
06701                                                 /*
06702                                                  * This data is outside of
06703                                                  * our query domain, and
06704                                                  * may not be cached.
06705                                                  */
06706                                                 rdataset->attributes |=
06707                                                     DNS_RDATASETATTR_EXTERNAL;
06708                                         }
06709 
06710                                         /*
06711                                          * Mark any additional data related
06712                                          * to this rdataset.
06713                                          */
06714                                         (void)dns_rdataset_additionaldata(
06715                                                         rdataset,
06716                                                         check_related,
06717                                                         fctx);
06718 
06719                                         /*
06720                                          * CNAME chaining.
06721                                          */
06722                                         if (want_chaining) {
06723                                                 wanted_chaining = ISC_TRUE;
06724                                                 name->attributes |=
06725                                                         DNS_NAMEATTR_CHAINING;
06726                                                 rdataset->attributes |=
06727                                                     DNS_RDATASETATTR_CHAINING;
06728                                                 qname = &tname;
06729                                         }
06730                                 }
06731                                 /*
06732                                  * We could add an "else" clause here and
06733                                  * log that we're ignoring this rdataset.
06734                                  */
06735                         }
06736                         /*
06737                          * If wanted_chaining is true, we've done
06738                          * some chaining as the result of processing
06739                          * this node, and thus we need to set
06740                          * chaining to true.
06741                          *
06742                          * We don't set chaining inside of the
06743                          * rdataset loop because doing that would
06744                          * cause us to ignore the signatures of
06745                          * CNAMEs.
06746                          */
06747                         if (wanted_chaining)
06748                                 chaining = ISC_TRUE;
06749                 } else {
06750                         /*
06751                          * Look for a DNAME (or its SIG).  Anything else is
06752                          * ignored.
06753                          */
06754                         wanted_chaining = ISC_FALSE;
06755                         for (rdataset = ISC_LIST_HEAD(name->list);
06756                              rdataset != NULL;
06757                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
06758                                 isc_boolean_t found_dname = ISC_FALSE;
06759                                 dns_name_t *dname_name;
06760 
06761                                 found = ISC_FALSE;
06762                                 aflag = 0;
06763                                 if (rdataset->type == dns_rdatatype_dname) {
06764                                         /*
06765                                          * We're looking for something else,
06766                                          * but we found a DNAME.
06767                                          *
06768                                          * If we're not chaining, then the
06769                                          * DNAME should not be external.
06770                                          */
06771                                         if (!chaining && external) {
06772                                                 log_formerr(fctx,
06773                                                             "external DNAME");
06774                                                 return (DNS_R_FORMERR);
06775                                         }
06776                                         found = ISC_TRUE;
06777                                         want_chaining = ISC_TRUE;
06778                                         POST(want_chaining);
06779                                         aflag = DNS_RDATASETATTR_ANSWER;
06780                                         result = dname_target(fctx, rdataset,
06781                                                               qname, name,
06782                                                               &dname);
06783                                         if (result == ISC_R_NOSPACE) {
06784                                                 /*
06785                                                  * We can't construct the
06786                                                  * DNAME target.  Do not
06787                                                  * try to continue.
06788                                                  */
06789                                                 want_chaining = ISC_FALSE;
06790                                                 POST(want_chaining);
06791                                         } else if (result != ISC_R_SUCCESS)
06792                                                 return (result);
06793                                         else
06794                                                 found_dname = ISC_TRUE;
06795 
06796                                         dname_name = dns_fixedname_name(&dname);
06797                                         if (!is_answertarget_allowed(view,
06798                                                         qname,
06799                                                         rdataset->type,
06800                                                         dname_name,
06801                                                         &fctx->domain)) {
06802                                                 return (DNS_R_SERVFAIL);
06803                                         }
06804                                 } else if (rdataset->type == dns_rdatatype_rrsig
06805                                            && rdataset->covers ==
06806                                            dns_rdatatype_dname) {
06807                                         /*
06808                                          * We've found a signature that
06809                                          * covers the DNAME.
06810                                          */
06811                                         found = ISC_TRUE;
06812                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
06813                                 }
06814 
06815                                 if (found) {
06816                                         /*
06817                                          * We've found an answer to our
06818                                          * question.
06819                                          */
06820                                         name->attributes |=
06821                                                 DNS_NAMEATTR_CACHE;
06822                                         rdataset->attributes |=
06823                                                 DNS_RDATASETATTR_CACHE;
06824                                         rdataset->trust = dns_trust_answer;
06825                                         if (!chaining) {
06826                                                 /*
06827                                                  * This data is "the" answer
06828                                                  * to our question only if
06829                                                  * we're not chaining.
06830                                                  */
06831                                                 INSIST(!external);
06832                                                 if (aflag ==
06833                                                     DNS_RDATASETATTR_ANSWER)
06834                                                         have_answer = ISC_TRUE;
06835                                                 name->attributes |=
06836                                                         DNS_NAMEATTR_ANSWER;
06837                                                 rdataset->attributes |= aflag;
06838                                                 if (aa)
06839                                                         rdataset->trust =
06840                                                           dns_trust_authanswer;
06841                                         } else if (external) {
06842                                                 rdataset->attributes |=
06843                                                     DNS_RDATASETATTR_EXTERNAL;
06844                                         }
06845 
06846                                         /*
06847                                          * DNAME chaining.
06848                                          */
06849                                         if (found_dname) {
06850                                                 /*
06851                                                  * Copy the dname into the
06852                                                  * qname fixed name.
06853                                                  *
06854                                                  * Although we check for
06855                                                  * failure of the copy
06856                                                  * operation, in practice it
06857                                                  * should never fail since
06858                                                  * we already know that the
06859                                                  * result fits in a fixedname.
06860                                                  */
06861                                                 dns_fixedname_init(&fqname);
06862                                                 result = dns_name_copy(
06863                                                   dns_fixedname_name(&dname),
06864                                                   dns_fixedname_name(&fqname),
06865                                                   NULL);
06866                                                 if (result != ISC_R_SUCCESS)
06867                                                         return (result);
06868                                                 wanted_chaining = ISC_TRUE;
06869                                                 name->attributes |=
06870                                                         DNS_NAMEATTR_CHAINING;
06871                                                 rdataset->attributes |=
06872                                                     DNS_RDATASETATTR_CHAINING;
06873                                                 qname = dns_fixedname_name(
06874                                                                    &fqname);
06875                                         }
06876                                 }
06877                         }
06878                         if (wanted_chaining)
06879                                 chaining = ISC_TRUE;
06880                 }
06881                 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
06882         }
06883         if (result == ISC_R_NOMORE)
06884                 result = ISC_R_SUCCESS;
06885         if (result != ISC_R_SUCCESS)
06886                 return (result);
06887 
06888         /*
06889          * We should have found an answer.
06890          */
06891         if (!have_answer) {
06892                 log_formerr(fctx, "reply has no answer");
06893                 return (DNS_R_FORMERR);
06894         }
06895 
06896         /*
06897          * This response is now potentially cacheable.
06898          */
06899         fctx->attributes |= FCTX_ATTR_WANTCACHE;
06900 
06901         /*
06902          * Did chaining end before we got the final answer?
06903          */
06904         if (chaining) {
06905                 /*
06906                  * Yes.  This may be a negative reply, so hand off
06907                  * authority section processing to the noanswer code.
06908                  * If it isn't a noanswer response, no harm will be
06909                  * done.
06910                  */
06911                 return (noanswer_response(fctx, qname, 0));
06912         }
06913 
06914         /*
06915          * We didn't end with an incomplete chain, so the rcode should be
06916          * "no error".
06917          */
06918         if (message->rcode != dns_rcode_noerror) {
06919                 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
06920                                   "indicates error");
06921                 return (DNS_R_FORMERR);
06922         }
06923 
06924         /*
06925          * Examine the authority section (if there is one).
06926          *
06927          * We expect there to be only one owner name for all the rdatasets
06928          * in this section, and we expect that it is not external.
06929          */
06930         done = ISC_FALSE;
06931         ns_name = NULL;
06932         ns_rdataset = NULL;
06933         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
06934         while (!done && result == ISC_R_SUCCESS) {
06935                 name = NULL;
06936                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
06937                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
06938                 if (!external) {
06939                         /*
06940                          * We expect to find NS or SIG NS rdatasets, and
06941                          * nothing else.
06942                          */
06943                         for (rdataset = ISC_LIST_HEAD(name->list);
06944                              rdataset != NULL;
06945                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
06946                                 if (rdataset->type == dns_rdatatype_ns ||
06947                                     (rdataset->type == dns_rdatatype_rrsig &&
06948                                      rdataset->covers == dns_rdatatype_ns)) {
06949                                         name->attributes |=
06950                                                 DNS_NAMEATTR_CACHE;
06951                                         rdataset->attributes |=
06952                                                 DNS_RDATASETATTR_CACHE;
06953                                         if (aa && !chaining)
06954                                                 rdataset->trust =
06955                                                     dns_trust_authauthority;
06956                                         else
06957                                                 rdataset->trust =
06958                                                     dns_trust_additional;
06959 
06960                                         if (rdataset->type == dns_rdatatype_ns) {
06961                                                 ns_name = name;
06962                                                 ns_rdataset = rdataset;
06963                                         }
06964                                         /*
06965                                          * Mark any additional data related
06966                                          * to this rdataset.
06967                                          */
06968                                         (void)dns_rdataset_additionaldata(
06969                                                         rdataset,
06970                                                         check_related,
06971                                                         fctx);
06972                                         done = ISC_TRUE;
06973                                 }
06974                         }
06975                 }
06976                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
06977         }
06978         if (result == ISC_R_NOMORE)
06979                 result = ISC_R_SUCCESS;
06980 
06981         log_ns_ttl(fctx, "answer_response");
06982 
06983         if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
06984             !dns_name_equal(ns_name, dns_rootname))
06985                 trim_ns_ttl(fctx, ns_name, ns_rdataset);
06986 
06987         return (result);
06988 }
06989 
06990 static void
06991 fctx_increference(fetchctx_t *fctx) {
06992         REQUIRE(VALID_FCTX(fctx));
06993 
06994         LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
06995         fctx->references++;
06996         UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
06997 }
06998 
06999 static isc_boolean_t
07000 fctx_decreference(fetchctx_t *fctx) {
07001         isc_boolean_t bucket_empty = ISC_FALSE;
07002 
07003         REQUIRE(VALID_FCTX(fctx));
07004 
07005         INSIST(fctx->references > 0);
07006         fctx->references--;
07007         if (fctx->references == 0) {
07008                 /*
07009                  * No one cares about the result of this fetch anymore.
07010                  */
07011                 if (fctx->pending == 0 && fctx->nqueries == 0 &&
07012                     ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
07013                         /*
07014                          * This fctx is already shutdown; we were just
07015                          * waiting for the last reference to go away.
07016                          */
07017                         bucket_empty = fctx_unlink(fctx);
07018                         fctx_destroy(fctx);
07019                 } else {
07020                         /*
07021                          * Initiate shutdown.
07022                          */
07023                         fctx_shutdown(fctx);
07024                 }
07025         }
07026         return (bucket_empty);
07027 }
07028 
07029 static void
07030 resume_dslookup(isc_task_t *task, isc_event_t *event) {
07031         dns_fetchevent_t *fevent;
07032         dns_resolver_t *res;
07033         fetchctx_t *fctx;
07034         isc_result_t result;
07035         isc_boolean_t bucket_empty;
07036         isc_boolean_t locked = ISC_FALSE;
07037         unsigned int bucketnum;
07038         dns_rdataset_t nameservers;
07039         dns_fixedname_t fixed;
07040         dns_name_t *domain;
07041 
07042         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
07043         fevent = (dns_fetchevent_t *)event;
07044         fctx = event->ev_arg;
07045         REQUIRE(VALID_FCTX(fctx));
07046         res = fctx->res;
07047 
07048         UNUSED(task);
07049         FCTXTRACE("resume_dslookup");
07050 
07051         if (fevent->node != NULL)
07052                 dns_db_detachnode(fevent->db, &fevent->node);
07053         if (fevent->db != NULL)
07054                 dns_db_detach(&fevent->db);
07055 
07056         dns_rdataset_init(&nameservers);
07057 
07058         bucketnum = fctx->bucketnum;
07059         if (fevent->result == ISC_R_CANCELED) {
07060                 dns_resolver_destroyfetch(&fctx->nsfetch);
07061                 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
07062         } else if (fevent->result == ISC_R_SUCCESS) {
07063 
07064                 FCTXTRACE("resuming DS lookup");
07065 
07066                 dns_resolver_destroyfetch(&fctx->nsfetch);
07067                 if (dns_rdataset_isassociated(&fctx->nameservers))
07068                         dns_rdataset_disassociate(&fctx->nameservers);
07069                 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
07070                 fctx->ns_ttl = fctx->nameservers.ttl;
07071                 fctx->ns_ttl_ok = ISC_TRUE;
07072                 log_ns_ttl(fctx, "resume_dslookup");
07073                 dns_name_free(&fctx->domain, fctx->mctx);
07074                 dns_name_init(&fctx->domain, NULL);
07075                 result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
07076                 if (result != ISC_R_SUCCESS) {
07077                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
07078                         goto cleanup;
07079                 }
07080                 /*
07081                  * Try again.
07082                  */
07083                 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
07084         } else {
07085                 unsigned int n;
07086                 dns_rdataset_t *nsrdataset = NULL;
07087 
07088                 /*
07089                  * Retrieve state from fctx->nsfetch before we destroy it.
07090                  */
07091                 dns_fixedname_init(&fixed);
07092                 domain = dns_fixedname_name(&fixed);
07093                 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
07094                 if (dns_name_equal(&fctx->nsname, domain)) {
07095                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
07096                         dns_resolver_destroyfetch(&fctx->nsfetch);
07097                         goto cleanup;
07098                 }
07099                 if (dns_rdataset_isassociated(
07100                     &fctx->nsfetch->private->nameservers)) {
07101                         dns_rdataset_clone(
07102                             &fctx->nsfetch->private->nameservers,
07103                             &nameservers);
07104                         nsrdataset = &nameservers;
07105                 } else
07106                         domain = NULL;
07107                 dns_resolver_destroyfetch(&fctx->nsfetch);
07108                 n = dns_name_countlabels(&fctx->nsname);
07109                 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
07110                                           &fctx->nsname);
07111 
07112                 if (dns_rdataset_isassociated(fevent->rdataset))
07113                         dns_rdataset_disassociate(fevent->rdataset);
07114                 FCTXTRACE("continuing to look for parent's NS records");
07115                 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
07116                                                   dns_rdatatype_ns, domain,
07117                                                   nsrdataset, NULL,
07118                                                   fctx->options, task,
07119                                                   resume_dslookup, fctx,
07120                                                   &fctx->nsrrset, NULL,
07121                                                   &fctx->nsfetch);
07122                 if (result != ISC_R_SUCCESS)
07123                         fctx_done(fctx, result, __LINE__);
07124                 else {
07125                         LOCK(&res->buckets[bucketnum].lock);
07126                         locked = ISC_TRUE;
07127                         fctx->references++;
07128                 }
07129         }
07130 
07131  cleanup:
07132         if (dns_rdataset_isassociated(&nameservers))
07133                 dns_rdataset_disassociate(&nameservers);
07134         if (dns_rdataset_isassociated(fevent->rdataset))
07135                 dns_rdataset_disassociate(fevent->rdataset);
07136         INSIST(fevent->sigrdataset == NULL);
07137         isc_event_free(&event);
07138         if (!locked)
07139                 LOCK(&res->buckets[bucketnum].lock);
07140         bucket_empty = fctx_decreference(fctx);
07141         UNLOCK(&res->buckets[bucketnum].lock);
07142         if (bucket_empty)
07143                 empty_bucket(res);
07144 }
07145 
07146 static inline void
07147 checknamessection(dns_message_t *message, dns_section_t section) {
07148         isc_result_t result;
07149         dns_name_t *name;
07150         dns_rdata_t rdata = DNS_RDATA_INIT;
07151         dns_rdataset_t *rdataset;
07152 
07153         for (result = dns_message_firstname(message, section);
07154              result == ISC_R_SUCCESS;
07155              result = dns_message_nextname(message, section))
07156         {
07157                 name = NULL;
07158                 dns_message_currentname(message, section, &name);
07159                 for (rdataset = ISC_LIST_HEAD(name->list);
07160                      rdataset != NULL;
07161                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
07162                         for (result = dns_rdataset_first(rdataset);
07163                              result == ISC_R_SUCCESS;
07164                              result = dns_rdataset_next(rdataset)) {
07165                                 dns_rdataset_current(rdataset, &rdata);
07166                                 if (!dns_rdata_checkowner(name, rdata.rdclass,
07167                                                           rdata.type,
07168                                                           ISC_FALSE) ||
07169                                     !dns_rdata_checknames(&rdata, name, NULL))
07170                                 {
07171                                         rdataset->attributes |=
07172                                                 DNS_RDATASETATTR_CHECKNAMES;
07173                                 }
07174                                 dns_rdata_reset(&rdata);
07175                         }
07176                 }
07177         }
07178 }
07179 
07180 static void
07181 checknames(dns_message_t *message) {
07182 
07183         checknamessection(message, DNS_SECTION_ANSWER);
07184         checknamessection(message, DNS_SECTION_AUTHORITY);
07185         checknamessection(message, DNS_SECTION_ADDITIONAL);
07186 }
07187 
07188 /*
07189  * Log server NSID at log level 'level'
07190  */
07191 static void
07192 log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query,
07193          int level, isc_mem_t *mctx)
07194 {
07195         static const char hex[17] = "0123456789abcdef";
07196         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
07197         isc_uint16_t buflen, i;
07198         unsigned char *p, *nsid;
07199         unsigned char *buf = NULL, *pbuf = NULL;
07200 
07201         /* Allocate buffer for storing hex version of the NSID */
07202         buflen = (isc_uint16_t)nsid_len * 2 + 1;
07203         buf = isc_mem_get(mctx, buflen);
07204         if (buf == NULL)
07205                 goto cleanup;
07206         pbuf = isc_mem_get(mctx, nsid_len + 1);
07207         if (pbuf == NULL)
07208                 goto cleanup;
07209 
07210         /* Convert to hex */
07211         p = buf;
07212         nsid = isc_buffer_current(opt);
07213         for (i = 0; i < nsid_len; i++) {
07214                 *p++ = hex[(nsid[i] >> 4) & 0xf];
07215                 *p++ = hex[nsid[i] & 0xf];
07216         }
07217         *p = '\0';
07218 
07219         /* Make printable version */
07220         p = pbuf;
07221         for (i = 0; i < nsid_len; i++) {
07222                 if (isprint(nsid[i]))
07223                         *p++ = nsid[i];
07224                 else
07225                         *p++ = '.';
07226         }
07227         *p = '\0';
07228 
07229         isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
07230                             sizeof(addrbuf));
07231         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
07232                       DNS_LOGMODULE_RESOLVER, level,
07233                       "received NSID %s (\"%s\") from %s", buf, pbuf, addrbuf);
07234  cleanup:
07235         if (pbuf != NULL)
07236                 isc_mem_put(mctx, pbuf, nsid_len + 1);
07237         if (buf != NULL)
07238                 isc_mem_put(mctx, buf, buflen);
07239 }
07240 
07241 static isc_boolean_t
07242 iscname(fetchctx_t *fctx) {
07243         isc_result_t result;
07244 
07245         result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
07246                                       &fctx->name, dns_rdatatype_cname, 0,
07247                                       NULL, NULL);
07248         return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
07249 }
07250 
07251 static isc_boolean_t
07252 betterreferral(fetchctx_t *fctx) {
07253         isc_result_t result;
07254         dns_name_t *name;
07255         dns_rdataset_t *rdataset;
07256         dns_message_t *message = fctx->rmessage;
07257 
07258         for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
07259              result == ISC_R_SUCCESS;
07260              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
07261                 name = NULL;
07262                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
07263                 if (!isstrictsubdomain(name, &fctx->domain))
07264                         continue;
07265                 for (rdataset = ISC_LIST_HEAD(name->list);
07266                      rdataset != NULL;
07267                      rdataset = ISC_LIST_NEXT(rdataset, link))
07268                         if (rdataset->type == dns_rdatatype_ns)
07269                                 return (ISC_TRUE);
07270         }
07271         return (ISC_FALSE);
07272 }
07273 
07274 static void
07275 process_opt(resquery_t *query, dns_rdataset_t *opt) {
07276         dns_rdata_t rdata;
07277         isc_buffer_t optbuf;
07278         isc_result_t result;
07279         isc_uint16_t optcode;
07280         isc_uint16_t optlen;
07281 #ifdef ISC_PLATFORM_USESIT
07282         unsigned char *sit;
07283         dns_adbaddrinfo_t *addrinfo;
07284         unsigned char cookie[8];
07285 #endif
07286 
07287         result = dns_rdataset_first(opt);
07288         if (result == ISC_R_SUCCESS) {
07289                 dns_rdata_init(&rdata);
07290                 dns_rdataset_current(opt, &rdata);
07291                 isc_buffer_init(&optbuf, rdata.data, rdata.length);
07292                 isc_buffer_add(&optbuf, rdata.length);
07293                 while (isc_buffer_remaininglength(&optbuf) >= 4) {
07294                         optcode = isc_buffer_getuint16(&optbuf);
07295                         optlen = isc_buffer_getuint16(&optbuf);
07296                         INSIST(optlen <= isc_buffer_remaininglength(&optbuf));
07297                         switch (optcode) {
07298                         case DNS_OPT_NSID:
07299                                 if (query->options & DNS_FETCHOPT_WANTNSID)
07300                                         log_nsid(&optbuf, optlen, query,
07301                                                  ISC_LOG_DEBUG(3),
07302                                                  query->fctx->res->mctx);
07303                                 isc_buffer_forward(&optbuf, optlen);
07304                                 break;
07305 #ifdef ISC_PLATFORM_USESIT
07306                         case DNS_OPT_SIT:
07307                                 sit = isc_buffer_current(&optbuf);
07308                                 compute_cc(query, cookie, sizeof(cookie));
07309                                 INSIST(query->fctx->rmessage->sitbad == 0 &&
07310                                        query->fctx->rmessage->sitok == 0);
07311                                 if (optlen >= 8U &&
07312                                     memcmp(cookie, sit, 8) == 0) {
07313                                         query->fctx->rmessage->sitok = 1;
07314                                         inc_stats(query->fctx->res,
07315                                                   dns_resstatscounter_sitok);
07316                                         addrinfo = query->addrinfo;
07317                                         dns_adb_setsit(query->fctx->adb,
07318                                                        addrinfo, sit, optlen);
07319                                 } else
07320                                         query->fctx->rmessage->sitbad = 1;
07321                                 isc_buffer_forward(&optbuf, optlen);
07322                                 inc_stats(query->fctx->res,
07323                                           dns_resstatscounter_sitin);
07324                                 break;
07325 #endif
07326                         default:
07327                                 isc_buffer_forward(&optbuf, optlen);
07328                                 break;
07329                         }
07330                 }
07331                 INSIST(isc_buffer_remaininglength(&optbuf) == 0U);
07332         }
07333 }
07334 
07335 static void
07336 resquery_response(isc_task_t *task, isc_event_t *event) {
07337         isc_result_t result = ISC_R_SUCCESS;
07338         resquery_t *query = event->ev_arg;
07339         dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
07340         isc_boolean_t keep_trying, get_nameservers, resend;
07341         isc_boolean_t truncated;
07342         dns_message_t *message;
07343         dns_rdataset_t *opt;
07344         fetchctx_t *fctx;
07345         dns_name_t *fname;
07346         dns_fixedname_t foundname;
07347         isc_stdtime_t now;
07348         isc_time_t tnow, *finish;
07349         dns_adbaddrinfo_t *addrinfo;
07350         unsigned int options;
07351         unsigned int findoptions;
07352         isc_result_t broken_server;
07353         badnstype_t broken_type = badns_response;
07354         isc_boolean_t no_response;
07355 
07356         REQUIRE(VALID_QUERY(query));
07357         fctx = query->fctx;
07358         options = query->options;
07359         REQUIRE(VALID_FCTX(fctx));
07360         REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
07361 
07362         QTRACE("response");
07363 
07364         if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
07365                 inc_stats(fctx->res, dns_resstatscounter_responsev4);
07366         else
07367                 inc_stats(fctx->res, dns_resstatscounter_responsev6);
07368 
07369         (void)isc_timer_touch(fctx->timer);
07370 
07371         keep_trying = ISC_FALSE;
07372         broken_server = ISC_R_SUCCESS;
07373         get_nameservers = ISC_FALSE;
07374         resend = ISC_FALSE;
07375         truncated = ISC_FALSE;
07376         finish = NULL;
07377         no_response = ISC_FALSE;
07378 
07379         if (fctx->res->exiting) {
07380                 result = ISC_R_SHUTTINGDOWN;
07381                 FCTXTRACE("resolver shutting down");
07382                 goto done;
07383         }
07384 
07385         fctx->timeouts = 0;
07386         fctx->timeout = ISC_FALSE;
07387         fctx->addrinfo = query->addrinfo;
07388 
07389         /*
07390          * XXXRTH  We should really get the current time just once.  We
07391          *              need a routine to convert from an isc_time_t to an
07392          *              isc_stdtime_t.
07393          */
07394         TIME_NOW(&tnow);
07395         finish = &tnow;
07396         isc_stdtime_get(&now);
07397 
07398         /*
07399          * Did the dispatcher have a problem?
07400          */
07401         if (devent->result != ISC_R_SUCCESS) {
07402                 if (devent->result == ISC_R_EOF &&
07403                     (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07404                         /*
07405                          * The problem might be that they
07406                          * don't understand EDNS0.  Turn it
07407                          * off and try again.
07408                          */
07409                         options |= DNS_FETCHOPT_NOEDNS0;
07410                         resend = ISC_TRUE;
07411                         add_bad_edns(fctx, &query->addrinfo->sockaddr);
07412                 } else {
07413                         /*
07414                          * There's no hope for this query.
07415                          */
07416                         keep_trying = ISC_TRUE;
07417 
07418                         /*
07419                          * If this is a network error on an exclusive query
07420                          * socket, mark the server as bad so that we won't try
07421                          * it for this fetch again.  Also adjust finish and
07422                          * no_response so that we penalize this address in SRTT
07423                          * adjustment later.
07424                          */
07425                         if (query->exclusivesocket &&
07426                             (devent->result == ISC_R_HOSTUNREACH ||
07427                              devent->result == ISC_R_NETUNREACH ||
07428                              devent->result == ISC_R_CONNREFUSED ||
07429                              devent->result == ISC_R_CANCELED)) {
07430                                     broken_server = devent->result;
07431                                     broken_type = badns_unreachable;
07432                                     finish = NULL;
07433                                     no_response = ISC_TRUE;
07434                         }
07435                 }
07436                 FCTXTRACE3("dispatcher failure", devent->result);
07437                 goto done;
07438         }
07439 
07440         message = fctx->rmessage;
07441 
07442         if (query->tsig != NULL) {
07443                 result = dns_message_setquerytsig(message, query->tsig);
07444                 if (result != ISC_R_SUCCESS) {
07445                         FCTXTRACE3("unable to set query tsig", result);
07446                         goto done;
07447                 }
07448         }
07449 
07450         if (query->tsigkey) {
07451                 result = dns_message_settsigkey(message, query->tsigkey);
07452                 if (result != ISC_R_SUCCESS) {
07453                         FCTXTRACE3("unable to set tsig key", result);
07454                         goto done;
07455                 }
07456         }
07457 
07458         if ((options & DNS_FETCHOPT_TCP) == 0) {
07459                 if ((options & DNS_FETCHOPT_NOEDNS0) == 0)
07460                         dns_adb_setudpsize(fctx->adb, query->addrinfo,
07461                                    isc_buffer_usedlength(&devent->buffer));
07462                 else
07463                         dns_adb_plainresponse(fctx->adb, query->addrinfo);
07464         }
07465         result = dns_message_parse(message, &devent->buffer, 0);
07466         if (result != ISC_R_SUCCESS) {
07467                 FCTXTRACE3("message failed to parse", result);
07468                 switch (result) {
07469                 case ISC_R_UNEXPECTEDEND:
07470                         if (!message->question_ok ||
07471                             (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
07472                             (options & DNS_FETCHOPT_TCP) != 0) {
07473                                 /*
07474                                  * Either the message ended prematurely,
07475                                  * and/or wasn't marked as being truncated,
07476                                  * and/or this is a response to a query we
07477                                  * sent over TCP.  In all of these cases,
07478                                  * something is wrong with the remote
07479                                  * server and we don't want to retry using
07480                                  * TCP.
07481                                  */
07482                                 if ((query->options & DNS_FETCHOPT_NOEDNS0)
07483                                     == 0) {
07484                                         /*
07485                                          * The problem might be that they
07486                                          * don't understand EDNS0.  Turn it
07487                                          * off and try again.
07488                                          */
07489                                         options |= DNS_FETCHOPT_NOEDNS0;
07490                                         resend = ISC_TRUE;
07491                                         add_bad_edns(fctx,
07492                                                     &query->addrinfo->sockaddr);
07493                                         inc_stats(fctx->res,
07494                                                  dns_resstatscounter_edns0fail);
07495                                 } else {
07496                                         broken_server = result;
07497                                         keep_trying = ISC_TRUE;
07498                                 }
07499                                 goto done;
07500                         }
07501                         /*
07502                          * We defer retrying via TCP for a bit so we can
07503                          * check out this message further.
07504                          */
07505                         truncated = ISC_TRUE;
07506                         break;
07507                 case DNS_R_FORMERR:
07508                         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07509                                 /*
07510                                  * The problem might be that they
07511                                  * don't understand EDNS0.  Turn it
07512                                  * off and try again.
07513                                  */
07514                                 options |= DNS_FETCHOPT_NOEDNS0;
07515                                 resend = ISC_TRUE;
07516                                 add_bad_edns(fctx, &query->addrinfo->sockaddr);
07517                                 inc_stats(fctx->res,
07518                                                  dns_resstatscounter_edns0fail);
07519                         } else {
07520                                 broken_server = DNS_R_UNEXPECTEDRCODE;
07521                                 keep_trying = ISC_TRUE;
07522                         }
07523                         goto done;
07524                 default:
07525                         /*
07526                          * Something bad has happened.
07527                          */
07528                         goto done;
07529                 }
07530         }
07531 
07532         /*
07533          * Log the incoming packet.
07534          */
07535         dns_message_logfmtpacket2(message, "received packet from",
07536                                   &query->addrinfo->sockaddr,
07537                                   DNS_LOGCATEGORY_RESOLVER,
07538                                   DNS_LOGMODULE_PACKETS,
07539                                   &dns_master_style_comment,
07540                                   ISC_LOG_DEBUG(10),
07541                                   fctx->res->mctx);
07542         /*
07543          * Process receive opt record.
07544          */
07545         opt = dns_message_getopt(message);
07546         if (opt != NULL)
07547                 process_opt(query, opt);
07548 
07549 #ifdef notyet
07550 #ifdef ISC_PLATFORM_USESIT
07551         if (message->sitbad) {
07552                 /*
07553                  * If the SIT is bad assume it is a attack and retry.
07554                  */
07555                 resend = ISC_TRUE;
07556                 /* XXXMPA log it */
07557                 FCTXTRACE("bad sit");
07558                 goto done;
07559         }
07560 #endif
07561 #endif
07562 
07563         /*
07564          * If the message is signed, check the signature.  If not, this
07565          * returns success anyway.
07566          */
07567         result = dns_message_checksig(message, fctx->res->view);
07568         if (result != ISC_R_SUCCESS) {
07569                 FCTXTRACE3("signature check failed", result);
07570                 goto done;
07571         }
07572 
07573         /*
07574          * The dispatcher should ensure we only get responses with QR set.
07575          */
07576         INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
07577         /*
07578          * INSIST() that the message comes from the place we sent it to,
07579          * since the dispatch code should ensure this.
07580          *
07581          * INSIST() that the message id is correct (this should also be
07582          * ensured by the dispatch code).
07583          */
07584 
07585         /*
07586          * We have an affirmative response to the query and we have
07587          * previously got a response from this server which indicated
07588          * EDNS may not be supported so we can now cache the lack of
07589          * EDNS support.
07590          */
07591         if (opt == NULL && !EDNSOK(query->addrinfo) &&
07592             (message->rcode == dns_rcode_noerror ||
07593              message->rcode == dns_rcode_nxdomain ||
07594              message->rcode == dns_rcode_refused ||
07595              message->rcode == dns_rcode_yxdomain) &&
07596              bad_edns(fctx, &query->addrinfo->sockaddr)) {
07597                 dns_message_logpacket2(message,
07598                                        "received packet (bad edns) from",
07599                                        &query->addrinfo->sockaddr,
07600                                        DNS_LOGCATEGORY_RESOLVER,
07601                                        DNS_LOGMODULE_RESOLVER,
07602                                        ISC_LOG_DEBUG(3),
07603                                        fctx->res->mctx);
07604                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07605                                     DNS_FETCHOPT_NOEDNS0,
07606                                     DNS_FETCHOPT_NOEDNS0);
07607         } else if (opt == NULL && (message->flags & DNS_MESSAGEFLAG_TC) == 0 &&
07608                    !EDNSOK(query->addrinfo) &&
07609                    (message->rcode == dns_rcode_noerror ||
07610                     message->rcode == dns_rcode_nxdomain) &&
07611                    (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07612                 /*
07613                  * We didn't get a OPT record in response to a EDNS query.
07614                  *
07615                  * Old versions of named incorrectly drop the OPT record
07616                  * when there is a signed, truncated response so we check
07617                  * that TC is not set.
07618                  *
07619                  * Record that the server is not talking EDNS.  While this
07620                  * should be safe to do for any rcode we limit it to NOERROR
07621                  * and NXDOMAIN.
07622                  */
07623                 dns_message_logpacket2(message, "received packet (no opt) from",
07624                                        &query->addrinfo->sockaddr,
07625                                        DNS_LOGCATEGORY_RESOLVER,
07626                                        DNS_LOGMODULE_RESOLVER,
07627                                        ISC_LOG_DEBUG(3),
07628                                        fctx->res->mctx);
07629                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07630                                     DNS_FETCHOPT_NOEDNS0,
07631                                     DNS_FETCHOPT_NOEDNS0);
07632         }
07633 
07634         /*
07635          * If we get a non error EDNS response record the fact so we
07636          * won't fallback to plain DNS in the future for this server.
07637          */
07638         if (opt != NULL && !EDNSOK(query->addrinfo) &&
07639             (query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
07640             (message->rcode == dns_rcode_noerror ||
07641              message->rcode == dns_rcode_nxdomain ||
07642              message->rcode == dns_rcode_refused ||
07643              message->rcode == dns_rcode_yxdomain)) {
07644                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07645                                     FCTX_ADDRINFO_EDNSOK,
07646                                     FCTX_ADDRINFO_EDNSOK);
07647         }
07648 
07649         /*
07650          * Deal with truncated responses by retrying using TCP.
07651          */
07652         if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
07653                 truncated = ISC_TRUE;
07654 
07655         if (truncated) {
07656                 inc_stats(fctx->res, dns_resstatscounter_truncated);
07657                 if ((options & DNS_FETCHOPT_TCP) != 0) {
07658                         broken_server = DNS_R_TRUNCATEDTCP;
07659                         keep_trying = ISC_TRUE;
07660                 } else {
07661                         options |= DNS_FETCHOPT_TCP;
07662                         resend = ISC_TRUE;
07663                 }
07664                 FCTXTRACE3("message truncated", result);
07665                 goto done;
07666         }
07667 
07668         /*
07669          * Is it a query response?
07670          */
07671         if (message->opcode != dns_opcode_query) {
07672                 /* XXXRTH Log */
07673                 broken_server = DNS_R_UNEXPECTEDOPCODE;
07674                 keep_trying = ISC_TRUE;
07675                 FCTXTRACE("invalid message opcode");
07676                 goto done;
07677         }
07678 
07679         /*
07680          * Update statistics about erroneous responses.
07681          */
07682         if (message->rcode != dns_rcode_noerror) {
07683                 switch (message->rcode) {
07684                 case dns_rcode_nxdomain:
07685                         inc_stats(fctx->res, dns_resstatscounter_nxdomain);
07686                         break;
07687                 case dns_rcode_servfail:
07688                         inc_stats(fctx->res, dns_resstatscounter_servfail);
07689                         break;
07690                 case dns_rcode_formerr:
07691                         inc_stats(fctx->res, dns_resstatscounter_formerr);
07692                         break;
07693                 case dns_rcode_refused:
07694                         inc_stats(fctx->res, dns_resstatscounter_refused);
07695                         break;
07696                 case dns_rcode_badvers:
07697                         inc_stats(fctx->res, dns_resstatscounter_badvers);
07698                         break;
07699                 default:
07700                         inc_stats(fctx->res, dns_resstatscounter_othererror);
07701                         break;
07702                 }
07703         }
07704 
07705         /*
07706          * Is the remote server broken, or does it dislike us?
07707          */
07708         if (message->rcode != dns_rcode_noerror &&
07709             message->rcode != dns_rcode_nxdomain) {
07710                 isc_buffer_t b;
07711                 char code[64];
07712 #ifdef ISC_PLATFORM_USESIT
07713                 unsigned char sit[64];
07714 
07715                 /*
07716                  * Some servers do not ignore unknown EDNS options.
07717                  */
07718                 if (!NOSIT(query->addrinfo) &&
07719                     (message->rcode == dns_rcode_formerr ||
07720                      message->rcode == dns_rcode_notimp ||
07721                      message->rcode == dns_rcode_refused) &&
07722                      dns_adb_getsit(fctx->adb, query->addrinfo,
07723                                    sit, sizeof(sit)) == 0U) {
07724                         dns_adb_changeflags(fctx->adb, query->addrinfo,
07725                                             FCTX_ADDRINFO_NOSIT,
07726                                             FCTX_ADDRINFO_NOSIT);
07727                         resend = ISC_TRUE;
07728                 } else
07729 #endif
07730                 if (((message->rcode == dns_rcode_formerr ||
07731                       message->rcode == dns_rcode_notimp) ||
07732                      (message->rcode == dns_rcode_servfail &&
07733                       dns_message_getopt(message) == NULL)) &&
07734                     (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
07735                         /*
07736                          * It's very likely they don't like EDNS0.
07737                          * If the response code is SERVFAIL, also check if the
07738                          * response contains an OPT RR and don't cache the
07739                          * failure since it can be returned for various other
07740                          * reasons.
07741                          *
07742                          * XXXRTH  We should check if the question
07743                          *              we're asking requires EDNS0, and
07744                          *              if so, we should bail out.
07745                          */
07746                         options |= DNS_FETCHOPT_NOEDNS0;
07747                         resend = ISC_TRUE;
07748                         /*
07749                          * Remember that they may not like EDNS0.
07750                          */
07751                         add_bad_edns(fctx, &query->addrinfo->sockaddr);
07752                         inc_stats(fctx->res, dns_resstatscounter_edns0fail);
07753                 } else if (message->rcode == dns_rcode_formerr) {
07754                         if (ISFORWARDER(query->addrinfo)) {
07755                                 /*
07756                                  * This forwarder doesn't understand us,
07757                                  * but other forwarders might.  Keep trying.
07758                                  */
07759                                 broken_server = DNS_R_REMOTEFORMERR;
07760                                 keep_trying = ISC_TRUE;
07761                         } else {
07762                                 /*
07763                                  * The server doesn't understand us.  Since
07764                                  * all servers for a zone need similar
07765                                  * capabilities, we assume that we will get
07766                                  * FORMERR from all servers, and thus we
07767                                  * cannot make any more progress with this
07768                                  * fetch.
07769                                  */
07770                                 log_formerr(fctx, "server sent FORMERR");
07771                                 result = DNS_R_FORMERR;
07772                         }
07773                 } else if (message->rcode == dns_rcode_yxdomain) {
07774                         /*
07775                          * DNAME mapping failed because the new name
07776                          * was too long.  There's no chance of success
07777                          * for this fetch.
07778                          */
07779                         result = DNS_R_YXDOMAIN;
07780                 } else if (message->rcode == dns_rcode_badvers) {
07781                         unsigned int flags, mask;
07782                         unsigned int version;
07783 #if defined(ISC_PLATFORM_USESIT) && DNS_EDNS_VERSION == 0
07784                         /*
07785                          * Some servers return BADVERS to unknown
07786                          * EDNS options.  This cannot be long term
07787                          * strategy.  Do not disable SIT if we have
07788                          * already have received a SIT from this
07789                          * server.
07790                          */
07791                         if (dns_adb_getsit(fctx->adb, query->addrinfo,
07792                                            sit, sizeof(sit)) == 0U) {
07793                                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07794                                                     FCTX_ADDRINFO_NOSIT,
07795                                                     FCTX_ADDRINFO_NOSIT);
07796                         }
07797 #endif
07798 
07799                         resend = ISC_TRUE;
07800                         INSIST(opt != NULL);
07801                         version = (opt->ttl >> 16) & 0xff;
07802                         flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
07803                                 DNS_FETCHOPT_EDNSVERSIONSET;
07804                         mask = DNS_FETCHOPT_EDNSVERSIONMASK |
07805                                DNS_FETCHOPT_EDNSVERSIONSET;
07806                         /*
07807                          * Record that we got a good EDNS response.
07808                          */
07809                         if (query->ednsversion > (int)version &&
07810                             !EDNSOK(query->addrinfo)) {
07811                                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07812                                                     FCTX_ADDRINFO_EDNSOK,
07813                                                     FCTX_ADDRINFO_EDNSOK);
07814                         }
07815                         /*
07816                          * XXXMPA we should really test against the version of
07817                          * EDNS we sent in the request.  Some servers return
07818                          * BADVERS for unknown EDNS options.
07819                          * RFC 2671 was not clear that they should be ignored.
07820                          * RFC 6891 is clear that that they should be ignored.
07821                          * If we are supporting EDNS > 0 then perform strict
07822                          * version checking of badvers responses.  We won't
07823                          * be sending SIT etc. in that case.
07824                          */
07825 #if DNS_EDNS_VERSION == 0
07826                          /* Avoids a compiler warning with < 0 */
07827                         if (version <= DNS_EDNS_VERSION)
07828 #else
07829                         if (version < DNS_EDNS_VERSION)
07830 #endif
07831                         {
07832                                 dns_adb_changeflags(fctx->adb, query->addrinfo,
07833                                                     flags, mask);
07834                         } else {
07835                                 broken_server = DNS_R_BADVERS;
07836                                 keep_trying = ISC_TRUE;
07837                         }
07838                 } else {
07839                         /*
07840                          * XXXRTH log.
07841                          */
07842                         broken_server = DNS_R_UNEXPECTEDRCODE;
07843                         INSIST(broken_server != ISC_R_SUCCESS);
07844                         keep_trying = ISC_TRUE;
07845                 }
07846 
07847                 isc_buffer_init(&b, code, sizeof(code) - 1);
07848                 dns_rcode_totext(fctx->rmessage->rcode, &b);
07849                 code[isc_buffer_usedlength(&b)] = '\0';
07850                 FCTXTRACE2("remote server broken: returned ", code);
07851                 goto done;
07852         }
07853 
07854         /*
07855          * Is the question the same as the one we asked?
07856          */
07857         result = same_question(fctx);
07858         if (result != ISC_R_SUCCESS) {
07859                 /* XXXRTH Log */
07860                 if (result == DNS_R_FORMERR)
07861                         keep_trying = ISC_TRUE;
07862                 FCTXTRACE3("response did not match question", result);
07863                 goto done;
07864         }
07865 
07866         /*
07867          * Is the server lame?
07868          */
07869         if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
07870             is_lame(fctx)) {
07871                 inc_stats(fctx->res, dns_resstatscounter_lame);
07872                 log_lame(fctx, query->addrinfo);
07873                 result = dns_adb_marklame(fctx->adb, query->addrinfo,
07874                                           &fctx->name, fctx->type,
07875                                           now + fctx->res->lame_ttl);
07876                 if (result != ISC_R_SUCCESS)
07877                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
07878                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
07879                                       "could not mark server as lame: %s",
07880                                       isc_result_totext(result));
07881                 broken_server = DNS_R_LAME;
07882                 keep_trying = ISC_TRUE;
07883                 FCTXTRACE("lame server");
07884                 goto done;
07885         }
07886 
07887         /*
07888          * Enforce delegations only zones like NET and COM.
07889          */
07890         if (!ISFORWARDER(query->addrinfo) &&
07891             dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
07892             !dns_name_equal(&fctx->domain, &fctx->name) &&
07893             fix_mustbedelegationornxdomain(message, fctx)) {
07894                 char namebuf[DNS_NAME_FORMATSIZE];
07895                 char domainbuf[DNS_NAME_FORMATSIZE];
07896                 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
07897                 char classbuf[64];
07898                 char typebuf[64];
07899 
07900                 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
07901                 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
07902                 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
07903                 dns_rdataclass_format(fctx->res->rdclass, classbuf,
07904                                       sizeof(classbuf));
07905                 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
07906                                     sizeof(addrbuf));
07907 
07908                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
07909                              DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
07910                              "enforced delegation-only for '%s' (%s/%s/%s) "
07911                              "from %s",
07912                              domainbuf, namebuf, typebuf, classbuf, addrbuf);
07913         }
07914 
07915         if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
07916                 checknames(message);
07917 
07918         /*
07919          * Clear cache bits.
07920          */
07921         fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
07922 
07923         /*
07924          * Did we get any answers?
07925          */
07926         if (message->counts[DNS_SECTION_ANSWER] > 0 &&
07927             (message->rcode == dns_rcode_noerror ||
07928              message->rcode == dns_rcode_nxdomain)) {
07929                 /*
07930                  * [normal case]
07931                  * We've got answers.  If it has an authoritative answer or an
07932                  * answer from a forwarder, we're done.
07933                  */
07934                 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
07935                     ISFORWARDER(query->addrinfo))
07936                 {
07937                         result = answer_response(fctx);
07938                         if (result != ISC_R_SUCCESS)
07939                                 FCTXTRACE3("answer_response (AA/fwd)", result);
07940                 } else if (iscname(fctx) &&
07941                          fctx->type != dns_rdatatype_any &&
07942                          fctx->type != dns_rdatatype_cname)
07943                 {
07944                         /*
07945                          * A BIND8 server could return a non-authoritative
07946                          * answer when a CNAME is followed.  We should treat
07947                          * it as a valid answer.
07948                          */
07949                         result = answer_response(fctx);
07950                         if (result != ISC_R_SUCCESS)
07951                                 FCTXTRACE3("answer_response (!ANY/!CNAME)",
07952                                            result);
07953                 } else if (fctx->type != dns_rdatatype_ns &&
07954                            !betterreferral(fctx)) {
07955                         /*
07956                          * Lame response !!!.
07957                          */
07958                         result = answer_response(fctx);
07959                         if (result != ISC_R_SUCCESS)
07960                                 FCTXTRACE3("answer_response (!NS)", result);
07961                 } else {
07962                         if (fctx->type == dns_rdatatype_ns) {
07963                                 /*
07964                                  * A BIND 8 server could incorrectly return a
07965                                  * non-authoritative answer to an NS query
07966                                  * instead of a referral. Since this answer
07967                                  * lacks the SIGs necessary to do DNSSEC
07968                                  * validation, we must invoke the following
07969                                  * special kludge to treat it as a referral.
07970                                  */
07971                                 result = noanswer_response(fctx, NULL,
07972                                                    LOOK_FOR_NS_IN_ANSWER);
07973                                 if (result != ISC_R_SUCCESS)
07974                                         FCTXTRACE3("noanswer_response (NS)",
07975                                                    result);
07976                         } else {
07977                                 /*
07978                                  * Some other servers may still somehow include
07979                                  * an answer when it should return a referral
07980                                  * with an empty answer.  Check to see if we can
07981                                  * treat this as a referral by ignoring the
07982                                  * answer.  Further more, there may be an
07983                                  * implementation that moves A/AAAA glue records
07984                                  * to the answer section for that type of
07985                                  * delegation when the query is for that glue
07986                                  * record.  LOOK_FOR_GLUE_IN_ANSWER will handle
07987                                  * such a corner case.
07988                                  */
07989                                 result = noanswer_response(fctx, NULL,
07990                                                    LOOK_FOR_GLUE_IN_ANSWER);
07991                                 if (result != ISC_R_SUCCESS)
07992                                         FCTXTRACE3("noanswer_response", result);
07993                         }
07994                         if (result != DNS_R_DELEGATION) {
07995                                 /*
07996                                  * At this point, AA is not set, the response
07997                                  * is not a referral, and the server is not a
07998                                  * forwarder.  It is technically lame and it's
07999                                  * easier to treat it as such than to figure out
08000                                  * some more elaborate course of action.
08001                                  */
08002                                 broken_server = DNS_R_LAME;
08003                                 keep_trying = ISC_TRUE;
08004                                 goto done;
08005                         }
08006                         goto force_referral;
08007                 }
08008                 if (result != ISC_R_SUCCESS) {
08009                         if (result == DNS_R_FORMERR)
08010                                 keep_trying = ISC_TRUE;
08011                         goto done;
08012                 }
08013         } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
08014                    message->rcode == dns_rcode_noerror ||
08015                    message->rcode == dns_rcode_nxdomain) {
08016                 /*
08017                  * NXDOMAIN, NXRDATASET, or referral.
08018                  */
08019                 result = noanswer_response(fctx, NULL, 0);
08020                 switch (result) {
08021                 case ISC_R_SUCCESS:
08022                 case DNS_R_CHASEDSSERVERS:
08023                         break;
08024                 case DNS_R_DELEGATION:
08025  force_referral:
08026                         /*
08027                          * We don't have the answer, but we know a better
08028                          * place to look.
08029                          */
08030                         get_nameservers = ISC_TRUE;
08031                         keep_trying = ISC_TRUE;
08032                         /*
08033                          * We have a new set of name servers, and it
08034                          * has not experienced any restarts yet.
08035                          */
08036                         fctx->restarts = 0;
08037 
08038                         /*
08039                          * Update local statistics counters collected for each
08040                          * new zone.
08041                          */
08042                         fctx->referrals++;
08043                         fctx->querysent = 0;
08044                         fctx->lamecount = 0;
08045                         fctx->neterr = 0;
08046                         fctx->badresp = 0;
08047                         fctx->adberr = 0;
08048 
08049                         result = ISC_R_SUCCESS;
08050                         break;
08051                 default:
08052                         /*
08053                          * Something has gone wrong.
08054                          */
08055                         if (result == DNS_R_FORMERR)
08056                                 keep_trying = ISC_TRUE;
08057                         FCTXTRACE3("noanswer_response", result);
08058                         goto done;
08059                 }
08060         } else {
08061                 /*
08062                  * The server is insane.
08063                  */
08064                 /* XXXRTH Log */
08065                 broken_server = DNS_R_UNEXPECTEDRCODE;
08066                 keep_trying = ISC_TRUE;
08067                 FCTXTRACE("broken server: unexpected rcode");
08068                 goto done;
08069         }
08070 
08071         /*
08072          * Follow additional section data chains.
08073          */
08074         chase_additional(fctx);
08075 
08076         /*
08077          * Cache the cacheable parts of the message.  This may also cause
08078          * work to be queued to the DNSSEC validator.
08079          */
08080         if (WANTCACHE(fctx)) {
08081                 result = cache_message(fctx, query->addrinfo, now);
08082                 if (result != ISC_R_SUCCESS) {
08083                         FCTXTRACE3("cache_message complete", result);
08084                         goto done;
08085                 }
08086         }
08087 
08088         /*
08089          * Ncache the negatively cacheable parts of the message.  This may
08090          * also cause work to be queued to the DNSSEC validator.
08091          */
08092         if (WANTNCACHE(fctx)) {
08093                 dns_rdatatype_t covers;
08094 
08095                 /*
08096                  * Cache DS NXDOMAIN seperately to other types.
08097                  */
08098                 if (message->rcode == dns_rcode_nxdomain &&
08099                     fctx->type != dns_rdatatype_ds)
08100                         covers = dns_rdatatype_any;
08101                 else
08102                         covers = fctx->type;
08103 
08104                 /*
08105                  * Cache any negative cache entries in the message.
08106                  */
08107                 result = ncache_message(fctx, query->addrinfo, covers, now);
08108                 if (result != ISC_R_SUCCESS)
08109                         FCTXTRACE3("ncache_message complete", result);
08110         }
08111 
08112  done:
08113         /*
08114          * Remember the query's addrinfo, in case we need to mark the
08115          * server as broken.
08116          */
08117         addrinfo = query->addrinfo;
08118 
08119         FCTXTRACE4("query canceled in response(); ",
08120                    no_response ? "no response" : "responding",
08121                    result);
08122 
08123         /*
08124          * Cancel the query.
08125          *
08126          * XXXRTH  Don't cancel the query if waiting for validation?
08127          */
08128         fctx_cancelquery(&query, &devent, finish, no_response);
08129 
08130         if (keep_trying) {
08131                 if (result == DNS_R_FORMERR)
08132                         broken_server = DNS_R_FORMERR;
08133                 if (broken_server != ISC_R_SUCCESS) {
08134                         /*
08135                          * Add this server to the list of bad servers for
08136                          * this fctx.
08137                          */
08138                         add_bad(fctx, addrinfo, broken_server, broken_type);
08139                 }
08140 
08141                 if (get_nameservers) {
08142                         dns_name_t *name;
08143                         dns_fixedname_init(&foundname);
08144                         fname = dns_fixedname_name(&foundname);
08145                         if (result != ISC_R_SUCCESS) {
08146                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08147                                 return;
08148                         }
08149                         findoptions = 0;
08150                         if (dns_rdatatype_atparent(fctx->type))
08151                                 findoptions |= DNS_DBFIND_NOEXACT;
08152                         if ((options & DNS_FETCHOPT_UNSHARED) == 0)
08153                                 name = &fctx->name;
08154                         else
08155                                 name = &fctx->domain;
08156                         result = dns_view_findzonecut(fctx->res->view,
08157                                                       name, fname,
08158                                                       now, findoptions,
08159                                                       ISC_TRUE,
08160                                                       &fctx->nameservers,
08161                                                       NULL);
08162                         if (result != ISC_R_SUCCESS) {
08163                                 FCTXTRACE("couldn't find a zonecut");
08164                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08165                                 return;
08166                         }
08167                         if (!dns_name_issubdomain(fname, &fctx->domain)) {
08168                                 /*
08169                                  * The best nameservers are now above our
08170                                  * QDOMAIN.
08171                                  */
08172                                 FCTXTRACE("nameservers now above QDOMAIN");
08173                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08174                                 return;
08175                         }
08176                         dns_name_free(&fctx->domain, fctx->mctx);
08177                         dns_name_init(&fctx->domain, NULL);
08178                         result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
08179                         if (result != ISC_R_SUCCESS) {
08180                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
08181                                 return;
08182                         }
08183                         fctx->ns_ttl = fctx->nameservers.ttl;
08184                         fctx->ns_ttl_ok = ISC_TRUE;
08185                         fctx_cancelqueries(fctx, ISC_TRUE);
08186                         fctx_cleanupfinds(fctx);
08187                         fctx_cleanupaltfinds(fctx);
08188                         fctx_cleanupforwaddrs(fctx);
08189                         fctx_cleanupaltaddrs(fctx);
08190                 }
08191                 /*
08192                  * Try again.
08193                  */
08194                 fctx_try(fctx, !get_nameservers, ISC_FALSE);
08195         } else if (resend) {
08196                 /*
08197                  * Resend (probably with changed options).
08198                  */
08199                 FCTXTRACE("resend");
08200                 inc_stats(fctx->res, dns_resstatscounter_retry);
08201                 result = fctx_query(fctx, addrinfo, options);
08202                 if (result != ISC_R_SUCCESS)
08203                         fctx_done(fctx, result, __LINE__);
08204         } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
08205                 /*
08206                  * All has gone well so far, but we are waiting for the
08207                  * DNSSEC validator to validate the answer.
08208                  */
08209                 FCTXTRACE("wait for validator");
08210                 fctx_cancelqueries(fctx, ISC_TRUE);
08211                 /*
08212                  * We must not retransmit while the validator is working;
08213                  * it has references to the current rmessage.
08214                  */
08215                 result = fctx_stopidletimer(fctx);
08216                 if (result != ISC_R_SUCCESS)
08217                         fctx_done(fctx, result, __LINE__);
08218         } else if (result == DNS_R_CHASEDSSERVERS) {
08219                 unsigned int n;
08220                 add_bad(fctx, addrinfo, result, broken_type);
08221                 fctx_cancelqueries(fctx, ISC_TRUE);
08222                 fctx_cleanupfinds(fctx);
08223                 fctx_cleanupforwaddrs(fctx);
08224 
08225                 n = dns_name_countlabels(&fctx->name);
08226                 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
08227 
08228                 FCTXTRACE("suspending DS lookup to find parent's NS records");
08229 
08230                 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
08231                                                   dns_rdatatype_ns,
08232                                                   NULL, NULL, NULL,
08233                                                   fctx->options, task,
08234                                                   resume_dslookup, fctx,
08235                                                   &fctx->nsrrset, NULL,
08236                                                   &fctx->nsfetch);
08237                 if (result != ISC_R_SUCCESS)
08238                         fctx_done(fctx, result, __LINE__);
08239                 else {
08240                         fctx_increference(fctx);
08241                         result = fctx_stopidletimer(fctx);
08242                         if (result != ISC_R_SUCCESS)
08243                                 fctx_done(fctx, result, __LINE__);
08244                 }
08245         } else {
08246                 /*
08247                  * We're done.
08248                  */
08249                 fctx_done(fctx, result, __LINE__);
08250         }
08251 }
08252 
08253 
08254 /***
08255  *** Resolver Methods
08256  ***/
08257 static void
08258 destroy(dns_resolver_t *res) {
08259         unsigned int i;
08260         alternate_t *a;
08261 
08262         REQUIRE(res->references == 0);
08263         REQUIRE(!res->priming);
08264         REQUIRE(res->primefetch == NULL);
08265 
08266         RTRACE("destroy");
08267 
08268         INSIST(res->nfctx == 0);
08269 
08270         DESTROYLOCK(&res->primelock);
08271         DESTROYLOCK(&res->nlock);
08272         DESTROYLOCK(&res->lock);
08273         for (i = 0; i < res->nbuckets; i++) {
08274                 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
08275                 isc_task_shutdown(res->buckets[i].task);
08276                 isc_task_detach(&res->buckets[i].task);
08277                 DESTROYLOCK(&res->buckets[i].lock);
08278                 isc_mem_detach(&res->buckets[i].mctx);
08279         }
08280         isc_mem_put(res->mctx, res->buckets,
08281                     res->nbuckets * sizeof(fctxbucket_t));
08282         if (res->dispatches4 != NULL)
08283                 dns_dispatchset_destroy(&res->dispatches4);
08284         if (res->dispatches6 != NULL)
08285                 dns_dispatchset_destroy(&res->dispatches6);
08286         while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
08287                 ISC_LIST_UNLINK(res->alternates, a, link);
08288                 if (!a->isaddress)
08289                         dns_name_free(&a->_u._n.name, res->mctx);
08290                 isc_mem_put(res->mctx, a, sizeof(*a));
08291         }
08292         dns_resolver_reset_algorithms(res);
08293         dns_resolver_reset_ds_digests(res);
08294         dns_badcache_destroy(&res->badcache);
08295         dns_resolver_resetmustbesecure(res);
08296 #if USE_ALGLOCK
08297         isc_rwlock_destroy(&res->alglock);
08298 #endif
08299 #if USE_MBSLOCK
08300         isc_rwlock_destroy(&res->mbslock);
08301 #endif
08302         isc_timer_detach(&res->spillattimer);
08303         res->magic = 0;
08304         isc_mem_put(res->mctx, res, sizeof(*res));
08305 }
08306 
08307 static void
08308 send_shutdown_events(dns_resolver_t *res) {
08309         isc_event_t *event, *next_event;
08310         isc_task_t *etask;
08311 
08312         /*
08313          * Caller must be holding the resolver lock.
08314          */
08315 
08316         for (event = ISC_LIST_HEAD(res->whenshutdown);
08317              event != NULL;
08318              event = next_event) {
08319                 next_event = ISC_LIST_NEXT(event, ev_link);
08320                 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
08321                 etask = event->ev_sender;
08322                 event->ev_sender = res;
08323                 isc_task_sendanddetach(&etask, &event);
08324         }
08325 }
08326 
08327 static void
08328 empty_bucket(dns_resolver_t *res) {
08329         RTRACE("empty_bucket");
08330 
08331         LOCK(&res->lock);
08332 
08333         INSIST(res->activebuckets > 0);
08334         res->activebuckets--;
08335         if (res->activebuckets == 0)
08336                 send_shutdown_events(res);
08337 
08338         UNLOCK(&res->lock);
08339 }
08340 
08341 static void
08342 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
08343         dns_resolver_t *res = event->ev_arg;
08344         isc_result_t result;
08345         unsigned int count;
08346         isc_boolean_t logit = ISC_FALSE;
08347 
08348         REQUIRE(VALID_RESOLVER(res));
08349 
08350         UNUSED(task);
08351 
08352         LOCK(&res->lock);
08353         INSIST(!res->exiting);
08354         if (res->spillat > res->spillatmin) {
08355                 res->spillat--;
08356                 logit = ISC_TRUE;
08357         }
08358         if (res->spillat <= res->spillatmin) {
08359                 result = isc_timer_reset(res->spillattimer,
08360                                          isc_timertype_inactive, NULL,
08361                                          NULL, ISC_TRUE);
08362                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08363         }
08364         count = res->spillat;
08365         UNLOCK(&res->lock);
08366         if (logit)
08367                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
08368                               DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
08369                               "clients-per-query decreased to %u", count);
08370 
08371         isc_event_free(&event);
08372 }
08373 
08374 isc_result_t
08375 dns_resolver_create(dns_view_t *view,
08376                     isc_taskmgr_t *taskmgr,
08377                     unsigned int ntasks, unsigned int ndisp,
08378                     isc_socketmgr_t *socketmgr,
08379                     isc_timermgr_t *timermgr,
08380                     unsigned int options,
08381                     dns_dispatchmgr_t *dispatchmgr,
08382                     dns_dispatch_t *dispatchv4,
08383                     dns_dispatch_t *dispatchv6,
08384                     dns_resolver_t **resp)
08385 {
08386         dns_resolver_t *res;
08387         isc_result_t result = ISC_R_SUCCESS;
08388         unsigned int i, buckets_created = 0;
08389         isc_task_t *task = NULL;
08390         char name[16];
08391         unsigned dispattr;
08392 
08393         /*
08394          * Create a resolver.
08395          */
08396 
08397         REQUIRE(DNS_VIEW_VALID(view));
08398         REQUIRE(ntasks > 0);
08399         REQUIRE(ndisp > 0);
08400         REQUIRE(resp != NULL && *resp == NULL);
08401         REQUIRE(dispatchmgr != NULL);
08402         REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
08403 
08404         res = isc_mem_get(view->mctx, sizeof(*res));
08405         if (res == NULL)
08406                 return (ISC_R_NOMEMORY);
08407         RTRACE("create");
08408         res->mctx = view->mctx;
08409         res->rdclass = view->rdclass;
08410         res->socketmgr = socketmgr;
08411         res->timermgr = timermgr;
08412         res->taskmgr = taskmgr;
08413         res->dispatchmgr = dispatchmgr;
08414         res->view = view;
08415         res->options = options;
08416         res->lame_ttl = 0;
08417         ISC_LIST_INIT(res->alternates);
08418         res->udpsize = RECV_BUFFER_SIZE;
08419         res->algorithms = NULL;
08420         res->digests = NULL;
08421         res->badcache = NULL;
08422         dns_badcache_init(res->mctx, DNS_RESOLVER_BADCACHESIZE,
08423                           &res->badcache);
08424         res->mustbesecure = NULL;
08425         res->spillatmin = res->spillat = 10;
08426         res->spillatmax = 100;
08427         res->spillattimer = NULL;
08428         res->zero_no_soa_ttl = ISC_FALSE;
08429         res->query_timeout = DEFAULT_QUERY_TIMEOUT;
08430         res->maxdepth = DEFAULT_RECURSION_DEPTH;
08431         res->maxqueries = DEFAULT_MAX_QUERIES;
08432         res->nbuckets = ntasks;
08433         if (view->resstats != NULL)
08434                 isc_stats_set(view->resstats, ntasks,
08435                               dns_resstatscounter_buckets);
08436         res->activebuckets = ntasks;
08437         res->buckets = isc_mem_get(view->mctx,
08438                                    ntasks * sizeof(fctxbucket_t));
08439         if (res->buckets == NULL) {
08440                 result = ISC_R_NOMEMORY;
08441                 goto cleanup_res;
08442         }
08443         for (i = 0; i < ntasks; i++) {
08444                 result = isc_mutex_init(&res->buckets[i].lock);
08445                 if (result != ISC_R_SUCCESS)
08446                         goto cleanup_buckets;
08447                 res->buckets[i].task = NULL;
08448                 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
08449                 if (result != ISC_R_SUCCESS) {
08450                         DESTROYLOCK(&res->buckets[i].lock);
08451                         goto cleanup_buckets;
08452                 }
08453                 res->buckets[i].mctx = NULL;
08454                 snprintf(name, sizeof(name), "res%u", i);
08455 #ifdef ISC_PLATFORM_USETHREADS
08456                 /*
08457                  * Use a separate memory context for each bucket to reduce
08458                  * contention among multiple threads.  Do this only when
08459                  * enabling threads because it will be require more memory.
08460                  */
08461                 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
08462                 if (result != ISC_R_SUCCESS) {
08463                         isc_task_detach(&res->buckets[i].task);
08464                         DESTROYLOCK(&res->buckets[i].lock);
08465                         goto cleanup_buckets;
08466                 }
08467                 isc_mem_setname(res->buckets[i].mctx, name, NULL);
08468 #else
08469                 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
08470 #endif
08471                 isc_task_setname(res->buckets[i].task, name, res);
08472                 ISC_LIST_INIT(res->buckets[i].fctxs);
08473                 res->buckets[i].exiting = ISC_FALSE;
08474                 buckets_created++;
08475         }
08476 
08477         res->dispatches4 = NULL;
08478         if (dispatchv4 != NULL) {
08479                 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
08480                                        dispatchv4, &res->dispatches4, ndisp);
08481                 dispattr = dns_dispatch_getattributes(dispatchv4);
08482                 res->exclusivev4 =
08483                         ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
08484         }
08485 
08486         res->dispatches6 = NULL;
08487         if (dispatchv6 != NULL) {
08488                 dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
08489                                        dispatchv6, &res->dispatches6, ndisp);
08490                 dispattr = dns_dispatch_getattributes(dispatchv6);
08491                 res->exclusivev6 =
08492                         ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
08493         }
08494 
08495         res->querydscp4 = -1;
08496         res->querydscp6 = -1;
08497         res->references = 1;
08498         res->exiting = ISC_FALSE;
08499         res->frozen = ISC_FALSE;
08500         ISC_LIST_INIT(res->whenshutdown);
08501         res->priming = ISC_FALSE;
08502         res->primefetch = NULL;
08503         res->nfctx = 0;
08504 
08505         result = isc_mutex_init(&res->lock);
08506         if (result != ISC_R_SUCCESS)
08507                 goto cleanup_dispatches;
08508 
08509         result = isc_mutex_init(&res->nlock);
08510         if (result != ISC_R_SUCCESS)
08511                 goto cleanup_lock;
08512 
08513         result = isc_mutex_init(&res->primelock);
08514         if (result != ISC_R_SUCCESS)
08515                 goto cleanup_nlock;
08516 
08517         task = NULL;
08518         result = isc_task_create(taskmgr, 0, &task);
08519         if (result != ISC_R_SUCCESS)
08520                 goto cleanup_primelock;
08521         isc_task_setname(task, "resolver_task", NULL);
08522 
08523         result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
08524                                   task, spillattimer_countdown, res,
08525                                   &res->spillattimer);
08526         isc_task_detach(&task);
08527         if (result != ISC_R_SUCCESS)
08528                 goto cleanup_primelock;
08529 
08530 #if USE_ALGLOCK
08531         result = isc_rwlock_init(&res->alglock, 0, 0);
08532         if (result != ISC_R_SUCCESS)
08533                 goto cleanup_spillattimer;
08534 #endif
08535 #if USE_MBSLOCK
08536         result = isc_rwlock_init(&res->mbslock, 0, 0);
08537         if (result != ISC_R_SUCCESS)
08538                 goto cleanup_alglock;
08539 #endif
08540 
08541         res->magic = RES_MAGIC;
08542 
08543         *resp = res;
08544 
08545         return (ISC_R_SUCCESS);
08546 
08547 #if USE_MBSLOCK
08548  cleanup_alglock:
08549 #if USE_ALGLOCK
08550         isc_rwlock_destroy(&res->alglock);
08551 #endif
08552 #endif
08553 #if USE_ALGLOCK || USE_MBSLOCK
08554  cleanup_spillattimer:
08555         isc_timer_detach(&res->spillattimer);
08556 #endif
08557 
08558  cleanup_primelock:
08559         DESTROYLOCK(&res->primelock);
08560 
08561  cleanup_nlock:
08562         DESTROYLOCK(&res->nlock);
08563 
08564  cleanup_lock:
08565         DESTROYLOCK(&res->lock);
08566 
08567  cleanup_dispatches:
08568         if (res->dispatches6 != NULL)
08569                 dns_dispatchset_destroy(&res->dispatches6);
08570         if (res->dispatches4 != NULL)
08571                 dns_dispatchset_destroy(&res->dispatches4);
08572 
08573  cleanup_buckets:
08574         for (i = 0; i < buckets_created; i++) {
08575                 isc_mem_detach(&res->buckets[i].mctx);
08576                 DESTROYLOCK(&res->buckets[i].lock);
08577                 isc_task_shutdown(res->buckets[i].task);
08578                 isc_task_detach(&res->buckets[i].task);
08579         }
08580         isc_mem_put(view->mctx, res->buckets,
08581                     res->nbuckets * sizeof(fctxbucket_t));
08582 
08583  cleanup_res:
08584         isc_mem_put(view->mctx, res, sizeof(*res));
08585 
08586         return (result);
08587 }
08588 
08589 static void
08590 prime_done(isc_task_t *task, isc_event_t *event) {
08591         dns_resolver_t *res;
08592         dns_fetchevent_t *fevent;
08593         dns_fetch_t *fetch;
08594         dns_db_t *db = NULL;
08595 
08596         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
08597         fevent = (dns_fetchevent_t *)event;
08598         res = event->ev_arg;
08599         REQUIRE(VALID_RESOLVER(res));
08600 
08601         UNUSED(task);
08602 
08603         LOCK(&res->lock);
08604 
08605         INSIST(res->priming);
08606         res->priming = ISC_FALSE;
08607         LOCK(&res->primelock);
08608         fetch = res->primefetch;
08609         res->primefetch = NULL;
08610         UNLOCK(&res->primelock);
08611 
08612         UNLOCK(&res->lock);
08613 
08614         if (fevent->result == ISC_R_SUCCESS &&
08615             res->view->cache != NULL && res->view->hints != NULL) {
08616                 dns_cache_attachdb(res->view->cache, &db);
08617                 dns_root_checkhints(res->view, res->view->hints, db);
08618                 dns_db_detach(&db);
08619         }
08620 
08621         if (fevent->node != NULL)
08622                 dns_db_detachnode(fevent->db, &fevent->node);
08623         if (fevent->db != NULL)
08624                 dns_db_detach(&fevent->db);
08625         if (dns_rdataset_isassociated(fevent->rdataset))
08626                 dns_rdataset_disassociate(fevent->rdataset);
08627         INSIST(fevent->sigrdataset == NULL);
08628 
08629         isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
08630 
08631         isc_event_free(&event);
08632         dns_resolver_destroyfetch(&fetch);
08633 }
08634 
08635 void
08636 dns_resolver_prime(dns_resolver_t *res) {
08637         isc_boolean_t want_priming = ISC_FALSE;
08638         dns_rdataset_t *rdataset;
08639         isc_result_t result;
08640 
08641         REQUIRE(VALID_RESOLVER(res));
08642         REQUIRE(res->frozen);
08643 
08644         RTRACE("dns_resolver_prime");
08645 
08646         LOCK(&res->lock);
08647 
08648         if (!res->exiting && !res->priming) {
08649                 INSIST(res->primefetch == NULL);
08650                 res->priming = ISC_TRUE;
08651                 want_priming = ISC_TRUE;
08652         }
08653 
08654         UNLOCK(&res->lock);
08655 
08656         if (want_priming) {
08657                 /*
08658                  * To avoid any possible recursive locking problems, we
08659                  * start the priming fetch like any other fetch, and holding
08660                  * no resolver locks.  No one else will try to start it
08661                  * because we're the ones who set res->priming to true.
08662                  * Any other callers of dns_resolver_prime() while we're
08663                  * running will see that res->priming is already true and
08664                  * do nothing.
08665                  */
08666                 RTRACE("priming");
08667                 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
08668                 if (rdataset == NULL) {
08669                         LOCK(&res->lock);
08670                         INSIST(res->priming);
08671                         INSIST(res->primefetch == NULL);
08672                         res->priming = ISC_FALSE;
08673                         UNLOCK(&res->lock);
08674                         return;
08675                 }
08676                 dns_rdataset_init(rdataset);
08677                 LOCK(&res->primelock);
08678                 result = dns_resolver_createfetch(res, dns_rootname,
08679                                                   dns_rdatatype_ns,
08680                                                   NULL, NULL, NULL, 0,
08681                                                   res->buckets[0].task,
08682                                                   prime_done,
08683                                                   res, rdataset, NULL,
08684                                                   &res->primefetch);
08685                 UNLOCK(&res->primelock);
08686                 if (result != ISC_R_SUCCESS) {
08687                         LOCK(&res->lock);
08688                         INSIST(res->priming);
08689                         res->priming = ISC_FALSE;
08690                         UNLOCK(&res->lock);
08691                 }
08692         }
08693 }
08694 
08695 void
08696 dns_resolver_freeze(dns_resolver_t *res) {
08697         /*
08698          * Freeze resolver.
08699          */
08700 
08701         REQUIRE(VALID_RESOLVER(res));
08702 
08703         res->frozen = ISC_TRUE;
08704 }
08705 
08706 void
08707 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
08708         REQUIRE(VALID_RESOLVER(source));
08709         REQUIRE(targetp != NULL && *targetp == NULL);
08710 
08711         RRTRACE(source, "attach");
08712         LOCK(&source->lock);
08713         REQUIRE(!source->exiting);
08714 
08715         INSIST(source->references > 0);
08716         source->references++;
08717         INSIST(source->references != 0);
08718         UNLOCK(&source->lock);
08719 
08720         *targetp = source;
08721 }
08722 
08723 void
08724 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
08725                           isc_event_t **eventp)
08726 {
08727         isc_task_t *clone;
08728         isc_event_t *event;
08729 
08730         REQUIRE(VALID_RESOLVER(res));
08731         REQUIRE(eventp != NULL);
08732 
08733         event = *eventp;
08734         *eventp = NULL;
08735 
08736         LOCK(&res->lock);
08737 
08738         if (res->exiting && res->activebuckets == 0) {
08739                 /*
08740                  * We're already shutdown.  Send the event.
08741                  */
08742                 event->ev_sender = res;
08743                 isc_task_send(task, &event);
08744         } else {
08745                 clone = NULL;
08746                 isc_task_attach(task, &clone);
08747                 event->ev_sender = clone;
08748                 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
08749         }
08750 
08751         UNLOCK(&res->lock);
08752 }
08753 
08754 void
08755 dns_resolver_shutdown(dns_resolver_t *res) {
08756         unsigned int i;
08757         fetchctx_t *fctx;
08758         isc_result_t result;
08759 
08760         REQUIRE(VALID_RESOLVER(res));
08761 
08762         RTRACE("shutdown");
08763 
08764         LOCK(&res->lock);
08765 
08766         if (!res->exiting) {
08767                 RTRACE("exiting");
08768                 res->exiting = ISC_TRUE;
08769 
08770                 for (i = 0; i < res->nbuckets; i++) {
08771                         LOCK(&res->buckets[i].lock);
08772                         for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
08773                              fctx != NULL;
08774                              fctx = ISC_LIST_NEXT(fctx, link))
08775                                 fctx_shutdown(fctx);
08776                         if (res->dispatches4 != NULL && !res->exclusivev4) {
08777                                 dns_dispatchset_cancelall(res->dispatches4,
08778                                                           res->buckets[i].task);
08779                         }
08780                         if (res->dispatches6 != NULL && !res->exclusivev6) {
08781                                 dns_dispatchset_cancelall(res->dispatches6,
08782                                                           res->buckets[i].task);
08783                         }
08784                         res->buckets[i].exiting = ISC_TRUE;
08785                         if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
08786                                 INSIST(res->activebuckets > 0);
08787                                 res->activebuckets--;
08788                         }
08789                         UNLOCK(&res->buckets[i].lock);
08790                 }
08791                 if (res->activebuckets == 0)
08792                         send_shutdown_events(res);
08793                 result = isc_timer_reset(res->spillattimer,
08794                                          isc_timertype_inactive, NULL,
08795                                          NULL, ISC_TRUE);
08796                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08797         }
08798 
08799         UNLOCK(&res->lock);
08800 }
08801 
08802 void
08803 dns_resolver_detach(dns_resolver_t **resp) {
08804         dns_resolver_t *res;
08805         isc_boolean_t need_destroy = ISC_FALSE;
08806 
08807         REQUIRE(resp != NULL);
08808         res = *resp;
08809         REQUIRE(VALID_RESOLVER(res));
08810 
08811         RTRACE("detach");
08812 
08813         LOCK(&res->lock);
08814 
08815         INSIST(res->references > 0);
08816         res->references--;
08817         if (res->references == 0) {
08818                 INSIST(res->exiting && res->activebuckets == 0);
08819                 need_destroy = ISC_TRUE;
08820         }
08821 
08822         UNLOCK(&res->lock);
08823 
08824         if (need_destroy)
08825                 destroy(res);
08826 
08827         *resp = NULL;
08828 }
08829 
08830 static inline isc_boolean_t
08831 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
08832            unsigned int options)
08833 {
08834         /*
08835          * Don't match fetch contexts that are shutting down.
08836          */
08837         if (fctx->cloned || fctx->state == fetchstate_done ||
08838             ISC_LIST_EMPTY(fctx->events))
08839                 return (ISC_FALSE);
08840 
08841         if (fctx->type != type || fctx->options != options)
08842                 return (ISC_FALSE);
08843         return (dns_name_equal(&fctx->name, name));
08844 }
08845 
08846 static inline void
08847 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
08848         char namebuf[DNS_NAME_FORMATSIZE];
08849         char typebuf[DNS_RDATATYPE_FORMATSIZE];
08850         int level = ISC_LOG_DEBUG(1);
08851 
08852         /*
08853          * If there's no chance of logging it, don't render (format) the
08854          * name and RDATA type (further below), and return early.
08855          */
08856         if (! isc_log_wouldlog(dns_lctx, level))
08857                 return;
08858 
08859         dns_name_format(name, namebuf, sizeof(namebuf));
08860         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
08861 
08862         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
08863                       DNS_LOGMODULE_RESOLVER, level,
08864                       "fetch: %s/%s", namebuf, typebuf);
08865 }
08866 
08867 isc_result_t
08868 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
08869                          dns_rdatatype_t type,
08870                          dns_name_t *domain, dns_rdataset_t *nameservers,
08871                          dns_forwarders_t *forwarders,
08872                          unsigned int options, isc_task_t *task,
08873                          isc_taskaction_t action, void *arg,
08874                          dns_rdataset_t *rdataset,
08875                          dns_rdataset_t *sigrdataset,
08876                          dns_fetch_t **fetchp)
08877 {
08878         return (dns_resolver_createfetch3(res, name, type, domain,
08879                                           nameservers, forwarders, NULL, 0,
08880                                           options, 0, NULL, task, action, arg,
08881                                           rdataset, sigrdataset, fetchp));
08882 }
08883 
08884 isc_result_t
08885 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
08886                           dns_rdatatype_t type,
08887                           dns_name_t *domain, dns_rdataset_t *nameservers,
08888                           dns_forwarders_t *forwarders,
08889                           isc_sockaddr_t *client, dns_messageid_t id,
08890                           unsigned int options, isc_task_t *task,
08891                           isc_taskaction_t action, void *arg,
08892                           dns_rdataset_t *rdataset,
08893                           dns_rdataset_t *sigrdataset,
08894                           dns_fetch_t **fetchp)
08895 {
08896         return (dns_resolver_createfetch3(res, name, type, domain,
08897                                           nameservers, forwarders, client, id,
08898                                           options, 0, NULL, task, action, arg,
08899                                           rdataset, sigrdataset, fetchp));
08900 }
08901 
08902 isc_result_t
08903 dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
08904                           dns_rdatatype_t type,
08905                           dns_name_t *domain, dns_rdataset_t *nameservers,
08906                           dns_forwarders_t *forwarders,
08907                           isc_sockaddr_t *client, dns_messageid_t id,
08908                           unsigned int options, unsigned int depth,
08909                           isc_counter_t *qc, isc_task_t *task,
08910                           isc_taskaction_t action, void *arg,
08911                           dns_rdataset_t *rdataset,
08912                           dns_rdataset_t *sigrdataset,
08913                           dns_fetch_t **fetchp)
08914 {
08915         dns_fetch_t *fetch;
08916         fetchctx_t *fctx = NULL;
08917         isc_result_t result = ISC_R_SUCCESS;
08918         unsigned int bucketnum;
08919         isc_boolean_t new_fctx = ISC_FALSE;
08920         isc_event_t *event;
08921         unsigned int count = 0;
08922         unsigned int spillat;
08923         unsigned int spillatmin;
08924         isc_boolean_t dodestroy = ISC_FALSE;
08925 
08926         UNUSED(forwarders);
08927 
08928         REQUIRE(VALID_RESOLVER(res));
08929         REQUIRE(res->frozen);
08930         /* XXXRTH  Check for meta type */
08931         if (domain != NULL) {
08932                 REQUIRE(DNS_RDATASET_VALID(nameservers));
08933                 REQUIRE(nameservers->type == dns_rdatatype_ns);
08934         } else
08935                 REQUIRE(nameservers == NULL);
08936         REQUIRE(forwarders == NULL);
08937         REQUIRE(!dns_rdataset_isassociated(rdataset));
08938         REQUIRE(sigrdataset == NULL ||
08939                 !dns_rdataset_isassociated(sigrdataset));
08940         REQUIRE(fetchp != NULL && *fetchp == NULL);
08941 
08942         log_fetch(name, type);
08943 
08944         /*
08945          * XXXRTH  use a mempool?
08946          */
08947         fetch = isc_mem_get(res->mctx, sizeof(*fetch));
08948         if (fetch == NULL)
08949                 return (ISC_R_NOMEMORY);
08950         fetch->mctx = NULL;
08951         isc_mem_attach(res->mctx, &fetch->mctx);
08952 
08953         bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
08954 
08955         LOCK(&res->lock);
08956         spillat = res->spillat;
08957         spillatmin = res->spillatmin;
08958         UNLOCK(&res->lock);
08959         LOCK(&res->buckets[bucketnum].lock);
08960 
08961         if (res->buckets[bucketnum].exiting) {
08962                 result = ISC_R_SHUTTINGDOWN;
08963                 goto unlock;
08964         }
08965 
08966         if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
08967                 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
08968                      fctx != NULL;
08969                      fctx = ISC_LIST_NEXT(fctx, link)) {
08970                         if (fctx_match(fctx, name, type, options))
08971                                 break;
08972                 }
08973         }
08974 
08975         /*
08976          * Is this a duplicate?
08977          */
08978         if (fctx != NULL && client != NULL) {
08979                 dns_fetchevent_t *fevent;
08980                 for (fevent = ISC_LIST_HEAD(fctx->events);
08981                      fevent != NULL;
08982                      fevent = ISC_LIST_NEXT(fevent, ev_link)) {
08983                         if (fevent->client != NULL && fevent->id == id &&
08984                             isc_sockaddr_equal(fevent->client, client)) {
08985                                 result = DNS_R_DUPLICATE;
08986                                 goto unlock;
08987                         }
08988                         count++;
08989                 }
08990         }
08991         if (count >= spillatmin && spillatmin != 0) {
08992                 INSIST(fctx != NULL);
08993                 if (count >= spillat)
08994                         fctx->spilled = ISC_TRUE;
08995                 if (fctx->spilled) {
08996                         result = DNS_R_DROP;
08997                         goto unlock;
08998                 }
08999         }
09000 
09001         if (fctx == NULL) {
09002                 result = fctx_create(res, name, type, domain, nameservers,
09003                                      options, bucketnum, depth, qc, &fctx);
09004                 if (result != ISC_R_SUCCESS)
09005                         goto unlock;
09006                 new_fctx = ISC_TRUE;
09007         } else if (fctx->depth > depth)
09008                 fctx->depth = depth;
09009 
09010         result = fctx_join(fctx, task, client, id, action, arg,
09011                            rdataset, sigrdataset, fetch);
09012         if (new_fctx) {
09013                 if (result == ISC_R_SUCCESS) {
09014                         /*
09015                          * Launch this fctx.
09016                          */
09017                         event = &fctx->control_event;
09018                         ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
09019                                        DNS_EVENT_FETCHCONTROL,
09020                                        fctx_start, fctx, NULL,
09021                                        NULL, NULL);
09022                         isc_task_send(res->buckets[bucketnum].task, &event);
09023                 } else {
09024                         /*
09025                          * We don't care about the result of fctx_unlink()
09026                          * since we know we're not exiting.
09027                          */
09028                         (void)fctx_unlink(fctx);
09029                         dodestroy = ISC_TRUE;
09030                 }
09031         }
09032 
09033  unlock:
09034         UNLOCK(&res->buckets[bucketnum].lock);
09035 
09036         if (dodestroy)
09037                 fctx_destroy(fctx);
09038 
09039         if (result == ISC_R_SUCCESS) {
09040                 FTRACE("created");
09041                 *fetchp = fetch;
09042         } else
09043                 isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
09044 
09045         return (result);
09046 }
09047 
09048 void
09049 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
09050         fetchctx_t *fctx;
09051         dns_resolver_t *res;
09052         dns_fetchevent_t *event, *next_event;
09053         isc_task_t *etask;
09054 
09055         REQUIRE(DNS_FETCH_VALID(fetch));
09056         fctx = fetch->private;
09057         REQUIRE(VALID_FCTX(fctx));
09058         res = fctx->res;
09059 
09060         FTRACE("cancelfetch");
09061 
09062         LOCK(&res->buckets[fctx->bucketnum].lock);
09063 
09064         /*
09065          * Find the completion event for this fetch (as opposed
09066          * to those for other fetches that have joined the same
09067          * fctx) and send it with result = ISC_R_CANCELED.
09068          */
09069         event = NULL;
09070         if (fctx->state != fetchstate_done) {
09071                 for (event = ISC_LIST_HEAD(fctx->events);
09072                      event != NULL;
09073                      event = next_event) {
09074                         next_event = ISC_LIST_NEXT(event, ev_link);
09075                         if (event->fetch == fetch) {
09076                                 ISC_LIST_UNLINK(fctx->events, event, ev_link);
09077                                 break;
09078                         }
09079                 }
09080         }
09081         if (event != NULL) {
09082                 etask = event->ev_sender;
09083                 event->ev_sender = fctx;
09084                 event->result = ISC_R_CANCELED;
09085                 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
09086         }
09087         /*
09088          * The fctx continues running even if no fetches remain;
09089          * the answer is still cached.
09090          */
09091 
09092         UNLOCK(&res->buckets[fctx->bucketnum].lock);
09093 }
09094 
09095 void
09096 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
09097         dns_fetch_t *fetch;
09098         dns_resolver_t *res;
09099         dns_fetchevent_t *event, *next_event;
09100         fetchctx_t *fctx;
09101         unsigned int bucketnum;
09102         isc_boolean_t bucket_empty;
09103 
09104         REQUIRE(fetchp != NULL);
09105         fetch = *fetchp;
09106         REQUIRE(DNS_FETCH_VALID(fetch));
09107         fctx = fetch->private;
09108         REQUIRE(VALID_FCTX(fctx));
09109         res = fctx->res;
09110 
09111         FTRACE("destroyfetch");
09112 
09113         bucketnum = fctx->bucketnum;
09114         LOCK(&res->buckets[bucketnum].lock);
09115 
09116         /*
09117          * Sanity check: the caller should have gotten its event before
09118          * trying to destroy the fetch.
09119          */
09120         event = NULL;
09121         if (fctx->state != fetchstate_done) {
09122                 for (event = ISC_LIST_HEAD(fctx->events);
09123                      event != NULL;
09124                      event = next_event) {
09125                         next_event = ISC_LIST_NEXT(event, ev_link);
09126                         RUNTIME_CHECK(event->fetch != fetch);
09127                 }
09128         }
09129 
09130         bucket_empty = fctx_decreference(fctx);
09131 
09132         UNLOCK(&res->buckets[bucketnum].lock);
09133 
09134         isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
09135         *fetchp = NULL;
09136 
09137         if (bucket_empty)
09138                 empty_bucket(res);
09139 }
09140 
09141 void
09142 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
09143                       isc_logcategory_t *category, isc_logmodule_t *module,
09144                       int level, isc_boolean_t duplicateok)
09145 {
09146         fetchctx_t *fctx;
09147         dns_resolver_t *res;
09148         char domainbuf[DNS_NAME_FORMATSIZE];
09149 
09150         REQUIRE(DNS_FETCH_VALID(fetch));
09151         fctx = fetch->private;
09152         REQUIRE(VALID_FCTX(fctx));
09153         res = fctx->res;
09154 
09155         LOCK(&res->buckets[fctx->bucketnum].lock);
09156 
09157         INSIST(fctx->exitline >= 0);
09158         if (!fctx->logged || duplicateok) {
09159                 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
09160                 isc_log_write(lctx, category, module, level,
09161                               "fetch completed at %s:%d for %s in "
09162                               "%" ISC_PRINT_QUADFORMAT "u."
09163                               "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
09164                               "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
09165                               "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
09166                               "adberr:%u,findfail:%u,valfail:%u]",
09167                               __FILE__, fctx->exitline, fctx->info,
09168                               fctx->duration / US_PER_SEC,
09169                               fctx->duration % US_PER_SEC,
09170                               isc_result_totext(fctx->result),
09171                               isc_result_totext(fctx->vresult), domainbuf,
09172                               fctx->referrals, fctx->restarts,
09173                               fctx->querysent, fctx->timeouts, fctx->lamecount,
09174                               fctx->neterr, fctx->badresp, fctx->adberr,
09175                               fctx->findfail, fctx->valfail);
09176                 fctx->logged = ISC_TRUE;
09177         }
09178 
09179         UNLOCK(&res->buckets[fctx->bucketnum].lock);
09180 }
09181 
09182 dns_dispatchmgr_t *
09183 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
09184         REQUIRE(VALID_RESOLVER(resolver));
09185         return (resolver->dispatchmgr);
09186 }
09187 
09188 dns_dispatch_t *
09189 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
09190         REQUIRE(VALID_RESOLVER(resolver));
09191         return (dns_dispatchset_get(resolver->dispatches4));
09192 }
09193 
09194 dns_dispatch_t *
09195 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
09196         REQUIRE(VALID_RESOLVER(resolver));
09197         return (dns_dispatchset_get(resolver->dispatches6));
09198 }
09199 
09200 isc_socketmgr_t *
09201 dns_resolver_socketmgr(dns_resolver_t *resolver) {
09202         REQUIRE(VALID_RESOLVER(resolver));
09203         return (resolver->socketmgr);
09204 }
09205 
09206 isc_taskmgr_t *
09207 dns_resolver_taskmgr(dns_resolver_t *resolver) {
09208         REQUIRE(VALID_RESOLVER(resolver));
09209         return (resolver->taskmgr);
09210 }
09211 
09212 isc_uint32_t
09213 dns_resolver_getlamettl(dns_resolver_t *resolver) {
09214         REQUIRE(VALID_RESOLVER(resolver));
09215         return (resolver->lame_ttl);
09216 }
09217 
09218 void
09219 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
09220         REQUIRE(VALID_RESOLVER(resolver));
09221         resolver->lame_ttl = lame_ttl;
09222 }
09223 
09224 unsigned int
09225 dns_resolver_nrunning(dns_resolver_t *resolver) {
09226         unsigned int n;
09227         LOCK(&resolver->nlock);
09228         n = resolver->nfctx;
09229         UNLOCK(&resolver->nlock);
09230         return (n);
09231 }
09232 
09233 isc_result_t
09234 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
09235                           dns_name_t *name, in_port_t port) {
09236         alternate_t *a;
09237         isc_result_t result;
09238 
09239         REQUIRE(VALID_RESOLVER(resolver));
09240         REQUIRE(!resolver->frozen);
09241         REQUIRE((alt == NULL) ^ (name == NULL));
09242 
09243         a = isc_mem_get(resolver->mctx, sizeof(*a));
09244         if (a == NULL)
09245                 return (ISC_R_NOMEMORY);
09246         if (alt != NULL) {
09247                 a->isaddress = ISC_TRUE;
09248                 a->_u.addr = *alt;
09249         } else {
09250                 a->isaddress = ISC_FALSE;
09251                 a->_u._n.port = port;
09252                 dns_name_init(&a->_u._n.name, NULL);
09253                 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
09254                 if (result != ISC_R_SUCCESS) {
09255                         isc_mem_put(resolver->mctx, a, sizeof(*a));
09256                         return (result);
09257                 }
09258         }
09259         ISC_LINK_INIT(a, link);
09260         ISC_LIST_APPEND(resolver->alternates, a, link);
09261 
09262         return (ISC_R_SUCCESS);
09263 }
09264 
09265 void
09266 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
09267         REQUIRE(VALID_RESOLVER(resolver));
09268         resolver->udpsize = udpsize;
09269 }
09270 
09271 isc_uint16_t
09272 dns_resolver_getudpsize(dns_resolver_t *resolver) {
09273         REQUIRE(VALID_RESOLVER(resolver));
09274         return (resolver->udpsize);
09275 }
09276 
09277 void
09278 dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
09279         if (name != NULL)
09280                 dns_badcache_flushname(resolver->badcache, name);
09281         else
09282                 dns_badcache_flush(resolver->badcache);
09283 }
09284 
09285 void
09286 dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name) {
09287         dns_badcache_flushtree(resolver->badcache, name);
09288 }
09289 
09290 void
09291 dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
09292                          dns_rdatatype_t type, isc_time_t *expire)
09293 {
09294         (void) dns_badcache_add(resolver->badcache, name, type,
09295                                 ISC_FALSE, 0, expire);
09296 }
09297 
09298 isc_boolean_t
09299 dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
09300                          dns_rdatatype_t type, isc_time_t *now)
09301 {
09302         return (dns_badcache_find(resolver->badcache, name, type, NULL, now));
09303 }
09304 
09305 void
09306 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
09307         (void) dns_badcache_print(resolver->badcache, "Bad cache", fp);
09308 }
09309 
09310 static void
09311 free_algorithm(void *node, void *arg) {
09312         unsigned char *algorithms = node;
09313         isc_mem_t *mctx = arg;
09314 
09315         isc_mem_put(mctx, algorithms, *algorithms);
09316 }
09317 
09318 void
09319 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
09320 
09321         REQUIRE(VALID_RESOLVER(resolver));
09322 
09323 #if USE_ALGLOCK
09324         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09325 #endif
09326         if (resolver->algorithms != NULL)
09327                 dns_rbt_destroy(&resolver->algorithms);
09328 #if USE_ALGLOCK
09329         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09330 #endif
09331 }
09332 
09333 isc_result_t
09334 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
09335                                unsigned int alg)
09336 {
09337         unsigned int len, mask;
09338         unsigned char *new;
09339         unsigned char *algorithms;
09340         isc_result_t result;
09341         dns_rbtnode_t *node = NULL;
09342 
09343         /*
09344          * Whether an algorithm is disabled (or not) is stored in a
09345          * per-name bitfield that is stored as the node data of an
09346          * RBT.
09347          */
09348 
09349         REQUIRE(VALID_RESOLVER(resolver));
09350         if (alg > 255)
09351                 return (ISC_R_RANGE);
09352 
09353 #if USE_ALGLOCK
09354         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09355 #endif
09356         if (resolver->algorithms == NULL) {
09357                 result = dns_rbt_create(resolver->mctx, free_algorithm,
09358                                         resolver->mctx, &resolver->algorithms);
09359                 if (result != ISC_R_SUCCESS)
09360                         goto cleanup;
09361         }
09362 
09363         len = alg/8 + 2;
09364         mask = 1 << (alg%8);
09365 
09366         result = dns_rbt_addnode(resolver->algorithms, name, &node);
09367 
09368         if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
09369                 algorithms = node->data;
09370                 /*
09371                  * If algorithms is set, algorithms[0] contains its
09372                  * length.
09373                  */
09374                 if (algorithms == NULL || len > *algorithms) {
09375                         /*
09376                          * If no bitfield exists in the node data, or if
09377                          * it is not long enough, allocate a new
09378                          * bitfield and copy the old (smaller) bitfield
09379                          * into it if one exists.
09380                          */
09381                         new = isc_mem_get(resolver->mctx, len);
09382                         if (new == NULL) {
09383                                 result = ISC_R_NOMEMORY;
09384                                 goto cleanup;
09385                         }
09386                         memset(new, 0, len);
09387                         if (algorithms != NULL)
09388                                 memmove(new, algorithms, *algorithms);
09389                         new[len-1] |= mask;
09390                         /* new[0] should contain the length of new. */
09391                         *new = len;
09392                         node->data = new;
09393                         /* Free the older bitfield. */
09394                         if (algorithms != NULL)
09395                                 isc_mem_put(resolver->mctx, algorithms,
09396                                             *algorithms);
09397                 } else
09398                         algorithms[len-1] |= mask;
09399         }
09400         result = ISC_R_SUCCESS;
09401  cleanup:
09402 #if USE_ALGLOCK
09403         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09404 #endif
09405         return (result);
09406 }
09407 
09408 isc_boolean_t
09409 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
09410                                  unsigned int alg)
09411 {
09412         unsigned int len, mask;
09413         unsigned char *algorithms;
09414         void *data = NULL;
09415         isc_result_t result;
09416         isc_boolean_t found = ISC_FALSE;
09417 
09418         REQUIRE(VALID_RESOLVER(resolver));
09419 
09420 #if USE_ALGLOCK
09421         RWLOCK(&resolver->alglock, isc_rwlocktype_read);
09422 #endif
09423         if (resolver->algorithms == NULL)
09424                 goto unlock;
09425         result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
09426         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
09427                 len = alg/8 + 2;
09428                 mask = 1 << (alg%8);
09429                 algorithms = data;
09430                 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
09431                         found = ISC_TRUE;
09432         }
09433  unlock:
09434 #if USE_ALGLOCK
09435         RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
09436 #endif
09437         if (found)
09438                 return (ISC_FALSE);
09439         return (dst_algorithm_supported(alg));
09440 }
09441 
09442 static void
09443 free_digest(void *node, void *arg) {
09444         unsigned char *digests = node;
09445         isc_mem_t *mctx = arg;
09446 
09447         isc_mem_put(mctx, digests, *digests);
09448 }
09449 
09450 void
09451 dns_resolver_reset_ds_digests(dns_resolver_t *resolver) {
09452 
09453         REQUIRE(VALID_RESOLVER(resolver));
09454 
09455 #if USE_ALGLOCK
09456         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09457 #endif
09458         if (resolver->digests != NULL)
09459                 dns_rbt_destroy(&resolver->digests);
09460 #if USE_ALGLOCK
09461         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09462 #endif
09463 }
09464 
09465 isc_result_t
09466 dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
09467                                unsigned int digest_type)
09468 {
09469         unsigned int len, mask;
09470         unsigned char *new;
09471         unsigned char *digests;
09472         isc_result_t result;
09473         dns_rbtnode_t *node = NULL;
09474 
09475         /*
09476          * Whether a digest is disabled (or not) is stored in a per-name
09477          * bitfield that is stored as the node data of an RBT.
09478          */
09479 
09480         REQUIRE(VALID_RESOLVER(resolver));
09481         if (digest_type > 255)
09482                 return (ISC_R_RANGE);
09483 
09484 #if USE_ALGLOCK
09485         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
09486 #endif
09487         if (resolver->digests == NULL) {
09488                 result = dns_rbt_create(resolver->mctx, free_digest,
09489                                         resolver->mctx, &resolver->digests);
09490                 if (result != ISC_R_SUCCESS)
09491                         goto cleanup;
09492         }
09493 
09494         len = digest_type/8 + 2;
09495         mask = 1 << (digest_type%8);
09496 
09497         result = dns_rbt_addnode(resolver->digests, name, &node);
09498 
09499         if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
09500                 digests = node->data;
09501                 /* If digests is set, digests[0] contains its length. */
09502                 if (digests == NULL || len > *digests) {
09503                         /*
09504                          * If no bitfield exists in the node data, or if
09505                          * it is not long enough, allocate a new
09506                          * bitfield and copy the old (smaller) bitfield
09507                          * into it if one exists.
09508                          */
09509                         new = isc_mem_get(resolver->mctx, len);
09510                         if (new == NULL) {
09511                                 result = ISC_R_NOMEMORY;
09512                                 goto cleanup;
09513                         }
09514                         memset(new, 0, len);
09515                         if (digests != NULL)
09516                                 memmove(new, digests, *digests);
09517                         new[len-1] |= mask;
09518                         /* new[0] should contain the length of new. */
09519                         *new = len;
09520                         node->data = new;
09521                         /* Free the older bitfield. */
09522                         if (digests != NULL)
09523                                 isc_mem_put(resolver->mctx, digests,
09524                                             *digests);
09525                 } else
09526                         digests[len-1] |= mask;
09527         }
09528         result = ISC_R_SUCCESS;
09529  cleanup:
09530 #if USE_ALGLOCK
09531         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
09532 #endif
09533         return (result);
09534 }
09535 
09536 isc_boolean_t
09537 dns_resolver_ds_digest_supported(dns_resolver_t *resolver, dns_name_t *name,
09538                                  unsigned int digest_type)
09539 {
09540         unsigned int len, mask;
09541         unsigned char *digests;
09542         void *data = NULL;
09543         isc_result_t result;
09544         isc_boolean_t found = ISC_FALSE;
09545 
09546         REQUIRE(VALID_RESOLVER(resolver));
09547 
09548 #if USE_ALGLOCK
09549         RWLOCK(&resolver->alglock, isc_rwlocktype_read);
09550 #endif
09551         if (resolver->digests == NULL)
09552                 goto unlock;
09553         result = dns_rbt_findname(resolver->digests, name, 0, NULL, &data);
09554         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
09555                 len = digest_type/8 + 2;
09556                 mask = 1 << (digest_type%8);
09557                 digests = data;
09558                 if (len <= *digests && (digests[len-1] & mask) != 0)
09559                         found = ISC_TRUE;
09560         }
09561  unlock:
09562 #if USE_ALGLOCK
09563         RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
09564 #endif
09565         if (found)
09566                 return (ISC_FALSE);
09567         return (dst_ds_digest_supported(digest_type));
09568 }
09569 
09570 void
09571 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
09572 
09573         REQUIRE(VALID_RESOLVER(resolver));
09574 
09575 #if USE_MBSLOCK
09576         RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
09577 #endif
09578         if (resolver->mustbesecure != NULL)
09579                 dns_rbt_destroy(&resolver->mustbesecure);
09580 #if USE_MBSLOCK
09581         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
09582 #endif
09583 }
09584 
09585 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
09586 
09587 isc_result_t
09588 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
09589                              isc_boolean_t value)
09590 {
09591         isc_result_t result;
09592 
09593         REQUIRE(VALID_RESOLVER(resolver));
09594 
09595 #if USE_MBSLOCK
09596         RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
09597 #endif
09598         if (resolver->mustbesecure == NULL) {
09599                 result = dns_rbt_create(resolver->mctx, NULL, NULL,
09600                                         &resolver->mustbesecure);
09601                 if (result != ISC_R_SUCCESS)
09602                         goto cleanup;
09603         }
09604         result = dns_rbt_addname(resolver->mustbesecure, name,
09605                                  value ? &yes : &no);
09606  cleanup:
09607 #if USE_MBSLOCK
09608         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
09609 #endif
09610         return (result);
09611 }
09612 
09613 isc_boolean_t
09614 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
09615         void *data = NULL;
09616         isc_boolean_t value = ISC_FALSE;
09617         isc_result_t result;
09618 
09619         REQUIRE(VALID_RESOLVER(resolver));
09620 
09621 #if USE_MBSLOCK
09622         RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
09623 #endif
09624         if (resolver->mustbesecure == NULL)
09625                 goto unlock;
09626         result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
09627         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
09628                 value = *(isc_boolean_t*)data;
09629  unlock:
09630 #if USE_MBSLOCK
09631         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
09632 #endif
09633         return (value);
09634 }
09635 
09636 void
09637 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
09638                                 isc_uint32_t *min, isc_uint32_t *max)
09639 {
09640         REQUIRE(VALID_RESOLVER(resolver));
09641 
09642         LOCK(&resolver->lock);
09643         if (cur != NULL)
09644                 *cur = resolver->spillat;
09645         if (min != NULL)
09646                 *min = resolver->spillatmin;
09647         if (max != NULL)
09648                 *max = resolver->spillatmax;
09649         UNLOCK(&resolver->lock);
09650 }
09651 
09652 void
09653 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
09654                                 isc_uint32_t max)
09655 {
09656         REQUIRE(VALID_RESOLVER(resolver));
09657 
09658         LOCK(&resolver->lock);
09659         resolver->spillatmin = resolver->spillat = min;
09660         resolver->spillatmax = max;
09661         UNLOCK(&resolver->lock);
09662 }
09663 
09664 isc_boolean_t
09665 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
09666         REQUIRE(VALID_RESOLVER(resolver));
09667 
09668         return (resolver->zero_no_soa_ttl);
09669 }
09670 
09671 void
09672 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
09673         REQUIRE(VALID_RESOLVER(resolver));
09674 
09675         resolver->zero_no_soa_ttl = state;
09676 }
09677 
09678 unsigned int
09679 dns_resolver_getoptions(dns_resolver_t *resolver) {
09680         REQUIRE(VALID_RESOLVER(resolver));
09681 
09682         return (resolver->options);
09683 }
09684 
09685 unsigned int
09686 dns_resolver_gettimeout(dns_resolver_t *resolver) {
09687         REQUIRE(VALID_RESOLVER(resolver));
09688 
09689         return (resolver->query_timeout);
09690 }
09691 
09692 void
09693 dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
09694         REQUIRE(VALID_RESOLVER(resolver));
09695 
09696         if (seconds == 0)
09697                 seconds = DEFAULT_QUERY_TIMEOUT;
09698         if (seconds > MAXIMUM_QUERY_TIMEOUT)
09699                 seconds = MAXIMUM_QUERY_TIMEOUT;
09700         if (seconds < MINIMUM_QUERY_TIMEOUT)
09701                 seconds =  MINIMUM_QUERY_TIMEOUT;
09702 
09703         resolver->query_timeout = seconds;
09704 }
09705 
09706 void
09707 dns_resolver_setquerydscp4(dns_resolver_t *resolver, isc_dscp_t dscp) {
09708         REQUIRE(VALID_RESOLVER(resolver));
09709 
09710         resolver->querydscp4 = dscp;
09711 }
09712 
09713 isc_dscp_t
09714 dns_resolver_getquerydscp4(dns_resolver_t *resolver) {
09715         REQUIRE(VALID_RESOLVER(resolver));
09716         return (resolver->querydscp4);
09717 }
09718 
09719 void
09720 dns_resolver_setquerydscp6(dns_resolver_t *resolver, isc_dscp_t dscp) {
09721         REQUIRE(VALID_RESOLVER(resolver));
09722 
09723         resolver->querydscp6 = dscp;
09724 }
09725 
09726 isc_dscp_t
09727 dns_resolver_getquerydscp6(dns_resolver_t *resolver) {
09728         REQUIRE(VALID_RESOLVER(resolver));
09729         return (resolver->querydscp6);
09730 }
09731 
09732 void
09733 dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) {
09734         REQUIRE(VALID_RESOLVER(resolver));
09735         resolver->maxdepth = maxdepth;
09736 }
09737 
09738 unsigned int
09739 dns_resolver_getmaxdepth(dns_resolver_t *resolver) {
09740         REQUIRE(VALID_RESOLVER(resolver));
09741         return (resolver->maxdepth);
09742 }
09743 
09744 void
09745 dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) {
09746         REQUIRE(VALID_RESOLVER(resolver));
09747         resolver->maxqueries = queries;
09748 }
09749 
09750 unsigned int
09751 dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
09752         REQUIRE(VALID_RESOLVER(resolver));
09753         return (resolver->maxqueries);
09754 }
09755 

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