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