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