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