]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/resolver.c
MFV r236171, MFC r236196:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / dns / resolver.c
1 /*
2  * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/platform.h>
25 #include <isc/print.h>
26 #include <isc/string.h>
27 #include <isc/random.h>
28 #include <isc/task.h>
29 #include <isc/stats.h>
30 #include <isc/timer.h>
31 #include <isc/util.h>
32
33 #include <dns/acl.h>
34 #include <dns/adb.h>
35 #include <dns/cache.h>
36 #include <dns/db.h>
37 #include <dns/dispatch.h>
38 #include <dns/ds.h>
39 #include <dns/events.h>
40 #include <dns/forward.h>
41 #include <dns/keytable.h>
42 #include <dns/log.h>
43 #include <dns/message.h>
44 #include <dns/ncache.h>
45 #include <dns/opcode.h>
46 #include <dns/peer.h>
47 #include <dns/rbt.h>
48 #include <dns/rcode.h>
49 #include <dns/rdata.h>
50 #include <dns/rdataclass.h>
51 #include <dns/rdatalist.h>
52 #include <dns/rdataset.h>
53 #include <dns/rdatastruct.h>
54 #include <dns/rdatatype.h>
55 #include <dns/resolver.h>
56 #include <dns/result.h>
57 #include <dns/rootns.h>
58 #include <dns/stats.h>
59 #include <dns/tsig.h>
60 #include <dns/validator.h>
61
62 #define DNS_RESOLVER_TRACE
63 #ifdef DNS_RESOLVER_TRACE
64 #define RTRACE(m)       isc_log_write(dns_lctx, \
65                                       DNS_LOGCATEGORY_RESOLVER, \
66                                       DNS_LOGMODULE_RESOLVER, \
67                                       ISC_LOG_DEBUG(3), \
68                                       "res %p: %s", res, (m))
69 #define RRTRACE(r, m)   isc_log_write(dns_lctx, \
70                                       DNS_LOGCATEGORY_RESOLVER, \
71                                       DNS_LOGMODULE_RESOLVER, \
72                                       ISC_LOG_DEBUG(3), \
73                                       "res %p: %s", (r), (m))
74 #define FCTXTRACE(m)    isc_log_write(dns_lctx, \
75                                       DNS_LOGCATEGORY_RESOLVER, \
76                                       DNS_LOGMODULE_RESOLVER, \
77                                       ISC_LOG_DEBUG(3), \
78                                       "fctx %p(%s'): %s", fctx, fctx->info, (m))
79 #define FCTXTRACE2(m1, m2) \
80                         isc_log_write(dns_lctx, \
81                                       DNS_LOGCATEGORY_RESOLVER, \
82                                       DNS_LOGMODULE_RESOLVER, \
83                                       ISC_LOG_DEBUG(3), \
84                                       "fctx %p(%s): %s %s", \
85                                       fctx, fctx->info, (m1), (m2))
86 #define FTRACE(m)       isc_log_write(dns_lctx, \
87                                       DNS_LOGCATEGORY_RESOLVER, \
88                                       DNS_LOGMODULE_RESOLVER, \
89                                       ISC_LOG_DEBUG(3), \
90                                       "fetch %p (fctx %p(%s)): %s", \
91                                       fetch, fetch->private, \
92                                       fetch->private->info, (m))
93 #define QTRACE(m)       isc_log_write(dns_lctx, \
94                                       DNS_LOGCATEGORY_RESOLVER, \
95                                       DNS_LOGMODULE_RESOLVER, \
96                                       ISC_LOG_DEBUG(3), \
97                                       "resquery %p (fctx %p(%s)): %s", \
98                                       query, query->fctx, \
99                                       query->fctx->info, (m))
100 #else
101 #define RTRACE(m)
102 #define RRTRACE(r, m)
103 #define FCTXTRACE(m)
104 #define FTRACE(m)
105 #define QTRACE(m)
106 #endif
107
108 #ifndef DEFAULT_QUERY_TIMEOUT
109 #define DEFAULT_QUERY_TIMEOUT 30  /* The default time in seconds for the whole query to live. */
110 #endif
111
112 #ifndef MAXIMUM_QUERY_TIMEOUT
113 #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
114 #endif
115
116 /*%
117  * Maximum EDNS0 input packet size.
118  */
119 #define RECV_BUFFER_SIZE                4096            /* XXXRTH  Constant. */
120
121 /*%
122  * This defines the maximum number of timeouts we will permit before we
123  * disable EDNS0 on the query.
124  */
125 #define MAX_EDNS0_TIMEOUTS      3
126
127 typedef struct fetchctx fetchctx_t;
128
129 typedef struct query {
130         /* Locked by task event serialization. */
131         unsigned int                    magic;
132         fetchctx_t *                    fctx;
133         isc_mem_t *                     mctx;
134         dns_dispatchmgr_t *             dispatchmgr;
135         dns_dispatch_t *                dispatch;
136         isc_boolean_t                   exclusivesocket;
137         dns_adbaddrinfo_t *             addrinfo;
138         isc_socket_t *                  tcpsocket;
139         isc_time_t                      start;
140         dns_messageid_t                 id;
141         dns_dispentry_t *               dispentry;
142         ISC_LINK(struct query)          link;
143         isc_buffer_t                    buffer;
144         isc_buffer_t                    *tsig;
145         dns_tsigkey_t                   *tsigkey;
146         unsigned int                    options;
147         unsigned int                    attributes;
148         unsigned int                    sends;
149         unsigned int                    connects;
150         unsigned char                   data[512];
151 } resquery_t;
152
153 #define QUERY_MAGIC                     ISC_MAGIC('Q', '!', '!', '!')
154 #define VALID_QUERY(query)              ISC_MAGIC_VALID(query, QUERY_MAGIC)
155
156 #define RESQUERY_ATTR_CANCELED          0x02
157
158 #define RESQUERY_CONNECTING(q)          ((q)->connects > 0)
159 #define RESQUERY_CANCELED(q)            (((q)->attributes & \
160                                           RESQUERY_ATTR_CANCELED) != 0)
161 #define RESQUERY_SENDING(q)             ((q)->sends > 0)
162
163 typedef enum {
164         fetchstate_init = 0,            /*%< Start event has not run yet. */
165         fetchstate_active,
166         fetchstate_done                 /*%< FETCHDONE events posted. */
167 } fetchstate;
168
169 typedef enum {
170         badns_unreachable = 0,
171         badns_response,
172         badns_validation
173 } badnstype_t;
174
175 struct fetchctx {
176         /*% Not locked. */
177         unsigned int                    magic;
178         dns_resolver_t *                res;
179         dns_name_t                      name;
180         dns_rdatatype_t                 type;
181         unsigned int                    options;
182         unsigned int                    bucketnum;
183         char *                          info;
184         isc_mem_t *                     mctx;
185
186         /*% Locked by appropriate bucket lock. */
187         fetchstate                      state;
188         isc_boolean_t                   want_shutdown;
189         isc_boolean_t                   cloned;
190         isc_boolean_t                   spilled;
191         unsigned int                    references;
192         isc_event_t                     control_event;
193         ISC_LINK(struct fetchctx)       link;
194         ISC_LIST(dns_fetchevent_t)      events;
195         /*% Locked by task event serialization. */
196         dns_name_t                      domain;
197         dns_rdataset_t                  nameservers;
198         unsigned int                    attributes;
199         isc_timer_t *                   timer;
200         isc_time_t                      expires;
201         isc_interval_t                  interval;
202         dns_message_t *                 qmessage;
203         dns_message_t *                 rmessage;
204         ISC_LIST(resquery_t)            queries;
205         dns_adbfindlist_t               finds;
206         dns_adbfind_t *                 find;
207         dns_adbfindlist_t               altfinds;
208         dns_adbfind_t *                 altfind;
209         dns_adbaddrinfolist_t           forwaddrs;
210         dns_adbaddrinfolist_t           altaddrs;
211         isc_sockaddrlist_t              forwarders;
212         dns_fwdpolicy_t                 fwdpolicy;
213         isc_sockaddrlist_t              bad;
214         isc_sockaddrlist_t              edns;
215         isc_sockaddrlist_t              edns512;
216         isc_sockaddrlist_t              bad_edns;
217         dns_validator_t                 *validator;
218         ISC_LIST(dns_validator_t)       validators;
219         dns_db_t *                      cache;
220         dns_adb_t *                     adb;
221         isc_boolean_t                   ns_ttl_ok;
222         isc_uint32_t                    ns_ttl;
223
224         /*%
225          * The number of events we're waiting for.
226          */
227         unsigned int                    pending;
228
229         /*%
230          * The number of times we've "restarted" the current
231          * nameserver set.  This acts as a failsafe to prevent
232          * us from pounding constantly on a particular set of
233          * servers that, for whatever reason, are not giving
234          * us useful responses, but are responding in such a
235          * way that they are not marked "bad".
236          */
237         unsigned int                    restarts;
238
239         /*%
240          * The number of timeouts that have occurred since we
241          * last successfully received a response packet.  This
242          * is used for EDNS0 black hole detection.
243          */
244         unsigned int                    timeouts;
245
246         /*%
247          * Look aside state for DS lookups.
248          */
249         dns_name_t                      nsname;
250         dns_fetch_t *                   nsfetch;
251         dns_rdataset_t                  nsrrset;
252
253         /*%
254          * Number of queries that reference this context.
255          */
256         unsigned int                    nqueries;
257
258         /*%
259          * The reason to print when logging a successful
260          * response to a query.
261          */
262         const char *                    reason;
263
264         /*%
265          * Random numbers to use for mixing up server addresses.
266          */
267         isc_uint32_t                    rand_buf;
268         isc_uint32_t                    rand_bits;
269
270         /*%
271          * Fetch-local statistics for detailed logging.
272          */
273         isc_result_t                    result; /*%< fetch result  */
274         isc_result_t                    vresult; /*%< validation result  */
275         int                             exitline;
276         isc_time_t                      start;
277         isc_uint64_t                    duration;
278         isc_boolean_t                   logged;
279         unsigned int                    querysent;
280         unsigned int                    referrals;
281         unsigned int                    lamecount;
282         unsigned int                    neterr;
283         unsigned int                    badresp;
284         unsigned int                    adberr;
285         unsigned int                    findfail;
286         unsigned int                    valfail;
287         isc_boolean_t                   timeout;
288         dns_adbaddrinfo_t               *addrinfo;
289         isc_sockaddr_t                  *client;
290 };
291
292 #define FCTX_MAGIC                      ISC_MAGIC('F', '!', '!', '!')
293 #define VALID_FCTX(fctx)                ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
294
295 #define FCTX_ATTR_HAVEANSWER            0x0001
296 #define FCTX_ATTR_GLUING                0x0002
297 #define FCTX_ATTR_ADDRWAIT              0x0004
298 #define FCTX_ATTR_SHUTTINGDOWN          0x0008
299 #define FCTX_ATTR_WANTCACHE             0x0010
300 #define FCTX_ATTR_WANTNCACHE            0x0020
301 #define FCTX_ATTR_NEEDEDNS0             0x0040
302 #define FCTX_ATTR_TRIEDFIND             0x0080
303 #define FCTX_ATTR_TRIEDALT              0x0100
304
305 #define HAVE_ANSWER(f)          (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
306                                  0)
307 #define GLUING(f)               (((f)->attributes & FCTX_ATTR_GLUING) != \
308                                  0)
309 #define ADDRWAIT(f)             (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
310                                  0)
311 #define SHUTTINGDOWN(f)         (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
312                                  != 0)
313 #define WANTCACHE(f)            (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
314 #define WANTNCACHE(f)           (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
315 #define NEEDEDNS0(f)            (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
316 #define TRIEDFIND(f)            (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
317 #define TRIEDALT(f)             (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
318
319 typedef struct {
320         dns_adbaddrinfo_t *             addrinfo;
321         fetchctx_t *                    fctx;
322 } dns_valarg_t;
323
324 struct dns_fetch {
325         unsigned int                    magic;
326         fetchctx_t *                    private;
327 };
328
329 #define DNS_FETCH_MAGIC                 ISC_MAGIC('F', 't', 'c', 'h')
330 #define DNS_FETCH_VALID(fetch)          ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
331
332 typedef struct fctxbucket {
333         isc_task_t *                    task;
334         isc_mutex_t                     lock;
335         ISC_LIST(fetchctx_t)            fctxs;
336         isc_boolean_t                   exiting;
337         isc_mem_t *                     mctx;
338 } fctxbucket_t;
339
340 typedef struct alternate {
341         isc_boolean_t                   isaddress;
342         union   {
343                 isc_sockaddr_t          addr;
344                 struct {
345                         dns_name_t      name;
346                         in_port_t       port;
347                 } _n;
348         } _u;
349         ISC_LINK(struct alternate)      link;
350 } alternate_t;
351
352 typedef struct dns_badcache dns_badcache_t;
353 struct dns_badcache {
354         dns_badcache_t *        next;
355         dns_rdatatype_t         type;
356         isc_time_t              expire;
357         unsigned int            hashval;
358         dns_name_t              name;
359 };
360 #define DNS_BADCACHE_SIZE 1021
361 #define DNS_BADCACHE_TTL(fctx) \
362         (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
363
364 struct dns_resolver {
365         /* Unlocked. */
366         unsigned int                    magic;
367         isc_mem_t *                     mctx;
368         isc_mutex_t                     lock;
369         isc_mutex_t                     nlock;
370         isc_mutex_t                     primelock;
371         dns_rdataclass_t                rdclass;
372         isc_socketmgr_t *               socketmgr;
373         isc_timermgr_t *                timermgr;
374         isc_taskmgr_t *                 taskmgr;
375         dns_view_t *                    view;
376         isc_boolean_t                   frozen;
377         unsigned int                    options;
378         dns_dispatchmgr_t *             dispatchmgr;
379         dns_dispatch_t *                dispatchv4;
380         isc_boolean_t                   exclusivev4;
381         dns_dispatch_t *                dispatchv6;
382         isc_boolean_t                   exclusivev6;
383         unsigned int                    ndisps;
384         unsigned int                    nbuckets;
385         fctxbucket_t *                  buckets;
386         isc_uint32_t                    lame_ttl;
387         ISC_LIST(alternate_t)           alternates;
388         isc_uint16_t                    udpsize;
389 #if USE_ALGLOCK
390         isc_rwlock_t                    alglock;
391 #endif
392         dns_rbt_t *                     algorithms;
393 #if USE_MBSLOCK
394         isc_rwlock_t                    mbslock;
395 #endif
396         dns_rbt_t *                     mustbesecure;
397         unsigned int                    spillatmax;
398         unsigned int                    spillatmin;
399         isc_timer_t *                   spillattimer;
400         isc_boolean_t                   zero_no_soa_ttl;
401         unsigned int                    query_timeout;
402
403         /* Locked by lock. */
404         unsigned int                    references;
405         isc_boolean_t                   exiting;
406         isc_eventlist_t                 whenshutdown;
407         unsigned int                    activebuckets;
408         isc_boolean_t                   priming;
409         unsigned int                    spillat;        /* clients-per-query */
410         unsigned int                    nextdisp;
411
412         /* Bad cache. */
413         dns_badcache_t  **              badcache;
414         unsigned int                    badcount;
415         unsigned int                    badhash;
416         unsigned int                    badsweep;
417
418         /* Locked by primelock. */
419         dns_fetch_t *                   primefetch;
420         /* Locked by nlock. */
421         unsigned int                    nfctx;
422 };
423
424 #define RES_MAGIC                       ISC_MAGIC('R', 'e', 's', '!')
425 #define VALID_RESOLVER(res)             ISC_MAGIC_VALID(res, RES_MAGIC)
426
427 /*%
428  * Private addrinfo flags.  These must not conflict with DNS_FETCHOPT_NOEDNS0,
429  * which we also use as an addrinfo flag.
430  */
431 #define FCTX_ADDRINFO_MARK              0x0001
432 #define FCTX_ADDRINFO_FORWARDER         0x1000
433 #define FCTX_ADDRINFO_TRIED             0x2000
434 #define UNMARKED(a)                     (((a)->flags & FCTX_ADDRINFO_MARK) \
435                                          == 0)
436 #define ISFORWARDER(a)                  (((a)->flags & \
437                                          FCTX_ADDRINFO_FORWARDER) != 0)
438 #define TRIED(a)                        (((a)->flags & \
439                                          FCTX_ADDRINFO_TRIED) != 0)
440
441 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
442 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
443
444 static void destroy(dns_resolver_t *res);
445 static void empty_bucket(dns_resolver_t *res);
446 static isc_result_t resquery_send(resquery_t *query);
447 static void resquery_response(isc_task_t *task, isc_event_t *event);
448 static void resquery_connected(isc_task_t *task, isc_event_t *event);
449 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
450                      isc_boolean_t badcache);
451 static void fctx_destroy(fetchctx_t *fctx);
452 static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
453 static isc_result_t ncache_adderesult(dns_message_t *message,
454                                       dns_db_t *cache, dns_dbnode_t *node,
455                                       dns_rdatatype_t covers,
456                                       isc_stdtime_t now, dns_ttl_t maxttl,
457                                       isc_boolean_t optout,
458                                       dns_rdataset_t *ardataset,
459                                       isc_result_t *eresultp);
460 static void validated(isc_task_t *task, isc_event_t *event);
461 static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
462 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
463                     isc_result_t reason, badnstype_t badtype);
464
465 /*%
466  * Increment resolver-related statistics counters.
467  */
468 static inline void
469 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
470         if (res->view->resstats != NULL)
471                 isc_stats_increment(res->view->resstats, counter);
472 }
473
474 static isc_result_t
475 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
476           dns_rdatatype_t type, dns_rdataset_t *rdataset,
477           dns_rdataset_t *sigrdataset, unsigned int valoptions,
478           isc_task_t *task)
479 {
480         dns_validator_t *validator = NULL;
481         dns_valarg_t *valarg;
482         isc_result_t result;
483
484         valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
485         if (valarg == NULL)
486                 return (ISC_R_NOMEMORY);
487
488         valarg->fctx = fctx;
489         valarg->addrinfo = addrinfo;
490
491         if (!ISC_LIST_EMPTY(fctx->validators))
492                 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
493
494         result = dns_validator_create(fctx->res->view, name, type, rdataset,
495                                       sigrdataset, fctx->rmessage,
496                                       valoptions, task, validated, valarg,
497                                       &validator);
498         if (result == ISC_R_SUCCESS) {
499                 inc_stats(fctx->res, dns_resstatscounter_val);
500                 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
501                         INSIST(fctx->validator == NULL);
502                         fctx->validator = validator;
503                 }
504                 ISC_LIST_APPEND(fctx->validators, validator, link);
505         } else
506                 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
507         return (result);
508 }
509
510 static isc_boolean_t
511 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
512         dns_namereln_t namereln;
513         dns_rdata_rrsig_t rrsig;
514         dns_rdata_t rdata = DNS_RDATA_INIT;
515         int order;
516         isc_result_t result;
517         unsigned int labels;
518
519         for (result = dns_rdataset_first(rdataset);
520              result == ISC_R_SUCCESS;
521              result = dns_rdataset_next(rdataset)) {
522                 dns_rdataset_current(rdataset, &rdata);
523                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
524                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
525                 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
526                                                 &order, &labels);
527                 if (namereln == dns_namereln_subdomain)
528                         return (ISC_TRUE);
529                 dns_rdata_reset(&rdata);
530         }
531         return (ISC_FALSE);
532 }
533
534 static isc_boolean_t
535 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
536         dns_name_t *name;
537         dns_name_t *domain = &fctx->domain;
538         dns_rdataset_t *rdataset;
539         dns_rdatatype_t type;
540         isc_result_t result;
541         isc_boolean_t keep_auth = ISC_FALSE;
542
543         if (message->rcode == dns_rcode_nxdomain)
544                 return (ISC_FALSE);
545
546         /*
547          * A DS RRset can appear anywhere in a zone, even for a delegation-only
548          * zone.  So a response to an explicit query for this type should be
549          * excluded from delegation-only fixup.
550          *
551          * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
552          * response to a query for these types can never violate the
553          * delegation-only assumption: if the query name is below a
554          * zone cut, the response should normally be a referral, which should
555          * be accepted; if the query name is below a zone cut but the server
556          * happens to have authority for the zone of the query name, the
557          * response is a (non-referral) answer.  But this does not violate
558          * delegation-only because the query name must be in a different zone
559          * due to the "apex-only" nature of these types.  Note that if the
560          * remote server happens to have authority for a child zone of a
561          * delegation-only zone, we may still incorrectly "fix" the response
562          * with NXDOMAIN for queries for other types.  Unfortunately it's
563          * generally impossible to differentiate this case from violation of
564          * the delegation-only assumption.  Once the resolver learns the
565          * correct zone cut, possibly via a separate query for an "apex-only"
566          * type, queries for other types will be resolved correctly.
567          *
568          * A query for type ANY will be accepted if it hits an exceptional
569          * type above in the answer section as it should be from a child
570          * zone.
571          *
572          * Also accept answers with RRSIG records from the child zone.
573          * Direct queries for RRSIG records should not be answered from
574          * the parent zone.
575          */
576
577         if (message->counts[DNS_SECTION_ANSWER] != 0 &&
578             (fctx->type == dns_rdatatype_ns ||
579              fctx->type == dns_rdatatype_ds ||
580              fctx->type == dns_rdatatype_soa ||
581              fctx->type == dns_rdatatype_any ||
582              fctx->type == dns_rdatatype_rrsig ||
583              fctx->type == dns_rdatatype_dnskey)) {
584                 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
585                 while (result == ISC_R_SUCCESS) {
586                         name = NULL;
587                         dns_message_currentname(message, DNS_SECTION_ANSWER,
588                                                 &name);
589                         for (rdataset = ISC_LIST_HEAD(name->list);
590                              rdataset != NULL;
591                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
592                                 if (!dns_name_equal(name, &fctx->name))
593                                         continue;
594                                 type = rdataset->type;
595                                 /*
596                                  * RRsig from child?
597                                  */
598                                 if (type == dns_rdatatype_rrsig &&
599                                     rrsig_fromchildzone(fctx, rdataset))
600                                         return (ISC_FALSE);
601                                 /*
602                                  * Direct query for apex records or DS.
603                                  */
604                                 if (fctx->type == type &&
605                                     (type == dns_rdatatype_ds ||
606                                      type == dns_rdatatype_ns ||
607                                      type == dns_rdatatype_soa ||
608                                      type == dns_rdatatype_dnskey))
609                                         return (ISC_FALSE);
610                                 /*
611                                  * Indirect query for apex records or DS.
612                                  */
613                                 if (fctx->type == dns_rdatatype_any &&
614                                     (type == dns_rdatatype_ns ||
615                                      type == dns_rdatatype_ds ||
616                                      type == dns_rdatatype_soa ||
617                                      type == dns_rdatatype_dnskey))
618                                         return (ISC_FALSE);
619                         }
620                         result = dns_message_nextname(message,
621                                                       DNS_SECTION_ANSWER);
622                 }
623         }
624
625         /*
626          * A NODATA response to a DS query?
627          */
628         if (fctx->type == dns_rdatatype_ds &&
629             message->counts[DNS_SECTION_ANSWER] == 0)
630                 return (ISC_FALSE);
631
632         /* Look for referral or indication of answer from child zone? */
633         if (message->counts[DNS_SECTION_AUTHORITY] == 0)
634                 goto munge;
635
636         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
637         while (result == ISC_R_SUCCESS) {
638                 name = NULL;
639                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
640                 for (rdataset = ISC_LIST_HEAD(name->list);
641                      rdataset != NULL;
642                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
643                         type = rdataset->type;
644                         if (type == dns_rdatatype_soa &&
645                             dns_name_equal(name, domain))
646                                 keep_auth = ISC_TRUE;
647
648                         if (type != dns_rdatatype_ns &&
649                             type != dns_rdatatype_soa &&
650                             type != dns_rdatatype_rrsig)
651                                 continue;
652
653                         if (type == dns_rdatatype_rrsig) {
654                                 if (rrsig_fromchildzone(fctx, rdataset))
655                                         return (ISC_FALSE);
656                                 else
657                                         continue;
658                         }
659
660                         /* NS or SOA records. */
661                         if (dns_name_equal(name, domain)) {
662                                 /*
663                                  * If a query for ANY causes a negative
664                                  * response, we can be sure that this is
665                                  * an empty node.  For other type of queries
666                                  * we cannot differentiate an empty node
667                                  * from a node that just doesn't have that
668                                  * type of record.  We only accept the former
669                                  * case.
670                                  */
671                                 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
672                                     fctx->type == dns_rdatatype_any)
673                                         return (ISC_FALSE);
674                         } else if (dns_name_issubdomain(name, domain)) {
675                                 /* Referral or answer from child zone. */
676                                 return (ISC_FALSE);
677                         }
678                 }
679                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
680         }
681
682  munge:
683         message->rcode = dns_rcode_nxdomain;
684         message->counts[DNS_SECTION_ANSWER] = 0;
685         if (!keep_auth)
686                 message->counts[DNS_SECTION_AUTHORITY] = 0;
687         message->counts[DNS_SECTION_ADDITIONAL] = 0;
688         return (ISC_TRUE);
689 }
690
691 static inline isc_result_t
692 fctx_starttimer(fetchctx_t *fctx) {
693         /*
694          * Start the lifetime timer for fctx.
695          *
696          * This is also used for stopping the idle timer; in that
697          * case we must purge events already posted to ensure that
698          * no further idle events are delivered.
699          */
700         return (isc_timer_reset(fctx->timer, isc_timertype_once,
701                                 &fctx->expires, NULL, ISC_TRUE));
702 }
703
704 static inline void
705 fctx_stoptimer(fetchctx_t *fctx) {
706         isc_result_t result;
707
708         /*
709          * We don't return a result if resetting the timer to inactive fails
710          * since there's nothing to be done about it.  Resetting to inactive
711          * should never fail anyway, since the code as currently written
712          * cannot fail in that case.
713          */
714         result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
715                                   NULL, NULL, ISC_TRUE);
716         if (result != ISC_R_SUCCESS) {
717                 UNEXPECTED_ERROR(__FILE__, __LINE__,
718                                  "isc_timer_reset(): %s",
719                                  isc_result_totext(result));
720         }
721 }
722
723
724 static inline isc_result_t
725 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
726         /*
727          * Start the idle timer for fctx.  The lifetime timer continues
728          * to be in effect.
729          */
730         return (isc_timer_reset(fctx->timer, isc_timertype_once,
731                                 &fctx->expires, interval, ISC_FALSE));
732 }
733
734 /*
735  * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
736  * we use fctx_stopidletimer for readability in the code below.
737  */
738 #define fctx_stopidletimer      fctx_starttimer
739
740
741 static inline void
742 resquery_destroy(resquery_t **queryp) {
743         resquery_t *query;
744
745         REQUIRE(queryp != NULL);
746         query = *queryp;
747         REQUIRE(!ISC_LINK_LINKED(query, link));
748
749         INSIST(query->tcpsocket == NULL);
750
751         query->fctx->nqueries--;
752         if (SHUTTINGDOWN(query->fctx)) {
753                 dns_resolver_t *res = query->fctx->res;
754                 if (maybe_destroy(query->fctx, ISC_FALSE))
755                         empty_bucket(res);
756         }
757         query->magic = 0;
758         isc_mem_put(query->mctx, query, sizeof(*query));
759         *queryp = NULL;
760 }
761
762 static void
763 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
764                  isc_time_t *finish, isc_boolean_t no_response)
765 {
766         fetchctx_t *fctx;
767         resquery_t *query;
768         unsigned int rtt, rttms;
769         unsigned int factor;
770         dns_adbfind_t *find;
771         dns_adbaddrinfo_t *addrinfo;
772         isc_socket_t *socket;
773
774         query = *queryp;
775         fctx = query->fctx;
776
777         FCTXTRACE("cancelquery");
778
779         REQUIRE(!RESQUERY_CANCELED(query));
780
781         query->attributes |= RESQUERY_ATTR_CANCELED;
782
783         /*
784          * Should we update the RTT?
785          */
786         if (finish != NULL || no_response) {
787                 if (finish != NULL) {
788                         /*
789                          * We have both the start and finish times for this
790                          * packet, so we can compute a real RTT.
791                          */
792                         rtt = (unsigned int)isc_time_microdiff(finish,
793                                                                &query->start);
794                         factor = DNS_ADB_RTTADJDEFAULT;
795
796                         rttms = rtt / 1000;
797                         if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
798                                 inc_stats(fctx->res,
799                                           dns_resstatscounter_queryrtt0);
800                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
801                                 inc_stats(fctx->res,
802                                           dns_resstatscounter_queryrtt1);
803                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
804                                 inc_stats(fctx->res,
805                                           dns_resstatscounter_queryrtt2);
806                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
807                                 inc_stats(fctx->res,
808                                           dns_resstatscounter_queryrtt3);
809                         } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
810                                 inc_stats(fctx->res,
811                                           dns_resstatscounter_queryrtt4);
812                         } else {
813                                 inc_stats(fctx->res,
814                                           dns_resstatscounter_queryrtt5);
815                         }
816                 } else {
817                         /*
818                          * We don't have an RTT for this query.  Maybe the
819                          * packet was lost, or maybe this server is very
820                          * slow.  We don't know.  Increase the RTT.
821                          */
822                         INSIST(no_response);
823                         rtt = query->addrinfo->srtt + 200000;
824                         if (rtt > 10000000)
825                                 rtt = 10000000;
826                         /*
827                          * Replace the current RTT with our value.
828                          */
829                         factor = DNS_ADB_RTTADJREPLACE;
830                 }
831                 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
832         }
833
834         /* Remember that the server has been tried. */
835         if (!TRIED(query->addrinfo)) {
836                 dns_adb_changeflags(fctx->adb, query->addrinfo,
837                                     FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
838         }
839
840         /*
841          * Age RTTs of servers not tried.
842          */
843         factor = DNS_ADB_RTTADJAGE;
844         if (finish != NULL)
845                 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
846                      addrinfo != NULL;
847                      addrinfo = ISC_LIST_NEXT(addrinfo, publink))
848                         if (UNMARKED(addrinfo))
849                                 dns_adb_adjustsrtt(fctx->adb, addrinfo,
850                                                    0, factor);
851
852         if (finish != NULL && TRIEDFIND(fctx))
853                 for (find = ISC_LIST_HEAD(fctx->finds);
854                      find != NULL;
855                      find = ISC_LIST_NEXT(find, publink))
856                         for (addrinfo = ISC_LIST_HEAD(find->list);
857                              addrinfo != NULL;
858                              addrinfo = ISC_LIST_NEXT(addrinfo, publink))
859                                 if (UNMARKED(addrinfo))
860                                         dns_adb_adjustsrtt(fctx->adb, addrinfo,
861                                                            0, factor);
862
863         if (finish != NULL && TRIEDALT(fctx)) {
864                 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
865                      addrinfo != NULL;
866                      addrinfo = ISC_LIST_NEXT(addrinfo, publink))
867                         if (UNMARKED(addrinfo))
868                                 dns_adb_adjustsrtt(fctx->adb, addrinfo,
869                                                    0, factor);
870                 for (find = ISC_LIST_HEAD(fctx->altfinds);
871                      find != NULL;
872                      find = ISC_LIST_NEXT(find, publink))
873                         for (addrinfo = ISC_LIST_HEAD(find->list);
874                              addrinfo != NULL;
875                              addrinfo = ISC_LIST_NEXT(addrinfo, publink))
876                                 if (UNMARKED(addrinfo))
877                                         dns_adb_adjustsrtt(fctx->adb, addrinfo,
878                                                            0, factor);
879         }
880
881         /*
882          * Check for any outstanding socket events.  If they exist, cancel
883          * them and let the event handlers finish the cleanup.  The resolver
884          * only needs to worry about managing the connect and send events;
885          * the dispatcher manages the recv events.
886          */
887         if (RESQUERY_CONNECTING(query)) {
888                 /*
889                  * Cancel the connect.
890                  */
891                 if (query->tcpsocket != NULL) {
892                         isc_socket_cancel(query->tcpsocket, NULL,
893                                           ISC_SOCKCANCEL_CONNECT);
894                 } else if (query->dispentry != NULL) {
895                         INSIST(query->exclusivesocket);
896                         socket = dns_dispatch_getentrysocket(query->dispentry);
897                         if (socket != NULL)
898                                 isc_socket_cancel(socket, NULL,
899                                                   ISC_SOCKCANCEL_CONNECT);
900                 }
901         } else if (RESQUERY_SENDING(query)) {
902                 /*
903                  * Cancel the pending send.
904                  */
905                 if (query->exclusivesocket && query->dispentry != NULL)
906                         socket = dns_dispatch_getentrysocket(query->dispentry);
907                 else
908                         socket = dns_dispatch_getsocket(query->dispatch);
909                 if (socket != NULL)
910                         isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
911         }
912
913         if (query->dispentry != NULL)
914                 dns_dispatch_removeresponse(&query->dispentry, deventp);
915
916         ISC_LIST_UNLINK(fctx->queries, query, link);
917
918         if (query->tsig != NULL)
919                 isc_buffer_free(&query->tsig);
920
921         if (query->tsigkey != NULL)
922                 dns_tsigkey_detach(&query->tsigkey);
923
924         if (query->dispatch != NULL)
925                 dns_dispatch_detach(&query->dispatch);
926
927         if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
928                 /*
929                  * It's safe to destroy the query now.
930                  */
931                 resquery_destroy(&query);
932 }
933
934 static void
935 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
936         resquery_t *query, *next_query;
937
938         FCTXTRACE("cancelqueries");
939
940         for (query = ISC_LIST_HEAD(fctx->queries);
941              query != NULL;
942              query = next_query) {
943                 next_query = ISC_LIST_NEXT(query, link);
944                 fctx_cancelquery(&query, NULL, NULL, no_response);
945         }
946 }
947
948 static void
949 fctx_cleanupfinds(fetchctx_t *fctx) {
950         dns_adbfind_t *find, *next_find;
951
952         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
953
954         for (find = ISC_LIST_HEAD(fctx->finds);
955              find != NULL;
956              find = next_find) {
957                 next_find = ISC_LIST_NEXT(find, publink);
958                 ISC_LIST_UNLINK(fctx->finds, find, publink);
959                 dns_adb_destroyfind(&find);
960         }
961         fctx->find = NULL;
962 }
963
964 static void
965 fctx_cleanupaltfinds(fetchctx_t *fctx) {
966         dns_adbfind_t *find, *next_find;
967
968         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
969
970         for (find = ISC_LIST_HEAD(fctx->altfinds);
971              find != NULL;
972              find = next_find) {
973                 next_find = ISC_LIST_NEXT(find, publink);
974                 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
975                 dns_adb_destroyfind(&find);
976         }
977         fctx->altfind = NULL;
978 }
979
980 static void
981 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
982         dns_adbaddrinfo_t *addr, *next_addr;
983
984         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
985
986         for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
987              addr != NULL;
988              addr = next_addr) {
989                 next_addr = ISC_LIST_NEXT(addr, publink);
990                 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
991                 dns_adb_freeaddrinfo(fctx->adb, &addr);
992         }
993 }
994
995 static void
996 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
997         dns_adbaddrinfo_t *addr, *next_addr;
998
999         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1000
1001         for (addr = ISC_LIST_HEAD(fctx->altaddrs);
1002              addr != NULL;
1003              addr = next_addr) {
1004                 next_addr = ISC_LIST_NEXT(addr, publink);
1005                 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
1006                 dns_adb_freeaddrinfo(fctx->adb, &addr);
1007         }
1008 }
1009
1010 static inline void
1011 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
1012         FCTXTRACE("stopeverything");
1013         fctx_cancelqueries(fctx, no_response);
1014         fctx_cleanupfinds(fctx);
1015         fctx_cleanupaltfinds(fctx);
1016         fctx_cleanupforwaddrs(fctx);
1017         fctx_cleanupaltaddrs(fctx);
1018         fctx_stoptimer(fctx);
1019 }
1020
1021 static inline void
1022 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
1023         dns_fetchevent_t *event, *next_event;
1024         isc_task_t *task;
1025         unsigned int count = 0;
1026         isc_interval_t i;
1027         isc_boolean_t logit = ISC_FALSE;
1028         isc_time_t now;
1029         unsigned int old_spillat;
1030         unsigned int new_spillat = 0;   /* initialized to silence
1031                                            compiler warnings */
1032
1033         /*
1034          * Caller must be holding the appropriate bucket lock.
1035          */
1036         REQUIRE(fctx->state == fetchstate_done);
1037
1038         FCTXTRACE("sendevents");
1039
1040         /*
1041          * Keep some record of fetch result for logging later (if required).
1042          */
1043         fctx->result = result;
1044         fctx->exitline = line;
1045         TIME_NOW(&now);
1046         fctx->duration = isc_time_microdiff(&now, &fctx->start);
1047
1048         for (event = ISC_LIST_HEAD(fctx->events);
1049              event != NULL;
1050              event = next_event) {
1051                 next_event = ISC_LIST_NEXT(event, ev_link);
1052                 ISC_LIST_UNLINK(fctx->events, event, ev_link);
1053                 task = event->ev_sender;
1054                 event->ev_sender = fctx;
1055                 event->vresult = fctx->vresult;
1056                 if (!HAVE_ANSWER(fctx))
1057                         event->result = result;
1058
1059                 INSIST(result != ISC_R_SUCCESS ||
1060                        dns_rdataset_isassociated(event->rdataset) ||
1061                        fctx->type == dns_rdatatype_any ||
1062                        fctx->type == dns_rdatatype_rrsig ||
1063                        fctx->type == dns_rdatatype_sig);
1064
1065                 /*
1066                  * Negative results must be indicated in event->result.
1067                  */
1068                 if (dns_rdataset_isassociated(event->rdataset) &&
1069                     NEGATIVE(event->rdataset)) {
1070                         INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
1071                                event->result == DNS_R_NCACHENXRRSET);
1072                 }
1073
1074                 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
1075                 count++;
1076         }
1077
1078         if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
1079             fctx->spilled &&
1080             (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
1081                 LOCK(&fctx->res->lock);
1082                 if (count == fctx->res->spillat && !fctx->res->exiting) {
1083                         old_spillat = fctx->res->spillat;
1084                         fctx->res->spillat += 5;
1085                         if (fctx->res->spillat > fctx->res->spillatmax &&
1086                             fctx->res->spillatmax != 0)
1087                                 fctx->res->spillat = fctx->res->spillatmax;
1088                         new_spillat = fctx->res->spillat;
1089                         if (new_spillat != old_spillat) {
1090                                 logit = ISC_TRUE;
1091                         }
1092                         isc_interval_set(&i, 20 * 60, 0);
1093                         result = isc_timer_reset(fctx->res->spillattimer,
1094                                                  isc_timertype_ticker, NULL,
1095                                                  &i, ISC_TRUE);
1096                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1097                 }
1098                 UNLOCK(&fctx->res->lock);
1099                 if (logit)
1100                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
1101                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
1102                                       "clients-per-query increased to %u",
1103                                       new_spillat);
1104         }
1105 }
1106
1107 static inline void
1108 log_edns(fetchctx_t *fctx) {
1109         char domainbuf[DNS_NAME_FORMATSIZE];
1110
1111         if (fctx->reason == NULL)
1112                 return;
1113
1114         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
1115         isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
1116                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1117                       "success resolving '%s' (in '%s'?) after %s",
1118                       fctx->info, domainbuf, fctx->reason);
1119
1120         fctx->reason = NULL;
1121 }
1122
1123 static void
1124 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
1125         dns_resolver_t *res;
1126         isc_boolean_t no_response;
1127
1128         REQUIRE(line >= 0);
1129
1130         FCTXTRACE("done");
1131
1132         res = fctx->res;
1133
1134         if (result == ISC_R_SUCCESS) {
1135                 /*%
1136                  * Log any deferred EDNS timeout messages.
1137                  */
1138                 log_edns(fctx);
1139                 no_response = ISC_TRUE;
1140          } else
1141                 no_response = ISC_FALSE;
1142
1143         fctx->reason = NULL;
1144         fctx_stopeverything(fctx, no_response);
1145
1146         LOCK(&res->buckets[fctx->bucketnum].lock);
1147
1148         fctx->state = fetchstate_done;
1149         fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1150         fctx_sendevents(fctx, result, line);
1151
1152         UNLOCK(&res->buckets[fctx->bucketnum].lock);
1153 }
1154
1155 static void
1156 process_sendevent(resquery_t *query, isc_event_t *event) {
1157         isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1158         isc_boolean_t retry = ISC_FALSE;
1159         isc_result_t result;
1160         fetchctx_t *fctx;
1161
1162         fctx = query->fctx;
1163
1164         if (RESQUERY_CANCELED(query)) {
1165                 if (query->sends == 0 && query->connects == 0) {
1166                         /*
1167                          * This query was canceled while the
1168                          * isc_socket_sendto/connect() was in progress.
1169                          */
1170                         if (query->tcpsocket != NULL)
1171                                 isc_socket_detach(&query->tcpsocket);
1172                         resquery_destroy(&query);
1173                 }
1174         } else {
1175                 switch (sevent->result) {
1176                 case ISC_R_SUCCESS:
1177                         break;
1178
1179                 case ISC_R_HOSTUNREACH:
1180                 case ISC_R_NETUNREACH:
1181                 case ISC_R_NOPERM:
1182                 case ISC_R_ADDRNOTAVAIL:
1183                 case ISC_R_CONNREFUSED:
1184
1185                         /*
1186                          * No route to remote.
1187                          */
1188                         add_bad(fctx, query->addrinfo, sevent->result,
1189                                 badns_unreachable);
1190                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
1191                         retry = ISC_TRUE;
1192                         break;
1193
1194                 default:
1195                         fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1196                         break;
1197                 }
1198         }
1199
1200         isc_event_free(&event);
1201
1202         if (retry) {
1203                 /*
1204                  * Behave as if the idle timer has expired.  For TCP
1205                  * this may not actually reflect the latest timer.
1206                  */
1207                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1208                 result = fctx_stopidletimer(fctx);
1209                 if (result != ISC_R_SUCCESS)
1210                         fctx_done(fctx, result, __LINE__);
1211                 else
1212                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
1213         }
1214 }
1215
1216 static void
1217 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
1218         resquery_t *query = event->ev_arg;
1219
1220         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1221
1222         QTRACE("udpconnected");
1223
1224         UNUSED(task);
1225
1226         INSIST(RESQUERY_CONNECTING(query));
1227
1228         query->connects--;
1229
1230         process_sendevent(query, event);
1231 }
1232
1233 static void
1234 resquery_senddone(isc_task_t *task, isc_event_t *event) {
1235         resquery_t *query = event->ev_arg;
1236
1237         REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1238
1239         QTRACE("senddone");
1240
1241         /*
1242          * XXXRTH
1243          *
1244          * Currently we don't wait for the senddone event before retrying
1245          * a query.  This means that if we get really behind, we may end
1246          * up doing extra work!
1247          */
1248
1249         UNUSED(task);
1250
1251         INSIST(RESQUERY_SENDING(query));
1252
1253         query->sends--;
1254
1255         process_sendevent(query, event);
1256 }
1257
1258 static inline isc_result_t
1259 fctx_addopt(dns_message_t *message, unsigned int version,
1260             isc_uint16_t udpsize, isc_boolean_t request_nsid)
1261 {
1262         dns_rdataset_t *rdataset;
1263         dns_rdatalist_t *rdatalist;
1264         dns_rdata_t *rdata;
1265         isc_result_t result;
1266
1267         rdatalist = NULL;
1268         result = dns_message_gettemprdatalist(message, &rdatalist);
1269         if (result != ISC_R_SUCCESS)
1270                 return (result);
1271         rdata = NULL;
1272         result = dns_message_gettemprdata(message, &rdata);
1273         if (result != ISC_R_SUCCESS)
1274                 return (result);
1275         rdataset = NULL;
1276         result = dns_message_gettemprdataset(message, &rdataset);
1277         if (result != ISC_R_SUCCESS)
1278                 return (result);
1279         dns_rdataset_init(rdataset);
1280
1281         rdatalist->type = dns_rdatatype_opt;
1282         rdatalist->covers = 0;
1283
1284         /*
1285          * Set Maximum UDP buffer size.
1286          */
1287         rdatalist->rdclass = udpsize;
1288
1289         /*
1290          * Set EXTENDED-RCODE and Z to 0, DO to 1.
1291          */
1292         rdatalist->ttl = (version << 16);
1293         rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1294
1295         /*
1296          * Set EDNS options if applicable
1297          */
1298         if (request_nsid) {
1299                 /* Send empty NSID option (RFC5001) */
1300                 unsigned char data[4];
1301                 isc_buffer_t buf;
1302
1303                 isc_buffer_init(&buf, data, sizeof(data));
1304                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
1305                 isc_buffer_putuint16(&buf, 0);
1306                 rdata->data = data;
1307                 rdata->length = sizeof(data);
1308         } else {
1309                 rdata->data = NULL;
1310                 rdata->length = 0;
1311         }
1312
1313         rdata->rdclass = rdatalist->rdclass;
1314         rdata->type = rdatalist->type;
1315         rdata->flags = 0;
1316
1317         ISC_LIST_INIT(rdatalist->rdata);
1318         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1319         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
1320
1321         return (dns_message_setopt(message, rdataset));
1322 }
1323
1324 static inline void
1325 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
1326         unsigned int seconds;
1327         unsigned int us;
1328
1329         /*
1330          * We retry every .8 seconds the first two times through the address
1331          * list, and then we do exponential back-off.
1332          */
1333         if (fctx->restarts < 3)
1334                 us = 800000;
1335         else
1336                 us = (800000 << (fctx->restarts - 2));
1337
1338         /*
1339          * Double the round-trip time.
1340          */
1341         rtt *= 2;
1342
1343         /*
1344          * Always wait for at least the doubled round-trip time.
1345          */
1346         if (us < rtt)
1347                 us = rtt;
1348
1349         /*
1350          * But don't ever wait for more than 10 seconds.
1351          */
1352         if (us > 10000000)
1353                 us = 10000000;
1354
1355         seconds = us / 1000000;
1356         us -= seconds * 1000000;
1357         isc_interval_set(&fctx->interval, seconds, us * 1000);
1358 }
1359
1360 static isc_result_t
1361 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
1362            unsigned int options)
1363 {
1364         dns_resolver_t *res;
1365         isc_task_t *task;
1366         isc_result_t result;
1367         resquery_t *query;
1368         isc_sockaddr_t addr;
1369         isc_boolean_t have_addr = ISC_FALSE;
1370         unsigned int srtt;
1371
1372         FCTXTRACE("query");
1373
1374         res = fctx->res;
1375         task = res->buckets[fctx->bucketnum].task;
1376
1377         srtt = addrinfo->srtt;
1378         if (ISFORWARDER(addrinfo) && srtt < 1000000)
1379                 srtt = 1000000;
1380
1381         fctx_setretryinterval(fctx, srtt);
1382         result = fctx_startidletimer(fctx, &fctx->interval);
1383         if (result != ISC_R_SUCCESS)
1384                 return (result);
1385
1386         INSIST(ISC_LIST_EMPTY(fctx->validators));
1387
1388         dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
1389
1390         query = isc_mem_get(fctx->mctx, sizeof(*query));
1391         if (query == NULL) {
1392                 result = ISC_R_NOMEMORY;
1393                 goto stop_idle_timer;
1394         }
1395         query->mctx = fctx->mctx;
1396         query->options = options;
1397         query->attributes = 0;
1398         query->sends = 0;
1399         query->connects = 0;
1400         /*
1401          * Note that the caller MUST guarantee that 'addrinfo' will remain
1402          * valid until this query is canceled.
1403          */
1404         query->addrinfo = addrinfo;
1405         TIME_NOW(&query->start);
1406
1407         /*
1408          * If this is a TCP query, then we need to make a socket and
1409          * a dispatch for it here.  Otherwise we use the resolver's
1410          * shared dispatch.
1411          */
1412         query->dispatchmgr = res->dispatchmgr;
1413         query->dispatch = NULL;
1414         query->exclusivesocket = ISC_FALSE;
1415         query->tcpsocket = NULL;
1416         if (res->view->peers != NULL) {
1417                 dns_peer_t *peer = NULL;
1418                 isc_netaddr_t dstip;
1419                 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
1420                 result = dns_peerlist_peerbyaddr(res->view->peers,
1421                                                  &dstip, &peer);
1422                 if (result == ISC_R_SUCCESS) {
1423                         result = dns_peer_getquerysource(peer, &addr);
1424                         if (result == ISC_R_SUCCESS)
1425                                 have_addr = ISC_TRUE;
1426                 }
1427         }
1428
1429         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1430                 int pf;
1431
1432                 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1433                 if (!have_addr) {
1434                         switch (pf) {
1435                         case PF_INET:
1436                                 result =
1437                                   dns_dispatch_getlocaladdress(res->dispatchv4,
1438                                                                &addr);
1439                                 break;
1440                         case PF_INET6:
1441                                 result =
1442                                   dns_dispatch_getlocaladdress(res->dispatchv6,
1443                                                                &addr);
1444                                 break;
1445                         default:
1446                                 result = ISC_R_NOTIMPLEMENTED;
1447                                 break;
1448                         }
1449                         if (result != ISC_R_SUCCESS)
1450                                 goto cleanup_query;
1451                 }
1452                 isc_sockaddr_setport(&addr, 0);
1453
1454                 result = isc_socket_create(res->socketmgr, pf,
1455                                            isc_sockettype_tcp,
1456                                            &query->tcpsocket);
1457                 if (result != ISC_R_SUCCESS)
1458                         goto cleanup_query;
1459
1460 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1461                 result = isc_socket_bind(query->tcpsocket, &addr, 0);
1462                 if (result != ISC_R_SUCCESS)
1463                         goto cleanup_socket;
1464 #endif
1465
1466                 /*
1467                  * A dispatch will be created once the connect succeeds.
1468                  */
1469         } else {
1470                 if (have_addr) {
1471                         unsigned int attrs, attrmask;
1472                         attrs = DNS_DISPATCHATTR_UDP;
1473                         switch (isc_sockaddr_pf(&addr)) {
1474                         case AF_INET:
1475                                 attrs |= DNS_DISPATCHATTR_IPV4;
1476                                 break;
1477                         case AF_INET6:
1478                                 attrs |= DNS_DISPATCHATTR_IPV6;
1479                                 break;
1480                         default:
1481                                 result = ISC_R_NOTIMPLEMENTED;
1482                                 goto cleanup_query;
1483                         }
1484                         attrmask = DNS_DISPATCHATTR_UDP;
1485                         attrmask |= DNS_DISPATCHATTR_TCP;
1486                         attrmask |= DNS_DISPATCHATTR_IPV4;
1487                         attrmask |= DNS_DISPATCHATTR_IPV6;
1488                         result = dns_dispatch_getudp(res->dispatchmgr,
1489                                                      res->socketmgr,
1490                                                      res->taskmgr, &addr,
1491                                                      4096, 1000, 32768, 16411,
1492                                                      16433, attrs, attrmask,
1493                                                      &query->dispatch);
1494                         if (result != ISC_R_SUCCESS)
1495                                 goto cleanup_query;
1496                 } else {
1497                         switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1498                         case PF_INET:
1499                                 dns_dispatch_attach(res->dispatchv4,
1500                                                     &query->dispatch);
1501                                 query->exclusivesocket = res->exclusivev4;
1502                                 break;
1503                         case PF_INET6:
1504                                 dns_dispatch_attach(res->dispatchv6,
1505                                                     &query->dispatch);
1506                                 query->exclusivesocket = res->exclusivev6;
1507                                 break;
1508                         default:
1509                                 result = ISC_R_NOTIMPLEMENTED;
1510                                 goto cleanup_query;
1511                         }
1512                 }
1513                 /*
1514                  * We should always have a valid dispatcher here.  If we
1515                  * don't support a protocol family, then its dispatcher
1516                  * will be NULL, but we shouldn't be finding addresses for
1517                  * protocol types we don't support, so the dispatcher
1518                  * we found should never be NULL.
1519                  */
1520                 INSIST(query->dispatch != NULL);
1521         }
1522
1523         query->dispentry = NULL;
1524         query->fctx = fctx;
1525         query->tsig = NULL;
1526         query->tsigkey = NULL;
1527         ISC_LINK_INIT(query, link);
1528         query->magic = QUERY_MAGIC;
1529
1530         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1531                 /*
1532                  * Connect to the remote server.
1533                  *
1534                  * XXXRTH  Should we attach to the socket?
1535                  */
1536                 result = isc_socket_connect(query->tcpsocket,
1537                                             &addrinfo->sockaddr, task,
1538                                             resquery_connected, query);
1539                 if (result != ISC_R_SUCCESS)
1540                         goto cleanup_socket;
1541                 query->connects++;
1542                 QTRACE("connecting via TCP");
1543         } else {
1544                 result = resquery_send(query);
1545                 if (result != ISC_R_SUCCESS)
1546                         goto cleanup_dispatch;
1547         }
1548         fctx->querysent++;
1549
1550         ISC_LIST_APPEND(fctx->queries, query, link);
1551         query->fctx->nqueries++;
1552         if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
1553                 inc_stats(res, dns_resstatscounter_queryv4);
1554         else
1555                 inc_stats(res, dns_resstatscounter_queryv6);
1556         if (res->view->resquerystats != NULL)
1557                 dns_rdatatypestats_increment(res->view->resquerystats,
1558                                              fctx->type);
1559
1560         return (ISC_R_SUCCESS);
1561
1562  cleanup_socket:
1563         isc_socket_detach(&query->tcpsocket);
1564
1565  cleanup_dispatch:
1566         if (query->dispatch != NULL)
1567                 dns_dispatch_detach(&query->dispatch);
1568
1569  cleanup_query:
1570         if (query->connects == 0) {
1571                 query->magic = 0;
1572                 isc_mem_put(fctx->mctx, query, sizeof(*query));
1573         }
1574
1575  stop_idle_timer:
1576         RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1577
1578         return (result);
1579 }
1580
1581 static isc_boolean_t
1582 bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1583         isc_sockaddr_t *sa;
1584
1585         for (sa = ISC_LIST_HEAD(fctx->bad_edns);
1586              sa != NULL;
1587              sa = ISC_LIST_NEXT(sa, link)) {
1588                 if (isc_sockaddr_equal(sa, address))
1589                         return (ISC_TRUE);
1590         }
1591
1592         return (ISC_FALSE);
1593 }
1594
1595 static void
1596 add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1597         isc_sockaddr_t *sa;
1598
1599         if (bad_edns(fctx, address))
1600                 return;
1601
1602         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1603         if (sa == NULL)
1604                 return;
1605
1606         *sa = *address;
1607         ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
1608 }
1609
1610 static isc_boolean_t
1611 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1612         isc_sockaddr_t *sa;
1613
1614         for (sa = ISC_LIST_HEAD(fctx->edns);
1615              sa != NULL;
1616              sa = ISC_LIST_NEXT(sa, link)) {
1617                 if (isc_sockaddr_equal(sa, address))
1618                         return (ISC_TRUE);
1619         }
1620
1621         return (ISC_FALSE);
1622 }
1623
1624 static void
1625 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1626         isc_sockaddr_t *sa;
1627
1628         if (triededns(fctx, address))
1629                 return;
1630
1631         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1632         if (sa == NULL)
1633                 return;
1634
1635         *sa = *address;
1636         ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
1637 }
1638
1639 static isc_boolean_t
1640 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1641         isc_sockaddr_t *sa;
1642
1643         for (sa = ISC_LIST_HEAD(fctx->edns512);
1644              sa != NULL;
1645              sa = ISC_LIST_NEXT(sa, link)) {
1646                 if (isc_sockaddr_equal(sa, address))
1647                         return (ISC_TRUE);
1648         }
1649
1650         return (ISC_FALSE);
1651 }
1652
1653 static void
1654 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1655         isc_sockaddr_t *sa;
1656
1657         if (triededns512(fctx, address))
1658                 return;
1659
1660         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1661         if (sa == NULL)
1662                 return;
1663
1664         *sa = *address;
1665         ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
1666 }
1667
1668 static isc_result_t
1669 resquery_send(resquery_t *query) {
1670         fetchctx_t *fctx;
1671         isc_result_t result;
1672         dns_name_t *qname = NULL;
1673         dns_rdataset_t *qrdataset = NULL;
1674         isc_region_t r;
1675         dns_resolver_t *res;
1676         isc_task_t *task;
1677         isc_socket_t *socket;
1678         isc_buffer_t tcpbuffer;
1679         isc_sockaddr_t *address;
1680         isc_buffer_t *buffer;
1681         isc_netaddr_t ipaddr;
1682         dns_tsigkey_t *tsigkey = NULL;
1683         dns_peer_t *peer = NULL;
1684         isc_boolean_t useedns;
1685         dns_compress_t cctx;
1686         isc_boolean_t cleanup_cctx = ISC_FALSE;
1687         isc_boolean_t secure_domain;
1688         isc_boolean_t connecting = ISC_FALSE;
1689
1690         fctx = query->fctx;
1691         QTRACE("send");
1692
1693         res = fctx->res;
1694         task = res->buckets[fctx->bucketnum].task;
1695         address = NULL;
1696
1697         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1698                 /*
1699                  * Reserve space for the TCP message length.
1700                  */
1701                 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1702                 isc_buffer_init(&query->buffer, query->data + 2,
1703                                 sizeof(query->data) - 2);
1704                 buffer = &tcpbuffer;
1705         } else {
1706                 isc_buffer_init(&query->buffer, query->data,
1707                                 sizeof(query->data));
1708                 buffer = &query->buffer;
1709         }
1710
1711         result = dns_message_gettempname(fctx->qmessage, &qname);
1712         if (result != ISC_R_SUCCESS)
1713                 goto cleanup_temps;
1714         result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1715         if (result != ISC_R_SUCCESS)
1716                 goto cleanup_temps;
1717
1718         /*
1719          * Get a query id from the dispatch.
1720          */
1721         result = dns_dispatch_addresponse2(query->dispatch,
1722                                            &query->addrinfo->sockaddr,
1723                                            task,
1724                                            resquery_response,
1725                                            query,
1726                                            &query->id,
1727                                            &query->dispentry,
1728                                            res->socketmgr);
1729         if (result != ISC_R_SUCCESS)
1730                 goto cleanup_temps;
1731
1732         fctx->qmessage->opcode = dns_opcode_query;
1733
1734         /*
1735          * Set up question.
1736          */
1737         dns_name_init(qname, NULL);
1738         dns_name_clone(&fctx->name, qname);
1739         dns_rdataset_init(qrdataset);
1740         dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1741         ISC_LIST_APPEND(qname->list, qrdataset, link);
1742         dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1743         qname = NULL;
1744         qrdataset = NULL;
1745
1746         /*
1747          * Set RD if the client has requested that we do a recursive query,
1748          * or if we're sending to a forwarder.
1749          */
1750         if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1751             ISFORWARDER(query->addrinfo))
1752                 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1753
1754         /*
1755          * Set CD if the client says don't validate or the question is
1756          * under a secure entry point.
1757          */
1758         if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
1759                 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1760         } else if (res->view->enablevalidation) {
1761                 result = dns_view_issecuredomain(res->view, &fctx->name,
1762                                                  &secure_domain);
1763                 if (result != ISC_R_SUCCESS)
1764                         secure_domain = ISC_FALSE;
1765                 if (res->view->dlv != NULL)
1766                         secure_domain = ISC_TRUE;
1767                 if (secure_domain)
1768                         fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1769         }
1770
1771         /*
1772          * We don't have to set opcode because it defaults to query.
1773          */
1774         fctx->qmessage->id = query->id;
1775
1776         /*
1777          * Convert the question to wire format.
1778          */
1779         result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1780         if (result != ISC_R_SUCCESS)
1781                 goto cleanup_message;
1782         cleanup_cctx = ISC_TRUE;
1783
1784         result = dns_message_renderbegin(fctx->qmessage, &cctx,
1785                                          &query->buffer);
1786         if (result != ISC_R_SUCCESS)
1787                 goto cleanup_message;
1788
1789         result = dns_message_rendersection(fctx->qmessage,
1790                                            DNS_SECTION_QUESTION, 0);
1791         if (result != ISC_R_SUCCESS)
1792                 goto cleanup_message;
1793
1794         peer = NULL;
1795         isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1796         (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1797
1798         /*
1799          * The ADB does not know about servers with "edns no".  Check this,
1800          * and then inform the ADB for future use.
1801          */
1802         if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1803             peer != NULL &&
1804             dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1805             !useedns)
1806         {
1807                 query->options |= DNS_FETCHOPT_NOEDNS0;
1808                 dns_adb_changeflags(fctx->adb, query->addrinfo,
1809                                     DNS_FETCHOPT_NOEDNS0,
1810                                     DNS_FETCHOPT_NOEDNS0);
1811         }
1812
1813         /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
1814         if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
1815                 query->options |= DNS_FETCHOPT_NOEDNS0;
1816
1817         /*
1818          * Handle timeouts by reducing the UDP response size to 512 bytes
1819          * then if that doesn't work disabling EDNS (includes DO) and CD.
1820          *
1821          * These timeout can be due to:
1822          *      * broken nameservers that don't respond to EDNS queries.
1823          *      * broken/misconfigured firewalls and NAT implementations
1824          *        that don't handle IP fragmentation.
1825          *      * broken/misconfigured firewalls that don't handle responses
1826          *        greater than 512 bytes.
1827          *      * broken/misconfigured firewalls that don't handle EDNS, DO
1828          *        or CD.
1829          *      * packet loss / link outage.
1830          */
1831         if (fctx->timeout) {
1832                 if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
1833                      fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
1834                     (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1835                         query->options |= DNS_FETCHOPT_NOEDNS0;
1836                         fctx->reason = "disabling EDNS";
1837                 } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
1838                             fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
1839                            (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1840                         query->options |= DNS_FETCHOPT_EDNS512;
1841                         fctx->reason = "reducing the advertised EDNS UDP "
1842                                        "packet size to 512 octets";
1843                 }
1844                 fctx->timeout = ISC_FALSE;
1845         }
1846
1847         /*
1848          * Use EDNS0, unless the caller doesn't want it, or we know that
1849          * the remote server doesn't like it.
1850          */
1851         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1852                 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1853                         unsigned int version = 0;       /* Default version. */
1854                         unsigned int flags;
1855                         isc_uint16_t udpsize = res->udpsize;
1856                         isc_boolean_t reqnsid = res->view->requestnsid;
1857
1858                         flags = query->addrinfo->flags;
1859                         if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
1860                                 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
1861                                 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
1862                         }
1863                         if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1864                                 udpsize = 512;
1865                         else if (peer != NULL)
1866                                 (void)dns_peer_getudpsize(peer, &udpsize);
1867
1868                         /* request NSID for current view or peer? */
1869                         if (peer != NULL)
1870                                 (void) dns_peer_getrequestnsid(peer, &reqnsid);
1871                         result = fctx_addopt(fctx->qmessage, version,
1872                                              udpsize, reqnsid);
1873                         if (reqnsid && result == ISC_R_SUCCESS) {
1874                                 query->options |= DNS_FETCHOPT_WANTNSID;
1875                         } else if (result != ISC_R_SUCCESS) {
1876                                 /*
1877                                  * We couldn't add the OPT, but we'll press on.
1878                                  * We're not using EDNS0, so set the NOEDNS0
1879                                  * bit.
1880                                  */
1881                                 query->options |= DNS_FETCHOPT_NOEDNS0;
1882                         }
1883                 } else {
1884                         /*
1885                          * We know this server doesn't like EDNS0, so we
1886                          * won't use it.  Set the NOEDNS0 bit since we're
1887                          * not using EDNS0.
1888                          */
1889                         query->options |= DNS_FETCHOPT_NOEDNS0;
1890                 }
1891         }
1892
1893         /*
1894          * If we need EDNS0 to do this query and aren't using it, we lose.
1895          */
1896         if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1897                 result = DNS_R_SERVFAIL;
1898                 goto cleanup_message;
1899         }
1900
1901         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
1902                 add_triededns(fctx, &query->addrinfo->sockaddr);
1903
1904         if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1905                 add_triededns512(fctx, &query->addrinfo->sockaddr);
1906
1907         /*
1908          * Clear CD if EDNS is not in use.
1909          */
1910         if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
1911                 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
1912
1913         /*
1914          * Add TSIG record tailored to the current recipient.
1915          */
1916         result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1917         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1918                 goto cleanup_message;
1919
1920         if (tsigkey != NULL) {
1921                 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
1922                 dns_tsigkey_detach(&tsigkey);
1923                 if (result != ISC_R_SUCCESS)
1924                         goto cleanup_message;
1925         }
1926
1927         result = dns_message_rendersection(fctx->qmessage,
1928                                            DNS_SECTION_ADDITIONAL, 0);
1929         if (result != ISC_R_SUCCESS)
1930                 goto cleanup_message;
1931
1932         result = dns_message_renderend(fctx->qmessage);
1933         if (result != ISC_R_SUCCESS)
1934                 goto cleanup_message;
1935
1936         dns_compress_invalidate(&cctx);
1937         cleanup_cctx = ISC_FALSE;
1938
1939         if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1940                 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1941                                    &query->tsigkey);
1942                 result = dns_message_getquerytsig(fctx->qmessage,
1943                                                   fctx->res->mctx,
1944                                                   &query->tsig);
1945                 if (result != ISC_R_SUCCESS)
1946                         goto cleanup_message;
1947         }
1948
1949         /*
1950          * If using TCP, write the length of the message at the beginning
1951          * of the buffer.
1952          */
1953         if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1954                 isc_buffer_usedregion(&query->buffer, &r);
1955                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1956                 isc_buffer_add(&tcpbuffer, r.length);
1957         }
1958
1959         /*
1960          * We're now done with the query message.
1961          */
1962         dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1963
1964         if (query->exclusivesocket)
1965                 socket = dns_dispatch_getentrysocket(query->dispentry);
1966         else
1967                 socket = dns_dispatch_getsocket(query->dispatch);
1968         /*
1969          * Send the query!
1970          */
1971         if ((query->options & DNS_FETCHOPT_TCP) == 0) {
1972                 address = &query->addrinfo->sockaddr;
1973                 if (query->exclusivesocket) {
1974                         result = isc_socket_connect(socket, address, task,
1975                                                     resquery_udpconnected,
1976                                                     query);
1977                         if (result != ISC_R_SUCCESS)
1978                                 goto cleanup_message;
1979                         connecting = ISC_TRUE;
1980                         query->connects++;
1981                 }
1982         }
1983         isc_buffer_usedregion(buffer, &r);
1984
1985         /*
1986          * XXXRTH  Make sure we don't send to ourselves!  We should probably
1987          *              prune out these addresses when we get them from the ADB.
1988          */
1989         result = isc_socket_sendto(socket, &r, task, resquery_senddone,
1990                                    query, address, NULL);
1991         if (result != ISC_R_SUCCESS) {
1992                 if (connecting) {
1993                         /*
1994                          * This query is still connecting.
1995                          * Mark it as canceled so that it will just be
1996                          * cleaned up when the connected event is received.
1997                          * Keep fctx around until the event is processed.
1998                          */
1999                         query->fctx->nqueries++;
2000                         query->attributes |= RESQUERY_ATTR_CANCELED;
2001                 }
2002                 goto cleanup_message;
2003         }
2004
2005         query->sends++;
2006
2007         QTRACE("sent");
2008
2009         return (ISC_R_SUCCESS);
2010
2011  cleanup_message:
2012         if (cleanup_cctx)
2013                 dns_compress_invalidate(&cctx);
2014
2015         dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
2016
2017         /*
2018          * Stop the dispatcher from listening.
2019          */
2020         dns_dispatch_removeresponse(&query->dispentry, NULL);
2021
2022  cleanup_temps:
2023         if (qname != NULL)
2024                 dns_message_puttempname(fctx->qmessage, &qname);
2025         if (qrdataset != NULL)
2026                 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
2027
2028         return (result);
2029 }
2030
2031 static void
2032 resquery_connected(isc_task_t *task, isc_event_t *event) {
2033         isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2034         resquery_t *query = event->ev_arg;
2035         isc_boolean_t retry = ISC_FALSE;
2036         isc_interval_t interval;
2037         isc_result_t result;
2038         unsigned int attrs;
2039         fetchctx_t *fctx;
2040
2041         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2042         REQUIRE(VALID_QUERY(query));
2043
2044         QTRACE("connected");
2045
2046         UNUSED(task);
2047
2048         /*
2049          * XXXRTH
2050          *
2051          * Currently we don't wait for the connect event before retrying
2052          * a query.  This means that if we get really behind, we may end
2053          * up doing extra work!
2054          */
2055
2056         query->connects--;
2057         fctx = query->fctx;
2058
2059         if (RESQUERY_CANCELED(query)) {
2060                 /*
2061                  * This query was canceled while the connect() was in
2062                  * progress.
2063                  */
2064                 isc_socket_detach(&query->tcpsocket);
2065                 resquery_destroy(&query);
2066         } else {
2067                 switch (sevent->result) {
2068                 case ISC_R_SUCCESS:
2069
2070                         /*
2071                          * Extend the idle timer for TCP.  20 seconds
2072                          * should be long enough for a TCP connection to be
2073                          * established, a single DNS request to be sent,
2074                          * and the response received.
2075                          */
2076                         isc_interval_set(&interval, 20, 0);
2077                         result = fctx_startidletimer(query->fctx, &interval);
2078                         if (result != ISC_R_SUCCESS) {
2079                                 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2080                                 fctx_done(fctx, result, __LINE__);
2081                                 break;
2082                         }
2083                         /*
2084                          * We are connected.  Create a dispatcher and
2085                          * send the query.
2086                          */
2087                         attrs = 0;
2088                         attrs |= DNS_DISPATCHATTR_TCP;
2089                         attrs |= DNS_DISPATCHATTR_PRIVATE;
2090                         attrs |= DNS_DISPATCHATTR_CONNECTED;
2091                         if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
2092                             AF_INET)
2093                                 attrs |= DNS_DISPATCHATTR_IPV4;
2094                         else
2095                                 attrs |= DNS_DISPATCHATTR_IPV6;
2096                         attrs |= DNS_DISPATCHATTR_MAKEQUERY;
2097
2098                         result = dns_dispatch_createtcp(query->dispatchmgr,
2099                                                      query->tcpsocket,
2100                                                      query->fctx->res->taskmgr,
2101                                                      4096, 2, 1, 1, 3, attrs,
2102                                                      &query->dispatch);
2103
2104                         /*
2105                          * Regardless of whether dns_dispatch_create()
2106                          * succeeded or not, we don't need our reference
2107                          * to the socket anymore.
2108                          */
2109                         isc_socket_detach(&query->tcpsocket);
2110
2111                         if (result == ISC_R_SUCCESS)
2112                                 result = resquery_send(query);
2113
2114                         if (result != ISC_R_SUCCESS) {
2115                                 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2116                                 fctx_done(fctx, result, __LINE__);
2117                         }
2118                         break;
2119
2120                 case ISC_R_NETUNREACH:
2121                 case ISC_R_HOSTUNREACH:
2122                 case ISC_R_CONNREFUSED:
2123                 case ISC_R_NOPERM:
2124                 case ISC_R_ADDRNOTAVAIL:
2125                 case ISC_R_CONNECTIONRESET:
2126                         /*
2127                          * No route to remote.
2128                          */
2129                         isc_socket_detach(&query->tcpsocket);
2130                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
2131                         retry = ISC_TRUE;
2132                         break;
2133
2134                 default:
2135                         isc_socket_detach(&query->tcpsocket);
2136                         fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2137                         break;
2138                 }
2139         }
2140
2141         isc_event_free(&event);
2142
2143         if (retry) {
2144                 /*
2145                  * Behave as if the idle timer has expired.  For TCP
2146                  * connections this may not actually reflect the latest timer.
2147                  */
2148                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2149                 result = fctx_stopidletimer(fctx);
2150                 if (result != ISC_R_SUCCESS)
2151                         fctx_done(fctx, result, __LINE__);
2152                 else
2153                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2154         }
2155 }
2156
2157 static void
2158 fctx_finddone(isc_task_t *task, isc_event_t *event) {
2159         fetchctx_t *fctx;
2160         dns_adbfind_t *find;
2161         dns_resolver_t *res;
2162         isc_boolean_t want_try = ISC_FALSE;
2163         isc_boolean_t want_done = ISC_FALSE;
2164         isc_boolean_t bucket_empty = ISC_FALSE;
2165         unsigned int bucketnum;
2166         isc_boolean_t destroy = ISC_FALSE;
2167
2168         find = event->ev_sender;
2169         fctx = event->ev_arg;
2170         REQUIRE(VALID_FCTX(fctx));
2171         res = fctx->res;
2172
2173         UNUSED(task);
2174
2175         FCTXTRACE("finddone");
2176
2177         bucketnum = fctx->bucketnum;
2178         LOCK(&res->buckets[bucketnum].lock);
2179
2180         INSIST(fctx->pending > 0);
2181         fctx->pending--;
2182
2183         if (ADDRWAIT(fctx)) {
2184                 /*
2185                  * The fetch is waiting for a name to be found.
2186                  */
2187                 INSIST(!SHUTTINGDOWN(fctx));
2188                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2189                 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
2190                         want_try = ISC_TRUE;
2191                 else {
2192                         fctx->findfail++;
2193                         if (fctx->pending == 0) {
2194                                 /*
2195                                  * We've got nothing else to wait for and don't
2196                                  * know the answer.  There's nothing to do but
2197                                  * fail the fctx.
2198                                  */
2199                                 want_done = ISC_TRUE;
2200                         }
2201                 }
2202         } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
2203                    fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
2204
2205                 if (fctx->references == 0) {
2206                         bucket_empty = fctx_unlink(fctx);
2207                         destroy = ISC_TRUE;
2208                 }
2209         }
2210         UNLOCK(&res->buckets[bucketnum].lock);
2211
2212         isc_event_free(&event);
2213         dns_adb_destroyfind(&find);
2214
2215         if (want_try)
2216                 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2217         else if (want_done)
2218                 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
2219         else if (destroy) {
2220                         fctx_destroy(fctx);
2221                 if (bucket_empty)
2222                         empty_bucket(res);
2223         }
2224 }
2225
2226
2227 static inline isc_boolean_t
2228 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
2229         isc_sockaddr_t *sa;
2230
2231         for (sa = ISC_LIST_HEAD(fctx->bad);
2232              sa != NULL;
2233              sa = ISC_LIST_NEXT(sa, link)) {
2234                 if (isc_sockaddr_equal(sa, address))
2235                         return (ISC_TRUE);
2236         }
2237
2238         return (ISC_FALSE);
2239 }
2240
2241 static inline isc_boolean_t
2242 mark_bad(fetchctx_t *fctx) {
2243         dns_adbfind_t *curr;
2244         dns_adbaddrinfo_t *addrinfo;
2245         isc_boolean_t all_bad = ISC_TRUE;
2246
2247         /*
2248          * Mark all known bad servers, so we don't try to talk to them
2249          * again.
2250          */
2251
2252         /*
2253          * Mark any bad nameservers.
2254          */
2255         for (curr = ISC_LIST_HEAD(fctx->finds);
2256              curr != NULL;
2257              curr = ISC_LIST_NEXT(curr, publink)) {
2258                 for (addrinfo = ISC_LIST_HEAD(curr->list);
2259                      addrinfo != NULL;
2260                      addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2261                         if (bad_server(fctx, &addrinfo->sockaddr))
2262                                 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2263                         else
2264                                 all_bad = ISC_FALSE;
2265                 }
2266         }
2267
2268         /*
2269          * Mark any bad forwarders.
2270          */
2271         for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2272              addrinfo != NULL;
2273              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2274                 if (bad_server(fctx, &addrinfo->sockaddr))
2275                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
2276                 else
2277                         all_bad = ISC_FALSE;
2278         }
2279
2280         /*
2281          * Mark any bad alternates.
2282          */
2283         for (curr = ISC_LIST_HEAD(fctx->altfinds);
2284              curr != NULL;
2285              curr = ISC_LIST_NEXT(curr, publink)) {
2286                 for (addrinfo = ISC_LIST_HEAD(curr->list);
2287                      addrinfo != NULL;
2288                      addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2289                         if (bad_server(fctx, &addrinfo->sockaddr))
2290                                 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2291                         else
2292                                 all_bad = ISC_FALSE;
2293                 }
2294         }
2295
2296         for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2297              addrinfo != NULL;
2298              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2299                 if (bad_server(fctx, &addrinfo->sockaddr))
2300                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
2301                 else
2302                         all_bad = ISC_FALSE;
2303         }
2304
2305         return (all_bad);
2306 }
2307
2308 static void
2309 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
2310         badnstype_t badtype)
2311 {
2312         char namebuf[DNS_NAME_FORMATSIZE];
2313         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2314         char classbuf[64];
2315         char typebuf[64];
2316         char code[64];
2317         isc_buffer_t b;
2318         isc_sockaddr_t *sa;
2319         const char *spc = "";
2320         isc_sockaddr_t *address = &addrinfo->sockaddr;
2321
2322         if (reason == DNS_R_LAME)
2323                 fctx->lamecount++;
2324         else {
2325                 switch (badtype) {
2326                 case badns_unreachable:
2327                         fctx->neterr++;
2328                         break;
2329                 case badns_response:
2330                         fctx->badresp++;
2331                         break;
2332                 case badns_validation:
2333                         break;  /* counted as 'valfail' */
2334                 }
2335         }
2336
2337         if (bad_server(fctx, address)) {
2338                 /*
2339                  * We already know this server is bad.
2340                  */
2341                 return;
2342         }
2343
2344         FCTXTRACE("add_bad");
2345
2346         sa = isc_mem_get(fctx->mctx, sizeof(*sa));
2347         if (sa == NULL)
2348                 return;
2349         *sa = *address;
2350         ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
2351
2352         if (reason == DNS_R_LAME)       /* already logged */
2353                 return;
2354
2355         if (reason == DNS_R_UNEXPECTEDRCODE &&
2356             fctx->rmessage->rcode == dns_rcode_servfail &&
2357             ISFORWARDER(addrinfo))
2358                 return;
2359
2360         if (reason == DNS_R_UNEXPECTEDRCODE) {
2361                 isc_buffer_init(&b, code, sizeof(code) - 1);
2362                 dns_rcode_totext(fctx->rmessage->rcode, &b);
2363                 code[isc_buffer_usedlength(&b)] = '\0';
2364                 spc = " ";
2365         } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
2366                 isc_buffer_init(&b, code, sizeof(code) - 1);
2367                 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
2368                 code[isc_buffer_usedlength(&b)] = '\0';
2369                 spc = " ";
2370         } else {
2371                 code[0] = '\0';
2372         }
2373         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2374         dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
2375         dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
2376         isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
2377         isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2378                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2379                       "error (%s%s%s) resolving '%s/%s/%s': %s",
2380                       dns_result_totext(reason), spc, code,
2381                       namebuf, typebuf, classbuf, addrbuf);
2382 }
2383
2384 /*
2385  * Sort addrinfo list by RTT.
2386  */
2387 static void
2388 sort_adbfind(dns_adbfind_t *find) {
2389         dns_adbaddrinfo_t *best, *curr;
2390         dns_adbaddrinfolist_t sorted;
2391
2392         /* Lame N^2 bubble sort. */
2393         ISC_LIST_INIT(sorted);
2394         while (!ISC_LIST_EMPTY(find->list)) {
2395                 best = ISC_LIST_HEAD(find->list);
2396                 curr = ISC_LIST_NEXT(best, publink);
2397                 while (curr != NULL) {
2398                         if (curr->srtt < best->srtt)
2399                                 best = curr;
2400                         curr = ISC_LIST_NEXT(curr, publink);
2401                 }
2402                 ISC_LIST_UNLINK(find->list, best, publink);
2403                 ISC_LIST_APPEND(sorted, best, publink);
2404         }
2405         find->list = sorted;
2406 }
2407
2408 /*
2409  * Sort a list of finds by server RTT.
2410  */
2411 static void
2412 sort_finds(dns_adbfindlist_t *findlist) {
2413         dns_adbfind_t *best, *curr;
2414         dns_adbfindlist_t sorted;
2415         dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
2416
2417         /* Sort each find's addrinfo list by SRTT. */
2418         for (curr = ISC_LIST_HEAD(*findlist);
2419              curr != NULL;
2420              curr = ISC_LIST_NEXT(curr, publink))
2421                 sort_adbfind(curr);
2422
2423         /* Lame N^2 bubble sort. */
2424         ISC_LIST_INIT(sorted);
2425         while (!ISC_LIST_EMPTY(*findlist)) {
2426                 best = ISC_LIST_HEAD(*findlist);
2427                 bestaddrinfo = ISC_LIST_HEAD(best->list);
2428                 INSIST(bestaddrinfo != NULL);
2429                 curr = ISC_LIST_NEXT(best, publink);
2430                 while (curr != NULL) {
2431                         addrinfo = ISC_LIST_HEAD(curr->list);
2432                         INSIST(addrinfo != NULL);
2433                         if (addrinfo->srtt < bestaddrinfo->srtt) {
2434                                 best = curr;
2435                                 bestaddrinfo = addrinfo;
2436                         }
2437                         curr = ISC_LIST_NEXT(curr, publink);
2438                 }
2439                 ISC_LIST_UNLINK(*findlist, best, publink);
2440                 ISC_LIST_APPEND(sorted, best, publink);
2441         }
2442         *findlist = sorted;
2443 }
2444
2445 static void
2446 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
2447          unsigned int options, unsigned int flags, isc_stdtime_t now,
2448          isc_boolean_t *need_alternate)
2449 {
2450         dns_adbaddrinfo_t *ai;
2451         dns_adbfind_t *find;
2452         dns_resolver_t *res;
2453         isc_boolean_t unshared;
2454         isc_result_t result;
2455
2456         res = fctx->res;
2457         unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
2458         /*
2459          * If this name is a subdomain of the query domain, tell
2460          * the ADB to start looking using zone/hint data. This keeps us
2461          * from getting stuck if the nameserver is beneath the zone cut
2462          * and we don't know its address (e.g. because the A record has
2463          * expired).
2464          */
2465         if (dns_name_issubdomain(name, &fctx->domain))
2466                 options |= DNS_ADBFIND_STARTATZONE;
2467         options |= DNS_ADBFIND_GLUEOK;
2468         options |= DNS_ADBFIND_HINTOK;
2469
2470         /*
2471          * See what we know about this address.
2472          */
2473         find = NULL;
2474         result = dns_adb_createfind(fctx->adb,
2475                                     res->buckets[fctx->bucketnum].task,
2476                                     fctx_finddone, fctx, name,
2477                                     &fctx->name, fctx->type,
2478                                     options, now, NULL,
2479                                     res->view->dstport, &find);
2480         if (result != ISC_R_SUCCESS) {
2481                 if (result == DNS_R_ALIAS) {
2482                         /*
2483                          * XXXRTH  Follow the CNAME/DNAME chain?
2484                          */
2485                         dns_adb_destroyfind(&find);
2486                         fctx->adberr++;
2487                 }
2488         } else if (!ISC_LIST_EMPTY(find->list)) {
2489                 /*
2490                  * We have at least some of the addresses for the
2491                  * name.
2492                  */
2493                 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
2494                 if (flags != 0 || port != 0) {
2495                         for (ai = ISC_LIST_HEAD(find->list);
2496                              ai != NULL;
2497                              ai = ISC_LIST_NEXT(ai, publink)) {
2498                                 ai->flags |= flags;
2499                                 if (port != 0)
2500                                         isc_sockaddr_setport(&ai->sockaddr,
2501                                                              port);
2502                         }
2503                 }
2504                 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
2505                         ISC_LIST_APPEND(fctx->altfinds, find, publink);
2506                 else
2507                         ISC_LIST_APPEND(fctx->finds, find, publink);
2508         } else {
2509                 /*
2510                  * We don't know any of the addresses for this
2511                  * name.
2512                  */
2513                 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
2514                         /*
2515                          * We're looking for them and will get an
2516                          * event about it later.
2517                          */
2518                         fctx->pending++;
2519                         /*
2520                          * Bootstrap.
2521                          */
2522                         if (need_alternate != NULL &&
2523                             !*need_alternate && unshared &&
2524                             ((res->dispatchv4 == NULL &&
2525                               find->result_v6 != DNS_R_NXDOMAIN) ||
2526                              (res->dispatchv6 == NULL &&
2527                               find->result_v4 != DNS_R_NXDOMAIN)))
2528                                 *need_alternate = ISC_TRUE;
2529                 } else {
2530                         if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
2531                                 fctx->lamecount++; /* cached lame server */
2532                         else
2533                                 fctx->adberr++; /* unreachable server, etc. */
2534
2535                         /*
2536                          * If we know there are no addresses for
2537                          * the family we are using then try to add
2538                          * an alternative server.
2539                          */
2540                         if (need_alternate != NULL && !*need_alternate &&
2541                             ((res->dispatchv4 == NULL &&
2542                               find->result_v6 == DNS_R_NXRRSET) ||
2543                              (res->dispatchv6 == NULL &&
2544                               find->result_v4 == DNS_R_NXRRSET)))
2545                                 *need_alternate = ISC_TRUE;
2546                         dns_adb_destroyfind(&find);
2547                 }
2548         }
2549 }
2550
2551 static isc_boolean_t
2552 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
2553         int order;
2554         unsigned int nlabels;
2555         dns_namereln_t namereln;
2556
2557         namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
2558         return (ISC_TF(namereln == dns_namereln_subdomain));
2559 }
2560
2561 static isc_result_t
2562 fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
2563         dns_rdata_t rdata = DNS_RDATA_INIT;
2564         isc_result_t result;
2565         dns_resolver_t *res;
2566         isc_stdtime_t now;
2567         unsigned int stdoptions = 0;
2568         isc_sockaddr_t *sa;
2569         dns_adbaddrinfo_t *ai;
2570         isc_boolean_t all_bad;
2571         dns_rdata_ns_t ns;
2572         isc_boolean_t need_alternate = ISC_FALSE;
2573
2574         FCTXTRACE("getaddresses");
2575
2576         /*
2577          * Don't pound on remote servers.  (Failsafe!)
2578          */
2579         fctx->restarts++;
2580         if (fctx->restarts > 10) {
2581                 FCTXTRACE("too many restarts");
2582                 return (DNS_R_SERVFAIL);
2583         }
2584
2585         res = fctx->res;
2586
2587         /*
2588          * Forwarders.
2589          */
2590
2591         INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
2592         INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
2593
2594         /*
2595          * If this fctx has forwarders, use them; otherwise use any
2596          * selective forwarders specified in the view; otherwise use the
2597          * resolver's forwarders (if any).
2598          */
2599         sa = ISC_LIST_HEAD(fctx->forwarders);
2600         if (sa == NULL) {
2601                 dns_forwarders_t *forwarders = NULL;
2602                 dns_name_t *name = &fctx->name;
2603                 dns_name_t suffix;
2604                 unsigned int labels;
2605                 dns_fixedname_t fixed;
2606                 dns_name_t *domain;
2607
2608                 /*
2609                  * DS records are found in the parent server.
2610                  * Strip label to get the correct forwarder (if any).
2611                  */
2612                 if (dns_rdatatype_atparent(fctx->type) &&
2613                     dns_name_countlabels(name) > 1) {
2614                         dns_name_init(&suffix, NULL);
2615                         labels = dns_name_countlabels(name);
2616                         dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2617                         name = &suffix;
2618                 }
2619
2620                 dns_fixedname_init(&fixed);
2621                 domain = dns_fixedname_name(&fixed);
2622                 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
2623                                             domain, &forwarders);
2624                 if (result == ISC_R_SUCCESS) {
2625                         sa = ISC_LIST_HEAD(forwarders->addrs);
2626                         fctx->fwdpolicy = forwarders->fwdpolicy;
2627                         if (fctx->fwdpolicy == dns_fwdpolicy_only &&
2628                             isstrictsubdomain(domain, &fctx->domain)) {
2629                                 dns_name_free(&fctx->domain, fctx->mctx);
2630                                 dns_name_init(&fctx->domain, NULL);
2631                                 result = dns_name_dup(domain, fctx->mctx,
2632                                                       &fctx->domain);
2633                                 if (result != ISC_R_SUCCESS)
2634                                         return (result);
2635                         }
2636                 }
2637         }
2638
2639         while (sa != NULL) {
2640                 if ((isc_sockaddr_pf(sa) == AF_INET &&
2641                          fctx->res->dispatchv4 == NULL) ||
2642                     (isc_sockaddr_pf(sa) == AF_INET6 &&
2643                         fctx->res->dispatchv6 == NULL)) {
2644                                 sa = ISC_LIST_NEXT(sa, link);
2645                                 continue;
2646                 }
2647                 ai = NULL;
2648                 result = dns_adb_findaddrinfo(fctx->adb,
2649                                               sa, &ai, 0);  /* XXXMLG */
2650                 if (result == ISC_R_SUCCESS) {
2651                         dns_adbaddrinfo_t *cur;
2652                         ai->flags |= FCTX_ADDRINFO_FORWARDER;
2653                         cur = ISC_LIST_HEAD(fctx->forwaddrs);
2654                         while (cur != NULL && cur->srtt < ai->srtt)
2655                                 cur = ISC_LIST_NEXT(cur, publink);
2656                         if (cur != NULL)
2657                                 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
2658                                                       ai, publink);
2659                         else
2660                                 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
2661                 }
2662                 sa = ISC_LIST_NEXT(sa, link);
2663         }
2664
2665         /*
2666          * If the forwarding policy is "only", we don't need the addresses
2667          * of the nameservers.
2668          */
2669         if (fctx->fwdpolicy == dns_fwdpolicy_only)
2670                 goto out;
2671
2672         /*
2673          * Normal nameservers.
2674          */
2675
2676         stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
2677         if (fctx->restarts == 1) {
2678                 /*
2679                  * To avoid sending out a flood of queries likely to
2680                  * result in NXRRSET, we suppress fetches for address
2681                  * families we don't have the first time through,
2682                  * provided that we have addresses in some family we
2683                  * can use.
2684                  *
2685                  * We don't want to set this option all the time, since
2686                  * if fctx->restarts > 1, we've clearly been having trouble
2687                  * with the addresses we had, so getting more could help.
2688                  */
2689                 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
2690         }
2691         if (res->dispatchv4 != NULL)
2692                 stdoptions |= DNS_ADBFIND_INET;
2693         if (res->dispatchv6 != NULL)
2694                 stdoptions |= DNS_ADBFIND_INET6;
2695         isc_stdtime_get(&now);
2696
2697         INSIST(ISC_LIST_EMPTY(fctx->finds));
2698         INSIST(ISC_LIST_EMPTY(fctx->altfinds));
2699
2700         for (result = dns_rdataset_first(&fctx->nameservers);
2701              result == ISC_R_SUCCESS;
2702              result = dns_rdataset_next(&fctx->nameservers))
2703         {
2704                 dns_rdataset_current(&fctx->nameservers, &rdata);
2705                 /*
2706                  * Extract the name from the NS record.
2707                  */
2708                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2709                 if (result != ISC_R_SUCCESS)
2710                         continue;
2711
2712                 findname(fctx, &ns.name, 0, stdoptions, 0, now,
2713                          &need_alternate);
2714                 dns_rdata_reset(&rdata);
2715                 dns_rdata_freestruct(&ns);
2716         }
2717         if (result != ISC_R_NOMORE)
2718                 return (result);
2719
2720         /*
2721          * Do we need to use 6 to 4?
2722          */
2723         if (need_alternate) {
2724                 int family;
2725                 alternate_t *a;
2726                 family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
2727                 for (a = ISC_LIST_HEAD(fctx->res->alternates);
2728                      a != NULL;
2729                      a = ISC_LIST_NEXT(a, link)) {
2730                         if (!a->isaddress) {
2731                                 findname(fctx, &a->_u._n.name, a->_u._n.port,
2732                                          stdoptions, FCTX_ADDRINFO_FORWARDER,
2733                                          now, NULL);
2734                                 continue;
2735                         }
2736                         if (isc_sockaddr_pf(&a->_u.addr) != family)
2737                                 continue;
2738                         ai = NULL;
2739                         result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
2740                                                       &ai, 0);
2741                         if (result == ISC_R_SUCCESS) {
2742                                 dns_adbaddrinfo_t *cur;
2743                                 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2744                                 cur = ISC_LIST_HEAD(fctx->altaddrs);
2745                                 while (cur != NULL && cur->srtt < ai->srtt)
2746                                         cur = ISC_LIST_NEXT(cur, publink);
2747                                 if (cur != NULL)
2748                                         ISC_LIST_INSERTBEFORE(fctx->altaddrs,
2749                                                               cur, ai, publink);
2750                                 else
2751                                         ISC_LIST_APPEND(fctx->altaddrs, ai,
2752                                                         publink);
2753                         }
2754                 }
2755         }
2756
2757  out:
2758         /*
2759          * Mark all known bad servers.
2760          */
2761         all_bad = mark_bad(fctx);
2762
2763         /*
2764          * How are we doing?
2765          */
2766         if (all_bad) {
2767                 /*
2768                  * We've got no addresses.
2769                  */
2770                 if (fctx->pending > 0) {
2771                         /*
2772                          * We're fetching the addresses, but don't have any
2773                          * yet.   Tell the caller to wait for an answer.
2774                          */
2775                         result = DNS_R_WAIT;
2776                 } else {
2777                         isc_time_t expire;
2778                         isc_interval_t i;
2779                         /*
2780                          * We've lost completely.  We don't know any
2781                          * addresses, and the ADB has told us it can't get
2782                          * them.
2783                          */
2784                         FCTXTRACE("no addresses");
2785                         isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
2786                         result = isc_time_nowplusinterval(&expire, &i);
2787                         if (badcache &&
2788                             (fctx->type == dns_rdatatype_dnskey ||
2789                              fctx->type == dns_rdatatype_dlv ||
2790                              fctx->type == dns_rdatatype_ds) &&
2791                              result == ISC_R_SUCCESS)
2792                                 dns_resolver_addbadcache(fctx->res,
2793                                                          &fctx->name,
2794                                                          fctx->type, &expire);
2795                         result = ISC_R_FAILURE;
2796                 }
2797         } else {
2798                 /*
2799                  * We've found some addresses.  We might still be looking
2800                  * for more addresses.
2801                  */
2802                 sort_finds(&fctx->finds);
2803                 sort_finds(&fctx->altfinds);
2804                 result = ISC_R_SUCCESS;
2805         }
2806
2807         return (result);
2808 }
2809
2810 static inline void
2811 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
2812 {
2813         isc_netaddr_t na;
2814         char buf[ISC_NETADDR_FORMATSIZE];
2815         isc_sockaddr_t *sa;
2816         isc_boolean_t aborted = ISC_FALSE;
2817         isc_boolean_t bogus;
2818         dns_acl_t *blackhole;
2819         isc_netaddr_t ipaddr;
2820         dns_peer_t *peer = NULL;
2821         dns_resolver_t *res;
2822         const char *msg = NULL;
2823
2824         sa = &addr->sockaddr;
2825
2826         res = fctx->res;
2827         isc_netaddr_fromsockaddr(&ipaddr, sa);
2828         blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
2829         (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
2830
2831         if (blackhole != NULL) {
2832                 int match;
2833
2834                 if (dns_acl_match(&ipaddr, NULL, blackhole,
2835                                   &res->view->aclenv,
2836                                   &match, NULL) == ISC_R_SUCCESS &&
2837                     match > 0)
2838                         aborted = ISC_TRUE;
2839         }
2840
2841         if (peer != NULL &&
2842             dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
2843             bogus)
2844                 aborted = ISC_TRUE;
2845
2846         if (aborted) {
2847                 addr->flags |= FCTX_ADDRINFO_MARK;
2848                 msg = "ignoring blackholed / bogus server: ";
2849         } else if (isc_sockaddr_ismulticast(sa)) {
2850                 addr->flags |= FCTX_ADDRINFO_MARK;
2851                 msg = "ignoring multicast address: ";
2852         } else if (isc_sockaddr_isexperimental(sa)) {
2853                 addr->flags |= FCTX_ADDRINFO_MARK;
2854                 msg = "ignoring experimental address: ";
2855         } else if (sa->type.sa.sa_family != AF_INET6) {
2856                 return;
2857         } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
2858                 addr->flags |= FCTX_ADDRINFO_MARK;
2859                 msg = "ignoring IPv6 mapped IPV4 address: ";
2860         } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
2861                 addr->flags |= FCTX_ADDRINFO_MARK;
2862                 msg = "ignoring IPv6 compatibility IPV4 address: ";
2863         } else
2864                 return;
2865
2866         if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
2867                 return;
2868
2869         isc_netaddr_fromsockaddr(&na, sa);
2870         isc_netaddr_format(&na, buf, sizeof(buf));
2871         FCTXTRACE2(msg, buf);
2872 }
2873
2874 static inline dns_adbaddrinfo_t *
2875 fctx_nextaddress(fetchctx_t *fctx) {
2876         dns_adbfind_t *find, *start;
2877         dns_adbaddrinfo_t *addrinfo;
2878         dns_adbaddrinfo_t *faddrinfo;
2879
2880         /*
2881          * Return the next untried address, if any.
2882          */
2883
2884         /*
2885          * Find the first unmarked forwarder (if any).
2886          */
2887         for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2888              addrinfo != NULL;
2889              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2890                 if (!UNMARKED(addrinfo))
2891                         continue;
2892                 possibly_mark(fctx, addrinfo);
2893                 if (UNMARKED(addrinfo)) {
2894                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
2895                         fctx->find = NULL;
2896                         return (addrinfo);
2897                 }
2898         }
2899
2900         /*
2901          * No forwarders.  Move to the next find.
2902          */
2903
2904         fctx->attributes |= FCTX_ATTR_TRIEDFIND;
2905
2906         find = fctx->find;
2907         if (find == NULL)
2908                 find = ISC_LIST_HEAD(fctx->finds);
2909         else {
2910                 find = ISC_LIST_NEXT(find, publink);
2911                 if (find == NULL)
2912                         find = ISC_LIST_HEAD(fctx->finds);
2913         }
2914
2915         /*
2916          * Find the first unmarked addrinfo.
2917          */
2918         addrinfo = NULL;
2919         if (find != NULL) {
2920                 start = find;
2921                 do {
2922                         for (addrinfo = ISC_LIST_HEAD(find->list);
2923                              addrinfo != NULL;
2924                              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2925                                 if (!UNMARKED(addrinfo))
2926                                         continue;
2927                                 possibly_mark(fctx, addrinfo);
2928                                 if (UNMARKED(addrinfo)) {
2929                                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
2930                                         break;
2931                                 }
2932                         }
2933                         if (addrinfo != NULL)
2934                                 break;
2935                         find = ISC_LIST_NEXT(find, publink);
2936                         if (find == NULL)
2937                                 find = ISC_LIST_HEAD(fctx->finds);
2938                 } while (find != start);
2939         }
2940
2941         fctx->find = find;
2942         if (addrinfo != NULL)
2943                 return (addrinfo);
2944
2945         /*
2946          * No nameservers left.  Try alternates.
2947          */
2948
2949         fctx->attributes |= FCTX_ATTR_TRIEDALT;
2950
2951         find = fctx->altfind;
2952         if (find == NULL)
2953                 find = ISC_LIST_HEAD(fctx->altfinds);
2954         else {
2955                 find = ISC_LIST_NEXT(find, publink);
2956                 if (find == NULL)
2957                         find = ISC_LIST_HEAD(fctx->altfinds);
2958         }
2959
2960         /*
2961          * Find the first unmarked addrinfo.
2962          */
2963         addrinfo = NULL;
2964         if (find != NULL) {
2965                 start = find;
2966                 do {
2967                         for (addrinfo = ISC_LIST_HEAD(find->list);
2968                              addrinfo != NULL;
2969                              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2970                                 if (!UNMARKED(addrinfo))
2971                                         continue;
2972                                 possibly_mark(fctx, addrinfo);
2973                                 if (UNMARKED(addrinfo)) {
2974                                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
2975                                         break;
2976                                 }
2977                         }
2978                         if (addrinfo != NULL)
2979                                 break;
2980                         find = ISC_LIST_NEXT(find, publink);
2981                         if (find == NULL)
2982                                 find = ISC_LIST_HEAD(fctx->altfinds);
2983                 } while (find != start);
2984         }
2985
2986         faddrinfo = addrinfo;
2987
2988         /*
2989          * See if we have a better alternate server by address.
2990          */
2991
2992         for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2993              addrinfo != NULL;
2994              addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2995                 if (!UNMARKED(addrinfo))
2996                         continue;
2997                 possibly_mark(fctx, addrinfo);
2998                 if (UNMARKED(addrinfo) &&
2999                     (faddrinfo == NULL ||
3000                      addrinfo->srtt < faddrinfo->srtt)) {
3001                         if (faddrinfo != NULL)
3002                                 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
3003                         addrinfo->flags |= FCTX_ADDRINFO_MARK;
3004                         break;
3005                 }
3006         }
3007
3008         if (addrinfo == NULL) {
3009                 addrinfo = faddrinfo;
3010                 fctx->altfind = find;
3011         }
3012
3013         return (addrinfo);
3014 }
3015
3016 static void
3017 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
3018         isc_result_t result;
3019         dns_adbaddrinfo_t *addrinfo;
3020
3021         FCTXTRACE("try");
3022
3023         REQUIRE(!ADDRWAIT(fctx));
3024
3025         addrinfo = fctx_nextaddress(fctx);
3026         if (addrinfo == NULL) {
3027                 /*
3028                  * We have no more addresses.  Start over.
3029                  */
3030                 fctx_cancelqueries(fctx, ISC_TRUE);
3031                 fctx_cleanupfinds(fctx);
3032                 fctx_cleanupaltfinds(fctx);
3033                 fctx_cleanupforwaddrs(fctx);
3034                 fctx_cleanupaltaddrs(fctx);
3035                 result = fctx_getaddresses(fctx, badcache);
3036                 if (result == DNS_R_WAIT) {
3037                         /*
3038                          * Sleep waiting for addresses.
3039                          */
3040                         FCTXTRACE("addrwait");
3041                         fctx->attributes |= FCTX_ATTR_ADDRWAIT;
3042                         return;
3043                 } else if (result != ISC_R_SUCCESS) {
3044                         /*
3045                          * Something bad happened.
3046                          */
3047                         fctx_done(fctx, result, __LINE__);
3048                         return;
3049                 }
3050
3051                 addrinfo = fctx_nextaddress(fctx);
3052                 /*
3053                  * While we may have addresses from the ADB, they
3054                  * might be bad ones.  In this case, return SERVFAIL.
3055                  */
3056                 if (addrinfo == NULL) {
3057                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3058                         return;
3059                 }
3060         }
3061
3062         result = fctx_query(fctx, addrinfo, fctx->options);
3063         if (result != ISC_R_SUCCESS)
3064                 fctx_done(fctx, result, __LINE__);
3065         else if (retrying)
3066                 inc_stats(fctx->res, dns_resstatscounter_retry);
3067 }
3068
3069 static isc_boolean_t
3070 fctx_unlink(fetchctx_t *fctx) {
3071         dns_resolver_t *res;
3072         unsigned int bucketnum;
3073
3074         /*
3075          * Caller must be holding the bucket lock.
3076          */
3077
3078         REQUIRE(VALID_FCTX(fctx));
3079         REQUIRE(fctx->state == fetchstate_done ||
3080                 fctx->state == fetchstate_init);
3081         REQUIRE(ISC_LIST_EMPTY(fctx->events));
3082         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3083         REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3084         REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3085         REQUIRE(fctx->pending == 0);
3086         REQUIRE(fctx->references == 0);
3087         REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3088
3089         FCTXTRACE("unlink");
3090
3091         res = fctx->res;
3092         bucketnum = fctx->bucketnum;
3093
3094         ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
3095
3096         LOCK(&res->nlock);
3097         res->nfctx--;
3098         UNLOCK(&res->nlock);
3099
3100         if (res->buckets[bucketnum].exiting &&
3101             ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
3102                 return (ISC_TRUE);
3103
3104         return (ISC_FALSE);
3105 }
3106
3107 static void
3108 fctx_destroy(fetchctx_t *fctx) {
3109         isc_sockaddr_t *sa, *next_sa;
3110
3111         REQUIRE(VALID_FCTX(fctx));
3112         REQUIRE(fctx->state == fetchstate_done ||
3113                 fctx->state == fetchstate_init);
3114         REQUIRE(ISC_LIST_EMPTY(fctx->events));
3115         REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3116         REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3117         REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3118         REQUIRE(fctx->pending == 0);
3119         REQUIRE(fctx->references == 0);
3120         REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3121         REQUIRE(!ISC_LINK_LINKED(fctx, link));
3122
3123         FCTXTRACE("destroy");
3124
3125         /*
3126          * Free bad.
3127          */
3128         for (sa = ISC_LIST_HEAD(fctx->bad);
3129              sa != NULL;
3130              sa = next_sa) {
3131                 next_sa = ISC_LIST_NEXT(sa, link);
3132                 ISC_LIST_UNLINK(fctx->bad, sa, link);
3133                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3134         }
3135
3136         for (sa = ISC_LIST_HEAD(fctx->edns);
3137              sa != NULL;
3138              sa = next_sa) {
3139                 next_sa = ISC_LIST_NEXT(sa, link);
3140                 ISC_LIST_UNLINK(fctx->edns, sa, link);
3141                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3142         }
3143
3144         for (sa = ISC_LIST_HEAD(fctx->edns512);
3145              sa != NULL;
3146              sa = next_sa) {
3147                 next_sa = ISC_LIST_NEXT(sa, link);
3148                 ISC_LIST_UNLINK(fctx->edns512, sa, link);
3149                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3150         }
3151
3152         for (sa = ISC_LIST_HEAD(fctx->bad_edns);
3153              sa != NULL;
3154              sa = next_sa) {
3155                 next_sa = ISC_LIST_NEXT(sa, link);
3156                 ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
3157                 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3158         }
3159
3160         isc_timer_detach(&fctx->timer);
3161         dns_message_destroy(&fctx->rmessage);
3162         dns_message_destroy(&fctx->qmessage);
3163         if (dns_name_countlabels(&fctx->domain) > 0)
3164                 dns_name_free(&fctx->domain, fctx->mctx);
3165         if (dns_rdataset_isassociated(&fctx->nameservers))
3166                 dns_rdataset_disassociate(&fctx->nameservers);
3167         dns_name_free(&fctx->name, fctx->mctx);
3168         dns_db_detach(&fctx->cache);
3169         dns_adb_detach(&fctx->adb);
3170         isc_mem_free(fctx->mctx, fctx->info);
3171         isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
3172 }
3173
3174 /*
3175  * Fetch event handlers.
3176  */
3177
3178 static void
3179 fctx_timeout(isc_task_t *task, isc_event_t *event) {
3180         fetchctx_t *fctx = event->ev_arg;
3181         isc_timerevent_t *tevent = (isc_timerevent_t *)event;
3182         resquery_t *query;
3183
3184         REQUIRE(VALID_FCTX(fctx));
3185
3186         UNUSED(task);
3187
3188         FCTXTRACE("timeout");
3189
3190         inc_stats(fctx->res, dns_resstatscounter_querytimeout);
3191
3192         if (event->ev_type == ISC_TIMEREVENT_LIFE) {
3193                 fctx->reason = NULL;
3194                 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
3195         } else {
3196                 isc_result_t result;
3197
3198                 fctx->timeouts++;
3199                 fctx->timeout = ISC_TRUE;
3200                 /*
3201                  * We could cancel the running queries here, or we could let
3202                  * them keep going.  Since we normally use separate sockets for
3203                  * different queries, we adopt the former approach to reduce
3204                  * the number of open sockets: cancel the oldest query if it
3205                  * expired after the query had started (this is usually the
3206                  * case but is not always so, depending on the task schedule
3207                  * timing).
3208                  */
3209                 query = ISC_LIST_HEAD(fctx->queries);
3210                 if (query != NULL &&
3211                     isc_time_compare(&tevent->due, &query->start) >= 0) {
3212                         fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
3213                 }
3214                 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3215                 /*
3216                  * Our timer has triggered.  Reestablish the fctx lifetime
3217                  * timer.
3218                  */
3219                 result = fctx_starttimer(fctx);
3220                 if (result != ISC_R_SUCCESS)
3221                         fctx_done(fctx, result, __LINE__);
3222                 else
3223                         /*
3224                          * Keep trying.
3225                          */
3226                         fctx_try(fctx, ISC_TRUE, ISC_FALSE);
3227         }
3228
3229         isc_event_free(&event);
3230 }
3231
3232 static void
3233 fctx_shutdown(fetchctx_t *fctx) {
3234         isc_event_t *cevent;
3235
3236         /*
3237          * Start the shutdown process for fctx, if it isn't already underway.
3238          */
3239
3240         FCTXTRACE("shutdown");
3241
3242         /*
3243          * The caller must be holding the appropriate bucket lock.
3244          */
3245
3246         if (fctx->want_shutdown)
3247                 return;
3248
3249         fctx->want_shutdown = ISC_TRUE;
3250
3251         /*
3252          * Unless we're still initializing (in which case the
3253          * control event is still outstanding), we need to post
3254          * the control event to tell the fetch we want it to
3255          * exit.
3256          */
3257         if (fctx->state != fetchstate_init) {
3258                 cevent = &fctx->control_event;
3259                 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
3260                               &cevent);
3261         }
3262 }
3263
3264 static void
3265 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
3266         fetchctx_t *fctx = event->ev_arg;
3267         isc_boolean_t bucket_empty = ISC_FALSE;
3268         dns_resolver_t *res;
3269         unsigned int bucketnum;
3270         dns_validator_t *validator;
3271         isc_boolean_t destroy = ISC_FALSE;
3272
3273         REQUIRE(VALID_FCTX(fctx));
3274
3275         UNUSED(task);
3276
3277         res = fctx->res;
3278         bucketnum = fctx->bucketnum;
3279
3280         FCTXTRACE("doshutdown");
3281
3282         /*
3283          * An fctx that is shutting down is no longer in ADDRWAIT mode.
3284          */
3285         fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3286
3287         /*
3288          * Cancel all pending validators.  Note that this must be done
3289          * without the bucket lock held, since that could cause deadlock.
3290          */
3291         validator = ISC_LIST_HEAD(fctx->validators);
3292         while (validator != NULL) {
3293                 dns_validator_cancel(validator);
3294                 validator = ISC_LIST_NEXT(validator, link);
3295         }
3296
3297         if (fctx->nsfetch != NULL)
3298                 dns_resolver_cancelfetch(fctx->nsfetch);
3299
3300         /*
3301          * Shut down anything that is still running on behalf of this
3302          * fetch.  To avoid deadlock with the ADB, we must do this
3303          * before we lock the bucket lock.
3304          */
3305         fctx_stopeverything(fctx, ISC_FALSE);
3306
3307         LOCK(&res->buckets[bucketnum].lock);
3308
3309         fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3310
3311         INSIST(fctx->state == fetchstate_active ||
3312                fctx->state == fetchstate_done);
3313         INSIST(fctx->want_shutdown);
3314
3315         if (fctx->state != fetchstate_done) {
3316                 fctx->state = fetchstate_done;
3317                 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3318         }
3319
3320         if (fctx->references == 0 && fctx->pending == 0 &&
3321             fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
3322                 bucket_empty = fctx_unlink(fctx);
3323                 destroy = ISC_TRUE;
3324         }
3325
3326         UNLOCK(&res->buckets[bucketnum].lock);
3327
3328         if (destroy) {
3329                 fctx_destroy(fctx);
3330                 if (bucket_empty)
3331                         empty_bucket(res);
3332         }
3333 }
3334
3335 static void
3336 fctx_start(isc_task_t *task, isc_event_t *event) {
3337         fetchctx_t *fctx = event->ev_arg;
3338         isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
3339         dns_resolver_t *res;
3340         unsigned int bucketnum;
3341         isc_boolean_t destroy = ISC_FALSE;
3342
3343         REQUIRE(VALID_FCTX(fctx));
3344
3345         UNUSED(task);
3346
3347         res = fctx->res;
3348         bucketnum = fctx->bucketnum;
3349
3350         FCTXTRACE("start");
3351
3352         LOCK(&res->buckets[bucketnum].lock);
3353
3354         INSIST(fctx->state == fetchstate_init);
3355         if (fctx->want_shutdown) {
3356                 /*
3357                  * We haven't started this fctx yet, and we've been requested
3358                  * to shut it down.
3359                  */
3360                 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3361                 fctx->state = fetchstate_done;
3362                 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3363                 /*
3364                  * Since we haven't started, we INSIST that we have no
3365                  * pending ADB finds and no pending validations.
3366                  */
3367                 INSIST(fctx->pending == 0);
3368                 INSIST(fctx->nqueries == 0);
3369                 INSIST(ISC_LIST_EMPTY(fctx->validators));
3370                 if (fctx->references == 0) {
3371                         /*
3372                          * It's now safe to destroy this fctx.
3373                          */
3374                         bucket_empty = fctx_unlink(fctx);
3375                         destroy = ISC_TRUE;
3376                 }
3377                 done = ISC_TRUE;
3378         } else {
3379                 /*
3380                  * Normal fctx startup.
3381                  */
3382                 fctx->state = fetchstate_active;
3383                 /*
3384                  * Reset the control event for later use in shutting down
3385                  * the fctx.
3386                  */
3387                 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
3388                                DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
3389                                NULL, NULL, NULL);
3390         }
3391
3392         UNLOCK(&res->buckets[bucketnum].lock);
3393
3394         if (!done) {
3395                 isc_result_t result;
3396
3397                 INSIST(!destroy);
3398
3399                 /*
3400                  * All is well.  Start working on the fetch.
3401                  */
3402                 result = fctx_starttimer(fctx);
3403                 if (result != ISC_R_SUCCESS)
3404                         fctx_done(fctx, result, __LINE__);
3405                 else
3406                         fctx_try(fctx, ISC_FALSE, ISC_FALSE);
3407         } else if (destroy) {
3408                         fctx_destroy(fctx);
3409                 if (bucket_empty)
3410                         empty_bucket(res);
3411         }
3412 }
3413
3414 /*
3415  * Fetch Creation, Joining, and Cancelation.
3416  */
3417
3418 static inline isc_result_t
3419 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
3420           dns_messageid_t id, isc_taskaction_t action, void *arg,
3421           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3422           dns_fetch_t *fetch)
3423 {
3424         isc_task_t *clone;
3425         dns_fetchevent_t *event;
3426
3427         FCTXTRACE("join");
3428
3429         /*
3430          * We store the task we're going to send this event to in the
3431          * sender field.  We'll make the fetch the sender when we actually
3432          * send the event.
3433          */
3434         clone = NULL;
3435         isc_task_attach(task, &clone);
3436         event = (dns_fetchevent_t *)
3437                 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
3438                                    action, arg, sizeof(*event));
3439         if (event == NULL) {
3440                 isc_task_detach(&clone);
3441                 return (ISC_R_NOMEMORY);
3442         }
3443         event->result = DNS_R_SERVFAIL;
3444         event->qtype = fctx->type;
3445         event->db = NULL;
3446         event->node = NULL;
3447         event->rdataset = rdataset;
3448         event->sigrdataset = sigrdataset;
3449         event->fetch = fetch;
3450         event->client = client;
3451         event->id = id;
3452         dns_fixedname_init(&event->foundname);
3453
3454         /*
3455          * Make sure that we can store the sigrdataset in the
3456          * first event if it is needed by any of the events.
3457          */
3458         if (event->sigrdataset != NULL)
3459                 ISC_LIST_PREPEND(fctx->events, event, ev_link);
3460         else
3461                 ISC_LIST_APPEND(fctx->events, event, ev_link);
3462         fctx->references++;
3463         fctx->client = client;
3464
3465         fetch->magic = DNS_FETCH_MAGIC;
3466         fetch->private = fctx;
3467
3468         return (ISC_R_SUCCESS);
3469 }
3470
3471 static inline void
3472 log_ns_ttl(fetchctx_t *fctx, const char *where) {
3473         char namebuf[DNS_NAME_FORMATSIZE];
3474         char domainbuf[DNS_NAME_FORMATSIZE];
3475
3476         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3477         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3478         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3479                       DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
3480                       "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
3481                       fctx, where, namebuf, domainbuf,
3482                       fctx->ns_ttl_ok, fctx->ns_ttl);
3483 }
3484
3485 static isc_result_t
3486 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
3487             dns_name_t *domain, dns_rdataset_t *nameservers,
3488             unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
3489 {
3490         fetchctx_t *fctx;
3491         isc_result_t result;
3492         isc_result_t iresult;
3493         isc_interval_t interval;
3494         dns_fixedname_t fixed;
3495         unsigned int findoptions = 0;
3496         char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
3497         char typebuf[DNS_RDATATYPE_FORMATSIZE];
3498         dns_name_t suffix;
3499         isc_mem_t *mctx;
3500
3501         /*
3502          * Caller must be holding the lock for bucket number 'bucketnum'.
3503          */
3504         REQUIRE(fctxp != NULL && *fctxp == NULL);
3505
3506         mctx = res->buckets[bucketnum].mctx;
3507         fctx = isc_mem_get(mctx, sizeof(*fctx));
3508         if (fctx == NULL)
3509                 return (ISC_R_NOMEMORY);
3510         dns_name_format(name, buf, sizeof(buf));
3511         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
3512         strcat(buf, "/");       /* checked */
3513         strcat(buf, typebuf);   /* checked */
3514         fctx->info = isc_mem_strdup(mctx, buf);
3515         if (fctx->info == NULL) {
3516                 result = ISC_R_NOMEMORY;
3517                 goto cleanup_fetch;
3518         }
3519         FCTXTRACE("create");
3520         dns_name_init(&fctx->name, NULL);
3521         result = dns_name_dup(name, mctx, &fctx->name);
3522         if (result != ISC_R_SUCCESS)
3523                 goto cleanup_info;
3524         dns_name_init(&fctx->domain, NULL);
3525         dns_rdataset_init(&fctx->nameservers);
3526
3527         fctx->type = type;
3528         fctx->options = options;
3529         /*
3530          * Note!  We do not attach to the task.  We are relying on the
3531          * resolver to ensure that this task doesn't go away while we are
3532          * using it.
3533          */
3534         fctx->res = res;
3535         fctx->references = 0;
3536         fctx->bucketnum = bucketnum;
3537         fctx->state = fetchstate_init;
3538         fctx->want_shutdown = ISC_FALSE;
3539         fctx->cloned = ISC_FALSE;
3540         ISC_LIST_INIT(fctx->queries);
3541         ISC_LIST_INIT(fctx->finds);
3542         ISC_LIST_INIT(fctx->altfinds);
3543         ISC_LIST_INIT(fctx->forwaddrs);
3544         ISC_LIST_INIT(fctx->altaddrs);
3545         ISC_LIST_INIT(fctx->forwarders);
3546         fctx->fwdpolicy = dns_fwdpolicy_none;
3547         ISC_LIST_INIT(fctx->bad);
3548         ISC_LIST_INIT(fctx->edns);
3549         ISC_LIST_INIT(fctx->edns512);
3550         ISC_LIST_INIT(fctx->bad_edns);
3551         ISC_LIST_INIT(fctx->validators);
3552         fctx->validator = NULL;
3553         fctx->find = NULL;
3554         fctx->altfind = NULL;
3555         fctx->pending = 0;
3556         fctx->restarts = 0;
3557         fctx->querysent = 0;
3558         fctx->referrals = 0;
3559         TIME_NOW(&fctx->start);
3560         fctx->timeouts = 0;
3561         fctx->lamecount = 0;
3562         fctx->adberr = 0;
3563         fctx->neterr = 0;
3564         fctx->badresp = 0;
3565         fctx->findfail = 0;
3566         fctx->valfail = 0;
3567         fctx->result = ISC_R_FAILURE;
3568         fctx->vresult = ISC_R_SUCCESS;
3569         fctx->exitline = -1;    /* sentinel */
3570         fctx->logged = ISC_FALSE;
3571         fctx->attributes = 0;
3572         fctx->spilled = ISC_FALSE;
3573         fctx->nqueries = 0;
3574         fctx->reason = NULL;
3575         fctx->rand_buf = 0;
3576         fctx->rand_bits = 0;
3577         fctx->timeout = ISC_FALSE;
3578         fctx->addrinfo = NULL;
3579         fctx->client = NULL;
3580         fctx->ns_ttl = 0;
3581         fctx->ns_ttl_ok = ISC_FALSE;
3582
3583         dns_name_init(&fctx->nsname, NULL);
3584         fctx->nsfetch = NULL;
3585         dns_rdataset_init(&fctx->nsrrset);
3586
3587         if (domain == NULL) {
3588                 dns_forwarders_t *forwarders = NULL;
3589                 unsigned int labels;
3590                 dns_name_t *fwdname = name;
3591
3592                 /*
3593                  * DS records are found in the parent server.
3594                  * Strip label to get the correct forwarder (if any).
3595                  */
3596                 if (dns_rdatatype_atparent(fctx->type) &&
3597                     dns_name_countlabels(name) > 1) {
3598                         dns_name_init(&suffix, NULL);
3599                         labels = dns_name_countlabels(name);
3600                         dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
3601                         fwdname = &suffix;
3602                 }
3603                 dns_fixedname_init(&fixed);
3604                 domain = dns_fixedname_name(&fixed);
3605                 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
3606                                             domain, &forwarders);
3607                 if (result == ISC_R_SUCCESS)
3608                         fctx->fwdpolicy = forwarders->fwdpolicy;
3609
3610                 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
3611                         /*
3612                          * The caller didn't supply a query domain and
3613                          * nameservers, and we're not in forward-only mode,
3614                          * so find the best nameservers to use.
3615                          */
3616                         if (dns_rdatatype_atparent(fctx->type))
3617                                 findoptions |= DNS_DBFIND_NOEXACT;
3618                         result = dns_view_findzonecut(res->view, name, domain,
3619                                                       0, findoptions, ISC_TRUE,
3620                                                       &fctx->nameservers,
3621                                                       NULL);
3622                         if (result != ISC_R_SUCCESS)
3623                                 goto cleanup_name;
3624                         result = dns_name_dup(domain, mctx, &fctx->domain);
3625                         if (result != ISC_R_SUCCESS) {
3626                                 dns_rdataset_disassociate(&fctx->nameservers);
3627                                 goto cleanup_name;
3628                         }
3629                         fctx->ns_ttl = fctx->nameservers.ttl;
3630                         fctx->ns_ttl_ok = ISC_TRUE;
3631                 } else {
3632                         /*
3633                          * We're in forward-only mode.  Set the query domain.
3634                          */
3635                         result = dns_name_dup(domain, mctx, &fctx->domain);
3636                         if (result != ISC_R_SUCCESS)
3637                                 goto cleanup_name;
3638                 }
3639         } else {
3640                 result = dns_name_dup(domain, mctx, &fctx->domain);
3641                 if (result != ISC_R_SUCCESS)
3642                         goto cleanup_name;
3643                 dns_rdataset_clone(nameservers, &fctx->nameservers);
3644                 fctx->ns_ttl = fctx->nameservers.ttl;
3645                 fctx->ns_ttl_ok = ISC_TRUE;
3646         }
3647
3648         log_ns_ttl(fctx, "fctx_create");
3649
3650         INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
3651
3652         fctx->qmessage = NULL;
3653         result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
3654                                     &fctx->qmessage);
3655
3656         if (result != ISC_R_SUCCESS)
3657                 goto cleanup_domain;
3658
3659         fctx->rmessage = NULL;
3660         result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3661                                     &fctx->rmessage);
3662
3663         if (result != ISC_R_SUCCESS)
3664                 goto cleanup_qmessage;
3665
3666         /*
3667          * Compute an expiration time for the entire fetch.
3668          */
3669         isc_interval_set(&interval, res->query_timeout, 0);
3670         iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
3671         if (iresult != ISC_R_SUCCESS) {
3672                 UNEXPECTED_ERROR(__FILE__, __LINE__,
3673                                  "isc_time_nowplusinterval: %s",
3674                                  isc_result_totext(iresult));
3675                 result = ISC_R_UNEXPECTED;
3676                 goto cleanup_rmessage;
3677         }
3678
3679         /*
3680          * Default retry interval initialization.  We set the interval now
3681          * mostly so it won't be uninitialized.  It will be set to the
3682          * correct value before a query is issued.
3683          */
3684         isc_interval_set(&fctx->interval, 2, 0);
3685
3686         /*
3687          * Create an inactive timer.  It will be made active when the fetch
3688          * is actually started.
3689          */
3690         fctx->timer = NULL;
3691         iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
3692                                    NULL, NULL,
3693                                    res->buckets[bucketnum].task, fctx_timeout,
3694                                    fctx, &fctx->timer);
3695         if (iresult != ISC_R_SUCCESS) {
3696                 UNEXPECTED_ERROR(__FILE__, __LINE__,
3697                                  "isc_timer_create: %s",
3698                                  isc_result_totext(iresult));
3699                 result = ISC_R_UNEXPECTED;
3700                 goto cleanup_rmessage;
3701         }
3702
3703         /*
3704          * Attach to the view's cache and adb.
3705          */
3706         fctx->cache = NULL;
3707         dns_db_attach(res->view->cachedb, &fctx->cache);
3708         fctx->adb = NULL;
3709         dns_adb_attach(res->view->adb, &fctx->adb);
3710         fctx->mctx = NULL;
3711         isc_mem_attach(mctx, &fctx->mctx);
3712
3713         ISC_LIST_INIT(fctx->events);
3714         ISC_LINK_INIT(fctx, link);
3715         fctx->magic = FCTX_MAGIC;
3716
3717         ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
3718
3719         LOCK(&res->nlock);
3720         res->nfctx++;
3721         UNLOCK(&res->nlock);
3722
3723         *fctxp = fctx;
3724
3725         return (ISC_R_SUCCESS);
3726
3727  cleanup_rmessage:
3728         dns_message_destroy(&fctx->rmessage);
3729
3730  cleanup_qmessage:
3731         dns_message_destroy(&fctx->qmessage);
3732
3733  cleanup_domain:
3734         if (dns_name_countlabels(&fctx->domain) > 0)
3735                 dns_name_free(&fctx->domain, mctx);
3736         if (dns_rdataset_isassociated(&fctx->nameservers))
3737                 dns_rdataset_disassociate(&fctx->nameservers);
3738
3739  cleanup_name:
3740         dns_name_free(&fctx->name, mctx);
3741
3742  cleanup_info:
3743         isc_mem_free(mctx, fctx->info);
3744
3745  cleanup_fetch:
3746         isc_mem_put(mctx, fctx, sizeof(*fctx));
3747
3748         return (result);
3749 }
3750
3751 /*
3752  * Handle Responses
3753  */
3754 static inline isc_boolean_t
3755 is_lame(fetchctx_t *fctx) {
3756         dns_message_t *message = fctx->rmessage;
3757         dns_name_t *name;
3758         dns_rdataset_t *rdataset;
3759         isc_result_t result;
3760
3761         if (message->rcode != dns_rcode_noerror &&
3762             message->rcode != dns_rcode_nxdomain)
3763                 return (ISC_FALSE);
3764
3765         if (message->counts[DNS_SECTION_ANSWER] != 0)
3766                 return (ISC_FALSE);
3767
3768         if (message->counts[DNS_SECTION_AUTHORITY] == 0)
3769                 return (ISC_FALSE);
3770
3771         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3772         while (result == ISC_R_SUCCESS) {
3773                 name = NULL;
3774                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3775                 for (rdataset = ISC_LIST_HEAD(name->list);
3776                      rdataset != NULL;
3777                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
3778                         dns_namereln_t namereln;
3779                         int order;
3780                         unsigned int labels;
3781                         if (rdataset->type != dns_rdatatype_ns)
3782                                 continue;
3783                         namereln = dns_name_fullcompare(name, &fctx->domain,
3784                                                         &order, &labels);
3785                         if (namereln == dns_namereln_equal &&
3786                             (message->flags & DNS_MESSAGEFLAG_AA) != 0)
3787                                 return (ISC_FALSE);
3788                         if (namereln == dns_namereln_subdomain)
3789                                 return (ISC_FALSE);
3790                         return (ISC_TRUE);
3791                 }
3792                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
3793         }
3794
3795         return (ISC_FALSE);
3796 }
3797
3798 static inline void
3799 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
3800         char namebuf[DNS_NAME_FORMATSIZE];
3801         char domainbuf[DNS_NAME_FORMATSIZE];
3802         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3803
3804         dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3805         dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3806         isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
3807         isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
3808                       DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
3809                       "lame server resolving '%s' (in '%s'?): %s",
3810                       namebuf, domainbuf, addrbuf);
3811 }
3812
3813 static inline void
3814 log_formerr(fetchctx_t *fctx, const char *format, ...) {
3815         char nsbuf[ISC_SOCKADDR_FORMATSIZE];
3816         char clbuf[ISC_SOCKADDR_FORMATSIZE];
3817         const char *clmsg = "";
3818         char msgbuf[2048];
3819         va_list args;
3820
3821         va_start(args, format);
3822         vsnprintf(msgbuf, sizeof(msgbuf), format, args);
3823         va_end(args);
3824
3825         isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
3826
3827         if (fctx->client != NULL) {
3828                 clmsg = " for client ";
3829                 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
3830         } else {
3831                 clbuf[0] = '\0';
3832         }
3833
3834         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3835                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
3836                       "DNS format error from %s resolving %s%s%s: %s",
3837                       nsbuf, fctx->info, clmsg, clbuf, msgbuf);
3838 }
3839
3840 static inline isc_result_t
3841 same_question(fetchctx_t *fctx) {
3842         isc_result_t result;
3843         dns_message_t *message = fctx->rmessage;
3844         dns_name_t *name;
3845         dns_rdataset_t *rdataset;
3846
3847         /*
3848          * Caller must be holding the fctx lock.
3849          */
3850
3851         /*
3852          * XXXRTH  Currently we support only one question.
3853          */
3854         if (message->counts[DNS_SECTION_QUESTION] != 1) {
3855                 log_formerr(fctx, "too many questions");
3856                 return (DNS_R_FORMERR);
3857         }
3858
3859         result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3860         if (result != ISC_R_SUCCESS)
3861                 return (result);
3862         name = NULL;
3863         dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
3864         rdataset = ISC_LIST_HEAD(name->list);
3865         INSIST(rdataset != NULL);
3866         INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
3867
3868         if (fctx->type != rdataset->type ||
3869             fctx->res->rdclass != rdataset->rdclass ||
3870             !dns_name_equal(&fctx->name, name)) {
3871                 char namebuf[DNS_NAME_FORMATSIZE];
3872                 char class[DNS_RDATACLASS_FORMATSIZE];
3873                 char type[DNS_RDATATYPE_FORMATSIZE];
3874
3875                 dns_name_format(name, namebuf, sizeof(namebuf));
3876                 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
3877                 dns_rdatatype_format(rdataset->type, type, sizeof(type));
3878                 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
3879                             namebuf, class, type);
3880                 return (DNS_R_FORMERR);
3881         }
3882
3883         return (ISC_R_SUCCESS);
3884 }
3885
3886 static void
3887 clone_results(fetchctx_t *fctx) {
3888         dns_fetchevent_t *event, *hevent;
3889         isc_result_t result;
3890         dns_name_t *name, *hname;
3891
3892         FCTXTRACE("clone_results");
3893
3894         /*
3895          * Set up any other events to have the same data as the first
3896          * event.
3897          *
3898          * Caller must be holding the appropriate lock.
3899          */
3900
3901         fctx->cloned = ISC_TRUE;
3902         hevent = ISC_LIST_HEAD(fctx->events);
3903         if (hevent == NULL)
3904                 return;
3905         hname = dns_fixedname_name(&hevent->foundname);
3906         for (event = ISC_LIST_NEXT(hevent, ev_link);
3907              event != NULL;
3908              event = ISC_LIST_NEXT(event, ev_link)) {
3909                 name = dns_fixedname_name(&event->foundname);
3910                 result = dns_name_copy(hname, name, NULL);
3911                 if (result != ISC_R_SUCCESS)
3912                         event->result = result;
3913                 else
3914                         event->result = hevent->result;
3915                 dns_db_attach(hevent->db, &event->db);
3916                 dns_db_attachnode(hevent->db, hevent->node, &event->node);
3917                 INSIST(hevent->rdataset != NULL);
3918                 INSIST(event->rdataset != NULL);
3919                 if (dns_rdataset_isassociated(hevent->rdataset))
3920                         dns_rdataset_clone(hevent->rdataset, event->rdataset);
3921                 INSIST(! (hevent->sigrdataset == NULL &&
3922                           event->sigrdataset != NULL));
3923                 if (hevent->sigrdataset != NULL &&
3924                     dns_rdataset_isassociated(hevent->sigrdataset) &&
3925                     event->sigrdataset != NULL)
3926                         dns_rdataset_clone(hevent->sigrdataset,
3927                                            event->sigrdataset);
3928         }
3929 }
3930
3931 #define CACHE(r)        (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3932 #define ANSWER(r)       (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3933 #define ANSWERSIG(r)    (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3934 #define EXTERNAL(r)     (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3935 #define CHAINING(r)     (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3936 #define CHASE(r)        (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3937 #define CHECKNAMES(r)   (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3938
3939
3940 /*
3941  * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3942  * no references and is no longer waiting for any events).
3943  *
3944  * Requires:
3945  *      '*fctx' is shutting down.
3946  *
3947  * Returns:
3948  *      true if the resolver is exiting and this is the last fctx in the bucket.
3949  */
3950 static isc_boolean_t
3951 maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
3952         unsigned int bucketnum;
3953         isc_boolean_t bucket_empty = ISC_FALSE;
3954         dns_resolver_t *res = fctx->res;
3955         dns_validator_t *validator, *next_validator;
3956         isc_boolean_t destroy = ISC_FALSE;
3957
3958         REQUIRE(SHUTTINGDOWN(fctx));
3959
3960         bucketnum = fctx->bucketnum;
3961         if (!locked)
3962                 LOCK(&res->buckets[bucketnum].lock);
3963         if (fctx->pending != 0 || fctx->nqueries != 0)
3964                 goto unlock;
3965
3966         for (validator = ISC_LIST_HEAD(fctx->validators);
3967              validator != NULL; validator = next_validator) {
3968                 next_validator = ISC_LIST_NEXT(validator, link);
3969                 dns_validator_cancel(validator);
3970         }
3971
3972         if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
3973                 bucket_empty = fctx_unlink(fctx);
3974                 destroy = ISC_TRUE;
3975         }
3976  unlock:
3977         if (!locked)
3978                 UNLOCK(&res->buckets[bucketnum].lock);
3979         if (destroy)
3980                 fctx_destroy(fctx);
3981         return (bucket_empty);
3982 }
3983
3984 /*
3985  * The validator has finished.
3986  */
3987 static void
3988 validated(isc_task_t *task, isc_event_t *event) {
3989         dns_adbaddrinfo_t *addrinfo;
3990         dns_dbnode_t *node = NULL;
3991         dns_dbnode_t *nsnode = NULL;
3992         dns_fetchevent_t *hevent;
3993         dns_name_t *name;
3994         dns_rdataset_t *ardataset = NULL;
3995         dns_rdataset_t *asigrdataset = NULL;
3996         dns_rdataset_t *rdataset;
3997         dns_rdataset_t *sigrdataset;
3998         dns_resolver_t *res;
3999         dns_valarg_t *valarg;
4000         dns_validatorevent_t *vevent;
4001         fetchctx_t *fctx;
4002         isc_boolean_t chaining;
4003         isc_boolean_t negative;
4004         isc_boolean_t sentresponse;
4005         isc_result_t eresult = ISC_R_SUCCESS;
4006         isc_result_t result = ISC_R_SUCCESS;
4007         isc_stdtime_t now;
4008         isc_uint32_t ttl;
4009
4010         UNUSED(task); /* for now */
4011
4012         REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
4013         valarg = event->ev_arg;
4014         fctx = valarg->fctx;
4015         res = fctx->res;
4016         addrinfo = valarg->addrinfo;
4017         REQUIRE(VALID_FCTX(fctx));
4018         REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
4019
4020         vevent = (dns_validatorevent_t *)event;
4021         fctx->vresult = vevent->result;
4022
4023         FCTXTRACE("received validation completion event");
4024
4025         LOCK(&res->buckets[fctx->bucketnum].lock);
4026
4027         ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
4028         fctx->validator = NULL;
4029
4030         /*
4031          * Destroy the validator early so that we can
4032          * destroy the fctx if necessary.
4033          */
4034         dns_validator_destroy(&vevent->validator);
4035         isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
4036
4037         negative = ISC_TF(vevent->rdataset == NULL);
4038
4039         sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
4040
4041         /*
4042          * If shutting down, ignore the results.  Check to see if we're
4043          * done waiting for validator completions and ADB pending events; if
4044          * so, destroy the fctx.
4045          */
4046         if (SHUTTINGDOWN(fctx) && !sentresponse) {
4047                 isc_uint32_t bucketnum = fctx->bucketnum;
4048                 isc_boolean_t bucket_empty;
4049                 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4050                 UNLOCK(&res->buckets[bucketnum].lock);
4051                 if (bucket_empty)
4052                         empty_bucket(res);
4053                 goto cleanup_event;
4054         }
4055
4056         isc_stdtime_get(&now);
4057
4058         /*
4059          * If chaining, we need to make sure that the right result code is
4060          * returned, and that the rdatasets are bound.
4061          */
4062         if (vevent->result == ISC_R_SUCCESS &&
4063             !negative &&
4064             vevent->rdataset != NULL &&
4065             CHAINING(vevent->rdataset))
4066         {
4067                 if (vevent->rdataset->type == dns_rdatatype_cname)
4068                         eresult = DNS_R_CNAME;
4069                 else {
4070                         INSIST(vevent->rdataset->type == dns_rdatatype_dname);
4071                         eresult = DNS_R_DNAME;
4072                 }
4073                 chaining = ISC_TRUE;
4074         } else
4075                 chaining = ISC_FALSE;
4076
4077         /*
4078          * Either we're not shutting down, or we are shutting down but want
4079          * to cache the result anyway (if this was a validation started by
4080          * a query with cd set)
4081          */
4082
4083         hevent = ISC_LIST_HEAD(fctx->events);
4084         if (hevent != NULL) {
4085                 if (!negative && !chaining &&
4086                     (fctx->type == dns_rdatatype_any ||
4087                      fctx->type == dns_rdatatype_rrsig ||
4088                      fctx->type == dns_rdatatype_sig)) {
4089                         /*
4090                          * Don't bind rdatasets; the caller
4091                          * will iterate the node.
4092                          */
4093                 } else {
4094                         ardataset = hevent->rdataset;
4095                         asigrdataset = hevent->sigrdataset;
4096                 }
4097         }
4098
4099         if (vevent->result != ISC_R_SUCCESS) {
4100                 FCTXTRACE("validation failed");
4101                 inc_stats(res, dns_resstatscounter_valfail);
4102                 fctx->valfail++;
4103                 fctx->vresult = vevent->result;
4104                 if (fctx->vresult != DNS_R_BROKENCHAIN) {
4105                         result = ISC_R_NOTFOUND;
4106                         if (vevent->rdataset != NULL)
4107                                 result = dns_db_findnode(fctx->cache,
4108                                                          vevent->name,
4109                                                          ISC_TRUE, &node);
4110                         if (result == ISC_R_SUCCESS)
4111                                 (void)dns_db_deleterdataset(fctx->cache, node,
4112                                                              NULL,
4113                                                             vevent->type, 0);
4114                         if (result == ISC_R_SUCCESS &&
4115                              vevent->sigrdataset != NULL)
4116                                 (void)dns_db_deleterdataset(fctx->cache, node,
4117                                                             NULL,
4118                                                             dns_rdatatype_rrsig,
4119                                                             vevent->type);
4120                         if (result == ISC_R_SUCCESS)
4121                                 dns_db_detachnode(fctx->cache, &node);
4122                 }
4123                 if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
4124                         /*
4125                          * Cache the data as pending for later validation.
4126                          */
4127                         result = ISC_R_NOTFOUND;
4128                         if (vevent->rdataset != NULL)
4129                                 result = dns_db_findnode(fctx->cache,
4130                                                          vevent->name,
4131                                                          ISC_TRUE, &node);
4132                         if (result == ISC_R_SUCCESS) {
4133                                 (void)dns_db_addrdataset(fctx->cache, node,
4134                                                          NULL, now,
4135                                                          vevent->rdataset, 0,
4136                                                          NULL);
4137                         }
4138                         if (result == ISC_R_SUCCESS &&
4139                             vevent->sigrdataset != NULL)
4140                                 (void)dns_db_addrdataset(fctx->cache, node,
4141                                                          NULL, now,
4142                                                          vevent->sigrdataset,
4143                                                          0, NULL);
4144                         if (result == ISC_R_SUCCESS)
4145                                 dns_db_detachnode(fctx->cache, &node);
4146                 }
4147                 result = fctx->vresult;
4148                 add_bad(fctx, addrinfo, result, badns_validation);
4149                 isc_event_free(&event);
4150                 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4151                 INSIST(fctx->validator == NULL);
4152                 fctx->validator = ISC_LIST_HEAD(fctx->validators);
4153                 if (fctx->validator != NULL)
4154                         dns_validator_send(fctx->validator);
4155                 else if (sentresponse)
4156                         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4157                 else if (result == DNS_R_BROKENCHAIN) {
4158                         isc_result_t tresult;
4159                         isc_time_t expire;
4160                         isc_interval_t i;
4161
4162                         isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
4163                         tresult = isc_time_nowplusinterval(&expire, &i);
4164                         if (negative &&
4165                             (fctx->type == dns_rdatatype_dnskey ||
4166                              fctx->type == dns_rdatatype_dlv ||
4167                              fctx->type == dns_rdatatype_ds) &&
4168                              tresult == ISC_R_SUCCESS)
4169                                 dns_resolver_addbadcache(res, &fctx->name,
4170                                                          fctx->type, &expire);
4171                         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4172                 } else
4173                         fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
4174                 return;
4175         }
4176
4177
4178         if (negative) {
4179                 dns_rdatatype_t covers;
4180                 FCTXTRACE("nonexistence validation OK");
4181
4182                 inc_stats(res, dns_resstatscounter_valnegsuccess);
4183
4184                 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
4185                         covers = dns_rdatatype_any;
4186                 else
4187                         covers = fctx->type;
4188
4189                 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
4190                                          &node);
4191                 if (result != ISC_R_SUCCESS)
4192                         goto noanswer_response;
4193
4194                 /*
4195                  * If we are asking for a SOA record set the cache time
4196                  * to zero to facilitate locating the containing zone of
4197                  * a arbitrary zone.
4198                  */
4199                 ttl = res->view->maxncachettl;
4200                 if (fctx->type == dns_rdatatype_soa &&
4201                     covers == dns_rdatatype_any && res->zero_no_soa_ttl)
4202                         ttl = 0;
4203
4204                 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4205                                            covers, now, ttl, vevent->optout,
4206                                            ardataset, &eresult);
4207                 if (result != ISC_R_SUCCESS)
4208                         goto noanswer_response;
4209                 goto answer_response;
4210         } else
4211                 inc_stats(res, dns_resstatscounter_valsuccess);
4212
4213         FCTXTRACE("validation OK");
4214
4215         if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
4216
4217                 result = dns_rdataset_addnoqname(vevent->rdataset,
4218                                    vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
4219                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4220                 INSIST(vevent->sigrdataset != NULL);
4221                 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
4222                 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
4223                         result = dns_rdataset_addclosest(vevent->rdataset,
4224                                  vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
4225                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4226                 }
4227         }
4228
4229         /*
4230          * The data was already cached as pending data.
4231          * Re-cache it as secure and bind the cached
4232          * rdatasets to the first event on the fetch
4233          * event list.
4234          */
4235         result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
4236         if (result != ISC_R_SUCCESS)
4237                 goto noanswer_response;
4238
4239         result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4240                                     vevent->rdataset, 0, ardataset);
4241         if (result != ISC_R_SUCCESS &&
4242             result != DNS_R_UNCHANGED)
4243                 goto noanswer_response;
4244         if (ardataset != NULL && NEGATIVE(ardataset)) {
4245                 if (NXDOMAIN(ardataset))
4246                         eresult = DNS_R_NCACHENXDOMAIN;
4247                 else
4248                         eresult = DNS_R_NCACHENXRRSET;
4249         } else if (vevent->sigrdataset != NULL) {
4250                 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4251                                             vevent->sigrdataset, 0,
4252                                             asigrdataset);
4253                 if (result != ISC_R_SUCCESS &&
4254                     result != DNS_R_UNCHANGED)
4255                         goto noanswer_response;
4256         }
4257
4258         if (sentresponse) {
4259                 isc_boolean_t bucket_empty = ISC_FALSE;
4260                 /*
4261                  * If we only deferred the destroy because we wanted to cache
4262                  * the data, destroy now.
4263                  */
4264                 dns_db_detachnode(fctx->cache, &node);
4265                 if (SHUTTINGDOWN(fctx))
4266                         bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4267                 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4268                 if (bucket_empty)
4269                         empty_bucket(res);
4270                 goto cleanup_event;
4271         }
4272
4273         if (!ISC_LIST_EMPTY(fctx->validators)) {
4274                 INSIST(!negative);
4275                 INSIST(fctx->type == dns_rdatatype_any ||
4276                        fctx->type == dns_rdatatype_rrsig ||
4277                        fctx->type == dns_rdatatype_sig);
4278                 /*
4279                  * Don't send a response yet - we have
4280                  * more rdatasets that still need to
4281                  * be validated.
4282                  */
4283                 dns_db_detachnode(fctx->cache, &node);
4284                 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4285                 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
4286                 goto cleanup_event;
4287         }
4288
4289  answer_response:
4290         /*
4291          * Cache any NS/NSEC records that happened to be validated.
4292          */
4293         result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
4294         while (result == ISC_R_SUCCESS) {
4295                 name = NULL;
4296                 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
4297                                         &name);
4298                 for (rdataset = ISC_LIST_HEAD(name->list);
4299                      rdataset != NULL;
4300                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
4301                         if ((rdataset->type != dns_rdatatype_ns &&
4302                              rdataset->type != dns_rdatatype_nsec) ||
4303                             rdataset->trust != dns_trust_secure)
4304                                 continue;
4305                         for (sigrdataset = ISC_LIST_HEAD(name->list);
4306                              sigrdataset != NULL;
4307                              sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4308                                 if (sigrdataset->type != dns_rdatatype_rrsig ||
4309                                     sigrdataset->covers != rdataset->type)
4310                                         continue;
4311                                 break;
4312                         }
4313                         if (sigrdataset == NULL ||
4314                             sigrdataset->trust != dns_trust_secure)
4315                                 continue;
4316                         result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
4317                                                  &nsnode);
4318                         if (result != ISC_R_SUCCESS)
4319                                 continue;
4320
4321                         result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
4322                                                     now, rdataset, 0, NULL);
4323                         if (result == ISC_R_SUCCESS)
4324                                 result = dns_db_addrdataset(fctx->cache, nsnode,
4325                                                             NULL, now,
4326                                                             sigrdataset, 0,
4327                                                             NULL);
4328                         dns_db_detachnode(fctx->cache, &nsnode);
4329                         if (result != ISC_R_SUCCESS)
4330                                 continue;
4331                 }
4332                 result = dns_message_nextname(fctx->rmessage,
4333                                               DNS_SECTION_AUTHORITY);
4334         }
4335
4336         result = ISC_R_SUCCESS;
4337
4338         /*
4339          * Respond with an answer, positive or negative,
4340          * as opposed to an error.  'node' must be non-NULL.
4341          */
4342
4343         fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4344
4345         if (hevent != NULL) {
4346                 hevent->result = eresult;
4347                 RUNTIME_CHECK(dns_name_copy(vevent->name,
4348                               dns_fixedname_name(&hevent->foundname), NULL)
4349                               == ISC_R_SUCCESS);
4350                 dns_db_attach(fctx->cache, &hevent->db);
4351                 dns_db_transfernode(fctx->cache, &node, &hevent->node);
4352                 clone_results(fctx);
4353         }
4354
4355  noanswer_response:
4356         if (node != NULL)
4357                 dns_db_detachnode(fctx->cache, &node);
4358
4359         UNLOCK(&res->buckets[fctx->bucketnum].lock);
4360         fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4361
4362  cleanup_event:
4363         INSIST(node == NULL);
4364         isc_event_free(&event);
4365 }
4366
4367 static inline isc_result_t
4368 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
4369            isc_stdtime_t now)
4370 {
4371         dns_rdataset_t *rdataset, *sigrdataset;
4372         dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
4373         dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
4374         dns_dbnode_t *node, **anodep;
4375         dns_db_t **adbp;
4376         dns_name_t *aname;
4377         dns_resolver_t *res;
4378         isc_boolean_t need_validation, secure_domain, have_answer;
4379         isc_result_t result, eresult;
4380         dns_fetchevent_t *event;
4381         unsigned int options;
4382         isc_task_t *task;
4383         isc_boolean_t fail;
4384         unsigned int valoptions = 0;
4385
4386         /*
4387          * The appropriate bucket lock must be held.
4388          */
4389
4390         res = fctx->res;
4391         need_validation = ISC_FALSE;
4392         POST(need_validation);
4393         secure_domain = ISC_FALSE;
4394         have_answer = ISC_FALSE;
4395         eresult = ISC_R_SUCCESS;
4396         task = res->buckets[fctx->bucketnum].task;
4397
4398         /*
4399          * Is DNSSEC validation required for this name?
4400          */
4401         if (res->view->enablevalidation) {
4402                 result = dns_view_issecuredomain(res->view, name,
4403                                                  &secure_domain);
4404                 if (result != ISC_R_SUCCESS)
4405                         return (result);
4406
4407                 if (!secure_domain && res->view->dlv != NULL) {
4408                         valoptions = DNS_VALIDATOR_DLV;
4409                         secure_domain = ISC_TRUE;
4410                 }
4411         }
4412
4413         if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4414                 need_validation = ISC_FALSE;
4415         else
4416                 need_validation = secure_domain;
4417
4418         adbp = NULL;
4419         aname = NULL;
4420         anodep = NULL;
4421         ardataset = NULL;
4422         asigrdataset = NULL;
4423         event = NULL;
4424         if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
4425             !need_validation) {
4426                 have_answer = ISC_TRUE;
4427                 event = ISC_LIST_HEAD(fctx->events);
4428                 if (event != NULL) {
4429                         adbp = &event->db;
4430                         aname = dns_fixedname_name(&event->foundname);
4431                         result = dns_name_copy(name, aname, NULL);
4432                         if (result != ISC_R_SUCCESS)
4433                                 return (result);
4434                         anodep = &event->node;
4435                         /*
4436                          * If this is an ANY, SIG or RRSIG query, we're not
4437                          * going to return any rdatasets, unless we encountered
4438                          * a CNAME or DNAME as "the answer".  In this case,
4439                          * we're going to return DNS_R_CNAME or DNS_R_DNAME
4440                          * and we must set up the rdatasets.
4441                          */
4442                         if ((fctx->type != dns_rdatatype_any &&
4443                              fctx->type != dns_rdatatype_rrsig &&
4444                              fctx->type != dns_rdatatype_sig) ||
4445                             (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
4446                                 ardataset = event->rdataset;
4447                                 asigrdataset = event->sigrdataset;
4448                         }
4449                 }
4450         }
4451
4452         /*
4453          * Find or create the cache node.
4454          */
4455         node = NULL;
4456         result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4457         if (result != ISC_R_SUCCESS)
4458                 return (result);
4459
4460         /*
4461          * Cache or validate each cacheable rdataset.
4462          */
4463         fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
4464         for (rdataset = ISC_LIST_HEAD(name->list);
4465              rdataset != NULL;
4466              rdataset = ISC_LIST_NEXT(rdataset, link)) {
4467                 if (!CACHE(rdataset))
4468                         continue;
4469                 if (CHECKNAMES(rdataset)) {
4470                         char namebuf[DNS_NAME_FORMATSIZE];
4471                         char typebuf[DNS_RDATATYPE_FORMATSIZE];
4472                         char classbuf[DNS_RDATATYPE_FORMATSIZE];
4473
4474                         dns_name_format(name, namebuf, sizeof(namebuf));
4475                         dns_rdatatype_format(rdataset->type, typebuf,
4476                                              sizeof(typebuf));
4477                         dns_rdataclass_format(rdataset->rdclass, classbuf,
4478                                               sizeof(classbuf));
4479                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
4480                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
4481                                       "check-names %s %s/%s/%s",
4482                                       fail ? "failure" : "warning",
4483                                       namebuf, typebuf, classbuf);
4484                         if (fail) {
4485                                 if (ANSWER(rdataset)) {
4486                                         dns_db_detachnode(fctx->cache, &node);
4487                                         return (DNS_R_BADNAME);
4488                                 }
4489                                 continue;
4490                         }
4491                 }
4492
4493                 /*
4494                  * Enforce the configure maximum cache TTL.
4495                  */
4496                 if (rdataset->ttl > res->view->maxcachettl)
4497                         rdataset->ttl = res->view->maxcachettl;
4498
4499                 /*
4500                  * If this RRset is in a secure domain, is in bailiwick,
4501                  * and is not glue, attempt DNSSEC validation.  (We do not
4502                  * attempt to validate glue or out-of-bailiwick data--even
4503                  * though there might be some performance benefit to doing
4504                  * so--because it makes it simpler and safer to ensure that
4505                  * records from a secure domain are only cached if validated
4506                  * within the context of a query to the domain that owns
4507                  * them.)
4508                  */
4509                 if (secure_domain && rdataset->trust != dns_trust_glue &&
4510                     !EXTERNAL(rdataset)) {
4511                         dns_trust_t trust;
4512
4513                         /*
4514                          * RRSIGs are validated as part of validating the
4515                          * type they cover.
4516                          */
4517                         if (rdataset->type == dns_rdatatype_rrsig)
4518                                 continue;
4519                         /*
4520                          * Find the SIG for this rdataset, if we have it.
4521                          */
4522                         for (sigrdataset = ISC_LIST_HEAD(name->list);
4523                              sigrdataset != NULL;
4524                              sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4525                                 if (sigrdataset->type == dns_rdatatype_rrsig &&
4526                                     sigrdataset->covers == rdataset->type)
4527                                         break;
4528                         }
4529                         if (sigrdataset == NULL) {
4530                                 if (!ANSWER(rdataset) && need_validation) {
4531                                         /*
4532                                          * Ignore non-answer rdatasets that
4533                                          * are missing signatures.
4534                                          */
4535                                         continue;
4536                                 }
4537                         }
4538
4539                         /*
4540                          * Normalize the rdataset and sigrdataset TTLs.
4541                          */
4542                         if (sigrdataset != NULL) {
4543                                 rdataset->ttl = ISC_MIN(rdataset->ttl,
4544                                                         sigrdataset->ttl);
4545                                 sigrdataset->ttl = rdataset->ttl;
4546                         }
4547
4548                         /*
4549                          * Cache this rdataset/sigrdataset pair as
4550                          * pending data.  Track whether it was additional
4551                          * or not.
4552                          */
4553                         if (rdataset->trust == dns_trust_additional)
4554                                 trust = dns_trust_pending_additional;
4555                         else
4556                                 trust = dns_trust_pending_answer;
4557
4558                         rdataset->trust = trust;
4559                         if (sigrdataset != NULL)
4560                                 sigrdataset->trust = trust;
4561                         if (!need_validation || !ANSWER(rdataset)) {
4562                                 addedrdataset = ardataset;
4563                                 result = dns_db_addrdataset(fctx->cache, node,
4564                                                             NULL, now, rdataset,
4565                                                             0, addedrdataset);
4566                                 if (result == DNS_R_UNCHANGED) {
4567                                         result = ISC_R_SUCCESS;
4568                                         if (!need_validation &&
4569                                             ardataset != NULL &&
4570                                             NEGATIVE(ardataset)) {
4571                                                 /*
4572                                                  * The answer in the cache is
4573                                                  * better than the answer we
4574                                                  * found, and is a negative
4575                                                  * cache entry, so we must set
4576                                                  * eresult appropriately.
4577                                                  */
4578                                                 if (NXDOMAIN(ardataset))
4579                                                         eresult =
4580                                                            DNS_R_NCACHENXDOMAIN;
4581                                                 else
4582                                                         eresult =
4583                                                            DNS_R_NCACHENXRRSET;
4584                                                 /*
4585                                                  * We have a negative response
4586                                                  * from the cache so don't
4587                                                  * attempt to add the RRSIG
4588                                                  * rrset.
4589                                                  */
4590                                                 continue;
4591                                         }
4592                                 }
4593                                 if (result != ISC_R_SUCCESS)
4594                                         break;
4595                                 if (sigrdataset != NULL) {
4596                                         addedrdataset = asigrdataset;
4597                                         result = dns_db_addrdataset(fctx->cache,
4598                                                                 node, NULL, now,
4599                                                                 sigrdataset, 0,
4600                                                                 addedrdataset);
4601                                         if (result == DNS_R_UNCHANGED)
4602                                                 result = ISC_R_SUCCESS;
4603                                         if (result != ISC_R_SUCCESS)
4604                                                 break;
4605                                 } else if (!ANSWER(rdataset))
4606                                         continue;
4607                         }
4608
4609                         if (ANSWER(rdataset) && need_validation) {
4610                                 if (fctx->type != dns_rdatatype_any &&
4611                                     fctx->type != dns_rdatatype_rrsig &&
4612                                     fctx->type != dns_rdatatype_sig) {
4613                                         /*
4614                                          * This is The Answer.  We will
4615                                          * validate it, but first we cache
4616                                          * the rest of the response - it may
4617                                          * contain useful keys.
4618                                          */
4619                                         INSIST(valrdataset == NULL &&
4620                                                valsigrdataset == NULL);
4621                                         valrdataset = rdataset;
4622                                         valsigrdataset = sigrdataset;
4623                                 } else {
4624                                         /*
4625                                          * This is one of (potentially)
4626                                          * multiple answers to an ANY
4627                                          * or SIG query.  To keep things
4628                                          * simple, we just start the
4629                                          * validator right away rather
4630                                          * than caching first and
4631                                          * having to remember which
4632                                          * rdatasets needed validation.
4633                                          */
4634                                         result = valcreate(fctx, addrinfo,
4635                                                            name, rdataset->type,
4636                                                            rdataset,
4637                                                            sigrdataset,
4638                                                            valoptions, task);
4639                                         /*
4640                                          * Defer any further validations.
4641                                          * This prevents multiple validators
4642                                          * from manipulating fctx->rmessage
4643                                          * simultaneously.
4644                                          */
4645                                         valoptions |= DNS_VALIDATOR_DEFER;
4646                                 }
4647                         } else if (CHAINING(rdataset)) {
4648                                 if (rdataset->type == dns_rdatatype_cname)
4649                                         eresult = DNS_R_CNAME;
4650                                 else {
4651                                         INSIST(rdataset->type ==
4652                                                dns_rdatatype_dname);
4653                                         eresult = DNS_R_DNAME;
4654                                 }
4655                         }
4656                 } else if (!EXTERNAL(rdataset)) {
4657                         /*
4658                          * It's OK to cache this rdataset now.
4659                          */
4660                         if (ANSWER(rdataset))
4661                                 addedrdataset = ardataset;
4662                         else if (ANSWERSIG(rdataset))
4663                                 addedrdataset = asigrdataset;
4664                         else
4665                                 addedrdataset = NULL;
4666                         if (CHAINING(rdataset)) {
4667                                 if (rdataset->type == dns_rdatatype_cname)
4668                                         eresult = DNS_R_CNAME;
4669                                 else {
4670                                         INSIST(rdataset->type ==
4671                                                dns_rdatatype_dname);
4672                                         eresult = DNS_R_DNAME;
4673                                 }
4674                         }
4675                         if (rdataset->trust == dns_trust_glue &&
4676                             (rdataset->type == dns_rdatatype_ns ||
4677                              (rdataset->type == dns_rdatatype_rrsig &&
4678                               rdataset->covers == dns_rdatatype_ns))) {
4679                                 /*
4680                                  * If the trust level is 'dns_trust_glue'
4681                                  * then we are adding data from a referral
4682                                  * we got while executing the search algorithm.
4683                                  * New referral data always takes precedence
4684                                  * over the existing cache contents.
4685                                  */
4686                                 options = DNS_DBADD_FORCE;
4687                         } else
4688                                 options = 0;
4689                         /*
4690                          * Now we can add the rdataset.
4691                          */
4692                         result = dns_db_addrdataset(fctx->cache,
4693                                                     node, NULL, now,
4694                                                     rdataset,
4695                                                     options,
4696                                                     addedrdataset);
4697                         if (result == DNS_R_UNCHANGED) {
4698                                 if (ANSWER(rdataset) &&
4699                                     ardataset != NULL &&
4700                                     NEGATIVE(ardataset)) {
4701                                         /*
4702                                          * The answer in the cache is better
4703                                          * than the answer we found, and is
4704                                          * a negative cache entry, so we
4705                                          * must set eresult appropriately.
4706                                          */
4707                                         if (NXDOMAIN(ardataset))
4708                                                 eresult = DNS_R_NCACHENXDOMAIN;
4709                                         else
4710                                                 eresult = DNS_R_NCACHENXRRSET;
4711                                 }
4712                                 result = ISC_R_SUCCESS;
4713                         } else if (result != ISC_R_SUCCESS)
4714                                 break;
4715                 }
4716         }
4717
4718         if (valrdataset != NULL)
4719                 result = valcreate(fctx, addrinfo, name, fctx->type,
4720                                    valrdataset, valsigrdataset, valoptions,
4721                                    task);
4722
4723         if (result == ISC_R_SUCCESS && have_answer) {
4724                 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4725                 if (event != NULL) {
4726                         /*
4727                          * Negative results must be indicated in event->result.
4728                          */
4729                         if (dns_rdataset_isassociated(event->rdataset) &&
4730                             NEGATIVE(event->rdataset)) {
4731                                 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
4732                                        eresult == DNS_R_NCACHENXRRSET);
4733                         }
4734                         event->result = eresult;
4735                         dns_db_attach(fctx->cache, adbp);
4736                         dns_db_transfernode(fctx->cache, &node, anodep);
4737                         clone_results(fctx);
4738                 }
4739         }
4740
4741         if (node != NULL)
4742                 dns_db_detachnode(fctx->cache, &node);
4743
4744         return (result);
4745 }
4746
4747 static inline isc_result_t
4748 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
4749 {
4750         isc_result_t result;
4751         dns_section_t section;
4752         dns_name_t *name;
4753
4754         FCTXTRACE("cache_message");
4755
4756         fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
4757
4758         LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4759
4760         for (section = DNS_SECTION_ANSWER;
4761              section <= DNS_SECTION_ADDITIONAL;
4762              section++) {
4763                 result = dns_message_firstname(fctx->rmessage, section);
4764                 while (result == ISC_R_SUCCESS) {
4765                         name = NULL;
4766                         dns_message_currentname(fctx->rmessage, section,
4767                                                 &name);
4768                         if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
4769                                 result = cache_name(fctx, name, addrinfo, now);
4770                                 if (result != ISC_R_SUCCESS)
4771                                         break;
4772                         }
4773                         result = dns_message_nextname(fctx->rmessage, section);
4774                 }
4775                 if (result != ISC_R_NOMORE)
4776                         break;
4777         }
4778         if (result == ISC_R_NOMORE)
4779                 result = ISC_R_SUCCESS;
4780
4781         UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4782
4783         return (result);
4784 }
4785
4786 /*
4787  * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
4788  */
4789 static isc_result_t
4790 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
4791                   dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
4792                   isc_boolean_t optout, dns_rdataset_t *ardataset,
4793                   isc_result_t *eresultp)
4794 {
4795         isc_result_t result;
4796         dns_rdataset_t rdataset;
4797
4798         if (ardataset == NULL) {
4799                 dns_rdataset_init(&rdataset);
4800                 ardataset = &rdataset;
4801         }
4802         result = dns_ncache_addoptout(message, cache, node, covers, now,
4803                                      maxttl, optout, ardataset);
4804         if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
4805                 /*
4806                  * If the cache now contains a negative entry and we
4807                  * care about whether it is DNS_R_NCACHENXDOMAIN or
4808                  * DNS_R_NCACHENXRRSET then extract it.
4809                  */
4810                 if (NEGATIVE(ardataset)) {
4811                         /*
4812                          * The cache data is a negative cache entry.
4813                          */
4814                         if (NXDOMAIN(ardataset))
4815                                 *eresultp = DNS_R_NCACHENXDOMAIN;
4816                         else
4817                                 *eresultp = DNS_R_NCACHENXRRSET;
4818                 } else {
4819                         /*
4820                          * Either we don't care about the nature of the
4821                          * cache rdataset (because no fetch is interested
4822                          * in the outcome), or the cache rdataset is not
4823                          * a negative cache entry.  Whichever case it is,
4824                          * we can return success.
4825                          *
4826                          * XXXRTH  There's a CNAME/DNAME problem here.
4827                          */
4828                         *eresultp = ISC_R_SUCCESS;
4829                 }
4830                 result = ISC_R_SUCCESS;
4831         }
4832         if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
4833                 dns_rdataset_disassociate(ardataset);
4834
4835         return (result);
4836 }
4837
4838 static inline isc_result_t
4839 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
4840                dns_rdatatype_t covers, isc_stdtime_t now)
4841 {
4842         isc_result_t result, eresult;
4843         dns_name_t *name;
4844         dns_resolver_t *res;
4845         dns_db_t **adbp;
4846         dns_dbnode_t *node, **anodep;
4847         dns_rdataset_t *ardataset;
4848         isc_boolean_t need_validation, secure_domain;
4849         dns_name_t *aname;
4850         dns_fetchevent_t *event;
4851         isc_uint32_t ttl;
4852         unsigned int valoptions = 0;
4853
4854         FCTXTRACE("ncache_message");
4855
4856         fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
4857
4858         res = fctx->res;
4859         need_validation = ISC_FALSE;
4860         POST(need_validation);
4861         secure_domain = ISC_FALSE;
4862         eresult = ISC_R_SUCCESS;
4863         name = &fctx->name;
4864         node = NULL;
4865
4866         /*
4867          * XXXMPA remove when we follow cnames and adjust the setting
4868          * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4869          */
4870         INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
4871
4872         /*
4873          * Is DNSSEC validation required for this name?
4874          */
4875         if (fctx->res->view->enablevalidation) {
4876                 result = dns_view_issecuredomain(res->view, name,
4877                                                  &secure_domain);
4878                 if (result != ISC_R_SUCCESS)
4879                         return (result);
4880
4881                 if (!secure_domain && res->view->dlv != NULL) {
4882                         valoptions = DNS_VALIDATOR_DLV;
4883                         secure_domain = ISC_TRUE;
4884                 }
4885         }
4886
4887         if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4888                 need_validation = ISC_FALSE;
4889         else
4890                 need_validation = secure_domain;
4891
4892         if (secure_domain) {
4893                 /*
4894                  * Mark all rdatasets as pending.
4895                  */
4896                 dns_rdataset_t *trdataset;
4897                 dns_name_t *tname;
4898
4899                 result = dns_message_firstname(fctx->rmessage,
4900                                                DNS_SECTION_AUTHORITY);
4901                 while (result == ISC_R_SUCCESS) {
4902                         tname = NULL;
4903                         dns_message_currentname(fctx->rmessage,
4904                                                 DNS_SECTION_AUTHORITY,
4905                                                 &tname);
4906                         for (trdataset = ISC_LIST_HEAD(tname->list);
4907                              trdataset != NULL;
4908                              trdataset = ISC_LIST_NEXT(trdataset, link))
4909                                 trdataset->trust = dns_trust_pending_answer;
4910                         result = dns_message_nextname(fctx->rmessage,
4911                                                       DNS_SECTION_AUTHORITY);
4912                 }
4913                 if (result != ISC_R_NOMORE)
4914                         return (result);
4915
4916         }
4917
4918         if (need_validation) {
4919                 /*
4920                  * Do negative response validation.
4921                  */
4922                 result = valcreate(fctx, addrinfo, name, fctx->type,
4923                                    NULL, NULL, valoptions,
4924                                    res->buckets[fctx->bucketnum].task);
4925                 /*
4926                  * If validation is necessary, return now.  Otherwise continue
4927                  * to process the message, letting the validation complete
4928                  * in its own good time.
4929                  */
4930                 return (result);
4931         }
4932
4933         LOCK(&res->buckets[fctx->bucketnum].lock);
4934
4935         adbp = NULL;
4936         aname = NULL;
4937         anodep = NULL;
4938         ardataset = NULL;
4939         if (!HAVE_ANSWER(fctx)) {
4940                 event = ISC_LIST_HEAD(fctx->events);
4941                 if (event != NULL) {
4942                         adbp = &event->db;
4943                         aname = dns_fixedname_name(&event->foundname);
4944                         result = dns_name_copy(name, aname, NULL);
4945                         if (result != ISC_R_SUCCESS)
4946                                 goto unlock;
4947                         anodep = &event->node;
4948                         ardataset = event->rdataset;
4949                 }
4950         } else
4951                 event = NULL;
4952
4953         result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4954         if (result != ISC_R_SUCCESS)
4955                 goto unlock;
4956
4957         /*
4958          * If we are asking for a SOA record set the cache time
4959          * to zero to facilitate locating the containing zone of
4960          * a arbitrary zone.
4961          */
4962         ttl = fctx->res->view->maxncachettl;
4963         if (fctx->type == dns_rdatatype_soa &&
4964             covers == dns_rdatatype_any &&
4965             fctx->res->zero_no_soa_ttl)
4966                 ttl = 0;
4967
4968         result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4969                                    covers, now, ttl, ISC_FALSE,
4970                                    ardataset, &eresult);
4971         if (result != ISC_R_SUCCESS)
4972                 goto unlock;
4973
4974         if (!HAVE_ANSWER(fctx)) {
4975                 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4976                 if (event != NULL) {
4977                         event->result = eresult;
4978                         dns_db_attach(fctx->cache, adbp);
4979                         dns_db_transfernode(fctx->cache, &node, anodep);
4980                         clone_results(fctx);
4981                 }
4982         }
4983
4984  unlock:
4985         UNLOCK(&res->buckets[fctx->bucketnum].lock);
4986
4987         if (node != NULL)
4988                 dns_db_detachnode(fctx->cache, &node);
4989
4990         return (result);
4991 }
4992
4993 static inline void
4994 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
4995              isc_boolean_t external, isc_boolean_t gluing)
4996 {
4997         name->attributes |= DNS_NAMEATTR_CACHE;
4998         if (gluing) {
4999                 rdataset->trust = dns_trust_glue;
5000                 /*
5001                  * Glue with 0 TTL causes problems.  We force the TTL to
5002                  * 1 second to prevent this.
5003                  */
5004                 if (rdataset->ttl == 0)
5005                         rdataset->ttl = 1;
5006         } else
5007                 rdataset->trust = dns_trust_additional;
5008         /*
5009          * Avoid infinite loops by only marking new rdatasets.
5010          */
5011         if (!CACHE(rdataset)) {
5012                 name->attributes |= DNS_NAMEATTR_CHASE;
5013                 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
5014         }
5015         rdataset->attributes |= DNS_RDATASETATTR_CACHE;
5016         if (external)
5017                 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
5018 }
5019
5020 static isc_result_t
5021 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
5022               dns_section_t section)
5023 {
5024         fetchctx_t *fctx = arg;
5025         isc_result_t result;
5026         dns_name_t *name;
5027         dns_rdataset_t *rdataset;
5028         isc_boolean_t external;
5029         dns_rdatatype_t rtype;
5030         isc_boolean_t gluing;
5031
5032         REQUIRE(VALID_FCTX(fctx));
5033
5034 #if CHECK_FOR_GLUE_IN_ANSWER
5035         if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
5036                 return (ISC_R_SUCCESS);
5037 #endif
5038
5039         if (GLUING(fctx))
5040                 gluing = ISC_TRUE;
5041         else
5042                 gluing = ISC_FALSE;
5043         name = NULL;
5044         rdataset = NULL;
5045         result = dns_message_findname(fctx->rmessage, section, addname,
5046                                       dns_rdatatype_any, 0, &name, NULL);
5047         if (result == ISC_R_SUCCESS) {
5048                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5049                 if (type == dns_rdatatype_a) {
5050                         for (rdataset = ISC_LIST_HEAD(name->list);
5051                              rdataset != NULL;
5052                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
5053                                 if (rdataset->type == dns_rdatatype_rrsig)
5054                                         rtype = rdataset->covers;
5055                                 else
5056                                         rtype = rdataset->type;
5057                                 if (rtype == dns_rdatatype_a ||
5058                                     rtype == dns_rdatatype_aaaa)
5059                                         mark_related(name, rdataset, external,
5060                                                      gluing);
5061                         }
5062                 } else {
5063                         result = dns_message_findtype(name, type, 0,
5064                                                       &rdataset);
5065                         if (result == ISC_R_SUCCESS) {
5066                                 mark_related(name, rdataset, external, gluing);
5067                                 /*
5068                                  * Do we have its SIG too?
5069                                  */
5070                                 rdataset = NULL;
5071                                 result = dns_message_findtype(name,
5072                                                       dns_rdatatype_rrsig,
5073                                                       type, &rdataset);
5074                                 if (result == ISC_R_SUCCESS)
5075                                         mark_related(name, rdataset, external,
5076                                                      gluing);
5077                         }
5078                 }
5079         }
5080
5081         return (ISC_R_SUCCESS);
5082 }
5083
5084 static isc_result_t
5085 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5086         return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
5087 }
5088
5089 #ifndef CHECK_FOR_GLUE_IN_ANSWER
5090 #define CHECK_FOR_GLUE_IN_ANSWER 0
5091 #endif
5092 #if CHECK_FOR_GLUE_IN_ANSWER
5093 static isc_result_t
5094 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5095         return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
5096 }
5097 #endif
5098
5099 static void
5100 chase_additional(fetchctx_t *fctx) {
5101         isc_boolean_t rescan;
5102         dns_section_t section = DNS_SECTION_ADDITIONAL;
5103         isc_result_t result;
5104
5105  again:
5106         rescan = ISC_FALSE;
5107
5108         for (result = dns_message_firstname(fctx->rmessage, section);
5109              result == ISC_R_SUCCESS;
5110              result = dns_message_nextname(fctx->rmessage, section)) {
5111                 dns_name_t *name = NULL;
5112                 dns_rdataset_t *rdataset;
5113                 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
5114                                         &name);
5115                 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
5116                         continue;
5117                 name->attributes &= ~DNS_NAMEATTR_CHASE;
5118                 for (rdataset = ISC_LIST_HEAD(name->list);
5119                      rdataset != NULL;
5120                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
5121                         if (CHASE(rdataset)) {
5122                                 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
5123                                 (void)dns_rdataset_additionaldata(rdataset,
5124                                                                   check_related,
5125                                                                   fctx);
5126                                 rescan = ISC_TRUE;
5127                         }
5128                 }
5129         }
5130         if (rescan)
5131                 goto again;
5132 }
5133
5134 static inline isc_result_t
5135 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
5136         isc_result_t result;
5137         dns_rdata_t rdata = DNS_RDATA_INIT;
5138         dns_rdata_cname_t cname;
5139
5140         result = dns_rdataset_first(rdataset);
5141         if (result != ISC_R_SUCCESS)
5142                 return (result);
5143         dns_rdataset_current(rdataset, &rdata);
5144         result = dns_rdata_tostruct(&rdata, &cname, NULL);
5145         if (result != ISC_R_SUCCESS)
5146                 return (result);
5147         dns_name_init(tname, NULL);
5148         dns_name_clone(&cname.cname, tname);
5149         dns_rdata_freestruct(&cname);
5150
5151         return (ISC_R_SUCCESS);
5152 }
5153
5154 static inline isc_result_t
5155 dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
5156              dns_name_t *oname, dns_fixedname_t *fixeddname)
5157 {
5158         isc_result_t result;
5159         dns_rdata_t rdata = DNS_RDATA_INIT;
5160         unsigned int nlabels;
5161         int order;
5162         dns_namereln_t namereln;
5163         dns_rdata_dname_t dname;
5164         dns_fixedname_t prefix;
5165
5166         /*
5167          * Get the target name of the DNAME.
5168          */
5169         result = dns_rdataset_first(rdataset);
5170         if (result != ISC_R_SUCCESS)
5171                 return (result);
5172         dns_rdataset_current(rdataset, &rdata);
5173         result = dns_rdata_tostruct(&rdata, &dname, NULL);
5174         if (result != ISC_R_SUCCESS)
5175                 return (result);
5176
5177         /*
5178          * Get the prefix of qname.
5179          */
5180         namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
5181         if (namereln != dns_namereln_subdomain) {
5182                 char qbuf[DNS_NAME_FORMATSIZE];
5183                 char obuf[DNS_NAME_FORMATSIZE];
5184
5185                 dns_rdata_freestruct(&dname);
5186                 dns_name_format(qname, qbuf, sizeof(qbuf));
5187                 dns_name_format(oname, obuf, sizeof(obuf));
5188                 log_formerr(fctx, "unrelated DNAME in answer: "
5189                                    "%s is not in %s", qbuf, obuf);
5190                 return (DNS_R_FORMERR);
5191         }
5192         dns_fixedname_init(&prefix);
5193         dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
5194         dns_fixedname_init(fixeddname);
5195         result = dns_name_concatenate(dns_fixedname_name(&prefix),
5196                                       &dname.dname,
5197                                       dns_fixedname_name(fixeddname), NULL);
5198         dns_rdata_freestruct(&dname);
5199         return (result);
5200 }
5201
5202 static isc_boolean_t
5203 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
5204                          dns_rdataset_t *rdataset)
5205 {
5206         isc_result_t result;
5207         dns_rdata_t rdata = DNS_RDATA_INIT;
5208         struct in_addr ina;
5209         struct in6_addr in6a;
5210         isc_netaddr_t netaddr;
5211         char addrbuf[ISC_NETADDR_FORMATSIZE];
5212         char namebuf[DNS_NAME_FORMATSIZE];
5213         char classbuf[64];
5214         char typebuf[64];
5215         int match;
5216
5217         /* By default, we allow any addresses. */
5218         if (view->denyansweracl == NULL)
5219                 return (ISC_TRUE);
5220
5221         /*
5222          * If the owner name matches one in the exclusion list, either exactly
5223          * or partially, allow it.
5224          */
5225         if (view->answeracl_exclude != NULL) {
5226                 dns_rbtnode_t *node = NULL;
5227
5228                 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
5229                                           &node, NULL, 0, NULL, NULL);
5230
5231                 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5232                         return (ISC_TRUE);
5233         }
5234
5235         /*
5236          * Otherwise, search the filter list for a match for each address
5237          * record.  If a match is found, the address should be filtered,
5238          * so should the entire answer.
5239          */
5240         for (result = dns_rdataset_first(rdataset);
5241              result == ISC_R_SUCCESS;
5242              result = dns_rdataset_next(rdataset)) {
5243                 dns_rdata_reset(&rdata);
5244                 dns_rdataset_current(rdataset, &rdata);
5245                 if (rdataset->type == dns_rdatatype_a) {
5246                         INSIST(rdata.length == sizeof(ina.s_addr));
5247                         memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
5248                         isc_netaddr_fromin(&netaddr, &ina);
5249                 } else {
5250                         INSIST(rdata.length == sizeof(in6a.s6_addr));
5251                         memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
5252                         isc_netaddr_fromin6(&netaddr, &in6a);
5253                 }
5254
5255                 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
5256                                        &view->aclenv, &match, NULL);
5257
5258                 if (result == ISC_R_SUCCESS && match > 0) {
5259                         isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
5260                         dns_name_format(name, namebuf, sizeof(namebuf));
5261                         dns_rdatatype_format(rdataset->type, typebuf,
5262                                              sizeof(typebuf));
5263                         dns_rdataclass_format(rdataset->rdclass, classbuf,
5264                                               sizeof(classbuf));
5265                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5266                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5267                                       "answer address %s denied for %s/%s/%s",
5268                                       addrbuf, namebuf, typebuf, classbuf);
5269                         return (ISC_FALSE);
5270                 }
5271         }
5272
5273         return (ISC_TRUE);
5274 }
5275
5276 static isc_boolean_t
5277 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
5278                         dns_rdatatype_t type, dns_name_t *tname,
5279                         dns_name_t *domain)
5280 {
5281         isc_result_t result;
5282         dns_rbtnode_t *node = NULL;
5283         char qnamebuf[DNS_NAME_FORMATSIZE];
5284         char tnamebuf[DNS_NAME_FORMATSIZE];
5285         char classbuf[64];
5286         char typebuf[64];
5287
5288         /* By default, we allow any target name. */
5289         if (view->denyanswernames == NULL)
5290                 return (ISC_TRUE);
5291
5292         /*
5293          * If the owner name matches one in the exclusion list, either exactly
5294          * or partially, allow it.
5295          */
5296         if (view->answernames_exclude != NULL) {
5297                 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
5298                                           &node, NULL, 0, NULL, NULL);
5299                 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5300                         return (ISC_TRUE);
5301         }
5302
5303         /*
5304          * If the target name is a subdomain of the search domain, allow it.
5305          */
5306         if (dns_name_issubdomain(tname, domain))
5307                 return (ISC_TRUE);
5308
5309         /*
5310          * Otherwise, apply filters.
5311          */
5312         result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
5313                                   NULL, 0, NULL, NULL);
5314         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
5315                 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
5316                 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
5317                 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
5318                 dns_rdataclass_format(view->rdclass, classbuf,
5319                                       sizeof(classbuf));
5320                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5321                               DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5322                               "%s target %s denied for %s/%s",
5323                               typebuf, tnamebuf, qnamebuf, classbuf);
5324                 return (ISC_FALSE);
5325         }
5326
5327         return (ISC_TRUE);
5328 }
5329
5330 static void
5331 trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
5332         char ns_namebuf[DNS_NAME_FORMATSIZE];
5333         char namebuf[DNS_NAME_FORMATSIZE];
5334         char tbuf[DNS_RDATATYPE_FORMATSIZE];
5335
5336         if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
5337                 dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
5338                 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
5339                 dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
5340
5341                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5342                               DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
5343                               "fctx %p: trimming ttl of %s/NS for %s/%s: "
5344                               "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
5345                               rdataset->ttl, fctx->ns_ttl);
5346                 rdataset->ttl = fctx->ns_ttl;
5347         }
5348 }
5349
5350 /*
5351  * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
5352  * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
5353  * section for the NS RRset if the query type is NS; if it has
5354  * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
5355  * section for A and AAAA queries.
5356  */
5357 #define LOOK_FOR_NS_IN_ANSWER 0x1
5358 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
5359
5360 static isc_result_t
5361 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
5362                   unsigned int look_in_options)
5363 {
5364         isc_result_t result;
5365         dns_message_t *message;
5366         dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
5367         dns_rdataset_t *rdataset, *ns_rdataset;
5368         isc_boolean_t aa, negative_response;
5369         dns_rdatatype_t type;
5370         dns_section_t section;
5371
5372         FCTXTRACE("noanswer_response");
5373
5374         if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
5375                 INSIST(fctx->type == dns_rdatatype_ns);
5376                 section = DNS_SECTION_ANSWER;
5377         } else
5378                 section = DNS_SECTION_AUTHORITY;
5379
5380         message = fctx->rmessage;
5381
5382         /*
5383          * Setup qname.
5384          */
5385         if (oqname == NULL) {
5386                 /*
5387                  * We have a normal, non-chained negative response or
5388                  * referral.
5389                  */
5390                 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5391                         aa = ISC_TRUE;
5392                 else
5393                         aa = ISC_FALSE;
5394                 qname = &fctx->name;
5395         } else {
5396                 /*
5397                  * We're being invoked by answer_response() after it has
5398                  * followed a CNAME/DNAME chain.
5399                  */
5400                 qname = oqname;
5401                 aa = ISC_FALSE;
5402                 /*
5403                  * If the current qname is not a subdomain of the query
5404                  * domain, there's no point in looking at the authority
5405                  * section without doing DNSSEC validation.
5406                  *
5407                  * Until we do that validation, we'll just return success
5408                  * in this case.
5409                  */
5410                 if (!dns_name_issubdomain(qname, &fctx->domain))
5411                         return (ISC_R_SUCCESS);
5412         }
5413
5414         /*
5415          * We have to figure out if this is a negative response, or a
5416          * referral.
5417          */
5418
5419         /*
5420          * Sometimes we can tell if its a negative response by looking at
5421          * the message header.
5422          */
5423         negative_response = ISC_FALSE;
5424         if (message->rcode == dns_rcode_nxdomain ||
5425             (message->counts[DNS_SECTION_ANSWER] == 0 &&
5426              message->counts[DNS_SECTION_AUTHORITY] == 0))
5427                 negative_response = ISC_TRUE;
5428
5429         /*
5430          * Process the authority section.
5431          */
5432         ns_name = NULL;
5433         ns_rdataset = NULL;
5434         soa_name = NULL;
5435         ds_name = NULL;
5436         result = dns_message_firstname(message, section);
5437         while (result == ISC_R_SUCCESS) {
5438                 name = NULL;
5439                 dns_message_currentname(message, section, &name);
5440                 if (dns_name_issubdomain(name, &fctx->domain)) {
5441                         /*
5442                          * Look for NS/SOA RRsets first.
5443                          */
5444                         for (rdataset = ISC_LIST_HEAD(name->list);
5445                              rdataset != NULL;
5446                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
5447                                 type = rdataset->type;
5448                                 if (type == dns_rdatatype_rrsig)
5449                                         type = rdataset->covers;
5450                                 if (((type == dns_rdatatype_ns ||
5451                                       type == dns_rdatatype_soa) &&
5452                                      !dns_name_issubdomain(qname, name))) {
5453                                         char qbuf[DNS_NAME_FORMATSIZE];
5454                                         char nbuf[DNS_NAME_FORMATSIZE];
5455                                         char tbuf[DNS_RDATATYPE_FORMATSIZE];
5456                                         dns_rdatatype_format(fctx->type, tbuf,
5457                                                              sizeof(tbuf));
5458                                         dns_name_format(name, nbuf,
5459                                                              sizeof(nbuf));
5460                                         dns_name_format(qname, qbuf,
5461                                                              sizeof(qbuf));
5462                                         log_formerr(fctx,
5463                                                     "unrelated %s %s in "
5464                                                     "%s authority section",
5465                                                     tbuf, qbuf, nbuf);
5466                                         return (DNS_R_FORMERR);
5467                                 }
5468                                 if (type == dns_rdatatype_ns) {
5469                                         /*
5470                                          * NS or RRSIG NS.
5471                                          *
5472                                          * Only one set of NS RRs is allowed.
5473                                          */
5474                                         if (rdataset->type ==
5475                                             dns_rdatatype_ns) {
5476                                                 if (ns_name != NULL &&
5477                                                     name != ns_name) {
5478                                                         log_formerr(fctx,
5479                                                                 "multiple NS "
5480                                                                 "RRsets in "
5481                                                                 "authority "
5482                                                                 "section");
5483                                                         return (DNS_R_FORMERR);
5484                                                 }
5485                                                 ns_name = name;
5486                                                 ns_rdataset = rdataset;
5487                                         }
5488                                         name->attributes |=
5489                                                 DNS_NAMEATTR_CACHE;
5490                                         rdataset->attributes |=
5491                                                 DNS_RDATASETATTR_CACHE;
5492                                         rdataset->trust = dns_trust_glue;
5493                                 }
5494                                 if (type == dns_rdatatype_soa) {
5495                                         /*
5496                                          * SOA, or RRSIG SOA.
5497                                          *
5498                                          * Only one SOA is allowed.
5499                                          */
5500                                         if (rdataset->type ==
5501                                             dns_rdatatype_soa) {
5502                                                 if (soa_name != NULL &&
5503                                                     name != soa_name) {
5504                                                         log_formerr(fctx,
5505                                                                 "multiple SOA "
5506                                                                 "RRs in "
5507                                                                 "authority "
5508                                                                 "section");
5509                                                         return (DNS_R_FORMERR);
5510                                                 }
5511                                                 soa_name = name;
5512                                         }
5513                                         name->attributes |=
5514                                                 DNS_NAMEATTR_NCACHE;
5515                                         rdataset->attributes |=
5516                                                 DNS_RDATASETATTR_NCACHE;
5517                                         if (aa)
5518                                                 rdataset->trust =
5519                                                     dns_trust_authauthority;
5520                                         else if (ISFORWARDER(fctx->addrinfo))
5521                                                 rdataset->trust =
5522                                                         dns_trust_answer;
5523                                         else
5524                                                 rdataset->trust =
5525                                                         dns_trust_additional;
5526                                 }
5527                         }
5528                 }
5529                 result = dns_message_nextname(message, section);
5530                 if (result == ISC_R_NOMORE)
5531                         break;
5532                 else if (result != ISC_R_SUCCESS)
5533                         return (result);
5534         }
5535
5536         log_ns_ttl(fctx, "noanswer_response");
5537
5538         if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
5539             !dns_name_equal(ns_name, dns_rootname))
5540                 trim_ns_ttl(fctx, ns_name, ns_rdataset);
5541
5542         /*
5543          * A negative response has a SOA record (Type 2)
5544          * and a optional NS RRset (Type 1) or it has neither
5545          * a SOA or a NS RRset (Type 3, handled above) or
5546          * rcode is NXDOMAIN (handled above) in which case
5547          * the NS RRset is allowed (Type 4).
5548          */
5549         if (soa_name != NULL)
5550                 negative_response = ISC_TRUE;
5551
5552         result = dns_message_firstname(message, section);
5553         while (result == ISC_R_SUCCESS) {
5554                 name = NULL;
5555                 dns_message_currentname(message, section, &name);
5556                 if (dns_name_issubdomain(name, &fctx->domain)) {
5557                         for (rdataset = ISC_LIST_HEAD(name->list);
5558                              rdataset != NULL;
5559                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
5560                                 type = rdataset->type;
5561                                 if (type == dns_rdatatype_rrsig)
5562                                         type = rdataset->covers;
5563                                 if (type == dns_rdatatype_nsec ||
5564                                     type == dns_rdatatype_nsec3) {
5565                                         /*
5566                                          * NSEC or RRSIG NSEC.
5567                                          */
5568                                         if (negative_response) {
5569                                                 name->attributes |=
5570                                                         DNS_NAMEATTR_NCACHE;
5571                                                 rdataset->attributes |=
5572                                                         DNS_RDATASETATTR_NCACHE;
5573                                         } else if (type == dns_rdatatype_nsec) {
5574                                                 name->attributes |=
5575                                                         DNS_NAMEATTR_CACHE;
5576                                                 rdataset->attributes |=
5577                                                         DNS_RDATASETATTR_CACHE;
5578                                         }
5579                                         if (aa)
5580                                                 rdataset->trust =
5581                                                     dns_trust_authauthority;
5582                                         else if (ISFORWARDER(fctx->addrinfo))
5583                                                 rdataset->trust =
5584                                                         dns_trust_answer;
5585                                         else
5586                                                 rdataset->trust =
5587                                                         dns_trust_additional;
5588                                         /*
5589                                          * No additional data needs to be
5590                                          * marked.
5591                                          */
5592                                 } else if (type == dns_rdatatype_ds) {
5593                                         /*
5594                                          * DS or SIG DS.
5595                                          *
5596                                          * These should only be here if
5597                                          * this is a referral, and there
5598                                          * should only be one DS RRset.
5599                                          */
5600                                         if (ns_name == NULL) {
5601                                                 log_formerr(fctx,
5602                                                             "DS with no "
5603                                                             "referral");
5604                                                 return (DNS_R_FORMERR);
5605                                         }
5606                                         if (rdataset->type ==
5607                                             dns_rdatatype_ds) {
5608                                                 if (ds_name != NULL &&
5609                                                     name != ds_name) {
5610                                                         log_formerr(fctx,
5611                                                                 "DS doesn't "
5612                                                                 "match "
5613                                                                 "referral "
5614                                                                 "(NS)");
5615                                                         return (DNS_R_FORMERR);
5616                                                 }
5617                                                 ds_name = name;
5618                                         }
5619                                         name->attributes |=
5620                                                 DNS_NAMEATTR_CACHE;
5621                                         rdataset->attributes |=
5622                                                 DNS_RDATASETATTR_CACHE;
5623                                         if (aa)
5624                                                 rdataset->trust =
5625                                                     dns_trust_authauthority;
5626                                         else if (ISFORWARDER(fctx->addrinfo))
5627                                                 rdataset->trust =
5628                                                         dns_trust_answer;
5629                                         else
5630                                                 rdataset->trust =
5631                                                         dns_trust_additional;
5632                                 }
5633                         }
5634                 }
5635                 result = dns_message_nextname(message, section);
5636                 if (result == ISC_R_NOMORE)
5637                         break;
5638                 else if (result != ISC_R_SUCCESS)
5639                         return (result);
5640         }
5641
5642         /*
5643          * Trigger lookups for DNS nameservers.
5644          */
5645         if (negative_response && message->rcode == dns_rcode_noerror &&
5646             fctx->type == dns_rdatatype_ds && soa_name != NULL &&
5647             dns_name_equal(soa_name, qname) &&
5648             !dns_name_equal(qname, dns_rootname))
5649                 return (DNS_R_CHASEDSSERVERS);
5650
5651         /*
5652          * Did we find anything?
5653          */
5654         if (!negative_response && ns_name == NULL) {
5655                 /*
5656                  * Nope.
5657                  */
5658                 if (oqname != NULL) {
5659                         /*
5660                          * We've already got a partial CNAME/DNAME chain,
5661                          * and haven't found else anything useful here, but
5662                          * no error has occurred since we have an answer.
5663                          */
5664                         return (ISC_R_SUCCESS);
5665                 } else {
5666                         /*
5667                          * The responder is insane.
5668                          */
5669                         log_formerr(fctx, "invalid response");
5670                         return (DNS_R_FORMERR);
5671                 }
5672         }
5673
5674         /*
5675          * If we found both NS and SOA, they should be the same name.
5676          */
5677         if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
5678                 log_formerr(fctx, "NS/SOA mismatch");
5679                 return (DNS_R_FORMERR);
5680         }
5681
5682         /*
5683          * Do we have a referral?  (We only want to follow a referral if
5684          * we're not following a chain.)
5685          */
5686         if (!negative_response && ns_name != NULL && oqname == NULL) {
5687                 /*
5688                  * We already know ns_name is a subdomain of fctx->domain.
5689                  * If ns_name is equal to fctx->domain, we're not making
5690                  * progress.  We return DNS_R_FORMERR so that we'll keep
5691                  * trying other servers.
5692                  */
5693                 if (dns_name_equal(ns_name, &fctx->domain)) {
5694                         log_formerr(fctx, "non-improving referral");
5695                         return (DNS_R_FORMERR);
5696                 }
5697
5698                 /*
5699                  * If the referral name is not a parent of the query
5700                  * name, consider the responder insane.
5701                  */
5702                 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
5703                         /* Logged twice */
5704                         log_formerr(fctx, "referral to non-parent");
5705                         FCTXTRACE("referral to non-parent");
5706                         return (DNS_R_FORMERR);
5707                 }
5708
5709                 /*
5710                  * Mark any additional data related to this rdataset.
5711                  * It's important that we do this before we change the
5712                  * query domain.
5713                  */
5714                 INSIST(ns_rdataset != NULL);
5715                 fctx->attributes |= FCTX_ATTR_GLUING;
5716                 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
5717                                                   fctx);
5718 #if CHECK_FOR_GLUE_IN_ANSWER
5719                 /*
5720                  * Look in the answer section for "glue" that is incorrectly
5721                  * returned as a answer.  This is needed if the server also
5722                  * minimizes the response size by not adding records to the
5723                  * additional section that are in the answer section or if
5724                  * the record gets dropped due to message size constraints.
5725                  */
5726                 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
5727                     (fctx->type == dns_rdatatype_aaaa ||
5728                      fctx->type == dns_rdatatype_a))
5729                         (void)dns_rdataset_additionaldata(ns_rdataset,
5730                                                           check_answer, fctx);
5731 #endif
5732                 fctx->attributes &= ~FCTX_ATTR_GLUING;
5733                 /*
5734                  * NS rdatasets with 0 TTL cause problems.
5735                  * dns_view_findzonecut() will not find them when we
5736                  * try to follow the referral, and we'll SERVFAIL
5737                  * because the best nameservers are now above QDOMAIN.
5738                  * We force the TTL to 1 second to prevent this.
5739                  */
5740                 if (ns_rdataset->ttl == 0)
5741                         ns_rdataset->ttl = 1;
5742                 /*
5743                  * Set the current query domain to the referral name.
5744                  *
5745                  * XXXRTH  We should check if we're in forward-only mode, and
5746                  *              if so we should bail out.
5747                  */
5748                 INSIST(dns_name_countlabels(&fctx->domain) > 0);
5749                 dns_name_free(&fctx->domain, fctx->mctx);
5750                 if (dns_rdataset_isassociated(&fctx->nameservers))
5751                         dns_rdataset_disassociate(&fctx->nameservers);
5752                 dns_name_init(&fctx->domain, NULL);
5753                 result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
5754                 if (result != ISC_R_SUCCESS)
5755                         return (result);
5756                 fctx->attributes |= FCTX_ATTR_WANTCACHE;
5757                 fctx->ns_ttl_ok = ISC_FALSE;
5758                 log_ns_ttl(fctx, "DELEGATION");
5759                 return (DNS_R_DELEGATION);
5760         }
5761
5762         /*
5763          * Since we're not doing a referral, we don't want to cache any
5764          * NS RRs we may have found.
5765          */
5766         if (ns_name != NULL)
5767                 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
5768
5769         if (negative_response && oqname == NULL)
5770                 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
5771
5772         return (ISC_R_SUCCESS);
5773 }
5774
5775 static isc_result_t
5776 answer_response(fetchctx_t *fctx) {
5777         isc_result_t result;
5778         dns_message_t *message;
5779         dns_name_t *name, *qname, tname, *ns_name;
5780         dns_rdataset_t *rdataset, *ns_rdataset;
5781         isc_boolean_t done, external, chaining, aa, found, want_chaining;
5782         isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
5783         unsigned int aflag;
5784         dns_rdatatype_t type;
5785         dns_fixedname_t dname, fqname;
5786         dns_view_t *view;
5787
5788         FCTXTRACE("answer_response");
5789
5790         message = fctx->rmessage;
5791
5792         /*
5793          * Examine the answer section, marking those rdatasets which are
5794          * part of the answer and should be cached.
5795          */
5796
5797         done = ISC_FALSE;
5798         found_cname = ISC_FALSE;
5799         found_type = ISC_FALSE;
5800         chaining = ISC_FALSE;
5801         have_answer = ISC_FALSE;
5802         want_chaining = ISC_FALSE;
5803         POST(want_chaining);
5804         if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5805                 aa = ISC_TRUE;
5806         else
5807                 aa = ISC_FALSE;
5808         qname = &fctx->name;
5809         type = fctx->type;
5810         view = fctx->res->view;
5811         result = dns_message_firstname(message, DNS_SECTION_ANSWER);
5812         while (!done && result == ISC_R_SUCCESS) {
5813                 name = NULL;
5814                 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
5815                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5816                 if (dns_name_equal(name, qname)) {
5817                         wanted_chaining = ISC_FALSE;
5818                         for (rdataset = ISC_LIST_HEAD(name->list);
5819                              rdataset != NULL;
5820                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
5821                                 found = ISC_FALSE;
5822                                 want_chaining = ISC_FALSE;
5823                                 aflag = 0;
5824                                 if (rdataset->type == dns_rdatatype_nsec3) {
5825                                         /*
5826                                          * NSEC3 records are not allowed to
5827                                          * appear in the answer section.
5828                                          */
5829                                         log_formerr(fctx, "NSEC3 in answer");
5830                                         return (DNS_R_FORMERR);
5831                                 }
5832
5833                                 /*
5834                                  * Apply filters, if given, on answers to reject
5835                                  * a malicious attempt of rebinding.
5836                                  */
5837                                 if ((rdataset->type == dns_rdatatype_a ||
5838                                      rdataset->type == dns_rdatatype_aaaa) &&
5839                                     !is_answeraddress_allowed(view, name,
5840                                                               rdataset)) {
5841                                         return (DNS_R_SERVFAIL);
5842                                 }
5843
5844                                 if (rdataset->type == type && !found_cname) {
5845                                         /*
5846                                          * We've found an ordinary answer.
5847                                          */
5848                                         found = ISC_TRUE;
5849                                         found_type = ISC_TRUE;
5850                                         done = ISC_TRUE;
5851                                         aflag = DNS_RDATASETATTR_ANSWER;
5852                                 } else if (type == dns_rdatatype_any) {
5853                                         /*
5854                                          * We've found an answer matching
5855                                          * an ANY query.  There may be
5856                                          * more.
5857                                          */
5858                                         found = ISC_TRUE;
5859                                         aflag = DNS_RDATASETATTR_ANSWER;
5860                                 } else if (rdataset->type == dns_rdatatype_rrsig
5861                                            && rdataset->covers == type
5862                                            && !found_cname) {
5863                                         /*
5864                                          * We've found a signature that
5865                                          * covers the type we're looking for.
5866                                          */
5867                                         found = ISC_TRUE;
5868                                         found_type = ISC_TRUE;
5869                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
5870                                 } else if (rdataset->type ==
5871                                            dns_rdatatype_cname
5872                                            && !found_type) {
5873                                         /*
5874                                          * We're looking for something else,
5875                                          * but we found a CNAME.
5876                                          *
5877                                          * Getting a CNAME response for some
5878                                          * query types is an error.
5879                                          */
5880                                         if (type == dns_rdatatype_rrsig ||
5881                                             type == dns_rdatatype_dnskey ||
5882                                             type == dns_rdatatype_nsec ||
5883                                             type == dns_rdatatype_nsec3) {
5884                                                 char buf[DNS_RDATATYPE_FORMATSIZE];
5885                                                 dns_rdatatype_format(fctx->type,
5886                                                               buf, sizeof(buf));
5887                                                 log_formerr(fctx,
5888                                                             "CNAME response "
5889                                                             "for %s RR", buf);
5890                                                 return (DNS_R_FORMERR);
5891                                         }
5892                                         found = ISC_TRUE;
5893                                         found_cname = ISC_TRUE;
5894                                         want_chaining = ISC_TRUE;
5895                                         aflag = DNS_RDATASETATTR_ANSWER;
5896                                         result = cname_target(rdataset,
5897                                                               &tname);
5898                                         if (result != ISC_R_SUCCESS)
5899                                                 return (result);
5900                                         /* Apply filters on the target name. */
5901                                         if (!is_answertarget_allowed(view,
5902                                                         name,
5903                                                         rdataset->type,
5904                                                         &tname,
5905                                                         &fctx->domain)) {
5906                                                 return (DNS_R_SERVFAIL);
5907                                         }
5908                                 } else if (rdataset->type == dns_rdatatype_rrsig
5909                                            && rdataset->covers ==
5910                                            dns_rdatatype_cname
5911                                            && !found_type) {
5912                                         /*
5913                                          * We're looking for something else,
5914                                          * but we found a SIG CNAME.
5915                                          */
5916                                         found = ISC_TRUE;
5917                                         found_cname = ISC_TRUE;
5918                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
5919                                 }
5920
5921                                 if (found) {
5922                                         /*
5923                                          * We've found an answer to our
5924                                          * question.
5925                                          */
5926                                         name->attributes |=
5927                                                 DNS_NAMEATTR_CACHE;
5928                                         rdataset->attributes |=
5929                                                 DNS_RDATASETATTR_CACHE;
5930                                         rdataset->trust = dns_trust_answer;
5931                                         if (!chaining) {
5932                                                 /*
5933                                                  * This data is "the" answer
5934                                                  * to our question only if
5935                                                  * we're not chaining (i.e.
5936                                                  * if we haven't followed
5937                                                  * a CNAME or DNAME).
5938                                                  */
5939                                                 INSIST(!external);
5940                                                 if (aflag ==
5941                                                     DNS_RDATASETATTR_ANSWER)
5942                                                         have_answer = ISC_TRUE;
5943                                                 name->attributes |=
5944                                                         DNS_NAMEATTR_ANSWER;
5945                                                 rdataset->attributes |= aflag;
5946                                                 if (aa)
5947                                                         rdataset->trust =
5948                                                           dns_trust_authanswer;
5949                                         } else if (external) {
5950                                                 /*
5951                                                  * This data is outside of
5952                                                  * our query domain, and
5953                                                  * may not be cached.
5954                                                  */
5955                                                 rdataset->attributes |=
5956                                                     DNS_RDATASETATTR_EXTERNAL;
5957                                         }
5958
5959                                         /*
5960                                          * Mark any additional data related
5961                                          * to this rdataset.
5962                                          */
5963                                         (void)dns_rdataset_additionaldata(
5964                                                         rdataset,
5965                                                         check_related,
5966                                                         fctx);
5967
5968                                         /*
5969                                          * CNAME chaining.
5970                                          */
5971                                         if (want_chaining) {
5972                                                 wanted_chaining = ISC_TRUE;
5973                                                 name->attributes |=
5974                                                         DNS_NAMEATTR_CHAINING;
5975                                                 rdataset->attributes |=
5976                                                     DNS_RDATASETATTR_CHAINING;
5977                                                 qname = &tname;
5978                                         }
5979                                 }
5980                                 /*
5981                                  * We could add an "else" clause here and
5982                                  * log that we're ignoring this rdataset.
5983                                  */
5984                         }
5985                         /*
5986                          * If wanted_chaining is true, we've done
5987                          * some chaining as the result of processing
5988                          * this node, and thus we need to set
5989                          * chaining to true.
5990                          *
5991                          * We don't set chaining inside of the
5992                          * rdataset loop because doing that would
5993                          * cause us to ignore the signatures of
5994                          * CNAMEs.
5995                          */
5996                         if (wanted_chaining)
5997                                 chaining = ISC_TRUE;
5998                 } else {
5999                         /*
6000                          * Look for a DNAME (or its SIG).  Anything else is
6001                          * ignored.
6002                          */
6003                         wanted_chaining = ISC_FALSE;
6004                         for (rdataset = ISC_LIST_HEAD(name->list);
6005                              rdataset != NULL;
6006                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
6007                                 isc_boolean_t found_dname = ISC_FALSE;
6008                                 dns_name_t *dname_name;
6009
6010                                 found = ISC_FALSE;
6011                                 aflag = 0;
6012                                 if (rdataset->type == dns_rdatatype_dname) {
6013                                         /*
6014                                          * We're looking for something else,
6015                                          * but we found a DNAME.
6016                                          *
6017                                          * If we're not chaining, then the
6018                                          * DNAME should not be external.
6019                                          */
6020                                         if (!chaining && external) {
6021                                                 log_formerr(fctx,
6022                                                             "external DNAME");
6023                                                 return (DNS_R_FORMERR);
6024                                         }
6025                                         found = ISC_TRUE;
6026                                         want_chaining = ISC_TRUE;
6027                                         POST(want_chaining);
6028                                         aflag = DNS_RDATASETATTR_ANSWER;
6029                                         result = dname_target(fctx, rdataset,
6030                                                               qname, name,
6031                                                               &dname);
6032                                         if (result == ISC_R_NOSPACE) {
6033                                                 /*
6034                                                  * We can't construct the
6035                                                  * DNAME target.  Do not
6036                                                  * try to continue.
6037                                                  */
6038                                                 want_chaining = ISC_FALSE;
6039                                                 POST(want_chaining);
6040                                         } else if (result != ISC_R_SUCCESS)
6041                                                 return (result);
6042                                         else
6043                                                 found_dname = ISC_TRUE;
6044
6045                                         dname_name = dns_fixedname_name(&dname);
6046                                         if (!is_answertarget_allowed(view,
6047                                                         qname,
6048                                                         rdataset->type,
6049                                                         dname_name,
6050                                                         &fctx->domain)) {
6051                                                 return (DNS_R_SERVFAIL);
6052                                         }
6053                                 } else if (rdataset->type == dns_rdatatype_rrsig
6054                                            && rdataset->covers ==
6055                                            dns_rdatatype_dname) {
6056                                         /*
6057                                          * We've found a signature that
6058                                          * covers the DNAME.
6059                                          */
6060                                         found = ISC_TRUE;
6061                                         aflag = DNS_RDATASETATTR_ANSWERSIG;
6062                                 }
6063
6064                                 if (found) {
6065                                         /*
6066                                          * We've found an answer to our
6067                                          * question.
6068                                          */
6069                                         name->attributes |=
6070                                                 DNS_NAMEATTR_CACHE;
6071                                         rdataset->attributes |=
6072                                                 DNS_RDATASETATTR_CACHE;
6073                                         rdataset->trust = dns_trust_answer;
6074                                         if (!chaining) {
6075                                                 /*
6076                                                  * This data is "the" answer
6077                                                  * to our question only if
6078                                                  * we're not chaining.
6079                                                  */
6080                                                 INSIST(!external);
6081                                                 if (aflag ==
6082                                                     DNS_RDATASETATTR_ANSWER)
6083                                                         have_answer = ISC_TRUE;
6084                                                 name->attributes |=
6085                                                         DNS_NAMEATTR_ANSWER;
6086                                                 rdataset->attributes |= aflag;
6087                                                 if (aa)
6088                                                         rdataset->trust =
6089                                                           dns_trust_authanswer;
6090                                         } else if (external) {
6091                                                 rdataset->attributes |=
6092                                                     DNS_RDATASETATTR_EXTERNAL;
6093                                         }
6094
6095                                         /*
6096                                          * DNAME chaining.
6097                                          */
6098                                         if (found_dname) {
6099                                                 /*
6100                                                  * Copy the dname into the
6101                                                  * qname fixed name.
6102                                                  *
6103                                                  * Although we check for
6104                                                  * failure of the copy
6105                                                  * operation, in practice it
6106                                                  * should never fail since
6107                                                  * we already know that the
6108                                                  * result fits in a fixedname.
6109                                                  */
6110                                                 dns_fixedname_init(&fqname);
6111                                                 result = dns_name_copy(
6112                                                   dns_fixedname_name(&dname),
6113                                                   dns_fixedname_name(&fqname),
6114                                                   NULL);
6115                                                 if (result != ISC_R_SUCCESS)
6116                                                         return (result);
6117                                                 wanted_chaining = ISC_TRUE;
6118                                                 name->attributes |=
6119                                                         DNS_NAMEATTR_CHAINING;
6120                                                 rdataset->attributes |=
6121                                                     DNS_RDATASETATTR_CHAINING;
6122                                                 qname = dns_fixedname_name(
6123                                                                    &fqname);
6124                                         }
6125                                 }
6126                         }
6127                         if (wanted_chaining)
6128                                 chaining = ISC_TRUE;
6129                 }
6130                 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
6131         }
6132         if (result == ISC_R_NOMORE)
6133                 result = ISC_R_SUCCESS;
6134         if (result != ISC_R_SUCCESS)
6135                 return (result);
6136
6137         /*
6138          * We should have found an answer.
6139          */
6140         if (!have_answer) {
6141                 log_formerr(fctx, "reply has no answer");
6142                 return (DNS_R_FORMERR);
6143         }
6144
6145         /*
6146          * This response is now potentially cacheable.
6147          */
6148         fctx->attributes |= FCTX_ATTR_WANTCACHE;
6149
6150         /*
6151          * Did chaining end before we got the final answer?
6152          */
6153         if (chaining) {
6154                 /*
6155                  * Yes.  This may be a negative reply, so hand off
6156                  * authority section processing to the noanswer code.
6157                  * If it isn't a noanswer response, no harm will be
6158                  * done.
6159                  */
6160                 return (noanswer_response(fctx, qname, 0));
6161         }
6162
6163         /*
6164          * We didn't end with an incomplete chain, so the rcode should be
6165          * "no error".
6166          */
6167         if (message->rcode != dns_rcode_noerror) {
6168                 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
6169                                   "indicates error");
6170                 return (DNS_R_FORMERR);
6171         }
6172
6173         /*
6174          * Examine the authority section (if there is one).
6175          *
6176          * We expect there to be only one owner name for all the rdatasets
6177          * in this section, and we expect that it is not external.
6178          */
6179         done = ISC_FALSE;
6180         ns_name = NULL;
6181         ns_rdataset = NULL;
6182         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6183         while (!done && result == ISC_R_SUCCESS) {
6184                 name = NULL;
6185                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6186                 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
6187                 if (!external) {
6188                         /*
6189                          * We expect to find NS or SIG NS rdatasets, and
6190                          * nothing else.
6191                          */
6192                         for (rdataset = ISC_LIST_HEAD(name->list);
6193                              rdataset != NULL;
6194                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
6195                                 if (rdataset->type == dns_rdatatype_ns ||
6196                                     (rdataset->type == dns_rdatatype_rrsig &&
6197                                      rdataset->covers == dns_rdatatype_ns)) {
6198                                         name->attributes |=
6199                                                 DNS_NAMEATTR_CACHE;
6200                                         rdataset->attributes |=
6201                                                 DNS_RDATASETATTR_CACHE;
6202                                         if (aa && !chaining)
6203                                                 rdataset->trust =
6204                                                     dns_trust_authauthority;
6205                                         else
6206                                                 rdataset->trust =
6207                                                     dns_trust_additional;
6208
6209                                         if (rdataset->type == dns_rdatatype_ns) {
6210                                                 ns_name = name;
6211                                                 ns_rdataset = rdataset;
6212                                         }
6213                                         /*
6214                                          * Mark any additional data related
6215                                          * to this rdataset.
6216                                          */
6217                                         (void)dns_rdataset_additionaldata(
6218                                                         rdataset,
6219                                                         check_related,
6220                                                         fctx);
6221                                         done = ISC_TRUE;
6222                                 }
6223                         }
6224                 }
6225                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
6226         }
6227         if (result == ISC_R_NOMORE)
6228                 result = ISC_R_SUCCESS;
6229
6230         log_ns_ttl(fctx, "answer_response");
6231
6232         if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
6233             !dns_name_equal(ns_name, dns_rootname))
6234                 trim_ns_ttl(fctx, ns_name, ns_rdataset);
6235
6236         return (result);
6237 }
6238
6239 static isc_boolean_t
6240 fctx_decreference(fetchctx_t *fctx) {
6241         isc_boolean_t bucket_empty = ISC_FALSE;
6242
6243         INSIST(fctx->references > 0);
6244         fctx->references--;
6245         if (fctx->references == 0) {
6246                 /*
6247                  * No one cares about the result of this fetch anymore.
6248                  */
6249                 if (fctx->pending == 0 && fctx->nqueries == 0 &&
6250                     ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
6251                         /*
6252                          * This fctx is already shutdown; we were just
6253                          * waiting for the last reference to go away.
6254                          */
6255                         bucket_empty = fctx_unlink(fctx);
6256                         fctx_destroy(fctx);
6257                 } else {
6258                         /*
6259                          * Initiate shutdown.
6260                          */
6261                         fctx_shutdown(fctx);
6262                 }
6263         }
6264         return (bucket_empty);
6265 }
6266
6267 static void
6268 resume_dslookup(isc_task_t *task, isc_event_t *event) {
6269         dns_fetchevent_t *fevent;
6270         dns_resolver_t *res;
6271         fetchctx_t *fctx;
6272         isc_result_t result;
6273         isc_boolean_t bucket_empty;
6274         isc_boolean_t locked = ISC_FALSE;
6275         unsigned int bucketnum;
6276         dns_rdataset_t nameservers;
6277         dns_fixedname_t fixed;
6278         dns_name_t *domain;
6279
6280         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
6281         fevent = (dns_fetchevent_t *)event;
6282         fctx = event->ev_arg;
6283         REQUIRE(VALID_FCTX(fctx));
6284         res = fctx->res;
6285
6286         UNUSED(task);
6287         FCTXTRACE("resume_dslookup");
6288
6289         if (fevent->node != NULL)
6290                 dns_db_detachnode(fevent->db, &fevent->node);
6291         if (fevent->db != NULL)
6292                 dns_db_detach(&fevent->db);
6293
6294         dns_rdataset_init(&nameservers);
6295
6296         bucketnum = fctx->bucketnum;
6297         if (fevent->result == ISC_R_CANCELED) {
6298                 dns_resolver_destroyfetch(&fctx->nsfetch);
6299                 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
6300         } else if (fevent->result == ISC_R_SUCCESS) {
6301
6302                 FCTXTRACE("resuming DS lookup");
6303
6304                 dns_resolver_destroyfetch(&fctx->nsfetch);
6305                 if (dns_rdataset_isassociated(&fctx->nameservers))
6306                         dns_rdataset_disassociate(&fctx->nameservers);
6307                 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
6308                 fctx->ns_ttl = fctx->nameservers.ttl;
6309                 fctx->ns_ttl_ok = ISC_TRUE;
6310                 log_ns_ttl(fctx, "resume_dslookup");
6311                 dns_name_free(&fctx->domain, fctx->mctx);
6312                 dns_name_init(&fctx->domain, NULL);
6313                 result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
6314                 if (result != ISC_R_SUCCESS) {
6315                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6316                         goto cleanup;
6317                 }
6318                 /*
6319                  * Try again.
6320                  */
6321                 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
6322         } else {
6323                 unsigned int n;
6324                 dns_rdataset_t *nsrdataset = NULL;
6325
6326                 /*
6327                  * Retrieve state from fctx->nsfetch before we destroy it.
6328                  */
6329                 dns_fixedname_init(&fixed);
6330                 domain = dns_fixedname_name(&fixed);
6331                 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
6332                 if (dns_name_equal(&fctx->nsname, domain)) {
6333                         fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6334                         dns_resolver_destroyfetch(&fctx->nsfetch);
6335                         goto cleanup;
6336                 }
6337                 if (dns_rdataset_isassociated(
6338                     &fctx->nsfetch->private->nameservers)) {
6339                         dns_rdataset_clone(
6340                             &fctx->nsfetch->private->nameservers,
6341                             &nameservers);
6342                         nsrdataset = &nameservers;
6343                 } else
6344                         domain = NULL;
6345                 dns_resolver_destroyfetch(&fctx->nsfetch);
6346                 n = dns_name_countlabels(&fctx->nsname);
6347                 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
6348                                           &fctx->nsname);
6349
6350                 if (dns_rdataset_isassociated(fevent->rdataset))
6351                         dns_rdataset_disassociate(fevent->rdataset);
6352                 FCTXTRACE("continuing to look for parent's NS records");
6353                 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
6354                                                   dns_rdatatype_ns, domain,
6355                                                   nsrdataset, NULL, 0, task,
6356                                                   resume_dslookup, fctx,
6357                                                   &fctx->nsrrset, NULL,
6358                                                   &fctx->nsfetch);
6359                 if (result != ISC_R_SUCCESS)
6360                         fctx_done(fctx, result, __LINE__);
6361                 else {
6362                         LOCK(&res->buckets[bucketnum].lock);
6363                         locked = ISC_TRUE;
6364                         fctx->references++;
6365                 }
6366         }
6367
6368  cleanup:
6369         if (dns_rdataset_isassociated(&nameservers))
6370                 dns_rdataset_disassociate(&nameservers);
6371         if (dns_rdataset_isassociated(fevent->rdataset))
6372                 dns_rdataset_disassociate(fevent->rdataset);
6373         INSIST(fevent->sigrdataset == NULL);
6374         isc_event_free(&event);
6375         if (!locked)
6376                 LOCK(&res->buckets[bucketnum].lock);
6377         bucket_empty = fctx_decreference(fctx);
6378         UNLOCK(&res->buckets[bucketnum].lock);
6379         if (bucket_empty)
6380                 empty_bucket(res);
6381 }
6382
6383 static inline void
6384 checknamessection(dns_message_t *message, dns_section_t section) {
6385         isc_result_t result;
6386         dns_name_t *name;
6387         dns_rdata_t rdata = DNS_RDATA_INIT;
6388         dns_rdataset_t *rdataset;
6389
6390         for (result = dns_message_firstname(message, section);
6391              result == ISC_R_SUCCESS;
6392              result = dns_message_nextname(message, section))
6393         {
6394                 name = NULL;
6395                 dns_message_currentname(message, section, &name);
6396                 for (rdataset = ISC_LIST_HEAD(name->list);
6397                      rdataset != NULL;
6398                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
6399                         for (result = dns_rdataset_first(rdataset);
6400                              result == ISC_R_SUCCESS;
6401                              result = dns_rdataset_next(rdataset)) {
6402                                 dns_rdataset_current(rdataset, &rdata);
6403                                 if (!dns_rdata_checkowner(name, rdata.rdclass,
6404                                                           rdata.type,
6405                                                           ISC_FALSE) ||
6406                                     !dns_rdata_checknames(&rdata, name, NULL))
6407                                 {
6408                                         rdataset->attributes |=
6409                                                 DNS_RDATASETATTR_CHECKNAMES;
6410                                 }
6411                                 dns_rdata_reset(&rdata);
6412                         }
6413                 }
6414         }
6415 }
6416
6417 static void
6418 checknames(dns_message_t *message) {
6419
6420         checknamessection(message, DNS_SECTION_ANSWER);
6421         checknamessection(message, DNS_SECTION_AUTHORITY);
6422         checknamessection(message, DNS_SECTION_ADDITIONAL);
6423 }
6424
6425 /*
6426  * Log server NSID at log level 'level'
6427  */
6428 static isc_result_t
6429 log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
6430 {
6431         static const char hex[17] = "0123456789abcdef";
6432         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6433         isc_uint16_t optcode, nsid_len, buflen, i;
6434         isc_result_t result;
6435         isc_buffer_t nsidbuf;
6436         dns_rdata_t rdata;
6437         unsigned char *p, *buf, *nsid;
6438
6439         /* Extract rdata from OPT rdataset */
6440         result = dns_rdataset_first(opt);
6441         if (result != ISC_R_SUCCESS)
6442                 return (ISC_R_FAILURE);
6443
6444         dns_rdata_init(&rdata);
6445         dns_rdataset_current(opt, &rdata);
6446         if (rdata.length < 4)
6447                 return (ISC_R_FAILURE);
6448
6449         /* Check for NSID */
6450         isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
6451         isc_buffer_add(&nsidbuf, rdata.length);
6452         optcode = isc_buffer_getuint16(&nsidbuf);
6453         nsid_len = isc_buffer_getuint16(&nsidbuf);
6454         if (optcode != DNS_OPT_NSID || nsid_len == 0)
6455                 return (ISC_R_FAILURE);
6456
6457         /* Allocate buffer for storing hex version of the NSID */
6458         buflen = nsid_len * 2 + 1;
6459         buf = isc_mem_get(mctx, buflen);
6460         if (buf == NULL)
6461                 return (ISC_R_NOSPACE);
6462
6463         /* Convert to hex */
6464         p = buf;
6465         nsid = rdata.data + 4;
6466         for (i = 0; i < nsid_len; i++) {
6467                 *p++ = hex[(nsid[0] >> 4) & 0xf];
6468                 *p++ = hex[nsid[0] & 0xf];
6469                 nsid++;
6470         }
6471         *p = '\0';
6472
6473         isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6474                             sizeof(addrbuf));
6475         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6476                       DNS_LOGMODULE_RESOLVER, level,
6477                       "received NSID '%s' from %s", buf, addrbuf);
6478
6479         /* Clean up */
6480         isc_mem_put(mctx, buf, buflen);
6481         return (ISC_R_SUCCESS);
6482 }
6483
6484 static void
6485 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
6486         isc_buffer_t buffer;
6487         char *buf = NULL;
6488         int len = 1024;
6489         isc_result_t result;
6490
6491         if (! isc_log_wouldlog(dns_lctx, level))
6492                 return;
6493
6494         /*
6495          * Note that these are multiline debug messages.  We want a newline
6496          * to appear in the log after each message.
6497          */
6498
6499         do {
6500                 buf = isc_mem_get(mctx, len);
6501                 if (buf == NULL)
6502                         break;
6503                 isc_buffer_init(&buffer, buf, len);
6504                 result = dns_message_totext(message, &dns_master_style_debug,
6505                                             0, &buffer);
6506                 if (result == ISC_R_NOSPACE) {
6507                         isc_mem_put(mctx, buf, len);
6508                         len += 1024;
6509                 } else if (result == ISC_R_SUCCESS)
6510                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6511                                       DNS_LOGMODULE_RESOLVER, level,
6512                                       "received packet:\n%.*s",
6513                                       (int)isc_buffer_usedlength(&buffer),
6514                                       buf);
6515         } while (result == ISC_R_NOSPACE);
6516
6517         if (buf != NULL)
6518                 isc_mem_put(mctx, buf, len);
6519 }
6520
6521 static isc_boolean_t
6522 iscname(fetchctx_t *fctx) {
6523         isc_result_t result;
6524
6525         result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
6526                                       &fctx->name, dns_rdatatype_cname, 0,
6527                                       NULL, NULL);
6528         return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
6529 }
6530
6531 static isc_boolean_t
6532 betterreferral(fetchctx_t *fctx) {
6533         isc_result_t result;
6534         dns_name_t *name;
6535         dns_rdataset_t *rdataset;
6536         dns_message_t *message = fctx->rmessage;
6537
6538         for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6539              result == ISC_R_SUCCESS;
6540              result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
6541                 name = NULL;
6542                 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6543                 if (!isstrictsubdomain(name, &fctx->domain))
6544                         continue;
6545                 for (rdataset = ISC_LIST_HEAD(name->list);
6546                      rdataset != NULL;
6547                      rdataset = ISC_LIST_NEXT(rdataset, link))
6548                         if (rdataset->type == dns_rdatatype_ns)
6549                                 return (ISC_TRUE);
6550         }
6551         return (ISC_FALSE);
6552 }
6553
6554 static void
6555 resquery_response(isc_task_t *task, isc_event_t *event) {
6556         isc_result_t result = ISC_R_SUCCESS;
6557         resquery_t *query = event->ev_arg;
6558         dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
6559         isc_boolean_t keep_trying, get_nameservers, resend;
6560         isc_boolean_t truncated;
6561         dns_message_t *message;
6562         dns_rdataset_t *opt;
6563         fetchctx_t *fctx;
6564         dns_name_t *fname;
6565         dns_fixedname_t foundname;
6566         isc_stdtime_t now;
6567         isc_time_t tnow, *finish;
6568         dns_adbaddrinfo_t *addrinfo;
6569         unsigned int options;
6570         unsigned int findoptions;
6571         isc_result_t broken_server;
6572         badnstype_t broken_type = badns_response;
6573         isc_boolean_t no_response;
6574
6575         REQUIRE(VALID_QUERY(query));
6576         fctx = query->fctx;
6577         options = query->options;
6578         REQUIRE(VALID_FCTX(fctx));
6579         REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
6580
6581         QTRACE("response");
6582
6583         if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
6584                 inc_stats(fctx->res, dns_resstatscounter_responsev4);
6585         else
6586                 inc_stats(fctx->res, dns_resstatscounter_responsev6);
6587
6588         (void)isc_timer_touch(fctx->timer);
6589
6590         keep_trying = ISC_FALSE;
6591         broken_server = ISC_R_SUCCESS;
6592         get_nameservers = ISC_FALSE;
6593         resend = ISC_FALSE;
6594         truncated = ISC_FALSE;
6595         finish = NULL;
6596         no_response = ISC_FALSE;
6597
6598         if (fctx->res->exiting) {
6599                 result = ISC_R_SHUTTINGDOWN;
6600                 goto done;
6601         }
6602
6603         fctx->timeouts = 0;
6604         fctx->timeout = ISC_FALSE;
6605         fctx->addrinfo = query->addrinfo;
6606
6607         /*
6608          * XXXRTH  We should really get the current time just once.  We
6609          *              need a routine to convert from an isc_time_t to an
6610          *              isc_stdtime_t.
6611          */
6612         TIME_NOW(&tnow);
6613         finish = &tnow;
6614         isc_stdtime_get(&now);
6615
6616         /*
6617          * Did the dispatcher have a problem?
6618          */
6619         if (devent->result != ISC_R_SUCCESS) {
6620                 if (devent->result == ISC_R_EOF &&
6621                     (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6622                         /*
6623                          * The problem might be that they
6624                          * don't understand EDNS0.  Turn it
6625                          * off and try again.
6626                          */
6627                         options |= DNS_FETCHOPT_NOEDNS0;
6628                         resend = ISC_TRUE;
6629                         /*
6630                          * Remember that they don't like EDNS0.
6631                          */
6632                         dns_adb_changeflags(fctx->adb,
6633                                             query->addrinfo,
6634                                             DNS_FETCHOPT_NOEDNS0,
6635                                             DNS_FETCHOPT_NOEDNS0);
6636                 } else {
6637                         /*
6638                          * There's no hope for this query.
6639                          */
6640                         keep_trying = ISC_TRUE;
6641
6642                         /*
6643                          * If this is a network error on an exclusive query
6644                          * socket, mark the server as bad so that we won't try
6645                          * it for this fetch again.  Also adjust finish and
6646                          * no_response so that we penalize this address in SRTT
6647                          * adjustment later.
6648                          */
6649                         if (query->exclusivesocket &&
6650                             (devent->result == ISC_R_HOSTUNREACH ||
6651                              devent->result == ISC_R_NETUNREACH ||
6652                              devent->result == ISC_R_CONNREFUSED ||
6653                              devent->result == ISC_R_CANCELED)) {
6654                                     broken_server = devent->result;
6655                                     broken_type = badns_unreachable;
6656                                     finish = NULL;
6657                                     no_response = ISC_TRUE;
6658                         }
6659                 }
6660                 goto done;
6661         }
6662
6663         message = fctx->rmessage;
6664
6665         if (query->tsig != NULL) {
6666                 result = dns_message_setquerytsig(message, query->tsig);
6667                 if (result != ISC_R_SUCCESS)
6668                         goto done;
6669         }
6670
6671         if (query->tsigkey) {
6672                 result = dns_message_settsigkey(message, query->tsigkey);
6673                 if (result != ISC_R_SUCCESS)
6674                         goto done;
6675         }
6676
6677         result = dns_message_parse(message, &devent->buffer, 0);
6678         if (result != ISC_R_SUCCESS) {
6679                 switch (result) {
6680                 case ISC_R_UNEXPECTEDEND:
6681                         if (!message->question_ok ||
6682                             (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
6683                             (options & DNS_FETCHOPT_TCP) != 0) {
6684                                 /*
6685                                  * Either the message ended prematurely,
6686                                  * and/or wasn't marked as being truncated,
6687                                  * and/or this is a response to a query we
6688                                  * sent over TCP.  In all of these cases,
6689                                  * something is wrong with the remote
6690                                  * server and we don't want to retry using
6691                                  * TCP.
6692                                  */
6693                                 if ((query->options & DNS_FETCHOPT_NOEDNS0)
6694                                     == 0) {
6695                                         /*
6696                                          * The problem might be that they
6697                                          * don't understand EDNS0.  Turn it
6698                                          * off and try again.
6699                                          */
6700                                         options |= DNS_FETCHOPT_NOEDNS0;
6701                                         resend = ISC_TRUE;
6702                                         /*
6703                                          * Remember that they don't like EDNS0.
6704                                          */
6705                                         dns_adb_changeflags(
6706                                                         fctx->adb,
6707                                                         query->addrinfo,
6708                                                         DNS_FETCHOPT_NOEDNS0,
6709                                                         DNS_FETCHOPT_NOEDNS0);
6710                                         inc_stats(fctx->res,
6711                                                  dns_resstatscounter_edns0fail);
6712                                 } else {
6713                                         broken_server = result;
6714                                         keep_trying = ISC_TRUE;
6715                                 }
6716                                 goto done;
6717                         }
6718                         /*
6719                          * We defer retrying via TCP for a bit so we can
6720                          * check out this message further.
6721                          */
6722                         truncated = ISC_TRUE;
6723                         break;
6724                 case DNS_R_FORMERR:
6725                         if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6726                                 /*
6727                                  * The problem might be that they
6728                                  * don't understand EDNS0.  Turn it
6729                                  * off and try again.
6730                                  */
6731                                 options |= DNS_FETCHOPT_NOEDNS0;
6732                                 resend = ISC_TRUE;
6733                                 /*
6734                                  * Remember that they don't like EDNS0.
6735                                  */
6736                                 dns_adb_changeflags(fctx->adb,
6737                                                     query->addrinfo,
6738                                                     DNS_FETCHOPT_NOEDNS0,
6739                                                     DNS_FETCHOPT_NOEDNS0);
6740                                 inc_stats(fctx->res,
6741                                                  dns_resstatscounter_edns0fail);
6742                         } else {
6743                                 broken_server = DNS_R_UNEXPECTEDRCODE;
6744                                 keep_trying = ISC_TRUE;
6745                         }
6746                         goto done;
6747                 default:
6748                         /*
6749                          * Something bad has happened.
6750                          */
6751                         goto done;
6752                 }
6753         }
6754
6755
6756         /*
6757          * Log the incoming packet.
6758          */
6759         log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
6760
6761         /*
6762          * Did we request NSID?  If so, and if the response contains
6763          * NSID data, log it at INFO level.
6764          */
6765         opt = dns_message_getopt(message);
6766         if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
6767                 log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
6768
6769         /*
6770          * If the message is signed, check the signature.  If not, this
6771          * returns success anyway.
6772          */
6773         result = dns_message_checksig(message, fctx->res->view);
6774         if (result != ISC_R_SUCCESS)
6775                 goto done;
6776
6777         /*
6778          * The dispatcher should ensure we only get responses with QR set.
6779          */
6780         INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
6781         /*
6782          * INSIST() that the message comes from the place we sent it to,
6783          * since the dispatch code should ensure this.
6784          *
6785          * INSIST() that the message id is correct (this should also be
6786          * ensured by the dispatch code).
6787          */
6788
6789         /*
6790          * We have an affirmative response to the query and we have
6791          * previously got a response from this server which indicated
6792          * EDNS may not be supported so we can now cache the lack of
6793          * EDNS support.
6794          */
6795         if (opt == NULL &&
6796             (message->rcode == dns_rcode_noerror ||
6797              message->rcode == dns_rcode_nxdomain ||
6798              message->rcode == dns_rcode_refused ||
6799              message->rcode == dns_rcode_yxdomain) &&
6800              bad_edns(fctx, &query->addrinfo->sockaddr)) {
6801                 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6802                 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6803                                     sizeof(addrbuf));
6804                 dns_adb_changeflags(fctx->adb, query->addrinfo,
6805                                     DNS_FETCHOPT_NOEDNS0,
6806                                     DNS_FETCHOPT_NOEDNS0);
6807         }
6808
6809         /*
6810          * Deal with truncated responses by retrying using TCP.
6811          */
6812         if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
6813                 truncated = ISC_TRUE;
6814
6815         if (truncated) {
6816                 inc_stats(fctx->res, dns_resstatscounter_truncated);
6817                 if ((options & DNS_FETCHOPT_TCP) != 0) {
6818                         broken_server = DNS_R_TRUNCATEDTCP;
6819                         keep_trying = ISC_TRUE;
6820                 } else {
6821                         options |= DNS_FETCHOPT_TCP;
6822                         resend = ISC_TRUE;
6823                 }
6824                 goto done;
6825         }
6826
6827         /*
6828          * Is it a query response?
6829          */
6830         if (message->opcode != dns_opcode_query) {
6831                 /* XXXRTH Log */
6832                 broken_server = DNS_R_UNEXPECTEDOPCODE;
6833                 keep_trying = ISC_TRUE;
6834                 goto done;
6835         }
6836
6837         /*
6838          * Update statistics about erroneous responses.
6839          */
6840         if (message->rcode != dns_rcode_noerror) {
6841                 switch (message->rcode) {
6842                 case dns_rcode_nxdomain:
6843                         inc_stats(fctx->res, dns_resstatscounter_nxdomain);
6844                         break;
6845                 case dns_rcode_servfail:
6846                         inc_stats(fctx->res, dns_resstatscounter_servfail);
6847                         break;
6848                 case dns_rcode_formerr:
6849                         inc_stats(fctx->res, dns_resstatscounter_formerr);
6850                         break;
6851                 default:
6852                         inc_stats(fctx->res, dns_resstatscounter_othererror);
6853                         break;
6854                 }
6855         }
6856
6857         /*
6858          * Is the remote server broken, or does it dislike us?
6859          */
6860         if (message->rcode != dns_rcode_noerror &&
6861             message->rcode != dns_rcode_nxdomain) {
6862                 if (((message->rcode == dns_rcode_formerr ||
6863                       message->rcode == dns_rcode_notimp) ||
6864                      (message->rcode == dns_rcode_servfail &&
6865                       dns_message_getopt(message) == NULL)) &&
6866                     (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6867                         /*
6868                          * It's very likely they don't like EDNS0.
6869                          * If the response code is SERVFAIL, also check if the
6870                          * response contains an OPT RR and don't cache the
6871                          * failure since it can be returned for various other
6872                          * reasons.
6873                          *
6874                          * XXXRTH  We should check if the question
6875                          *              we're asking requires EDNS0, and
6876                          *              if so, we should bail out.
6877                          */
6878                         options |= DNS_FETCHOPT_NOEDNS0;
6879                         resend = ISC_TRUE;
6880                         /*
6881                          * Remember that they may not like EDNS0.
6882                          */
6883                         add_bad_edns(fctx, &query->addrinfo->sockaddr);
6884                         inc_stats(fctx->res, dns_resstatscounter_edns0fail);
6885                 } else if (message->rcode == dns_rcode_formerr) {
6886                         if (ISFORWARDER(query->addrinfo)) {
6887                                 /*
6888                                  * This forwarder doesn't understand us,
6889                                  * but other forwarders might.  Keep trying.
6890                                  */
6891                                 broken_server = DNS_R_REMOTEFORMERR;
6892                                 keep_trying = ISC_TRUE;
6893                         } else {
6894                                 /*
6895                                  * The server doesn't understand us.  Since
6896                                  * all servers for a zone need similar
6897                                  * capabilities, we assume that we will get
6898                                  * FORMERR from all servers, and thus we
6899                                  * cannot make any more progress with this
6900                                  * fetch.
6901                                  */
6902                                 log_formerr(fctx, "server sent FORMERR");
6903                                 result = DNS_R_FORMERR;
6904                         }
6905                 } else if (message->rcode == dns_rcode_yxdomain) {
6906                         /*
6907                          * DNAME mapping failed because the new name
6908                          * was too long.  There's no chance of success
6909                          * for this fetch.
6910                          */
6911                         result = DNS_R_YXDOMAIN;
6912                 } else if (message->rcode == dns_rcode_badvers) {
6913                         unsigned int flags, mask;
6914                         unsigned int version;
6915
6916                         resend = ISC_TRUE;
6917                         INSIST(opt != NULL);
6918                         version = (opt->ttl >> 16) & 0xff;
6919                         flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
6920                                 DNS_FETCHOPT_EDNSVERSIONSET;
6921                         mask = DNS_FETCHOPT_EDNSVERSIONMASK |
6922                                DNS_FETCHOPT_EDNSVERSIONSET;
6923                         switch (version) {
6924                         case 0:
6925                                 dns_adb_changeflags(fctx->adb, query->addrinfo,
6926                                                     flags, mask);
6927                                 break;
6928                         default:
6929                                 broken_server = DNS_R_BADVERS;
6930                                 keep_trying = ISC_TRUE;
6931                                 break;
6932                         }
6933                 } else {
6934                         /*
6935                          * XXXRTH log.
6936                          */
6937                         broken_server = DNS_R_UNEXPECTEDRCODE;
6938                         INSIST(broken_server != ISC_R_SUCCESS);
6939                         keep_trying = ISC_TRUE;
6940                 }
6941                 goto done;
6942         }
6943
6944         /*
6945          * Is the question the same as the one we asked?
6946          */
6947         result = same_question(fctx);
6948         if (result != ISC_R_SUCCESS) {
6949                 /* XXXRTH Log */
6950                 if (result == DNS_R_FORMERR)
6951                         keep_trying = ISC_TRUE;
6952                 goto done;
6953         }
6954
6955         /*
6956          * Is the server lame?
6957          */
6958         if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
6959             is_lame(fctx)) {
6960                 inc_stats(fctx->res, dns_resstatscounter_lame);
6961                 log_lame(fctx, query->addrinfo);
6962                 result = dns_adb_marklame(fctx->adb, query->addrinfo,
6963                                           &fctx->name, fctx->type,
6964                                           now + fctx->res->lame_ttl);
6965                 if (result != ISC_R_SUCCESS)
6966                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6967                                       DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
6968                                       "could not mark server as lame: %s",
6969                                       isc_result_totext(result));
6970                 broken_server = DNS_R_LAME;
6971                 keep_trying = ISC_TRUE;
6972                 goto done;
6973         }
6974
6975         /*
6976          * Enforce delegations only zones like NET and COM.
6977          */
6978         if (!ISFORWARDER(query->addrinfo) &&
6979             dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
6980             !dns_name_equal(&fctx->domain, &fctx->name) &&
6981             fix_mustbedelegationornxdomain(message, fctx)) {
6982                 char namebuf[DNS_NAME_FORMATSIZE];
6983                 char domainbuf[DNS_NAME_FORMATSIZE];
6984                 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6985                 char classbuf[64];
6986                 char typebuf[64];
6987
6988                 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
6989                 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
6990                 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
6991                 dns_rdataclass_format(fctx->res->rdclass, classbuf,
6992                                       sizeof(classbuf));
6993                 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6994                                     sizeof(addrbuf));
6995
6996                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
6997                              DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
6998                              "enforced delegation-only for '%s' (%s/%s/%s) "
6999                              "from %s",
7000                              domainbuf, namebuf, typebuf, classbuf, addrbuf);
7001         }
7002
7003         if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
7004                 checknames(message);
7005
7006         /*
7007          * Clear cache bits.
7008          */
7009         fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
7010
7011         /*
7012          * Did we get any answers?
7013          */
7014         if (message->counts[DNS_SECTION_ANSWER] > 0 &&
7015             (message->rcode == dns_rcode_noerror ||
7016              message->rcode == dns_rcode_nxdomain)) {
7017                 /*
7018                  * [normal case]
7019                  * We've got answers.  If it has an authoritative answer or an
7020                  * answer from a forwarder, we're done.
7021                  */
7022                 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
7023                     ISFORWARDER(query->addrinfo))
7024                         result = answer_response(fctx);
7025                 else if (iscname(fctx) &&
7026                          fctx->type != dns_rdatatype_any &&
7027                          fctx->type != dns_rdatatype_cname) {
7028                         /*
7029                          * A BIND8 server could return a non-authoritative
7030                          * answer when a CNAME is followed.  We should treat
7031                          * it as a valid answer.
7032                          */
7033                         result = answer_response(fctx);
7034                 } else if (fctx->type != dns_rdatatype_ns &&
7035                            !betterreferral(fctx)) {
7036                         /*
7037                          * Lame response !!!.
7038                          */
7039                         result = answer_response(fctx);
7040                 } else {
7041                         if (fctx->type == dns_rdatatype_ns) {
7042                                 /*
7043                                  * A BIND 8 server could incorrectly return a
7044                                  * non-authoritative answer to an NS query
7045                                  * instead of a referral. Since this answer
7046                                  * lacks the SIGs necessary to do DNSSEC
7047                                  * validation, we must invoke the following
7048                                  * special kludge to treat it as a referral.
7049                                  */
7050                                 result = noanswer_response(fctx, NULL,
7051                                                    LOOK_FOR_NS_IN_ANSWER);
7052                         } else {
7053                                 /*
7054                                  * Some other servers may still somehow include
7055                                  * an answer when it should return a referral
7056                                  * with an empty answer.  Check to see if we can
7057                                  * treat this as a referral by ignoring the
7058                                  * answer.  Further more, there may be an
7059                                  * implementation that moves A/AAAA glue records
7060                                  * to the answer section for that type of
7061                                  * delegation when the query is for that glue
7062                                  * record.  LOOK_FOR_GLUE_IN_ANSWER will handle
7063                                  * such a corner case.
7064                                  */
7065                                 result = noanswer_response(fctx, NULL,
7066                                                    LOOK_FOR_GLUE_IN_ANSWER);
7067                         }
7068                         if (result != DNS_R_DELEGATION) {
7069                                 /*
7070                                  * At this point, AA is not set, the response
7071                                  * is not a referral, and the server is not a
7072                                  * forwarder.  It is technically lame and it's
7073                                  * easier to treat it as such than to figure out
7074                                  * some more elaborate course of action.
7075                                  */
7076                                 broken_server = DNS_R_LAME;
7077                                 keep_trying = ISC_TRUE;
7078                                 goto done;
7079                         }
7080                         goto force_referral;
7081                 }
7082                 if (result != ISC_R_SUCCESS) {
7083                         if (result == DNS_R_FORMERR)
7084                                 keep_trying = ISC_TRUE;
7085                         goto done;
7086                 }
7087         } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
7088                    message->rcode == dns_rcode_noerror ||
7089                    message->rcode == dns_rcode_nxdomain) {
7090                 /*
7091                  * NXDOMAIN, NXRDATASET, or referral.
7092                  */
7093                 result = noanswer_response(fctx, NULL, 0);
7094                 if (result == DNS_R_CHASEDSSERVERS) {
7095                 } else if (result == DNS_R_DELEGATION) {
7096                 force_referral:
7097                         /*
7098                          * We don't have the answer, but we know a better
7099                          * place to look.
7100                          */
7101                         get_nameservers = ISC_TRUE;
7102                         keep_trying = ISC_TRUE;
7103                         /*
7104                          * We have a new set of name servers, and it
7105                          * has not experienced any restarts yet.
7106                          */
7107                         fctx->restarts = 0;
7108
7109                         /*
7110                          * Update local statistics counters collected for each
7111                          * new zone.
7112                          */
7113                         fctx->referrals++;
7114                         fctx->querysent = 0;
7115                         fctx->lamecount = 0;
7116                         fctx->neterr = 0;
7117                         fctx->badresp = 0;
7118                         fctx->adberr = 0;
7119
7120                         result = ISC_R_SUCCESS;
7121                 } else if (result != ISC_R_SUCCESS) {
7122                         /*
7123                          * Something has gone wrong.
7124                          */
7125                         if (result == DNS_R_FORMERR)
7126                                 keep_trying = ISC_TRUE;
7127                         goto done;
7128                 }
7129         } else {
7130                 /*
7131                  * The server is insane.
7132                  */
7133                 /* XXXRTH Log */
7134                 broken_server = DNS_R_UNEXPECTEDRCODE;
7135                 keep_trying = ISC_TRUE;
7136                 goto done;
7137         }
7138
7139         /*
7140          * Follow additional section data chains.
7141          */
7142         chase_additional(fctx);
7143
7144         /*
7145          * Cache the cacheable parts of the message.  This may also cause
7146          * work to be queued to the DNSSEC validator.
7147          */
7148         if (WANTCACHE(fctx)) {
7149                 result = cache_message(fctx, query->addrinfo, now);
7150                 if (result != ISC_R_SUCCESS)
7151                         goto done;
7152         }
7153
7154         /*
7155          * Ncache the negatively cacheable parts of the message.  This may
7156          * also cause work to be queued to the DNSSEC validator.
7157          */
7158         if (WANTNCACHE(fctx)) {
7159                 dns_rdatatype_t covers;
7160                 if (message->rcode == dns_rcode_nxdomain)
7161                         covers = dns_rdatatype_any;
7162                 else
7163                         covers = fctx->type;
7164
7165                 /*
7166                  * Cache any negative cache entries in the message.
7167                  */
7168                 result = ncache_message(fctx, query->addrinfo, covers, now);
7169         }
7170
7171  done:
7172         /*
7173          * Remember the query's addrinfo, in case we need to mark the
7174          * server as broken.
7175          */
7176         addrinfo = query->addrinfo;
7177
7178         /*
7179          * Cancel the query.
7180          *
7181          * XXXRTH  Don't cancel the query if waiting for validation?
7182          */
7183         fctx_cancelquery(&query, &devent, finish, no_response);
7184
7185         if (keep_trying) {
7186                 if (result == DNS_R_FORMERR)
7187                         broken_server = DNS_R_FORMERR;
7188                 if (broken_server != ISC_R_SUCCESS) {
7189                         /*
7190                          * Add this server to the list of bad servers for
7191                          * this fctx.
7192                          */
7193                         add_bad(fctx, addrinfo, broken_server, broken_type);
7194                 }
7195
7196                 if (get_nameservers) {
7197                         dns_name_t *name;
7198                         dns_fixedname_init(&foundname);
7199                         fname = dns_fixedname_name(&foundname);
7200                         if (result != ISC_R_SUCCESS) {
7201                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7202                                 return;
7203                         }
7204                         findoptions = 0;
7205                         if (dns_rdatatype_atparent(fctx->type))
7206                                 findoptions |= DNS_DBFIND_NOEXACT;
7207                         if ((options & DNS_FETCHOPT_UNSHARED) == 0)
7208                                 name = &fctx->name;
7209                         else
7210                                 name = &fctx->domain;
7211                         result = dns_view_findzonecut(fctx->res->view,
7212                                                       name, fname,
7213                                                       now, findoptions,
7214                                                       ISC_TRUE,
7215                                                       &fctx->nameservers,
7216                                                       NULL);
7217                         if (result != ISC_R_SUCCESS) {
7218                                 FCTXTRACE("couldn't find a zonecut");
7219                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7220                                 return;
7221                         }
7222                         if (!dns_name_issubdomain(fname, &fctx->domain)) {
7223                                 /*
7224                                  * The best nameservers are now above our
7225                                  * QDOMAIN.
7226                                  */
7227                                 FCTXTRACE("nameservers now above QDOMAIN");
7228                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7229                                 return;
7230                         }
7231                         dns_name_free(&fctx->domain, fctx->mctx);
7232                         dns_name_init(&fctx->domain, NULL);
7233                         result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
7234                         if (result != ISC_R_SUCCESS) {
7235                                 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7236                                 return;
7237                         }
7238                         fctx->ns_ttl = fctx->nameservers.ttl;
7239                         fctx->ns_ttl_ok = ISC_TRUE;
7240                         fctx_cancelqueries(fctx, ISC_TRUE);
7241                         fctx_cleanupfinds(fctx);
7242                         fctx_cleanupaltfinds(fctx);
7243                         fctx_cleanupforwaddrs(fctx);
7244                         fctx_cleanupaltaddrs(fctx);
7245                 }
7246                 /*
7247                  * Try again.
7248                  */
7249                 fctx_try(fctx, !get_nameservers, ISC_FALSE);
7250         } else if (resend) {
7251                 /*
7252                  * Resend (probably with changed options).
7253                  */
7254                 FCTXTRACE("resend");
7255                 inc_stats(fctx->res, dns_resstatscounter_retry);
7256                 result = fctx_query(fctx, addrinfo, options);
7257                 if (result != ISC_R_SUCCESS)
7258                         fctx_done(fctx, result, __LINE__);
7259         } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
7260                 /*
7261                  * All has gone well so far, but we are waiting for the
7262                  * DNSSEC validator to validate the answer.
7263                  */
7264                 FCTXTRACE("wait for validator");
7265                 fctx_cancelqueries(fctx, ISC_TRUE);
7266                 /*
7267                  * We must not retransmit while the validator is working;
7268                  * it has references to the current rmessage.
7269                  */
7270                 result = fctx_stopidletimer(fctx);
7271                 if (result != ISC_R_SUCCESS)
7272                         fctx_done(fctx, result, __LINE__);
7273         } else if (result == DNS_R_CHASEDSSERVERS) {
7274                 unsigned int n;
7275                 add_bad(fctx, addrinfo, result, broken_type);
7276                 fctx_cancelqueries(fctx, ISC_TRUE);
7277                 fctx_cleanupfinds(fctx);
7278                 fctx_cleanupforwaddrs(fctx);
7279
7280                 n = dns_name_countlabels(&fctx->name);
7281                 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
7282
7283                 FCTXTRACE("suspending DS lookup to find parent's NS records");
7284
7285                 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
7286                                                   dns_rdatatype_ns,
7287                                                   NULL, NULL, NULL, 0, task,
7288                                                   resume_dslookup, fctx,
7289                                                   &fctx->nsrrset, NULL,
7290                                                   &fctx->nsfetch);
7291                 if (result != ISC_R_SUCCESS)
7292                         fctx_done(fctx, result, __LINE__);
7293                 else {
7294                         LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7295                         fctx->references++;
7296                         UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7297                         result = fctx_stopidletimer(fctx);
7298                         if (result != ISC_R_SUCCESS)
7299                                 fctx_done(fctx, result, __LINE__);
7300                 }
7301         } else {
7302                 /*
7303                  * We're done.
7304                  */
7305                 fctx_done(fctx, result, __LINE__);
7306         }
7307 }
7308
7309
7310 /***
7311  *** Resolver Methods
7312  ***/
7313 static void
7314 destroy_badcache(dns_resolver_t *res) {
7315         dns_badcache_t *bad, *next;
7316         unsigned int i;
7317
7318         if (res->badcache != NULL) {
7319                 for (i = 0; i < res->badhash; i++)
7320                         for (bad = res->badcache[i]; bad != NULL;
7321                              bad = next) {
7322                                 next = bad->next;
7323                                 isc_mem_put(res->mctx, bad, sizeof(*bad) +
7324                                             bad->name.length);
7325                                 res->badcount--;
7326                         }
7327                 isc_mem_put(res->mctx, res->badcache,
7328                             sizeof(*res->badcache) * res->badhash);
7329                 res->badcache = NULL;
7330                 res->badhash = 0;
7331                 INSIST(res->badcount == 0);
7332         }
7333 }
7334
7335 static void
7336 destroy(dns_resolver_t *res) {
7337         unsigned int i;
7338         alternate_t *a;
7339
7340         REQUIRE(res->references == 0);
7341         REQUIRE(!res->priming);
7342         REQUIRE(res->primefetch == NULL);
7343
7344         RTRACE("destroy");
7345
7346         INSIST(res->nfctx == 0);
7347
7348         DESTROYLOCK(&res->primelock);
7349         DESTROYLOCK(&res->nlock);
7350         DESTROYLOCK(&res->lock);
7351         for (i = 0; i < res->nbuckets; i++) {
7352                 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
7353                 isc_task_shutdown(res->buckets[i].task);
7354                 isc_task_detach(&res->buckets[i].task);
7355                 DESTROYLOCK(&res->buckets[i].lock);
7356                 isc_mem_detach(&res->buckets[i].mctx);
7357         }
7358         isc_mem_put(res->mctx, res->buckets,
7359                     res->nbuckets * sizeof(fctxbucket_t));
7360         if (res->dispatchv4 != NULL)
7361                 dns_dispatch_detach(&res->dispatchv4);
7362         if (res->dispatchv6 != NULL)
7363                 dns_dispatch_detach(&res->dispatchv6);
7364         while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
7365                 ISC_LIST_UNLINK(res->alternates, a, link);
7366                 if (!a->isaddress)
7367                         dns_name_free(&a->_u._n.name, res->mctx);
7368                 isc_mem_put(res->mctx, a, sizeof(*a));
7369         }
7370         dns_resolver_reset_algorithms(res);
7371         destroy_badcache(res);
7372         dns_resolver_resetmustbesecure(res);
7373 #if USE_ALGLOCK
7374         isc_rwlock_destroy(&res->alglock);
7375 #endif
7376 #if USE_MBSLOCK
7377         isc_rwlock_destroy(&res->mbslock);
7378 #endif
7379         isc_timer_detach(&res->spillattimer);
7380         res->magic = 0;
7381         isc_mem_put(res->mctx, res, sizeof(*res));
7382 }
7383
7384 static void
7385 send_shutdown_events(dns_resolver_t *res) {
7386         isc_event_t *event, *next_event;
7387         isc_task_t *etask;
7388
7389         /*
7390          * Caller must be holding the resolver lock.
7391          */
7392
7393         for (event = ISC_LIST_HEAD(res->whenshutdown);
7394              event != NULL;
7395              event = next_event) {
7396                 next_event = ISC_LIST_NEXT(event, ev_link);
7397                 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
7398                 etask = event->ev_sender;
7399                 event->ev_sender = res;
7400                 isc_task_sendanddetach(&etask, &event);
7401         }
7402 }
7403
7404 static void
7405 empty_bucket(dns_resolver_t *res) {
7406         RTRACE("empty_bucket");
7407
7408         LOCK(&res->lock);
7409
7410         INSIST(res->activebuckets > 0);
7411         res->activebuckets--;
7412         if (res->activebuckets == 0)
7413                 send_shutdown_events(res);
7414
7415         UNLOCK(&res->lock);
7416 }
7417
7418 static void
7419 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
7420         dns_resolver_t *res = event->ev_arg;
7421         isc_result_t result;
7422         unsigned int count;
7423         isc_boolean_t logit = ISC_FALSE;
7424
7425         REQUIRE(VALID_RESOLVER(res));
7426
7427         UNUSED(task);
7428
7429         LOCK(&res->lock);
7430         INSIST(!res->exiting);
7431         if (res->spillat > res->spillatmin) {
7432                 res->spillat--;
7433                 logit = ISC_TRUE;
7434         }
7435         if (res->spillat <= res->spillatmin) {
7436                 result = isc_timer_reset(res->spillattimer,
7437                                          isc_timertype_inactive, NULL,
7438                                          NULL, ISC_TRUE);
7439                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7440         }
7441         count = res->spillat;
7442         UNLOCK(&res->lock);
7443         if (logit)
7444                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7445                               DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
7446                               "clients-per-query decreased to %u", count);
7447
7448         isc_event_free(&event);
7449 }
7450
7451 isc_result_t
7452 dns_resolver_create(dns_view_t *view,
7453                     isc_taskmgr_t *taskmgr, unsigned int ntasks,
7454                     isc_socketmgr_t *socketmgr,
7455                     isc_timermgr_t *timermgr,
7456                     unsigned int options,
7457                     dns_dispatchmgr_t *dispatchmgr,
7458                     dns_dispatch_t *dispatchv4,
7459                     dns_dispatch_t *dispatchv6,
7460                     dns_resolver_t **resp)
7461 {
7462         dns_resolver_t *res;
7463         isc_result_t result = ISC_R_SUCCESS;
7464         unsigned int i, buckets_created = 0;
7465         isc_task_t *task = NULL;
7466         char name[16];
7467         unsigned dispattr;
7468
7469         /*
7470          * Create a resolver.
7471          */
7472
7473         REQUIRE(DNS_VIEW_VALID(view));
7474         REQUIRE(ntasks > 0);
7475         REQUIRE(resp != NULL && *resp == NULL);
7476         REQUIRE(dispatchmgr != NULL);
7477         REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
7478
7479         res = isc_mem_get(view->mctx, sizeof(*res));
7480         if (res == NULL)
7481                 return (ISC_R_NOMEMORY);
7482         RTRACE("create");
7483         res->mctx = view->mctx;
7484         res->rdclass = view->rdclass;
7485         res->socketmgr = socketmgr;
7486         res->timermgr = timermgr;
7487         res->taskmgr = taskmgr;
7488         res->dispatchmgr = dispatchmgr;
7489         res->view = view;
7490         res->options = options;
7491         res->lame_ttl = 0;
7492         ISC_LIST_INIT(res->alternates);
7493         res->udpsize = RECV_BUFFER_SIZE;
7494         res->algorithms = NULL;
7495         res->badcache = NULL;
7496         res->badcount = 0;
7497         res->badhash = 0;
7498         res->badsweep = 0;
7499         res->mustbesecure = NULL;
7500         res->spillatmin = res->spillat = 10;
7501         res->spillatmax = 100;
7502         res->spillattimer = NULL;
7503         res->zero_no_soa_ttl = ISC_FALSE;
7504         res->query_timeout = DEFAULT_QUERY_TIMEOUT;
7505         res->ndisps = 0;
7506         res->nextdisp = 0; /* meaningless at this point, but init it */
7507         res->nbuckets = ntasks;
7508         res->activebuckets = ntasks;
7509         res->buckets = isc_mem_get(view->mctx,
7510                                    ntasks * sizeof(fctxbucket_t));
7511         if (res->buckets == NULL) {
7512                 result = ISC_R_NOMEMORY;
7513                 goto cleanup_res;
7514         }
7515         for (i = 0; i < ntasks; i++) {
7516                 result = isc_mutex_init(&res->buckets[i].lock);
7517                 if (result != ISC_R_SUCCESS)
7518                         goto cleanup_buckets;
7519                 res->buckets[i].task = NULL;
7520                 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
7521                 if (result != ISC_R_SUCCESS) {
7522                         DESTROYLOCK(&res->buckets[i].lock);
7523                         goto cleanup_buckets;
7524                 }
7525                 res->buckets[i].mctx = NULL;
7526                 snprintf(name, sizeof(name), "res%u", i);
7527 #ifdef ISC_PLATFORM_USETHREADS
7528                 /*
7529                  * Use a separate memory context for each bucket to reduce
7530                  * contention among multiple threads.  Do this only when
7531                  * enabling threads because it will be require more memory.
7532                  */
7533                 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
7534                 if (result != ISC_R_SUCCESS) {
7535                         isc_task_detach(&res->buckets[i].task);
7536                         DESTROYLOCK(&res->buckets[i].lock);
7537                         goto cleanup_buckets;
7538                 }
7539                 isc_mem_setname(res->buckets[i].mctx, name, NULL);
7540 #else
7541                 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
7542 #endif
7543                 isc_task_setname(res->buckets[i].task, name, res);
7544                 ISC_LIST_INIT(res->buckets[i].fctxs);
7545                 res->buckets[i].exiting = ISC_FALSE;
7546                 buckets_created++;
7547         }
7548
7549         res->dispatchv4 = NULL;
7550         if (dispatchv4 != NULL) {
7551                 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
7552                 dispattr = dns_dispatch_getattributes(dispatchv4);
7553                 res->exclusivev4 =
7554                         ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7555         }
7556
7557         res->dispatchv6 = NULL;
7558         if (dispatchv6 != NULL) {
7559                 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
7560                 dispattr = dns_dispatch_getattributes(dispatchv6);
7561                 res->exclusivev6 =
7562                         ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7563         }
7564
7565         res->references = 1;
7566         res->exiting = ISC_FALSE;
7567         res->frozen = ISC_FALSE;
7568         ISC_LIST_INIT(res->whenshutdown);
7569         res->priming = ISC_FALSE;
7570         res->primefetch = NULL;
7571         res->nfctx = 0;
7572
7573         result = isc_mutex_init(&res->lock);
7574         if (result != ISC_R_SUCCESS)
7575                 goto cleanup_dispatches;
7576
7577         result = isc_mutex_init(&res->nlock);
7578         if (result != ISC_R_SUCCESS)
7579                 goto cleanup_lock;
7580
7581         result = isc_mutex_init(&res->primelock);
7582         if (result != ISC_R_SUCCESS)
7583                 goto cleanup_nlock;
7584
7585         task = NULL;
7586         result = isc_task_create(taskmgr, 0, &task);
7587         if (result != ISC_R_SUCCESS)
7588                 goto cleanup_primelock;
7589
7590         result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
7591                                   task, spillattimer_countdown, res,
7592                                   &res->spillattimer);
7593         isc_task_detach(&task);
7594         if (result != ISC_R_SUCCESS)
7595                 goto cleanup_primelock;
7596
7597 #if USE_ALGLOCK
7598         result = isc_rwlock_init(&res->alglock, 0, 0);
7599         if (result != ISC_R_SUCCESS)
7600                 goto cleanup_spillattimer;
7601 #endif
7602 #if USE_MBSLOCK
7603         result = isc_rwlock_init(&res->mbslock, 0, 0);
7604         if (result != ISC_R_SUCCESS)
7605                 goto cleanup_alglock;
7606 #endif
7607
7608         res->magic = RES_MAGIC;
7609
7610         *resp = res;
7611
7612         return (ISC_R_SUCCESS);
7613
7614 #if USE_MBSLOCK
7615  cleanup_alglock:
7616 #if USE_ALGLOCK
7617         isc_rwlock_destroy(&res->alglock);
7618 #endif
7619 #endif
7620 #if USE_ALGLOCK || USE_MBSLOCK
7621  cleanup_spillattimer:
7622         isc_timer_detach(&res->spillattimer);
7623 #endif
7624
7625  cleanup_primelock:
7626         DESTROYLOCK(&res->primelock);
7627
7628  cleanup_nlock:
7629         DESTROYLOCK(&res->nlock);
7630
7631  cleanup_lock:
7632         DESTROYLOCK(&res->lock);
7633
7634  cleanup_dispatches:
7635         if (res->dispatchv6 != NULL)
7636                 dns_dispatch_detach(&res->dispatchv6);
7637         if (res->dispatchv4 != NULL)
7638                 dns_dispatch_detach(&res->dispatchv4);
7639
7640  cleanup_buckets:
7641         for (i = 0; i < buckets_created; i++) {
7642                 isc_mem_detach(&res->buckets[i].mctx);
7643                 DESTROYLOCK(&res->buckets[i].lock);
7644                 isc_task_shutdown(res->buckets[i].task);
7645                 isc_task_detach(&res->buckets[i].task);
7646         }
7647         isc_mem_put(view->mctx, res->buckets,
7648                     res->nbuckets * sizeof(fctxbucket_t));
7649
7650  cleanup_res:
7651         isc_mem_put(view->mctx, res, sizeof(*res));
7652
7653         return (result);
7654 }
7655
7656 #ifdef BIND9
7657 static void
7658 prime_done(isc_task_t *task, isc_event_t *event) {
7659         dns_resolver_t *res;
7660         dns_fetchevent_t *fevent;
7661         dns_fetch_t *fetch;
7662         dns_db_t *db = NULL;
7663
7664         REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
7665         fevent = (dns_fetchevent_t *)event;
7666         res = event->ev_arg;
7667         REQUIRE(VALID_RESOLVER(res));
7668
7669         UNUSED(task);
7670
7671         LOCK(&res->lock);
7672
7673         INSIST(res->priming);
7674         res->priming = ISC_FALSE;
7675         LOCK(&res->primelock);
7676         fetch = res->primefetch;
7677         res->primefetch = NULL;
7678         UNLOCK(&res->primelock);
7679
7680         UNLOCK(&res->lock);
7681
7682         if (fevent->result == ISC_R_SUCCESS &&
7683             res->view->cache != NULL && res->view->hints != NULL) {
7684                 dns_cache_attachdb(res->view->cache, &db);
7685                 dns_root_checkhints(res->view, res->view->hints, db);
7686                 dns_db_detach(&db);
7687         }
7688
7689         if (fevent->node != NULL)
7690                 dns_db_detachnode(fevent->db, &fevent->node);
7691         if (fevent->db != NULL)
7692                 dns_db_detach(&fevent->db);
7693         if (dns_rdataset_isassociated(fevent->rdataset))
7694                 dns_rdataset_disassociate(fevent->rdataset);
7695         INSIST(fevent->sigrdataset == NULL);
7696
7697         isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
7698
7699         isc_event_free(&event);
7700         dns_resolver_destroyfetch(&fetch);
7701 }
7702
7703 void
7704 dns_resolver_prime(dns_resolver_t *res) {
7705         isc_boolean_t want_priming = ISC_FALSE;
7706         dns_rdataset_t *rdataset;
7707         isc_result_t result;
7708
7709         REQUIRE(VALID_RESOLVER(res));
7710         REQUIRE(res->frozen);
7711
7712         RTRACE("dns_resolver_prime");
7713
7714         LOCK(&res->lock);
7715
7716         if (!res->exiting && !res->priming) {
7717                 INSIST(res->primefetch == NULL);
7718                 res->priming = ISC_TRUE;
7719                 want_priming = ISC_TRUE;
7720         }
7721
7722         UNLOCK(&res->lock);
7723
7724         if (want_priming) {
7725                 /*
7726                  * To avoid any possible recursive locking problems, we
7727                  * start the priming fetch like any other fetch, and holding
7728                  * no resolver locks.  No one else will try to start it
7729                  * because we're the ones who set res->priming to true.
7730                  * Any other callers of dns_resolver_prime() while we're
7731                  * running will see that res->priming is already true and
7732                  * do nothing.
7733                  */
7734                 RTRACE("priming");
7735                 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
7736                 if (rdataset == NULL) {
7737                         LOCK(&res->lock);
7738                         INSIST(res->priming);
7739                         INSIST(res->primefetch == NULL);
7740                         res->priming = ISC_FALSE;
7741                         UNLOCK(&res->lock);
7742                         return;
7743                 }
7744                 dns_rdataset_init(rdataset);
7745                 LOCK(&res->primelock);
7746                 result = dns_resolver_createfetch(res, dns_rootname,
7747                                                   dns_rdatatype_ns,
7748                                                   NULL, NULL, NULL, 0,
7749                                                   res->buckets[0].task,
7750                                                   prime_done,
7751                                                   res, rdataset, NULL,
7752                                                   &res->primefetch);
7753                 UNLOCK(&res->primelock);
7754                 if (result != ISC_R_SUCCESS) {
7755                         LOCK(&res->lock);
7756                         INSIST(res->priming);
7757                         res->priming = ISC_FALSE;
7758                         UNLOCK(&res->lock);
7759                 }
7760         }
7761 }
7762 #endif /* BIND9 */
7763
7764 void
7765 dns_resolver_freeze(dns_resolver_t *res) {
7766         /*
7767          * Freeze resolver.
7768          */
7769
7770         REQUIRE(VALID_RESOLVER(res));
7771
7772         res->frozen = ISC_TRUE;
7773 }
7774
7775 void
7776 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
7777         REQUIRE(VALID_RESOLVER(source));
7778         REQUIRE(targetp != NULL && *targetp == NULL);
7779
7780         RRTRACE(source, "attach");
7781         LOCK(&source->lock);
7782         REQUIRE(!source->exiting);
7783
7784         INSIST(source->references > 0);
7785         source->references++;
7786         INSIST(source->references != 0);
7787         UNLOCK(&source->lock);
7788
7789         *targetp = source;
7790 }
7791
7792 void
7793 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
7794                           isc_event_t **eventp)
7795 {
7796         isc_task_t *clone;
7797         isc_event_t *event;
7798
7799         REQUIRE(VALID_RESOLVER(res));
7800         REQUIRE(eventp != NULL);
7801
7802         event = *eventp;
7803         *eventp = NULL;
7804
7805         LOCK(&res->lock);
7806
7807         if (res->exiting && res->activebuckets == 0) {
7808                 /*
7809                  * We're already shutdown.  Send the event.
7810                  */
7811                 event->ev_sender = res;
7812                 isc_task_send(task, &event);
7813         } else {
7814                 clone = NULL;
7815                 isc_task_attach(task, &clone);
7816                 event->ev_sender = clone;
7817                 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
7818         }
7819
7820         UNLOCK(&res->lock);
7821 }
7822
7823 void
7824 dns_resolver_shutdown(dns_resolver_t *res) {
7825         unsigned int i;
7826         fetchctx_t *fctx;
7827         isc_socket_t *sock;
7828         isc_result_t result;
7829
7830         REQUIRE(VALID_RESOLVER(res));
7831
7832         RTRACE("shutdown");
7833
7834         LOCK(&res->lock);
7835
7836         if (!res->exiting) {
7837                 RTRACE("exiting");
7838                 res->exiting = ISC_TRUE;
7839
7840                 for (i = 0; i < res->nbuckets; i++) {
7841                         LOCK(&res->buckets[i].lock);
7842                         for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
7843                              fctx != NULL;
7844                              fctx = ISC_LIST_NEXT(fctx, link))
7845                                 fctx_shutdown(fctx);
7846                         if (res->dispatchv4 != NULL && !res->exclusivev4) {
7847                                 sock = dns_dispatch_getsocket(res->dispatchv4);
7848                                 isc_socket_cancel(sock, res->buckets[i].task,
7849                                                   ISC_SOCKCANCEL_ALL);
7850                         }
7851                         if (res->dispatchv6 != NULL && !res->exclusivev6) {
7852                                 sock = dns_dispatch_getsocket(res->dispatchv6);
7853                                 isc_socket_cancel(sock, res->buckets[i].task,
7854                                                   ISC_SOCKCANCEL_ALL);
7855                         }
7856                         res->buckets[i].exiting = ISC_TRUE;
7857                         if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
7858                                 INSIST(res->activebuckets > 0);
7859                                 res->activebuckets--;
7860                         }
7861                         UNLOCK(&res->buckets[i].lock);
7862                 }
7863                 if (res->activebuckets == 0)
7864                         send_shutdown_events(res);
7865                 result = isc_timer_reset(res->spillattimer,
7866                                          isc_timertype_inactive, NULL,
7867                                          NULL, ISC_TRUE);
7868                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7869         }
7870
7871         UNLOCK(&res->lock);
7872 }
7873
7874 void
7875 dns_resolver_detach(dns_resolver_t **resp) {
7876         dns_resolver_t *res;
7877         isc_boolean_t need_destroy = ISC_FALSE;
7878
7879         REQUIRE(resp != NULL);
7880         res = *resp;
7881         REQUIRE(VALID_RESOLVER(res));
7882
7883         RTRACE("detach");
7884
7885         LOCK(&res->lock);
7886
7887         INSIST(res->references > 0);
7888         res->references--;
7889         if (res->references == 0) {
7890                 INSIST(res->exiting && res->activebuckets == 0);
7891                 need_destroy = ISC_TRUE;
7892         }
7893
7894         UNLOCK(&res->lock);
7895
7896         if (need_destroy)
7897                 destroy(res);
7898
7899         *resp = NULL;
7900 }
7901
7902 static inline isc_boolean_t
7903 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
7904            unsigned int options)
7905 {
7906         /*
7907          * Don't match fetch contexts that are shutting down.
7908          */
7909         if (fctx->cloned || fctx->state == fetchstate_done ||
7910             ISC_LIST_EMPTY(fctx->events))
7911                 return (ISC_FALSE);
7912
7913         if (fctx->type != type || fctx->options != options)
7914                 return (ISC_FALSE);
7915         return (dns_name_equal(&fctx->name, name));
7916 }
7917
7918 static inline void
7919 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
7920         char namebuf[DNS_NAME_FORMATSIZE];
7921         char typebuf[DNS_RDATATYPE_FORMATSIZE];
7922         int level = ISC_LOG_DEBUG(1);
7923
7924         if (! isc_log_wouldlog(dns_lctx, level))
7925                 return;
7926
7927         dns_name_format(name, namebuf, sizeof(namebuf));
7928         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
7929
7930         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7931                       DNS_LOGMODULE_RESOLVER, level,
7932                       "createfetch: %s %s", namebuf, typebuf);
7933 }
7934
7935 isc_result_t
7936 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
7937                          dns_rdatatype_t type,
7938                          dns_name_t *domain, dns_rdataset_t *nameservers,
7939                          dns_forwarders_t *forwarders,
7940                          unsigned int options, isc_task_t *task,
7941                          isc_taskaction_t action, void *arg,
7942                          dns_rdataset_t *rdataset,
7943                          dns_rdataset_t *sigrdataset,
7944                          dns_fetch_t **fetchp)
7945 {
7946         return (dns_resolver_createfetch2(res, name, type, domain,
7947                                           nameservers, forwarders, NULL, 0,
7948                                           options, task, action, arg,
7949                                           rdataset, sigrdataset, fetchp));
7950 }
7951
7952 isc_result_t
7953 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
7954                           dns_rdatatype_t type,
7955                           dns_name_t *domain, dns_rdataset_t *nameservers,
7956                           dns_forwarders_t *forwarders,
7957                           isc_sockaddr_t *client, dns_messageid_t id,
7958                           unsigned int options, isc_task_t *task,
7959                           isc_taskaction_t action, void *arg,
7960                           dns_rdataset_t *rdataset,
7961                           dns_rdataset_t *sigrdataset,
7962                           dns_fetch_t **fetchp)
7963 {
7964         dns_fetch_t *fetch;
7965         fetchctx_t *fctx = NULL;
7966         isc_result_t result = ISC_R_SUCCESS;
7967         unsigned int bucketnum;
7968         isc_boolean_t new_fctx = ISC_FALSE;
7969         isc_event_t *event;
7970         unsigned int count = 0;
7971         unsigned int spillat;
7972         unsigned int spillatmin;
7973         isc_boolean_t destroy = ISC_FALSE;
7974
7975         UNUSED(forwarders);
7976
7977         REQUIRE(VALID_RESOLVER(res));
7978         REQUIRE(res->frozen);
7979         /* XXXRTH  Check for meta type */
7980         if (domain != NULL) {
7981                 REQUIRE(DNS_RDATASET_VALID(nameservers));
7982                 REQUIRE(nameservers->type == dns_rdatatype_ns);
7983         } else
7984                 REQUIRE(nameservers == NULL);
7985         REQUIRE(forwarders == NULL);
7986         REQUIRE(!dns_rdataset_isassociated(rdataset));
7987         REQUIRE(sigrdataset == NULL ||
7988                 !dns_rdataset_isassociated(sigrdataset));
7989         REQUIRE(fetchp != NULL && *fetchp == NULL);
7990
7991         log_fetch(name, type);
7992
7993         /*
7994          * XXXRTH  use a mempool?
7995          */
7996         fetch = isc_mem_get(res->mctx, sizeof(*fetch));
7997         if (fetch == NULL)
7998                 return (ISC_R_NOMEMORY);
7999
8000         bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
8001
8002         LOCK(&res->lock);
8003         spillat = res->spillat;
8004         spillatmin = res->spillatmin;
8005         UNLOCK(&res->lock);
8006         LOCK(&res->buckets[bucketnum].lock);
8007
8008         if (res->buckets[bucketnum].exiting) {
8009                 result = ISC_R_SHUTTINGDOWN;
8010                 goto unlock;
8011         }
8012
8013         if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
8014                 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
8015                      fctx != NULL;
8016                      fctx = ISC_LIST_NEXT(fctx, link)) {
8017                         if (fctx_match(fctx, name, type, options))
8018                                 break;
8019                 }
8020         }
8021
8022         /*
8023          * Is this a duplicate?
8024          */
8025         if (fctx != NULL && client != NULL) {
8026                 dns_fetchevent_t *fevent;
8027                 for (fevent = ISC_LIST_HEAD(fctx->events);
8028                      fevent != NULL;
8029                      fevent = ISC_LIST_NEXT(fevent, ev_link)) {
8030                         if (fevent->client != NULL && fevent->id == id &&
8031                             isc_sockaddr_equal(fevent->client, client)) {
8032                                 result = DNS_R_DUPLICATE;
8033                                 goto unlock;
8034                         }
8035                         count++;
8036                 }
8037         }
8038         if (count >= spillatmin && spillatmin != 0) {
8039                 INSIST(fctx != NULL);
8040                 if (count >= spillat)
8041                         fctx->spilled = ISC_TRUE;
8042                 if (fctx->spilled) {
8043                         result = DNS_R_DROP;
8044                         goto unlock;
8045                 }
8046         }
8047
8048         if (fctx == NULL) {
8049                 result = fctx_create(res, name, type, domain, nameservers,
8050                                      options, bucketnum, &fctx);
8051                 if (result != ISC_R_SUCCESS)
8052                         goto unlock;
8053                 new_fctx = ISC_TRUE;
8054         }
8055
8056         result = fctx_join(fctx, task, client, id, action, arg,
8057                            rdataset, sigrdataset, fetch);
8058         if (new_fctx) {
8059                 if (result == ISC_R_SUCCESS) {
8060                         /*
8061                          * Launch this fctx.
8062                          */
8063                         event = &fctx->control_event;
8064                         ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
8065                                        DNS_EVENT_FETCHCONTROL,
8066                                        fctx_start, fctx, NULL,
8067                                        NULL, NULL);
8068                         isc_task_send(res->buckets[bucketnum].task, &event);
8069                 } else {
8070                         /*
8071                          * We don't care about the result of fctx_unlink()
8072                          * since we know we're not exiting.
8073                          */
8074                         (void)fctx_unlink(fctx);
8075                         destroy = ISC_TRUE;
8076                 }
8077         }
8078
8079  unlock:
8080         UNLOCK(&res->buckets[bucketnum].lock);
8081
8082         if (destroy)
8083                 fctx_destroy(fctx);
8084
8085         if (result == ISC_R_SUCCESS) {
8086                 FTRACE("created");
8087                 *fetchp = fetch;
8088         } else
8089                 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
8090
8091         return (result);
8092 }
8093
8094 void
8095 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
8096         fetchctx_t *fctx;
8097         dns_resolver_t *res;
8098         dns_fetchevent_t *event, *next_event;
8099         isc_task_t *etask;
8100
8101         REQUIRE(DNS_FETCH_VALID(fetch));
8102         fctx = fetch->private;
8103         REQUIRE(VALID_FCTX(fctx));
8104         res = fctx->res;
8105
8106         FTRACE("cancelfetch");
8107
8108         LOCK(&res->buckets[fctx->bucketnum].lock);
8109
8110         /*
8111          * Find the completion event for this fetch (as opposed
8112          * to those for other fetches that have joined the same
8113          * fctx) and send it with result = ISC_R_CANCELED.
8114          */
8115         event = NULL;
8116         if (fctx->state != fetchstate_done) {
8117                 for (event = ISC_LIST_HEAD(fctx->events);
8118                      event != NULL;
8119                      event = next_event) {
8120                         next_event = ISC_LIST_NEXT(event, ev_link);
8121                         if (event->fetch == fetch) {
8122                                 ISC_LIST_UNLINK(fctx->events, event, ev_link);
8123                                 break;
8124                         }
8125                 }
8126         }
8127         if (event != NULL) {
8128                 etask = event->ev_sender;
8129                 event->ev_sender = fctx;
8130                 event->result = ISC_R_CANCELED;
8131                 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
8132         }
8133         /*
8134          * The fctx continues running even if no fetches remain;
8135          * the answer is still cached.
8136          */
8137
8138         UNLOCK(&res->buckets[fctx->bucketnum].lock);
8139 }
8140
8141 void
8142 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
8143         dns_fetch_t *fetch;
8144         dns_resolver_t *res;
8145         dns_fetchevent_t *event, *next_event;
8146         fetchctx_t *fctx;
8147         unsigned int bucketnum;
8148         isc_boolean_t bucket_empty;
8149
8150         REQUIRE(fetchp != NULL);
8151         fetch = *fetchp;
8152         REQUIRE(DNS_FETCH_VALID(fetch));
8153         fctx = fetch->private;
8154         REQUIRE(VALID_FCTX(fctx));
8155         res = fctx->res;
8156
8157         FTRACE("destroyfetch");
8158
8159         bucketnum = fctx->bucketnum;
8160         LOCK(&res->buckets[bucketnum].lock);
8161
8162         /*
8163          * Sanity check: the caller should have gotten its event before
8164          * trying to destroy the fetch.
8165          */
8166         event = NULL;
8167         if (fctx->state != fetchstate_done) {
8168                 for (event = ISC_LIST_HEAD(fctx->events);
8169                      event != NULL;
8170                      event = next_event) {
8171                         next_event = ISC_LIST_NEXT(event, ev_link);
8172                         RUNTIME_CHECK(event->fetch != fetch);
8173                 }
8174         }
8175
8176         bucket_empty = fctx_decreference(fctx);
8177
8178         UNLOCK(&res->buckets[bucketnum].lock);
8179
8180         isc_mem_put(res->mctx, fetch, sizeof(*fetch));
8181         *fetchp = NULL;
8182
8183         if (bucket_empty)
8184                 empty_bucket(res);
8185 }
8186
8187 void
8188 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
8189                       isc_logcategory_t *category, isc_logmodule_t *module,
8190                       int level, isc_boolean_t duplicateok)
8191 {
8192         fetchctx_t *fctx;
8193         dns_resolver_t *res;
8194         char domainbuf[DNS_NAME_FORMATSIZE];
8195
8196         REQUIRE(DNS_FETCH_VALID(fetch));
8197         fctx = fetch->private;
8198         REQUIRE(VALID_FCTX(fctx));
8199         res = fctx->res;
8200
8201         LOCK(&res->buckets[fctx->bucketnum].lock);
8202
8203         INSIST(fctx->exitline >= 0);
8204         if (!fctx->logged || duplicateok) {
8205                 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
8206                 isc_log_write(lctx, category, module, level,
8207                               "fetch completed at %s:%d for %s in "
8208                               "%" ISC_PRINT_QUADFORMAT "u."
8209                               "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
8210                               "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
8211                               "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
8212                               "adberr:%u,findfail:%u,valfail:%u]",
8213                               __FILE__, fctx->exitline, fctx->info,
8214                               fctx->duration / 1000000,
8215                               fctx->duration % 1000000,
8216                               isc_result_totext(fctx->result),
8217                               isc_result_totext(fctx->vresult), domainbuf,
8218                               fctx->referrals, fctx->restarts,
8219                               fctx->querysent, fctx->timeouts, fctx->lamecount,
8220                               fctx->neterr, fctx->badresp, fctx->adberr,
8221                               fctx->findfail, fctx->valfail);
8222                 fctx->logged = ISC_TRUE;
8223         }
8224
8225         UNLOCK(&res->buckets[fctx->bucketnum].lock);
8226 }
8227
8228 dns_dispatchmgr_t *
8229 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
8230         REQUIRE(VALID_RESOLVER(resolver));
8231         return (resolver->dispatchmgr);
8232 }
8233
8234 dns_dispatch_t *
8235 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
8236         REQUIRE(VALID_RESOLVER(resolver));
8237         return (resolver->dispatchv4);
8238 }
8239
8240 dns_dispatch_t *
8241 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
8242         REQUIRE(VALID_RESOLVER(resolver));
8243         return (resolver->dispatchv6);
8244 }
8245
8246 isc_socketmgr_t *
8247 dns_resolver_socketmgr(dns_resolver_t *resolver) {
8248         REQUIRE(VALID_RESOLVER(resolver));
8249         return (resolver->socketmgr);
8250 }
8251
8252 isc_taskmgr_t *
8253 dns_resolver_taskmgr(dns_resolver_t *resolver) {
8254         REQUIRE(VALID_RESOLVER(resolver));
8255         return (resolver->taskmgr);
8256 }
8257
8258 isc_uint32_t
8259 dns_resolver_getlamettl(dns_resolver_t *resolver) {
8260         REQUIRE(VALID_RESOLVER(resolver));
8261         return (resolver->lame_ttl);
8262 }
8263
8264 void
8265 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
8266         REQUIRE(VALID_RESOLVER(resolver));
8267         resolver->lame_ttl = lame_ttl;
8268 }
8269
8270 unsigned int
8271 dns_resolver_nrunning(dns_resolver_t *resolver) {
8272         unsigned int n;
8273         LOCK(&resolver->nlock);
8274         n = resolver->nfctx;
8275         UNLOCK(&resolver->nlock);
8276         return (n);
8277 }
8278
8279 isc_result_t
8280 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
8281                           dns_name_t *name, in_port_t port) {
8282         alternate_t *a;
8283         isc_result_t result;
8284
8285         REQUIRE(VALID_RESOLVER(resolver));
8286         REQUIRE(!resolver->frozen);
8287         REQUIRE((alt == NULL) ^ (name == NULL));
8288
8289         a = isc_mem_get(resolver->mctx, sizeof(*a));
8290         if (a == NULL)
8291                 return (ISC_R_NOMEMORY);
8292         if (alt != NULL) {
8293                 a->isaddress = ISC_TRUE;
8294                 a->_u.addr = *alt;
8295         } else {
8296                 a->isaddress = ISC_FALSE;
8297                 a->_u._n.port = port;
8298                 dns_name_init(&a->_u._n.name, NULL);
8299                 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
8300                 if (result != ISC_R_SUCCESS) {
8301                         isc_mem_put(resolver->mctx, a, sizeof(*a));
8302                         return (result);
8303                 }
8304         }
8305         ISC_LINK_INIT(a, link);
8306         ISC_LIST_APPEND(resolver->alternates, a, link);
8307
8308         return (ISC_R_SUCCESS);
8309 }
8310
8311 void
8312 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
8313         REQUIRE(VALID_RESOLVER(resolver));
8314         resolver->udpsize = udpsize;
8315 }
8316
8317 isc_uint16_t
8318 dns_resolver_getudpsize(dns_resolver_t *resolver) {
8319         REQUIRE(VALID_RESOLVER(resolver));
8320         return (resolver->udpsize);
8321 }
8322
8323 void
8324 dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
8325         unsigned int i;
8326         dns_badcache_t *bad, *prev, *next;
8327
8328         REQUIRE(VALID_RESOLVER(resolver));
8329
8330         LOCK(&resolver->lock);
8331         if (resolver->badcache == NULL)
8332                 goto unlock;
8333
8334         if (name != NULL) {
8335                 isc_time_t now;
8336                 isc_result_t result;
8337                 result = isc_time_now(&now);
8338                 if (result != ISC_R_SUCCESS)
8339                         isc_time_settoepoch(&now);
8340                 i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
8341                 prev = NULL;
8342                 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8343                         int n;
8344                         next = bad->next;
8345                         n = isc_time_compare(&bad->expire, &now);
8346                         if (n < 0 || dns_name_equal(name, &bad->name)) {
8347                                 if (prev == NULL)
8348                                         resolver->badcache[i] = bad->next;
8349                                 else
8350                                         prev->next = bad->next;
8351                                 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8352                                             bad->name.length);
8353                                 resolver->badcount--;
8354                         } else
8355                                 prev = bad;
8356                 }
8357         } else
8358                 destroy_badcache(resolver);
8359
8360  unlock:
8361         UNLOCK(&resolver->lock);
8362
8363 }
8364
8365 static void
8366 resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
8367         unsigned int newsize;
8368         dns_badcache_t **new, *bad, *next;
8369         unsigned int i;
8370
8371         if (grow)
8372                 newsize = resolver->badhash * 2 + 1;
8373         else
8374                 newsize = (resolver->badhash - 1) / 2;
8375
8376         new = isc_mem_get(resolver->mctx,
8377                           sizeof(*resolver->badcache) * newsize);
8378         if (new == NULL)
8379                 return;
8380         memset(new, 0, sizeof(*resolver->badcache) * newsize);
8381         for (i = 0; i < resolver->badhash; i++) {
8382                 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8383                         next = bad->next;
8384                         if (isc_time_compare(&bad->expire, now) < 0) {
8385                                 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8386                                             bad->name.length);
8387                                 resolver->badcount--;
8388                         } else {
8389                                 bad->next = new[bad->hashval % newsize];
8390                                 new[bad->hashval % newsize] = bad;
8391                         }
8392                 }
8393         }
8394         isc_mem_put(resolver->mctx, resolver->badcache,
8395                     sizeof(*resolver->badcache) * resolver->badhash);
8396         resolver->badhash = newsize;
8397         resolver->badcache = new;
8398 }
8399
8400 void
8401 dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
8402                          dns_rdatatype_t type, isc_time_t *expire)
8403 {
8404         isc_time_t now;
8405         isc_result_t result = ISC_R_SUCCESS;
8406         unsigned int i, hashval;
8407         dns_badcache_t *bad, *prev, *next;
8408
8409         REQUIRE(VALID_RESOLVER(resolver));
8410
8411         LOCK(&resolver->lock);
8412         if (resolver->badcache == NULL) {
8413                 resolver->badcache = isc_mem_get(resolver->mctx,
8414                                                  sizeof(*resolver->badcache) *
8415                                                  DNS_BADCACHE_SIZE);
8416                 if (resolver->badcache == NULL)
8417                         goto cleanup;
8418                 resolver->badhash = DNS_BADCACHE_SIZE;
8419                 memset(resolver->badcache, 0, sizeof(*resolver->badcache) *
8420                        resolver->badhash);
8421         }
8422
8423         result = isc_time_now(&now);
8424         if (result != ISC_R_SUCCESS)
8425                 isc_time_settoepoch(&now);
8426         hashval = dns_name_hash(name, ISC_FALSE);
8427         i = hashval % resolver->badhash;
8428         prev = NULL;
8429         for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8430                 next = bad->next;
8431                 if (bad->type == type && dns_name_equal(name, &bad->name))
8432                         break;
8433                 if (isc_time_compare(&bad->expire, &now) < 0) {
8434                         if (prev == NULL)
8435                                 resolver->badcache[i] = bad->next;
8436                         else
8437                                 prev->next = bad->next;
8438                         isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8439                                     bad->name.length);
8440                         resolver->badcount--;
8441                 } else
8442                         prev = bad;
8443         }
8444         if (bad == NULL) {
8445                 isc_buffer_t buffer;
8446                 bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
8447                 if (bad == NULL)
8448                         goto cleanup;
8449                 bad->type = type;
8450                 bad->hashval = hashval;
8451                 isc_buffer_init(&buffer, bad + 1, name->length);
8452                 dns_name_init(&bad->name, NULL);
8453                 dns_name_copy(name, &bad->name, &buffer);
8454                 bad->next = resolver->badcache[i];
8455                 resolver->badcache[i] = bad;
8456                 resolver->badcount++;
8457                 if (resolver->badcount > resolver->badhash * 8)
8458                         resizehash(resolver, &now, ISC_TRUE);
8459                 if (resolver->badcount < resolver->badhash * 2 &&
8460                     resolver->badhash > DNS_BADCACHE_SIZE)
8461                         resizehash(resolver, &now, ISC_FALSE);
8462         }
8463         bad->expire = *expire;
8464  cleanup:
8465         UNLOCK(&resolver->lock);
8466 }
8467
8468 isc_boolean_t
8469 dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
8470                          dns_rdatatype_t type, isc_time_t *now)
8471 {
8472         dns_badcache_t *bad, *prev, *next;
8473         isc_boolean_t answer = ISC_FALSE;
8474         unsigned int i;
8475
8476         REQUIRE(VALID_RESOLVER(resolver));
8477
8478         LOCK(&resolver->lock);
8479         if (resolver->badcache == NULL)
8480                 goto unlock;
8481
8482         i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
8483         prev = NULL;
8484         for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8485                 next = bad->next;
8486                 /*
8487                  * Search the hash list. Clean out expired records as we go.
8488                  */
8489                 if (isc_time_compare(&bad->expire, now) < 0) {
8490                         if (prev != NULL)
8491                                 prev->next = bad->next;
8492                         else
8493                                 resolver->badcache[i] = bad->next;
8494                         isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8495                                     bad->name.length);
8496                         resolver->badcount--;
8497                         continue;
8498                 }
8499                 if (bad->type == type && dns_name_equal(name, &bad->name)) {
8500                         answer = ISC_TRUE;
8501                         break;
8502                 }
8503                 prev = bad;
8504         }
8505
8506         /*
8507          * Slow sweep to clean out stale records.
8508          */
8509         i = resolver->badsweep++ % resolver->badhash;
8510         bad = resolver->badcache[i];
8511         if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) {
8512                 resolver->badcache[i] = bad->next;
8513                 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8514                             bad->name.length);
8515                 resolver->badcount--;
8516         }
8517
8518  unlock:
8519         UNLOCK(&resolver->lock);
8520         return (answer);
8521 }
8522
8523 void
8524 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
8525         char namebuf[DNS_NAME_FORMATSIZE];
8526         char typebuf[DNS_RDATATYPE_FORMATSIZE];
8527         dns_badcache_t *bad, *next, *prev;
8528         isc_time_t now;
8529         unsigned int i;
8530         isc_uint64_t t;
8531
8532         LOCK(&resolver->lock);
8533         fprintf(fp, ";\n; Bad cache\n;\n");
8534
8535         if (resolver->badcache == NULL)
8536                 goto unlock;
8537
8538         TIME_NOW(&now);
8539         for (i = 0; i < resolver->badhash; i++) {
8540                 prev = NULL;
8541                 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8542                         next = bad->next;
8543                         if (isc_time_compare(&bad->expire, &now) < 0) {
8544                                 if (prev != NULL)
8545                                         prev->next = bad->next;
8546                                 else
8547                                         resolver->badcache[i] = bad->next;
8548                                 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8549                                             bad->name.length);
8550                                 resolver->badcount--;
8551                                 continue;
8552                         }
8553                         prev = bad;
8554                         dns_name_format(&bad->name, namebuf, sizeof(namebuf));
8555                         dns_rdatatype_format(bad->type, typebuf,
8556                                              sizeof(typebuf));
8557                         t = isc_time_microdiff(&bad->expire, &now);
8558                         t /= 1000;
8559                         fprintf(fp, "; %s/%s [ttl "
8560                                 "%" ISC_PLATFORM_QUADFORMAT "u]\n",
8561                                 namebuf, typebuf, t);
8562                 }
8563         }
8564
8565  unlock:
8566         UNLOCK(&resolver->lock);
8567 }
8568
8569 static void
8570 free_algorithm(void *node, void *arg) {
8571         unsigned char *algorithms = node;
8572         isc_mem_t *mctx = arg;
8573
8574         isc_mem_put(mctx, algorithms, *algorithms);
8575 }
8576
8577 void
8578 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
8579
8580         REQUIRE(VALID_RESOLVER(resolver));
8581
8582 #if USE_ALGLOCK
8583         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8584 #endif
8585         if (resolver->algorithms != NULL)
8586                 dns_rbt_destroy(&resolver->algorithms);
8587 #if USE_ALGLOCK
8588         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8589 #endif
8590 }
8591
8592 isc_result_t
8593 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
8594                                unsigned int alg)
8595 {
8596         unsigned int len, mask;
8597         unsigned char *new;
8598         unsigned char *algorithms;
8599         isc_result_t result;
8600         dns_rbtnode_t *node = NULL;
8601
8602         REQUIRE(VALID_RESOLVER(resolver));
8603         if (alg > 255)
8604                 return (ISC_R_RANGE);
8605
8606 #if USE_ALGLOCK
8607         RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8608 #endif
8609         if (resolver->algorithms == NULL) {
8610                 result = dns_rbt_create(resolver->mctx, free_algorithm,
8611                                         resolver->mctx, &resolver->algorithms);
8612                 if (result != ISC_R_SUCCESS)
8613                         goto cleanup;
8614         }
8615
8616         len = alg/8 + 2;
8617         mask = 1 << (alg%8);
8618
8619         result = dns_rbt_addnode(resolver->algorithms, name, &node);
8620
8621         if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
8622                 algorithms = node->data;
8623                 if (algorithms == NULL || len > *algorithms) {
8624                         new = isc_mem_get(resolver->mctx, len);
8625                         if (new == NULL) {
8626                                 result = ISC_R_NOMEMORY;
8627                                 goto cleanup;
8628                         }
8629                         memset(new, 0, len);
8630                         if (algorithms != NULL)
8631                                 memcpy(new, algorithms, *algorithms);
8632                         new[len-1] |= mask;
8633                         *new = len;
8634                         node->data = new;
8635                         if (algorithms != NULL)
8636                                 isc_mem_put(resolver->mctx, algorithms,
8637                                             *algorithms);
8638                 } else
8639                         algorithms[len-1] |= mask;
8640         }
8641         result = ISC_R_SUCCESS;
8642  cleanup:
8643 #if USE_ALGLOCK
8644         RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8645 #endif
8646         return (result);
8647 }
8648
8649 isc_boolean_t
8650 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
8651                                  unsigned int alg)
8652 {
8653         unsigned int len, mask;
8654         unsigned char *algorithms;
8655         void *data = NULL;
8656         isc_result_t result;
8657         isc_boolean_t found = ISC_FALSE;
8658
8659         REQUIRE(VALID_RESOLVER(resolver));
8660
8661 #if USE_ALGLOCK
8662         RWLOCK(&resolver->alglock, isc_rwlocktype_read);
8663 #endif
8664         if (resolver->algorithms == NULL)
8665                 goto unlock;
8666         result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
8667         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
8668                 len = alg/8 + 2;
8669                 mask = 1 << (alg%8);
8670                 algorithms = data;
8671                 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
8672                         found = ISC_TRUE;
8673         }
8674  unlock:
8675 #if USE_ALGLOCK
8676         RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
8677 #endif
8678         if (found)
8679                 return (ISC_FALSE);
8680         return (dst_algorithm_supported(alg));
8681 }
8682
8683 isc_boolean_t
8684 dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
8685
8686         UNUSED(resolver);
8687         return (dns_ds_digest_supported(digest));
8688 }
8689
8690 void
8691 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
8692
8693         REQUIRE(VALID_RESOLVER(resolver));
8694
8695 #if USE_MBSLOCK
8696         RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8697 #endif
8698         if (resolver->mustbesecure != NULL)
8699                 dns_rbt_destroy(&resolver->mustbesecure);
8700 #if USE_MBSLOCK
8701         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8702 #endif
8703 }
8704
8705 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
8706
8707 isc_result_t
8708 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
8709                              isc_boolean_t value)
8710 {
8711         isc_result_t result;
8712
8713         REQUIRE(VALID_RESOLVER(resolver));
8714
8715 #if USE_MBSLOCK
8716         RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8717 #endif
8718         if (resolver->mustbesecure == NULL) {
8719                 result = dns_rbt_create(resolver->mctx, NULL, NULL,
8720                                         &resolver->mustbesecure);
8721                 if (result != ISC_R_SUCCESS)
8722                         goto cleanup;
8723         }
8724         result = dns_rbt_addname(resolver->mustbesecure, name,
8725                                  value ? &yes : &no);
8726  cleanup:
8727 #if USE_MBSLOCK
8728         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8729 #endif
8730         return (result);
8731 }
8732
8733 isc_boolean_t
8734 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
8735         void *data = NULL;
8736         isc_boolean_t value = ISC_FALSE;
8737         isc_result_t result;
8738
8739         REQUIRE(VALID_RESOLVER(resolver));
8740
8741 #if USE_MBSLOCK
8742         RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
8743 #endif
8744         if (resolver->mustbesecure == NULL)
8745                 goto unlock;
8746         result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
8747         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
8748                 value = *(isc_boolean_t*)data;
8749  unlock:
8750 #if USE_MBSLOCK
8751         RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
8752 #endif
8753         return (value);
8754 }
8755
8756 void
8757 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
8758                                 isc_uint32_t *min, isc_uint32_t *max)
8759 {
8760         REQUIRE(VALID_RESOLVER(resolver));
8761
8762         LOCK(&resolver->lock);
8763         if (cur != NULL)
8764                 *cur = resolver->spillat;
8765         if (min != NULL)
8766                 *min = resolver->spillatmin;
8767         if (max != NULL)
8768                 *max = resolver->spillatmax;
8769         UNLOCK(&resolver->lock);
8770 }
8771
8772 void
8773 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
8774                                 isc_uint32_t max)
8775 {
8776         REQUIRE(VALID_RESOLVER(resolver));
8777
8778         LOCK(&resolver->lock);
8779         resolver->spillatmin = resolver->spillat = min;
8780         resolver->spillatmax = max;
8781         UNLOCK(&resolver->lock);
8782 }
8783
8784 isc_boolean_t
8785 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
8786         REQUIRE(VALID_RESOLVER(resolver));
8787
8788         return (resolver->zero_no_soa_ttl);
8789 }
8790
8791 void
8792 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
8793         REQUIRE(VALID_RESOLVER(resolver));
8794
8795         resolver->zero_no_soa_ttl = state;
8796 }
8797
8798 unsigned int
8799 dns_resolver_getoptions(dns_resolver_t *resolver) {
8800         REQUIRE(VALID_RESOLVER(resolver));
8801
8802         return (resolver->options);
8803 }
8804
8805 unsigned int
8806 dns_resolver_gettimeout(dns_resolver_t *resolver) {
8807         REQUIRE(VALID_RESOLVER(resolver));
8808
8809         return (resolver->query_timeout);
8810 }
8811
8812 void
8813 dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
8814         REQUIRE(VALID_RESOLVER(resolver));
8815
8816         if (seconds == 0)
8817                 seconds = DEFAULT_QUERY_TIMEOUT;
8818         if (seconds > MAXIMUM_QUERY_TIMEOUT)
8819                 seconds = MAXIMUM_QUERY_TIMEOUT;
8820
8821         resolver->query_timeout = seconds;
8822 }