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