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