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