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