Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / resolver.c
blob089da68adfadd822b69c1b609eaaa257944b2ca3
1 /* $NetBSD: resolver.c,v 1.1.1.4 2009/12/26 22:24:56 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: resolver.c,v 1.413 2009/11/18 23:48:07 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <isc/platform.h>
27 #include <isc/print.h>
28 #include <isc/string.h>
29 #include <isc/random.h>
30 #include <isc/task.h>
31 #include <isc/stats.h>
32 #include <isc/timer.h>
33 #include <isc/util.h>
35 #include <dns/acl.h>
36 #include <dns/adb.h>
37 #include <dns/cache.h>
38 #include <dns/db.h>
39 #include <dns/dispatch.h>
40 #include <dns/ds.h>
41 #include <dns/events.h>
42 #include <dns/forward.h>
43 #include <dns/keytable.h>
44 #include <dns/log.h>
45 #include <dns/message.h>
46 #include <dns/ncache.h>
47 #include <dns/opcode.h>
48 #include <dns/peer.h>
49 #include <dns/rbt.h>
50 #include <dns/rcode.h>
51 #include <dns/rdata.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdatalist.h>
54 #include <dns/rdataset.h>
55 #include <dns/rdatastruct.h>
56 #include <dns/rdatatype.h>
57 #include <dns/resolver.h>
58 #include <dns/result.h>
59 #include <dns/rootns.h>
60 #include <dns/stats.h>
61 #include <dns/tsig.h>
62 #include <dns/validator.h>
64 #define DNS_RESOLVER_TRACE
65 #ifdef DNS_RESOLVER_TRACE
66 #define RTRACE(m) isc_log_write(dns_lctx, \
67 DNS_LOGCATEGORY_RESOLVER, \
68 DNS_LOGMODULE_RESOLVER, \
69 ISC_LOG_DEBUG(3), \
70 "res %p: %s", res, (m))
71 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
72 DNS_LOGCATEGORY_RESOLVER, \
73 DNS_LOGMODULE_RESOLVER, \
74 ISC_LOG_DEBUG(3), \
75 "res %p: %s", (r), (m))
76 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
77 DNS_LOGCATEGORY_RESOLVER, \
78 DNS_LOGMODULE_RESOLVER, \
79 ISC_LOG_DEBUG(3), \
80 "fctx %p(%s'): %s", fctx, fctx->info, (m))
81 #define FCTXTRACE2(m1, m2) \
82 isc_log_write(dns_lctx, \
83 DNS_LOGCATEGORY_RESOLVER, \
84 DNS_LOGMODULE_RESOLVER, \
85 ISC_LOG_DEBUG(3), \
86 "fctx %p(%s): %s %s", \
87 fctx, fctx->info, (m1), (m2))
88 #define FTRACE(m) isc_log_write(dns_lctx, \
89 DNS_LOGCATEGORY_RESOLVER, \
90 DNS_LOGMODULE_RESOLVER, \
91 ISC_LOG_DEBUG(3), \
92 "fetch %p (fctx %p(%s)): %s", \
93 fetch, fetch->private, \
94 fetch->private->info, (m))
95 #define QTRACE(m) isc_log_write(dns_lctx, \
96 DNS_LOGCATEGORY_RESOLVER, \
97 DNS_LOGMODULE_RESOLVER, \
98 ISC_LOG_DEBUG(3), \
99 "resquery %p (fctx %p(%s)): %s", \
100 query, query->fctx, \
101 query->fctx->info, (m))
102 #else
103 #define RTRACE(m)
104 #define RRTRACE(r, m)
105 #define FCTXTRACE(m)
106 #define FTRACE(m)
107 #define QTRACE(m)
108 #endif
111 * Maximum EDNS0 input packet size.
113 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
116 * This defines the maximum number of timeouts we will permit before we
117 * disable EDNS0 on the query.
119 #define MAX_EDNS0_TIMEOUTS 3
121 typedef struct fetchctx fetchctx_t;
123 typedef struct query {
124 /* Locked by task event serialization. */
125 unsigned int magic;
126 fetchctx_t * fctx;
127 isc_mem_t * mctx;
128 dns_dispatchmgr_t * dispatchmgr;
129 dns_dispatch_t * dispatch;
130 isc_boolean_t exclusivesocket;
131 dns_adbaddrinfo_t * addrinfo;
132 isc_socket_t * tcpsocket;
133 isc_time_t start;
134 dns_messageid_t id;
135 dns_dispentry_t * dispentry;
136 ISC_LINK(struct query) link;
137 isc_buffer_t buffer;
138 isc_buffer_t *tsig;
139 dns_tsigkey_t *tsigkey;
140 unsigned int options;
141 unsigned int attributes;
142 unsigned int sends;
143 unsigned int connects;
144 unsigned char data[512];
145 } resquery_t;
147 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
148 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
150 #define RESQUERY_ATTR_CANCELED 0x02
152 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
153 #define RESQUERY_CANCELED(q) (((q)->attributes & \
154 RESQUERY_ATTR_CANCELED) != 0)
155 #define RESQUERY_SENDING(q) ((q)->sends > 0)
157 typedef enum {
158 fetchstate_init = 0, /*%< Start event has not run yet. */
159 fetchstate_active,
160 fetchstate_done /*%< FETCHDONE events posted. */
161 } fetchstate;
163 typedef enum {
164 badns_unreachable = 0,
165 badns_response,
166 badns_validation
167 } badnstype_t;
169 struct fetchctx {
170 /*% Not locked. */
171 unsigned int magic;
172 dns_resolver_t * res;
173 dns_name_t name;
174 dns_rdatatype_t type;
175 unsigned int options;
176 unsigned int bucketnum;
177 char * info;
178 /*% Locked by appropriate bucket lock. */
179 fetchstate state;
180 isc_boolean_t want_shutdown;
181 isc_boolean_t cloned;
182 isc_boolean_t spilled;
183 unsigned int references;
184 isc_event_t control_event;
185 ISC_LINK(struct fetchctx) link;
186 ISC_LIST(dns_fetchevent_t) events;
187 /*% Locked by task event serialization. */
188 dns_name_t domain;
189 dns_rdataset_t nameservers;
190 unsigned int attributes;
191 isc_timer_t * timer;
192 isc_time_t expires;
193 isc_interval_t interval;
194 dns_message_t * qmessage;
195 dns_message_t * rmessage;
196 ISC_LIST(resquery_t) queries;
197 dns_adbfindlist_t finds;
198 dns_adbfind_t * find;
199 dns_adbfindlist_t altfinds;
200 dns_adbfind_t * altfind;
201 dns_adbaddrinfolist_t forwaddrs;
202 dns_adbaddrinfolist_t altaddrs;
203 isc_sockaddrlist_t forwarders;
204 dns_fwdpolicy_t fwdpolicy;
205 isc_sockaddrlist_t bad;
206 isc_sockaddrlist_t edns;
207 isc_sockaddrlist_t edns512;
208 dns_validator_t *validator;
209 ISC_LIST(dns_validator_t) validators;
210 dns_db_t * cache;
211 dns_adb_t * adb;
214 * The number of events we're waiting for.
216 unsigned int pending;
219 * The number of times we've "restarted" the current
220 * nameserver set. This acts as a failsafe to prevent
221 * us from pounding constantly on a particular set of
222 * servers that, for whatever reason, are not giving
223 * us useful responses, but are responding in such a
224 * way that they are not marked "bad".
226 unsigned int restarts;
229 * The number of timeouts that have occurred since we
230 * last successfully received a response packet. This
231 * is used for EDNS0 black hole detection.
233 unsigned int timeouts;
236 * Look aside state for DS lookups.
238 dns_name_t nsname;
239 dns_fetch_t * nsfetch;
240 dns_rdataset_t nsrrset;
243 * Number of queries that reference this context.
245 unsigned int nqueries;
248 * The reason to print when logging a successful
249 * response to a query.
251 const char * reason;
254 * Random numbers to use for mixing up server addresses.
256 isc_uint32_t rand_buf;
257 isc_uint32_t rand_bits;
260 * Fetch-local statistics for detailed logging.
262 isc_result_t result; /*%< fetch result */
263 isc_result_t vresult; /*%< validation result */
264 int exitline;
265 isc_time_t start;
266 isc_uint64_t duration;
267 isc_boolean_t logged;
268 unsigned int querysent;
269 unsigned int referrals;
270 unsigned int lamecount;
271 unsigned int neterr;
272 unsigned int badresp;
273 unsigned int adberr;
274 unsigned int findfail;
275 unsigned int valfail;
276 isc_boolean_t timeout;
277 dns_adbaddrinfo_t *addrinfo;
278 isc_sockaddr_t *client;
281 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
282 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
284 #define FCTX_ATTR_HAVEANSWER 0x0001
285 #define FCTX_ATTR_GLUING 0x0002
286 #define FCTX_ATTR_ADDRWAIT 0x0004
287 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
288 #define FCTX_ATTR_WANTCACHE 0x0010
289 #define FCTX_ATTR_WANTNCACHE 0x0020
290 #define FCTX_ATTR_NEEDEDNS0 0x0040
291 #define FCTX_ATTR_TRIEDFIND 0x0080
292 #define FCTX_ATTR_TRIEDALT 0x0100
294 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
296 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
298 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
300 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
301 != 0)
302 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
303 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
304 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
305 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
306 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
308 typedef struct {
309 dns_adbaddrinfo_t * addrinfo;
310 fetchctx_t * fctx;
311 } dns_valarg_t;
313 struct dns_fetch {
314 unsigned int magic;
315 fetchctx_t * private;
318 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
319 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
321 typedef struct fctxbucket {
322 isc_task_t * task;
323 isc_mutex_t lock;
324 ISC_LIST(fetchctx_t) fctxs;
325 isc_boolean_t exiting;
326 isc_mem_t * mctx;
327 } fctxbucket_t;
329 typedef struct alternate {
330 isc_boolean_t isaddress;
331 union {
332 isc_sockaddr_t addr;
333 struct {
334 dns_name_t name;
335 in_port_t port;
336 } _n;
337 } _u;
338 ISC_LINK(struct alternate) link;
339 } alternate_t;
341 struct dns_resolver {
342 /* Unlocked. */
343 unsigned int magic;
344 isc_mem_t * mctx;
345 isc_mutex_t lock;
346 isc_mutex_t nlock;
347 isc_mutex_t primelock;
348 dns_rdataclass_t rdclass;
349 isc_socketmgr_t * socketmgr;
350 isc_timermgr_t * timermgr;
351 isc_taskmgr_t * taskmgr;
352 dns_view_t * view;
353 isc_boolean_t frozen;
354 unsigned int options;
355 dns_dispatchmgr_t * dispatchmgr;
356 dns_dispatch_t * dispatchv4;
357 isc_boolean_t exclusivev4;
358 dns_dispatch_t * dispatchv6;
359 isc_boolean_t exclusivev6;
360 unsigned int ndisps;
361 unsigned int nbuckets;
362 fctxbucket_t * buckets;
363 isc_uint32_t lame_ttl;
364 ISC_LIST(alternate_t) alternates;
365 isc_uint16_t udpsize;
366 #if USE_ALGLOCK
367 isc_rwlock_t alglock;
368 #endif
369 dns_rbt_t * algorithms;
370 #if USE_MBSLOCK
371 isc_rwlock_t mbslock;
372 #endif
373 dns_rbt_t * mustbesecure;
374 unsigned int spillatmax;
375 unsigned int spillatmin;
376 isc_timer_t * spillattimer;
377 isc_boolean_t zero_no_soa_ttl;
379 /* Locked by lock. */
380 unsigned int references;
381 isc_boolean_t exiting;
382 isc_eventlist_t whenshutdown;
383 unsigned int activebuckets;
384 isc_boolean_t priming;
385 unsigned int spillat; /* clients-per-query */
386 unsigned int nextdisp;
387 /* Locked by primelock. */
388 dns_fetch_t * primefetch;
389 /* Locked by nlock. */
390 unsigned int nfctx;
393 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
394 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
397 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
398 * which we also use as an addrinfo flag.
400 #define FCTX_ADDRINFO_MARK 0x0001
401 #define FCTX_ADDRINFO_FORWARDER 0x1000
402 #define FCTX_ADDRINFO_TRIED 0x2000
403 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
404 == 0)
405 #define ISFORWARDER(a) (((a)->flags & \
406 FCTX_ADDRINFO_FORWARDER) != 0)
407 #define TRIED(a) (((a)->flags & \
408 FCTX_ADDRINFO_TRIED) != 0)
410 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
412 static void destroy(dns_resolver_t *res);
413 static void empty_bucket(dns_resolver_t *res);
414 static isc_result_t resquery_send(resquery_t *query);
415 static void resquery_response(isc_task_t *task, isc_event_t *event);
416 static void resquery_connected(isc_task_t *task, isc_event_t *event);
417 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying);
418 static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
419 static isc_result_t ncache_adderesult(dns_message_t *message,
420 dns_db_t *cache, dns_dbnode_t *node,
421 dns_rdatatype_t covers,
422 isc_stdtime_t now, dns_ttl_t maxttl,
423 isc_boolean_t optout,
424 dns_rdataset_t *ardataset,
425 isc_result_t *eresultp);
426 static void validated(isc_task_t *task, isc_event_t *event);
427 static void maybe_destroy(fetchctx_t *fctx);
428 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
429 isc_result_t reason, badnstype_t badtype);
432 * Increment resolver-related statistics counters.
434 static inline void
435 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
436 if (res->view->resstats != NULL)
437 isc_stats_increment(res->view->resstats, counter);
440 static isc_result_t
441 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
442 dns_rdatatype_t type, dns_rdataset_t *rdataset,
443 dns_rdataset_t *sigrdataset, unsigned int valoptions,
444 isc_task_t *task)
446 dns_validator_t *validator = NULL;
447 dns_valarg_t *valarg;
448 isc_result_t result;
450 valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
451 sizeof(*valarg));
452 if (valarg == NULL)
453 return (ISC_R_NOMEMORY);
455 valarg->fctx = fctx;
456 valarg->addrinfo = addrinfo;
458 if (!ISC_LIST_EMPTY(fctx->validators))
459 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
461 result = dns_validator_create(fctx->res->view, name, type, rdataset,
462 sigrdataset, fctx->rmessage,
463 valoptions, task, validated, valarg,
464 &validator);
465 if (result == ISC_R_SUCCESS) {
466 inc_stats(fctx->res, dns_resstatscounter_val);
467 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
468 INSIST(fctx->validator == NULL);
469 fctx->validator = validator;
471 ISC_LIST_APPEND(fctx->validators, validator, link);
472 } else
473 isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
474 valarg, sizeof(*valarg));
475 return (result);
478 static isc_boolean_t
479 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
480 dns_namereln_t namereln;
481 dns_rdata_rrsig_t rrsig;
482 dns_rdata_t rdata = DNS_RDATA_INIT;
483 int order;
484 isc_result_t result;
485 unsigned int labels;
487 for (result = dns_rdataset_first(rdataset);
488 result == ISC_R_SUCCESS;
489 result = dns_rdataset_next(rdataset)) {
490 dns_rdataset_current(rdataset, &rdata);
491 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
492 RUNTIME_CHECK(result == ISC_R_SUCCESS);
493 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
494 &order, &labels);
495 if (namereln == dns_namereln_subdomain)
496 return (ISC_TRUE);
497 dns_rdata_reset(&rdata);
499 return (ISC_FALSE);
502 static isc_boolean_t
503 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
504 dns_name_t *name;
505 dns_name_t *domain = &fctx->domain;
506 dns_rdataset_t *rdataset;
507 dns_rdatatype_t type;
508 isc_result_t result;
509 isc_boolean_t keep_auth = ISC_FALSE;
511 if (message->rcode == dns_rcode_nxdomain)
512 return (ISC_FALSE);
515 * A DS RRset can appear anywhere in a zone, even for a delegation-only
516 * zone. So a response to an explicit query for this type should be
517 * excluded from delegation-only fixup.
519 * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
520 * response to a query for these types can never violate the
521 * delegation-only assumption: if the query name is below a
522 * zone cut, the response should normally be a referral, which should
523 * be accepted; if the query name is below a zone cut but the server
524 * happens to have authority for the zone of the query name, the
525 * response is a (non-referral) answer. But this does not violate
526 * delegation-only because the query name must be in a different zone
527 * due to the "apex-only" nature of these types. Note that if the
528 * remote server happens to have authority for a child zone of a
529 * delegation-only zone, we may still incorrectly "fix" the response
530 * with NXDOMAIN for queries for other types. Unfortunately it's
531 * generally impossible to differentiate this case from violation of
532 * the delegation-only assumption. Once the resolver learns the
533 * correct zone cut, possibly via a separate query for an "apex-only"
534 * type, queries for other types will be resolved correctly.
536 * A query for type ANY will be accepted if it hits an exceptional
537 * type above in the answer section as it should be from a child
538 * zone.
540 * Also accept answers with RRSIG records from the child zone.
541 * Direct queries for RRSIG records should not be answered from
542 * the parent zone.
545 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
546 (fctx->type == dns_rdatatype_ns ||
547 fctx->type == dns_rdatatype_ds ||
548 fctx->type == dns_rdatatype_soa ||
549 fctx->type == dns_rdatatype_any ||
550 fctx->type == dns_rdatatype_rrsig ||
551 fctx->type == dns_rdatatype_dnskey)) {
552 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
553 while (result == ISC_R_SUCCESS) {
554 name = NULL;
555 dns_message_currentname(message, DNS_SECTION_ANSWER,
556 &name);
557 for (rdataset = ISC_LIST_HEAD(name->list);
558 rdataset != NULL;
559 rdataset = ISC_LIST_NEXT(rdataset, link)) {
560 if (!dns_name_equal(name, &fctx->name))
561 continue;
562 type = rdataset->type;
564 * RRsig from child?
566 if (type == dns_rdatatype_rrsig &&
567 rrsig_fromchildzone(fctx, rdataset))
568 return (ISC_FALSE);
570 * Direct query for apex records or DS.
572 if (fctx->type == type &&
573 (type == dns_rdatatype_ds ||
574 type == dns_rdatatype_ns ||
575 type == dns_rdatatype_soa ||
576 type == dns_rdatatype_dnskey))
577 return (ISC_FALSE);
579 * Indirect query for apex records or DS.
581 if (fctx->type == dns_rdatatype_any &&
582 (type == dns_rdatatype_ns ||
583 type == dns_rdatatype_ds ||
584 type == dns_rdatatype_soa ||
585 type == dns_rdatatype_dnskey))
586 return (ISC_FALSE);
588 result = dns_message_nextname(message,
589 DNS_SECTION_ANSWER);
594 * A NODATA response to a DS query?
596 if (fctx->type == dns_rdatatype_ds &&
597 message->counts[DNS_SECTION_ANSWER] == 0)
598 return (ISC_FALSE);
600 /* Look for referral or indication of answer from child zone? */
601 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
602 goto munge;
604 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
605 while (result == ISC_R_SUCCESS) {
606 name = NULL;
607 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
608 for (rdataset = ISC_LIST_HEAD(name->list);
609 rdataset != NULL;
610 rdataset = ISC_LIST_NEXT(rdataset, link)) {
611 type = rdataset->type;
612 if (type == dns_rdatatype_soa &&
613 dns_name_equal(name, domain))
614 keep_auth = ISC_TRUE;
616 if (type != dns_rdatatype_ns &&
617 type != dns_rdatatype_soa &&
618 type != dns_rdatatype_rrsig)
619 continue;
621 if (type == dns_rdatatype_rrsig) {
622 if (rrsig_fromchildzone(fctx, rdataset))
623 return (ISC_FALSE);
624 else
625 continue;
628 /* NS or SOA records. */
629 if (dns_name_equal(name, domain)) {
631 * If a query for ANY causes a negative
632 * response, we can be sure that this is
633 * an empty node. For other type of queries
634 * we cannot differentiate an empty node
635 * from a node that just doesn't have that
636 * type of record. We only accept the former
637 * case.
639 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
640 fctx->type == dns_rdatatype_any)
641 return (ISC_FALSE);
642 } else if (dns_name_issubdomain(name, domain)) {
643 /* Referral or answer from child zone. */
644 return (ISC_FALSE);
647 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
650 munge:
651 message->rcode = dns_rcode_nxdomain;
652 message->counts[DNS_SECTION_ANSWER] = 0;
653 if (!keep_auth)
654 message->counts[DNS_SECTION_AUTHORITY] = 0;
655 message->counts[DNS_SECTION_ADDITIONAL] = 0;
656 return (ISC_TRUE);
659 static inline isc_result_t
660 fctx_starttimer(fetchctx_t *fctx) {
662 * Start the lifetime timer for fctx.
664 * This is also used for stopping the idle timer; in that
665 * case we must purge events already posted to ensure that
666 * no further idle events are delivered.
668 return (isc_timer_reset(fctx->timer, isc_timertype_once,
669 &fctx->expires, NULL, ISC_TRUE));
672 static inline void
673 fctx_stoptimer(fetchctx_t *fctx) {
674 isc_result_t result;
677 * We don't return a result if resetting the timer to inactive fails
678 * since there's nothing to be done about it. Resetting to inactive
679 * should never fail anyway, since the code as currently written
680 * cannot fail in that case.
682 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
683 NULL, NULL, ISC_TRUE);
684 if (result != ISC_R_SUCCESS) {
685 UNEXPECTED_ERROR(__FILE__, __LINE__,
686 "isc_timer_reset(): %s",
687 isc_result_totext(result));
692 static inline isc_result_t
693 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
695 * Start the idle timer for fctx. The lifetime timer continues
696 * to be in effect.
698 return (isc_timer_reset(fctx->timer, isc_timertype_once,
699 &fctx->expires, interval, ISC_FALSE));
703 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
704 * we use fctx_stopidletimer for readability in the code below.
706 #define fctx_stopidletimer fctx_starttimer
709 static inline void
710 resquery_destroy(resquery_t **queryp) {
711 resquery_t *query;
713 REQUIRE(queryp != NULL);
714 query = *queryp;
715 REQUIRE(!ISC_LINK_LINKED(query, link));
717 INSIST(query->tcpsocket == NULL);
719 query->fctx->nqueries--;
720 if (SHUTTINGDOWN(query->fctx))
721 maybe_destroy(query->fctx); /* Locks bucket. */
722 query->magic = 0;
723 isc_mem_put(query->mctx, query, sizeof(*query));
724 *queryp = NULL;
727 static void
728 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
729 isc_time_t *finish, isc_boolean_t no_response)
731 fetchctx_t *fctx;
732 resquery_t *query;
733 unsigned int rtt, rttms;
734 unsigned int factor;
735 dns_adbfind_t *find;
736 dns_adbaddrinfo_t *addrinfo;
737 isc_socket_t *socket;
739 query = *queryp;
740 fctx = query->fctx;
742 FCTXTRACE("cancelquery");
744 REQUIRE(!RESQUERY_CANCELED(query));
746 query->attributes |= RESQUERY_ATTR_CANCELED;
749 * Should we update the RTT?
751 if (finish != NULL || no_response) {
752 if (finish != NULL) {
754 * We have both the start and finish times for this
755 * packet, so we can compute a real RTT.
757 rtt = (unsigned int)isc_time_microdiff(finish,
758 &query->start);
759 factor = DNS_ADB_RTTADJDEFAULT;
761 rttms = rtt / 1000;
762 if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
763 inc_stats(fctx->res,
764 dns_resstatscounter_queryrtt0);
765 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
766 inc_stats(fctx->res,
767 dns_resstatscounter_queryrtt1);
768 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
769 inc_stats(fctx->res,
770 dns_resstatscounter_queryrtt2);
771 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
772 inc_stats(fctx->res,
773 dns_resstatscounter_queryrtt3);
774 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
775 inc_stats(fctx->res,
776 dns_resstatscounter_queryrtt4);
777 } else {
778 inc_stats(fctx->res,
779 dns_resstatscounter_queryrtt5);
781 } else {
783 * We don't have an RTT for this query. Maybe the
784 * packet was lost, or maybe this server is very
785 * slow. We don't know. Increase the RTT.
787 INSIST(no_response);
788 rtt = query->addrinfo->srtt + 200000;
789 if (rtt > 10000000)
790 rtt = 10000000;
792 * Replace the current RTT with our value.
794 factor = DNS_ADB_RTTADJREPLACE;
796 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
799 /* Remember that the server has been tried. */
800 if (!TRIED(query->addrinfo)) {
801 dns_adb_changeflags(fctx->adb, query->addrinfo,
802 FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
806 * Age RTTs of servers not tried.
808 factor = DNS_ADB_RTTADJAGE;
809 if (finish != NULL)
810 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
811 addrinfo != NULL;
812 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
813 if (UNMARKED(addrinfo))
814 dns_adb_adjustsrtt(fctx->adb, addrinfo,
815 0, factor);
817 if (finish != NULL && TRIEDFIND(fctx))
818 for (find = ISC_LIST_HEAD(fctx->finds);
819 find != NULL;
820 find = ISC_LIST_NEXT(find, publink))
821 for (addrinfo = ISC_LIST_HEAD(find->list);
822 addrinfo != NULL;
823 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
824 if (UNMARKED(addrinfo))
825 dns_adb_adjustsrtt(fctx->adb, addrinfo,
826 0, factor);
828 if (finish != NULL && TRIEDALT(fctx)) {
829 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
830 addrinfo != NULL;
831 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
832 if (UNMARKED(addrinfo))
833 dns_adb_adjustsrtt(fctx->adb, addrinfo,
834 0, factor);
835 for (find = ISC_LIST_HEAD(fctx->altfinds);
836 find != NULL;
837 find = ISC_LIST_NEXT(find, publink))
838 for (addrinfo = ISC_LIST_HEAD(find->list);
839 addrinfo != NULL;
840 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
841 if (UNMARKED(addrinfo))
842 dns_adb_adjustsrtt(fctx->adb, addrinfo,
843 0, factor);
847 * Check for any outstanding socket events. If they exist, cancel
848 * them and let the event handlers finish the cleanup. The resolver
849 * only needs to worry about managing the connect and send events;
850 * the dispatcher manages the recv events.
852 if (RESQUERY_CONNECTING(query)) {
854 * Cancel the connect.
856 if (query->tcpsocket != NULL) {
857 isc_socket_cancel(query->tcpsocket, NULL,
858 ISC_SOCKCANCEL_CONNECT);
859 } else if (query->dispentry != NULL) {
860 INSIST(query->exclusivesocket);
861 socket = dns_dispatch_getentrysocket(query->dispentry);
862 if (socket != NULL)
863 isc_socket_cancel(socket, NULL,
864 ISC_SOCKCANCEL_CONNECT);
866 } else if (RESQUERY_SENDING(query)) {
868 * Cancel the pending send.
870 if (query->exclusivesocket && query->dispentry != NULL)
871 socket = dns_dispatch_getentrysocket(query->dispentry);
872 else
873 socket = dns_dispatch_getsocket(query->dispatch);
874 if (socket != NULL)
875 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
878 if (query->dispentry != NULL)
879 dns_dispatch_removeresponse(&query->dispentry, deventp);
881 ISC_LIST_UNLINK(fctx->queries, query, link);
883 if (query->tsig != NULL)
884 isc_buffer_free(&query->tsig);
886 if (query->tsigkey != NULL)
887 dns_tsigkey_detach(&query->tsigkey);
889 if (query->dispatch != NULL)
890 dns_dispatch_detach(&query->dispatch);
892 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
894 * It's safe to destroy the query now.
896 resquery_destroy(&query);
899 static void
900 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
901 resquery_t *query, *next_query;
903 FCTXTRACE("cancelqueries");
905 for (query = ISC_LIST_HEAD(fctx->queries);
906 query != NULL;
907 query = next_query) {
908 next_query = ISC_LIST_NEXT(query, link);
909 fctx_cancelquery(&query, NULL, NULL, no_response);
913 static void
914 fctx_cleanupfinds(fetchctx_t *fctx) {
915 dns_adbfind_t *find, *next_find;
917 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
919 for (find = ISC_LIST_HEAD(fctx->finds);
920 find != NULL;
921 find = next_find) {
922 next_find = ISC_LIST_NEXT(find, publink);
923 ISC_LIST_UNLINK(fctx->finds, find, publink);
924 dns_adb_destroyfind(&find);
926 fctx->find = NULL;
929 static void
930 fctx_cleanupaltfinds(fetchctx_t *fctx) {
931 dns_adbfind_t *find, *next_find;
933 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
935 for (find = ISC_LIST_HEAD(fctx->altfinds);
936 find != NULL;
937 find = next_find) {
938 next_find = ISC_LIST_NEXT(find, publink);
939 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
940 dns_adb_destroyfind(&find);
942 fctx->altfind = NULL;
945 static void
946 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
947 dns_adbaddrinfo_t *addr, *next_addr;
949 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
951 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
952 addr != NULL;
953 addr = next_addr) {
954 next_addr = ISC_LIST_NEXT(addr, publink);
955 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
956 dns_adb_freeaddrinfo(fctx->adb, &addr);
960 static void
961 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
962 dns_adbaddrinfo_t *addr, *next_addr;
964 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
966 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
967 addr != NULL;
968 addr = next_addr) {
969 next_addr = ISC_LIST_NEXT(addr, publink);
970 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
971 dns_adb_freeaddrinfo(fctx->adb, &addr);
975 static inline void
976 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
977 FCTXTRACE("stopeverything");
978 fctx_cancelqueries(fctx, no_response);
979 fctx_cleanupfinds(fctx);
980 fctx_cleanupaltfinds(fctx);
981 fctx_cleanupforwaddrs(fctx);
982 fctx_cleanupaltaddrs(fctx);
983 fctx_stoptimer(fctx);
986 static inline void
987 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
988 dns_fetchevent_t *event, *next_event;
989 isc_task_t *task;
990 unsigned int count = 0;
991 isc_interval_t i;
992 isc_boolean_t logit = ISC_FALSE;
993 isc_time_t now;
994 unsigned int old_spillat;
995 unsigned int new_spillat = 0; /* initialized to silence
996 compiler warnings */
999 * Caller must be holding the appropriate bucket lock.
1001 REQUIRE(fctx->state == fetchstate_done);
1003 FCTXTRACE("sendevents");
1006 * Keep some record of fetch result for logging later (if required).
1008 fctx->result = result;
1009 fctx->exitline = line;
1010 TIME_NOW(&now);
1011 fctx->duration = isc_time_microdiff(&now, &fctx->start);
1013 for (event = ISC_LIST_HEAD(fctx->events);
1014 event != NULL;
1015 event = next_event) {
1016 next_event = ISC_LIST_NEXT(event, ev_link);
1017 ISC_LIST_UNLINK(fctx->events, event, ev_link);
1018 task = event->ev_sender;
1019 event->ev_sender = fctx;
1020 event->vresult = fctx->vresult;
1021 if (!HAVE_ANSWER(fctx))
1022 event->result = result;
1024 INSIST(result != ISC_R_SUCCESS ||
1025 dns_rdataset_isassociated(event->rdataset) ||
1026 fctx->type == dns_rdatatype_any ||
1027 fctx->type == dns_rdatatype_rrsig ||
1028 fctx->type == dns_rdatatype_sig);
1031 * Negative results must be indicated in event->result.
1033 if (dns_rdataset_isassociated(event->rdataset) &&
1034 event->rdataset->type == dns_rdatatype_none) {
1035 INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
1036 event->result == DNS_R_NCACHENXRRSET);
1039 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
1040 count++;
1043 if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
1044 fctx->spilled &&
1045 (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
1046 LOCK(&fctx->res->lock);
1047 if (count == fctx->res->spillat && !fctx->res->exiting) {
1048 old_spillat = fctx->res->spillat;
1049 fctx->res->spillat += 5;
1050 if (fctx->res->spillat > fctx->res->spillatmax &&
1051 fctx->res->spillatmax != 0)
1052 fctx->res->spillat = fctx->res->spillatmax;
1053 new_spillat = fctx->res->spillat;
1054 if (new_spillat != old_spillat) {
1055 logit = ISC_TRUE;
1057 isc_interval_set(&i, 20 * 60, 0);
1058 result = isc_timer_reset(fctx->res->spillattimer,
1059 isc_timertype_ticker, NULL,
1060 &i, ISC_TRUE);
1061 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1063 UNLOCK(&fctx->res->lock);
1064 if (logit)
1065 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
1066 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
1067 "clients-per-query increased to %u",
1068 new_spillat);
1072 static inline void
1073 log_edns(fetchctx_t *fctx) {
1074 char domainbuf[DNS_NAME_FORMATSIZE];
1076 if (fctx->reason == NULL)
1077 return;
1079 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
1080 return;
1081 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
1082 isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
1083 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1084 "success resolving '%s' (in '%s'?) after %s",
1085 fctx->info, domainbuf, fctx->reason);
1087 fctx->reason = NULL;
1090 static void
1091 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
1092 dns_resolver_t *res;
1093 isc_boolean_t no_response;
1095 REQUIRE(line >= 0);
1097 FCTXTRACE("done");
1099 res = fctx->res;
1101 if (result == ISC_R_SUCCESS) {
1103 * Log any deferred EDNS timeout messages.
1105 log_edns(fctx);
1106 no_response = ISC_TRUE;
1107 } else
1108 no_response = ISC_FALSE;
1110 fctx->reason = NULL;
1111 fctx_stopeverything(fctx, no_response);
1113 LOCK(&res->buckets[fctx->bucketnum].lock);
1115 fctx->state = fetchstate_done;
1116 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1117 fctx_sendevents(fctx, result, line);
1119 UNLOCK(&res->buckets[fctx->bucketnum].lock);
1122 static void
1123 process_sendevent(resquery_t *query, isc_event_t *event) {
1124 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1125 isc_boolean_t retry = ISC_FALSE;
1126 isc_result_t result;
1127 fetchctx_t *fctx;
1129 fctx = query->fctx;
1131 if (RESQUERY_CANCELED(query)) {
1132 if (query->sends == 0 && query->connects == 0) {
1134 * This query was canceled while the
1135 * isc_socket_sendto/connect() was in progress.
1137 if (query->tcpsocket != NULL)
1138 isc_socket_detach(&query->tcpsocket);
1139 resquery_destroy(&query);
1141 } else {
1142 switch (sevent->result) {
1143 case ISC_R_SUCCESS:
1144 break;
1146 case ISC_R_HOSTUNREACH:
1147 case ISC_R_NETUNREACH:
1148 case ISC_R_NOPERM:
1149 case ISC_R_ADDRNOTAVAIL:
1150 case ISC_R_CONNREFUSED:
1153 * No route to remote.
1155 add_bad(fctx, query->addrinfo, sevent->result,
1156 badns_unreachable);
1157 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
1158 retry = ISC_TRUE;
1159 break;
1161 default:
1162 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1163 break;
1167 isc_event_free(&event);
1169 if (retry) {
1171 * Behave as if the idle timer has expired. For TCP
1172 * this may not actually reflect the latest timer.
1174 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1175 result = fctx_stopidletimer(fctx);
1176 if (result != ISC_R_SUCCESS)
1177 fctx_done(fctx, result, __LINE__);
1178 else
1179 fctx_try(fctx, ISC_TRUE);
1183 static void
1184 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
1185 resquery_t *query = event->ev_arg;
1187 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1189 QTRACE("udpconnected");
1191 UNUSED(task);
1193 INSIST(RESQUERY_CONNECTING(query));
1195 query->connects--;
1197 process_sendevent(query, event);
1200 static void
1201 resquery_senddone(isc_task_t *task, isc_event_t *event) {
1202 resquery_t *query = event->ev_arg;
1204 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1206 QTRACE("senddone");
1209 * XXXRTH
1211 * Currently we don't wait for the senddone event before retrying
1212 * a query. This means that if we get really behind, we may end
1213 * up doing extra work!
1216 UNUSED(task);
1218 INSIST(RESQUERY_SENDING(query));
1220 query->sends--;
1222 process_sendevent(query, event);
1225 static inline isc_result_t
1226 fctx_addopt(dns_message_t *message, unsigned int version,
1227 isc_uint16_t udpsize, isc_boolean_t request_nsid)
1229 dns_rdataset_t *rdataset;
1230 dns_rdatalist_t *rdatalist;
1231 dns_rdata_t *rdata;
1232 isc_result_t result;
1234 rdatalist = NULL;
1235 result = dns_message_gettemprdatalist(message, &rdatalist);
1236 if (result != ISC_R_SUCCESS)
1237 return (result);
1238 rdata = NULL;
1239 result = dns_message_gettemprdata(message, &rdata);
1240 if (result != ISC_R_SUCCESS)
1241 return (result);
1242 rdataset = NULL;
1243 result = dns_message_gettemprdataset(message, &rdataset);
1244 if (result != ISC_R_SUCCESS)
1245 return (result);
1246 dns_rdataset_init(rdataset);
1248 rdatalist->type = dns_rdatatype_opt;
1249 rdatalist->covers = 0;
1252 * Set Maximum UDP buffer size.
1254 rdatalist->rdclass = udpsize;
1257 * Set EXTENDED-RCODE and Z to 0, DO to 1.
1259 rdatalist->ttl = (version << 16);
1260 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1263 * Set EDNS options if applicable
1265 if (request_nsid) {
1266 /* Send empty NSID option (RFC5001) */
1267 unsigned char data[4];
1268 isc_buffer_t buf;
1270 isc_buffer_init(&buf, data, sizeof(data));
1271 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
1272 isc_buffer_putuint16(&buf, 0);
1273 rdata->data = data;
1274 rdata->length = sizeof(data);
1275 } else {
1276 rdata->data = NULL;
1277 rdata->length = 0;
1280 rdata->rdclass = rdatalist->rdclass;
1281 rdata->type = rdatalist->type;
1282 rdata->flags = 0;
1284 ISC_LIST_INIT(rdatalist->rdata);
1285 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1286 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
1288 return (dns_message_setopt(message, rdataset));
1291 static inline void
1292 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
1293 unsigned int seconds;
1294 unsigned int us;
1297 * We retry every .8 seconds the first two times through the address
1298 * list, and then we do exponential back-off.
1300 if (fctx->restarts < 3)
1301 us = 800000;
1302 else
1303 us = (800000 << (fctx->restarts - 2));
1306 * Double the round-trip time.
1308 rtt *= 2;
1311 * Always wait for at least the doubled round-trip time.
1313 if (us < rtt)
1314 us = rtt;
1317 * But don't ever wait for more than 10 seconds.
1319 if (us > 10000000)
1320 us = 10000000;
1322 seconds = us / 1000000;
1323 us -= seconds * 1000000;
1324 isc_interval_set(&fctx->interval, seconds, us * 1000);
1327 static isc_result_t
1328 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
1329 unsigned int options)
1331 dns_resolver_t *res;
1332 isc_task_t *task;
1333 isc_result_t result;
1334 resquery_t *query;
1335 isc_sockaddr_t addr;
1336 isc_boolean_t have_addr = ISC_FALSE;
1337 unsigned int srtt;
1339 FCTXTRACE("query");
1341 res = fctx->res;
1342 task = res->buckets[fctx->bucketnum].task;
1344 srtt = addrinfo->srtt;
1345 if (ISFORWARDER(addrinfo) && srtt < 1000000)
1346 srtt = 1000000;
1348 fctx_setretryinterval(fctx, srtt);
1349 result = fctx_startidletimer(fctx, &fctx->interval);
1350 if (result != ISC_R_SUCCESS)
1351 return (result);
1353 INSIST(ISC_LIST_EMPTY(fctx->validators));
1355 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
1357 query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,
1358 sizeof(*query));
1359 if (query == NULL) {
1360 result = ISC_R_NOMEMORY;
1361 goto stop_idle_timer;
1363 query->mctx = res->buckets[fctx->bucketnum].mctx;
1364 query->options = options;
1365 query->attributes = 0;
1366 query->sends = 0;
1367 query->connects = 0;
1369 * Note that the caller MUST guarantee that 'addrinfo' will remain
1370 * valid until this query is canceled.
1372 query->addrinfo = addrinfo;
1373 TIME_NOW(&query->start);
1376 * If this is a TCP query, then we need to make a socket and
1377 * a dispatch for it here. Otherwise we use the resolver's
1378 * shared dispatch.
1380 query->dispatchmgr = res->dispatchmgr;
1381 query->dispatch = NULL;
1382 query->exclusivesocket = ISC_FALSE;
1383 query->tcpsocket = NULL;
1384 if (res->view->peers != NULL) {
1385 dns_peer_t *peer = NULL;
1386 isc_netaddr_t dstip;
1387 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
1388 result = dns_peerlist_peerbyaddr(res->view->peers,
1389 &dstip, &peer);
1390 if (result == ISC_R_SUCCESS) {
1391 result = dns_peer_getquerysource(peer, &addr);
1392 if (result == ISC_R_SUCCESS)
1393 have_addr = ISC_TRUE;
1397 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1398 int pf;
1400 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1401 if (!have_addr) {
1402 switch (pf) {
1403 case PF_INET:
1404 result =
1405 dns_dispatch_getlocaladdress(res->dispatchv4,
1406 &addr);
1407 break;
1408 case PF_INET6:
1409 result =
1410 dns_dispatch_getlocaladdress(res->dispatchv6,
1411 &addr);
1412 break;
1413 default:
1414 result = ISC_R_NOTIMPLEMENTED;
1415 break;
1417 if (result != ISC_R_SUCCESS)
1418 goto cleanup_query;
1420 isc_sockaddr_setport(&addr, 0);
1422 result = isc_socket_create(res->socketmgr, pf,
1423 isc_sockettype_tcp,
1424 &query->tcpsocket);
1425 if (result != ISC_R_SUCCESS)
1426 goto cleanup_query;
1428 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1429 result = isc_socket_bind(query->tcpsocket, &addr, 0);
1430 if (result != ISC_R_SUCCESS)
1431 goto cleanup_socket;
1432 #endif
1435 * A dispatch will be created once the connect succeeds.
1437 } else {
1438 if (have_addr) {
1439 unsigned int attrs, attrmask;
1440 attrs = DNS_DISPATCHATTR_UDP;
1441 switch (isc_sockaddr_pf(&addr)) {
1442 case AF_INET:
1443 attrs |= DNS_DISPATCHATTR_IPV4;
1444 break;
1445 case AF_INET6:
1446 attrs |= DNS_DISPATCHATTR_IPV6;
1447 break;
1448 default:
1449 result = ISC_R_NOTIMPLEMENTED;
1450 goto cleanup_query;
1452 attrmask = DNS_DISPATCHATTR_UDP;
1453 attrmask |= DNS_DISPATCHATTR_TCP;
1454 attrmask |= DNS_DISPATCHATTR_IPV4;
1455 attrmask |= DNS_DISPATCHATTR_IPV6;
1456 result = dns_dispatch_getudp(res->dispatchmgr,
1457 res->socketmgr,
1458 res->taskmgr, &addr,
1459 4096, 1000, 32768, 16411,
1460 16433, attrs, attrmask,
1461 &query->dispatch);
1462 if (result != ISC_R_SUCCESS)
1463 goto cleanup_query;
1464 } else {
1465 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1466 case PF_INET:
1467 dns_dispatch_attach(res->dispatchv4,
1468 &query->dispatch);
1469 query->exclusivesocket = res->exclusivev4;
1470 break;
1471 case PF_INET6:
1472 dns_dispatch_attach(res->dispatchv6,
1473 &query->dispatch);
1474 query->exclusivesocket = res->exclusivev6;
1475 break;
1476 default:
1477 result = ISC_R_NOTIMPLEMENTED;
1478 goto cleanup_query;
1482 * We should always have a valid dispatcher here. If we
1483 * don't support a protocol family, then its dispatcher
1484 * will be NULL, but we shouldn't be finding addresses for
1485 * protocol types we don't support, so the dispatcher
1486 * we found should never be NULL.
1488 INSIST(query->dispatch != NULL);
1491 query->dispentry = NULL;
1492 query->fctx = fctx;
1493 query->tsig = NULL;
1494 query->tsigkey = NULL;
1495 ISC_LINK_INIT(query, link);
1496 query->magic = QUERY_MAGIC;
1498 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1500 * Connect to the remote server.
1502 * XXXRTH Should we attach to the socket?
1504 result = isc_socket_connect(query->tcpsocket,
1505 &addrinfo->sockaddr, task,
1506 resquery_connected, query);
1507 if (result != ISC_R_SUCCESS)
1508 goto cleanup_socket;
1509 query->connects++;
1510 QTRACE("connecting via TCP");
1511 } else {
1512 result = resquery_send(query);
1513 if (result != ISC_R_SUCCESS)
1514 goto cleanup_dispatch;
1516 fctx->querysent++;
1518 ISC_LIST_APPEND(fctx->queries, query, link);
1519 query->fctx->nqueries++;
1520 if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
1521 inc_stats(res, dns_resstatscounter_queryv4);
1522 else
1523 inc_stats(res, dns_resstatscounter_queryv6);
1524 if (res->view->resquerystats != NULL)
1525 dns_rdatatypestats_increment(res->view->resquerystats,
1526 fctx->type);
1528 return (ISC_R_SUCCESS);
1530 cleanup_socket:
1531 isc_socket_detach(&query->tcpsocket);
1533 cleanup_dispatch:
1534 if (query->dispatch != NULL)
1535 dns_dispatch_detach(&query->dispatch);
1537 cleanup_query:
1538 query->magic = 0;
1539 isc_mem_put(res->buckets[fctx->bucketnum].mctx,
1540 query, sizeof(*query));
1542 stop_idle_timer:
1543 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1545 return (result);
1548 static isc_boolean_t
1549 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1550 isc_sockaddr_t *sa;
1552 for (sa = ISC_LIST_HEAD(fctx->edns);
1553 sa != NULL;
1554 sa = ISC_LIST_NEXT(sa, link)) {
1555 if (isc_sockaddr_equal(sa, address))
1556 return (ISC_TRUE);
1559 return (ISC_FALSE);
1562 static void
1563 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1564 isc_sockaddr_t *sa;
1566 if (triededns(fctx, address))
1567 return;
1569 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
1570 sizeof(*sa));
1571 if (sa == NULL)
1572 return;
1574 *sa = *address;
1575 ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
1578 static isc_boolean_t
1579 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1580 isc_sockaddr_t *sa;
1582 for (sa = ISC_LIST_HEAD(fctx->edns512);
1583 sa != NULL;
1584 sa = ISC_LIST_NEXT(sa, link)) {
1585 if (isc_sockaddr_equal(sa, address))
1586 return (ISC_TRUE);
1589 return (ISC_FALSE);
1592 static void
1593 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1594 isc_sockaddr_t *sa;
1596 if (triededns512(fctx, address))
1597 return;
1599 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
1600 sizeof(*sa));
1601 if (sa == NULL)
1602 return;
1604 *sa = *address;
1605 ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
1608 static isc_result_t
1609 resquery_send(resquery_t *query) {
1610 fetchctx_t *fctx;
1611 isc_result_t result;
1612 dns_name_t *qname = NULL;
1613 dns_rdataset_t *qrdataset = NULL;
1614 isc_region_t r;
1615 dns_resolver_t *res;
1616 isc_task_t *task;
1617 isc_socket_t *socket;
1618 isc_buffer_t tcpbuffer;
1619 isc_sockaddr_t *address;
1620 isc_buffer_t *buffer;
1621 isc_netaddr_t ipaddr;
1622 dns_tsigkey_t *tsigkey = NULL;
1623 dns_peer_t *peer = NULL;
1624 isc_boolean_t useedns;
1625 dns_compress_t cctx;
1626 isc_boolean_t cleanup_cctx = ISC_FALSE;
1627 isc_boolean_t secure_domain;
1629 fctx = query->fctx;
1630 QTRACE("send");
1632 res = fctx->res;
1633 task = res->buckets[fctx->bucketnum].task;
1634 address = NULL;
1636 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1638 * Reserve space for the TCP message length.
1640 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1641 isc_buffer_init(&query->buffer, query->data + 2,
1642 sizeof(query->data) - 2);
1643 buffer = &tcpbuffer;
1644 } else {
1645 isc_buffer_init(&query->buffer, query->data,
1646 sizeof(query->data));
1647 buffer = &query->buffer;
1650 result = dns_message_gettempname(fctx->qmessage, &qname);
1651 if (result != ISC_R_SUCCESS)
1652 goto cleanup_temps;
1653 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1654 if (result != ISC_R_SUCCESS)
1655 goto cleanup_temps;
1658 * Get a query id from the dispatch.
1660 result = dns_dispatch_addresponse2(query->dispatch,
1661 &query->addrinfo->sockaddr,
1662 task,
1663 resquery_response,
1664 query,
1665 &query->id,
1666 &query->dispentry,
1667 res->socketmgr);
1668 if (result != ISC_R_SUCCESS)
1669 goto cleanup_temps;
1671 fctx->qmessage->opcode = dns_opcode_query;
1674 * Set up question.
1676 dns_name_init(qname, NULL);
1677 dns_name_clone(&fctx->name, qname);
1678 dns_rdataset_init(qrdataset);
1679 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1680 ISC_LIST_APPEND(qname->list, qrdataset, link);
1681 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1682 qname = NULL;
1683 qrdataset = NULL;
1686 * Set RD if the client has requested that we do a recursive query,
1687 * or if we're sending to a forwarder.
1689 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1690 ISFORWARDER(query->addrinfo))
1691 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1694 * Set CD if the client says don't validate or the question is
1695 * under a secure entry point.
1697 if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
1698 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1699 } else if (res->view->enablevalidation) {
1700 result = dns_view_issecuredomain(res->view, &fctx->name,
1701 &secure_domain);
1702 if (result != ISC_R_SUCCESS)
1703 secure_domain = ISC_FALSE;
1704 if (res->view->dlv != NULL)
1705 secure_domain = ISC_TRUE;
1706 if (secure_domain)
1707 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1711 * We don't have to set opcode because it defaults to query.
1713 fctx->qmessage->id = query->id;
1716 * Convert the question to wire format.
1718 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1719 if (result != ISC_R_SUCCESS)
1720 goto cleanup_message;
1721 cleanup_cctx = ISC_TRUE;
1723 result = dns_message_renderbegin(fctx->qmessage, &cctx,
1724 &query->buffer);
1725 if (result != ISC_R_SUCCESS)
1726 goto cleanup_message;
1728 result = dns_message_rendersection(fctx->qmessage,
1729 DNS_SECTION_QUESTION, 0);
1730 if (result != ISC_R_SUCCESS)
1731 goto cleanup_message;
1733 peer = NULL;
1734 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1735 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1738 * The ADB does not know about servers with "edns no". Check this,
1739 * and then inform the ADB for future use.
1741 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1742 peer != NULL &&
1743 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1744 !useedns)
1746 query->options |= DNS_FETCHOPT_NOEDNS0;
1747 dns_adb_changeflags(fctx->adb, query->addrinfo,
1748 DNS_FETCHOPT_NOEDNS0,
1749 DNS_FETCHOPT_NOEDNS0);
1752 /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
1753 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
1754 query->options |= DNS_FETCHOPT_NOEDNS0;
1757 * Handle timeouts by reducing the UDP response size to 512 bytes
1758 * then if that doesn't work disabling EDNS (includes DO) and CD.
1760 * These timeout can be due to:
1761 * * broken nameservers that don't respond to EDNS queries.
1762 * * broken/misconfigured firewalls and NAT implementations
1763 * that don't handle IP fragmentation.
1764 * * broken/misconfigured firewalls that don't handle responses
1765 * greater than 512 bytes.
1766 * * broken/misconfigured firewalls that don't handle EDNS, DO
1767 * or CD.
1768 * * packet loss / link outage.
1770 if (fctx->timeout) {
1771 if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
1772 fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
1773 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1774 query->options |= DNS_FETCHOPT_NOEDNS0;
1775 fctx->reason = "disabling EDNS";
1776 } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
1777 fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
1778 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1779 query->options |= DNS_FETCHOPT_EDNS512;
1780 fctx->reason = "reducing the advertised EDNS UDP "
1781 "packet size to 512 octets";
1783 fctx->timeout = ISC_FALSE;
1787 * Use EDNS0, unless the caller doesn't want it, or we know that
1788 * the remote server doesn't like it.
1790 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1791 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1792 unsigned int version = 0; /* Default version. */
1793 unsigned int flags;
1794 isc_uint16_t udpsize = res->udpsize;
1795 isc_boolean_t reqnsid = res->view->requestnsid;
1797 flags = query->addrinfo->flags;
1798 if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
1799 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
1800 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
1802 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1803 udpsize = 512;
1804 else if (peer != NULL)
1805 (void)dns_peer_getudpsize(peer, &udpsize);
1807 /* request NSID for current view or peer? */
1808 if (peer != NULL)
1809 (void) dns_peer_getrequestnsid(peer, &reqnsid);
1810 result = fctx_addopt(fctx->qmessage, version,
1811 udpsize, reqnsid);
1812 if (reqnsid && result == ISC_R_SUCCESS) {
1813 query->options |= DNS_FETCHOPT_WANTNSID;
1814 } else if (result != ISC_R_SUCCESS) {
1816 * We couldn't add the OPT, but we'll press on.
1817 * We're not using EDNS0, so set the NOEDNS0
1818 * bit.
1820 query->options |= DNS_FETCHOPT_NOEDNS0;
1822 } else {
1824 * We know this server doesn't like EDNS0, so we
1825 * won't use it. Set the NOEDNS0 bit since we're
1826 * not using EDNS0.
1828 query->options |= DNS_FETCHOPT_NOEDNS0;
1833 * If we need EDNS0 to do this query and aren't using it, we lose.
1835 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1836 result = DNS_R_SERVFAIL;
1837 goto cleanup_message;
1840 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
1841 add_triededns(fctx, &query->addrinfo->sockaddr);
1843 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1844 add_triededns512(fctx, &query->addrinfo->sockaddr);
1847 * Clear CD if EDNS is not in use.
1849 if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
1850 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
1853 * Add TSIG record tailored to the current recipient.
1855 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1856 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1857 goto cleanup_message;
1859 if (tsigkey != NULL) {
1860 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
1861 dns_tsigkey_detach(&tsigkey);
1862 if (result != ISC_R_SUCCESS)
1863 goto cleanup_message;
1866 result = dns_message_rendersection(fctx->qmessage,
1867 DNS_SECTION_ADDITIONAL, 0);
1868 if (result != ISC_R_SUCCESS)
1869 goto cleanup_message;
1871 result = dns_message_renderend(fctx->qmessage);
1872 if (result != ISC_R_SUCCESS)
1873 goto cleanup_message;
1875 dns_compress_invalidate(&cctx);
1876 cleanup_cctx = ISC_FALSE;
1878 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1879 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1880 &query->tsigkey);
1881 result = dns_message_getquerytsig(fctx->qmessage,
1882 fctx->res->mctx,
1883 &query->tsig);
1884 if (result != ISC_R_SUCCESS)
1885 goto cleanup_message;
1889 * If using TCP, write the length of the message at the beginning
1890 * of the buffer.
1892 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1893 isc_buffer_usedregion(&query->buffer, &r);
1894 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1895 isc_buffer_add(&tcpbuffer, r.length);
1899 * We're now done with the query message.
1901 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1903 if (query->exclusivesocket)
1904 socket = dns_dispatch_getentrysocket(query->dispentry);
1905 else
1906 socket = dns_dispatch_getsocket(query->dispatch);
1908 * Send the query!
1910 if ((query->options & DNS_FETCHOPT_TCP) == 0) {
1911 address = &query->addrinfo->sockaddr;
1912 if (query->exclusivesocket) {
1913 result = isc_socket_connect(socket, address, task,
1914 resquery_udpconnected,
1915 query);
1916 if (result != ISC_R_SUCCESS)
1917 goto cleanup_message;
1918 query->connects++;
1921 isc_buffer_usedregion(buffer, &r);
1924 * XXXRTH Make sure we don't send to ourselves! We should probably
1925 * prune out these addresses when we get them from the ADB.
1927 result = isc_socket_sendto(socket, &r, task, resquery_senddone,
1928 query, address, NULL);
1929 if (result != ISC_R_SUCCESS)
1930 goto cleanup_message;
1932 query->sends++;
1934 QTRACE("sent");
1936 return (ISC_R_SUCCESS);
1938 cleanup_message:
1939 if (cleanup_cctx)
1940 dns_compress_invalidate(&cctx);
1942 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1945 * Stop the dispatcher from listening.
1947 dns_dispatch_removeresponse(&query->dispentry, NULL);
1949 cleanup_temps:
1950 if (qname != NULL)
1951 dns_message_puttempname(fctx->qmessage, &qname);
1952 if (qrdataset != NULL)
1953 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
1955 return (result);
1958 static void
1959 resquery_connected(isc_task_t *task, isc_event_t *event) {
1960 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1961 resquery_t *query = event->ev_arg;
1962 isc_boolean_t retry = ISC_FALSE;
1963 isc_interval_t interval;
1964 isc_result_t result;
1965 unsigned int attrs;
1966 fetchctx_t *fctx;
1968 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1969 REQUIRE(VALID_QUERY(query));
1971 QTRACE("connected");
1973 UNUSED(task);
1976 * XXXRTH
1978 * Currently we don't wait for the connect event before retrying
1979 * a query. This means that if we get really behind, we may end
1980 * up doing extra work!
1983 query->connects--;
1984 fctx = query->fctx;
1986 if (RESQUERY_CANCELED(query)) {
1988 * This query was canceled while the connect() was in
1989 * progress.
1991 isc_socket_detach(&query->tcpsocket);
1992 resquery_destroy(&query);
1993 } else {
1994 switch (sevent->result) {
1995 case ISC_R_SUCCESS:
1998 * Extend the idle timer for TCP. 20 seconds
1999 * should be long enough for a TCP connection to be
2000 * established, a single DNS request to be sent,
2001 * and the response received.
2003 isc_interval_set(&interval, 20, 0);
2004 result = fctx_startidletimer(query->fctx, &interval);
2005 if (result != ISC_R_SUCCESS) {
2006 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2007 fctx_done(fctx, result, __LINE__);
2008 break;
2011 * We are connected. Create a dispatcher and
2012 * send the query.
2014 attrs = 0;
2015 attrs |= DNS_DISPATCHATTR_TCP;
2016 attrs |= DNS_DISPATCHATTR_PRIVATE;
2017 attrs |= DNS_DISPATCHATTR_CONNECTED;
2018 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
2019 AF_INET)
2020 attrs |= DNS_DISPATCHATTR_IPV4;
2021 else
2022 attrs |= DNS_DISPATCHATTR_IPV6;
2023 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
2025 result = dns_dispatch_createtcp(query->dispatchmgr,
2026 query->tcpsocket,
2027 query->fctx->res->taskmgr,
2028 4096, 2, 1, 1, 3, attrs,
2029 &query->dispatch);
2032 * Regardless of whether dns_dispatch_create()
2033 * succeeded or not, we don't need our reference
2034 * to the socket anymore.
2036 isc_socket_detach(&query->tcpsocket);
2038 if (result == ISC_R_SUCCESS)
2039 result = resquery_send(query);
2041 if (result != ISC_R_SUCCESS) {
2042 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2043 fctx_done(fctx, result, __LINE__);
2045 break;
2047 case ISC_R_NETUNREACH:
2048 case ISC_R_HOSTUNREACH:
2049 case ISC_R_CONNREFUSED:
2050 case ISC_R_NOPERM:
2051 case ISC_R_ADDRNOTAVAIL:
2052 case ISC_R_CONNECTIONRESET:
2054 * No route to remote.
2056 isc_socket_detach(&query->tcpsocket);
2057 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
2058 retry = ISC_TRUE;
2059 break;
2061 default:
2062 isc_socket_detach(&query->tcpsocket);
2063 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2064 break;
2068 isc_event_free(&event);
2070 if (retry) {
2072 * Behave as if the idle timer has expired. For TCP
2073 * connections this may not actually reflect the latest timer.
2075 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2076 result = fctx_stopidletimer(fctx);
2077 if (result != ISC_R_SUCCESS)
2078 fctx_done(fctx, result, __LINE__);
2079 else
2080 fctx_try(fctx, ISC_TRUE);
2084 static void
2085 fctx_finddone(isc_task_t *task, isc_event_t *event) {
2086 fetchctx_t *fctx;
2087 dns_adbfind_t *find;
2088 dns_resolver_t *res;
2089 isc_boolean_t want_try = ISC_FALSE;
2090 isc_boolean_t want_done = ISC_FALSE;
2091 isc_boolean_t bucket_empty = ISC_FALSE;
2092 unsigned int bucketnum;
2094 find = event->ev_sender;
2095 fctx = event->ev_arg;
2096 REQUIRE(VALID_FCTX(fctx));
2097 res = fctx->res;
2099 UNUSED(task);
2101 FCTXTRACE("finddone");
2103 INSIST(fctx->pending > 0);
2104 fctx->pending--;
2106 if (ADDRWAIT(fctx)) {
2108 * The fetch is waiting for a name to be found.
2110 INSIST(!SHUTTINGDOWN(fctx));
2111 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2112 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
2113 want_try = ISC_TRUE;
2114 else {
2115 fctx->findfail++;
2116 if (fctx->pending == 0) {
2118 * We've got nothing else to wait for and don't
2119 * know the answer. There's nothing to do but
2120 * fail the fctx.
2122 want_done = ISC_TRUE;
2125 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
2126 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
2127 bucketnum = fctx->bucketnum;
2128 LOCK(&res->buckets[bucketnum].lock);
2130 * Note that we had to wait until we had the lock before
2131 * looking at fctx->references.
2133 if (fctx->references == 0)
2134 bucket_empty = fctx_destroy(fctx);
2135 UNLOCK(&res->buckets[bucketnum].lock);
2138 isc_event_free(&event);
2139 dns_adb_destroyfind(&find);
2141 if (want_try)
2142 fctx_try(fctx, ISC_TRUE);
2143 else if (want_done)
2144 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
2145 else if (bucket_empty)
2146 empty_bucket(res);
2150 static inline isc_boolean_t
2151 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
2152 isc_sockaddr_t *sa;
2154 for (sa = ISC_LIST_HEAD(fctx->bad);
2155 sa != NULL;
2156 sa = ISC_LIST_NEXT(sa, link)) {
2157 if (isc_sockaddr_equal(sa, address))
2158 return (ISC_TRUE);
2161 return (ISC_FALSE);
2164 static inline isc_boolean_t
2165 mark_bad(fetchctx_t *fctx) {
2166 dns_adbfind_t *curr;
2167 dns_adbaddrinfo_t *addrinfo;
2168 isc_boolean_t all_bad = ISC_TRUE;
2171 * Mark all known bad servers, so we don't try to talk to them
2172 * again.
2176 * Mark any bad nameservers.
2178 for (curr = ISC_LIST_HEAD(fctx->finds);
2179 curr != NULL;
2180 curr = ISC_LIST_NEXT(curr, publink)) {
2181 for (addrinfo = ISC_LIST_HEAD(curr->list);
2182 addrinfo != NULL;
2183 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2184 if (bad_server(fctx, &addrinfo->sockaddr))
2185 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2186 else
2187 all_bad = ISC_FALSE;
2192 * Mark any bad forwarders.
2194 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2195 addrinfo != NULL;
2196 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2197 if (bad_server(fctx, &addrinfo->sockaddr))
2198 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2199 else
2200 all_bad = ISC_FALSE;
2204 * Mark any bad alternates.
2206 for (curr = ISC_LIST_HEAD(fctx->altfinds);
2207 curr != NULL;
2208 curr = ISC_LIST_NEXT(curr, publink)) {
2209 for (addrinfo = ISC_LIST_HEAD(curr->list);
2210 addrinfo != NULL;
2211 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2212 if (bad_server(fctx, &addrinfo->sockaddr))
2213 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2214 else
2215 all_bad = ISC_FALSE;
2219 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2220 addrinfo != NULL;
2221 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2222 if (bad_server(fctx, &addrinfo->sockaddr))
2223 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2224 else
2225 all_bad = ISC_FALSE;
2228 return (all_bad);
2231 static void
2232 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
2233 badnstype_t badtype)
2235 char namebuf[DNS_NAME_FORMATSIZE];
2236 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2237 char classbuf[64];
2238 char typebuf[64];
2239 char code[64];
2240 isc_buffer_t b;
2241 isc_sockaddr_t *sa;
2242 const char *spc = "";
2243 isc_sockaddr_t *address = &addrinfo->sockaddr;
2245 if (reason == DNS_R_LAME)
2246 fctx->lamecount++;
2247 else {
2248 switch (badtype) {
2249 case badns_unreachable:
2250 fctx->neterr++;
2251 break;
2252 case badns_response:
2253 fctx->badresp++;
2254 break;
2255 case badns_validation:
2256 break; /* counted as 'valfail' */
2260 if (bad_server(fctx, address)) {
2262 * We already know this server is bad.
2264 return;
2267 FCTXTRACE("add_bad");
2269 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
2270 sizeof(*sa));
2271 if (sa == NULL)
2272 return;
2273 *sa = *address;
2274 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
2276 if (reason == DNS_R_LAME) /* already logged */
2277 return;
2279 if (reason == DNS_R_UNEXPECTEDRCODE &&
2280 fctx->rmessage->rcode == dns_rcode_servfail &&
2281 ISFORWARDER(addrinfo))
2282 return;
2284 if (reason == DNS_R_UNEXPECTEDRCODE) {
2285 isc_buffer_init(&b, code, sizeof(code) - 1);
2286 dns_rcode_totext(fctx->rmessage->rcode, &b);
2287 code[isc_buffer_usedlength(&b)] = '\0';
2288 spc = " ";
2289 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
2290 isc_buffer_init(&b, code, sizeof(code) - 1);
2291 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
2292 code[isc_buffer_usedlength(&b)] = '\0';
2293 spc = " ";
2294 } else {
2295 code[0] = '\0';
2297 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2298 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
2299 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
2300 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
2301 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2302 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2303 "error (%s%s%s) resolving '%s/%s/%s': %s",
2304 dns_result_totext(reason), spc, code,
2305 namebuf, typebuf, classbuf, addrbuf);
2309 * Return 'bits' bits of random entropy from fctx->rand_buf,
2310 * refreshing it by calling isc_random_get() whenever the requested
2311 * number of bits is greater than the number in the buffer.
2313 static inline isc_uint32_t
2314 random_bits(fetchctx_t *fctx, isc_uint32_t bits) {
2315 isc_uint32_t ret = 0;
2317 REQUIRE(VALID_FCTX(fctx));
2318 REQUIRE(bits <= 32);
2319 if (bits == 0)
2320 return (0);
2322 if (bits >= fctx->rand_bits) {
2323 /* if rand_bits == 0, this is unnecessary but harmless */
2324 bits -= fctx->rand_bits;
2325 ret = fctx->rand_buf << bits;
2327 /* refresh random buffer now */
2328 isc_random_get(&fctx->rand_buf);
2329 fctx->rand_bits = sizeof(fctx->rand_buf) * CHAR_BIT;
2332 if (bits > 0) {
2333 isc_uint32_t mask = 0xffffffff;
2334 if (bits < 32) {
2335 mask = (1 << bits) - 1;
2338 ret |= fctx->rand_buf & mask;
2339 fctx->rand_buf >>= bits;
2340 fctx->rand_bits -= bits;
2343 return (ret);
2347 * Add some random jitter to a server's RTT value so that the
2348 * order of queries will be unpredictable.
2350 * RTT values of servers which have been tried are fuzzed by 128 ms.
2351 * Servers that haven't been tried yet have their RTT set to a random
2352 * value between 0 ms and 7 ms; they should get to go first, but in
2353 * unpredictable order.
2355 static inline void
2356 randomize_srtt(fetchctx_t *fctx, dns_adbaddrinfo_t *ai) {
2357 if (TRIED(ai)) {
2358 ai->srtt >>= 10; /* convert to milliseconds, near enough */
2359 ai->srtt |= (ai->srtt & 0x80) | random_bits(fctx, 7);
2360 ai->srtt <<= 10; /* now back to microseconds */
2361 } else
2362 ai->srtt = random_bits(fctx, 3) << 10;
2366 * Sort addrinfo list by RTT (with random jitter)
2368 static void
2369 sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) {
2370 dns_adbaddrinfo_t *best, *curr;
2371 dns_adbaddrinfolist_t sorted;
2373 /* Add jitter to SRTT values */
2374 curr = ISC_LIST_HEAD(find->list);
2375 while (curr != NULL) {
2376 randomize_srtt(fctx, curr);
2377 curr = ISC_LIST_NEXT(curr, publink);
2380 /* Lame N^2 bubble sort. */
2381 ISC_LIST_INIT(sorted);
2382 while (!ISC_LIST_EMPTY(find->list)) {
2383 best = ISC_LIST_HEAD(find->list);
2384 curr = ISC_LIST_NEXT(best, publink);
2385 while (curr != NULL) {
2386 if (curr->srtt < best->srtt)
2387 best = curr;
2388 curr = ISC_LIST_NEXT(curr, publink);
2390 ISC_LIST_UNLINK(find->list, best, publink);
2391 ISC_LIST_APPEND(sorted, best, publink);
2393 find->list = sorted;
2397 * Sort a list of finds by server RTT (with random jitter)
2399 static void
2400 sort_finds(fetchctx_t *fctx, dns_adbfindlist_t *findlist) {
2401 dns_adbfind_t *best, *curr;
2402 dns_adbfindlist_t sorted;
2403 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
2405 /* Sort each find's addrinfo list by SRTT (after adding jitter) */
2406 for (curr = ISC_LIST_HEAD(*findlist);
2407 curr != NULL;
2408 curr = ISC_LIST_NEXT(curr, publink))
2409 sort_adbfind(fctx, curr);
2411 /* Lame N^2 bubble sort. */
2412 ISC_LIST_INIT(sorted);
2413 while (!ISC_LIST_EMPTY(*findlist)) {
2414 best = ISC_LIST_HEAD(*findlist);
2415 bestaddrinfo = ISC_LIST_HEAD(best->list);
2416 INSIST(bestaddrinfo != NULL);
2417 curr = ISC_LIST_NEXT(best, publink);
2418 while (curr != NULL) {
2419 addrinfo = ISC_LIST_HEAD(curr->list);
2420 INSIST(addrinfo != NULL);
2421 if (addrinfo->srtt < bestaddrinfo->srtt) {
2422 best = curr;
2423 bestaddrinfo = addrinfo;
2425 curr = ISC_LIST_NEXT(curr, publink);
2427 ISC_LIST_UNLINK(*findlist, best, publink);
2428 ISC_LIST_APPEND(sorted, best, publink);
2430 *findlist = sorted;
2433 static void
2434 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
2435 unsigned int options, unsigned int flags, isc_stdtime_t now,
2436 isc_boolean_t *need_alternate)
2438 dns_adbaddrinfo_t *ai;
2439 dns_adbfind_t *find;
2440 dns_resolver_t *res;
2441 isc_boolean_t unshared;
2442 isc_result_t result;
2444 res = fctx->res;
2445 unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
2447 * If this name is a subdomain of the query domain, tell
2448 * the ADB to start looking using zone/hint data. This keeps us
2449 * from getting stuck if the nameserver is beneath the zone cut
2450 * and we don't know its address (e.g. because the A record has
2451 * expired).
2453 if (dns_name_issubdomain(name, &fctx->domain))
2454 options |= DNS_ADBFIND_STARTATZONE;
2455 options |= DNS_ADBFIND_GLUEOK;
2456 options |= DNS_ADBFIND_HINTOK;
2459 * See what we know about this address.
2461 find = NULL;
2462 result = dns_adb_createfind(fctx->adb,
2463 res->buckets[fctx->bucketnum].task,
2464 fctx_finddone, fctx, name,
2465 &fctx->name, fctx->type,
2466 options, now, NULL,
2467 res->view->dstport, &find);
2468 if (result != ISC_R_SUCCESS) {
2469 if (result == DNS_R_ALIAS) {
2471 * XXXRTH Follow the CNAME/DNAME chain?
2473 dns_adb_destroyfind(&find);
2474 fctx->adberr++;
2476 } else if (!ISC_LIST_EMPTY(find->list)) {
2478 * We have at least some of the addresses for the
2479 * name.
2481 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
2482 if (flags != 0 || port != 0) {
2483 for (ai = ISC_LIST_HEAD(find->list);
2484 ai != NULL;
2485 ai = ISC_LIST_NEXT(ai, publink)) {
2486 ai->flags |= flags;
2487 if (port != 0)
2488 isc_sockaddr_setport(&ai->sockaddr,
2489 port);
2492 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
2493 ISC_LIST_APPEND(fctx->altfinds, find, publink);
2494 else
2495 ISC_LIST_APPEND(fctx->finds, find, publink);
2496 } else {
2498 * We don't know any of the addresses for this
2499 * name.
2501 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
2503 * We're looking for them and will get an
2504 * event about it later.
2506 fctx->pending++;
2508 * Bootstrap.
2510 if (need_alternate != NULL &&
2511 !*need_alternate && unshared &&
2512 ((res->dispatchv4 == NULL &&
2513 find->result_v6 != DNS_R_NXDOMAIN) ||
2514 (res->dispatchv6 == NULL &&
2515 find->result_v4 != DNS_R_NXDOMAIN)))
2516 *need_alternate = ISC_TRUE;
2517 } else {
2518 if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
2519 fctx->lamecount++; /* cached lame server */
2520 else
2521 fctx->adberr++; /* unreachable server, etc. */
2524 * If we know there are no addresses for
2525 * the family we are using then try to add
2526 * an alternative server.
2528 if (need_alternate != NULL && !*need_alternate &&
2529 ((res->dispatchv4 == NULL &&
2530 find->result_v6 == DNS_R_NXRRSET) ||
2531 (res->dispatchv6 == NULL &&
2532 find->result_v4 == DNS_R_NXRRSET)))
2533 *need_alternate = ISC_TRUE;
2534 dns_adb_destroyfind(&find);
2539 static isc_boolean_t
2540 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
2541 int order;
2542 unsigned int nlabels;
2543 dns_namereln_t namereln;
2545 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
2546 return (ISC_TF(namereln == dns_namereln_subdomain));
2549 static isc_result_t
2550 fctx_getaddresses(fetchctx_t *fctx) {
2551 dns_rdata_t rdata = DNS_RDATA_INIT;
2552 isc_result_t result;
2553 dns_resolver_t *res;
2554 isc_stdtime_t now;
2555 unsigned int stdoptions;
2556 isc_sockaddr_t *sa;
2557 dns_adbaddrinfo_t *ai;
2558 isc_boolean_t all_bad;
2559 dns_rdata_ns_t ns;
2560 isc_boolean_t need_alternate = ISC_FALSE;
2562 FCTXTRACE("getaddresses");
2565 * Don't pound on remote servers. (Failsafe!)
2567 fctx->restarts++;
2568 if (fctx->restarts > 10) {
2569 FCTXTRACE("too many restarts");
2570 return (DNS_R_SERVFAIL);
2573 res = fctx->res;
2574 stdoptions = 0; /* Keep compiler happy. */
2577 * Forwarders.
2580 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
2581 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
2584 * If this fctx has forwarders, use them; otherwise use any
2585 * selective forwarders specified in the view; otherwise use the
2586 * resolver's forwarders (if any).
2588 sa = ISC_LIST_HEAD(fctx->forwarders);
2589 if (sa == NULL) {
2590 dns_forwarders_t *forwarders = NULL;
2591 dns_name_t *name = &fctx->name;
2592 dns_name_t suffix;
2593 unsigned int labels;
2594 dns_fixedname_t fixed;
2595 dns_name_t *domain;
2598 * DS records are found in the parent server.
2599 * Strip label to get the correct forwarder (if any).
2601 if (dns_rdatatype_atparent(fctx->type) &&
2602 dns_name_countlabels(name) > 1) {
2603 dns_name_init(&suffix, NULL);
2604 labels = dns_name_countlabels(name);
2605 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2606 name = &suffix;
2609 dns_fixedname_init(&fixed);
2610 domain = dns_fixedname_name(&fixed);
2611 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
2612 domain, &forwarders);
2613 if (result == ISC_R_SUCCESS) {
2614 sa = ISC_LIST_HEAD(forwarders->addrs);
2615 fctx->fwdpolicy = forwarders->fwdpolicy;
2616 if (fctx->fwdpolicy == dns_fwdpolicy_only &&
2617 isstrictsubdomain(domain, &fctx->domain)) {
2618 isc_mem_t *mctx;
2620 mctx = res->buckets[fctx->bucketnum].mctx;
2621 dns_name_free(&fctx->domain, mctx);
2622 dns_name_init(&fctx->domain, NULL);
2623 result = dns_name_dup(domain, mctx,
2624 &fctx->domain);
2625 if (result != ISC_R_SUCCESS)
2626 return (result);
2631 while (sa != NULL) {
2632 if ((isc_sockaddr_pf(sa) == AF_INET &&
2633 fctx->res->dispatchv4 == NULL) ||
2634 (isc_sockaddr_pf(sa) == AF_INET6 &&
2635 fctx->res->dispatchv6 == NULL)) {
2636 sa = ISC_LIST_NEXT(sa, link);
2637 continue;
2639 ai = NULL;
2640 result = dns_adb_findaddrinfo(fctx->adb,
2641 sa, &ai, 0); /* XXXMLG */
2642 if (result == ISC_R_SUCCESS) {
2643 dns_adbaddrinfo_t *cur;
2644 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2645 cur = ISC_LIST_HEAD(fctx->forwaddrs);
2646 while (cur != NULL && cur->srtt < ai->srtt)
2647 cur = ISC_LIST_NEXT(cur, publink);
2648 if (cur != NULL)
2649 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
2650 ai, publink);
2651 else
2652 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
2654 sa = ISC_LIST_NEXT(sa, link);
2658 * If the forwarding policy is "only", we don't need the addresses
2659 * of the nameservers.
2661 if (fctx->fwdpolicy == dns_fwdpolicy_only)
2662 goto out;
2665 * Normal nameservers.
2668 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
2669 if (fctx->restarts == 1) {
2671 * To avoid sending out a flood of queries likely to
2672 * result in NXRRSET, we suppress fetches for address
2673 * families we don't have the first time through,
2674 * provided that we have addresses in some family we
2675 * can use.
2677 * We don't want to set this option all the time, since
2678 * if fctx->restarts > 1, we've clearly been having trouble
2679 * with the addresses we had, so getting more could help.
2681 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
2683 if (res->dispatchv4 != NULL)
2684 stdoptions |= DNS_ADBFIND_INET;
2685 if (res->dispatchv6 != NULL)
2686 stdoptions |= DNS_ADBFIND_INET6;
2687 isc_stdtime_get(&now);
2689 INSIST(ISC_LIST_EMPTY(fctx->finds));
2690 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
2692 for (result = dns_rdataset_first(&fctx->nameservers);
2693 result == ISC_R_SUCCESS;
2694 result = dns_rdataset_next(&fctx->nameservers))
2696 dns_rdataset_current(&fctx->nameservers, &rdata);
2698 * Extract the name from the NS record.
2700 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2701 if (result != ISC_R_SUCCESS)
2702 continue;
2704 findname(fctx, &ns.name, 0, stdoptions, 0, now,
2705 &need_alternate);
2706 dns_rdata_reset(&rdata);
2707 dns_rdata_freestruct(&ns);
2709 if (result != ISC_R_NOMORE)
2710 return (result);
2713 * Do we need to use 6 to 4?
2715 if (need_alternate) {
2716 int family;
2717 alternate_t *a;
2718 family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
2719 for (a = ISC_LIST_HEAD(fctx->res->alternates);
2720 a != NULL;
2721 a = ISC_LIST_NEXT(a, link)) {
2722 if (!a->isaddress) {
2723 findname(fctx, &a->_u._n.name, a->_u._n.port,
2724 stdoptions, FCTX_ADDRINFO_FORWARDER,
2725 now, NULL);
2726 continue;
2728 if (isc_sockaddr_pf(&a->_u.addr) != family)
2729 continue;
2730 ai = NULL;
2731 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
2732 &ai, 0);
2733 if (result == ISC_R_SUCCESS) {
2734 dns_adbaddrinfo_t *cur;
2735 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2736 cur = ISC_LIST_HEAD(fctx->altaddrs);
2737 while (cur != NULL && cur->srtt < ai->srtt)
2738 cur = ISC_LIST_NEXT(cur, publink);
2739 if (cur != NULL)
2740 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
2741 cur, ai, publink);
2742 else
2743 ISC_LIST_APPEND(fctx->altaddrs, ai,
2744 publink);
2749 out:
2751 * Mark all known bad servers.
2753 all_bad = mark_bad(fctx);
2756 * How are we doing?
2758 if (all_bad) {
2760 * We've got no addresses.
2762 if (fctx->pending > 0) {
2764 * We're fetching the addresses, but don't have any
2765 * yet. Tell the caller to wait for an answer.
2767 result = DNS_R_WAIT;
2768 } else {
2770 * We've lost completely. We don't know any
2771 * addresses, and the ADB has told us it can't get
2772 * them.
2774 FCTXTRACE("no addresses");
2775 result = ISC_R_FAILURE;
2777 } else {
2779 * We've found some addresses. We might still be looking
2780 * for more addresses.
2782 sort_finds(fctx, &fctx->finds);
2783 sort_finds(fctx, &fctx->altfinds);
2784 result = ISC_R_SUCCESS;
2787 return (result);
2790 static inline void
2791 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
2793 isc_netaddr_t na;
2794 char buf[ISC_NETADDR_FORMATSIZE];
2795 isc_sockaddr_t *sa;
2796 isc_boolean_t aborted = ISC_FALSE;
2797 isc_boolean_t bogus;
2798 dns_acl_t *blackhole;
2799 isc_netaddr_t ipaddr;
2800 dns_peer_t *peer = NULL;
2801 dns_resolver_t *res;
2802 const char *msg = NULL;
2804 sa = &addr->sockaddr;
2806 res = fctx->res;
2807 isc_netaddr_fromsockaddr(&ipaddr, sa);
2808 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
2809 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
2811 if (blackhole != NULL) {
2812 int match;
2814 if (dns_acl_match(&ipaddr, NULL, blackhole,
2815 &res->view->aclenv,
2816 &match, NULL) == ISC_R_SUCCESS &&
2817 match > 0)
2818 aborted = ISC_TRUE;
2821 if (peer != NULL &&
2822 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
2823 bogus)
2824 aborted = ISC_TRUE;
2826 if (aborted) {
2827 addr->flags |= FCTX_ADDRINFO_MARK;
2828 msg = "ignoring blackholed / bogus server: ";
2829 } else if (isc_sockaddr_ismulticast(sa)) {
2830 addr->flags |= FCTX_ADDRINFO_MARK;
2831 msg = "ignoring multicast address: ";
2832 } else if (isc_sockaddr_isexperimental(sa)) {
2833 addr->flags |= FCTX_ADDRINFO_MARK;
2834 msg = "ignoring experimental address: ";
2835 } else if (sa->type.sa.sa_family != AF_INET6) {
2836 return;
2837 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
2838 addr->flags |= FCTX_ADDRINFO_MARK;
2839 msg = "ignoring IPv6 mapped IPV4 address: ";
2840 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
2841 addr->flags |= FCTX_ADDRINFO_MARK;
2842 msg = "ignoring IPv6 compatibility IPV4 address: ";
2843 } else
2844 return;
2846 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
2847 return;
2849 isc_netaddr_fromsockaddr(&na, sa);
2850 isc_netaddr_format(&na, buf, sizeof(buf));
2851 FCTXTRACE2(msg, buf);
2854 static inline dns_adbaddrinfo_t *
2855 fctx_nextaddress(fetchctx_t *fctx) {
2856 dns_adbfind_t *find, *start;
2857 dns_adbaddrinfo_t *addrinfo;
2858 dns_adbaddrinfo_t *faddrinfo;
2861 * Return the next untried address, if any.
2865 * Find the first unmarked forwarder (if any).
2867 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2868 addrinfo != NULL;
2869 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2870 if (!UNMARKED(addrinfo))
2871 continue;
2872 possibly_mark(fctx, addrinfo);
2873 if (UNMARKED(addrinfo)) {
2874 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2875 fctx->find = NULL;
2876 return (addrinfo);
2881 * No forwarders. Move to the next find.
2884 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
2886 find = fctx->find;
2887 if (find == NULL)
2888 find = ISC_LIST_HEAD(fctx->finds);
2889 else {
2890 find = ISC_LIST_NEXT(find, publink);
2891 if (find == NULL)
2892 find = ISC_LIST_HEAD(fctx->finds);
2896 * Find the first unmarked addrinfo.
2898 addrinfo = NULL;
2899 if (find != NULL) {
2900 start = find;
2901 do {
2902 for (addrinfo = ISC_LIST_HEAD(find->list);
2903 addrinfo != NULL;
2904 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2905 if (!UNMARKED(addrinfo))
2906 continue;
2907 possibly_mark(fctx, addrinfo);
2908 if (UNMARKED(addrinfo)) {
2909 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2910 break;
2913 if (addrinfo != NULL)
2914 break;
2915 find = ISC_LIST_NEXT(find, publink);
2916 if (find == NULL)
2917 find = ISC_LIST_HEAD(fctx->finds);
2918 } while (find != start);
2921 fctx->find = find;
2922 if (addrinfo != NULL)
2923 return (addrinfo);
2926 * No nameservers left. Try alternates.
2929 fctx->attributes |= FCTX_ATTR_TRIEDALT;
2931 find = fctx->altfind;
2932 if (find == NULL)
2933 find = ISC_LIST_HEAD(fctx->altfinds);
2934 else {
2935 find = ISC_LIST_NEXT(find, publink);
2936 if (find == NULL)
2937 find = ISC_LIST_HEAD(fctx->altfinds);
2941 * Find the first unmarked addrinfo.
2943 addrinfo = NULL;
2944 if (find != NULL) {
2945 start = find;
2946 do {
2947 for (addrinfo = ISC_LIST_HEAD(find->list);
2948 addrinfo != NULL;
2949 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2950 if (!UNMARKED(addrinfo))
2951 continue;
2952 possibly_mark(fctx, addrinfo);
2953 if (UNMARKED(addrinfo)) {
2954 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2955 break;
2958 if (addrinfo != NULL)
2959 break;
2960 find = ISC_LIST_NEXT(find, publink);
2961 if (find == NULL)
2962 find = ISC_LIST_HEAD(fctx->altfinds);
2963 } while (find != start);
2966 faddrinfo = addrinfo;
2969 * See if we have a better alternate server by address.
2972 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2973 addrinfo != NULL;
2974 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2975 if (!UNMARKED(addrinfo))
2976 continue;
2977 possibly_mark(fctx, addrinfo);
2978 if (UNMARKED(addrinfo) &&
2979 (faddrinfo == NULL ||
2980 addrinfo->srtt < faddrinfo->srtt)) {
2981 if (faddrinfo != NULL)
2982 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
2983 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2984 break;
2988 if (addrinfo == NULL) {
2989 addrinfo = faddrinfo;
2990 fctx->altfind = find;
2993 return (addrinfo);
2996 static void
2997 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
2998 isc_result_t result;
2999 dns_adbaddrinfo_t *addrinfo;
3001 FCTXTRACE("try");
3003 REQUIRE(!ADDRWAIT(fctx));
3005 addrinfo = fctx_nextaddress(fctx);
3006 if (addrinfo == NULL) {
3008 * We have no more addresses. Start over.
3010 fctx_cancelqueries(fctx, ISC_TRUE);
3011 fctx_cleanupfinds(fctx);
3012 fctx_cleanupaltfinds(fctx);
3013 fctx_cleanupforwaddrs(fctx);
3014 fctx_cleanupaltaddrs(fctx);
3015 result = fctx_getaddresses(fctx);
3016 if (result == DNS_R_WAIT) {
3018 * Sleep waiting for addresses.
3020 FCTXTRACE("addrwait");
3021 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
3022 return;
3023 } else if (result != ISC_R_SUCCESS) {
3025 * Something bad happened.
3027 fctx_done(fctx, result, __LINE__);
3028 return;
3031 addrinfo = fctx_nextaddress(fctx);
3033 * While we may have addresses from the ADB, they
3034 * might be bad ones. In this case, return SERVFAIL.
3036 if (addrinfo == NULL) {
3037 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3038 return;
3042 result = fctx_query(fctx, addrinfo, fctx->options);
3043 if (result != ISC_R_SUCCESS)
3044 fctx_done(fctx, result, __LINE__);
3045 else if (retrying)
3046 inc_stats(fctx->res, dns_resstatscounter_retry);
3049 static isc_boolean_t
3050 fctx_destroy(fetchctx_t *fctx) {
3051 dns_resolver_t *res;
3052 unsigned int bucketnum;
3053 isc_sockaddr_t *sa, *next_sa;
3056 * Caller must be holding the bucket lock.
3059 REQUIRE(VALID_FCTX(fctx));
3060 REQUIRE(fctx->state == fetchstate_done ||
3061 fctx->state == fetchstate_init);
3062 REQUIRE(ISC_LIST_EMPTY(fctx->events));
3063 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3064 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3065 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3066 REQUIRE(fctx->pending == 0);
3067 REQUIRE(fctx->references == 0);
3068 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3070 FCTXTRACE("destroy");
3072 res = fctx->res;
3073 bucketnum = fctx->bucketnum;
3075 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
3078 * Free bad.
3080 for (sa = ISC_LIST_HEAD(fctx->bad);
3081 sa != NULL;
3082 sa = next_sa) {
3083 next_sa = ISC_LIST_NEXT(sa, link);
3084 ISC_LIST_UNLINK(fctx->bad, sa, link);
3085 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
3088 for (sa = ISC_LIST_HEAD(fctx->edns);
3089 sa != NULL;
3090 sa = next_sa) {
3091 next_sa = ISC_LIST_NEXT(sa, link);
3092 ISC_LIST_UNLINK(fctx->edns, sa, link);
3093 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
3096 for (sa = ISC_LIST_HEAD(fctx->edns512);
3097 sa != NULL;
3098 sa = next_sa) {
3099 next_sa = ISC_LIST_NEXT(sa, link);
3100 ISC_LIST_UNLINK(fctx->edns512, sa, link);
3101 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
3104 isc_timer_detach(&fctx->timer);
3105 dns_message_destroy(&fctx->rmessage);
3106 dns_message_destroy(&fctx->qmessage);
3107 if (dns_name_countlabels(&fctx->domain) > 0)
3108 dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
3109 if (dns_rdataset_isassociated(&fctx->nameservers))
3110 dns_rdataset_disassociate(&fctx->nameservers);
3111 dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
3112 dns_db_detach(&fctx->cache);
3113 dns_adb_detach(&fctx->adb);
3114 isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
3115 isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
3117 LOCK(&res->nlock);
3118 res->nfctx--;
3119 UNLOCK(&res->nlock);
3121 if (res->buckets[bucketnum].exiting &&
3122 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
3123 return (ISC_TRUE);
3125 return (ISC_FALSE);
3129 * Fetch event handlers.
3132 static void
3133 fctx_timeout(isc_task_t *task, isc_event_t *event) {
3134 fetchctx_t *fctx = event->ev_arg;
3135 isc_timerevent_t *tevent = (isc_timerevent_t *)event;
3136 resquery_t *query;
3138 REQUIRE(VALID_FCTX(fctx));
3140 UNUSED(task);
3142 FCTXTRACE("timeout");
3144 inc_stats(fctx->res, dns_resstatscounter_querytimeout);
3146 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
3147 fctx->reason = NULL;
3148 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
3149 } else {
3150 isc_result_t result;
3152 fctx->timeouts++;
3153 fctx->timeout = ISC_TRUE;
3155 * We could cancel the running queries here, or we could let
3156 * them keep going. Since we normally use separate sockets for
3157 * different queries, we adopt the former approach to reduce
3158 * the number of open sockets: cancel the oldest query if it
3159 * expired after the query had started (this is usually the
3160 * case but is not always so, depending on the task schedule
3161 * timing).
3163 query = ISC_LIST_HEAD(fctx->queries);
3164 if (query != NULL &&
3165 isc_time_compare(&tevent->due, &query->start) >= 0) {
3166 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
3168 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3170 * Our timer has triggered. Reestablish the fctx lifetime
3171 * timer.
3173 result = fctx_starttimer(fctx);
3174 if (result != ISC_R_SUCCESS)
3175 fctx_done(fctx, result, __LINE__);
3176 else
3178 * Keep trying.
3180 fctx_try(fctx, ISC_TRUE);
3183 isc_event_free(&event);
3186 static void
3187 fctx_shutdown(fetchctx_t *fctx) {
3188 isc_event_t *cevent;
3191 * Start the shutdown process for fctx, if it isn't already underway.
3194 FCTXTRACE("shutdown");
3197 * The caller must be holding the appropriate bucket lock.
3200 if (fctx->want_shutdown)
3201 return;
3203 fctx->want_shutdown = ISC_TRUE;
3206 * Unless we're still initializing (in which case the
3207 * control event is still outstanding), we need to post
3208 * the control event to tell the fetch we want it to
3209 * exit.
3211 if (fctx->state != fetchstate_init) {
3212 cevent = &fctx->control_event;
3213 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
3214 &cevent);
3218 static void
3219 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
3220 fetchctx_t *fctx = event->ev_arg;
3221 isc_boolean_t bucket_empty = ISC_FALSE;
3222 dns_resolver_t *res;
3223 unsigned int bucketnum;
3224 dns_validator_t *validator;
3226 REQUIRE(VALID_FCTX(fctx));
3228 UNUSED(task);
3230 res = fctx->res;
3231 bucketnum = fctx->bucketnum;
3233 FCTXTRACE("doshutdown");
3236 * An fctx that is shutting down is no longer in ADDRWAIT mode.
3238 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3241 * Cancel all pending validators. Note that this must be done
3242 * without the bucket lock held, since that could cause deadlock.
3244 validator = ISC_LIST_HEAD(fctx->validators);
3245 while (validator != NULL) {
3246 dns_validator_cancel(validator);
3247 validator = ISC_LIST_NEXT(validator, link);
3250 if (fctx->nsfetch != NULL)
3251 dns_resolver_cancelfetch(fctx->nsfetch);
3254 * Shut down anything that is still running on behalf of this
3255 * fetch. To avoid deadlock with the ADB, we must do this
3256 * before we lock the bucket lock.
3258 fctx_stopeverything(fctx, ISC_FALSE);
3260 LOCK(&res->buckets[bucketnum].lock);
3262 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3264 INSIST(fctx->state == fetchstate_active ||
3265 fctx->state == fetchstate_done);
3266 INSIST(fctx->want_shutdown);
3268 if (fctx->state != fetchstate_done) {
3269 fctx->state = fetchstate_done;
3270 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3273 if (fctx->references == 0 && fctx->pending == 0 &&
3274 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators))
3275 bucket_empty = fctx_destroy(fctx);
3277 UNLOCK(&res->buckets[bucketnum].lock);
3279 if (bucket_empty)
3280 empty_bucket(res);
3283 static void
3284 fctx_start(isc_task_t *task, isc_event_t *event) {
3285 fetchctx_t *fctx = event->ev_arg;
3286 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
3287 dns_resolver_t *res;
3288 unsigned int bucketnum;
3290 REQUIRE(VALID_FCTX(fctx));
3292 UNUSED(task);
3294 res = fctx->res;
3295 bucketnum = fctx->bucketnum;
3297 FCTXTRACE("start");
3299 LOCK(&res->buckets[bucketnum].lock);
3301 INSIST(fctx->state == fetchstate_init);
3302 if (fctx->want_shutdown) {
3304 * We haven't started this fctx yet, and we've been requested
3305 * to shut it down.
3307 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3308 fctx->state = fetchstate_done;
3309 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3311 * Since we haven't started, we INSIST that we have no
3312 * pending ADB finds and no pending validations.
3314 INSIST(fctx->pending == 0);
3315 INSIST(fctx->nqueries == 0);
3316 INSIST(ISC_LIST_EMPTY(fctx->validators));
3317 if (fctx->references == 0) {
3319 * It's now safe to destroy this fctx.
3321 bucket_empty = fctx_destroy(fctx);
3323 done = ISC_TRUE;
3324 } else {
3326 * Normal fctx startup.
3328 fctx->state = fetchstate_active;
3330 * Reset the control event for later use in shutting down
3331 * the fctx.
3333 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
3334 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
3335 NULL, NULL, NULL);
3338 UNLOCK(&res->buckets[bucketnum].lock);
3340 if (!done) {
3341 isc_result_t result;
3344 * All is well. Start working on the fetch.
3346 result = fctx_starttimer(fctx);
3347 if (result != ISC_R_SUCCESS)
3348 fctx_done(fctx, result, __LINE__);
3349 else
3350 fctx_try(fctx, ISC_FALSE);
3351 } else if (bucket_empty)
3352 empty_bucket(res);
3356 * Fetch Creation, Joining, and Cancelation.
3359 static inline isc_result_t
3360 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
3361 dns_messageid_t id, isc_taskaction_t action, void *arg,
3362 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3363 dns_fetch_t *fetch)
3365 isc_task_t *clone;
3366 dns_fetchevent_t *event;
3368 FCTXTRACE("join");
3371 * We store the task we're going to send this event to in the
3372 * sender field. We'll make the fetch the sender when we actually
3373 * send the event.
3375 clone = NULL;
3376 isc_task_attach(task, &clone);
3377 event = (dns_fetchevent_t *)
3378 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
3379 action, arg, sizeof(*event));
3380 if (event == NULL) {
3381 isc_task_detach(&clone);
3382 return (ISC_R_NOMEMORY);
3384 event->result = DNS_R_SERVFAIL;
3385 event->qtype = fctx->type;
3386 event->db = NULL;
3387 event->node = NULL;
3388 event->rdataset = rdataset;
3389 event->sigrdataset = sigrdataset;
3390 event->fetch = fetch;
3391 event->client = client;
3392 event->id = id;
3393 dns_fixedname_init(&event->foundname);
3396 * Make sure that we can store the sigrdataset in the
3397 * first event if it is needed by any of the events.
3399 if (event->sigrdataset != NULL)
3400 ISC_LIST_PREPEND(fctx->events, event, ev_link);
3401 else
3402 ISC_LIST_APPEND(fctx->events, event, ev_link);
3403 fctx->references++;
3404 fctx->client = client;
3406 fetch->magic = DNS_FETCH_MAGIC;
3407 fetch->private = fctx;
3409 return (ISC_R_SUCCESS);
3412 static isc_result_t
3413 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
3414 dns_name_t *domain, dns_rdataset_t *nameservers,
3415 unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
3417 fetchctx_t *fctx;
3418 isc_result_t result;
3419 isc_result_t iresult;
3420 isc_interval_t interval;
3421 dns_fixedname_t fixed;
3422 unsigned int findoptions = 0;
3423 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
3424 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3425 dns_name_t suffix;
3428 * Caller must be holding the lock for bucket number 'bucketnum'.
3430 REQUIRE(fctxp != NULL && *fctxp == NULL);
3432 fctx = isc_mem_get(res->buckets[bucketnum].mctx, sizeof(*fctx));
3433 if (fctx == NULL)
3434 return (ISC_R_NOMEMORY);
3435 dns_name_format(name, buf, sizeof(buf));
3436 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
3437 strcat(buf, "/"); /* checked */
3438 strcat(buf, typebuf); /* checked */
3439 fctx->info = isc_mem_strdup(res->buckets[bucketnum].mctx, buf);
3440 if (fctx->info == NULL) {
3441 result = ISC_R_NOMEMORY;
3442 goto cleanup_fetch;
3444 FCTXTRACE("create");
3445 dns_name_init(&fctx->name, NULL);
3446 result = dns_name_dup(name, res->buckets[bucketnum].mctx, &fctx->name);
3447 if (result != ISC_R_SUCCESS)
3448 goto cleanup_info;
3449 dns_name_init(&fctx->domain, NULL);
3450 dns_rdataset_init(&fctx->nameservers);
3452 fctx->type = type;
3453 fctx->options = options;
3455 * Note! We do not attach to the task. We are relying on the
3456 * resolver to ensure that this task doesn't go away while we are
3457 * using it.
3459 fctx->res = res;
3460 fctx->references = 0;
3461 fctx->bucketnum = bucketnum;
3462 fctx->state = fetchstate_init;
3463 fctx->want_shutdown = ISC_FALSE;
3464 fctx->cloned = ISC_FALSE;
3465 ISC_LIST_INIT(fctx->queries);
3466 ISC_LIST_INIT(fctx->finds);
3467 ISC_LIST_INIT(fctx->altfinds);
3468 ISC_LIST_INIT(fctx->forwaddrs);
3469 ISC_LIST_INIT(fctx->altaddrs);
3470 ISC_LIST_INIT(fctx->forwarders);
3471 fctx->fwdpolicy = dns_fwdpolicy_none;
3472 ISC_LIST_INIT(fctx->bad);
3473 ISC_LIST_INIT(fctx->edns);
3474 ISC_LIST_INIT(fctx->edns512);
3475 ISC_LIST_INIT(fctx->validators);
3476 fctx->validator = NULL;
3477 fctx->find = NULL;
3478 fctx->altfind = NULL;
3479 fctx->pending = 0;
3480 fctx->restarts = 0;
3481 fctx->querysent = 0;
3482 fctx->referrals = 0;
3483 TIME_NOW(&fctx->start);
3484 fctx->timeouts = 0;
3485 fctx->lamecount = 0;
3486 fctx->adberr = 0;
3487 fctx->neterr = 0;
3488 fctx->badresp = 0;
3489 fctx->findfail = 0;
3490 fctx->valfail = 0;
3491 fctx->result = ISC_R_FAILURE;
3492 fctx->vresult = ISC_R_SUCCESS;
3493 fctx->exitline = -1; /* sentinel */
3494 fctx->logged = ISC_FALSE;
3495 fctx->attributes = 0;
3496 fctx->spilled = ISC_FALSE;
3497 fctx->nqueries = 0;
3498 fctx->reason = NULL;
3499 fctx->rand_buf = 0;
3500 fctx->rand_bits = 0;
3501 fctx->timeout = ISC_FALSE;
3502 fctx->addrinfo = NULL;
3503 fctx->client = NULL;
3505 dns_name_init(&fctx->nsname, NULL);
3506 fctx->nsfetch = NULL;
3507 dns_rdataset_init(&fctx->nsrrset);
3509 if (domain == NULL) {
3510 dns_forwarders_t *forwarders = NULL;
3511 unsigned int labels;
3512 dns_name_t *fwdname = name;
3515 * DS records are found in the parent server.
3516 * Strip label to get the correct forwarder (if any).
3518 if (dns_rdatatype_atparent(fctx->type) &&
3519 dns_name_countlabels(name) > 1) {
3520 dns_name_init(&suffix, NULL);
3521 labels = dns_name_countlabels(name);
3522 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
3523 fwdname = &suffix;
3525 dns_fixedname_init(&fixed);
3526 domain = dns_fixedname_name(&fixed);
3527 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
3528 domain, &forwarders);
3529 if (result == ISC_R_SUCCESS)
3530 fctx->fwdpolicy = forwarders->fwdpolicy;
3532 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
3534 * The caller didn't supply a query domain and
3535 * nameservers, and we're not in forward-only mode,
3536 * so find the best nameservers to use.
3538 if (dns_rdatatype_atparent(fctx->type))
3539 findoptions |= DNS_DBFIND_NOEXACT;
3540 result = dns_view_findzonecut(res->view, name, domain,
3541 0, findoptions, ISC_TRUE,
3542 &fctx->nameservers,
3543 NULL);
3544 if (result != ISC_R_SUCCESS)
3545 goto cleanup_name;
3546 result = dns_name_dup(domain,
3547 res->buckets[bucketnum].mctx,
3548 &fctx->domain);
3549 if (result != ISC_R_SUCCESS) {
3550 dns_rdataset_disassociate(&fctx->nameservers);
3551 goto cleanup_name;
3553 } else {
3555 * We're in forward-only mode. Set the query domain.
3557 result = dns_name_dup(domain,
3558 res->buckets[bucketnum].mctx,
3559 &fctx->domain);
3560 if (result != ISC_R_SUCCESS)
3561 goto cleanup_name;
3563 } else {
3564 result = dns_name_dup(domain,
3565 res->buckets[bucketnum].mctx,
3566 &fctx->domain);
3567 if (result != ISC_R_SUCCESS)
3568 goto cleanup_name;
3569 dns_rdataset_clone(nameservers, &fctx->nameservers);
3572 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
3574 fctx->qmessage = NULL;
3575 result = dns_message_create(res->buckets[bucketnum].mctx,
3576 DNS_MESSAGE_INTENTRENDER,
3577 &fctx->qmessage);
3579 if (result != ISC_R_SUCCESS)
3580 goto cleanup_domain;
3582 fctx->rmessage = NULL;
3583 result = dns_message_create(res->buckets[bucketnum].mctx,
3584 DNS_MESSAGE_INTENTPARSE,
3585 &fctx->rmessage);
3587 if (result != ISC_R_SUCCESS)
3588 goto cleanup_qmessage;
3591 * Compute an expiration time for the entire fetch.
3593 isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
3594 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
3595 if (iresult != ISC_R_SUCCESS) {
3596 UNEXPECTED_ERROR(__FILE__, __LINE__,
3597 "isc_time_nowplusinterval: %s",
3598 isc_result_totext(iresult));
3599 result = ISC_R_UNEXPECTED;
3600 goto cleanup_rmessage;
3604 * Default retry interval initialization. We set the interval now
3605 * mostly so it won't be uninitialized. It will be set to the
3606 * correct value before a query is issued.
3608 isc_interval_set(&fctx->interval, 2, 0);
3611 * Create an inactive timer. It will be made active when the fetch
3612 * is actually started.
3614 fctx->timer = NULL;
3615 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
3616 NULL, NULL,
3617 res->buckets[bucketnum].task, fctx_timeout,
3618 fctx, &fctx->timer);
3619 if (iresult != ISC_R_SUCCESS) {
3620 UNEXPECTED_ERROR(__FILE__, __LINE__,
3621 "isc_timer_create: %s",
3622 isc_result_totext(iresult));
3623 result = ISC_R_UNEXPECTED;
3624 goto cleanup_rmessage;
3628 * Attach to the view's cache and adb.
3630 fctx->cache = NULL;
3631 dns_db_attach(res->view->cachedb, &fctx->cache);
3632 fctx->adb = NULL;
3633 dns_adb_attach(res->view->adb, &fctx->adb);
3635 ISC_LIST_INIT(fctx->events);
3636 ISC_LINK_INIT(fctx, link);
3637 fctx->magic = FCTX_MAGIC;
3639 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
3641 LOCK(&res->nlock);
3642 res->nfctx++;
3643 UNLOCK(&res->nlock);
3645 *fctxp = fctx;
3647 return (ISC_R_SUCCESS);
3649 cleanup_rmessage:
3650 dns_message_destroy(&fctx->rmessage);
3652 cleanup_qmessage:
3653 dns_message_destroy(&fctx->qmessage);
3655 cleanup_domain:
3656 if (dns_name_countlabels(&fctx->domain) > 0)
3657 dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
3658 if (dns_rdataset_isassociated(&fctx->nameservers))
3659 dns_rdataset_disassociate(&fctx->nameservers);
3661 cleanup_name:
3662 dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
3664 cleanup_info:
3665 isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
3667 cleanup_fetch:
3668 isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
3670 return (result);
3674 * Handle Responses
3676 static inline isc_boolean_t
3677 is_lame(fetchctx_t *fctx) {
3678 dns_message_t *message = fctx->rmessage;
3679 dns_name_t *name;
3680 dns_rdataset_t *rdataset;
3681 isc_result_t result;
3683 if (message->rcode != dns_rcode_noerror &&
3684 message->rcode != dns_rcode_nxdomain)
3685 return (ISC_FALSE);
3687 if (message->counts[DNS_SECTION_ANSWER] != 0)
3688 return (ISC_FALSE);
3690 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
3691 return (ISC_FALSE);
3693 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3694 while (result == ISC_R_SUCCESS) {
3695 name = NULL;
3696 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3697 for (rdataset = ISC_LIST_HEAD(name->list);
3698 rdataset != NULL;
3699 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3700 dns_namereln_t namereln;
3701 int order;
3702 unsigned int labels;
3703 if (rdataset->type != dns_rdatatype_ns)
3704 continue;
3705 namereln = dns_name_fullcompare(name, &fctx->domain,
3706 &order, &labels);
3707 if (namereln == dns_namereln_equal &&
3708 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
3709 return (ISC_FALSE);
3710 if (namereln == dns_namereln_subdomain)
3711 return (ISC_FALSE);
3712 return (ISC_TRUE);
3714 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
3717 return (ISC_FALSE);
3720 static inline void
3721 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
3722 char namebuf[DNS_NAME_FORMATSIZE];
3723 char domainbuf[DNS_NAME_FORMATSIZE];
3724 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3726 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3727 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3728 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
3729 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
3730 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
3731 "lame server resolving '%s' (in '%s'?): %s",
3732 namebuf, domainbuf, addrbuf);
3735 static inline void
3736 log_formerr(fetchctx_t *fctx, const char *format, ...) {
3737 char nsbuf[ISC_SOCKADDR_FORMATSIZE];
3738 char clbuf[ISC_SOCKADDR_FORMATSIZE];
3739 const char *clmsg = "";
3740 char msgbuf[2048];
3741 va_list args;
3743 va_start(args, format);
3744 vsnprintf(msgbuf, sizeof(msgbuf), format, args);
3745 va_end(args);
3747 isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
3749 if (fctx->client != NULL) {
3750 clmsg = " for client ";
3751 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
3752 } else {
3753 clbuf[0] = '\0';
3756 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3757 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
3758 "DNS format error from %s resolving %s%s%s: %s",
3759 nsbuf, fctx->info, clmsg, clbuf, msgbuf);
3762 static inline isc_result_t
3763 same_question(fetchctx_t *fctx) {
3764 isc_result_t result;
3765 dns_message_t *message = fctx->rmessage;
3766 dns_name_t *name;
3767 dns_rdataset_t *rdataset;
3770 * Caller must be holding the fctx lock.
3774 * XXXRTH Currently we support only one question.
3776 if (message->counts[DNS_SECTION_QUESTION] != 1) {
3777 log_formerr(fctx, "too many questions");
3778 return (DNS_R_FORMERR);
3781 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3782 if (result != ISC_R_SUCCESS)
3783 return (result);
3784 name = NULL;
3785 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
3786 rdataset = ISC_LIST_HEAD(name->list);
3787 INSIST(rdataset != NULL);
3788 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
3790 if (fctx->type != rdataset->type ||
3791 fctx->res->rdclass != rdataset->rdclass ||
3792 !dns_name_equal(&fctx->name, name)) {
3793 char namebuf[DNS_NAME_FORMATSIZE];
3794 char class[DNS_RDATACLASS_FORMATSIZE];
3795 char type[DNS_RDATATYPE_FORMATSIZE];
3797 dns_name_format(name, namebuf, sizeof(namebuf));
3798 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
3799 dns_rdatatype_format(rdataset->type, type, sizeof(type));
3800 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
3801 namebuf, class, type);
3802 return (DNS_R_FORMERR);
3805 return (ISC_R_SUCCESS);
3808 static void
3809 clone_results(fetchctx_t *fctx) {
3810 dns_fetchevent_t *event, *hevent;
3811 isc_result_t result;
3812 dns_name_t *name, *hname;
3814 FCTXTRACE("clone_results");
3817 * Set up any other events to have the same data as the first
3818 * event.
3820 * Caller must be holding the appropriate lock.
3823 fctx->cloned = ISC_TRUE;
3824 hevent = ISC_LIST_HEAD(fctx->events);
3825 if (hevent == NULL)
3826 return;
3827 hname = dns_fixedname_name(&hevent->foundname);
3828 for (event = ISC_LIST_NEXT(hevent, ev_link);
3829 event != NULL;
3830 event = ISC_LIST_NEXT(event, ev_link)) {
3831 name = dns_fixedname_name(&event->foundname);
3832 result = dns_name_copy(hname, name, NULL);
3833 if (result != ISC_R_SUCCESS)
3834 event->result = result;
3835 else
3836 event->result = hevent->result;
3837 dns_db_attach(hevent->db, &event->db);
3838 dns_db_attachnode(hevent->db, hevent->node, &event->node);
3839 INSIST(hevent->rdataset != NULL);
3840 INSIST(event->rdataset != NULL);
3841 if (dns_rdataset_isassociated(hevent->rdataset))
3842 dns_rdataset_clone(hevent->rdataset, event->rdataset);
3843 INSIST(! (hevent->sigrdataset == NULL &&
3844 event->sigrdataset != NULL));
3845 if (hevent->sigrdataset != NULL &&
3846 dns_rdataset_isassociated(hevent->sigrdataset) &&
3847 event->sigrdataset != NULL)
3848 dns_rdataset_clone(hevent->sigrdataset,
3849 event->sigrdataset);
3853 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3854 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3855 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3856 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3857 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3858 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3859 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3863 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3864 * no references and is no longer waiting for any events). If this
3865 * was the last fctx in the resolver, destroy the resolver.
3867 * Requires:
3868 * '*fctx' is shutting down.
3870 static void
3871 maybe_destroy(fetchctx_t *fctx) {
3872 unsigned int bucketnum;
3873 isc_boolean_t bucket_empty = ISC_FALSE;
3874 dns_resolver_t *res = fctx->res;
3875 dns_validator_t *validator, *next_validator;
3877 REQUIRE(SHUTTINGDOWN(fctx));
3879 if (fctx->pending != 0 || fctx->nqueries != 0)
3880 return;
3882 for (validator = ISC_LIST_HEAD(fctx->validators);
3883 validator != NULL; validator = next_validator) {
3884 next_validator = ISC_LIST_NEXT(validator, link);
3885 dns_validator_cancel(validator);
3887 * If this is a active validator wait for the cancel
3888 * to complete before calling dns_validator_destroy().
3890 if (validator == fctx->validator)
3891 continue;
3892 ISC_LIST_UNLINK(fctx->validators, validator, link);
3893 dns_validator_destroy(&validator);
3896 bucketnum = fctx->bucketnum;
3897 LOCK(&res->buckets[bucketnum].lock);
3898 if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators))
3899 bucket_empty = fctx_destroy(fctx);
3900 UNLOCK(&res->buckets[bucketnum].lock);
3902 if (bucket_empty)
3903 empty_bucket(res);
3907 * The validator has finished.
3909 static void
3910 validated(isc_task_t *task, isc_event_t *event) {
3911 isc_result_t result = ISC_R_SUCCESS;
3912 isc_result_t eresult = ISC_R_SUCCESS;
3913 isc_stdtime_t now;
3914 fetchctx_t *fctx;
3915 dns_validatorevent_t *vevent;
3916 dns_fetchevent_t *hevent;
3917 dns_rdataset_t *ardataset = NULL;
3918 dns_rdataset_t *asigrdataset = NULL;
3919 dns_dbnode_t *node = NULL;
3920 isc_boolean_t negative;
3921 isc_boolean_t chaining;
3922 isc_boolean_t sentresponse;
3923 isc_uint32_t ttl;
3924 dns_dbnode_t *nsnode = NULL;
3925 dns_name_t *name;
3926 dns_rdataset_t *rdataset;
3927 dns_rdataset_t *sigrdataset;
3928 dns_valarg_t *valarg;
3929 dns_adbaddrinfo_t *addrinfo;
3931 UNUSED(task); /* for now */
3933 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
3934 valarg = event->ev_arg;
3935 fctx = valarg->fctx;
3936 addrinfo = valarg->addrinfo;
3937 REQUIRE(VALID_FCTX(fctx));
3938 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
3940 vevent = (dns_validatorevent_t *)event;
3941 fctx->vresult = vevent->result;
3943 FCTXTRACE("received validation completion event");
3945 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
3946 fctx->validator = NULL;
3949 * Destroy the validator early so that we can
3950 * destroy the fctx if necessary.
3952 dns_validator_destroy(&vevent->validator);
3953 isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
3954 valarg, sizeof(*valarg));
3956 negative = ISC_TF(vevent->rdataset == NULL);
3958 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
3961 * If shutting down, ignore the results. Check to see if we're
3962 * done waiting for validator completions and ADB pending events; if
3963 * so, destroy the fctx.
3965 if (SHUTTINGDOWN(fctx) && !sentresponse) {
3966 maybe_destroy(fctx); /* Locks bucket. */
3967 goto cleanup_event;
3970 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3973 * If chaining, we need to make sure that the right result code is
3974 * returned, and that the rdatasets are bound.
3976 if (vevent->result == ISC_R_SUCCESS &&
3977 !negative &&
3978 vevent->rdataset != NULL &&
3979 CHAINING(vevent->rdataset))
3981 if (vevent->rdataset->type == dns_rdatatype_cname)
3982 eresult = DNS_R_CNAME;
3983 else {
3984 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
3985 eresult = DNS_R_DNAME;
3987 chaining = ISC_TRUE;
3988 } else
3989 chaining = ISC_FALSE;
3992 * Either we're not shutting down, or we are shutting down but want
3993 * to cache the result anyway (if this was a validation started by
3994 * a query with cd set)
3997 hevent = ISC_LIST_HEAD(fctx->events);
3998 if (hevent != NULL) {
3999 if (!negative && !chaining &&
4000 (fctx->type == dns_rdatatype_any ||
4001 fctx->type == dns_rdatatype_rrsig ||
4002 fctx->type == dns_rdatatype_sig)) {
4004 * Don't bind rdatasets; the caller
4005 * will iterate the node.
4007 } else {
4008 ardataset = hevent->rdataset;
4009 asigrdataset = hevent->sigrdataset;
4013 if (vevent->result != ISC_R_SUCCESS) {
4014 FCTXTRACE("validation failed");
4015 inc_stats(fctx->res, dns_resstatscounter_valfail);
4016 fctx->valfail++;
4017 fctx->vresult = vevent->result;
4018 result = ISC_R_NOTFOUND;
4019 if (vevent->rdataset != NULL)
4020 result = dns_db_findnode(fctx->cache, vevent->name,
4021 ISC_TRUE, &node);
4022 if (result == ISC_R_SUCCESS)
4023 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
4024 vevent->type, 0);
4025 if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
4026 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
4027 dns_rdatatype_rrsig,
4028 vevent->type);
4029 if (result == ISC_R_SUCCESS)
4030 dns_db_detachnode(fctx->cache, &node);
4031 result = vevent->result;
4032 add_bad(fctx, addrinfo, result, badns_validation);
4033 isc_event_free(&event);
4034 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4035 INSIST(fctx->validator == NULL);
4036 fctx->validator = ISC_LIST_HEAD(fctx->validators);
4037 if (fctx->validator != NULL) {
4038 dns_validator_send(fctx->validator);
4039 } else if (sentresponse)
4040 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4041 else
4042 fctx_try(fctx, ISC_TRUE); /* Locks bucket. */
4043 return;
4046 isc_stdtime_get(&now);
4048 if (negative) {
4049 dns_rdatatype_t covers;
4050 FCTXTRACE("nonexistence validation OK");
4052 inc_stats(fctx->res, dns_resstatscounter_valnegsuccess);
4054 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
4055 covers = dns_rdatatype_any;
4056 else
4057 covers = fctx->type;
4059 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
4060 &node);
4061 if (result != ISC_R_SUCCESS)
4062 goto noanswer_response;
4065 * If we are asking for a SOA record set the cache time
4066 * to zero to facilitate locating the containing zone of
4067 * a arbitrary zone.
4069 ttl = fctx->res->view->maxncachettl;
4070 if (fctx->type == dns_rdatatype_soa &&
4071 covers == dns_rdatatype_any &&
4072 fctx->res->zero_no_soa_ttl)
4073 ttl = 0;
4075 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4076 covers, now, ttl, vevent->optout,
4077 ardataset, &eresult);
4078 if (result != ISC_R_SUCCESS)
4079 goto noanswer_response;
4080 goto answer_response;
4081 } else
4082 inc_stats(fctx->res, dns_resstatscounter_valsuccess);
4084 FCTXTRACE("validation OK");
4086 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
4088 result = dns_rdataset_addnoqname(vevent->rdataset,
4089 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
4090 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4091 INSIST(vevent->sigrdataset != NULL);
4092 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
4093 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
4094 result = dns_rdataset_addclosest(vevent->rdataset,
4095 vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
4096 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4101 * The data was already cached as pending data.
4102 * Re-cache it as secure and bind the cached
4103 * rdatasets to the first event on the fetch
4104 * event list.
4106 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
4107 if (result != ISC_R_SUCCESS)
4108 goto noanswer_response;
4110 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4111 vevent->rdataset, 0, ardataset);
4112 if (result != ISC_R_SUCCESS &&
4113 result != DNS_R_UNCHANGED)
4114 goto noanswer_response;
4115 if (ardataset != NULL && ardataset->type == 0) {
4116 if (NXDOMAIN(ardataset))
4117 eresult = DNS_R_NCACHENXDOMAIN;
4118 else
4119 eresult = DNS_R_NCACHENXRRSET;
4120 } else if (vevent->sigrdataset != NULL) {
4121 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4122 vevent->sigrdataset, 0,
4123 asigrdataset);
4124 if (result != ISC_R_SUCCESS &&
4125 result != DNS_R_UNCHANGED)
4126 goto noanswer_response;
4129 if (sentresponse) {
4131 * If we only deferred the destroy because we wanted to cache
4132 * the data, destroy now.
4134 dns_db_detachnode(fctx->cache, &node);
4135 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4136 if (SHUTTINGDOWN(fctx))
4137 maybe_destroy(fctx); /* Locks bucket. */
4138 goto cleanup_event;
4141 if (!ISC_LIST_EMPTY(fctx->validators)) {
4142 INSIST(!negative);
4143 INSIST(fctx->type == dns_rdatatype_any ||
4144 fctx->type == dns_rdatatype_rrsig ||
4145 fctx->type == dns_rdatatype_sig);
4147 * Don't send a response yet - we have
4148 * more rdatasets that still need to
4149 * be validated.
4151 dns_db_detachnode(fctx->cache, &node);
4152 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4153 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
4154 goto cleanup_event;
4157 answer_response:
4159 * Cache any NS/NSEC records that happened to be validated.
4161 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
4162 while (result == ISC_R_SUCCESS) {
4163 name = NULL;
4164 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
4165 &name);
4166 for (rdataset = ISC_LIST_HEAD(name->list);
4167 rdataset != NULL;
4168 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4169 if ((rdataset->type != dns_rdatatype_ns &&
4170 rdataset->type != dns_rdatatype_nsec) ||
4171 rdataset->trust != dns_trust_secure)
4172 continue;
4173 for (sigrdataset = ISC_LIST_HEAD(name->list);
4174 sigrdataset != NULL;
4175 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4176 if (sigrdataset->type != dns_rdatatype_rrsig ||
4177 sigrdataset->covers != rdataset->type)
4178 continue;
4179 break;
4181 if (sigrdataset == NULL ||
4182 sigrdataset->trust != dns_trust_secure)
4183 continue;
4184 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
4185 &nsnode);
4186 if (result != ISC_R_SUCCESS)
4187 continue;
4189 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
4190 now, rdataset, 0, NULL);
4191 if (result == ISC_R_SUCCESS)
4192 result = dns_db_addrdataset(fctx->cache, nsnode,
4193 NULL, now,
4194 sigrdataset, 0,
4195 NULL);
4196 dns_db_detachnode(fctx->cache, &nsnode);
4198 result = dns_message_nextname(fctx->rmessage,
4199 DNS_SECTION_AUTHORITY);
4202 result = ISC_R_SUCCESS;
4205 * Respond with an answer, positive or negative,
4206 * as opposed to an error. 'node' must be non-NULL.
4209 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4211 if (hevent != NULL) {
4212 hevent->result = eresult;
4213 RUNTIME_CHECK(dns_name_copy(vevent->name,
4214 dns_fixedname_name(&hevent->foundname), NULL)
4215 == ISC_R_SUCCESS);
4216 dns_db_attach(fctx->cache, &hevent->db);
4217 dns_db_transfernode(fctx->cache, &node, &hevent->node);
4218 clone_results(fctx);
4221 noanswer_response:
4222 if (node != NULL)
4223 dns_db_detachnode(fctx->cache, &node);
4225 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4227 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4229 cleanup_event:
4230 INSIST(node == NULL);
4231 isc_event_free(&event);
4234 static inline isc_result_t
4235 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
4236 isc_stdtime_t now)
4238 dns_rdataset_t *rdataset, *sigrdataset;
4239 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
4240 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
4241 dns_dbnode_t *node, **anodep;
4242 dns_db_t **adbp;
4243 dns_name_t *aname;
4244 dns_resolver_t *res;
4245 isc_boolean_t need_validation, secure_domain, have_answer;
4246 isc_result_t result, eresult;
4247 dns_fetchevent_t *event;
4248 unsigned int options;
4249 isc_task_t *task;
4250 isc_boolean_t fail;
4251 unsigned int valoptions = 0;
4254 * The appropriate bucket lock must be held.
4257 res = fctx->res;
4258 need_validation = ISC_FALSE;
4259 secure_domain = ISC_FALSE;
4260 have_answer = ISC_FALSE;
4261 eresult = ISC_R_SUCCESS;
4262 task = res->buckets[fctx->bucketnum].task;
4265 * Is DNSSEC validation required for this name?
4267 if (res->view->enablevalidation) {
4268 result = dns_view_issecuredomain(res->view, name,
4269 &secure_domain);
4270 if (result != ISC_R_SUCCESS)
4271 return (result);
4273 if (!secure_domain && res->view->dlv != NULL) {
4274 valoptions = DNS_VALIDATOR_DLV;
4275 secure_domain = ISC_TRUE;
4279 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4280 need_validation = ISC_FALSE;
4281 else
4282 need_validation = secure_domain;
4284 adbp = NULL;
4285 aname = NULL;
4286 anodep = NULL;
4287 ardataset = NULL;
4288 asigrdataset = NULL;
4289 event = NULL;
4290 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
4291 !need_validation) {
4292 have_answer = ISC_TRUE;
4293 event = ISC_LIST_HEAD(fctx->events);
4294 if (event != NULL) {
4295 adbp = &event->db;
4296 aname = dns_fixedname_name(&event->foundname);
4297 result = dns_name_copy(name, aname, NULL);
4298 if (result != ISC_R_SUCCESS)
4299 return (result);
4300 anodep = &event->node;
4302 * If this is an ANY, SIG or RRSIG query, we're not
4303 * going to return any rdatasets, unless we encountered
4304 * a CNAME or DNAME as "the answer". In this case,
4305 * we're going to return DNS_R_CNAME or DNS_R_DNAME
4306 * and we must set up the rdatasets.
4308 if ((fctx->type != dns_rdatatype_any &&
4309 fctx->type != dns_rdatatype_rrsig &&
4310 fctx->type != dns_rdatatype_sig) ||
4311 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
4312 ardataset = event->rdataset;
4313 asigrdataset = event->sigrdataset;
4319 * Find or create the cache node.
4321 node = NULL;
4322 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4323 if (result != ISC_R_SUCCESS)
4324 return (result);
4327 * Cache or validate each cacheable rdataset.
4329 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
4330 for (rdataset = ISC_LIST_HEAD(name->list);
4331 rdataset != NULL;
4332 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4333 if (!CACHE(rdataset))
4334 continue;
4335 if (CHECKNAMES(rdataset)) {
4336 char namebuf[DNS_NAME_FORMATSIZE];
4337 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4338 char classbuf[DNS_RDATATYPE_FORMATSIZE];
4340 dns_name_format(name, namebuf, sizeof(namebuf));
4341 dns_rdatatype_format(rdataset->type, typebuf,
4342 sizeof(typebuf));
4343 dns_rdataclass_format(rdataset->rdclass, classbuf,
4344 sizeof(classbuf));
4345 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
4346 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
4347 "check-names %s %s/%s/%s",
4348 fail ? "failure" : "warning",
4349 namebuf, typebuf, classbuf);
4350 if (fail) {
4351 if (ANSWER(rdataset)) {
4352 dns_db_detachnode(fctx->cache, &node);
4353 return (DNS_R_BADNAME);
4355 continue;
4360 * Enforce the configure maximum cache TTL.
4362 if (rdataset->ttl > res->view->maxcachettl)
4363 rdataset->ttl = res->view->maxcachettl;
4366 * If this rrset is in a secure domain, do DNSSEC validation
4367 * for it, unless it is glue.
4369 if (secure_domain && rdataset->trust != dns_trust_glue) {
4370 dns_trust_t trust;
4372 * RRSIGs are validated as part of validating the
4373 * type they cover.
4375 if (rdataset->type == dns_rdatatype_rrsig)
4376 continue;
4378 * Find the SIG for this rdataset, if we have it.
4380 for (sigrdataset = ISC_LIST_HEAD(name->list);
4381 sigrdataset != NULL;
4382 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4383 if (sigrdataset->type == dns_rdatatype_rrsig &&
4384 sigrdataset->covers == rdataset->type)
4385 break;
4387 if (sigrdataset == NULL) {
4388 if (!ANSWER(rdataset) && need_validation) {
4390 * Ignore non-answer rdatasets that
4391 * are missing signatures.
4393 continue;
4398 * Normalize the rdataset and sigrdataset TTLs.
4400 if (sigrdataset != NULL) {
4401 rdataset->ttl = ISC_MIN(rdataset->ttl,
4402 sigrdataset->ttl);
4403 sigrdataset->ttl = rdataset->ttl;
4407 * Reject out of bailiwick additional records
4408 * without RRSIGs as they can't possibly validate
4409 * as "secure" and as we will never never want to
4410 * store these as "answers" after validation.
4412 if (rdataset->trust == dns_trust_additional &&
4413 sigrdataset == NULL && EXTERNAL(rdataset))
4414 continue;
4417 * XXXMPA: If we store as "answer" after validating
4418 * then we need to do bailiwick processing and
4419 * also need to track whether RRsets are in or
4420 * out of bailiwick. This will require a another
4421 * pending trust level.
4423 * Cache this rdataset/sigrdataset pair as
4424 * pending data. Track whether it was additional
4425 * or not.
4427 if (rdataset->trust == dns_trust_additional)
4428 trust = dns_trust_pending_additional;
4429 else
4430 trust = dns_trust_pending_answer;
4432 rdataset->trust = trust;
4433 if (sigrdataset != NULL)
4434 sigrdataset->trust = trust;
4435 if (!need_validation || !ANSWER(rdataset)) {
4436 addedrdataset = ardataset;
4437 result = dns_db_addrdataset(fctx->cache, node,
4438 NULL, now, rdataset,
4439 0, addedrdataset);
4440 if (result == DNS_R_UNCHANGED) {
4441 result = ISC_R_SUCCESS;
4442 if (!need_validation &&
4443 ardataset != NULL &&
4444 ardataset->type == 0) {
4446 * The answer in the cache is
4447 * better than the answer we
4448 * found, and is a negative
4449 * cache entry, so we must set
4450 * eresult appropriately.
4452 if (NXDOMAIN(ardataset))
4453 eresult =
4454 DNS_R_NCACHENXDOMAIN;
4455 else
4456 eresult =
4457 DNS_R_NCACHENXRRSET;
4459 * We have a negative response
4460 * from the cache so don't
4461 * attempt to add the RRSIG
4462 * rrset.
4464 continue;
4467 if (result != ISC_R_SUCCESS)
4468 break;
4469 if (sigrdataset != NULL) {
4470 addedrdataset = asigrdataset;
4471 result = dns_db_addrdataset(fctx->cache,
4472 node, NULL, now,
4473 sigrdataset, 0,
4474 addedrdataset);
4475 if (result == DNS_R_UNCHANGED)
4476 result = ISC_R_SUCCESS;
4477 if (result != ISC_R_SUCCESS)
4478 break;
4479 } else if (!ANSWER(rdataset))
4480 continue;
4483 if (ANSWER(rdataset) && need_validation) {
4484 if (fctx->type != dns_rdatatype_any &&
4485 fctx->type != dns_rdatatype_rrsig &&
4486 fctx->type != dns_rdatatype_sig) {
4488 * This is The Answer. We will
4489 * validate it, but first we cache
4490 * the rest of the response - it may
4491 * contain useful keys.
4493 INSIST(valrdataset == NULL &&
4494 valsigrdataset == NULL);
4495 valrdataset = rdataset;
4496 valsigrdataset = sigrdataset;
4497 } else {
4499 * This is one of (potentially)
4500 * multiple answers to an ANY
4501 * or SIG query. To keep things
4502 * simple, we just start the
4503 * validator right away rather
4504 * than caching first and
4505 * having to remember which
4506 * rdatasets needed validation.
4508 result = valcreate(fctx, addrinfo,
4509 name, rdataset->type,
4510 rdataset,
4511 sigrdataset,
4512 valoptions, task);
4514 * Defer any further validations.
4515 * This prevents multiple validators
4516 * from manipulating fctx->rmessage
4517 * simultaneously.
4519 valoptions |= DNS_VALIDATOR_DEFER;
4521 } else if (CHAINING(rdataset)) {
4522 if (rdataset->type == dns_rdatatype_cname)
4523 eresult = DNS_R_CNAME;
4524 else {
4525 INSIST(rdataset->type ==
4526 dns_rdatatype_dname);
4527 eresult = DNS_R_DNAME;
4530 } else if (!EXTERNAL(rdataset)) {
4532 * It's OK to cache this rdataset now.
4534 if (ANSWER(rdataset))
4535 addedrdataset = ardataset;
4536 else if (ANSWERSIG(rdataset))
4537 addedrdataset = asigrdataset;
4538 else
4539 addedrdataset = NULL;
4540 if (CHAINING(rdataset)) {
4541 if (rdataset->type == dns_rdatatype_cname)
4542 eresult = DNS_R_CNAME;
4543 else {
4544 INSIST(rdataset->type ==
4545 dns_rdatatype_dname);
4546 eresult = DNS_R_DNAME;
4549 if (rdataset->trust == dns_trust_glue &&
4550 (rdataset->type == dns_rdatatype_ns ||
4551 (rdataset->type == dns_rdatatype_rrsig &&
4552 rdataset->covers == dns_rdatatype_ns))) {
4554 * If the trust level is 'dns_trust_glue'
4555 * then we are adding data from a referral
4556 * we got while executing the search algorithm.
4557 * New referral data always takes precedence
4558 * over the existing cache contents.
4560 options = DNS_DBADD_FORCE;
4561 } else
4562 options = 0;
4564 * Now we can add the rdataset.
4566 result = dns_db_addrdataset(fctx->cache,
4567 node, NULL, now,
4568 rdataset,
4569 options,
4570 addedrdataset);
4571 if (result == DNS_R_UNCHANGED) {
4572 if (ANSWER(rdataset) &&
4573 ardataset != NULL &&
4574 ardataset->type == 0) {
4576 * The answer in the cache is better
4577 * than the answer we found, and is
4578 * a negative cache entry, so we
4579 * must set eresult appropriately.
4581 if (NXDOMAIN(ardataset))
4582 eresult = DNS_R_NCACHENXDOMAIN;
4583 else
4584 eresult = DNS_R_NCACHENXRRSET;
4586 result = ISC_R_SUCCESS;
4587 } else if (result != ISC_R_SUCCESS)
4588 break;
4592 if (valrdataset != NULL)
4593 result = valcreate(fctx, addrinfo, name, fctx->type,
4594 valrdataset, valsigrdataset, valoptions,
4595 task);
4597 if (result == ISC_R_SUCCESS && have_answer) {
4598 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4599 if (event != NULL) {
4601 * Negative results must be indicated in event->result.
4603 if (dns_rdataset_isassociated(event->rdataset) &&
4604 event->rdataset->type == dns_rdatatype_none) {
4605 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
4606 eresult == DNS_R_NCACHENXRRSET);
4608 event->result = eresult;
4609 dns_db_attach(fctx->cache, adbp);
4610 dns_db_transfernode(fctx->cache, &node, anodep);
4611 clone_results(fctx);
4615 if (node != NULL)
4616 dns_db_detachnode(fctx->cache, &node);
4618 return (result);
4621 static inline isc_result_t
4622 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
4624 isc_result_t result;
4625 dns_section_t section;
4626 dns_name_t *name;
4628 FCTXTRACE("cache_message");
4630 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
4632 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4634 for (section = DNS_SECTION_ANSWER;
4635 section <= DNS_SECTION_ADDITIONAL;
4636 section++) {
4637 result = dns_message_firstname(fctx->rmessage, section);
4638 while (result == ISC_R_SUCCESS) {
4639 name = NULL;
4640 dns_message_currentname(fctx->rmessage, section,
4641 &name);
4642 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
4643 result = cache_name(fctx, name, addrinfo, now);
4644 if (result != ISC_R_SUCCESS)
4645 break;
4647 result = dns_message_nextname(fctx->rmessage, section);
4649 if (result != ISC_R_NOMORE)
4650 break;
4652 if (result == ISC_R_NOMORE)
4653 result = ISC_R_SUCCESS;
4655 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4657 return (result);
4661 * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
4663 static isc_result_t
4664 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
4665 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
4666 isc_boolean_t optout, dns_rdataset_t *ardataset,
4667 isc_result_t *eresultp)
4669 isc_result_t result;
4670 dns_rdataset_t rdataset;
4672 if (ardataset == NULL) {
4673 dns_rdataset_init(&rdataset);
4674 ardataset = &rdataset;
4676 result = dns_ncache_addoptout(message, cache, node, covers, now,
4677 maxttl, optout, ardataset);
4678 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
4680 * If the cache now contains a negative entry and we
4681 * care about whether it is DNS_R_NCACHENXDOMAIN or
4682 * DNS_R_NCACHENXRRSET then extract it.
4684 if (ardataset->type == 0) {
4686 * The cache data is a negative cache entry.
4688 if (NXDOMAIN(ardataset))
4689 *eresultp = DNS_R_NCACHENXDOMAIN;
4690 else
4691 *eresultp = DNS_R_NCACHENXRRSET;
4692 } else {
4694 * Either we don't care about the nature of the
4695 * cache rdataset (because no fetch is interested
4696 * in the outcome), or the cache rdataset is not
4697 * a negative cache entry. Whichever case it is,
4698 * we can return success.
4700 * XXXRTH There's a CNAME/DNAME problem here.
4702 *eresultp = ISC_R_SUCCESS;
4704 result = ISC_R_SUCCESS;
4706 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
4707 dns_rdataset_disassociate(ardataset);
4709 return (result);
4712 static inline isc_result_t
4713 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
4714 dns_rdatatype_t covers, isc_stdtime_t now)
4716 isc_result_t result, eresult;
4717 dns_name_t *name;
4718 dns_resolver_t *res;
4719 dns_db_t **adbp;
4720 dns_dbnode_t *node, **anodep;
4721 dns_rdataset_t *ardataset;
4722 isc_boolean_t need_validation, secure_domain;
4723 dns_name_t *aname;
4724 dns_fetchevent_t *event;
4725 isc_uint32_t ttl;
4726 unsigned int valoptions = 0;
4728 FCTXTRACE("ncache_message");
4730 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
4732 res = fctx->res;
4733 need_validation = ISC_FALSE;
4734 secure_domain = ISC_FALSE;
4735 eresult = ISC_R_SUCCESS;
4736 name = &fctx->name;
4737 node = NULL;
4740 * XXXMPA remove when we follow cnames and adjust the setting
4741 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4743 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
4746 * Is DNSSEC validation required for this name?
4748 if (fctx->res->view->enablevalidation) {
4749 result = dns_view_issecuredomain(res->view, name,
4750 &secure_domain);
4751 if (result != ISC_R_SUCCESS)
4752 return (result);
4754 if (!secure_domain && res->view->dlv != NULL) {
4755 valoptions = DNS_VALIDATOR_DLV;
4756 secure_domain = ISC_TRUE;
4760 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4761 need_validation = ISC_FALSE;
4762 else
4763 need_validation = secure_domain;
4765 if (secure_domain) {
4767 * Mark all rdatasets as pending.
4769 dns_rdataset_t *trdataset;
4770 dns_name_t *tname;
4772 result = dns_message_firstname(fctx->rmessage,
4773 DNS_SECTION_AUTHORITY);
4774 while (result == ISC_R_SUCCESS) {
4775 tname = NULL;
4776 dns_message_currentname(fctx->rmessage,
4777 DNS_SECTION_AUTHORITY,
4778 &tname);
4779 for (trdataset = ISC_LIST_HEAD(tname->list);
4780 trdataset != NULL;
4781 trdataset = ISC_LIST_NEXT(trdataset, link))
4782 trdataset->trust = dns_trust_pending_answer;
4783 result = dns_message_nextname(fctx->rmessage,
4784 DNS_SECTION_AUTHORITY);
4786 if (result != ISC_R_NOMORE)
4787 return (result);
4791 if (need_validation) {
4793 * Do negative response validation.
4795 result = valcreate(fctx, addrinfo, name, fctx->type,
4796 NULL, NULL, valoptions,
4797 res->buckets[fctx->bucketnum].task);
4799 * If validation is necessary, return now. Otherwise continue
4800 * to process the message, letting the validation complete
4801 * in its own good time.
4803 return (result);
4806 LOCK(&res->buckets[fctx->bucketnum].lock);
4808 adbp = NULL;
4809 aname = NULL;
4810 anodep = NULL;
4811 ardataset = NULL;
4812 if (!HAVE_ANSWER(fctx)) {
4813 event = ISC_LIST_HEAD(fctx->events);
4814 if (event != NULL) {
4815 adbp = &event->db;
4816 aname = dns_fixedname_name(&event->foundname);
4817 result = dns_name_copy(name, aname, NULL);
4818 if (result != ISC_R_SUCCESS)
4819 goto unlock;
4820 anodep = &event->node;
4821 ardataset = event->rdataset;
4823 } else
4824 event = NULL;
4826 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4827 if (result != ISC_R_SUCCESS)
4828 goto unlock;
4831 * If we are asking for a SOA record set the cache time
4832 * to zero to facilitate locating the containing zone of
4833 * a arbitrary zone.
4835 ttl = fctx->res->view->maxncachettl;
4836 if (fctx->type == dns_rdatatype_soa &&
4837 covers == dns_rdatatype_any &&
4838 fctx->res->zero_no_soa_ttl)
4839 ttl = 0;
4841 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4842 covers, now, ttl, ISC_FALSE,
4843 ardataset, &eresult);
4844 if (result != ISC_R_SUCCESS)
4845 goto unlock;
4847 if (!HAVE_ANSWER(fctx)) {
4848 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4849 if (event != NULL) {
4850 event->result = eresult;
4851 dns_db_attach(fctx->cache, adbp);
4852 dns_db_transfernode(fctx->cache, &node, anodep);
4853 clone_results(fctx);
4857 unlock:
4858 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4860 if (node != NULL)
4861 dns_db_detachnode(fctx->cache, &node);
4863 return (result);
4866 static inline void
4867 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
4868 isc_boolean_t external, isc_boolean_t gluing)
4870 name->attributes |= DNS_NAMEATTR_CACHE;
4871 if (gluing) {
4872 rdataset->trust = dns_trust_glue;
4874 * Glue with 0 TTL causes problems. We force the TTL to
4875 * 1 second to prevent this.
4877 if (rdataset->ttl == 0)
4878 rdataset->ttl = 1;
4879 } else
4880 rdataset->trust = dns_trust_additional;
4882 * Avoid infinite loops by only marking new rdatasets.
4884 if (!CACHE(rdataset)) {
4885 name->attributes |= DNS_NAMEATTR_CHASE;
4886 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
4888 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
4889 if (external)
4890 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
4893 static isc_result_t
4894 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
4895 dns_section_t section)
4897 fetchctx_t *fctx = arg;
4898 isc_result_t result;
4899 dns_name_t *name;
4900 dns_rdataset_t *rdataset;
4901 isc_boolean_t external;
4902 dns_rdatatype_t rtype;
4903 isc_boolean_t gluing;
4905 REQUIRE(VALID_FCTX(fctx));
4907 #if CHECK_FOR_GLUE_IN_ANSWER
4908 if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
4909 return (ISC_R_SUCCESS);
4910 #endif
4912 if (GLUING(fctx))
4913 gluing = ISC_TRUE;
4914 else
4915 gluing = ISC_FALSE;
4916 name = NULL;
4917 rdataset = NULL;
4918 result = dns_message_findname(fctx->rmessage, section, addname,
4919 dns_rdatatype_any, 0, &name, NULL);
4920 if (result == ISC_R_SUCCESS) {
4921 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4922 if (type == dns_rdatatype_a) {
4923 for (rdataset = ISC_LIST_HEAD(name->list);
4924 rdataset != NULL;
4925 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4926 if (rdataset->type == dns_rdatatype_rrsig)
4927 rtype = rdataset->covers;
4928 else
4929 rtype = rdataset->type;
4930 if (rtype == dns_rdatatype_a ||
4931 rtype == dns_rdatatype_aaaa)
4932 mark_related(name, rdataset, external,
4933 gluing);
4935 } else {
4936 result = dns_message_findtype(name, type, 0,
4937 &rdataset);
4938 if (result == ISC_R_SUCCESS) {
4939 mark_related(name, rdataset, external, gluing);
4941 * Do we have its SIG too?
4943 rdataset = NULL;
4944 result = dns_message_findtype(name,
4945 dns_rdatatype_rrsig,
4946 type, &rdataset);
4947 if (result == ISC_R_SUCCESS)
4948 mark_related(name, rdataset, external,
4949 gluing);
4954 return (ISC_R_SUCCESS);
4957 static isc_result_t
4958 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
4959 return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
4962 #ifndef CHECK_FOR_GLUE_IN_ANSWER
4963 #define CHECK_FOR_GLUE_IN_ANSWER 0
4964 #endif
4965 #if CHECK_FOR_GLUE_IN_ANSWER
4966 static isc_result_t
4967 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
4968 return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
4970 #endif
4972 static void
4973 chase_additional(fetchctx_t *fctx) {
4974 isc_boolean_t rescan;
4975 dns_section_t section = DNS_SECTION_ADDITIONAL;
4976 isc_result_t result;
4978 again:
4979 rescan = ISC_FALSE;
4981 for (result = dns_message_firstname(fctx->rmessage, section);
4982 result == ISC_R_SUCCESS;
4983 result = dns_message_nextname(fctx->rmessage, section)) {
4984 dns_name_t *name = NULL;
4985 dns_rdataset_t *rdataset;
4986 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
4987 &name);
4988 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
4989 continue;
4990 name->attributes &= ~DNS_NAMEATTR_CHASE;
4991 for (rdataset = ISC_LIST_HEAD(name->list);
4992 rdataset != NULL;
4993 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4994 if (CHASE(rdataset)) {
4995 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
4996 (void)dns_rdataset_additionaldata(rdataset,
4997 check_related,
4998 fctx);
4999 rescan = ISC_TRUE;
5003 if (rescan)
5004 goto again;
5007 static inline isc_result_t
5008 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
5009 isc_result_t result;
5010 dns_rdata_t rdata = DNS_RDATA_INIT;
5011 dns_rdata_cname_t cname;
5013 result = dns_rdataset_first(rdataset);
5014 if (result != ISC_R_SUCCESS)
5015 return (result);
5016 dns_rdataset_current(rdataset, &rdata);
5017 result = dns_rdata_tostruct(&rdata, &cname, NULL);
5018 if (result != ISC_R_SUCCESS)
5019 return (result);
5020 dns_name_init(tname, NULL);
5021 dns_name_clone(&cname.cname, tname);
5022 dns_rdata_freestruct(&cname);
5024 return (ISC_R_SUCCESS);
5027 static inline isc_result_t
5028 dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
5029 dns_name_t *oname, dns_fixedname_t *fixeddname)
5031 isc_result_t result;
5032 dns_rdata_t rdata = DNS_RDATA_INIT;
5033 unsigned int nlabels;
5034 int order;
5035 dns_namereln_t namereln;
5036 dns_rdata_dname_t dname;
5037 dns_fixedname_t prefix;
5040 * Get the target name of the DNAME.
5042 result = dns_rdataset_first(rdataset);
5043 if (result != ISC_R_SUCCESS)
5044 return (result);
5045 dns_rdataset_current(rdataset, &rdata);
5046 result = dns_rdata_tostruct(&rdata, &dname, NULL);
5047 if (result != ISC_R_SUCCESS)
5048 return (result);
5051 * Get the prefix of qname.
5053 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
5054 if (namereln != dns_namereln_subdomain) {
5055 char qbuf[DNS_NAME_FORMATSIZE];
5056 char obuf[DNS_NAME_FORMATSIZE];
5058 dns_rdata_freestruct(&dname);
5059 dns_name_format(qname, qbuf, sizeof(qbuf));
5060 dns_name_format(oname, obuf, sizeof(obuf));
5061 log_formerr(fctx, "unrelated DNAME in answer: "
5062 "%s is not in %s", qbuf, obuf);
5063 return (DNS_R_FORMERR);
5065 dns_fixedname_init(&prefix);
5066 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
5067 dns_fixedname_init(fixeddname);
5068 result = dns_name_concatenate(dns_fixedname_name(&prefix),
5069 &dname.dname,
5070 dns_fixedname_name(fixeddname), NULL);
5071 dns_rdata_freestruct(&dname);
5072 return (result);
5075 static isc_boolean_t
5076 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
5077 dns_rdataset_t *rdataset)
5079 isc_result_t result;
5080 dns_rdata_t rdata = DNS_RDATA_INIT;
5081 struct in_addr ina;
5082 struct in6_addr in6a;
5083 isc_netaddr_t netaddr;
5084 char addrbuf[ISC_NETADDR_FORMATSIZE];
5085 char namebuf[DNS_NAME_FORMATSIZE];
5086 char classbuf[64];
5087 char typebuf[64];
5088 int match;
5090 /* By default, we allow any addresses. */
5091 if (view->denyansweracl == NULL)
5092 return (ISC_TRUE);
5095 * If the owner name matches one in the exclusion list, either exactly
5096 * or partially, allow it.
5098 if (view->answeracl_exclude != NULL) {
5099 dns_rbtnode_t *node = NULL;
5101 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
5102 &node, NULL, 0, NULL, NULL);
5104 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5105 return (ISC_TRUE);
5109 * Otherwise, search the filter list for a match for each address
5110 * record. If a match is found, the address should be filtered,
5111 * so should the entire answer.
5113 for (result = dns_rdataset_first(rdataset);
5114 result == ISC_R_SUCCESS;
5115 result = dns_rdataset_next(rdataset)) {
5116 dns_rdata_reset(&rdata);
5117 dns_rdataset_current(rdataset, &rdata);
5118 if (rdataset->type == dns_rdatatype_a) {
5119 INSIST(rdata.length == sizeof(ina.s_addr));
5120 memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
5121 isc_netaddr_fromin(&netaddr, &ina);
5122 } else {
5123 INSIST(rdata.length == sizeof(in6a.s6_addr));
5124 memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
5125 isc_netaddr_fromin6(&netaddr, &in6a);
5128 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
5129 &view->aclenv, &match, NULL);
5131 if (result == ISC_R_SUCCESS && match > 0) {
5132 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
5133 dns_name_format(name, namebuf, sizeof(namebuf));
5134 dns_rdatatype_format(rdataset->type, typebuf,
5135 sizeof(typebuf));
5136 dns_rdataclass_format(rdataset->rdclass, classbuf,
5137 sizeof(classbuf));
5138 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5139 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5140 "answer address %s denied for %s/%s/%s",
5141 addrbuf, namebuf, typebuf, classbuf);
5142 return (ISC_FALSE);
5146 return (ISC_TRUE);
5149 static isc_boolean_t
5150 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
5151 dns_rdatatype_t type, dns_name_t *tname,
5152 dns_name_t *domain)
5154 isc_result_t result;
5155 dns_rbtnode_t *node = NULL;
5156 char qnamebuf[DNS_NAME_FORMATSIZE];
5157 char tnamebuf[DNS_NAME_FORMATSIZE];
5158 char classbuf[64];
5159 char typebuf[64];
5161 /* By default, we allow any target name. */
5162 if (view->denyanswernames == NULL)
5163 return (ISC_TRUE);
5166 * If the owner name matches one in the exclusion list, either exactly
5167 * or partially, allow it.
5169 if (view->answernames_exclude != NULL) {
5170 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
5171 &node, NULL, 0, NULL, NULL);
5172 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5173 return (ISC_TRUE);
5177 * If the target name is a subdomain of the search domain, allow it.
5179 if (dns_name_issubdomain(tname, domain))
5180 return (ISC_TRUE);
5183 * Otherwise, apply filters.
5185 result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
5186 NULL, 0, NULL, NULL);
5187 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
5188 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
5189 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
5190 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
5191 dns_rdataclass_format(view->rdclass, classbuf,
5192 sizeof(classbuf));
5193 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5194 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5195 "%s target %s denied for %s/%s",
5196 typebuf, tnamebuf, qnamebuf, classbuf);
5197 return (ISC_FALSE);
5200 return (ISC_TRUE);
5204 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
5205 * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
5206 * section for the NS RRset if the query type is NS; if it has
5207 * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
5208 * section for A and AAAA queries.
5210 #define LOOK_FOR_NS_IN_ANSWER 0x1
5211 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
5213 static isc_result_t
5214 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
5215 unsigned int look_in_options)
5217 isc_result_t result;
5218 dns_message_t *message;
5219 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
5220 dns_rdataset_t *rdataset, *ns_rdataset;
5221 isc_boolean_t aa, negative_response;
5222 dns_rdatatype_t type;
5223 dns_section_t section;
5225 FCTXTRACE("noanswer_response");
5227 if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
5228 INSIST(fctx->type == dns_rdatatype_ns);
5229 section = DNS_SECTION_ANSWER;
5230 } else
5231 section = DNS_SECTION_AUTHORITY;
5233 message = fctx->rmessage;
5236 * Setup qname.
5238 if (oqname == NULL) {
5240 * We have a normal, non-chained negative response or
5241 * referral.
5243 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5244 aa = ISC_TRUE;
5245 else
5246 aa = ISC_FALSE;
5247 qname = &fctx->name;
5248 } else {
5250 * We're being invoked by answer_response() after it has
5251 * followed a CNAME/DNAME chain.
5253 qname = oqname;
5254 aa = ISC_FALSE;
5256 * If the current qname is not a subdomain of the query
5257 * domain, there's no point in looking at the authority
5258 * section without doing DNSSEC validation.
5260 * Until we do that validation, we'll just return success
5261 * in this case.
5263 if (!dns_name_issubdomain(qname, &fctx->domain))
5264 return (ISC_R_SUCCESS);
5268 * We have to figure out if this is a negative response, or a
5269 * referral.
5273 * Sometimes we can tell if its a negative response by looking at
5274 * the message header.
5276 negative_response = ISC_FALSE;
5277 if (message->rcode == dns_rcode_nxdomain ||
5278 (message->counts[DNS_SECTION_ANSWER] == 0 &&
5279 message->counts[DNS_SECTION_AUTHORITY] == 0))
5280 negative_response = ISC_TRUE;
5283 * Process the authority section.
5285 ns_name = NULL;
5286 ns_rdataset = NULL;
5287 soa_name = NULL;
5288 ds_name = NULL;
5289 result = dns_message_firstname(message, section);
5290 while (result == ISC_R_SUCCESS) {
5291 name = NULL;
5292 dns_message_currentname(message, section, &name);
5293 if (dns_name_issubdomain(name, &fctx->domain)) {
5295 * Look for NS/SOA RRsets first.
5297 for (rdataset = ISC_LIST_HEAD(name->list);
5298 rdataset != NULL;
5299 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5300 type = rdataset->type;
5301 if (type == dns_rdatatype_rrsig)
5302 type = rdataset->covers;
5303 if (((type == dns_rdatatype_ns ||
5304 type == dns_rdatatype_soa) &&
5305 !dns_name_issubdomain(qname, name))) {
5306 char qbuf[DNS_NAME_FORMATSIZE];
5307 char nbuf[DNS_NAME_FORMATSIZE];
5308 char tbuf[DNS_RDATATYPE_FORMATSIZE];
5309 dns_rdatatype_format(fctx->type, tbuf,
5310 sizeof(tbuf));
5311 dns_name_format(name, nbuf,
5312 sizeof(nbuf));
5313 dns_name_format(qname, qbuf,
5314 sizeof(qbuf));
5315 log_formerr(fctx,
5316 "unrelated %s %s in "
5317 "%s authority section",
5318 tbuf, qbuf, nbuf);
5319 return (DNS_R_FORMERR);
5321 if (type == dns_rdatatype_ns) {
5323 * NS or RRSIG NS.
5325 * Only one set of NS RRs is allowed.
5327 if (rdataset->type ==
5328 dns_rdatatype_ns) {
5329 if (ns_name != NULL &&
5330 name != ns_name) {
5331 log_formerr(fctx,
5332 "multiple NS "
5333 "RRsets in "
5334 "authority "
5335 "section");
5336 return (DNS_R_FORMERR);
5338 ns_name = name;
5339 ns_rdataset = rdataset;
5341 name->attributes |=
5342 DNS_NAMEATTR_CACHE;
5343 rdataset->attributes |=
5344 DNS_RDATASETATTR_CACHE;
5345 rdataset->trust = dns_trust_glue;
5347 if (type == dns_rdatatype_soa) {
5349 * SOA, or RRSIG SOA.
5351 * Only one SOA is allowed.
5353 if (rdataset->type ==
5354 dns_rdatatype_soa) {
5355 if (soa_name != NULL &&
5356 name != soa_name) {
5357 log_formerr(fctx,
5358 "multiple SOA "
5359 "RRs in "
5360 "authority "
5361 "section");
5362 return (DNS_R_FORMERR);
5364 soa_name = name;
5366 name->attributes |=
5367 DNS_NAMEATTR_NCACHE;
5368 rdataset->attributes |=
5369 DNS_RDATASETATTR_NCACHE;
5370 if (aa)
5371 rdataset->trust =
5372 dns_trust_authauthority;
5373 else
5374 rdataset->trust =
5375 dns_trust_additional;
5379 result = dns_message_nextname(message, section);
5380 if (result == ISC_R_NOMORE)
5381 break;
5382 else if (result != ISC_R_SUCCESS)
5383 return (result);
5387 * A negative response has a SOA record (Type 2)
5388 * and a optional NS RRset (Type 1) or it has neither
5389 * a SOA or a NS RRset (Type 3, handled above) or
5390 * rcode is NXDOMAIN (handled above) in which case
5391 * the NS RRset is allowed (Type 4).
5393 if (soa_name != NULL)
5394 negative_response = ISC_TRUE;
5396 result = dns_message_firstname(message, section);
5397 while (result == ISC_R_SUCCESS) {
5398 name = NULL;
5399 dns_message_currentname(message, section, &name);
5400 if (dns_name_issubdomain(name, &fctx->domain)) {
5401 for (rdataset = ISC_LIST_HEAD(name->list);
5402 rdataset != NULL;
5403 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5404 type = rdataset->type;
5405 if (type == dns_rdatatype_rrsig)
5406 type = rdataset->covers;
5407 if (type == dns_rdatatype_nsec ||
5408 type == dns_rdatatype_nsec3) {
5410 * NSEC or RRSIG NSEC.
5412 if (negative_response) {
5413 name->attributes |=
5414 DNS_NAMEATTR_NCACHE;
5415 rdataset->attributes |=
5416 DNS_RDATASETATTR_NCACHE;
5417 } else if (type == dns_rdatatype_nsec) {
5418 name->attributes |=
5419 DNS_NAMEATTR_CACHE;
5420 rdataset->attributes |=
5421 DNS_RDATASETATTR_CACHE;
5423 if (aa)
5424 rdataset->trust =
5425 dns_trust_authauthority;
5426 else
5427 rdataset->trust =
5428 dns_trust_additional;
5430 * No additional data needs to be
5431 * marked.
5433 } else if (type == dns_rdatatype_ds) {
5435 * DS or SIG DS.
5437 * These should only be here if
5438 * this is a referral, and there
5439 * should only be one DS RRset.
5441 if (ns_name == NULL) {
5442 log_formerr(fctx,
5443 "DS with no "
5444 "referral");
5445 return (DNS_R_FORMERR);
5447 if (rdataset->type ==
5448 dns_rdatatype_ds) {
5449 if (ds_name != NULL &&
5450 name != ds_name) {
5451 log_formerr(fctx,
5452 "DS doesn't "
5453 "match "
5454 "referral "
5455 "(NS)");
5456 return (DNS_R_FORMERR);
5458 ds_name = name;
5460 name->attributes |=
5461 DNS_NAMEATTR_CACHE;
5462 rdataset->attributes |=
5463 DNS_RDATASETATTR_CACHE;
5464 if (aa)
5465 rdataset->trust =
5466 dns_trust_authauthority;
5467 else
5468 rdataset->trust =
5469 dns_trust_additional;
5473 result = dns_message_nextname(message, section);
5474 if (result == ISC_R_NOMORE)
5475 break;
5476 else if (result != ISC_R_SUCCESS)
5477 return (result);
5481 * Trigger lookups for DNS nameservers.
5483 if (negative_response && message->rcode == dns_rcode_noerror &&
5484 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
5485 dns_name_equal(soa_name, qname) &&
5486 !dns_name_equal(qname, dns_rootname))
5487 return (DNS_R_CHASEDSSERVERS);
5490 * Did we find anything?
5492 if (!negative_response && ns_name == NULL) {
5494 * Nope.
5496 if (oqname != NULL) {
5498 * We've already got a partial CNAME/DNAME chain,
5499 * and haven't found else anything useful here, but
5500 * no error has occurred since we have an answer.
5502 return (ISC_R_SUCCESS);
5503 } else {
5505 * The responder is insane.
5507 log_formerr(fctx, "invalid response");
5508 return (DNS_R_FORMERR);
5513 * If we found both NS and SOA, they should be the same name.
5515 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
5516 log_formerr(fctx, "NS/SOA mismatch");
5517 return (DNS_R_FORMERR);
5521 * Do we have a referral? (We only want to follow a referral if
5522 * we're not following a chain.)
5524 if (!negative_response && ns_name != NULL && oqname == NULL) {
5526 * We already know ns_name is a subdomain of fctx->domain.
5527 * If ns_name is equal to fctx->domain, we're not making
5528 * progress. We return DNS_R_FORMERR so that we'll keep
5529 * trying other servers.
5531 if (dns_name_equal(ns_name, &fctx->domain)) {
5532 log_formerr(fctx, "sideways referral");
5533 return (DNS_R_FORMERR);
5537 * If the referral name is not a parent of the query
5538 * name, consider the responder insane.
5540 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
5541 /* Logged twice */
5542 log_formerr(fctx, "referral to non-parent");
5543 FCTXTRACE("referral to non-parent");
5544 return (DNS_R_FORMERR);
5548 * Mark any additional data related to this rdataset.
5549 * It's important that we do this before we change the
5550 * query domain.
5552 INSIST(ns_rdataset != NULL);
5553 fctx->attributes |= FCTX_ATTR_GLUING;
5554 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
5555 fctx);
5556 #if CHECK_FOR_GLUE_IN_ANSWER
5558 * Look in the answer section for "glue" that is incorrectly
5559 * returned as a answer. This is needed if the server also
5560 * minimizes the response size by not adding records to the
5561 * additional section that are in the answer section or if
5562 * the record gets dropped due to message size constraints.
5564 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
5565 (fctx->type == dns_rdatatype_aaaa ||
5566 fctx->type == dns_rdatatype_a))
5567 (void)dns_rdataset_additionaldata(ns_rdataset,
5568 check_answer, fctx);
5569 #endif
5570 fctx->attributes &= ~FCTX_ATTR_GLUING;
5572 * NS rdatasets with 0 TTL cause problems.
5573 * dns_view_findzonecut() will not find them when we
5574 * try to follow the referral, and we'll SERVFAIL
5575 * because the best nameservers are now above QDOMAIN.
5576 * We force the TTL to 1 second to prevent this.
5578 if (ns_rdataset->ttl == 0)
5579 ns_rdataset->ttl = 1;
5581 * Set the current query domain to the referral name.
5583 * XXXRTH We should check if we're in forward-only mode, and
5584 * if so we should bail out.
5586 INSIST(dns_name_countlabels(&fctx->domain) > 0);
5587 dns_name_free(&fctx->domain,
5588 fctx->res->buckets[fctx->bucketnum].mctx);
5589 if (dns_rdataset_isassociated(&fctx->nameservers))
5590 dns_rdataset_disassociate(&fctx->nameservers);
5591 dns_name_init(&fctx->domain, NULL);
5592 result = dns_name_dup(ns_name,
5593 fctx->res->buckets[fctx->bucketnum].mctx,
5594 &fctx->domain);
5595 if (result != ISC_R_SUCCESS)
5596 return (result);
5597 fctx->attributes |= FCTX_ATTR_WANTCACHE;
5598 return (DNS_R_DELEGATION);
5602 * Since we're not doing a referral, we don't want to cache any
5603 * NS RRs we may have found.
5605 if (ns_name != NULL)
5606 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
5608 if (negative_response && oqname == NULL)
5609 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
5611 return (ISC_R_SUCCESS);
5614 static isc_result_t
5615 answer_response(fetchctx_t *fctx) {
5616 isc_result_t result;
5617 dns_message_t *message;
5618 dns_name_t *name, *qname, tname;
5619 dns_rdataset_t *rdataset;
5620 isc_boolean_t done, external, chaining, aa, found, want_chaining;
5621 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
5622 unsigned int aflag;
5623 dns_rdatatype_t type;
5624 dns_fixedname_t dname, fqname;
5625 dns_view_t *view;
5627 FCTXTRACE("answer_response");
5629 message = fctx->rmessage;
5632 * Examine the answer section, marking those rdatasets which are
5633 * part of the answer and should be cached.
5636 done = ISC_FALSE;
5637 found_cname = ISC_FALSE;
5638 found_type = ISC_FALSE;
5639 chaining = ISC_FALSE;
5640 have_answer = ISC_FALSE;
5641 want_chaining = ISC_FALSE;
5642 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5643 aa = ISC_TRUE;
5644 else
5645 aa = ISC_FALSE;
5646 qname = &fctx->name;
5647 type = fctx->type;
5648 view = fctx->res->view;
5649 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
5650 while (!done && result == ISC_R_SUCCESS) {
5651 name = NULL;
5652 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
5653 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5654 if (dns_name_equal(name, qname)) {
5655 wanted_chaining = ISC_FALSE;
5656 for (rdataset = ISC_LIST_HEAD(name->list);
5657 rdataset != NULL;
5658 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5659 found = ISC_FALSE;
5660 want_chaining = ISC_FALSE;
5661 aflag = 0;
5662 if (rdataset->type == dns_rdatatype_nsec3) {
5664 * NSEC3 records are not allowed to
5665 * appear in the answer section.
5667 log_formerr(fctx, "NSEC3 in answer");
5668 return (DNS_R_FORMERR);
5672 * Apply filters, if given, on answers to reject
5673 * a malicious attempt of rebinding.
5675 if ((rdataset->type == dns_rdatatype_a ||
5676 rdataset->type == dns_rdatatype_aaaa) &&
5677 !is_answeraddress_allowed(view, name,
5678 rdataset)) {
5679 return (DNS_R_SERVFAIL);
5682 if (rdataset->type == type && !found_cname) {
5684 * We've found an ordinary answer.
5686 found = ISC_TRUE;
5687 found_type = ISC_TRUE;
5688 done = ISC_TRUE;
5689 aflag = DNS_RDATASETATTR_ANSWER;
5690 } else if (type == dns_rdatatype_any) {
5692 * We've found an answer matching
5693 * an ANY query. There may be
5694 * more.
5696 found = ISC_TRUE;
5697 aflag = DNS_RDATASETATTR_ANSWER;
5698 } else if (rdataset->type == dns_rdatatype_rrsig
5699 && rdataset->covers == type
5700 && !found_cname) {
5702 * We've found a signature that
5703 * covers the type we're looking for.
5705 found = ISC_TRUE;
5706 found_type = ISC_TRUE;
5707 aflag = DNS_RDATASETATTR_ANSWERSIG;
5708 } else if (rdataset->type ==
5709 dns_rdatatype_cname
5710 && !found_type) {
5712 * We're looking for something else,
5713 * but we found a CNAME.
5715 * Getting a CNAME response for some
5716 * query types is an error.
5718 if (type == dns_rdatatype_rrsig ||
5719 type == dns_rdatatype_dnskey ||
5720 type == dns_rdatatype_nsec ||
5721 type == dns_rdatatype_nsec3) {
5722 char buf[DNS_RDATATYPE_FORMATSIZE];
5723 dns_rdatatype_format(fctx->type,
5724 buf, sizeof(buf));
5725 log_formerr(fctx,
5726 "CNAME response "
5727 "for %s RR", buf);
5728 return (DNS_R_FORMERR);
5730 found = ISC_TRUE;
5731 found_cname = ISC_TRUE;
5732 want_chaining = ISC_TRUE;
5733 aflag = DNS_RDATASETATTR_ANSWER;
5734 result = cname_target(rdataset,
5735 &tname);
5736 if (result != ISC_R_SUCCESS)
5737 return (result);
5738 /* Apply filters on the target name. */
5739 if (!is_answertarget_allowed(view,
5740 name,
5741 rdataset->type,
5742 &tname,
5743 &fctx->domain)) {
5744 return (DNS_R_SERVFAIL);
5746 } else if (rdataset->type == dns_rdatatype_rrsig
5747 && rdataset->covers ==
5748 dns_rdatatype_cname
5749 && !found_type) {
5751 * We're looking for something else,
5752 * but we found a SIG CNAME.
5754 found = ISC_TRUE;
5755 found_cname = ISC_TRUE;
5756 aflag = DNS_RDATASETATTR_ANSWERSIG;
5759 if (found) {
5761 * We've found an answer to our
5762 * question.
5764 name->attributes |=
5765 DNS_NAMEATTR_CACHE;
5766 rdataset->attributes |=
5767 DNS_RDATASETATTR_CACHE;
5768 rdataset->trust = dns_trust_answer;
5769 if (!chaining) {
5771 * This data is "the" answer
5772 * to our question only if
5773 * we're not chaining (i.e.
5774 * if we haven't followed
5775 * a CNAME or DNAME).
5777 INSIST(!external);
5778 if (aflag ==
5779 DNS_RDATASETATTR_ANSWER)
5780 have_answer = ISC_TRUE;
5781 name->attributes |=
5782 DNS_NAMEATTR_ANSWER;
5783 rdataset->attributes |= aflag;
5784 if (aa)
5785 rdataset->trust =
5786 dns_trust_authanswer;
5787 } else if (external) {
5789 * This data is outside of
5790 * our query domain, and
5791 * may only be cached if it
5792 * comes from a secure zone
5793 * and validates.
5795 rdataset->attributes |=
5796 DNS_RDATASETATTR_EXTERNAL;
5800 * Mark any additional data related
5801 * to this rdataset.
5803 (void)dns_rdataset_additionaldata(
5804 rdataset,
5805 check_related,
5806 fctx);
5809 * CNAME chaining.
5811 if (want_chaining) {
5812 wanted_chaining = ISC_TRUE;
5813 name->attributes |=
5814 DNS_NAMEATTR_CHAINING;
5815 rdataset->attributes |=
5816 DNS_RDATASETATTR_CHAINING;
5817 qname = &tname;
5821 * We could add an "else" clause here and
5822 * log that we're ignoring this rdataset.
5826 * If wanted_chaining is true, we've done
5827 * some chaining as the result of processing
5828 * this node, and thus we need to set
5829 * chaining to true.
5831 * We don't set chaining inside of the
5832 * rdataset loop because doing that would
5833 * cause us to ignore the signatures of
5834 * CNAMEs.
5836 if (wanted_chaining)
5837 chaining = ISC_TRUE;
5838 } else {
5840 * Look for a DNAME (or its SIG). Anything else is
5841 * ignored.
5843 wanted_chaining = ISC_FALSE;
5844 for (rdataset = ISC_LIST_HEAD(name->list);
5845 rdataset != NULL;
5846 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5847 isc_boolean_t found_dname = ISC_FALSE;
5848 dns_name_t *dname_name;
5850 found = ISC_FALSE;
5851 aflag = 0;
5852 if (rdataset->type == dns_rdatatype_dname) {
5854 * We're looking for something else,
5855 * but we found a DNAME.
5857 * If we're not chaining, then the
5858 * DNAME should not be external.
5860 if (!chaining && external) {
5861 log_formerr(fctx,
5862 "external DNAME");
5863 return (DNS_R_FORMERR);
5865 found = ISC_TRUE;
5866 want_chaining = ISC_TRUE;
5867 aflag = DNS_RDATASETATTR_ANSWER;
5868 result = dname_target(fctx, rdataset,
5869 qname, name,
5870 &dname);
5871 if (result == ISC_R_NOSPACE) {
5873 * We can't construct the
5874 * DNAME target. Do not
5875 * try to continue.
5877 want_chaining = ISC_FALSE;
5878 } else if (result != ISC_R_SUCCESS)
5879 return (result);
5880 else
5881 found_dname = ISC_TRUE;
5883 dname_name = dns_fixedname_name(&dname);
5884 if (!is_answertarget_allowed(view,
5885 qname,
5886 rdataset->type,
5887 dname_name,
5888 &fctx->domain)) {
5889 return (DNS_R_SERVFAIL);
5891 } else if (rdataset->type == dns_rdatatype_rrsig
5892 && rdataset->covers ==
5893 dns_rdatatype_dname) {
5895 * We've found a signature that
5896 * covers the DNAME.
5898 found = ISC_TRUE;
5899 aflag = DNS_RDATASETATTR_ANSWERSIG;
5902 if (found) {
5904 * We've found an answer to our
5905 * question.
5907 name->attributes |=
5908 DNS_NAMEATTR_CACHE;
5909 rdataset->attributes |=
5910 DNS_RDATASETATTR_CACHE;
5911 rdataset->trust = dns_trust_answer;
5912 if (!chaining) {
5914 * This data is "the" answer
5915 * to our question only if
5916 * we're not chaining.
5918 INSIST(!external);
5919 if (aflag ==
5920 DNS_RDATASETATTR_ANSWER)
5921 have_answer = ISC_TRUE;
5922 name->attributes |=
5923 DNS_NAMEATTR_ANSWER;
5924 rdataset->attributes |= aflag;
5925 if (aa)
5926 rdataset->trust =
5927 dns_trust_authanswer;
5928 } else if (external) {
5929 rdataset->attributes |=
5930 DNS_RDATASETATTR_EXTERNAL;
5934 * DNAME chaining.
5936 if (found_dname) {
5938 * Copy the dname into the
5939 * qname fixed name.
5941 * Although we check for
5942 * failure of the copy
5943 * operation, in practice it
5944 * should never fail since
5945 * we already know that the
5946 * result fits in a fixedname.
5948 dns_fixedname_init(&fqname);
5949 result = dns_name_copy(
5950 dns_fixedname_name(&dname),
5951 dns_fixedname_name(&fqname),
5952 NULL);
5953 if (result != ISC_R_SUCCESS)
5954 return (result);
5955 wanted_chaining = ISC_TRUE;
5956 name->attributes |=
5957 DNS_NAMEATTR_CHAINING;
5958 rdataset->attributes |=
5959 DNS_RDATASETATTR_CHAINING;
5960 qname = dns_fixedname_name(
5961 &fqname);
5965 if (wanted_chaining)
5966 chaining = ISC_TRUE;
5968 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
5970 if (result == ISC_R_NOMORE)
5971 result = ISC_R_SUCCESS;
5972 if (result != ISC_R_SUCCESS)
5973 return (result);
5976 * We should have found an answer.
5978 if (!have_answer) {
5979 log_formerr(fctx, "reply has no answer");
5980 return (DNS_R_FORMERR);
5984 * This response is now potentially cacheable.
5986 fctx->attributes |= FCTX_ATTR_WANTCACHE;
5989 * Did chaining end before we got the final answer?
5991 if (chaining) {
5993 * Yes. This may be a negative reply, so hand off
5994 * authority section processing to the noanswer code.
5995 * If it isn't a noanswer response, no harm will be
5996 * done.
5998 return (noanswer_response(fctx, qname, 0));
6002 * We didn't end with an incomplete chain, so the rcode should be
6003 * "no error".
6005 if (message->rcode != dns_rcode_noerror) {
6006 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
6007 "indicates error");
6008 return (DNS_R_FORMERR);
6012 * Examine the authority section (if there is one).
6014 * We expect there to be only one owner name for all the rdatasets
6015 * in this section, and we expect that it is not external.
6017 done = ISC_FALSE;
6018 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6019 while (!done && result == ISC_R_SUCCESS) {
6020 name = NULL;
6021 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6022 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
6023 if (!external) {
6025 * We expect to find NS or SIG NS rdatasets, and
6026 * nothing else.
6028 for (rdataset = ISC_LIST_HEAD(name->list);
6029 rdataset != NULL;
6030 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6031 if (rdataset->type == dns_rdatatype_ns ||
6032 (rdataset->type == dns_rdatatype_rrsig &&
6033 rdataset->covers == dns_rdatatype_ns)) {
6034 name->attributes |=
6035 DNS_NAMEATTR_CACHE;
6036 rdataset->attributes |=
6037 DNS_RDATASETATTR_CACHE;
6038 if (aa && !chaining)
6039 rdataset->trust =
6040 dns_trust_authauthority;
6041 else
6042 rdataset->trust =
6043 dns_trust_additional;
6046 * Mark any additional data related
6047 * to this rdataset.
6049 (void)dns_rdataset_additionaldata(
6050 rdataset,
6051 check_related,
6052 fctx);
6053 done = ISC_TRUE;
6057 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
6059 if (result == ISC_R_NOMORE)
6060 result = ISC_R_SUCCESS;
6062 return (result);
6065 static void
6066 resume_dslookup(isc_task_t *task, isc_event_t *event) {
6067 dns_fetchevent_t *fevent;
6068 dns_resolver_t *res;
6069 fetchctx_t *fctx;
6070 isc_result_t result;
6071 isc_boolean_t bucket_empty = ISC_FALSE;
6072 isc_boolean_t locked = ISC_FALSE;
6073 unsigned int bucketnum;
6074 dns_rdataset_t nameservers;
6075 dns_fixedname_t fixed;
6076 dns_name_t *domain;
6078 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
6079 fevent = (dns_fetchevent_t *)event;
6080 fctx = event->ev_arg;
6081 REQUIRE(VALID_FCTX(fctx));
6082 res = fctx->res;
6084 UNUSED(task);
6085 FCTXTRACE("resume_dslookup");
6087 if (fevent->node != NULL)
6088 dns_db_detachnode(fevent->db, &fevent->node);
6089 if (fevent->db != NULL)
6090 dns_db_detach(&fevent->db);
6092 dns_rdataset_init(&nameservers);
6094 bucketnum = fctx->bucketnum;
6095 if (fevent->result == ISC_R_CANCELED) {
6096 dns_resolver_destroyfetch(&fctx->nsfetch);
6097 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
6098 } else if (fevent->result == ISC_R_SUCCESS) {
6100 FCTXTRACE("resuming DS lookup");
6102 dns_resolver_destroyfetch(&fctx->nsfetch);
6103 if (dns_rdataset_isassociated(&fctx->nameservers))
6104 dns_rdataset_disassociate(&fctx->nameservers);
6105 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
6106 dns_name_free(&fctx->domain,
6107 fctx->res->buckets[bucketnum].mctx);
6108 dns_name_init(&fctx->domain, NULL);
6109 result = dns_name_dup(&fctx->nsname,
6110 fctx->res->buckets[bucketnum].mctx,
6111 &fctx->domain);
6112 if (result != ISC_R_SUCCESS) {
6113 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6114 goto cleanup;
6117 * Try again.
6119 fctx_try(fctx, ISC_TRUE);
6120 } else {
6121 unsigned int n;
6122 dns_rdataset_t *nsrdataset = NULL;
6125 * Retrieve state from fctx->nsfetch before we destroy it.
6127 dns_fixedname_init(&fixed);
6128 domain = dns_fixedname_name(&fixed);
6129 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
6130 if (dns_name_equal(&fctx->nsname, domain)) {
6131 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6132 dns_resolver_destroyfetch(&fctx->nsfetch);
6133 goto cleanup;
6135 if (dns_rdataset_isassociated(
6136 &fctx->nsfetch->private->nameservers)) {
6137 dns_rdataset_clone(
6138 &fctx->nsfetch->private->nameservers,
6139 &nameservers);
6140 nsrdataset = &nameservers;
6141 } else
6142 domain = NULL;
6143 dns_resolver_destroyfetch(&fctx->nsfetch);
6144 n = dns_name_countlabels(&fctx->nsname);
6145 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
6146 &fctx->nsname);
6148 if (dns_rdataset_isassociated(fevent->rdataset))
6149 dns_rdataset_disassociate(fevent->rdataset);
6150 FCTXTRACE("continuing to look for parent's NS records");
6151 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
6152 dns_rdatatype_ns, domain,
6153 nsrdataset, NULL, 0, task,
6154 resume_dslookup, fctx,
6155 &fctx->nsrrset, NULL,
6156 &fctx->nsfetch);
6157 if (result != ISC_R_SUCCESS)
6158 fctx_done(fctx, result, __LINE__);
6159 else {
6160 LOCK(&res->buckets[bucketnum].lock);
6161 locked = ISC_TRUE;
6162 fctx->references++;
6166 cleanup:
6167 if (dns_rdataset_isassociated(&nameservers))
6168 dns_rdataset_disassociate(&nameservers);
6169 if (dns_rdataset_isassociated(fevent->rdataset))
6170 dns_rdataset_disassociate(fevent->rdataset);
6171 INSIST(fevent->sigrdataset == NULL);
6172 isc_event_free(&event);
6173 if (!locked)
6174 LOCK(&res->buckets[bucketnum].lock);
6175 fctx->references--;
6176 if (fctx->references == 0)
6177 bucket_empty = fctx_destroy(fctx);
6178 UNLOCK(&res->buckets[bucketnum].lock);
6179 if (bucket_empty)
6180 empty_bucket(res);
6183 static inline void
6184 checknamessection(dns_message_t *message, dns_section_t section) {
6185 isc_result_t result;
6186 dns_name_t *name;
6187 dns_rdata_t rdata = DNS_RDATA_INIT;
6188 dns_rdataset_t *rdataset;
6190 for (result = dns_message_firstname(message, section);
6191 result == ISC_R_SUCCESS;
6192 result = dns_message_nextname(message, section))
6194 name = NULL;
6195 dns_message_currentname(message, section, &name);
6196 for (rdataset = ISC_LIST_HEAD(name->list);
6197 rdataset != NULL;
6198 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6199 for (result = dns_rdataset_first(rdataset);
6200 result == ISC_R_SUCCESS;
6201 result = dns_rdataset_next(rdataset)) {
6202 dns_rdataset_current(rdataset, &rdata);
6203 if (!dns_rdata_checkowner(name, rdata.rdclass,
6204 rdata.type,
6205 ISC_FALSE) ||
6206 !dns_rdata_checknames(&rdata, name, NULL))
6208 rdataset->attributes |=
6209 DNS_RDATASETATTR_CHECKNAMES;
6211 dns_rdata_reset(&rdata);
6217 static void
6218 checknames(dns_message_t *message) {
6220 checknamessection(message, DNS_SECTION_ANSWER);
6221 checknamessection(message, DNS_SECTION_AUTHORITY);
6222 checknamessection(message, DNS_SECTION_ADDITIONAL);
6226 * Log server NSID at log level 'level'
6228 static isc_result_t
6229 log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
6231 static const char hex[17] = "0123456789abcdef";
6232 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6233 isc_uint16_t optcode, nsid_len, buflen, i;
6234 isc_result_t result;
6235 isc_buffer_t nsidbuf;
6236 dns_rdata_t rdata;
6237 unsigned char *p, *buf, *nsid;
6239 /* Extract rdata from OPT rdataset */
6240 result = dns_rdataset_first(opt);
6241 if (result != ISC_R_SUCCESS)
6242 return (ISC_R_FAILURE);
6244 dns_rdata_init(&rdata);
6245 dns_rdataset_current(opt, &rdata);
6246 if (rdata.length < 4)
6247 return (ISC_R_FAILURE);
6249 /* Check for NSID */
6250 isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
6251 isc_buffer_add(&nsidbuf, rdata.length);
6252 optcode = isc_buffer_getuint16(&nsidbuf);
6253 nsid_len = isc_buffer_getuint16(&nsidbuf);
6254 if (optcode != DNS_OPT_NSID || nsid_len == 0)
6255 return (ISC_R_FAILURE);
6257 /* Allocate buffer for storing hex version of the NSID */
6258 buflen = nsid_len * 2 + 1;
6259 buf = isc_mem_get(mctx, buflen);
6260 if (buf == NULL)
6261 return (ISC_R_NOSPACE);
6263 /* Convert to hex */
6264 p = buf;
6265 nsid = rdata.data + 4;
6266 for (i = 0; i < nsid_len; i++) {
6267 *p++ = hex[(nsid[0] >> 4) & 0xf];
6268 *p++ = hex[nsid[0] & 0xf];
6269 nsid++;
6271 *p = '\0';
6273 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6274 sizeof(addrbuf));
6275 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6276 DNS_LOGMODULE_RESOLVER, level,
6277 "received NSID '%s' from %s", buf, addrbuf);
6279 /* Clean up */
6280 isc_mem_put(mctx, buf, buflen);
6281 return (ISC_R_SUCCESS);
6284 static void
6285 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
6286 isc_buffer_t buffer;
6287 char *buf = NULL;
6288 int len = 1024;
6289 isc_result_t result;
6291 if (! isc_log_wouldlog(dns_lctx, level))
6292 return;
6295 * Note that these are multiline debug messages. We want a newline
6296 * to appear in the log after each message.
6299 do {
6300 buf = isc_mem_get(mctx, len);
6301 if (buf == NULL)
6302 break;
6303 isc_buffer_init(&buffer, buf, len);
6304 result = dns_message_totext(message, &dns_master_style_debug,
6305 0, &buffer);
6306 if (result == ISC_R_NOSPACE) {
6307 isc_mem_put(mctx, buf, len);
6308 len += 1024;
6309 } else if (result == ISC_R_SUCCESS)
6310 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6311 DNS_LOGMODULE_RESOLVER, level,
6312 "received packet:\n%.*s",
6313 (int)isc_buffer_usedlength(&buffer),
6314 buf);
6315 } while (result == ISC_R_NOSPACE);
6317 if (buf != NULL)
6318 isc_mem_put(mctx, buf, len);
6321 static isc_boolean_t
6322 iscname(fetchctx_t *fctx) {
6323 isc_result_t result;
6325 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
6326 &fctx->name, dns_rdatatype_cname, 0,
6327 NULL, NULL);
6328 return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
6331 static void
6332 resquery_response(isc_task_t *task, isc_event_t *event) {
6333 isc_result_t result = ISC_R_SUCCESS;
6334 resquery_t *query = event->ev_arg;
6335 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
6336 isc_boolean_t keep_trying, get_nameservers, resend;
6337 isc_boolean_t truncated;
6338 dns_message_t *message;
6339 dns_rdataset_t *opt;
6340 fetchctx_t *fctx;
6341 dns_name_t *fname;
6342 dns_fixedname_t foundname;
6343 isc_stdtime_t now;
6344 isc_time_t tnow, *finish;
6345 dns_adbaddrinfo_t *addrinfo;
6346 unsigned int options;
6347 unsigned int findoptions;
6348 isc_result_t broken_server;
6349 badnstype_t broken_type = badns_response;
6351 REQUIRE(VALID_QUERY(query));
6352 fctx = query->fctx;
6353 options = query->options;
6354 REQUIRE(VALID_FCTX(fctx));
6355 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
6357 QTRACE("response");
6359 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
6360 inc_stats(fctx->res, dns_resstatscounter_responsev4);
6361 else
6362 inc_stats(fctx->res, dns_resstatscounter_responsev6);
6364 (void)isc_timer_touch(fctx->timer);
6366 keep_trying = ISC_FALSE;
6367 broken_server = ISC_R_SUCCESS;
6368 get_nameservers = ISC_FALSE;
6369 resend = ISC_FALSE;
6370 truncated = ISC_FALSE;
6371 finish = NULL;
6373 if (fctx->res->exiting) {
6374 result = ISC_R_SHUTTINGDOWN;
6375 goto done;
6378 fctx->timeouts = 0;
6379 fctx->timeout = ISC_FALSE;
6380 fctx->addrinfo = query->addrinfo;
6383 * XXXRTH We should really get the current time just once. We
6384 * need a routine to convert from an isc_time_t to an
6385 * isc_stdtime_t.
6387 TIME_NOW(&tnow);
6388 finish = &tnow;
6389 isc_stdtime_get(&now);
6392 * Did the dispatcher have a problem?
6394 if (devent->result != ISC_R_SUCCESS) {
6395 if (devent->result == ISC_R_EOF &&
6396 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6398 * The problem might be that they
6399 * don't understand EDNS0. Turn it
6400 * off and try again.
6402 options |= DNS_FETCHOPT_NOEDNS0;
6403 resend = ISC_TRUE;
6405 * Remember that they don't like EDNS0.
6407 dns_adb_changeflags(fctx->adb,
6408 query->addrinfo,
6409 DNS_FETCHOPT_NOEDNS0,
6410 DNS_FETCHOPT_NOEDNS0);
6411 } else {
6413 * There's no hope for this query.
6415 keep_trying = ISC_TRUE;
6418 * If this is a network error on an exclusive query
6419 * socket, mark the server as bad so that we won't try
6420 * it for this fetch again.
6422 if (query->exclusivesocket &&
6423 (devent->result == ISC_R_HOSTUNREACH ||
6424 devent->result == ISC_R_NETUNREACH ||
6425 devent->result == ISC_R_CONNREFUSED ||
6426 devent->result == ISC_R_CANCELED)) {
6427 broken_server = devent->result;
6428 broken_type = badns_unreachable;
6431 goto done;
6434 message = fctx->rmessage;
6436 if (query->tsig != NULL) {
6437 result = dns_message_setquerytsig(message, query->tsig);
6438 if (result != ISC_R_SUCCESS)
6439 goto done;
6442 if (query->tsigkey) {
6443 result = dns_message_settsigkey(message, query->tsigkey);
6444 if (result != ISC_R_SUCCESS)
6445 goto done;
6448 result = dns_message_parse(message, &devent->buffer, 0);
6449 if (result != ISC_R_SUCCESS) {
6450 switch (result) {
6451 case ISC_R_UNEXPECTEDEND:
6452 if (!message->question_ok ||
6453 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
6454 (options & DNS_FETCHOPT_TCP) != 0) {
6456 * Either the message ended prematurely,
6457 * and/or wasn't marked as being truncated,
6458 * and/or this is a response to a query we
6459 * sent over TCP. In all of these cases,
6460 * something is wrong with the remote
6461 * server and we don't want to retry using
6462 * TCP.
6464 if ((query->options & DNS_FETCHOPT_NOEDNS0)
6465 == 0) {
6467 * The problem might be that they
6468 * don't understand EDNS0. Turn it
6469 * off and try again.
6471 options |= DNS_FETCHOPT_NOEDNS0;
6472 resend = ISC_TRUE;
6474 * Remember that they don't like EDNS0.
6476 dns_adb_changeflags(
6477 fctx->adb,
6478 query->addrinfo,
6479 DNS_FETCHOPT_NOEDNS0,
6480 DNS_FETCHOPT_NOEDNS0);
6481 inc_stats(fctx->res,
6482 dns_resstatscounter_edns0fail);
6483 } else {
6484 broken_server = result;
6485 keep_trying = ISC_TRUE;
6487 goto done;
6490 * We defer retrying via TCP for a bit so we can
6491 * check out this message further.
6493 truncated = ISC_TRUE;
6494 break;
6495 case DNS_R_FORMERR:
6496 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6498 * The problem might be that they
6499 * don't understand EDNS0. Turn it
6500 * off and try again.
6502 options |= DNS_FETCHOPT_NOEDNS0;
6503 resend = ISC_TRUE;
6505 * Remember that they don't like EDNS0.
6507 dns_adb_changeflags(fctx->adb,
6508 query->addrinfo,
6509 DNS_FETCHOPT_NOEDNS0,
6510 DNS_FETCHOPT_NOEDNS0);
6511 inc_stats(fctx->res,
6512 dns_resstatscounter_edns0fail);
6513 } else {
6514 broken_server = DNS_R_UNEXPECTEDRCODE;
6515 keep_trying = ISC_TRUE;
6517 goto done;
6518 default:
6520 * Something bad has happened.
6522 goto done;
6528 * Log the incoming packet.
6530 log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
6533 * Did we request NSID? If so, and if the response contains
6534 * NSID data, log it at INFO level.
6536 opt = dns_message_getopt(message);
6537 if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
6538 log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
6541 * If the message is signed, check the signature. If not, this
6542 * returns success anyway.
6544 result = dns_message_checksig(message, fctx->res->view);
6545 if (result != ISC_R_SUCCESS)
6546 goto done;
6549 * The dispatcher should ensure we only get responses with QR set.
6551 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
6553 * INSIST() that the message comes from the place we sent it to,
6554 * since the dispatch code should ensure this.
6556 * INSIST() that the message id is correct (this should also be
6557 * ensured by the dispatch code).
6562 * Deal with truncated responses by retrying using TCP.
6564 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
6565 truncated = ISC_TRUE;
6567 if (truncated) {
6568 inc_stats(fctx->res, dns_resstatscounter_truncated);
6569 if ((options & DNS_FETCHOPT_TCP) != 0) {
6570 broken_server = DNS_R_TRUNCATEDTCP;
6571 keep_trying = ISC_TRUE;
6572 } else {
6573 options |= DNS_FETCHOPT_TCP;
6574 resend = ISC_TRUE;
6576 goto done;
6580 * Is it a query response?
6582 if (message->opcode != dns_opcode_query) {
6583 /* XXXRTH Log */
6584 broken_server = DNS_R_UNEXPECTEDOPCODE;
6585 keep_trying = ISC_TRUE;
6586 goto done;
6590 * Update statistics about erroneous responses.
6592 if (message->rcode != dns_rcode_noerror) {
6593 switch (message->rcode) {
6594 case dns_rcode_nxdomain:
6595 inc_stats(fctx->res, dns_resstatscounter_nxdomain);
6596 break;
6597 case dns_rcode_servfail:
6598 inc_stats(fctx->res, dns_resstatscounter_servfail);
6599 break;
6600 case dns_rcode_formerr:
6601 inc_stats(fctx->res, dns_resstatscounter_formerr);
6602 break;
6603 default:
6604 inc_stats(fctx->res, dns_resstatscounter_othererror);
6605 break;
6610 * Is the remote server broken, or does it dislike us?
6612 if (message->rcode != dns_rcode_noerror &&
6613 message->rcode != dns_rcode_nxdomain) {
6614 if (((message->rcode == dns_rcode_formerr ||
6615 message->rcode == dns_rcode_notimp) ||
6616 (message->rcode == dns_rcode_servfail &&
6617 dns_message_getopt(message) == NULL)) &&
6618 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6620 * It's very likely they don't like EDNS0.
6621 * If the response code is SERVFAIL, also check if the
6622 * response contains an OPT RR and don't cache the
6623 * failure since it can be returned for various other
6624 * reasons.
6626 * XXXRTH We should check if the question
6627 * we're asking requires EDNS0, and
6628 * if so, we should bail out.
6630 options |= DNS_FETCHOPT_NOEDNS0;
6631 resend = ISC_TRUE;
6633 * Remember that they don't like EDNS0.
6635 if (message->rcode != dns_rcode_servfail)
6636 dns_adb_changeflags(fctx->adb, query->addrinfo,
6637 DNS_FETCHOPT_NOEDNS0,
6638 DNS_FETCHOPT_NOEDNS0);
6639 inc_stats(fctx->res, dns_resstatscounter_edns0fail);
6640 } else if (message->rcode == dns_rcode_formerr) {
6641 if (ISFORWARDER(query->addrinfo)) {
6643 * This forwarder doesn't understand us,
6644 * but other forwarders might. Keep trying.
6646 broken_server = DNS_R_REMOTEFORMERR;
6647 keep_trying = ISC_TRUE;
6648 } else {
6650 * The server doesn't understand us. Since
6651 * all servers for a zone need similar
6652 * capabilities, we assume that we will get
6653 * FORMERR from all servers, and thus we
6654 * cannot make any more progress with this
6655 * fetch.
6657 log_formerr(fctx, "server sent FORMERR");
6658 result = DNS_R_FORMERR;
6660 } else if (message->rcode == dns_rcode_yxdomain) {
6662 * DNAME mapping failed because the new name
6663 * was too long. There's no chance of success
6664 * for this fetch.
6666 result = DNS_R_YXDOMAIN;
6667 } else if (message->rcode == dns_rcode_badvers) {
6668 unsigned int flags, mask;
6669 unsigned int version;
6671 resend = ISC_TRUE;
6672 version = (opt->ttl >> 16) & 0xff;
6673 flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
6674 DNS_FETCHOPT_EDNSVERSIONSET;
6675 mask = DNS_FETCHOPT_EDNSVERSIONMASK |
6676 DNS_FETCHOPT_EDNSVERSIONSET;
6677 switch (version) {
6678 case 0:
6679 dns_adb_changeflags(fctx->adb, query->addrinfo,
6680 flags, mask);
6681 break;
6682 default:
6683 broken_server = DNS_R_BADVERS;
6684 keep_trying = ISC_TRUE;
6685 break;
6687 } else {
6689 * XXXRTH log.
6691 broken_server = DNS_R_UNEXPECTEDRCODE;
6692 INSIST(broken_server != ISC_R_SUCCESS);
6693 keep_trying = ISC_TRUE;
6695 goto done;
6699 * Is the question the same as the one we asked?
6701 result = same_question(fctx);
6702 if (result != ISC_R_SUCCESS) {
6703 /* XXXRTH Log */
6704 if (result == DNS_R_FORMERR)
6705 keep_trying = ISC_TRUE;
6706 goto done;
6710 * Is the server lame?
6712 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
6713 is_lame(fctx)) {
6714 inc_stats(fctx->res, dns_resstatscounter_lame);
6715 log_lame(fctx, query->addrinfo);
6716 result = dns_adb_marklame(fctx->adb, query->addrinfo,
6717 &fctx->name, fctx->type,
6718 now + fctx->res->lame_ttl);
6719 if (result != ISC_R_SUCCESS)
6720 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6721 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
6722 "could not mark server as lame: %s",
6723 isc_result_totext(result));
6724 broken_server = DNS_R_LAME;
6725 keep_trying = ISC_TRUE;
6726 goto done;
6730 * Enforce delegations only zones like NET and COM.
6732 if (!ISFORWARDER(query->addrinfo) &&
6733 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
6734 !dns_name_equal(&fctx->domain, &fctx->name) &&
6735 fix_mustbedelegationornxdomain(message, fctx)) {
6736 char namebuf[DNS_NAME_FORMATSIZE];
6737 char domainbuf[DNS_NAME_FORMATSIZE];
6738 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6739 char classbuf[64];
6740 char typebuf[64];
6742 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
6743 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
6744 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
6745 dns_rdataclass_format(fctx->res->rdclass, classbuf,
6746 sizeof(classbuf));
6747 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6748 sizeof(addrbuf));
6750 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
6751 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
6752 "enforced delegation-only for '%s' (%s/%s/%s) "
6753 "from %s",
6754 domainbuf, namebuf, typebuf, classbuf, addrbuf);
6757 if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
6758 checknames(message);
6761 * Clear cache bits.
6763 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
6766 * Did we get any answers?
6768 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
6769 (message->rcode == dns_rcode_noerror ||
6770 message->rcode == dns_rcode_nxdomain)) {
6772 * [normal case]
6773 * We've got answers. If it has an authoritative answer or an
6774 * answer from a forwarder, we're done.
6776 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
6777 ISFORWARDER(query->addrinfo))
6778 result = answer_response(fctx);
6779 else if (iscname(fctx) &&
6780 fctx->type != dns_rdatatype_any &&
6781 fctx->type != dns_rdatatype_cname) {
6783 * A BIND8 server could return a non-authoritative
6784 * answer when a CNAME is followed. We should treat
6785 * it as a valid answer.
6787 result = answer_response(fctx);
6788 } else {
6789 if (fctx->type == dns_rdatatype_ns) {
6791 * A BIND 8 server could incorrectly return a
6792 * non-authoritative answer to an NS query
6793 * instead of a referral. Since this answer
6794 * lacks the SIGs necessary to do DNSSEC
6795 * validation, we must invoke the following
6796 * special kludge to treat it as a referral.
6798 result = noanswer_response(fctx, NULL,
6799 LOOK_FOR_NS_IN_ANSWER);
6800 } else {
6802 * Some other servers may still somehow include
6803 * an answer when it should return a referral
6804 * with an empty answer. Check to see if we can
6805 * treat this as a referral by ignoring the
6806 * answer. Further more, there may be an
6807 * implementation that moves A/AAAA glue records
6808 * to the answer section for that type of
6809 * delegation when the query is for that glue
6810 * record. LOOK_FOR_GLUE_IN_ANSWER will handle
6811 * such a corner case.
6813 result = noanswer_response(fctx, NULL,
6814 LOOK_FOR_GLUE_IN_ANSWER);
6816 if (result != DNS_R_DELEGATION) {
6818 * At this point, AA is not set, the response
6819 * is not a referral, and the server is not a
6820 * forwarder. It is technically lame and it's
6821 * easier to treat it as such than to figure out
6822 * some more elaborate course of action.
6824 broken_server = DNS_R_LAME;
6825 keep_trying = ISC_TRUE;
6826 goto done;
6828 goto force_referral;
6830 if (result != ISC_R_SUCCESS) {
6831 if (result == DNS_R_FORMERR)
6832 keep_trying = ISC_TRUE;
6833 goto done;
6835 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
6836 message->rcode == dns_rcode_noerror ||
6837 message->rcode == dns_rcode_nxdomain) {
6839 * NXDOMAIN, NXRDATASET, or referral.
6841 result = noanswer_response(fctx, NULL, 0);
6842 if (result == DNS_R_CHASEDSSERVERS) {
6843 } else if (result == DNS_R_DELEGATION) {
6844 force_referral:
6846 * We don't have the answer, but we know a better
6847 * place to look.
6849 get_nameservers = ISC_TRUE;
6850 keep_trying = ISC_TRUE;
6852 * We have a new set of name servers, and it
6853 * has not experienced any restarts yet.
6855 fctx->restarts = 0;
6858 * Update local statistics counters collected for each
6859 * new zone.
6861 fctx->referrals++;
6862 fctx->querysent = 0;
6863 fctx->lamecount = 0;
6864 fctx->neterr = 0;
6865 fctx->badresp = 0;
6866 fctx->adberr = 0;
6868 result = ISC_R_SUCCESS;
6869 } else if (result != ISC_R_SUCCESS) {
6871 * Something has gone wrong.
6873 if (result == DNS_R_FORMERR)
6874 keep_trying = ISC_TRUE;
6875 goto done;
6877 } else {
6879 * The server is insane.
6881 /* XXXRTH Log */
6882 broken_server = DNS_R_UNEXPECTEDRCODE;
6883 keep_trying = ISC_TRUE;
6884 goto done;
6888 * Follow additional section data chains.
6890 chase_additional(fctx);
6893 * Cache the cacheable parts of the message. This may also cause
6894 * work to be queued to the DNSSEC validator.
6896 if (WANTCACHE(fctx)) {
6897 result = cache_message(fctx, query->addrinfo, now);
6898 if (result != ISC_R_SUCCESS)
6899 goto done;
6903 * Ncache the negatively cacheable parts of the message. This may
6904 * also cause work to be queued to the DNSSEC validator.
6906 if (WANTNCACHE(fctx)) {
6907 dns_rdatatype_t covers;
6908 if (message->rcode == dns_rcode_nxdomain)
6909 covers = dns_rdatatype_any;
6910 else
6911 covers = fctx->type;
6914 * Cache any negative cache entries in the message.
6916 result = ncache_message(fctx, query->addrinfo, covers, now);
6919 done:
6921 * Remember the query's addrinfo, in case we need to mark the
6922 * server as broken.
6924 addrinfo = query->addrinfo;
6927 * Cancel the query.
6929 * XXXRTH Don't cancel the query if waiting for validation?
6931 fctx_cancelquery(&query, &devent, finish, ISC_FALSE);
6933 if (keep_trying) {
6934 if (result == DNS_R_FORMERR)
6935 broken_server = DNS_R_FORMERR;
6936 if (broken_server != ISC_R_SUCCESS) {
6938 * Add this server to the list of bad servers for
6939 * this fctx.
6941 add_bad(fctx, addrinfo, broken_server, broken_type);
6944 if (get_nameservers) {
6945 dns_name_t *name;
6946 dns_fixedname_init(&foundname);
6947 fname = dns_fixedname_name(&foundname);
6948 if (result != ISC_R_SUCCESS) {
6949 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6950 return;
6952 findoptions = 0;
6953 if (dns_rdatatype_atparent(fctx->type))
6954 findoptions |= DNS_DBFIND_NOEXACT;
6955 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
6956 name = &fctx->name;
6957 else
6958 name = &fctx->domain;
6959 result = dns_view_findzonecut(fctx->res->view,
6960 name, fname,
6961 now, findoptions,
6962 ISC_TRUE,
6963 &fctx->nameservers,
6964 NULL);
6965 if (result != ISC_R_SUCCESS) {
6966 FCTXTRACE("couldn't find a zonecut");
6967 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6968 return;
6970 if (!dns_name_issubdomain(fname, &fctx->domain)) {
6972 * The best nameservers are now above our
6973 * QDOMAIN.
6975 FCTXTRACE("nameservers now above QDOMAIN");
6976 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6977 return;
6979 dns_name_free(&fctx->domain,
6980 fctx->res->buckets[fctx->bucketnum].mctx);
6981 dns_name_init(&fctx->domain, NULL);
6982 result = dns_name_dup(fname,
6983 fctx->res->buckets[fctx->bucketnum].mctx,
6984 &fctx->domain);
6985 if (result != ISC_R_SUCCESS) {
6986 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6987 return;
6989 fctx_cancelqueries(fctx, ISC_TRUE);
6990 fctx_cleanupfinds(fctx);
6991 fctx_cleanupaltfinds(fctx);
6992 fctx_cleanupforwaddrs(fctx);
6993 fctx_cleanupaltaddrs(fctx);
6996 * Try again.
6998 fctx_try(fctx, !get_nameservers);
6999 } else if (resend) {
7001 * Resend (probably with changed options).
7003 FCTXTRACE("resend");
7004 inc_stats(fctx->res, dns_resstatscounter_retry);
7005 result = fctx_query(fctx, addrinfo, options);
7006 if (result != ISC_R_SUCCESS)
7007 fctx_done(fctx, result, __LINE__);
7008 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
7010 * All has gone well so far, but we are waiting for the
7011 * DNSSEC validator to validate the answer.
7013 FCTXTRACE("wait for validator");
7014 fctx_cancelqueries(fctx, ISC_TRUE);
7016 * We must not retransmit while the validator is working;
7017 * it has references to the current rmessage.
7019 result = fctx_stopidletimer(fctx);
7020 if (result != ISC_R_SUCCESS)
7021 fctx_done(fctx, result, __LINE__);
7022 } else if (result == DNS_R_CHASEDSSERVERS) {
7023 unsigned int n;
7024 add_bad(fctx, addrinfo, result, broken_type);
7025 fctx_cancelqueries(fctx, ISC_TRUE);
7026 fctx_cleanupfinds(fctx);
7027 fctx_cleanupforwaddrs(fctx);
7029 n = dns_name_countlabels(&fctx->name);
7030 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
7032 FCTXTRACE("suspending DS lookup to find parent's NS records");
7034 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
7035 dns_rdatatype_ns,
7036 NULL, NULL, NULL, 0, task,
7037 resume_dslookup, fctx,
7038 &fctx->nsrrset, NULL,
7039 &fctx->nsfetch);
7040 if (result != ISC_R_SUCCESS)
7041 fctx_done(fctx, result, __LINE__);
7042 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7043 fctx->references++;
7044 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7045 result = fctx_stopidletimer(fctx);
7046 if (result != ISC_R_SUCCESS)
7047 fctx_done(fctx, result, __LINE__);
7048 } else {
7050 * We're done.
7052 fctx_done(fctx, result, __LINE__);
7057 /***
7058 *** Resolver Methods
7059 ***/
7061 static void
7062 destroy(dns_resolver_t *res) {
7063 unsigned int i;
7064 alternate_t *a;
7066 REQUIRE(res->references == 0);
7067 REQUIRE(!res->priming);
7068 REQUIRE(res->primefetch == NULL);
7070 RTRACE("destroy");
7072 INSIST(res->nfctx == 0);
7074 DESTROYLOCK(&res->primelock);
7075 DESTROYLOCK(&res->nlock);
7076 DESTROYLOCK(&res->lock);
7077 for (i = 0; i < res->nbuckets; i++) {
7078 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
7079 isc_task_shutdown(res->buckets[i].task);
7080 isc_task_detach(&res->buckets[i].task);
7081 DESTROYLOCK(&res->buckets[i].lock);
7082 isc_mem_detach(&res->buckets[i].mctx);
7084 isc_mem_put(res->mctx, res->buckets,
7085 res->nbuckets * sizeof(fctxbucket_t));
7086 if (res->dispatchv4 != NULL)
7087 dns_dispatch_detach(&res->dispatchv4);
7088 if (res->dispatchv6 != NULL)
7089 dns_dispatch_detach(&res->dispatchv6);
7090 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
7091 ISC_LIST_UNLINK(res->alternates, a, link);
7092 if (!a->isaddress)
7093 dns_name_free(&a->_u._n.name, res->mctx);
7094 isc_mem_put(res->mctx, a, sizeof(*a));
7096 dns_resolver_reset_algorithms(res);
7097 dns_resolver_resetmustbesecure(res);
7098 #if USE_ALGLOCK
7099 isc_rwlock_destroy(&res->alglock);
7100 #endif
7101 #if USE_MBSLOCK
7102 isc_rwlock_destroy(&res->mbslock);
7103 #endif
7104 isc_timer_detach(&res->spillattimer);
7105 res->magic = 0;
7106 isc_mem_put(res->mctx, res, sizeof(*res));
7109 static void
7110 send_shutdown_events(dns_resolver_t *res) {
7111 isc_event_t *event, *next_event;
7112 isc_task_t *etask;
7115 * Caller must be holding the resolver lock.
7118 for (event = ISC_LIST_HEAD(res->whenshutdown);
7119 event != NULL;
7120 event = next_event) {
7121 next_event = ISC_LIST_NEXT(event, ev_link);
7122 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
7123 etask = event->ev_sender;
7124 event->ev_sender = res;
7125 isc_task_sendanddetach(&etask, &event);
7129 static void
7130 empty_bucket(dns_resolver_t *res) {
7131 RTRACE("empty_bucket");
7133 LOCK(&res->lock);
7135 INSIST(res->activebuckets > 0);
7136 res->activebuckets--;
7137 if (res->activebuckets == 0)
7138 send_shutdown_events(res);
7140 UNLOCK(&res->lock);
7143 static void
7144 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
7145 dns_resolver_t *res = event->ev_arg;
7146 isc_result_t result;
7147 unsigned int count;
7148 isc_boolean_t logit = ISC_FALSE;
7150 REQUIRE(VALID_RESOLVER(res));
7152 UNUSED(task);
7154 LOCK(&res->lock);
7155 INSIST(!res->exiting);
7156 if (res->spillat > res->spillatmin) {
7157 res->spillat--;
7158 logit = ISC_TRUE;
7160 if (res->spillat <= res->spillatmin) {
7161 result = isc_timer_reset(res->spillattimer,
7162 isc_timertype_inactive, NULL,
7163 NULL, ISC_TRUE);
7164 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7166 count = res->spillat;
7167 UNLOCK(&res->lock);
7168 if (logit)
7169 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7170 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
7171 "clients-per-query decreased to %u", count);
7173 isc_event_free(&event);
7176 isc_result_t
7177 dns_resolver_create(dns_view_t *view,
7178 isc_taskmgr_t *taskmgr, unsigned int ntasks,
7179 isc_socketmgr_t *socketmgr,
7180 isc_timermgr_t *timermgr,
7181 unsigned int options,
7182 dns_dispatchmgr_t *dispatchmgr,
7183 dns_dispatch_t *dispatchv4,
7184 dns_dispatch_t *dispatchv6,
7185 dns_resolver_t **resp)
7187 dns_resolver_t *res;
7188 isc_result_t result = ISC_R_SUCCESS;
7189 unsigned int i, buckets_created = 0;
7190 isc_task_t *task = NULL;
7191 char name[16];
7192 unsigned dispattr;
7195 * Create a resolver.
7198 REQUIRE(DNS_VIEW_VALID(view));
7199 REQUIRE(ntasks > 0);
7200 REQUIRE(resp != NULL && *resp == NULL);
7201 REQUIRE(dispatchmgr != NULL);
7202 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
7204 res = isc_mem_get(view->mctx, sizeof(*res));
7205 if (res == NULL)
7206 return (ISC_R_NOMEMORY);
7207 RTRACE("create");
7208 res->mctx = view->mctx;
7209 res->rdclass = view->rdclass;
7210 res->socketmgr = socketmgr;
7211 res->timermgr = timermgr;
7212 res->taskmgr = taskmgr;
7213 res->dispatchmgr = dispatchmgr;
7214 res->view = view;
7215 res->options = options;
7216 res->lame_ttl = 0;
7217 ISC_LIST_INIT(res->alternates);
7218 res->udpsize = RECV_BUFFER_SIZE;
7219 res->algorithms = NULL;
7220 res->mustbesecure = NULL;
7221 res->spillatmin = res->spillat = 10;
7222 res->spillatmax = 100;
7223 res->spillattimer = NULL;
7224 res->zero_no_soa_ttl = ISC_FALSE;
7225 res->ndisps = 0;
7226 res->nextdisp = 0; /* meaningless at this point, but init it */
7227 res->nbuckets = ntasks;
7228 res->activebuckets = ntasks;
7229 res->buckets = isc_mem_get(view->mctx,
7230 ntasks * sizeof(fctxbucket_t));
7231 if (res->buckets == NULL) {
7232 result = ISC_R_NOMEMORY;
7233 goto cleanup_res;
7235 for (i = 0; i < ntasks; i++) {
7236 result = isc_mutex_init(&res->buckets[i].lock);
7237 if (result != ISC_R_SUCCESS)
7238 goto cleanup_buckets;
7239 res->buckets[i].task = NULL;
7240 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
7241 if (result != ISC_R_SUCCESS) {
7242 DESTROYLOCK(&res->buckets[i].lock);
7243 goto cleanup_buckets;
7245 res->buckets[i].mctx = NULL;
7246 snprintf(name, sizeof(name), "res%u", i);
7247 #ifdef ISC_PLATFORM_USETHREADS
7249 * Use a separate memory context for each bucket to reduce
7250 * contention among multiple threads. Do this only when
7251 * enabling threads because it will be require more memory.
7253 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
7254 if (result != ISC_R_SUCCESS) {
7255 isc_task_detach(&res->buckets[i].task);
7256 DESTROYLOCK(&res->buckets[i].lock);
7257 goto cleanup_buckets;
7259 isc_mem_setname(res->buckets[i].mctx, name, NULL);
7260 #else
7261 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
7262 #endif
7263 isc_task_setname(res->buckets[i].task, name, res);
7264 ISC_LIST_INIT(res->buckets[i].fctxs);
7265 res->buckets[i].exiting = ISC_FALSE;
7266 buckets_created++;
7269 res->dispatchv4 = NULL;
7270 if (dispatchv4 != NULL) {
7271 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
7272 dispattr = dns_dispatch_getattributes(dispatchv4);
7273 res->exclusivev4 =
7274 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7277 res->dispatchv6 = NULL;
7278 if (dispatchv6 != NULL) {
7279 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
7280 dispattr = dns_dispatch_getattributes(dispatchv6);
7281 res->exclusivev6 =
7282 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7285 res->references = 1;
7286 res->exiting = ISC_FALSE;
7287 res->frozen = ISC_FALSE;
7288 ISC_LIST_INIT(res->whenshutdown);
7289 res->priming = ISC_FALSE;
7290 res->primefetch = NULL;
7291 res->nfctx = 0;
7293 result = isc_mutex_init(&res->lock);
7294 if (result != ISC_R_SUCCESS)
7295 goto cleanup_dispatches;
7297 result = isc_mutex_init(&res->nlock);
7298 if (result != ISC_R_SUCCESS)
7299 goto cleanup_lock;
7301 result = isc_mutex_init(&res->primelock);
7302 if (result != ISC_R_SUCCESS)
7303 goto cleanup_nlock;
7305 task = NULL;
7306 result = isc_task_create(taskmgr, 0, &task);
7307 if (result != ISC_R_SUCCESS)
7308 goto cleanup_primelock;
7310 result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
7311 task, spillattimer_countdown, res,
7312 &res->spillattimer);
7313 isc_task_detach(&task);
7314 if (result != ISC_R_SUCCESS)
7315 goto cleanup_primelock;
7317 #if USE_ALGLOCK
7318 result = isc_rwlock_init(&res->alglock, 0, 0);
7319 if (result != ISC_R_SUCCESS)
7320 goto cleanup_spillattimer;
7321 #endif
7322 #if USE_MBSLOCK
7323 result = isc_rwlock_init(&res->mbslock, 0, 0);
7324 if (result != ISC_R_SUCCESS)
7325 goto cleanup_alglock;
7326 #endif
7328 res->magic = RES_MAGIC;
7330 *resp = res;
7332 return (ISC_R_SUCCESS);
7334 #if USE_MBSLOCK
7335 cleanup_alglock:
7336 #if USE_ALGLOCK
7337 isc_rwlock_destroy(&res->alglock);
7338 #endif
7339 #endif
7340 #if USE_ALGLOCK || USE_MBSLOCK
7341 cleanup_spillattimer:
7342 isc_timer_detach(&res->spillattimer);
7343 #endif
7345 cleanup_primelock:
7346 DESTROYLOCK(&res->primelock);
7348 cleanup_nlock:
7349 DESTROYLOCK(&res->nlock);
7351 cleanup_lock:
7352 DESTROYLOCK(&res->lock);
7354 cleanup_dispatches:
7355 if (res->dispatchv6 != NULL)
7356 dns_dispatch_detach(&res->dispatchv6);
7357 if (res->dispatchv4 != NULL)
7358 dns_dispatch_detach(&res->dispatchv4);
7360 cleanup_buckets:
7361 for (i = 0; i < buckets_created; i++) {
7362 isc_mem_detach(&res->buckets[i].mctx);
7363 DESTROYLOCK(&res->buckets[i].lock);
7364 isc_task_shutdown(res->buckets[i].task);
7365 isc_task_detach(&res->buckets[i].task);
7367 isc_mem_put(view->mctx, res->buckets,
7368 res->nbuckets * sizeof(fctxbucket_t));
7370 cleanup_res:
7371 isc_mem_put(view->mctx, res, sizeof(*res));
7373 return (result);
7376 #ifdef BIND9
7377 static void
7378 prime_done(isc_task_t *task, isc_event_t *event) {
7379 dns_resolver_t *res;
7380 dns_fetchevent_t *fevent;
7381 dns_fetch_t *fetch;
7382 dns_db_t *db = NULL;
7384 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
7385 fevent = (dns_fetchevent_t *)event;
7386 res = event->ev_arg;
7387 REQUIRE(VALID_RESOLVER(res));
7389 UNUSED(task);
7391 LOCK(&res->lock);
7393 INSIST(res->priming);
7394 res->priming = ISC_FALSE;
7395 LOCK(&res->primelock);
7396 fetch = res->primefetch;
7397 res->primefetch = NULL;
7398 UNLOCK(&res->primelock);
7400 UNLOCK(&res->lock);
7402 if (fevent->result == ISC_R_SUCCESS &&
7403 res->view->cache != NULL && res->view->hints != NULL) {
7404 dns_cache_attachdb(res->view->cache, &db);
7405 dns_root_checkhints(res->view, res->view->hints, db);
7406 dns_db_detach(&db);
7409 if (fevent->node != NULL)
7410 dns_db_detachnode(fevent->db, &fevent->node);
7411 if (fevent->db != NULL)
7412 dns_db_detach(&fevent->db);
7413 if (dns_rdataset_isassociated(fevent->rdataset))
7414 dns_rdataset_disassociate(fevent->rdataset);
7415 INSIST(fevent->sigrdataset == NULL);
7417 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
7419 isc_event_free(&event);
7420 dns_resolver_destroyfetch(&fetch);
7423 void
7424 dns_resolver_prime(dns_resolver_t *res) {
7425 isc_boolean_t want_priming = ISC_FALSE;
7426 dns_rdataset_t *rdataset;
7427 isc_result_t result;
7429 REQUIRE(VALID_RESOLVER(res));
7430 REQUIRE(res->frozen);
7432 RTRACE("dns_resolver_prime");
7434 LOCK(&res->lock);
7436 if (!res->exiting && !res->priming) {
7437 INSIST(res->primefetch == NULL);
7438 res->priming = ISC_TRUE;
7439 want_priming = ISC_TRUE;
7442 UNLOCK(&res->lock);
7444 if (want_priming) {
7446 * To avoid any possible recursive locking problems, we
7447 * start the priming fetch like any other fetch, and holding
7448 * no resolver locks. No one else will try to start it
7449 * because we're the ones who set res->priming to true.
7450 * Any other callers of dns_resolver_prime() while we're
7451 * running will see that res->priming is already true and
7452 * do nothing.
7454 RTRACE("priming");
7455 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
7456 if (rdataset == NULL) {
7457 LOCK(&res->lock);
7458 INSIST(res->priming);
7459 INSIST(res->primefetch == NULL);
7460 res->priming = ISC_FALSE;
7461 UNLOCK(&res->lock);
7462 return;
7464 dns_rdataset_init(rdataset);
7465 LOCK(&res->primelock);
7466 result = dns_resolver_createfetch(res, dns_rootname,
7467 dns_rdatatype_ns,
7468 NULL, NULL, NULL, 0,
7469 res->buckets[0].task,
7470 prime_done,
7471 res, rdataset, NULL,
7472 &res->primefetch);
7473 UNLOCK(&res->primelock);
7474 if (result != ISC_R_SUCCESS) {
7475 LOCK(&res->lock);
7476 INSIST(res->priming);
7477 res->priming = ISC_FALSE;
7478 UNLOCK(&res->lock);
7482 #endif /* BIND9 */
7484 void
7485 dns_resolver_freeze(dns_resolver_t *res) {
7488 * Freeze resolver.
7491 REQUIRE(VALID_RESOLVER(res));
7492 REQUIRE(!res->frozen);
7494 res->frozen = ISC_TRUE;
7497 void
7498 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
7499 REQUIRE(VALID_RESOLVER(source));
7500 REQUIRE(targetp != NULL && *targetp == NULL);
7502 RRTRACE(source, "attach");
7503 LOCK(&source->lock);
7504 REQUIRE(!source->exiting);
7506 INSIST(source->references > 0);
7507 source->references++;
7508 INSIST(source->references != 0);
7509 UNLOCK(&source->lock);
7511 *targetp = source;
7514 void
7515 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
7516 isc_event_t **eventp)
7518 isc_task_t *clone;
7519 isc_event_t *event;
7521 REQUIRE(VALID_RESOLVER(res));
7522 REQUIRE(eventp != NULL);
7524 event = *eventp;
7525 *eventp = NULL;
7527 LOCK(&res->lock);
7529 if (res->exiting && res->activebuckets == 0) {
7531 * We're already shutdown. Send the event.
7533 event->ev_sender = res;
7534 isc_task_send(task, &event);
7535 } else {
7536 clone = NULL;
7537 isc_task_attach(task, &clone);
7538 event->ev_sender = clone;
7539 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
7542 UNLOCK(&res->lock);
7545 void
7546 dns_resolver_shutdown(dns_resolver_t *res) {
7547 unsigned int i;
7548 fetchctx_t *fctx;
7549 isc_socket_t *sock;
7550 isc_result_t result;
7552 REQUIRE(VALID_RESOLVER(res));
7554 RTRACE("shutdown");
7556 LOCK(&res->lock);
7558 if (!res->exiting) {
7559 RTRACE("exiting");
7560 res->exiting = ISC_TRUE;
7562 for (i = 0; i < res->nbuckets; i++) {
7563 LOCK(&res->buckets[i].lock);
7564 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
7565 fctx != NULL;
7566 fctx = ISC_LIST_NEXT(fctx, link))
7567 fctx_shutdown(fctx);
7568 if (res->dispatchv4 != NULL && !res->exclusivev4) {
7569 sock = dns_dispatch_getsocket(res->dispatchv4);
7570 isc_socket_cancel(sock, res->buckets[i].task,
7571 ISC_SOCKCANCEL_ALL);
7573 if (res->dispatchv6 != NULL && !res->exclusivev6) {
7574 sock = dns_dispatch_getsocket(res->dispatchv6);
7575 isc_socket_cancel(sock, res->buckets[i].task,
7576 ISC_SOCKCANCEL_ALL);
7578 res->buckets[i].exiting = ISC_TRUE;
7579 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
7580 INSIST(res->activebuckets > 0);
7581 res->activebuckets--;
7583 UNLOCK(&res->buckets[i].lock);
7585 if (res->activebuckets == 0)
7586 send_shutdown_events(res);
7587 result = isc_timer_reset(res->spillattimer,
7588 isc_timertype_inactive, NULL,
7589 NULL, ISC_TRUE);
7590 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7593 UNLOCK(&res->lock);
7596 void
7597 dns_resolver_detach(dns_resolver_t **resp) {
7598 dns_resolver_t *res;
7599 isc_boolean_t need_destroy = ISC_FALSE;
7601 REQUIRE(resp != NULL);
7602 res = *resp;
7603 REQUIRE(VALID_RESOLVER(res));
7605 RTRACE("detach");
7607 LOCK(&res->lock);
7609 INSIST(res->references > 0);
7610 res->references--;
7611 if (res->references == 0) {
7612 INSIST(res->exiting && res->activebuckets == 0);
7613 need_destroy = ISC_TRUE;
7616 UNLOCK(&res->lock);
7618 if (need_destroy)
7619 destroy(res);
7621 *resp = NULL;
7624 static inline isc_boolean_t
7625 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
7626 unsigned int options)
7628 if (fctx->type != type || fctx->options != options)
7629 return (ISC_FALSE);
7630 return (dns_name_equal(&fctx->name, name));
7633 static inline void
7634 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
7635 char namebuf[DNS_NAME_FORMATSIZE];
7636 char typebuf[DNS_RDATATYPE_FORMATSIZE];
7637 int level = ISC_LOG_DEBUG(1);
7639 if (! isc_log_wouldlog(dns_lctx, level))
7640 return;
7642 dns_name_format(name, namebuf, sizeof(namebuf));
7643 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
7645 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7646 DNS_LOGMODULE_RESOLVER, level,
7647 "createfetch: %s %s", namebuf, typebuf);
7650 isc_result_t
7651 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
7652 dns_rdatatype_t type,
7653 dns_name_t *domain, dns_rdataset_t *nameservers,
7654 dns_forwarders_t *forwarders,
7655 unsigned int options, isc_task_t *task,
7656 isc_taskaction_t action, void *arg,
7657 dns_rdataset_t *rdataset,
7658 dns_rdataset_t *sigrdataset,
7659 dns_fetch_t **fetchp)
7661 return (dns_resolver_createfetch2(res, name, type, domain,
7662 nameservers, forwarders, NULL, 0,
7663 options, task, action, arg,
7664 rdataset, sigrdataset, fetchp));
7667 isc_result_t
7668 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
7669 dns_rdatatype_t type,
7670 dns_name_t *domain, dns_rdataset_t *nameservers,
7671 dns_forwarders_t *forwarders,
7672 isc_sockaddr_t *client, dns_messageid_t id,
7673 unsigned int options, isc_task_t *task,
7674 isc_taskaction_t action, void *arg,
7675 dns_rdataset_t *rdataset,
7676 dns_rdataset_t *sigrdataset,
7677 dns_fetch_t **fetchp)
7679 dns_fetch_t *fetch;
7680 fetchctx_t *fctx = NULL;
7681 isc_result_t result = ISC_R_SUCCESS;
7682 unsigned int bucketnum;
7683 isc_boolean_t new_fctx = ISC_FALSE;
7684 isc_event_t *event;
7685 unsigned int count = 0;
7686 unsigned int spillat;
7687 unsigned int spillatmin;
7689 UNUSED(forwarders);
7691 REQUIRE(VALID_RESOLVER(res));
7692 REQUIRE(res->frozen);
7693 /* XXXRTH Check for meta type */
7694 if (domain != NULL) {
7695 REQUIRE(DNS_RDATASET_VALID(nameservers));
7696 REQUIRE(nameservers->type == dns_rdatatype_ns);
7697 } else
7698 REQUIRE(nameservers == NULL);
7699 REQUIRE(forwarders == NULL);
7700 REQUIRE(!dns_rdataset_isassociated(rdataset));
7701 REQUIRE(sigrdataset == NULL ||
7702 !dns_rdataset_isassociated(sigrdataset));
7703 REQUIRE(fetchp != NULL && *fetchp == NULL);
7705 log_fetch(name, type);
7708 * XXXRTH use a mempool?
7710 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
7711 if (fetch == NULL)
7712 return (ISC_R_NOMEMORY);
7714 bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
7716 LOCK(&res->lock);
7717 spillat = res->spillat;
7718 spillatmin = res->spillatmin;
7719 UNLOCK(&res->lock);
7720 LOCK(&res->buckets[bucketnum].lock);
7722 if (res->buckets[bucketnum].exiting) {
7723 result = ISC_R_SHUTTINGDOWN;
7724 goto unlock;
7727 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
7728 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
7729 fctx != NULL;
7730 fctx = ISC_LIST_NEXT(fctx, link)) {
7731 if (fctx_match(fctx, name, type, options))
7732 break;
7737 * Is this a duplicate?
7739 if (fctx != NULL && client != NULL) {
7740 dns_fetchevent_t *fevent;
7741 for (fevent = ISC_LIST_HEAD(fctx->events);
7742 fevent != NULL;
7743 fevent = ISC_LIST_NEXT(fevent, ev_link)) {
7744 if (fevent->client != NULL && fevent->id == id &&
7745 isc_sockaddr_equal(fevent->client, client)) {
7746 result = DNS_R_DUPLICATE;
7747 goto unlock;
7749 count++;
7752 if (count >= spillatmin && spillatmin != 0) {
7753 INSIST(fctx != NULL);
7754 if (count >= spillat)
7755 fctx->spilled = ISC_TRUE;
7756 if (fctx->spilled) {
7757 result = DNS_R_DROP;
7758 goto unlock;
7763 * If we didn't have a fetch, would attach to a done fetch, this
7764 * fetch has already cloned its results, or if the fetch has gone
7765 * "idle" (no one was interested in it), we need to start a new
7766 * fetch instead of joining with the existing one.
7768 if (fctx == NULL ||
7769 fctx->state == fetchstate_done ||
7770 fctx->cloned ||
7771 ISC_LIST_EMPTY(fctx->events)) {
7772 fctx = NULL;
7773 result = fctx_create(res, name, type, domain, nameservers,
7774 options, bucketnum, &fctx);
7775 if (result != ISC_R_SUCCESS)
7776 goto unlock;
7777 new_fctx = ISC_TRUE;
7780 result = fctx_join(fctx, task, client, id, action, arg,
7781 rdataset, sigrdataset, fetch);
7782 if (new_fctx) {
7783 if (result == ISC_R_SUCCESS) {
7785 * Launch this fctx.
7787 event = &fctx->control_event;
7788 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
7789 DNS_EVENT_FETCHCONTROL,
7790 fctx_start, fctx, NULL,
7791 NULL, NULL);
7792 isc_task_send(res->buckets[bucketnum].task, &event);
7793 } else {
7795 * We don't care about the result of fctx_destroy()
7796 * since we know we're not exiting.
7798 (void)fctx_destroy(fctx);
7802 unlock:
7803 UNLOCK(&res->buckets[bucketnum].lock);
7805 if (result == ISC_R_SUCCESS) {
7806 FTRACE("created");
7807 *fetchp = fetch;
7808 } else
7809 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
7811 return (result);
7814 void
7815 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
7816 fetchctx_t *fctx;
7817 dns_resolver_t *res;
7818 dns_fetchevent_t *event, *next_event;
7819 isc_task_t *etask;
7821 REQUIRE(DNS_FETCH_VALID(fetch));
7822 fctx = fetch->private;
7823 REQUIRE(VALID_FCTX(fctx));
7824 res = fctx->res;
7826 FTRACE("cancelfetch");
7828 LOCK(&res->buckets[fctx->bucketnum].lock);
7831 * Find the completion event for this fetch (as opposed
7832 * to those for other fetches that have joined the same
7833 * fctx) and send it with result = ISC_R_CANCELED.
7835 event = NULL;
7836 if (fctx->state != fetchstate_done) {
7837 for (event = ISC_LIST_HEAD(fctx->events);
7838 event != NULL;
7839 event = next_event) {
7840 next_event = ISC_LIST_NEXT(event, ev_link);
7841 if (event->fetch == fetch) {
7842 ISC_LIST_UNLINK(fctx->events, event, ev_link);
7843 break;
7847 if (event != NULL) {
7848 etask = event->ev_sender;
7849 event->ev_sender = fctx;
7850 event->result = ISC_R_CANCELED;
7851 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
7854 * The fctx continues running even if no fetches remain;
7855 * the answer is still cached.
7858 UNLOCK(&res->buckets[fctx->bucketnum].lock);
7861 void
7862 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
7863 dns_fetch_t *fetch;
7864 dns_resolver_t *res;
7865 dns_fetchevent_t *event, *next_event;
7866 fetchctx_t *fctx;
7867 unsigned int bucketnum;
7868 isc_boolean_t bucket_empty = ISC_FALSE;
7870 REQUIRE(fetchp != NULL);
7871 fetch = *fetchp;
7872 REQUIRE(DNS_FETCH_VALID(fetch));
7873 fctx = fetch->private;
7874 REQUIRE(VALID_FCTX(fctx));
7875 res = fctx->res;
7877 FTRACE("destroyfetch");
7879 bucketnum = fctx->bucketnum;
7880 LOCK(&res->buckets[bucketnum].lock);
7883 * Sanity check: the caller should have gotten its event before
7884 * trying to destroy the fetch.
7886 event = NULL;
7887 if (fctx->state != fetchstate_done) {
7888 for (event = ISC_LIST_HEAD(fctx->events);
7889 event != NULL;
7890 event = next_event) {
7891 next_event = ISC_LIST_NEXT(event, ev_link);
7892 RUNTIME_CHECK(event->fetch != fetch);
7896 INSIST(fctx->references > 0);
7897 fctx->references--;
7898 if (fctx->references == 0) {
7900 * No one cares about the result of this fetch anymore.
7902 if (fctx->pending == 0 && fctx->nqueries == 0 &&
7903 ISC_LIST_EMPTY(fctx->validators) &&
7904 SHUTTINGDOWN(fctx)) {
7906 * This fctx is already shutdown; we were just
7907 * waiting for the last reference to go away.
7909 bucket_empty = fctx_destroy(fctx);
7910 } else {
7912 * Initiate shutdown.
7914 fctx_shutdown(fctx);
7918 UNLOCK(&res->buckets[bucketnum].lock);
7920 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
7921 *fetchp = NULL;
7923 if (bucket_empty)
7924 empty_bucket(res);
7927 void
7928 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
7929 isc_logcategory_t *category, isc_logmodule_t *module,
7930 int level, isc_boolean_t duplicateok)
7932 fetchctx_t *fctx;
7933 dns_resolver_t *res;
7934 char domainbuf[DNS_NAME_FORMATSIZE];
7936 REQUIRE(DNS_FETCH_VALID(fetch));
7937 fctx = fetch->private;
7938 REQUIRE(VALID_FCTX(fctx));
7939 res = fctx->res;
7941 LOCK(&res->buckets[fctx->bucketnum].lock);
7943 INSIST(fctx->exitline >= 0);
7944 if (!fctx->logged || duplicateok) {
7945 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
7946 isc_log_write(lctx, category, module, level,
7947 "fetch completed at %s:%d for %s in "
7948 "%" ISC_PRINT_QUADFORMAT "u."
7949 "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
7950 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
7951 "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
7952 "adberr:%u,findfail:%u,valfail:%u]",
7953 __FILE__, fctx->exitline, fctx->info,
7954 fctx->duration / 1000000,
7955 fctx->duration % 1000000,
7956 isc_result_totext(fctx->result),
7957 isc_result_totext(fctx->vresult), domainbuf,
7958 fctx->referrals, fctx->restarts,
7959 fctx->querysent, fctx->timeouts, fctx->lamecount,
7960 fctx->neterr, fctx->badresp, fctx->adberr,
7961 fctx->findfail, fctx->valfail);
7962 fctx->logged = ISC_TRUE;
7965 UNLOCK(&res->buckets[fctx->bucketnum].lock);
7968 dns_dispatchmgr_t *
7969 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
7970 REQUIRE(VALID_RESOLVER(resolver));
7971 return (resolver->dispatchmgr);
7974 dns_dispatch_t *
7975 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
7976 REQUIRE(VALID_RESOLVER(resolver));
7977 return (resolver->dispatchv4);
7980 dns_dispatch_t *
7981 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
7982 REQUIRE(VALID_RESOLVER(resolver));
7983 return (resolver->dispatchv6);
7986 isc_socketmgr_t *
7987 dns_resolver_socketmgr(dns_resolver_t *resolver) {
7988 REQUIRE(VALID_RESOLVER(resolver));
7989 return (resolver->socketmgr);
7992 isc_taskmgr_t *
7993 dns_resolver_taskmgr(dns_resolver_t *resolver) {
7994 REQUIRE(VALID_RESOLVER(resolver));
7995 return (resolver->taskmgr);
7998 isc_uint32_t
7999 dns_resolver_getlamettl(dns_resolver_t *resolver) {
8000 REQUIRE(VALID_RESOLVER(resolver));
8001 return (resolver->lame_ttl);
8004 void
8005 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
8006 REQUIRE(VALID_RESOLVER(resolver));
8007 resolver->lame_ttl = lame_ttl;
8010 unsigned int
8011 dns_resolver_nrunning(dns_resolver_t *resolver) {
8012 unsigned int n;
8013 LOCK(&resolver->nlock);
8014 n = resolver->nfctx;
8015 UNLOCK(&resolver->nlock);
8016 return (n);
8019 isc_result_t
8020 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
8021 dns_name_t *name, in_port_t port) {
8022 alternate_t *a;
8023 isc_result_t result;
8025 REQUIRE(VALID_RESOLVER(resolver));
8026 REQUIRE(!resolver->frozen);
8027 REQUIRE((alt == NULL) ^ (name == NULL));
8029 a = isc_mem_get(resolver->mctx, sizeof(*a));
8030 if (a == NULL)
8031 return (ISC_R_NOMEMORY);
8032 if (alt != NULL) {
8033 a->isaddress = ISC_TRUE;
8034 a->_u.addr = *alt;
8035 } else {
8036 a->isaddress = ISC_FALSE;
8037 a->_u._n.port = port;
8038 dns_name_init(&a->_u._n.name, NULL);
8039 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
8040 if (result != ISC_R_SUCCESS) {
8041 isc_mem_put(resolver->mctx, a, sizeof(*a));
8042 return (result);
8045 ISC_LINK_INIT(a, link);
8046 ISC_LIST_APPEND(resolver->alternates, a, link);
8048 return (ISC_R_SUCCESS);
8051 void
8052 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
8053 REQUIRE(VALID_RESOLVER(resolver));
8054 resolver->udpsize = udpsize;
8057 isc_uint16_t
8058 dns_resolver_getudpsize(dns_resolver_t *resolver) {
8059 REQUIRE(VALID_RESOLVER(resolver));
8060 return (resolver->udpsize);
8063 static void
8064 free_algorithm(void *node, void *arg) {
8065 unsigned char *algorithms = node;
8066 isc_mem_t *mctx = arg;
8068 isc_mem_put(mctx, algorithms, *algorithms);
8071 void
8072 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
8074 REQUIRE(VALID_RESOLVER(resolver));
8076 #if USE_ALGLOCK
8077 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8078 #endif
8079 if (resolver->algorithms != NULL)
8080 dns_rbt_destroy(&resolver->algorithms);
8081 #if USE_ALGLOCK
8082 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8083 #endif
8086 isc_result_t
8087 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
8088 unsigned int alg)
8090 unsigned int len, mask;
8091 unsigned char *new;
8092 unsigned char *algorithms;
8093 isc_result_t result;
8094 dns_rbtnode_t *node = NULL;
8096 REQUIRE(VALID_RESOLVER(resolver));
8097 if (alg > 255)
8098 return (ISC_R_RANGE);
8100 #if USE_ALGLOCK
8101 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8102 #endif
8103 if (resolver->algorithms == NULL) {
8104 result = dns_rbt_create(resolver->mctx, free_algorithm,
8105 resolver->mctx, &resolver->algorithms);
8106 if (result != ISC_R_SUCCESS)
8107 goto cleanup;
8110 len = alg/8 + 2;
8111 mask = 1 << (alg%8);
8113 result = dns_rbt_addnode(resolver->algorithms, name, &node);
8115 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
8116 algorithms = node->data;
8117 if (algorithms == NULL || len > *algorithms) {
8118 new = isc_mem_get(resolver->mctx, len);
8119 if (new == NULL) {
8120 result = ISC_R_NOMEMORY;
8121 goto cleanup;
8123 memset(new, 0, len);
8124 if (algorithms != NULL)
8125 memcpy(new, algorithms, *algorithms);
8126 new[len-1] |= mask;
8127 *new = len;
8128 node->data = new;
8129 if (algorithms != NULL)
8130 isc_mem_put(resolver->mctx, algorithms,
8131 *algorithms);
8132 } else
8133 algorithms[len-1] |= mask;
8135 result = ISC_R_SUCCESS;
8136 cleanup:
8137 #if USE_ALGLOCK
8138 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8139 #endif
8140 return (result);
8143 isc_boolean_t
8144 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
8145 unsigned int alg)
8147 unsigned int len, mask;
8148 unsigned char *algorithms;
8149 void *data = NULL;
8150 isc_result_t result;
8151 isc_boolean_t found = ISC_FALSE;
8153 REQUIRE(VALID_RESOLVER(resolver));
8155 #if USE_ALGLOCK
8156 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
8157 #endif
8158 if (resolver->algorithms == NULL)
8159 goto unlock;
8160 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
8161 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
8162 len = alg/8 + 2;
8163 mask = 1 << (alg%8);
8164 algorithms = data;
8165 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
8166 found = ISC_TRUE;
8168 unlock:
8169 #if USE_ALGLOCK
8170 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
8171 #endif
8172 if (found)
8173 return (ISC_FALSE);
8174 return (dst_algorithm_supported(alg));
8177 isc_boolean_t
8178 dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
8180 UNUSED(resolver);
8181 return (dns_ds_digest_supported(digest));
8184 void
8185 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
8187 REQUIRE(VALID_RESOLVER(resolver));
8189 #if USE_MBSLOCK
8190 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8191 #endif
8192 if (resolver->mustbesecure != NULL)
8193 dns_rbt_destroy(&resolver->mustbesecure);
8194 #if USE_MBSLOCK
8195 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8196 #endif
8199 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
8201 isc_result_t
8202 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
8203 isc_boolean_t value)
8205 isc_result_t result;
8207 REQUIRE(VALID_RESOLVER(resolver));
8209 #if USE_MBSLOCK
8210 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8211 #endif
8212 if (resolver->mustbesecure == NULL) {
8213 result = dns_rbt_create(resolver->mctx, NULL, NULL,
8214 &resolver->mustbesecure);
8215 if (result != ISC_R_SUCCESS)
8216 goto cleanup;
8218 result = dns_rbt_addname(resolver->mustbesecure, name,
8219 value ? &yes : &no);
8220 cleanup:
8221 #if USE_MBSLOCK
8222 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8223 #endif
8224 return (result);
8227 isc_boolean_t
8228 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
8229 void *data = NULL;
8230 isc_boolean_t value = ISC_FALSE;
8231 isc_result_t result;
8233 REQUIRE(VALID_RESOLVER(resolver));
8235 #if USE_MBSLOCK
8236 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
8237 #endif
8238 if (resolver->mustbesecure == NULL)
8239 goto unlock;
8240 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
8241 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
8242 value = *(isc_boolean_t*)data;
8243 unlock:
8244 #if USE_MBSLOCK
8245 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
8246 #endif
8247 return (value);
8250 void
8251 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
8252 isc_uint32_t *min, isc_uint32_t *max)
8254 REQUIRE(VALID_RESOLVER(resolver));
8256 LOCK(&resolver->lock);
8257 if (cur != NULL)
8258 *cur = resolver->spillat;
8259 if (min != NULL)
8260 *min = resolver->spillatmin;
8261 if (max != NULL)
8262 *max = resolver->spillatmax;
8263 UNLOCK(&resolver->lock);
8266 void
8267 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
8268 isc_uint32_t max)
8270 REQUIRE(VALID_RESOLVER(resolver));
8272 LOCK(&resolver->lock);
8273 resolver->spillatmin = resolver->spillat = min;
8274 resolver->spillatmax = max;
8275 UNLOCK(&resolver->lock);
8278 isc_boolean_t
8279 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
8280 REQUIRE(VALID_RESOLVER(resolver));
8282 return (resolver->zero_no_soa_ttl);
8285 void
8286 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
8287 REQUIRE(VALID_RESOLVER(resolver));
8289 resolver->zero_no_soa_ttl = state;
8292 unsigned int
8293 dns_resolver_getoptions(dns_resolver_t *resolver) {
8294 REQUIRE(VALID_RESOLVER(resolver));
8296 return (resolver->options);