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