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