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