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