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