2 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
24 #include <isc/platform.h>
25 #include <isc/print.h>
26 #include <isc/string.h>
27 #include <isc/random.h>
29 #include <isc/stats.h>
30 #include <isc/timer.h>
35 #include <dns/cache.h>
37 #include <dns/dispatch.h>
39 #include <dns/events.h>
40 #include <dns/forward.h>
41 #include <dns/keytable.h>
43 #include <dns/message.h>
44 #include <dns/ncache.h>
45 #include <dns/opcode.h>
48 #include <dns/rcode.h>
49 #include <dns/rdata.h>
50 #include <dns/rdataclass.h>
51 #include <dns/rdatalist.h>
52 #include <dns/rdataset.h>
53 #include <dns/rdatastruct.h>
54 #include <dns/rdatatype.h>
55 #include <dns/resolver.h>
56 #include <dns/result.h>
57 #include <dns/rootns.h>
58 #include <dns/stats.h>
60 #include <dns/validator.h>
62 #define DNS_RESOLVER_TRACE
63 #ifdef DNS_RESOLVER_TRACE
64 #define RTRACE(m) isc_log_write(dns_lctx, \
65 DNS_LOGCATEGORY_RESOLVER, \
66 DNS_LOGMODULE_RESOLVER, \
68 "res %p: %s", res, (m))
69 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
70 DNS_LOGCATEGORY_RESOLVER, \
71 DNS_LOGMODULE_RESOLVER, \
73 "res %p: %s", (r), (m))
74 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
75 DNS_LOGCATEGORY_RESOLVER, \
76 DNS_LOGMODULE_RESOLVER, \
78 "fctx %p(%s'): %s", fctx, fctx->info, (m))
79 #define FCTXTRACE2(m1, m2) \
80 isc_log_write(dns_lctx, \
81 DNS_LOGCATEGORY_RESOLVER, \
82 DNS_LOGMODULE_RESOLVER, \
84 "fctx %p(%s): %s %s", \
85 fctx, fctx->info, (m1), (m2))
86 #define FTRACE(m) isc_log_write(dns_lctx, \
87 DNS_LOGCATEGORY_RESOLVER, \
88 DNS_LOGMODULE_RESOLVER, \
90 "fetch %p (fctx %p(%s)): %s", \
91 fetch, fetch->private, \
92 fetch->private->info, (m))
93 #define QTRACE(m) isc_log_write(dns_lctx, \
94 DNS_LOGCATEGORY_RESOLVER, \
95 DNS_LOGMODULE_RESOLVER, \
97 "resquery %p (fctx %p(%s)): %s", \
99 query->fctx->info, (m))
102 #define RRTRACE(r, m)
108 #define US_PER_SEC 1000000U
110 * The maximum time we will wait for a single query.
112 #define MAX_SINGLE_QUERY_TIMEOUT 9U
113 #define MAX_SINGLE_QUERY_TIMEOUT_US (MAX_SINGLE_QUERY_TIMEOUT*US_PER_SEC)
116 * We need to allow a individual query time to complete / timeout.
118 #define MINIMUM_QUERY_TIMEOUT (MAX_SINGLE_QUERY_TIMEOUT + 1U)
120 /* The default time in seconds for the whole query to live. */
121 #ifndef DEFAULT_QUERY_TIMEOUT
122 #define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
125 #ifndef MAXIMUM_QUERY_TIMEOUT
126 #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
130 * Maximum EDNS0 input packet size.
132 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
135 * This defines the maximum number of timeouts we will permit before we
136 * disable EDNS0 on the query.
138 #define MAX_EDNS0_TIMEOUTS 3
140 typedef struct fetchctx fetchctx_t;
142 typedef struct query {
143 /* Locked by task event serialization. */
147 dns_dispatchmgr_t * dispatchmgr;
148 dns_dispatch_t * dispatch;
149 isc_boolean_t exclusivesocket;
150 dns_adbaddrinfo_t * addrinfo;
151 isc_socket_t * tcpsocket;
154 dns_dispentry_t * dispentry;
155 ISC_LINK(struct query) link;
158 dns_tsigkey_t *tsigkey;
159 unsigned int options;
160 unsigned int attributes;
162 unsigned int connects;
163 unsigned char data[512];
166 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
167 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
169 #define RESQUERY_ATTR_CANCELED 0x02
171 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
172 #define RESQUERY_CANCELED(q) (((q)->attributes & \
173 RESQUERY_ATTR_CANCELED) != 0)
174 #define RESQUERY_SENDING(q) ((q)->sends > 0)
177 fetchstate_init = 0, /*%< Start event has not run yet. */
179 fetchstate_done /*%< FETCHDONE events posted. */
183 badns_unreachable = 0,
191 dns_resolver_t * res;
193 dns_rdatatype_t type;
194 unsigned int options;
195 unsigned int bucketnum;
199 /*% Locked by appropriate bucket lock. */
201 isc_boolean_t want_shutdown;
202 isc_boolean_t cloned;
203 isc_boolean_t spilled;
204 unsigned int references;
205 isc_event_t control_event;
206 ISC_LINK(struct fetchctx) link;
207 ISC_LIST(dns_fetchevent_t) events;
208 /*% Locked by task event serialization. */
210 dns_rdataset_t nameservers;
211 unsigned int attributes;
214 isc_interval_t interval;
215 dns_message_t * qmessage;
216 dns_message_t * rmessage;
217 ISC_LIST(resquery_t) queries;
218 dns_adbfindlist_t finds;
219 dns_adbfind_t * find;
220 dns_adbfindlist_t altfinds;
221 dns_adbfind_t * altfind;
222 dns_adbaddrinfolist_t forwaddrs;
223 dns_adbaddrinfolist_t altaddrs;
224 isc_sockaddrlist_t forwarders;
225 dns_fwdpolicy_t fwdpolicy;
226 isc_sockaddrlist_t bad;
227 isc_sockaddrlist_t edns;
228 isc_sockaddrlist_t edns512;
229 isc_sockaddrlist_t bad_edns;
230 dns_validator_t *validator;
231 ISC_LIST(dns_validator_t) validators;
234 isc_boolean_t ns_ttl_ok;
238 * The number of events we're waiting for.
240 unsigned int pending;
243 * The number of times we've "restarted" the current
244 * nameserver set. This acts as a failsafe to prevent
245 * us from pounding constantly on a particular set of
246 * servers that, for whatever reason, are not giving
247 * us useful responses, but are responding in such a
248 * way that they are not marked "bad".
250 unsigned int restarts;
253 * The number of timeouts that have occurred since we
254 * last successfully received a response packet. This
255 * is used for EDNS0 black hole detection.
257 unsigned int timeouts;
260 * Look aside state for DS lookups.
263 dns_fetch_t * nsfetch;
264 dns_rdataset_t nsrrset;
267 * Number of queries that reference this context.
269 unsigned int nqueries;
272 * The reason to print when logging a successful
273 * response to a query.
278 * Random numbers to use for mixing up server addresses.
280 isc_uint32_t rand_buf;
281 isc_uint32_t rand_bits;
284 * Fetch-local statistics for detailed logging.
286 isc_result_t result; /*%< fetch result */
287 isc_result_t vresult; /*%< validation result */
290 isc_uint64_t duration;
291 isc_boolean_t logged;
292 unsigned int querysent;
293 unsigned int referrals;
294 unsigned int lamecount;
296 unsigned int badresp;
298 unsigned int findfail;
299 unsigned int valfail;
300 isc_boolean_t timeout;
301 dns_adbaddrinfo_t *addrinfo;
302 isc_sockaddr_t *client;
305 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
306 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
308 #define FCTX_ATTR_HAVEANSWER 0x0001
309 #define FCTX_ATTR_GLUING 0x0002
310 #define FCTX_ATTR_ADDRWAIT 0x0004
311 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
312 #define FCTX_ATTR_WANTCACHE 0x0010
313 #define FCTX_ATTR_WANTNCACHE 0x0020
314 #define FCTX_ATTR_NEEDEDNS0 0x0040
315 #define FCTX_ATTR_TRIEDFIND 0x0080
316 #define FCTX_ATTR_TRIEDALT 0x0100
318 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
320 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
322 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
324 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
326 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
327 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
328 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
329 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
330 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
333 dns_adbaddrinfo_t * addrinfo;
339 fetchctx_t * private;
342 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
343 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
345 typedef struct fctxbucket {
348 ISC_LIST(fetchctx_t) fctxs;
349 isc_boolean_t exiting;
353 typedef struct alternate {
354 isc_boolean_t isaddress;
362 ISC_LINK(struct alternate) link;
365 typedef struct dns_badcache dns_badcache_t;
366 struct dns_badcache {
367 dns_badcache_t * next;
368 dns_rdatatype_t type;
370 unsigned int hashval;
373 #define DNS_BADCACHE_SIZE 1021
374 #define DNS_BADCACHE_TTL(fctx) \
375 (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
377 struct dns_resolver {
383 isc_mutex_t primelock;
384 dns_rdataclass_t rdclass;
385 isc_socketmgr_t * socketmgr;
386 isc_timermgr_t * timermgr;
387 isc_taskmgr_t * taskmgr;
389 isc_boolean_t frozen;
390 unsigned int options;
391 dns_dispatchmgr_t * dispatchmgr;
392 dns_dispatch_t * dispatchv4;
393 isc_boolean_t exclusivev4;
394 dns_dispatch_t * dispatchv6;
395 isc_boolean_t exclusivev6;
397 unsigned int nbuckets;
398 fctxbucket_t * buckets;
399 isc_uint32_t lame_ttl;
400 ISC_LIST(alternate_t) alternates;
401 isc_uint16_t udpsize;
403 isc_rwlock_t alglock;
405 dns_rbt_t * algorithms;
407 isc_rwlock_t mbslock;
409 dns_rbt_t * mustbesecure;
410 unsigned int spillatmax;
411 unsigned int spillatmin;
412 isc_timer_t * spillattimer;
413 isc_boolean_t zero_no_soa_ttl;
414 unsigned int query_timeout;
416 /* Locked by lock. */
417 unsigned int references;
418 isc_boolean_t exiting;
419 isc_eventlist_t whenshutdown;
420 unsigned int activebuckets;
421 isc_boolean_t priming;
422 unsigned int spillat; /* clients-per-query */
423 unsigned int nextdisp;
426 dns_badcache_t ** badcache;
427 unsigned int badcount;
428 unsigned int badhash;
429 unsigned int badsweep;
431 /* Locked by primelock. */
432 dns_fetch_t * primefetch;
433 /* Locked by nlock. */
437 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
438 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
441 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
442 * which we also use as an addrinfo flag.
444 #define FCTX_ADDRINFO_MARK 0x0001
445 #define FCTX_ADDRINFO_FORWARDER 0x1000
446 #define FCTX_ADDRINFO_TRIED 0x2000
447 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
449 #define ISFORWARDER(a) (((a)->flags & \
450 FCTX_ADDRINFO_FORWARDER) != 0)
451 #define TRIED(a) (((a)->flags & \
452 FCTX_ADDRINFO_TRIED) != 0)
454 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
455 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
457 static void destroy(dns_resolver_t *res);
458 static void empty_bucket(dns_resolver_t *res);
459 static isc_result_t resquery_send(resquery_t *query);
460 static void resquery_response(isc_task_t *task, isc_event_t *event);
461 static void resquery_connected(isc_task_t *task, isc_event_t *event);
462 static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
463 isc_boolean_t badcache);
464 static void fctx_destroy(fetchctx_t *fctx);
465 static isc_boolean_t fctx_unlink(fetchctx_t *fctx);
466 static isc_result_t ncache_adderesult(dns_message_t *message,
467 dns_db_t *cache, dns_dbnode_t *node,
468 dns_rdatatype_t covers,
469 isc_stdtime_t now, dns_ttl_t maxttl,
470 isc_boolean_t optout,
471 dns_rdataset_t *ardataset,
472 isc_result_t *eresultp);
473 static void validated(isc_task_t *task, isc_event_t *event);
474 static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
475 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
476 isc_result_t reason, badnstype_t badtype);
479 * Increment resolver-related statistics counters.
482 inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
483 if (res->view->resstats != NULL)
484 isc_stats_increment(res->view->resstats, counter);
488 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
489 dns_rdatatype_t type, dns_rdataset_t *rdataset,
490 dns_rdataset_t *sigrdataset, unsigned int valoptions,
493 dns_validator_t *validator = NULL;
494 dns_valarg_t *valarg;
497 valarg = isc_mem_get(fctx->mctx, sizeof(*valarg));
499 return (ISC_R_NOMEMORY);
502 valarg->addrinfo = addrinfo;
504 if (!ISC_LIST_EMPTY(fctx->validators))
505 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
507 result = dns_validator_create(fctx->res->view, name, type, rdataset,
508 sigrdataset, fctx->rmessage,
509 valoptions, task, validated, valarg,
511 if (result == ISC_R_SUCCESS) {
512 inc_stats(fctx->res, dns_resstatscounter_val);
513 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
514 INSIST(fctx->validator == NULL);
515 fctx->validator = validator;
517 ISC_LIST_APPEND(fctx->validators, validator, link);
519 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
524 rrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
525 dns_namereln_t namereln;
526 dns_rdata_rrsig_t rrsig;
527 dns_rdata_t rdata = DNS_RDATA_INIT;
532 for (result = dns_rdataset_first(rdataset);
533 result == ISC_R_SUCCESS;
534 result = dns_rdataset_next(rdataset)) {
535 dns_rdataset_current(rdataset, &rdata);
536 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
537 RUNTIME_CHECK(result == ISC_R_SUCCESS);
538 namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
540 if (namereln == dns_namereln_subdomain)
542 dns_rdata_reset(&rdata);
548 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
550 dns_name_t *domain = &fctx->domain;
551 dns_rdataset_t *rdataset;
552 dns_rdatatype_t type;
554 isc_boolean_t keep_auth = ISC_FALSE;
556 if (message->rcode == dns_rcode_nxdomain)
560 * A DS RRset can appear anywhere in a zone, even for a delegation-only
561 * zone. So a response to an explicit query for this type should be
562 * excluded from delegation-only fixup.
564 * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
565 * response to a query for these types can never violate the
566 * delegation-only assumption: if the query name is below a
567 * zone cut, the response should normally be a referral, which should
568 * be accepted; if the query name is below a zone cut but the server
569 * happens to have authority for the zone of the query name, the
570 * response is a (non-referral) answer. But this does not violate
571 * delegation-only because the query name must be in a different zone
572 * due to the "apex-only" nature of these types. Note that if the
573 * remote server happens to have authority for a child zone of a
574 * delegation-only zone, we may still incorrectly "fix" the response
575 * with NXDOMAIN for queries for other types. Unfortunately it's
576 * generally impossible to differentiate this case from violation of
577 * the delegation-only assumption. Once the resolver learns the
578 * correct zone cut, possibly via a separate query for an "apex-only"
579 * type, queries for other types will be resolved correctly.
581 * A query for type ANY will be accepted if it hits an exceptional
582 * type above in the answer section as it should be from a child
585 * Also accept answers with RRSIG records from the child zone.
586 * Direct queries for RRSIG records should not be answered from
590 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
591 (fctx->type == dns_rdatatype_ns ||
592 fctx->type == dns_rdatatype_ds ||
593 fctx->type == dns_rdatatype_soa ||
594 fctx->type == dns_rdatatype_any ||
595 fctx->type == dns_rdatatype_rrsig ||
596 fctx->type == dns_rdatatype_dnskey)) {
597 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
598 while (result == ISC_R_SUCCESS) {
600 dns_message_currentname(message, DNS_SECTION_ANSWER,
602 for (rdataset = ISC_LIST_HEAD(name->list);
604 rdataset = ISC_LIST_NEXT(rdataset, link)) {
605 if (!dns_name_equal(name, &fctx->name))
607 type = rdataset->type;
611 if (type == dns_rdatatype_rrsig &&
612 rrsig_fromchildzone(fctx, rdataset))
615 * Direct query for apex records or DS.
617 if (fctx->type == type &&
618 (type == dns_rdatatype_ds ||
619 type == dns_rdatatype_ns ||
620 type == dns_rdatatype_soa ||
621 type == dns_rdatatype_dnskey))
624 * Indirect query for apex records or DS.
626 if (fctx->type == dns_rdatatype_any &&
627 (type == dns_rdatatype_ns ||
628 type == dns_rdatatype_ds ||
629 type == dns_rdatatype_soa ||
630 type == dns_rdatatype_dnskey))
633 result = dns_message_nextname(message,
639 * A NODATA response to a DS query?
641 if (fctx->type == dns_rdatatype_ds &&
642 message->counts[DNS_SECTION_ANSWER] == 0)
645 /* Look for referral or indication of answer from child zone? */
646 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
649 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
650 while (result == ISC_R_SUCCESS) {
652 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
653 for (rdataset = ISC_LIST_HEAD(name->list);
655 rdataset = ISC_LIST_NEXT(rdataset, link)) {
656 type = rdataset->type;
657 if (type == dns_rdatatype_soa &&
658 dns_name_equal(name, domain))
659 keep_auth = ISC_TRUE;
661 if (type != dns_rdatatype_ns &&
662 type != dns_rdatatype_soa &&
663 type != dns_rdatatype_rrsig)
666 if (type == dns_rdatatype_rrsig) {
667 if (rrsig_fromchildzone(fctx, rdataset))
673 /* NS or SOA records. */
674 if (dns_name_equal(name, domain)) {
676 * If a query for ANY causes a negative
677 * response, we can be sure that this is
678 * an empty node. For other type of queries
679 * we cannot differentiate an empty node
680 * from a node that just doesn't have that
681 * type of record. We only accept the former
684 if (message->counts[DNS_SECTION_ANSWER] == 0 &&
685 fctx->type == dns_rdatatype_any)
687 } else if (dns_name_issubdomain(name, domain)) {
688 /* Referral or answer from child zone. */
692 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
696 message->rcode = dns_rcode_nxdomain;
697 message->counts[DNS_SECTION_ANSWER] = 0;
699 message->counts[DNS_SECTION_AUTHORITY] = 0;
700 message->counts[DNS_SECTION_ADDITIONAL] = 0;
704 static inline isc_result_t
705 fctx_starttimer(fetchctx_t *fctx) {
707 * Start the lifetime timer for fctx.
709 * This is also used for stopping the idle timer; in that
710 * case we must purge events already posted to ensure that
711 * no further idle events are delivered.
713 return (isc_timer_reset(fctx->timer, isc_timertype_once,
714 &fctx->expires, NULL, ISC_TRUE));
718 fctx_stoptimer(fetchctx_t *fctx) {
722 * We don't return a result if resetting the timer to inactive fails
723 * since there's nothing to be done about it. Resetting to inactive
724 * should never fail anyway, since the code as currently written
725 * cannot fail in that case.
727 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
728 NULL, NULL, ISC_TRUE);
729 if (result != ISC_R_SUCCESS) {
730 UNEXPECTED_ERROR(__FILE__, __LINE__,
731 "isc_timer_reset(): %s",
732 isc_result_totext(result));
737 static inline isc_result_t
738 fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
740 * Start the idle timer for fctx. The lifetime timer continues
743 return (isc_timer_reset(fctx->timer, isc_timertype_once,
744 &fctx->expires, interval, ISC_FALSE));
748 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
749 * we use fctx_stopidletimer for readability in the code below.
751 #define fctx_stopidletimer fctx_starttimer
755 resquery_destroy(resquery_t **queryp) {
758 REQUIRE(queryp != NULL);
760 REQUIRE(!ISC_LINK_LINKED(query, link));
762 INSIST(query->tcpsocket == NULL);
764 query->fctx->nqueries--;
765 if (SHUTTINGDOWN(query->fctx)) {
766 dns_resolver_t *res = query->fctx->res;
767 if (maybe_destroy(query->fctx, ISC_FALSE))
771 isc_mem_put(query->mctx, query, sizeof(*query));
776 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
777 isc_time_t *finish, isc_boolean_t no_response)
781 unsigned int rtt, rttms;
784 dns_adbaddrinfo_t *addrinfo;
785 isc_socket_t *socket;
790 FCTXTRACE("cancelquery");
792 REQUIRE(!RESQUERY_CANCELED(query));
794 query->attributes |= RESQUERY_ATTR_CANCELED;
797 * Should we update the RTT?
799 if (finish != NULL || no_response) {
800 if (finish != NULL) {
802 * We have both the start and finish times for this
803 * packet, so we can compute a real RTT.
805 rtt = (unsigned int)isc_time_microdiff(finish,
807 factor = DNS_ADB_RTTADJDEFAULT;
810 if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
812 dns_resstatscounter_queryrtt0);
813 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
815 dns_resstatscounter_queryrtt1);
816 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
818 dns_resstatscounter_queryrtt2);
819 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
821 dns_resstatscounter_queryrtt3);
822 } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
824 dns_resstatscounter_queryrtt4);
827 dns_resstatscounter_queryrtt5);
831 * We don't have an RTT for this query. Maybe the
832 * packet was lost, or maybe this server is very
833 * slow. We don't know. Increase the RTT.
836 rtt = query->addrinfo->srtt + 200000;
837 if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
838 rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
840 * Replace the current RTT with our value.
842 factor = DNS_ADB_RTTADJREPLACE;
844 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
847 /* Remember that the server has been tried. */
848 if (!TRIED(query->addrinfo)) {
849 dns_adb_changeflags(fctx->adb, query->addrinfo,
850 FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
854 * Age RTTs of servers not tried.
856 factor = DNS_ADB_RTTADJAGE;
858 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
860 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
861 if (UNMARKED(addrinfo))
862 dns_adb_adjustsrtt(fctx->adb, addrinfo,
865 if (finish != NULL && TRIEDFIND(fctx))
866 for (find = ISC_LIST_HEAD(fctx->finds);
868 find = ISC_LIST_NEXT(find, publink))
869 for (addrinfo = ISC_LIST_HEAD(find->list);
871 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
872 if (UNMARKED(addrinfo))
873 dns_adb_adjustsrtt(fctx->adb, addrinfo,
876 if (finish != NULL && TRIEDALT(fctx)) {
877 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
879 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
880 if (UNMARKED(addrinfo))
881 dns_adb_adjustsrtt(fctx->adb, addrinfo,
883 for (find = ISC_LIST_HEAD(fctx->altfinds);
885 find = ISC_LIST_NEXT(find, publink))
886 for (addrinfo = ISC_LIST_HEAD(find->list);
888 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
889 if (UNMARKED(addrinfo))
890 dns_adb_adjustsrtt(fctx->adb, addrinfo,
895 * Check for any outstanding socket events. If they exist, cancel
896 * them and let the event handlers finish the cleanup. The resolver
897 * only needs to worry about managing the connect and send events;
898 * the dispatcher manages the recv events.
900 if (RESQUERY_CONNECTING(query)) {
902 * Cancel the connect.
904 if (query->tcpsocket != NULL) {
905 isc_socket_cancel(query->tcpsocket, NULL,
906 ISC_SOCKCANCEL_CONNECT);
907 } else if (query->dispentry != NULL) {
908 INSIST(query->exclusivesocket);
909 socket = dns_dispatch_getentrysocket(query->dispentry);
911 isc_socket_cancel(socket, NULL,
912 ISC_SOCKCANCEL_CONNECT);
914 } else if (RESQUERY_SENDING(query)) {
916 * Cancel the pending send.
918 if (query->exclusivesocket && query->dispentry != NULL)
919 socket = dns_dispatch_getentrysocket(query->dispentry);
921 socket = dns_dispatch_getsocket(query->dispatch);
923 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
926 if (query->dispentry != NULL)
927 dns_dispatch_removeresponse(&query->dispentry, deventp);
929 ISC_LIST_UNLINK(fctx->queries, query, link);
931 if (query->tsig != NULL)
932 isc_buffer_free(&query->tsig);
934 if (query->tsigkey != NULL)
935 dns_tsigkey_detach(&query->tsigkey);
937 if (query->dispatch != NULL)
938 dns_dispatch_detach(&query->dispatch);
940 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
942 * It's safe to destroy the query now.
944 resquery_destroy(&query);
948 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
949 resquery_t *query, *next_query;
951 FCTXTRACE("cancelqueries");
953 for (query = ISC_LIST_HEAD(fctx->queries);
955 query = next_query) {
956 next_query = ISC_LIST_NEXT(query, link);
957 fctx_cancelquery(&query, NULL, NULL, no_response);
962 fctx_cleanupfinds(fetchctx_t *fctx) {
963 dns_adbfind_t *find, *next_find;
965 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
967 for (find = ISC_LIST_HEAD(fctx->finds);
970 next_find = ISC_LIST_NEXT(find, publink);
971 ISC_LIST_UNLINK(fctx->finds, find, publink);
972 dns_adb_destroyfind(&find);
978 fctx_cleanupaltfinds(fetchctx_t *fctx) {
979 dns_adbfind_t *find, *next_find;
981 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
983 for (find = ISC_LIST_HEAD(fctx->altfinds);
986 next_find = ISC_LIST_NEXT(find, publink);
987 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
988 dns_adb_destroyfind(&find);
990 fctx->altfind = NULL;
994 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
995 dns_adbaddrinfo_t *addr, *next_addr;
997 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
999 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
1002 next_addr = ISC_LIST_NEXT(addr, publink);
1003 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
1004 dns_adb_freeaddrinfo(fctx->adb, &addr);
1009 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
1010 dns_adbaddrinfo_t *addr, *next_addr;
1012 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1014 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
1017 next_addr = ISC_LIST_NEXT(addr, publink);
1018 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
1019 dns_adb_freeaddrinfo(fctx->adb, &addr);
1024 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
1025 FCTXTRACE("stopeverything");
1026 fctx_cancelqueries(fctx, no_response);
1027 fctx_cleanupfinds(fctx);
1028 fctx_cleanupaltfinds(fctx);
1029 fctx_cleanupforwaddrs(fctx);
1030 fctx_cleanupaltaddrs(fctx);
1031 fctx_stoptimer(fctx);
1035 fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
1036 dns_fetchevent_t *event, *next_event;
1038 unsigned int count = 0;
1040 isc_boolean_t logit = ISC_FALSE;
1042 unsigned int old_spillat;
1043 unsigned int new_spillat = 0; /* initialized to silence
1044 compiler warnings */
1047 * Caller must be holding the appropriate bucket lock.
1049 REQUIRE(fctx->state == fetchstate_done);
1051 FCTXTRACE("sendevents");
1054 * Keep some record of fetch result for logging later (if required).
1056 fctx->result = result;
1057 fctx->exitline = line;
1059 fctx->duration = isc_time_microdiff(&now, &fctx->start);
1061 for (event = ISC_LIST_HEAD(fctx->events);
1063 event = next_event) {
1064 next_event = ISC_LIST_NEXT(event, ev_link);
1065 ISC_LIST_UNLINK(fctx->events, event, ev_link);
1066 task = event->ev_sender;
1067 event->ev_sender = fctx;
1068 event->vresult = fctx->vresult;
1069 if (!HAVE_ANSWER(fctx))
1070 event->result = result;
1072 INSIST(result != ISC_R_SUCCESS ||
1073 dns_rdataset_isassociated(event->rdataset) ||
1074 fctx->type == dns_rdatatype_any ||
1075 fctx->type == dns_rdatatype_rrsig ||
1076 fctx->type == dns_rdatatype_sig);
1079 * Negative results must be indicated in event->result.
1081 if (dns_rdataset_isassociated(event->rdataset) &&
1082 NEGATIVE(event->rdataset)) {
1083 INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
1084 event->result == DNS_R_NCACHENXRRSET);
1087 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
1091 if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
1093 (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
1094 LOCK(&fctx->res->lock);
1095 if (count == fctx->res->spillat && !fctx->res->exiting) {
1096 old_spillat = fctx->res->spillat;
1097 fctx->res->spillat += 5;
1098 if (fctx->res->spillat > fctx->res->spillatmax &&
1099 fctx->res->spillatmax != 0)
1100 fctx->res->spillat = fctx->res->spillatmax;
1101 new_spillat = fctx->res->spillat;
1102 if (new_spillat != old_spillat) {
1105 isc_interval_set(&i, 20 * 60, 0);
1106 result = isc_timer_reset(fctx->res->spillattimer,
1107 isc_timertype_ticker, NULL,
1109 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1111 UNLOCK(&fctx->res->lock);
1113 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
1114 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
1115 "clients-per-query increased to %u",
1121 log_edns(fetchctx_t *fctx) {
1122 char domainbuf[DNS_NAME_FORMATSIZE];
1124 if (fctx->reason == NULL)
1127 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
1128 isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
1129 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1130 "success resolving '%s' (in '%s'?) after %s",
1131 fctx->info, domainbuf, fctx->reason);
1133 fctx->reason = NULL;
1137 fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
1138 dns_resolver_t *res;
1139 isc_boolean_t no_response;
1147 if (result == ISC_R_SUCCESS) {
1149 * Log any deferred EDNS timeout messages.
1152 no_response = ISC_TRUE;
1154 no_response = ISC_FALSE;
1156 fctx->reason = NULL;
1157 fctx_stopeverything(fctx, no_response);
1159 LOCK(&res->buckets[fctx->bucketnum].lock);
1161 fctx->state = fetchstate_done;
1162 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1163 fctx_sendevents(fctx, result, line);
1165 UNLOCK(&res->buckets[fctx->bucketnum].lock);
1169 process_sendevent(resquery_t *query, isc_event_t *event) {
1170 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1171 isc_boolean_t retry = ISC_FALSE;
1172 isc_result_t result;
1177 if (RESQUERY_CANCELED(query)) {
1178 if (query->sends == 0 && query->connects == 0) {
1180 * This query was canceled while the
1181 * isc_socket_sendto/connect() was in progress.
1183 if (query->tcpsocket != NULL)
1184 isc_socket_detach(&query->tcpsocket);
1185 resquery_destroy(&query);
1188 switch (sevent->result) {
1192 case ISC_R_HOSTUNREACH:
1193 case ISC_R_NETUNREACH:
1195 case ISC_R_ADDRNOTAVAIL:
1196 case ISC_R_CONNREFUSED:
1199 * No route to remote.
1201 add_bad(fctx, query->addrinfo, sevent->result,
1203 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
1208 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1213 isc_event_free(&event);
1217 * Behave as if the idle timer has expired. For TCP
1218 * this may not actually reflect the latest timer.
1220 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1221 result = fctx_stopidletimer(fctx);
1222 if (result != ISC_R_SUCCESS)
1223 fctx_done(fctx, result, __LINE__);
1225 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
1230 resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
1231 resquery_t *query = event->ev_arg;
1233 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1235 QTRACE("udpconnected");
1239 INSIST(RESQUERY_CONNECTING(query));
1243 process_sendevent(query, event);
1247 resquery_senddone(isc_task_t *task, isc_event_t *event) {
1248 resquery_t *query = event->ev_arg;
1250 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1257 * Currently we don't wait for the senddone event before retrying
1258 * a query. This means that if we get really behind, we may end
1259 * up doing extra work!
1264 INSIST(RESQUERY_SENDING(query));
1268 process_sendevent(query, event);
1271 static inline isc_result_t
1272 fctx_addopt(dns_message_t *message, unsigned int version,
1273 isc_uint16_t udpsize, isc_boolean_t request_nsid)
1275 dns_rdataset_t *rdataset;
1276 dns_rdatalist_t *rdatalist;
1278 isc_result_t result;
1281 result = dns_message_gettemprdatalist(message, &rdatalist);
1282 if (result != ISC_R_SUCCESS)
1285 result = dns_message_gettemprdata(message, &rdata);
1286 if (result != ISC_R_SUCCESS)
1289 result = dns_message_gettemprdataset(message, &rdataset);
1290 if (result != ISC_R_SUCCESS)
1292 dns_rdataset_init(rdataset);
1294 rdatalist->type = dns_rdatatype_opt;
1295 rdatalist->covers = 0;
1298 * Set Maximum UDP buffer size.
1300 rdatalist->rdclass = udpsize;
1303 * Set EXTENDED-RCODE and Z to 0, DO to 1.
1305 rdatalist->ttl = (version << 16);
1306 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1309 * Set EDNS options if applicable
1312 /* Send empty NSID option (RFC5001) */
1313 unsigned char data[4];
1316 isc_buffer_init(&buf, data, sizeof(data));
1317 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
1318 isc_buffer_putuint16(&buf, 0);
1320 rdata->length = sizeof(data);
1326 rdata->rdclass = rdatalist->rdclass;
1327 rdata->type = rdatalist->type;
1330 ISC_LIST_INIT(rdatalist->rdata);
1331 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1332 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
1334 return (dns_message_setopt(message, rdataset));
1338 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
1339 unsigned int seconds;
1343 * We retry every .8 seconds the first two times through the address
1344 * list, and then we do exponential back-off.
1346 if (fctx->restarts < 3)
1349 us = (800000 << (fctx->restarts - 2));
1352 * Add a fudge factor to the expected rtt based on the current
1357 else if (rtt < 100000)
1363 * Always wait for at least the expected rtt.
1369 * But don't ever wait for more than 10 seconds.
1371 if (us > MAX_SINGLE_QUERY_TIMEOUT_US)
1372 us = MAX_SINGLE_QUERY_TIMEOUT_US;
1374 seconds = us / US_PER_SEC;
1375 us -= seconds * US_PER_SEC;
1376 isc_interval_set(&fctx->interval, seconds, us * 1000);
1380 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
1381 unsigned int options)
1383 dns_resolver_t *res;
1385 isc_result_t result;
1387 isc_sockaddr_t addr;
1388 isc_boolean_t have_addr = ISC_FALSE;
1394 task = res->buckets[fctx->bucketnum].task;
1396 srtt = addrinfo->srtt;
1399 * A forwarder needs to make multiple queries. Give it at least
1400 * a second to do these in.
1402 if (ISFORWARDER(addrinfo) && srtt < 1000000)
1405 fctx_setretryinterval(fctx, srtt);
1406 result = fctx_startidletimer(fctx, &fctx->interval);
1407 if (result != ISC_R_SUCCESS)
1410 INSIST(ISC_LIST_EMPTY(fctx->validators));
1412 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
1414 query = isc_mem_get(fctx->mctx, sizeof(*query));
1415 if (query == NULL) {
1416 result = ISC_R_NOMEMORY;
1417 goto stop_idle_timer;
1419 query->mctx = fctx->mctx;
1420 query->options = options;
1421 query->attributes = 0;
1423 query->connects = 0;
1425 * Note that the caller MUST guarantee that 'addrinfo' will remain
1426 * valid until this query is canceled.
1428 query->addrinfo = addrinfo;
1429 TIME_NOW(&query->start);
1432 * If this is a TCP query, then we need to make a socket and
1433 * a dispatch for it here. Otherwise we use the resolver's
1436 query->dispatchmgr = res->dispatchmgr;
1437 query->dispatch = NULL;
1438 query->exclusivesocket = ISC_FALSE;
1439 query->tcpsocket = NULL;
1440 if (res->view->peers != NULL) {
1441 dns_peer_t *peer = NULL;
1442 isc_netaddr_t dstip;
1443 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
1444 result = dns_peerlist_peerbyaddr(res->view->peers,
1446 if (result == ISC_R_SUCCESS) {
1447 result = dns_peer_getquerysource(peer, &addr);
1448 if (result == ISC_R_SUCCESS)
1449 have_addr = ISC_TRUE;
1453 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1456 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1461 dns_dispatch_getlocaladdress(res->dispatchv4,
1466 dns_dispatch_getlocaladdress(res->dispatchv6,
1470 result = ISC_R_NOTIMPLEMENTED;
1473 if (result != ISC_R_SUCCESS)
1476 isc_sockaddr_setport(&addr, 0);
1478 result = isc_socket_create(res->socketmgr, pf,
1481 if (result != ISC_R_SUCCESS)
1484 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1485 result = isc_socket_bind(query->tcpsocket, &addr, 0);
1486 if (result != ISC_R_SUCCESS)
1487 goto cleanup_socket;
1491 * A dispatch will be created once the connect succeeds.
1495 unsigned int attrs, attrmask;
1496 attrs = DNS_DISPATCHATTR_UDP;
1497 switch (isc_sockaddr_pf(&addr)) {
1499 attrs |= DNS_DISPATCHATTR_IPV4;
1502 attrs |= DNS_DISPATCHATTR_IPV6;
1505 result = ISC_R_NOTIMPLEMENTED;
1508 attrmask = DNS_DISPATCHATTR_UDP;
1509 attrmask |= DNS_DISPATCHATTR_TCP;
1510 attrmask |= DNS_DISPATCHATTR_IPV4;
1511 attrmask |= DNS_DISPATCHATTR_IPV6;
1512 result = dns_dispatch_getudp(res->dispatchmgr,
1514 res->taskmgr, &addr,
1515 4096, 1000, 32768, 16411,
1516 16433, attrs, attrmask,
1518 if (result != ISC_R_SUCCESS)
1521 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1523 dns_dispatch_attach(res->dispatchv4,
1525 query->exclusivesocket = res->exclusivev4;
1528 dns_dispatch_attach(res->dispatchv6,
1530 query->exclusivesocket = res->exclusivev6;
1533 result = ISC_R_NOTIMPLEMENTED;
1538 * We should always have a valid dispatcher here. If we
1539 * don't support a protocol family, then its dispatcher
1540 * will be NULL, but we shouldn't be finding addresses for
1541 * protocol types we don't support, so the dispatcher
1542 * we found should never be NULL.
1544 INSIST(query->dispatch != NULL);
1547 query->dispentry = NULL;
1550 query->tsigkey = NULL;
1551 ISC_LINK_INIT(query, link);
1552 query->magic = QUERY_MAGIC;
1554 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1556 * Connect to the remote server.
1558 * XXXRTH Should we attach to the socket?
1560 result = isc_socket_connect(query->tcpsocket,
1561 &addrinfo->sockaddr, task,
1562 resquery_connected, query);
1563 if (result != ISC_R_SUCCESS)
1564 goto cleanup_socket;
1566 QTRACE("connecting via TCP");
1568 result = resquery_send(query);
1569 if (result != ISC_R_SUCCESS)
1570 goto cleanup_dispatch;
1574 ISC_LIST_APPEND(fctx->queries, query, link);
1575 query->fctx->nqueries++;
1576 if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
1577 inc_stats(res, dns_resstatscounter_queryv4);
1579 inc_stats(res, dns_resstatscounter_queryv6);
1580 if (res->view->resquerystats != NULL)
1581 dns_rdatatypestats_increment(res->view->resquerystats,
1584 return (ISC_R_SUCCESS);
1587 isc_socket_detach(&query->tcpsocket);
1590 if (query->dispatch != NULL)
1591 dns_dispatch_detach(&query->dispatch);
1594 if (query->connects == 0) {
1596 isc_mem_put(fctx->mctx, query, sizeof(*query));
1600 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1605 static isc_boolean_t
1606 bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1609 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
1611 sa = ISC_LIST_NEXT(sa, link)) {
1612 if (isc_sockaddr_equal(sa, address))
1620 add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1623 if (bad_edns(fctx, address))
1626 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1631 ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
1634 static isc_boolean_t
1635 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1638 for (sa = ISC_LIST_HEAD(fctx->edns);
1640 sa = ISC_LIST_NEXT(sa, link)) {
1641 if (isc_sockaddr_equal(sa, address))
1649 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1652 if (triededns(fctx, address))
1655 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1660 ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
1663 static isc_boolean_t
1664 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1667 for (sa = ISC_LIST_HEAD(fctx->edns512);
1669 sa = ISC_LIST_NEXT(sa, link)) {
1670 if (isc_sockaddr_equal(sa, address))
1678 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1681 if (triededns512(fctx, address))
1684 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
1689 ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
1693 resquery_send(resquery_t *query) {
1695 isc_result_t result;
1696 dns_name_t *qname = NULL;
1697 dns_rdataset_t *qrdataset = NULL;
1699 dns_resolver_t *res;
1701 isc_socket_t *socket;
1702 isc_buffer_t tcpbuffer;
1703 isc_sockaddr_t *address;
1704 isc_buffer_t *buffer;
1705 isc_netaddr_t ipaddr;
1706 dns_tsigkey_t *tsigkey = NULL;
1707 dns_peer_t *peer = NULL;
1708 isc_boolean_t useedns;
1709 dns_compress_t cctx;
1710 isc_boolean_t cleanup_cctx = ISC_FALSE;
1711 isc_boolean_t secure_domain;
1712 isc_boolean_t connecting = ISC_FALSE;
1718 task = res->buckets[fctx->bucketnum].task;
1721 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1723 * Reserve space for the TCP message length.
1725 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1726 isc_buffer_init(&query->buffer, query->data + 2,
1727 sizeof(query->data) - 2);
1728 buffer = &tcpbuffer;
1730 isc_buffer_init(&query->buffer, query->data,
1731 sizeof(query->data));
1732 buffer = &query->buffer;
1735 result = dns_message_gettempname(fctx->qmessage, &qname);
1736 if (result != ISC_R_SUCCESS)
1738 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1739 if (result != ISC_R_SUCCESS)
1743 * Get a query id from the dispatch.
1745 result = dns_dispatch_addresponse2(query->dispatch,
1746 &query->addrinfo->sockaddr,
1753 if (result != ISC_R_SUCCESS)
1756 fctx->qmessage->opcode = dns_opcode_query;
1761 dns_name_init(qname, NULL);
1762 dns_name_clone(&fctx->name, qname);
1763 dns_rdataset_init(qrdataset);
1764 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1765 ISC_LIST_APPEND(qname->list, qrdataset, link);
1766 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1771 * Set RD if the client has requested that we do a recursive query,
1772 * or if we're sending to a forwarder.
1774 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1775 ISFORWARDER(query->addrinfo))
1776 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1779 * Set CD if the client says don't validate or the question is
1780 * under a secure entry point.
1782 if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
1783 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1784 } else if (res->view->enablevalidation) {
1785 result = dns_view_issecuredomain(res->view, &fctx->name,
1787 if (result != ISC_R_SUCCESS)
1788 secure_domain = ISC_FALSE;
1789 if (res->view->dlv != NULL)
1790 secure_domain = ISC_TRUE;
1792 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1796 * We don't have to set opcode because it defaults to query.
1798 fctx->qmessage->id = query->id;
1801 * Convert the question to wire format.
1803 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1804 if (result != ISC_R_SUCCESS)
1805 goto cleanup_message;
1806 cleanup_cctx = ISC_TRUE;
1808 result = dns_message_renderbegin(fctx->qmessage, &cctx,
1810 if (result != ISC_R_SUCCESS)
1811 goto cleanup_message;
1813 result = dns_message_rendersection(fctx->qmessage,
1814 DNS_SECTION_QUESTION, 0);
1815 if (result != ISC_R_SUCCESS)
1816 goto cleanup_message;
1819 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1820 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1823 * The ADB does not know about servers with "edns no". Check this,
1824 * and then inform the ADB for future use.
1826 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1828 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1831 query->options |= DNS_FETCHOPT_NOEDNS0;
1832 dns_adb_changeflags(fctx->adb, query->addrinfo,
1833 DNS_FETCHOPT_NOEDNS0,
1834 DNS_FETCHOPT_NOEDNS0);
1837 /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
1838 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
1839 query->options |= DNS_FETCHOPT_NOEDNS0;
1842 * Handle timeouts by reducing the UDP response size to 512 bytes
1843 * then if that doesn't work disabling EDNS (includes DO) and CD.
1845 * These timeout can be due to:
1846 * * broken nameservers that don't respond to EDNS queries.
1847 * * broken/misconfigured firewalls and NAT implementations
1848 * that don't handle IP fragmentation.
1849 * * broken/misconfigured firewalls that don't handle responses
1850 * greater than 512 bytes.
1851 * * broken/misconfigured firewalls that don't handle EDNS, DO
1853 * * packet loss / link outage.
1855 if (fctx->timeout) {
1856 if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
1857 fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
1858 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1859 query->options |= DNS_FETCHOPT_NOEDNS0;
1860 fctx->reason = "disabling EDNS";
1861 } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
1862 fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
1863 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1864 query->options |= DNS_FETCHOPT_EDNS512;
1865 fctx->reason = "reducing the advertised EDNS UDP "
1866 "packet size to 512 octets";
1868 fctx->timeout = ISC_FALSE;
1872 * Use EDNS0, unless the caller doesn't want it, or we know that
1873 * the remote server doesn't like it.
1875 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1876 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1877 unsigned int version = 0; /* Default version. */
1879 isc_uint16_t udpsize = res->udpsize;
1880 isc_boolean_t reqnsid = res->view->requestnsid;
1882 flags = query->addrinfo->flags;
1883 if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
1884 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
1885 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
1887 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1889 else if (peer != NULL)
1890 (void)dns_peer_getudpsize(peer, &udpsize);
1892 /* request NSID for current view or peer? */
1894 (void) dns_peer_getrequestnsid(peer, &reqnsid);
1895 result = fctx_addopt(fctx->qmessage, version,
1897 if (reqnsid && result == ISC_R_SUCCESS) {
1898 query->options |= DNS_FETCHOPT_WANTNSID;
1899 } else if (result != ISC_R_SUCCESS) {
1901 * We couldn't add the OPT, but we'll press on.
1902 * We're not using EDNS0, so set the NOEDNS0
1905 query->options |= DNS_FETCHOPT_NOEDNS0;
1909 * We know this server doesn't like EDNS0, so we
1910 * won't use it. Set the NOEDNS0 bit since we're
1913 query->options |= DNS_FETCHOPT_NOEDNS0;
1918 * If we need EDNS0 to do this query and aren't using it, we lose.
1920 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1921 result = DNS_R_SERVFAIL;
1922 goto cleanup_message;
1925 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
1926 add_triededns(fctx, &query->addrinfo->sockaddr);
1928 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1929 add_triededns512(fctx, &query->addrinfo->sockaddr);
1932 * Clear CD if EDNS is not in use.
1934 if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
1935 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
1938 * Add TSIG record tailored to the current recipient.
1940 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1941 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1942 goto cleanup_message;
1944 if (tsigkey != NULL) {
1945 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
1946 dns_tsigkey_detach(&tsigkey);
1947 if (result != ISC_R_SUCCESS)
1948 goto cleanup_message;
1951 result = dns_message_rendersection(fctx->qmessage,
1952 DNS_SECTION_ADDITIONAL, 0);
1953 if (result != ISC_R_SUCCESS)
1954 goto cleanup_message;
1956 result = dns_message_renderend(fctx->qmessage);
1957 if (result != ISC_R_SUCCESS)
1958 goto cleanup_message;
1960 dns_compress_invalidate(&cctx);
1961 cleanup_cctx = ISC_FALSE;
1963 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1964 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1966 result = dns_message_getquerytsig(fctx->qmessage,
1969 if (result != ISC_R_SUCCESS)
1970 goto cleanup_message;
1974 * If using TCP, write the length of the message at the beginning
1977 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1978 isc_buffer_usedregion(&query->buffer, &r);
1979 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1980 isc_buffer_add(&tcpbuffer, r.length);
1984 * We're now done with the query message.
1986 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1988 if (query->exclusivesocket)
1989 socket = dns_dispatch_getentrysocket(query->dispentry);
1991 socket = dns_dispatch_getsocket(query->dispatch);
1995 if ((query->options & DNS_FETCHOPT_TCP) == 0) {
1996 address = &query->addrinfo->sockaddr;
1997 if (query->exclusivesocket) {
1998 result = isc_socket_connect(socket, address, task,
1999 resquery_udpconnected,
2001 if (result != ISC_R_SUCCESS)
2002 goto cleanup_message;
2003 connecting = ISC_TRUE;
2007 isc_buffer_usedregion(buffer, &r);
2010 * XXXRTH Make sure we don't send to ourselves! We should probably
2011 * prune out these addresses when we get them from the ADB.
2013 result = isc_socket_sendto(socket, &r, task, resquery_senddone,
2014 query, address, NULL);
2015 if (result != ISC_R_SUCCESS) {
2018 * This query is still connecting.
2019 * Mark it as canceled so that it will just be
2020 * cleaned up when the connected event is received.
2021 * Keep fctx around until the event is processed.
2023 query->fctx->nqueries++;
2024 query->attributes |= RESQUERY_ATTR_CANCELED;
2026 goto cleanup_message;
2033 return (ISC_R_SUCCESS);
2037 dns_compress_invalidate(&cctx);
2039 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
2042 * Stop the dispatcher from listening.
2044 dns_dispatch_removeresponse(&query->dispentry, NULL);
2048 dns_message_puttempname(fctx->qmessage, &qname);
2049 if (qrdataset != NULL)
2050 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
2056 resquery_connected(isc_task_t *task, isc_event_t *event) {
2057 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2058 resquery_t *query = event->ev_arg;
2059 isc_boolean_t retry = ISC_FALSE;
2060 isc_interval_t interval;
2061 isc_result_t result;
2065 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2066 REQUIRE(VALID_QUERY(query));
2068 QTRACE("connected");
2075 * Currently we don't wait for the connect event before retrying
2076 * a query. This means that if we get really behind, we may end
2077 * up doing extra work!
2083 if (RESQUERY_CANCELED(query)) {
2085 * This query was canceled while the connect() was in
2088 isc_socket_detach(&query->tcpsocket);
2089 resquery_destroy(&query);
2091 switch (sevent->result) {
2095 * Extend the idle timer for TCP. 20 seconds
2096 * should be long enough for a TCP connection to be
2097 * established, a single DNS request to be sent,
2098 * and the response received.
2100 isc_interval_set(&interval, 20, 0);
2101 result = fctx_startidletimer(query->fctx, &interval);
2102 if (result != ISC_R_SUCCESS) {
2103 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2104 fctx_done(fctx, result, __LINE__);
2108 * We are connected. Create a dispatcher and
2112 attrs |= DNS_DISPATCHATTR_TCP;
2113 attrs |= DNS_DISPATCHATTR_PRIVATE;
2114 attrs |= DNS_DISPATCHATTR_CONNECTED;
2115 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
2117 attrs |= DNS_DISPATCHATTR_IPV4;
2119 attrs |= DNS_DISPATCHATTR_IPV6;
2120 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
2122 result = dns_dispatch_createtcp(query->dispatchmgr,
2124 query->fctx->res->taskmgr,
2125 4096, 2, 1, 1, 3, attrs,
2129 * Regardless of whether dns_dispatch_create()
2130 * succeeded or not, we don't need our reference
2131 * to the socket anymore.
2133 isc_socket_detach(&query->tcpsocket);
2135 if (result == ISC_R_SUCCESS)
2136 result = resquery_send(query);
2138 if (result != ISC_R_SUCCESS) {
2139 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2140 fctx_done(fctx, result, __LINE__);
2144 case ISC_R_NETUNREACH:
2145 case ISC_R_HOSTUNREACH:
2146 case ISC_R_CONNREFUSED:
2148 case ISC_R_ADDRNOTAVAIL:
2149 case ISC_R_CONNECTIONRESET:
2151 * No route to remote.
2153 isc_socket_detach(&query->tcpsocket);
2154 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
2159 isc_socket_detach(&query->tcpsocket);
2160 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
2165 isc_event_free(&event);
2169 * Behave as if the idle timer has expired. For TCP
2170 * connections this may not actually reflect the latest timer.
2172 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2173 result = fctx_stopidletimer(fctx);
2174 if (result != ISC_R_SUCCESS)
2175 fctx_done(fctx, result, __LINE__);
2177 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2182 fctx_finddone(isc_task_t *task, isc_event_t *event) {
2184 dns_adbfind_t *find;
2185 dns_resolver_t *res;
2186 isc_boolean_t want_try = ISC_FALSE;
2187 isc_boolean_t want_done = ISC_FALSE;
2188 isc_boolean_t bucket_empty = ISC_FALSE;
2189 unsigned int bucketnum;
2190 isc_boolean_t destroy = ISC_FALSE;
2192 find = event->ev_sender;
2193 fctx = event->ev_arg;
2194 REQUIRE(VALID_FCTX(fctx));
2199 FCTXTRACE("finddone");
2201 bucketnum = fctx->bucketnum;
2202 LOCK(&res->buckets[bucketnum].lock);
2204 INSIST(fctx->pending > 0);
2207 if (ADDRWAIT(fctx)) {
2209 * The fetch is waiting for a name to be found.
2211 INSIST(!SHUTTINGDOWN(fctx));
2212 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2213 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
2214 want_try = ISC_TRUE;
2217 if (fctx->pending == 0) {
2219 * We've got nothing else to wait for and don't
2220 * know the answer. There's nothing to do but
2223 want_done = ISC_TRUE;
2226 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
2227 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
2229 if (fctx->references == 0) {
2230 bucket_empty = fctx_unlink(fctx);
2234 UNLOCK(&res->buckets[bucketnum].lock);
2236 isc_event_free(&event);
2237 dns_adb_destroyfind(&find);
2240 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
2242 fctx_done(fctx, ISC_R_FAILURE, __LINE__);
2251 static inline isc_boolean_t
2252 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
2255 for (sa = ISC_LIST_HEAD(fctx->bad);
2257 sa = ISC_LIST_NEXT(sa, link)) {
2258 if (isc_sockaddr_equal(sa, address))
2265 static inline isc_boolean_t
2266 mark_bad(fetchctx_t *fctx) {
2267 dns_adbfind_t *curr;
2268 dns_adbaddrinfo_t *addrinfo;
2269 isc_boolean_t all_bad = ISC_TRUE;
2272 * Mark all known bad servers, so we don't try to talk to them
2277 * Mark any bad nameservers.
2279 for (curr = ISC_LIST_HEAD(fctx->finds);
2281 curr = ISC_LIST_NEXT(curr, publink)) {
2282 for (addrinfo = ISC_LIST_HEAD(curr->list);
2284 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2285 if (bad_server(fctx, &addrinfo->sockaddr))
2286 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2288 all_bad = ISC_FALSE;
2293 * Mark any bad forwarders.
2295 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2297 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2298 if (bad_server(fctx, &addrinfo->sockaddr))
2299 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2301 all_bad = ISC_FALSE;
2305 * Mark any bad alternates.
2307 for (curr = ISC_LIST_HEAD(fctx->altfinds);
2309 curr = ISC_LIST_NEXT(curr, publink)) {
2310 for (addrinfo = ISC_LIST_HEAD(curr->list);
2312 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2313 if (bad_server(fctx, &addrinfo->sockaddr))
2314 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2316 all_bad = ISC_FALSE;
2320 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2322 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2323 if (bad_server(fctx, &addrinfo->sockaddr))
2324 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2326 all_bad = ISC_FALSE;
2333 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
2334 badnstype_t badtype)
2336 char namebuf[DNS_NAME_FORMATSIZE];
2337 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2343 const char *spc = "";
2344 isc_sockaddr_t *address = &addrinfo->sockaddr;
2346 if (reason == DNS_R_LAME)
2350 case badns_unreachable:
2353 case badns_response:
2356 case badns_validation:
2357 break; /* counted as 'valfail' */
2361 if (bad_server(fctx, address)) {
2363 * We already know this server is bad.
2368 FCTXTRACE("add_bad");
2370 sa = isc_mem_get(fctx->mctx, sizeof(*sa));
2374 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
2376 if (reason == DNS_R_LAME) /* already logged */
2379 if (reason == DNS_R_UNEXPECTEDRCODE &&
2380 fctx->rmessage->rcode == dns_rcode_servfail &&
2381 ISFORWARDER(addrinfo))
2384 if (reason == DNS_R_UNEXPECTEDRCODE) {
2385 isc_buffer_init(&b, code, sizeof(code) - 1);
2386 dns_rcode_totext(fctx->rmessage->rcode, &b);
2387 code[isc_buffer_usedlength(&b)] = '\0';
2389 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
2390 isc_buffer_init(&b, code, sizeof(code) - 1);
2391 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
2392 code[isc_buffer_usedlength(&b)] = '\0';
2397 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2398 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
2399 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
2400 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
2401 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2402 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2403 "error (%s%s%s) resolving '%s/%s/%s': %s",
2404 dns_result_totext(reason), spc, code,
2405 namebuf, typebuf, classbuf, addrbuf);
2409 * Sort addrinfo list by RTT.
2412 sort_adbfind(dns_adbfind_t *find) {
2413 dns_adbaddrinfo_t *best, *curr;
2414 dns_adbaddrinfolist_t sorted;
2416 /* Lame N^2 bubble sort. */
2417 ISC_LIST_INIT(sorted);
2418 while (!ISC_LIST_EMPTY(find->list)) {
2419 best = ISC_LIST_HEAD(find->list);
2420 curr = ISC_LIST_NEXT(best, publink);
2421 while (curr != NULL) {
2422 if (curr->srtt < best->srtt)
2424 curr = ISC_LIST_NEXT(curr, publink);
2426 ISC_LIST_UNLINK(find->list, best, publink);
2427 ISC_LIST_APPEND(sorted, best, publink);
2429 find->list = sorted;
2433 * Sort a list of finds by server RTT.
2436 sort_finds(dns_adbfindlist_t *findlist) {
2437 dns_adbfind_t *best, *curr;
2438 dns_adbfindlist_t sorted;
2439 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
2441 /* Sort each find's addrinfo list by SRTT. */
2442 for (curr = ISC_LIST_HEAD(*findlist);
2444 curr = ISC_LIST_NEXT(curr, publink))
2447 /* Lame N^2 bubble sort. */
2448 ISC_LIST_INIT(sorted);
2449 while (!ISC_LIST_EMPTY(*findlist)) {
2450 best = ISC_LIST_HEAD(*findlist);
2451 bestaddrinfo = ISC_LIST_HEAD(best->list);
2452 INSIST(bestaddrinfo != NULL);
2453 curr = ISC_LIST_NEXT(best, publink);
2454 while (curr != NULL) {
2455 addrinfo = ISC_LIST_HEAD(curr->list);
2456 INSIST(addrinfo != NULL);
2457 if (addrinfo->srtt < bestaddrinfo->srtt) {
2459 bestaddrinfo = addrinfo;
2461 curr = ISC_LIST_NEXT(curr, publink);
2463 ISC_LIST_UNLINK(*findlist, best, publink);
2464 ISC_LIST_APPEND(sorted, best, publink);
2470 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
2471 unsigned int options, unsigned int flags, isc_stdtime_t now,
2472 isc_boolean_t *need_alternate)
2474 dns_adbaddrinfo_t *ai;
2475 dns_adbfind_t *find;
2476 dns_resolver_t *res;
2477 isc_boolean_t unshared;
2478 isc_result_t result;
2481 unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
2483 * If this name is a subdomain of the query domain, tell
2484 * the ADB to start looking using zone/hint data. This keeps us
2485 * from getting stuck if the nameserver is beneath the zone cut
2486 * and we don't know its address (e.g. because the A record has
2489 if (dns_name_issubdomain(name, &fctx->domain))
2490 options |= DNS_ADBFIND_STARTATZONE;
2491 options |= DNS_ADBFIND_GLUEOK;
2492 options |= DNS_ADBFIND_HINTOK;
2495 * See what we know about this address.
2498 result = dns_adb_createfind(fctx->adb,
2499 res->buckets[fctx->bucketnum].task,
2500 fctx_finddone, fctx, name,
2501 &fctx->name, fctx->type,
2503 res->view->dstport, &find);
2504 if (result != ISC_R_SUCCESS) {
2505 if (result == DNS_R_ALIAS) {
2507 * XXXRTH Follow the CNAME/DNAME chain?
2509 dns_adb_destroyfind(&find);
2512 } else if (!ISC_LIST_EMPTY(find->list)) {
2514 * We have at least some of the addresses for the
2517 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
2518 if (flags != 0 || port != 0) {
2519 for (ai = ISC_LIST_HEAD(find->list);
2521 ai = ISC_LIST_NEXT(ai, publink)) {
2524 isc_sockaddr_setport(&ai->sockaddr,
2528 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
2529 ISC_LIST_APPEND(fctx->altfinds, find, publink);
2531 ISC_LIST_APPEND(fctx->finds, find, publink);
2534 * We don't know any of the addresses for this
2537 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
2539 * We're looking for them and will get an
2540 * event about it later.
2546 if (need_alternate != NULL &&
2547 !*need_alternate && unshared &&
2548 ((res->dispatchv4 == NULL &&
2549 find->result_v6 != DNS_R_NXDOMAIN) ||
2550 (res->dispatchv6 == NULL &&
2551 find->result_v4 != DNS_R_NXDOMAIN)))
2552 *need_alternate = ISC_TRUE;
2554 if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
2555 fctx->lamecount++; /* cached lame server */
2557 fctx->adberr++; /* unreachable server, etc. */
2560 * If we know there are no addresses for
2561 * the family we are using then try to add
2562 * an alternative server.
2564 if (need_alternate != NULL && !*need_alternate &&
2565 ((res->dispatchv4 == NULL &&
2566 find->result_v6 == DNS_R_NXRRSET) ||
2567 (res->dispatchv6 == NULL &&
2568 find->result_v4 == DNS_R_NXRRSET)))
2569 *need_alternate = ISC_TRUE;
2570 dns_adb_destroyfind(&find);
2575 static isc_boolean_t
2576 isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
2578 unsigned int nlabels;
2579 dns_namereln_t namereln;
2581 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
2582 return (ISC_TF(namereln == dns_namereln_subdomain));
2586 fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
2587 dns_rdata_t rdata = DNS_RDATA_INIT;
2588 isc_result_t result;
2589 dns_resolver_t *res;
2591 unsigned int stdoptions = 0;
2593 dns_adbaddrinfo_t *ai;
2594 isc_boolean_t all_bad;
2596 isc_boolean_t need_alternate = ISC_FALSE;
2598 FCTXTRACE("getaddresses");
2601 * Don't pound on remote servers. (Failsafe!)
2604 if (fctx->restarts > 10) {
2605 FCTXTRACE("too many restarts");
2606 return (DNS_R_SERVFAIL);
2615 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
2616 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
2619 * If this fctx has forwarders, use them; otherwise use any
2620 * selective forwarders specified in the view; otherwise use the
2621 * resolver's forwarders (if any).
2623 sa = ISC_LIST_HEAD(fctx->forwarders);
2625 dns_forwarders_t *forwarders = NULL;
2626 dns_name_t *name = &fctx->name;
2628 unsigned int labels;
2629 dns_fixedname_t fixed;
2633 * DS records are found in the parent server.
2634 * Strip label to get the correct forwarder (if any).
2636 if (dns_rdatatype_atparent(fctx->type) &&
2637 dns_name_countlabels(name) > 1) {
2638 dns_name_init(&suffix, NULL);
2639 labels = dns_name_countlabels(name);
2640 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2644 dns_fixedname_init(&fixed);
2645 domain = dns_fixedname_name(&fixed);
2646 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
2647 domain, &forwarders);
2648 if (result == ISC_R_SUCCESS) {
2649 sa = ISC_LIST_HEAD(forwarders->addrs);
2650 fctx->fwdpolicy = forwarders->fwdpolicy;
2651 if (fctx->fwdpolicy == dns_fwdpolicy_only &&
2652 isstrictsubdomain(domain, &fctx->domain)) {
2653 dns_name_free(&fctx->domain, fctx->mctx);
2654 dns_name_init(&fctx->domain, NULL);
2655 result = dns_name_dup(domain, fctx->mctx,
2657 if (result != ISC_R_SUCCESS)
2663 while (sa != NULL) {
2664 if ((isc_sockaddr_pf(sa) == AF_INET &&
2665 fctx->res->dispatchv4 == NULL) ||
2666 (isc_sockaddr_pf(sa) == AF_INET6 &&
2667 fctx->res->dispatchv6 == NULL)) {
2668 sa = ISC_LIST_NEXT(sa, link);
2672 result = dns_adb_findaddrinfo(fctx->adb,
2673 sa, &ai, 0); /* XXXMLG */
2674 if (result == ISC_R_SUCCESS) {
2675 dns_adbaddrinfo_t *cur;
2676 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2677 cur = ISC_LIST_HEAD(fctx->forwaddrs);
2678 while (cur != NULL && cur->srtt < ai->srtt)
2679 cur = ISC_LIST_NEXT(cur, publink);
2681 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
2684 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
2686 sa = ISC_LIST_NEXT(sa, link);
2690 * If the forwarding policy is "only", we don't need the addresses
2691 * of the nameservers.
2693 if (fctx->fwdpolicy == dns_fwdpolicy_only)
2697 * Normal nameservers.
2700 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
2701 if (fctx->restarts == 1) {
2703 * To avoid sending out a flood of queries likely to
2704 * result in NXRRSET, we suppress fetches for address
2705 * families we don't have the first time through,
2706 * provided that we have addresses in some family we
2709 * We don't want to set this option all the time, since
2710 * if fctx->restarts > 1, we've clearly been having trouble
2711 * with the addresses we had, so getting more could help.
2713 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
2715 if (res->dispatchv4 != NULL)
2716 stdoptions |= DNS_ADBFIND_INET;
2717 if (res->dispatchv6 != NULL)
2718 stdoptions |= DNS_ADBFIND_INET6;
2719 isc_stdtime_get(&now);
2721 INSIST(ISC_LIST_EMPTY(fctx->finds));
2722 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
2724 for (result = dns_rdataset_first(&fctx->nameservers);
2725 result == ISC_R_SUCCESS;
2726 result = dns_rdataset_next(&fctx->nameservers))
2728 dns_rdataset_current(&fctx->nameservers, &rdata);
2730 * Extract the name from the NS record.
2732 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2733 if (result != ISC_R_SUCCESS)
2736 findname(fctx, &ns.name, 0, stdoptions, 0, now,
2738 dns_rdata_reset(&rdata);
2739 dns_rdata_freestruct(&ns);
2741 if (result != ISC_R_NOMORE)
2745 * Do we need to use 6 to 4?
2747 if (need_alternate) {
2750 family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
2751 for (a = ISC_LIST_HEAD(fctx->res->alternates);
2753 a = ISC_LIST_NEXT(a, link)) {
2754 if (!a->isaddress) {
2755 findname(fctx, &a->_u._n.name, a->_u._n.port,
2756 stdoptions, FCTX_ADDRINFO_FORWARDER,
2760 if (isc_sockaddr_pf(&a->_u.addr) != family)
2763 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
2765 if (result == ISC_R_SUCCESS) {
2766 dns_adbaddrinfo_t *cur;
2767 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2768 cur = ISC_LIST_HEAD(fctx->altaddrs);
2769 while (cur != NULL && cur->srtt < ai->srtt)
2770 cur = ISC_LIST_NEXT(cur, publink);
2772 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
2775 ISC_LIST_APPEND(fctx->altaddrs, ai,
2783 * Mark all known bad servers.
2785 all_bad = mark_bad(fctx);
2792 * We've got no addresses.
2794 if (fctx->pending > 0) {
2796 * We're fetching the addresses, but don't have any
2797 * yet. Tell the caller to wait for an answer.
2799 result = DNS_R_WAIT;
2804 * We've lost completely. We don't know any
2805 * addresses, and the ADB has told us it can't get
2808 FCTXTRACE("no addresses");
2809 isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
2810 result = isc_time_nowplusinterval(&expire, &i);
2812 (fctx->type == dns_rdatatype_dnskey ||
2813 fctx->type == dns_rdatatype_dlv ||
2814 fctx->type == dns_rdatatype_ds) &&
2815 result == ISC_R_SUCCESS)
2816 dns_resolver_addbadcache(fctx->res,
2818 fctx->type, &expire);
2819 result = ISC_R_FAILURE;
2823 * We've found some addresses. We might still be looking
2824 * for more addresses.
2826 sort_finds(&fctx->finds);
2827 sort_finds(&fctx->altfinds);
2828 result = ISC_R_SUCCESS;
2835 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
2838 char buf[ISC_NETADDR_FORMATSIZE];
2840 isc_boolean_t aborted = ISC_FALSE;
2841 isc_boolean_t bogus;
2842 dns_acl_t *blackhole;
2843 isc_netaddr_t ipaddr;
2844 dns_peer_t *peer = NULL;
2845 dns_resolver_t *res;
2846 const char *msg = NULL;
2848 sa = &addr->sockaddr;
2851 isc_netaddr_fromsockaddr(&ipaddr, sa);
2852 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
2853 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
2855 if (blackhole != NULL) {
2858 if (dns_acl_match(&ipaddr, NULL, blackhole,
2860 &match, NULL) == ISC_R_SUCCESS &&
2866 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
2871 addr->flags |= FCTX_ADDRINFO_MARK;
2872 msg = "ignoring blackholed / bogus server: ";
2873 } else if (isc_sockaddr_ismulticast(sa)) {
2874 addr->flags |= FCTX_ADDRINFO_MARK;
2875 msg = "ignoring multicast address: ";
2876 } else if (isc_sockaddr_isexperimental(sa)) {
2877 addr->flags |= FCTX_ADDRINFO_MARK;
2878 msg = "ignoring experimental address: ";
2879 } else if (sa->type.sa.sa_family != AF_INET6) {
2881 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
2882 addr->flags |= FCTX_ADDRINFO_MARK;
2883 msg = "ignoring IPv6 mapped IPV4 address: ";
2884 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
2885 addr->flags |= FCTX_ADDRINFO_MARK;
2886 msg = "ignoring IPv6 compatibility IPV4 address: ";
2890 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
2893 isc_netaddr_fromsockaddr(&na, sa);
2894 isc_netaddr_format(&na, buf, sizeof(buf));
2895 FCTXTRACE2(msg, buf);
2898 static inline dns_adbaddrinfo_t *
2899 fctx_nextaddress(fetchctx_t *fctx) {
2900 dns_adbfind_t *find, *start;
2901 dns_adbaddrinfo_t *addrinfo;
2902 dns_adbaddrinfo_t *faddrinfo;
2905 * Return the next untried address, if any.
2909 * Find the first unmarked forwarder (if any).
2911 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2913 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2914 if (!UNMARKED(addrinfo))
2916 possibly_mark(fctx, addrinfo);
2917 if (UNMARKED(addrinfo)) {
2918 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2925 * No forwarders. Move to the next find.
2928 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
2932 find = ISC_LIST_HEAD(fctx->finds);
2934 find = ISC_LIST_NEXT(find, publink);
2936 find = ISC_LIST_HEAD(fctx->finds);
2940 * Find the first unmarked addrinfo.
2946 for (addrinfo = ISC_LIST_HEAD(find->list);
2948 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2949 if (!UNMARKED(addrinfo))
2951 possibly_mark(fctx, addrinfo);
2952 if (UNMARKED(addrinfo)) {
2953 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2957 if (addrinfo != NULL)
2959 find = ISC_LIST_NEXT(find, publink);
2961 find = ISC_LIST_HEAD(fctx->finds);
2962 } while (find != start);
2966 if (addrinfo != NULL)
2970 * No nameservers left. Try alternates.
2973 fctx->attributes |= FCTX_ATTR_TRIEDALT;
2975 find = fctx->altfind;
2977 find = ISC_LIST_HEAD(fctx->altfinds);
2979 find = ISC_LIST_NEXT(find, publink);
2981 find = ISC_LIST_HEAD(fctx->altfinds);
2985 * Find the first unmarked addrinfo.
2991 for (addrinfo = ISC_LIST_HEAD(find->list);
2993 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2994 if (!UNMARKED(addrinfo))
2996 possibly_mark(fctx, addrinfo);
2997 if (UNMARKED(addrinfo)) {
2998 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3002 if (addrinfo != NULL)
3004 find = ISC_LIST_NEXT(find, publink);
3006 find = ISC_LIST_HEAD(fctx->altfinds);
3007 } while (find != start);
3010 faddrinfo = addrinfo;
3013 * See if we have a better alternate server by address.
3016 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
3018 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
3019 if (!UNMARKED(addrinfo))
3021 possibly_mark(fctx, addrinfo);
3022 if (UNMARKED(addrinfo) &&
3023 (faddrinfo == NULL ||
3024 addrinfo->srtt < faddrinfo->srtt)) {
3025 if (faddrinfo != NULL)
3026 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
3027 addrinfo->flags |= FCTX_ADDRINFO_MARK;
3032 if (addrinfo == NULL) {
3033 addrinfo = faddrinfo;
3034 fctx->altfind = find;
3041 fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
3042 isc_result_t result;
3043 dns_adbaddrinfo_t *addrinfo;
3047 REQUIRE(!ADDRWAIT(fctx));
3049 addrinfo = fctx_nextaddress(fctx);
3050 if (addrinfo == NULL) {
3052 * We have no more addresses. Start over.
3054 fctx_cancelqueries(fctx, ISC_TRUE);
3055 fctx_cleanupfinds(fctx);
3056 fctx_cleanupaltfinds(fctx);
3057 fctx_cleanupforwaddrs(fctx);
3058 fctx_cleanupaltaddrs(fctx);
3059 result = fctx_getaddresses(fctx, badcache);
3060 if (result == DNS_R_WAIT) {
3062 * Sleep waiting for addresses.
3064 FCTXTRACE("addrwait");
3065 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
3067 } else if (result != ISC_R_SUCCESS) {
3069 * Something bad happened.
3071 fctx_done(fctx, result, __LINE__);
3075 addrinfo = fctx_nextaddress(fctx);
3077 * While we may have addresses from the ADB, they
3078 * might be bad ones. In this case, return SERVFAIL.
3080 if (addrinfo == NULL) {
3081 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
3086 result = fctx_query(fctx, addrinfo, fctx->options);
3087 if (result != ISC_R_SUCCESS)
3088 fctx_done(fctx, result, __LINE__);
3090 inc_stats(fctx->res, dns_resstatscounter_retry);
3093 static isc_boolean_t
3094 fctx_unlink(fetchctx_t *fctx) {
3095 dns_resolver_t *res;
3096 unsigned int bucketnum;
3099 * Caller must be holding the bucket lock.
3102 REQUIRE(VALID_FCTX(fctx));
3103 REQUIRE(fctx->state == fetchstate_done ||
3104 fctx->state == fetchstate_init);
3105 REQUIRE(ISC_LIST_EMPTY(fctx->events));
3106 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3107 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3108 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3109 REQUIRE(fctx->pending == 0);
3110 REQUIRE(fctx->references == 0);
3111 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3113 FCTXTRACE("unlink");
3116 bucketnum = fctx->bucketnum;
3118 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
3122 UNLOCK(&res->nlock);
3124 if (res->buckets[bucketnum].exiting &&
3125 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
3132 fctx_destroy(fetchctx_t *fctx) {
3133 isc_sockaddr_t *sa, *next_sa;
3135 REQUIRE(VALID_FCTX(fctx));
3136 REQUIRE(fctx->state == fetchstate_done ||
3137 fctx->state == fetchstate_init);
3138 REQUIRE(ISC_LIST_EMPTY(fctx->events));
3139 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
3140 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
3141 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
3142 REQUIRE(fctx->pending == 0);
3143 REQUIRE(fctx->references == 0);
3144 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
3145 REQUIRE(!ISC_LINK_LINKED(fctx, link));
3147 FCTXTRACE("destroy");
3152 for (sa = ISC_LIST_HEAD(fctx->bad);
3155 next_sa = ISC_LIST_NEXT(sa, link);
3156 ISC_LIST_UNLINK(fctx->bad, sa, link);
3157 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3160 for (sa = ISC_LIST_HEAD(fctx->edns);
3163 next_sa = ISC_LIST_NEXT(sa, link);
3164 ISC_LIST_UNLINK(fctx->edns, sa, link);
3165 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3168 for (sa = ISC_LIST_HEAD(fctx->edns512);
3171 next_sa = ISC_LIST_NEXT(sa, link);
3172 ISC_LIST_UNLINK(fctx->edns512, sa, link);
3173 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3176 for (sa = ISC_LIST_HEAD(fctx->bad_edns);
3179 next_sa = ISC_LIST_NEXT(sa, link);
3180 ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
3181 isc_mem_put(fctx->mctx, sa, sizeof(*sa));
3184 isc_timer_detach(&fctx->timer);
3185 dns_message_destroy(&fctx->rmessage);
3186 dns_message_destroy(&fctx->qmessage);
3187 if (dns_name_countlabels(&fctx->domain) > 0)
3188 dns_name_free(&fctx->domain, fctx->mctx);
3189 if (dns_rdataset_isassociated(&fctx->nameservers))
3190 dns_rdataset_disassociate(&fctx->nameservers);
3191 dns_name_free(&fctx->name, fctx->mctx);
3192 dns_db_detach(&fctx->cache);
3193 dns_adb_detach(&fctx->adb);
3194 isc_mem_free(fctx->mctx, fctx->info);
3195 isc_mem_putanddetach(&fctx->mctx, fctx, sizeof(*fctx));
3199 * Fetch event handlers.
3203 fctx_timeout(isc_task_t *task, isc_event_t *event) {
3204 fetchctx_t *fctx = event->ev_arg;
3205 isc_timerevent_t *tevent = (isc_timerevent_t *)event;
3208 REQUIRE(VALID_FCTX(fctx));
3212 FCTXTRACE("timeout");
3214 inc_stats(fctx->res, dns_resstatscounter_querytimeout);
3216 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
3217 fctx->reason = NULL;
3218 fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
3220 isc_result_t result;
3223 fctx->timeout = ISC_TRUE;
3225 * We could cancel the running queries here, or we could let
3226 * them keep going. Since we normally use separate sockets for
3227 * different queries, we adopt the former approach to reduce
3228 * the number of open sockets: cancel the oldest query if it
3229 * expired after the query had started (this is usually the
3230 * case but is not always so, depending on the task schedule
3233 query = ISC_LIST_HEAD(fctx->queries);
3234 if (query != NULL &&
3235 isc_time_compare(&tevent->due, &query->start) >= 0) {
3236 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
3238 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3240 * Our timer has triggered. Reestablish the fctx lifetime
3243 result = fctx_starttimer(fctx);
3244 if (result != ISC_R_SUCCESS)
3245 fctx_done(fctx, result, __LINE__);
3250 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
3253 isc_event_free(&event);
3257 fctx_shutdown(fetchctx_t *fctx) {
3258 isc_event_t *cevent;
3261 * Start the shutdown process for fctx, if it isn't already underway.
3264 FCTXTRACE("shutdown");
3267 * The caller must be holding the appropriate bucket lock.
3270 if (fctx->want_shutdown)
3273 fctx->want_shutdown = ISC_TRUE;
3276 * Unless we're still initializing (in which case the
3277 * control event is still outstanding), we need to post
3278 * the control event to tell the fetch we want it to
3281 if (fctx->state != fetchstate_init) {
3282 cevent = &fctx->control_event;
3283 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
3289 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
3290 fetchctx_t *fctx = event->ev_arg;
3291 isc_boolean_t bucket_empty = ISC_FALSE;
3292 dns_resolver_t *res;
3293 unsigned int bucketnum;
3294 dns_validator_t *validator;
3295 isc_boolean_t destroy = ISC_FALSE;
3297 REQUIRE(VALID_FCTX(fctx));
3302 bucketnum = fctx->bucketnum;
3304 FCTXTRACE("doshutdown");
3307 * An fctx that is shutting down is no longer in ADDRWAIT mode.
3309 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
3312 * Cancel all pending validators. Note that this must be done
3313 * without the bucket lock held, since that could cause deadlock.
3315 validator = ISC_LIST_HEAD(fctx->validators);
3316 while (validator != NULL) {
3317 dns_validator_cancel(validator);
3318 validator = ISC_LIST_NEXT(validator, link);
3321 if (fctx->nsfetch != NULL)
3322 dns_resolver_cancelfetch(fctx->nsfetch);
3325 * Shut down anything that is still running on behalf of this
3326 * fetch. To avoid deadlock with the ADB, we must do this
3327 * before we lock the bucket lock.
3329 fctx_stopeverything(fctx, ISC_FALSE);
3331 LOCK(&res->buckets[bucketnum].lock);
3333 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3335 INSIST(fctx->state == fetchstate_active ||
3336 fctx->state == fetchstate_done);
3337 INSIST(fctx->want_shutdown);
3339 if (fctx->state != fetchstate_done) {
3340 fctx->state = fetchstate_done;
3341 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3344 if (fctx->references == 0 && fctx->pending == 0 &&
3345 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
3346 bucket_empty = fctx_unlink(fctx);
3350 UNLOCK(&res->buckets[bucketnum].lock);
3360 fctx_start(isc_task_t *task, isc_event_t *event) {
3361 fetchctx_t *fctx = event->ev_arg;
3362 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
3363 dns_resolver_t *res;
3364 unsigned int bucketnum;
3365 isc_boolean_t destroy = ISC_FALSE;
3367 REQUIRE(VALID_FCTX(fctx));
3372 bucketnum = fctx->bucketnum;
3376 LOCK(&res->buckets[bucketnum].lock);
3378 INSIST(fctx->state == fetchstate_init);
3379 if (fctx->want_shutdown) {
3381 * We haven't started this fctx yet, and we've been requested
3384 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
3385 fctx->state = fetchstate_done;
3386 fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
3388 * Since we haven't started, we INSIST that we have no
3389 * pending ADB finds and no pending validations.
3391 INSIST(fctx->pending == 0);
3392 INSIST(fctx->nqueries == 0);
3393 INSIST(ISC_LIST_EMPTY(fctx->validators));
3394 if (fctx->references == 0) {
3396 * It's now safe to destroy this fctx.
3398 bucket_empty = fctx_unlink(fctx);
3404 * Normal fctx startup.
3406 fctx->state = fetchstate_active;
3408 * Reset the control event for later use in shutting down
3411 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
3412 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
3416 UNLOCK(&res->buckets[bucketnum].lock);
3419 isc_result_t result;
3424 * All is well. Start working on the fetch.
3426 result = fctx_starttimer(fctx);
3427 if (result != ISC_R_SUCCESS)
3428 fctx_done(fctx, result, __LINE__);
3430 fctx_try(fctx, ISC_FALSE, ISC_FALSE);
3431 } else if (destroy) {
3439 * Fetch Creation, Joining, and Cancelation.
3442 static inline isc_result_t
3443 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
3444 dns_messageid_t id, isc_taskaction_t action, void *arg,
3445 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3449 dns_fetchevent_t *event;
3454 * We store the task we're going to send this event to in the
3455 * sender field. We'll make the fetch the sender when we actually
3459 isc_task_attach(task, &clone);
3460 event = (dns_fetchevent_t *)
3461 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
3462 action, arg, sizeof(*event));
3463 if (event == NULL) {
3464 isc_task_detach(&clone);
3465 return (ISC_R_NOMEMORY);
3467 event->result = DNS_R_SERVFAIL;
3468 event->qtype = fctx->type;
3471 event->rdataset = rdataset;
3472 event->sigrdataset = sigrdataset;
3473 event->fetch = fetch;
3474 event->client = client;
3476 dns_fixedname_init(&event->foundname);
3479 * Make sure that we can store the sigrdataset in the
3480 * first event if it is needed by any of the events.
3482 if (event->sigrdataset != NULL)
3483 ISC_LIST_PREPEND(fctx->events, event, ev_link);
3485 ISC_LIST_APPEND(fctx->events, event, ev_link);
3487 fctx->client = client;
3489 fetch->magic = DNS_FETCH_MAGIC;
3490 fetch->private = fctx;
3492 return (ISC_R_SUCCESS);
3496 log_ns_ttl(fetchctx_t *fctx, const char *where) {
3497 char namebuf[DNS_NAME_FORMATSIZE];
3498 char domainbuf[DNS_NAME_FORMATSIZE];
3500 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3501 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3502 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3503 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
3504 "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
3505 fctx, where, namebuf, domainbuf,
3506 fctx->ns_ttl_ok, fctx->ns_ttl);
3510 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
3511 dns_name_t *domain, dns_rdataset_t *nameservers,
3512 unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
3515 isc_result_t result;
3516 isc_result_t iresult;
3517 isc_interval_t interval;
3518 dns_fixedname_t fixed;
3519 unsigned int findoptions = 0;
3520 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
3521 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3526 * Caller must be holding the lock for bucket number 'bucketnum'.
3528 REQUIRE(fctxp != NULL && *fctxp == NULL);
3530 mctx = res->buckets[bucketnum].mctx;
3531 fctx = isc_mem_get(mctx, sizeof(*fctx));
3533 return (ISC_R_NOMEMORY);
3534 dns_name_format(name, buf, sizeof(buf));
3535 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
3536 strcat(buf, "/"); /* checked */
3537 strcat(buf, typebuf); /* checked */
3538 fctx->info = isc_mem_strdup(mctx, buf);
3539 if (fctx->info == NULL) {
3540 result = ISC_R_NOMEMORY;
3543 FCTXTRACE("create");
3544 dns_name_init(&fctx->name, NULL);
3545 result = dns_name_dup(name, mctx, &fctx->name);
3546 if (result != ISC_R_SUCCESS)
3548 dns_name_init(&fctx->domain, NULL);
3549 dns_rdataset_init(&fctx->nameservers);
3552 fctx->options = options;
3554 * Note! We do not attach to the task. We are relying on the
3555 * resolver to ensure that this task doesn't go away while we are
3559 fctx->references = 0;
3560 fctx->bucketnum = bucketnum;
3561 fctx->state = fetchstate_init;
3562 fctx->want_shutdown = ISC_FALSE;
3563 fctx->cloned = ISC_FALSE;
3564 ISC_LIST_INIT(fctx->queries);
3565 ISC_LIST_INIT(fctx->finds);
3566 ISC_LIST_INIT(fctx->altfinds);
3567 ISC_LIST_INIT(fctx->forwaddrs);
3568 ISC_LIST_INIT(fctx->altaddrs);
3569 ISC_LIST_INIT(fctx->forwarders);
3570 fctx->fwdpolicy = dns_fwdpolicy_none;
3571 ISC_LIST_INIT(fctx->bad);
3572 ISC_LIST_INIT(fctx->edns);
3573 ISC_LIST_INIT(fctx->edns512);
3574 ISC_LIST_INIT(fctx->bad_edns);
3575 ISC_LIST_INIT(fctx->validators);
3576 fctx->validator = NULL;
3578 fctx->altfind = NULL;
3581 fctx->querysent = 0;
3582 fctx->referrals = 0;
3583 TIME_NOW(&fctx->start);
3585 fctx->lamecount = 0;
3591 fctx->result = ISC_R_FAILURE;
3592 fctx->vresult = ISC_R_SUCCESS;
3593 fctx->exitline = -1; /* sentinel */
3594 fctx->logged = ISC_FALSE;
3595 fctx->attributes = 0;
3596 fctx->spilled = ISC_FALSE;
3598 fctx->reason = NULL;
3600 fctx->rand_bits = 0;
3601 fctx->timeout = ISC_FALSE;
3602 fctx->addrinfo = NULL;
3603 fctx->client = NULL;
3605 fctx->ns_ttl_ok = ISC_FALSE;
3607 dns_name_init(&fctx->nsname, NULL);
3608 fctx->nsfetch = NULL;
3609 dns_rdataset_init(&fctx->nsrrset);
3611 if (domain == NULL) {
3612 dns_forwarders_t *forwarders = NULL;
3613 unsigned int labels;
3614 dns_name_t *fwdname = name;
3617 * DS records are found in the parent server.
3618 * Strip label to get the correct forwarder (if any).
3620 if (dns_rdatatype_atparent(fctx->type) &&
3621 dns_name_countlabels(name) > 1) {
3622 dns_name_init(&suffix, NULL);
3623 labels = dns_name_countlabels(name);
3624 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
3627 dns_fixedname_init(&fixed);
3628 domain = dns_fixedname_name(&fixed);
3629 result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
3630 domain, &forwarders);
3631 if (result == ISC_R_SUCCESS)
3632 fctx->fwdpolicy = forwarders->fwdpolicy;
3634 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
3636 * The caller didn't supply a query domain and
3637 * nameservers, and we're not in forward-only mode,
3638 * so find the best nameservers to use.
3640 if (dns_rdatatype_atparent(fctx->type))
3641 findoptions |= DNS_DBFIND_NOEXACT;
3642 result = dns_view_findzonecut(res->view, name, domain,
3643 0, findoptions, ISC_TRUE,
3646 if (result != ISC_R_SUCCESS)
3648 result = dns_name_dup(domain, mctx, &fctx->domain);
3649 if (result != ISC_R_SUCCESS) {
3650 dns_rdataset_disassociate(&fctx->nameservers);
3653 fctx->ns_ttl = fctx->nameservers.ttl;
3654 fctx->ns_ttl_ok = ISC_TRUE;
3657 * We're in forward-only mode. Set the query domain.
3659 result = dns_name_dup(domain, mctx, &fctx->domain);
3660 if (result != ISC_R_SUCCESS)
3664 result = dns_name_dup(domain, mctx, &fctx->domain);
3665 if (result != ISC_R_SUCCESS)
3667 dns_rdataset_clone(nameservers, &fctx->nameservers);
3668 fctx->ns_ttl = fctx->nameservers.ttl;
3669 fctx->ns_ttl_ok = ISC_TRUE;
3672 log_ns_ttl(fctx, "fctx_create");
3674 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
3676 fctx->qmessage = NULL;
3677 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
3680 if (result != ISC_R_SUCCESS)
3681 goto cleanup_domain;
3683 fctx->rmessage = NULL;
3684 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3687 if (result != ISC_R_SUCCESS)
3688 goto cleanup_qmessage;
3691 * Compute an expiration time for the entire fetch.
3693 isc_interval_set(&interval, res->query_timeout, 0);
3694 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
3695 if (iresult != ISC_R_SUCCESS) {
3696 UNEXPECTED_ERROR(__FILE__, __LINE__,
3697 "isc_time_nowplusinterval: %s",
3698 isc_result_totext(iresult));
3699 result = ISC_R_UNEXPECTED;
3700 goto cleanup_rmessage;
3704 * Default retry interval initialization. We set the interval now
3705 * mostly so it won't be uninitialized. It will be set to the
3706 * correct value before a query is issued.
3708 isc_interval_set(&fctx->interval, 2, 0);
3711 * Create an inactive timer. It will be made active when the fetch
3712 * is actually started.
3715 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
3717 res->buckets[bucketnum].task, fctx_timeout,
3718 fctx, &fctx->timer);
3719 if (iresult != ISC_R_SUCCESS) {
3720 UNEXPECTED_ERROR(__FILE__, __LINE__,
3721 "isc_timer_create: %s",
3722 isc_result_totext(iresult));
3723 result = ISC_R_UNEXPECTED;
3724 goto cleanup_rmessage;
3728 * Attach to the view's cache and adb.
3731 dns_db_attach(res->view->cachedb, &fctx->cache);
3733 dns_adb_attach(res->view->adb, &fctx->adb);
3735 isc_mem_attach(mctx, &fctx->mctx);
3737 ISC_LIST_INIT(fctx->events);
3738 ISC_LINK_INIT(fctx, link);
3739 fctx->magic = FCTX_MAGIC;
3741 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
3745 UNLOCK(&res->nlock);
3749 return (ISC_R_SUCCESS);
3752 dns_message_destroy(&fctx->rmessage);
3755 dns_message_destroy(&fctx->qmessage);
3758 if (dns_name_countlabels(&fctx->domain) > 0)
3759 dns_name_free(&fctx->domain, mctx);
3760 if (dns_rdataset_isassociated(&fctx->nameservers))
3761 dns_rdataset_disassociate(&fctx->nameservers);
3764 dns_name_free(&fctx->name, mctx);
3767 isc_mem_free(mctx, fctx->info);
3770 isc_mem_put(mctx, fctx, sizeof(*fctx));
3778 static inline isc_boolean_t
3779 is_lame(fetchctx_t *fctx) {
3780 dns_message_t *message = fctx->rmessage;
3782 dns_rdataset_t *rdataset;
3783 isc_result_t result;
3785 if (message->rcode != dns_rcode_noerror &&
3786 message->rcode != dns_rcode_nxdomain)
3789 if (message->counts[DNS_SECTION_ANSWER] != 0)
3792 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
3795 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3796 while (result == ISC_R_SUCCESS) {
3798 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3799 for (rdataset = ISC_LIST_HEAD(name->list);
3801 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3802 dns_namereln_t namereln;
3804 unsigned int labels;
3805 if (rdataset->type != dns_rdatatype_ns)
3807 namereln = dns_name_fullcompare(name, &fctx->domain,
3809 if (namereln == dns_namereln_equal &&
3810 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
3812 if (namereln == dns_namereln_subdomain)
3816 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
3823 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
3824 char namebuf[DNS_NAME_FORMATSIZE];
3825 char domainbuf[DNS_NAME_FORMATSIZE];
3826 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3828 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3829 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3830 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
3831 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
3832 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
3833 "lame server resolving '%s' (in '%s'?): %s",
3834 namebuf, domainbuf, addrbuf);
3838 log_formerr(fetchctx_t *fctx, const char *format, ...) {
3839 char nsbuf[ISC_SOCKADDR_FORMATSIZE];
3840 char clbuf[ISC_SOCKADDR_FORMATSIZE];
3841 const char *clmsg = "";
3845 va_start(args, format);
3846 vsnprintf(msgbuf, sizeof(msgbuf), format, args);
3849 isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
3851 if (fctx->client != NULL) {
3852 clmsg = " for client ";
3853 isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
3858 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3859 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
3860 "DNS format error from %s resolving %s%s%s: %s",
3861 nsbuf, fctx->info, clmsg, clbuf, msgbuf);
3864 static inline isc_result_t
3865 same_question(fetchctx_t *fctx) {
3866 isc_result_t result;
3867 dns_message_t *message = fctx->rmessage;
3869 dns_rdataset_t *rdataset;
3872 * Caller must be holding the fctx lock.
3876 * XXXRTH Currently we support only one question.
3878 if (message->counts[DNS_SECTION_QUESTION] != 1) {
3879 log_formerr(fctx, "too many questions");
3880 return (DNS_R_FORMERR);
3883 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3884 if (result != ISC_R_SUCCESS)
3887 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
3888 rdataset = ISC_LIST_HEAD(name->list);
3889 INSIST(rdataset != NULL);
3890 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
3892 if (fctx->type != rdataset->type ||
3893 fctx->res->rdclass != rdataset->rdclass ||
3894 !dns_name_equal(&fctx->name, name)) {
3895 char namebuf[DNS_NAME_FORMATSIZE];
3896 char class[DNS_RDATACLASS_FORMATSIZE];
3897 char type[DNS_RDATATYPE_FORMATSIZE];
3899 dns_name_format(name, namebuf, sizeof(namebuf));
3900 dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
3901 dns_rdatatype_format(rdataset->type, type, sizeof(type));
3902 log_formerr(fctx, "question section mismatch: got %s/%s/%s",
3903 namebuf, class, type);
3904 return (DNS_R_FORMERR);
3907 return (ISC_R_SUCCESS);
3911 clone_results(fetchctx_t *fctx) {
3912 dns_fetchevent_t *event, *hevent;
3913 isc_result_t result;
3914 dns_name_t *name, *hname;
3916 FCTXTRACE("clone_results");
3919 * Set up any other events to have the same data as the first
3922 * Caller must be holding the appropriate lock.
3925 fctx->cloned = ISC_TRUE;
3926 hevent = ISC_LIST_HEAD(fctx->events);
3929 hname = dns_fixedname_name(&hevent->foundname);
3930 for (event = ISC_LIST_NEXT(hevent, ev_link);
3932 event = ISC_LIST_NEXT(event, ev_link)) {
3933 name = dns_fixedname_name(&event->foundname);
3934 result = dns_name_copy(hname, name, NULL);
3935 if (result != ISC_R_SUCCESS)
3936 event->result = result;
3938 event->result = hevent->result;
3939 dns_db_attach(hevent->db, &event->db);
3940 dns_db_attachnode(hevent->db, hevent->node, &event->node);
3941 INSIST(hevent->rdataset != NULL);
3942 INSIST(event->rdataset != NULL);
3943 if (dns_rdataset_isassociated(hevent->rdataset))
3944 dns_rdataset_clone(hevent->rdataset, event->rdataset);
3945 INSIST(! (hevent->sigrdataset == NULL &&
3946 event->sigrdataset != NULL));
3947 if (hevent->sigrdataset != NULL &&
3948 dns_rdataset_isassociated(hevent->sigrdataset) &&
3949 event->sigrdataset != NULL)
3950 dns_rdataset_clone(hevent->sigrdataset,
3951 event->sigrdataset);
3955 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3956 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3957 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3958 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3959 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3960 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3961 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3965 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3966 * no references and is no longer waiting for any events).
3969 * '*fctx' is shutting down.
3972 * true if the resolver is exiting and this is the last fctx in the bucket.
3974 static isc_boolean_t
3975 maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
3976 unsigned int bucketnum;
3977 isc_boolean_t bucket_empty = ISC_FALSE;
3978 dns_resolver_t *res = fctx->res;
3979 dns_validator_t *validator, *next_validator;
3980 isc_boolean_t destroy = ISC_FALSE;
3982 REQUIRE(SHUTTINGDOWN(fctx));
3984 bucketnum = fctx->bucketnum;
3986 LOCK(&res->buckets[bucketnum].lock);
3987 if (fctx->pending != 0 || fctx->nqueries != 0)
3990 for (validator = ISC_LIST_HEAD(fctx->validators);
3991 validator != NULL; validator = next_validator) {
3992 next_validator = ISC_LIST_NEXT(validator, link);
3993 dns_validator_cancel(validator);
3996 if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) {
3997 bucket_empty = fctx_unlink(fctx);
4002 UNLOCK(&res->buckets[bucketnum].lock);
4005 return (bucket_empty);
4009 * The validator has finished.
4012 validated(isc_task_t *task, isc_event_t *event) {
4013 dns_adbaddrinfo_t *addrinfo;
4014 dns_dbnode_t *node = NULL;
4015 dns_dbnode_t *nsnode = NULL;
4016 dns_fetchevent_t *hevent;
4018 dns_rdataset_t *ardataset = NULL;
4019 dns_rdataset_t *asigrdataset = NULL;
4020 dns_rdataset_t *rdataset;
4021 dns_rdataset_t *sigrdataset;
4022 dns_resolver_t *res;
4023 dns_valarg_t *valarg;
4024 dns_validatorevent_t *vevent;
4026 isc_boolean_t chaining;
4027 isc_boolean_t negative;
4028 isc_boolean_t sentresponse;
4029 isc_result_t eresult = ISC_R_SUCCESS;
4030 isc_result_t result = ISC_R_SUCCESS;
4034 UNUSED(task); /* for now */
4036 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
4037 valarg = event->ev_arg;
4038 fctx = valarg->fctx;
4040 addrinfo = valarg->addrinfo;
4041 REQUIRE(VALID_FCTX(fctx));
4042 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
4044 vevent = (dns_validatorevent_t *)event;
4045 fctx->vresult = vevent->result;
4047 FCTXTRACE("received validation completion event");
4049 LOCK(&res->buckets[fctx->bucketnum].lock);
4051 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
4052 fctx->validator = NULL;
4055 * Destroy the validator early so that we can
4056 * destroy the fctx if necessary.
4058 dns_validator_destroy(&vevent->validator);
4059 isc_mem_put(fctx->mctx, valarg, sizeof(*valarg));
4061 negative = ISC_TF(vevent->rdataset == NULL);
4063 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
4066 * If shutting down, ignore the results. Check to see if we're
4067 * done waiting for validator completions and ADB pending events; if
4068 * so, destroy the fctx.
4070 if (SHUTTINGDOWN(fctx) && !sentresponse) {
4071 isc_uint32_t bucketnum = fctx->bucketnum;
4072 isc_boolean_t bucket_empty;
4073 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4074 UNLOCK(&res->buckets[bucketnum].lock);
4080 isc_stdtime_get(&now);
4083 * If chaining, we need to make sure that the right result code is
4084 * returned, and that the rdatasets are bound.
4086 if (vevent->result == ISC_R_SUCCESS &&
4088 vevent->rdataset != NULL &&
4089 CHAINING(vevent->rdataset))
4091 if (vevent->rdataset->type == dns_rdatatype_cname)
4092 eresult = DNS_R_CNAME;
4094 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
4095 eresult = DNS_R_DNAME;
4097 chaining = ISC_TRUE;
4099 chaining = ISC_FALSE;
4102 * Either we're not shutting down, or we are shutting down but want
4103 * to cache the result anyway (if this was a validation started by
4104 * a query with cd set)
4107 hevent = ISC_LIST_HEAD(fctx->events);
4108 if (hevent != NULL) {
4109 if (!negative && !chaining &&
4110 (fctx->type == dns_rdatatype_any ||
4111 fctx->type == dns_rdatatype_rrsig ||
4112 fctx->type == dns_rdatatype_sig)) {
4114 * Don't bind rdatasets; the caller
4115 * will iterate the node.
4118 ardataset = hevent->rdataset;
4119 asigrdataset = hevent->sigrdataset;
4123 if (vevent->result != ISC_R_SUCCESS) {
4124 FCTXTRACE("validation failed");
4125 inc_stats(res, dns_resstatscounter_valfail);
4127 fctx->vresult = vevent->result;
4128 if (fctx->vresult != DNS_R_BROKENCHAIN) {
4129 result = ISC_R_NOTFOUND;
4130 if (vevent->rdataset != NULL)
4131 result = dns_db_findnode(fctx->cache,
4134 if (result == ISC_R_SUCCESS)
4135 (void)dns_db_deleterdataset(fctx->cache, node,
4138 if (result == ISC_R_SUCCESS &&
4139 vevent->sigrdataset != NULL)
4140 (void)dns_db_deleterdataset(fctx->cache, node,
4142 dns_rdatatype_rrsig,
4144 if (result == ISC_R_SUCCESS)
4145 dns_db_detachnode(fctx->cache, &node);
4147 if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
4149 * Cache the data as pending for later validation.
4151 result = ISC_R_NOTFOUND;
4152 if (vevent->rdataset != NULL)
4153 result = dns_db_findnode(fctx->cache,
4156 if (result == ISC_R_SUCCESS) {
4157 (void)dns_db_addrdataset(fctx->cache, node,
4159 vevent->rdataset, 0,
4162 if (result == ISC_R_SUCCESS &&
4163 vevent->sigrdataset != NULL)
4164 (void)dns_db_addrdataset(fctx->cache, node,
4166 vevent->sigrdataset,
4168 if (result == ISC_R_SUCCESS)
4169 dns_db_detachnode(fctx->cache, &node);
4171 result = fctx->vresult;
4172 add_bad(fctx, addrinfo, result, badns_validation);
4173 isc_event_free(&event);
4174 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4175 INSIST(fctx->validator == NULL);
4176 fctx->validator = ISC_LIST_HEAD(fctx->validators);
4177 if (fctx->validator != NULL)
4178 dns_validator_send(fctx->validator);
4179 else if (sentresponse)
4180 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4181 else if (result == DNS_R_BROKENCHAIN) {
4182 isc_result_t tresult;
4186 isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
4187 tresult = isc_time_nowplusinterval(&expire, &i);
4189 (fctx->type == dns_rdatatype_dnskey ||
4190 fctx->type == dns_rdatatype_dlv ||
4191 fctx->type == dns_rdatatype_ds) &&
4192 tresult == ISC_R_SUCCESS)
4193 dns_resolver_addbadcache(res, &fctx->name,
4194 fctx->type, &expire);
4195 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4197 fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
4203 dns_rdatatype_t covers;
4204 FCTXTRACE("nonexistence validation OK");
4206 inc_stats(res, dns_resstatscounter_valnegsuccess);
4208 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
4209 covers = dns_rdatatype_any;
4211 covers = fctx->type;
4213 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
4215 if (result != ISC_R_SUCCESS)
4216 goto noanswer_response;
4219 * If we are asking for a SOA record set the cache time
4220 * to zero to facilitate locating the containing zone of
4223 ttl = res->view->maxncachettl;
4224 if (fctx->type == dns_rdatatype_soa &&
4225 covers == dns_rdatatype_any && res->zero_no_soa_ttl)
4228 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4229 covers, now, ttl, vevent->optout,
4230 ardataset, &eresult);
4231 if (result != ISC_R_SUCCESS)
4232 goto noanswer_response;
4233 goto answer_response;
4235 inc_stats(res, dns_resstatscounter_valsuccess);
4237 FCTXTRACE("validation OK");
4239 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
4241 result = dns_rdataset_addnoqname(vevent->rdataset,
4242 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
4243 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4244 INSIST(vevent->sigrdataset != NULL);
4245 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
4246 if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
4247 result = dns_rdataset_addclosest(vevent->rdataset,
4248 vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
4249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4254 * The data was already cached as pending data.
4255 * Re-cache it as secure and bind the cached
4256 * rdatasets to the first event on the fetch
4259 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
4260 if (result != ISC_R_SUCCESS)
4261 goto noanswer_response;
4263 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4264 vevent->rdataset, 0, ardataset);
4265 if (result != ISC_R_SUCCESS &&
4266 result != DNS_R_UNCHANGED)
4267 goto noanswer_response;
4268 if (ardataset != NULL && NEGATIVE(ardataset)) {
4269 if (NXDOMAIN(ardataset))
4270 eresult = DNS_R_NCACHENXDOMAIN;
4272 eresult = DNS_R_NCACHENXRRSET;
4273 } else if (vevent->sigrdataset != NULL) {
4274 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
4275 vevent->sigrdataset, 0,
4277 if (result != ISC_R_SUCCESS &&
4278 result != DNS_R_UNCHANGED)
4279 goto noanswer_response;
4283 isc_boolean_t bucket_empty = ISC_FALSE;
4285 * If we only deferred the destroy because we wanted to cache
4286 * the data, destroy now.
4288 dns_db_detachnode(fctx->cache, &node);
4289 if (SHUTTINGDOWN(fctx))
4290 bucket_empty = maybe_destroy(fctx, ISC_TRUE);
4291 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4297 if (!ISC_LIST_EMPTY(fctx->validators)) {
4299 INSIST(fctx->type == dns_rdatatype_any ||
4300 fctx->type == dns_rdatatype_rrsig ||
4301 fctx->type == dns_rdatatype_sig);
4303 * Don't send a response yet - we have
4304 * more rdatasets that still need to
4307 dns_db_detachnode(fctx->cache, &node);
4308 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4309 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
4315 * Cache any NS/NSEC records that happened to be validated.
4317 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
4318 while (result == ISC_R_SUCCESS) {
4320 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
4322 for (rdataset = ISC_LIST_HEAD(name->list);
4324 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4325 if ((rdataset->type != dns_rdatatype_ns &&
4326 rdataset->type != dns_rdatatype_nsec) ||
4327 rdataset->trust != dns_trust_secure)
4329 for (sigrdataset = ISC_LIST_HEAD(name->list);
4330 sigrdataset != NULL;
4331 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4332 if (sigrdataset->type != dns_rdatatype_rrsig ||
4333 sigrdataset->covers != rdataset->type)
4337 if (sigrdataset == NULL ||
4338 sigrdataset->trust != dns_trust_secure)
4340 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
4342 if (result != ISC_R_SUCCESS)
4345 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
4346 now, rdataset, 0, NULL);
4347 if (result == ISC_R_SUCCESS)
4348 result = dns_db_addrdataset(fctx->cache, nsnode,
4352 dns_db_detachnode(fctx->cache, &nsnode);
4353 if (result != ISC_R_SUCCESS)
4356 result = dns_message_nextname(fctx->rmessage,
4357 DNS_SECTION_AUTHORITY);
4360 result = ISC_R_SUCCESS;
4363 * Respond with an answer, positive or negative,
4364 * as opposed to an error. 'node' must be non-NULL.
4367 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4369 if (hevent != NULL) {
4370 hevent->result = eresult;
4371 RUNTIME_CHECK(dns_name_copy(vevent->name,
4372 dns_fixedname_name(&hevent->foundname), NULL)
4374 dns_db_attach(fctx->cache, &hevent->db);
4375 dns_db_transfernode(fctx->cache, &node, &hevent->node);
4376 clone_results(fctx);
4381 dns_db_detachnode(fctx->cache, &node);
4383 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4384 fctx_done(fctx, result, __LINE__); /* Locks bucket. */
4387 INSIST(node == NULL);
4388 isc_event_free(&event);
4391 static inline isc_result_t
4392 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
4395 dns_rdataset_t *rdataset, *sigrdataset;
4396 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
4397 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
4398 dns_dbnode_t *node, **anodep;
4401 dns_resolver_t *res;
4402 isc_boolean_t need_validation, secure_domain, have_answer;
4403 isc_result_t result, eresult;
4404 dns_fetchevent_t *event;
4405 unsigned int options;
4408 unsigned int valoptions = 0;
4411 * The appropriate bucket lock must be held.
4415 need_validation = ISC_FALSE;
4416 POST(need_validation);
4417 secure_domain = ISC_FALSE;
4418 have_answer = ISC_FALSE;
4419 eresult = ISC_R_SUCCESS;
4420 task = res->buckets[fctx->bucketnum].task;
4423 * Is DNSSEC validation required for this name?
4425 if (res->view->enablevalidation) {
4426 result = dns_view_issecuredomain(res->view, name,
4428 if (result != ISC_R_SUCCESS)
4431 if (!secure_domain && res->view->dlv != NULL) {
4432 valoptions = DNS_VALIDATOR_DLV;
4433 secure_domain = ISC_TRUE;
4437 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4438 need_validation = ISC_FALSE;
4440 need_validation = secure_domain;
4446 asigrdataset = NULL;
4448 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
4450 have_answer = ISC_TRUE;
4451 event = ISC_LIST_HEAD(fctx->events);
4452 if (event != NULL) {
4454 aname = dns_fixedname_name(&event->foundname);
4455 result = dns_name_copy(name, aname, NULL);
4456 if (result != ISC_R_SUCCESS)
4458 anodep = &event->node;
4460 * If this is an ANY, SIG or RRSIG query, we're not
4461 * going to return any rdatasets, unless we encountered
4462 * a CNAME or DNAME as "the answer". In this case,
4463 * we're going to return DNS_R_CNAME or DNS_R_DNAME
4464 * and we must set up the rdatasets.
4466 if ((fctx->type != dns_rdatatype_any &&
4467 fctx->type != dns_rdatatype_rrsig &&
4468 fctx->type != dns_rdatatype_sig) ||
4469 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
4470 ardataset = event->rdataset;
4471 asigrdataset = event->sigrdataset;
4477 * Find or create the cache node.
4480 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4481 if (result != ISC_R_SUCCESS)
4485 * Cache or validate each cacheable rdataset.
4487 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
4488 for (rdataset = ISC_LIST_HEAD(name->list);
4490 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4491 if (!CACHE(rdataset))
4493 if (CHECKNAMES(rdataset)) {
4494 char namebuf[DNS_NAME_FORMATSIZE];
4495 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4496 char classbuf[DNS_RDATATYPE_FORMATSIZE];
4498 dns_name_format(name, namebuf, sizeof(namebuf));
4499 dns_rdatatype_format(rdataset->type, typebuf,
4501 dns_rdataclass_format(rdataset->rdclass, classbuf,
4503 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
4504 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
4505 "check-names %s %s/%s/%s",
4506 fail ? "failure" : "warning",
4507 namebuf, typebuf, classbuf);
4509 if (ANSWER(rdataset)) {
4510 dns_db_detachnode(fctx->cache, &node);
4511 return (DNS_R_BADNAME);
4518 * Enforce the configure maximum cache TTL.
4520 if (rdataset->ttl > res->view->maxcachettl)
4521 rdataset->ttl = res->view->maxcachettl;
4524 * If this RRset is in a secure domain, is in bailiwick,
4525 * and is not glue, attempt DNSSEC validation. (We do not
4526 * attempt to validate glue or out-of-bailiwick data--even
4527 * though there might be some performance benefit to doing
4528 * so--because it makes it simpler and safer to ensure that
4529 * records from a secure domain are only cached if validated
4530 * within the context of a query to the domain that owns
4533 if (secure_domain && rdataset->trust != dns_trust_glue &&
4534 !EXTERNAL(rdataset)) {
4538 * RRSIGs are validated as part of validating the
4541 if (rdataset->type == dns_rdatatype_rrsig)
4544 * Find the SIG for this rdataset, if we have it.
4546 for (sigrdataset = ISC_LIST_HEAD(name->list);
4547 sigrdataset != NULL;
4548 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
4549 if (sigrdataset->type == dns_rdatatype_rrsig &&
4550 sigrdataset->covers == rdataset->type)
4553 if (sigrdataset == NULL) {
4554 if (!ANSWER(rdataset) && need_validation) {
4556 * Ignore non-answer rdatasets that
4557 * are missing signatures.
4564 * Normalize the rdataset and sigrdataset TTLs.
4566 if (sigrdataset != NULL) {
4567 rdataset->ttl = ISC_MIN(rdataset->ttl,
4569 sigrdataset->ttl = rdataset->ttl;
4573 * Cache this rdataset/sigrdataset pair as
4574 * pending data. Track whether it was additional
4577 if (rdataset->trust == dns_trust_additional)
4578 trust = dns_trust_pending_additional;
4580 trust = dns_trust_pending_answer;
4582 rdataset->trust = trust;
4583 if (sigrdataset != NULL)
4584 sigrdataset->trust = trust;
4585 if (!need_validation || !ANSWER(rdataset)) {
4586 addedrdataset = ardataset;
4587 result = dns_db_addrdataset(fctx->cache, node,
4588 NULL, now, rdataset,
4590 if (result == DNS_R_UNCHANGED) {
4591 result = ISC_R_SUCCESS;
4592 if (!need_validation &&
4593 ardataset != NULL &&
4594 NEGATIVE(ardataset)) {
4596 * The answer in the cache is
4597 * better than the answer we
4598 * found, and is a negative
4599 * cache entry, so we must set
4600 * eresult appropriately.
4602 if (NXDOMAIN(ardataset))
4604 DNS_R_NCACHENXDOMAIN;
4607 DNS_R_NCACHENXRRSET;
4609 * We have a negative response
4610 * from the cache so don't
4611 * attempt to add the RRSIG
4617 if (result != ISC_R_SUCCESS)
4619 if (sigrdataset != NULL) {
4620 addedrdataset = asigrdataset;
4621 result = dns_db_addrdataset(fctx->cache,
4625 if (result == DNS_R_UNCHANGED)
4626 result = ISC_R_SUCCESS;
4627 if (result != ISC_R_SUCCESS)
4629 } else if (!ANSWER(rdataset))
4633 if (ANSWER(rdataset) && need_validation) {
4634 if (fctx->type != dns_rdatatype_any &&
4635 fctx->type != dns_rdatatype_rrsig &&
4636 fctx->type != dns_rdatatype_sig) {
4638 * This is The Answer. We will
4639 * validate it, but first we cache
4640 * the rest of the response - it may
4641 * contain useful keys.
4643 INSIST(valrdataset == NULL &&
4644 valsigrdataset == NULL);
4645 valrdataset = rdataset;
4646 valsigrdataset = sigrdataset;
4649 * This is one of (potentially)
4650 * multiple answers to an ANY
4651 * or SIG query. To keep things
4652 * simple, we just start the
4653 * validator right away rather
4654 * than caching first and
4655 * having to remember which
4656 * rdatasets needed validation.
4658 result = valcreate(fctx, addrinfo,
4659 name, rdataset->type,
4664 * Defer any further validations.
4665 * This prevents multiple validators
4666 * from manipulating fctx->rmessage
4669 valoptions |= DNS_VALIDATOR_DEFER;
4671 } else if (CHAINING(rdataset)) {
4672 if (rdataset->type == dns_rdatatype_cname)
4673 eresult = DNS_R_CNAME;
4675 INSIST(rdataset->type ==
4676 dns_rdatatype_dname);
4677 eresult = DNS_R_DNAME;
4680 } else if (!EXTERNAL(rdataset)) {
4682 * It's OK to cache this rdataset now.
4684 if (ANSWER(rdataset))
4685 addedrdataset = ardataset;
4686 else if (ANSWERSIG(rdataset))
4687 addedrdataset = asigrdataset;
4689 addedrdataset = NULL;
4690 if (CHAINING(rdataset)) {
4691 if (rdataset->type == dns_rdatatype_cname)
4692 eresult = DNS_R_CNAME;
4694 INSIST(rdataset->type ==
4695 dns_rdatatype_dname);
4696 eresult = DNS_R_DNAME;
4699 if (rdataset->trust == dns_trust_glue &&
4700 (rdataset->type == dns_rdatatype_ns ||
4701 (rdataset->type == dns_rdatatype_rrsig &&
4702 rdataset->covers == dns_rdatatype_ns))) {
4704 * If the trust level is 'dns_trust_glue'
4705 * then we are adding data from a referral
4706 * we got while executing the search algorithm.
4707 * New referral data always takes precedence
4708 * over the existing cache contents.
4710 options = DNS_DBADD_FORCE;
4714 * Now we can add the rdataset.
4716 result = dns_db_addrdataset(fctx->cache,
4721 if (result == DNS_R_UNCHANGED) {
4722 if (ANSWER(rdataset) &&
4723 ardataset != NULL &&
4724 NEGATIVE(ardataset)) {
4726 * The answer in the cache is better
4727 * than the answer we found, and is
4728 * a negative cache entry, so we
4729 * must set eresult appropriately.
4731 if (NXDOMAIN(ardataset))
4732 eresult = DNS_R_NCACHENXDOMAIN;
4734 eresult = DNS_R_NCACHENXRRSET;
4736 result = ISC_R_SUCCESS;
4737 } else if (result != ISC_R_SUCCESS)
4742 if (valrdataset != NULL)
4743 result = valcreate(fctx, addrinfo, name, fctx->type,
4744 valrdataset, valsigrdataset, valoptions,
4747 if (result == ISC_R_SUCCESS && have_answer) {
4748 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4749 if (event != NULL) {
4751 * Negative results must be indicated in event->result.
4753 if (dns_rdataset_isassociated(event->rdataset) &&
4754 NEGATIVE(event->rdataset)) {
4755 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
4756 eresult == DNS_R_NCACHENXRRSET);
4758 event->result = eresult;
4759 dns_db_attach(fctx->cache, adbp);
4760 dns_db_transfernode(fctx->cache, &node, anodep);
4761 clone_results(fctx);
4766 dns_db_detachnode(fctx->cache, &node);
4771 static inline isc_result_t
4772 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
4774 isc_result_t result;
4775 dns_section_t section;
4778 FCTXTRACE("cache_message");
4780 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
4782 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4784 for (section = DNS_SECTION_ANSWER;
4785 section <= DNS_SECTION_ADDITIONAL;
4787 result = dns_message_firstname(fctx->rmessage, section);
4788 while (result == ISC_R_SUCCESS) {
4790 dns_message_currentname(fctx->rmessage, section,
4792 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
4793 result = cache_name(fctx, name, addrinfo, now);
4794 if (result != ISC_R_SUCCESS)
4797 result = dns_message_nextname(fctx->rmessage, section);
4799 if (result != ISC_R_NOMORE)
4802 if (result == ISC_R_NOMORE)
4803 result = ISC_R_SUCCESS;
4805 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4811 * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
4814 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
4815 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
4816 isc_boolean_t optout, dns_rdataset_t *ardataset,
4817 isc_result_t *eresultp)
4819 isc_result_t result;
4820 dns_rdataset_t rdataset;
4822 if (ardataset == NULL) {
4823 dns_rdataset_init(&rdataset);
4824 ardataset = &rdataset;
4826 result = dns_ncache_addoptout(message, cache, node, covers, now,
4827 maxttl, optout, ardataset);
4828 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
4830 * If the cache now contains a negative entry and we
4831 * care about whether it is DNS_R_NCACHENXDOMAIN or
4832 * DNS_R_NCACHENXRRSET then extract it.
4834 if (NEGATIVE(ardataset)) {
4836 * The cache data is a negative cache entry.
4838 if (NXDOMAIN(ardataset))
4839 *eresultp = DNS_R_NCACHENXDOMAIN;
4841 *eresultp = DNS_R_NCACHENXRRSET;
4844 * Either we don't care about the nature of the
4845 * cache rdataset (because no fetch is interested
4846 * in the outcome), or the cache rdataset is not
4847 * a negative cache entry. Whichever case it is,
4848 * we can return success.
4850 * XXXRTH There's a CNAME/DNAME problem here.
4852 *eresultp = ISC_R_SUCCESS;
4854 result = ISC_R_SUCCESS;
4856 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
4857 dns_rdataset_disassociate(ardataset);
4862 static inline isc_result_t
4863 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
4864 dns_rdatatype_t covers, isc_stdtime_t now)
4866 isc_result_t result, eresult;
4868 dns_resolver_t *res;
4870 dns_dbnode_t *node, **anodep;
4871 dns_rdataset_t *ardataset;
4872 isc_boolean_t need_validation, secure_domain;
4874 dns_fetchevent_t *event;
4876 unsigned int valoptions = 0;
4878 FCTXTRACE("ncache_message");
4880 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
4883 need_validation = ISC_FALSE;
4884 POST(need_validation);
4885 secure_domain = ISC_FALSE;
4886 eresult = ISC_R_SUCCESS;
4891 * XXXMPA remove when we follow cnames and adjust the setting
4892 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4894 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
4897 * Is DNSSEC validation required for this name?
4899 if (fctx->res->view->enablevalidation) {
4900 result = dns_view_issecuredomain(res->view, name,
4902 if (result != ISC_R_SUCCESS)
4905 if (!secure_domain && res->view->dlv != NULL) {
4906 valoptions = DNS_VALIDATOR_DLV;
4907 secure_domain = ISC_TRUE;
4911 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4912 need_validation = ISC_FALSE;
4914 need_validation = secure_domain;
4916 if (secure_domain) {
4918 * Mark all rdatasets as pending.
4920 dns_rdataset_t *trdataset;
4923 result = dns_message_firstname(fctx->rmessage,
4924 DNS_SECTION_AUTHORITY);
4925 while (result == ISC_R_SUCCESS) {
4927 dns_message_currentname(fctx->rmessage,
4928 DNS_SECTION_AUTHORITY,
4930 for (trdataset = ISC_LIST_HEAD(tname->list);
4932 trdataset = ISC_LIST_NEXT(trdataset, link))
4933 trdataset->trust = dns_trust_pending_answer;
4934 result = dns_message_nextname(fctx->rmessage,
4935 DNS_SECTION_AUTHORITY);
4937 if (result != ISC_R_NOMORE)
4942 if (need_validation) {
4944 * Do negative response validation.
4946 result = valcreate(fctx, addrinfo, name, fctx->type,
4947 NULL, NULL, valoptions,
4948 res->buckets[fctx->bucketnum].task);
4950 * If validation is necessary, return now. Otherwise continue
4951 * to process the message, letting the validation complete
4952 * in its own good time.
4957 LOCK(&res->buckets[fctx->bucketnum].lock);
4963 if (!HAVE_ANSWER(fctx)) {
4964 event = ISC_LIST_HEAD(fctx->events);
4965 if (event != NULL) {
4967 aname = dns_fixedname_name(&event->foundname);
4968 result = dns_name_copy(name, aname, NULL);
4969 if (result != ISC_R_SUCCESS)
4971 anodep = &event->node;
4972 ardataset = event->rdataset;
4977 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4978 if (result != ISC_R_SUCCESS)
4982 * If we are asking for a SOA record set the cache time
4983 * to zero to facilitate locating the containing zone of
4986 ttl = fctx->res->view->maxncachettl;
4987 if (fctx->type == dns_rdatatype_soa &&
4988 covers == dns_rdatatype_any &&
4989 fctx->res->zero_no_soa_ttl)
4992 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4993 covers, now, ttl, ISC_FALSE,
4994 ardataset, &eresult);
4995 if (result != ISC_R_SUCCESS)
4998 if (!HAVE_ANSWER(fctx)) {
4999 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
5000 if (event != NULL) {
5001 event->result = eresult;
5002 dns_db_attach(fctx->cache, adbp);
5003 dns_db_transfernode(fctx->cache, &node, anodep);
5004 clone_results(fctx);
5009 UNLOCK(&res->buckets[fctx->bucketnum].lock);
5012 dns_db_detachnode(fctx->cache, &node);
5018 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
5019 isc_boolean_t external, isc_boolean_t gluing)
5021 name->attributes |= DNS_NAMEATTR_CACHE;
5023 rdataset->trust = dns_trust_glue;
5025 * Glue with 0 TTL causes problems. We force the TTL to
5026 * 1 second to prevent this.
5028 if (rdataset->ttl == 0)
5031 rdataset->trust = dns_trust_additional;
5033 * Avoid infinite loops by only marking new rdatasets.
5035 if (!CACHE(rdataset)) {
5036 name->attributes |= DNS_NAMEATTR_CHASE;
5037 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
5039 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
5041 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
5045 check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
5046 dns_section_t section)
5048 fetchctx_t *fctx = arg;
5049 isc_result_t result;
5051 dns_rdataset_t *rdataset;
5052 isc_boolean_t external;
5053 dns_rdatatype_t rtype;
5054 isc_boolean_t gluing;
5056 REQUIRE(VALID_FCTX(fctx));
5058 #if CHECK_FOR_GLUE_IN_ANSWER
5059 if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
5060 return (ISC_R_SUCCESS);
5069 result = dns_message_findname(fctx->rmessage, section, addname,
5070 dns_rdatatype_any, 0, &name, NULL);
5071 if (result == ISC_R_SUCCESS) {
5072 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5073 if (type == dns_rdatatype_a) {
5074 for (rdataset = ISC_LIST_HEAD(name->list);
5076 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5077 if (rdataset->type == dns_rdatatype_rrsig)
5078 rtype = rdataset->covers;
5080 rtype = rdataset->type;
5081 if (rtype == dns_rdatatype_a ||
5082 rtype == dns_rdatatype_aaaa)
5083 mark_related(name, rdataset, external,
5087 result = dns_message_findtype(name, type, 0,
5089 if (result == ISC_R_SUCCESS) {
5090 mark_related(name, rdataset, external, gluing);
5092 * Do we have its SIG too?
5095 result = dns_message_findtype(name,
5096 dns_rdatatype_rrsig,
5098 if (result == ISC_R_SUCCESS)
5099 mark_related(name, rdataset, external,
5105 return (ISC_R_SUCCESS);
5109 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5110 return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
5113 #ifndef CHECK_FOR_GLUE_IN_ANSWER
5114 #define CHECK_FOR_GLUE_IN_ANSWER 0
5116 #if CHECK_FOR_GLUE_IN_ANSWER
5118 check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
5119 return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
5124 chase_additional(fetchctx_t *fctx) {
5125 isc_boolean_t rescan;
5126 dns_section_t section = DNS_SECTION_ADDITIONAL;
5127 isc_result_t result;
5132 for (result = dns_message_firstname(fctx->rmessage, section);
5133 result == ISC_R_SUCCESS;
5134 result = dns_message_nextname(fctx->rmessage, section)) {
5135 dns_name_t *name = NULL;
5136 dns_rdataset_t *rdataset;
5137 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
5139 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
5141 name->attributes &= ~DNS_NAMEATTR_CHASE;
5142 for (rdataset = ISC_LIST_HEAD(name->list);
5144 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5145 if (CHASE(rdataset)) {
5146 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
5147 (void)dns_rdataset_additionaldata(rdataset,
5158 static inline isc_result_t
5159 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
5160 isc_result_t result;
5161 dns_rdata_t rdata = DNS_RDATA_INIT;
5162 dns_rdata_cname_t cname;
5164 result = dns_rdataset_first(rdataset);
5165 if (result != ISC_R_SUCCESS)
5167 dns_rdataset_current(rdataset, &rdata);
5168 result = dns_rdata_tostruct(&rdata, &cname, NULL);
5169 if (result != ISC_R_SUCCESS)
5171 dns_name_init(tname, NULL);
5172 dns_name_clone(&cname.cname, tname);
5173 dns_rdata_freestruct(&cname);
5175 return (ISC_R_SUCCESS);
5178 static inline isc_result_t
5179 dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
5180 dns_name_t *oname, dns_fixedname_t *fixeddname)
5182 isc_result_t result;
5183 dns_rdata_t rdata = DNS_RDATA_INIT;
5184 unsigned int nlabels;
5186 dns_namereln_t namereln;
5187 dns_rdata_dname_t dname;
5188 dns_fixedname_t prefix;
5191 * Get the target name of the DNAME.
5193 result = dns_rdataset_first(rdataset);
5194 if (result != ISC_R_SUCCESS)
5196 dns_rdataset_current(rdataset, &rdata);
5197 result = dns_rdata_tostruct(&rdata, &dname, NULL);
5198 if (result != ISC_R_SUCCESS)
5202 * Get the prefix of qname.
5204 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
5205 if (namereln != dns_namereln_subdomain) {
5206 char qbuf[DNS_NAME_FORMATSIZE];
5207 char obuf[DNS_NAME_FORMATSIZE];
5209 dns_rdata_freestruct(&dname);
5210 dns_name_format(qname, qbuf, sizeof(qbuf));
5211 dns_name_format(oname, obuf, sizeof(obuf));
5212 log_formerr(fctx, "unrelated DNAME in answer: "
5213 "%s is not in %s", qbuf, obuf);
5214 return (DNS_R_FORMERR);
5216 dns_fixedname_init(&prefix);
5217 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
5218 dns_fixedname_init(fixeddname);
5219 result = dns_name_concatenate(dns_fixedname_name(&prefix),
5221 dns_fixedname_name(fixeddname), NULL);
5222 dns_rdata_freestruct(&dname);
5226 static isc_boolean_t
5227 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
5228 dns_rdataset_t *rdataset)
5230 isc_result_t result;
5231 dns_rdata_t rdata = DNS_RDATA_INIT;
5233 struct in6_addr in6a;
5234 isc_netaddr_t netaddr;
5235 char addrbuf[ISC_NETADDR_FORMATSIZE];
5236 char namebuf[DNS_NAME_FORMATSIZE];
5241 /* By default, we allow any addresses. */
5242 if (view->denyansweracl == NULL)
5246 * If the owner name matches one in the exclusion list, either exactly
5247 * or partially, allow it.
5249 if (view->answeracl_exclude != NULL) {
5250 dns_rbtnode_t *node = NULL;
5252 result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
5253 &node, NULL, 0, NULL, NULL);
5255 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5260 * Otherwise, search the filter list for a match for each address
5261 * record. If a match is found, the address should be filtered,
5262 * so should the entire answer.
5264 for (result = dns_rdataset_first(rdataset);
5265 result == ISC_R_SUCCESS;
5266 result = dns_rdataset_next(rdataset)) {
5267 dns_rdata_reset(&rdata);
5268 dns_rdataset_current(rdataset, &rdata);
5269 if (rdataset->type == dns_rdatatype_a) {
5270 INSIST(rdata.length == sizeof(ina.s_addr));
5271 memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
5272 isc_netaddr_fromin(&netaddr, &ina);
5274 INSIST(rdata.length == sizeof(in6a.s6_addr));
5275 memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
5276 isc_netaddr_fromin6(&netaddr, &in6a);
5279 result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
5280 &view->aclenv, &match, NULL);
5282 if (result == ISC_R_SUCCESS && match > 0) {
5283 isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
5284 dns_name_format(name, namebuf, sizeof(namebuf));
5285 dns_rdatatype_format(rdataset->type, typebuf,
5287 dns_rdataclass_format(rdataset->rdclass, classbuf,
5289 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5290 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5291 "answer address %s denied for %s/%s/%s",
5292 addrbuf, namebuf, typebuf, classbuf);
5300 static isc_boolean_t
5301 is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
5302 dns_rdatatype_t type, dns_name_t *tname,
5305 isc_result_t result;
5306 dns_rbtnode_t *node = NULL;
5307 char qnamebuf[DNS_NAME_FORMATSIZE];
5308 char tnamebuf[DNS_NAME_FORMATSIZE];
5312 /* By default, we allow any target name. */
5313 if (view->denyanswernames == NULL)
5317 * If the owner name matches one in the exclusion list, either exactly
5318 * or partially, allow it.
5320 if (view->answernames_exclude != NULL) {
5321 result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
5322 &node, NULL, 0, NULL, NULL);
5323 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
5328 * If the target name is a subdomain of the search domain, allow it.
5330 if (dns_name_issubdomain(tname, domain))
5334 * Otherwise, apply filters.
5336 result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
5337 NULL, 0, NULL, NULL);
5338 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
5339 dns_name_format(name, qnamebuf, sizeof(qnamebuf));
5340 dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
5341 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
5342 dns_rdataclass_format(view->rdclass, classbuf,
5344 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5345 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5346 "%s target %s denied for %s/%s",
5347 typebuf, tnamebuf, qnamebuf, classbuf);
5355 trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
5356 char ns_namebuf[DNS_NAME_FORMATSIZE];
5357 char namebuf[DNS_NAME_FORMATSIZE];
5358 char tbuf[DNS_RDATATYPE_FORMATSIZE];
5360 if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
5361 dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
5362 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
5363 dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
5365 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5366 DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
5367 "fctx %p: trimming ttl of %s/NS for %s/%s: "
5368 "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
5369 rdataset->ttl, fctx->ns_ttl);
5370 rdataset->ttl = fctx->ns_ttl;
5375 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
5376 * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
5377 * section for the NS RRset if the query type is NS; if it has
5378 * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
5379 * section for A and AAAA queries.
5381 #define LOOK_FOR_NS_IN_ANSWER 0x1
5382 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
5385 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
5386 unsigned int look_in_options)
5388 isc_result_t result;
5389 dns_message_t *message;
5390 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
5391 dns_rdataset_t *rdataset, *ns_rdataset;
5392 isc_boolean_t aa, negative_response;
5393 dns_rdatatype_t type;
5394 dns_section_t section;
5396 FCTXTRACE("noanswer_response");
5398 if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
5399 INSIST(fctx->type == dns_rdatatype_ns);
5400 section = DNS_SECTION_ANSWER;
5402 section = DNS_SECTION_AUTHORITY;
5404 message = fctx->rmessage;
5409 if (oqname == NULL) {
5411 * We have a normal, non-chained negative response or
5414 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5418 qname = &fctx->name;
5421 * We're being invoked by answer_response() after it has
5422 * followed a CNAME/DNAME chain.
5427 * If the current qname is not a subdomain of the query
5428 * domain, there's no point in looking at the authority
5429 * section without doing DNSSEC validation.
5431 * Until we do that validation, we'll just return success
5434 if (!dns_name_issubdomain(qname, &fctx->domain))
5435 return (ISC_R_SUCCESS);
5439 * We have to figure out if this is a negative response, or a
5444 * Sometimes we can tell if its a negative response by looking at
5445 * the message header.
5447 negative_response = ISC_FALSE;
5448 if (message->rcode == dns_rcode_nxdomain ||
5449 (message->counts[DNS_SECTION_ANSWER] == 0 &&
5450 message->counts[DNS_SECTION_AUTHORITY] == 0))
5451 negative_response = ISC_TRUE;
5454 * Process the authority section.
5460 result = dns_message_firstname(message, section);
5461 while (result == ISC_R_SUCCESS) {
5463 dns_message_currentname(message, section, &name);
5464 if (dns_name_issubdomain(name, &fctx->domain)) {
5466 * Look for NS/SOA RRsets first.
5468 for (rdataset = ISC_LIST_HEAD(name->list);
5470 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5471 type = rdataset->type;
5472 if (type == dns_rdatatype_rrsig)
5473 type = rdataset->covers;
5474 if (((type == dns_rdatatype_ns ||
5475 type == dns_rdatatype_soa) &&
5476 !dns_name_issubdomain(qname, name))) {
5477 char qbuf[DNS_NAME_FORMATSIZE];
5478 char nbuf[DNS_NAME_FORMATSIZE];
5479 char tbuf[DNS_RDATATYPE_FORMATSIZE];
5480 dns_rdatatype_format(fctx->type, tbuf,
5482 dns_name_format(name, nbuf,
5484 dns_name_format(qname, qbuf,
5487 "unrelated %s %s in "
5488 "%s authority section",
5490 return (DNS_R_FORMERR);
5492 if (type == dns_rdatatype_ns) {
5496 * Only one set of NS RRs is allowed.
5498 if (rdataset->type ==
5500 if (ns_name != NULL &&
5507 return (DNS_R_FORMERR);
5510 ns_rdataset = rdataset;
5514 rdataset->attributes |=
5515 DNS_RDATASETATTR_CACHE;
5516 rdataset->trust = dns_trust_glue;
5518 if (type == dns_rdatatype_soa) {
5520 * SOA, or RRSIG SOA.
5522 * Only one SOA is allowed.
5524 if (rdataset->type ==
5525 dns_rdatatype_soa) {
5526 if (soa_name != NULL &&
5533 return (DNS_R_FORMERR);
5538 DNS_NAMEATTR_NCACHE;
5539 rdataset->attributes |=
5540 DNS_RDATASETATTR_NCACHE;
5543 dns_trust_authauthority;
5544 else if (ISFORWARDER(fctx->addrinfo))
5549 dns_trust_additional;
5553 result = dns_message_nextname(message, section);
5554 if (result == ISC_R_NOMORE)
5556 else if (result != ISC_R_SUCCESS)
5560 log_ns_ttl(fctx, "noanswer_response");
5562 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
5563 !dns_name_equal(ns_name, dns_rootname))
5564 trim_ns_ttl(fctx, ns_name, ns_rdataset);
5567 * A negative response has a SOA record (Type 2)
5568 * and a optional NS RRset (Type 1) or it has neither
5569 * a SOA or a NS RRset (Type 3, handled above) or
5570 * rcode is NXDOMAIN (handled above) in which case
5571 * the NS RRset is allowed (Type 4).
5573 if (soa_name != NULL)
5574 negative_response = ISC_TRUE;
5576 result = dns_message_firstname(message, section);
5577 while (result == ISC_R_SUCCESS) {
5579 dns_message_currentname(message, section, &name);
5580 if (dns_name_issubdomain(name, &fctx->domain)) {
5581 for (rdataset = ISC_LIST_HEAD(name->list);
5583 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5584 type = rdataset->type;
5585 if (type == dns_rdatatype_rrsig)
5586 type = rdataset->covers;
5587 if (type == dns_rdatatype_nsec ||
5588 type == dns_rdatatype_nsec3) {
5590 * NSEC or RRSIG NSEC.
5592 if (negative_response) {
5594 DNS_NAMEATTR_NCACHE;
5595 rdataset->attributes |=
5596 DNS_RDATASETATTR_NCACHE;
5597 } else if (type == dns_rdatatype_nsec) {
5600 rdataset->attributes |=
5601 DNS_RDATASETATTR_CACHE;
5605 dns_trust_authauthority;
5606 else if (ISFORWARDER(fctx->addrinfo))
5611 dns_trust_additional;
5613 * No additional data needs to be
5616 } else if (type == dns_rdatatype_ds) {
5620 * These should only be here if
5621 * this is a referral, and there
5622 * should only be one DS RRset.
5624 if (ns_name == NULL) {
5628 return (DNS_R_FORMERR);
5630 if (rdataset->type ==
5632 if (ds_name != NULL &&
5639 return (DNS_R_FORMERR);
5645 rdataset->attributes |=
5646 DNS_RDATASETATTR_CACHE;
5649 dns_trust_authauthority;
5650 else if (ISFORWARDER(fctx->addrinfo))
5655 dns_trust_additional;
5659 result = dns_message_nextname(message, section);
5660 if (result == ISC_R_NOMORE)
5662 else if (result != ISC_R_SUCCESS)
5667 * Trigger lookups for DNS nameservers.
5669 if (negative_response && message->rcode == dns_rcode_noerror &&
5670 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
5671 dns_name_equal(soa_name, qname) &&
5672 !dns_name_equal(qname, dns_rootname))
5673 return (DNS_R_CHASEDSSERVERS);
5676 * Did we find anything?
5678 if (!negative_response && ns_name == NULL) {
5682 if (oqname != NULL) {
5684 * We've already got a partial CNAME/DNAME chain,
5685 * and haven't found else anything useful here, but
5686 * no error has occurred since we have an answer.
5688 return (ISC_R_SUCCESS);
5691 * The responder is insane.
5693 log_formerr(fctx, "invalid response");
5694 return (DNS_R_FORMERR);
5699 * If we found both NS and SOA, they should be the same name.
5701 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
5702 log_formerr(fctx, "NS/SOA mismatch");
5703 return (DNS_R_FORMERR);
5707 * Do we have a referral? (We only want to follow a referral if
5708 * we're not following a chain.)
5710 if (!negative_response && ns_name != NULL && oqname == NULL) {
5712 * We already know ns_name is a subdomain of fctx->domain.
5713 * If ns_name is equal to fctx->domain, we're not making
5714 * progress. We return DNS_R_FORMERR so that we'll keep
5715 * trying other servers.
5717 if (dns_name_equal(ns_name, &fctx->domain)) {
5718 log_formerr(fctx, "non-improving referral");
5719 return (DNS_R_FORMERR);
5723 * If the referral name is not a parent of the query
5724 * name, consider the responder insane.
5726 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
5728 log_formerr(fctx, "referral to non-parent");
5729 FCTXTRACE("referral to non-parent");
5730 return (DNS_R_FORMERR);
5734 * Mark any additional data related to this rdataset.
5735 * It's important that we do this before we change the
5738 INSIST(ns_rdataset != NULL);
5739 fctx->attributes |= FCTX_ATTR_GLUING;
5740 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
5742 #if CHECK_FOR_GLUE_IN_ANSWER
5744 * Look in the answer section for "glue" that is incorrectly
5745 * returned as a answer. This is needed if the server also
5746 * minimizes the response size by not adding records to the
5747 * additional section that are in the answer section or if
5748 * the record gets dropped due to message size constraints.
5750 if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
5751 (fctx->type == dns_rdatatype_aaaa ||
5752 fctx->type == dns_rdatatype_a))
5753 (void)dns_rdataset_additionaldata(ns_rdataset,
5754 check_answer, fctx);
5756 fctx->attributes &= ~FCTX_ATTR_GLUING;
5758 * NS rdatasets with 0 TTL cause problems.
5759 * dns_view_findzonecut() will not find them when we
5760 * try to follow the referral, and we'll SERVFAIL
5761 * because the best nameservers are now above QDOMAIN.
5762 * We force the TTL to 1 second to prevent this.
5764 if (ns_rdataset->ttl == 0)
5765 ns_rdataset->ttl = 1;
5767 * Set the current query domain to the referral name.
5769 * XXXRTH We should check if we're in forward-only mode, and
5770 * if so we should bail out.
5772 INSIST(dns_name_countlabels(&fctx->domain) > 0);
5773 dns_name_free(&fctx->domain, fctx->mctx);
5774 if (dns_rdataset_isassociated(&fctx->nameservers))
5775 dns_rdataset_disassociate(&fctx->nameservers);
5776 dns_name_init(&fctx->domain, NULL);
5777 result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
5778 if (result != ISC_R_SUCCESS)
5780 fctx->attributes |= FCTX_ATTR_WANTCACHE;
5781 fctx->ns_ttl_ok = ISC_FALSE;
5782 log_ns_ttl(fctx, "DELEGATION");
5783 return (DNS_R_DELEGATION);
5787 * Since we're not doing a referral, we don't want to cache any
5788 * NS RRs we may have found.
5790 if (ns_name != NULL)
5791 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
5793 if (negative_response && oqname == NULL)
5794 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
5796 return (ISC_R_SUCCESS);
5800 answer_response(fetchctx_t *fctx) {
5801 isc_result_t result;
5802 dns_message_t *message;
5803 dns_name_t *name, *qname, tname, *ns_name;
5804 dns_rdataset_t *rdataset, *ns_rdataset;
5805 isc_boolean_t done, external, chaining, aa, found, want_chaining;
5806 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
5808 dns_rdatatype_t type;
5809 dns_fixedname_t dname, fqname;
5812 FCTXTRACE("answer_response");
5814 message = fctx->rmessage;
5817 * Examine the answer section, marking those rdatasets which are
5818 * part of the answer and should be cached.
5822 found_cname = ISC_FALSE;
5823 found_type = ISC_FALSE;
5824 chaining = ISC_FALSE;
5825 have_answer = ISC_FALSE;
5826 want_chaining = ISC_FALSE;
5827 POST(want_chaining);
5828 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
5832 qname = &fctx->name;
5834 view = fctx->res->view;
5835 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
5836 while (!done && result == ISC_R_SUCCESS) {
5838 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
5839 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5840 if (dns_name_equal(name, qname)) {
5841 wanted_chaining = ISC_FALSE;
5842 for (rdataset = ISC_LIST_HEAD(name->list);
5844 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5846 want_chaining = ISC_FALSE;
5848 if (rdataset->type == dns_rdatatype_nsec3) {
5850 * NSEC3 records are not allowed to
5851 * appear in the answer section.
5853 log_formerr(fctx, "NSEC3 in answer");
5854 return (DNS_R_FORMERR);
5858 * Apply filters, if given, on answers to reject
5859 * a malicious attempt of rebinding.
5861 if ((rdataset->type == dns_rdatatype_a ||
5862 rdataset->type == dns_rdatatype_aaaa) &&
5863 !is_answeraddress_allowed(view, name,
5865 return (DNS_R_SERVFAIL);
5868 if (rdataset->type == type && !found_cname) {
5870 * We've found an ordinary answer.
5873 found_type = ISC_TRUE;
5875 aflag = DNS_RDATASETATTR_ANSWER;
5876 } else if (type == dns_rdatatype_any) {
5878 * We've found an answer matching
5879 * an ANY query. There may be
5883 aflag = DNS_RDATASETATTR_ANSWER;
5884 } else if (rdataset->type == dns_rdatatype_rrsig
5885 && rdataset->covers == type
5888 * We've found a signature that
5889 * covers the type we're looking for.
5892 found_type = ISC_TRUE;
5893 aflag = DNS_RDATASETATTR_ANSWERSIG;
5894 } else if (rdataset->type ==
5898 * We're looking for something else,
5899 * but we found a CNAME.
5901 * Getting a CNAME response for some
5902 * query types is an error.
5904 if (type == dns_rdatatype_rrsig ||
5905 type == dns_rdatatype_dnskey ||
5906 type == dns_rdatatype_nsec ||
5907 type == dns_rdatatype_nsec3) {
5908 char buf[DNS_RDATATYPE_FORMATSIZE];
5909 dns_rdatatype_format(fctx->type,
5914 return (DNS_R_FORMERR);
5917 found_cname = ISC_TRUE;
5918 want_chaining = ISC_TRUE;
5919 aflag = DNS_RDATASETATTR_ANSWER;
5920 result = cname_target(rdataset,
5922 if (result != ISC_R_SUCCESS)
5924 /* Apply filters on the target name. */
5925 if (!is_answertarget_allowed(view,
5930 return (DNS_R_SERVFAIL);
5932 } else if (rdataset->type == dns_rdatatype_rrsig
5933 && rdataset->covers ==
5937 * We're looking for something else,
5938 * but we found a SIG CNAME.
5941 found_cname = ISC_TRUE;
5942 aflag = DNS_RDATASETATTR_ANSWERSIG;
5947 * We've found an answer to our
5952 rdataset->attributes |=
5953 DNS_RDATASETATTR_CACHE;
5954 rdataset->trust = dns_trust_answer;
5957 * This data is "the" answer
5958 * to our question only if
5959 * we're not chaining (i.e.
5960 * if we haven't followed
5961 * a CNAME or DNAME).
5965 DNS_RDATASETATTR_ANSWER)
5966 have_answer = ISC_TRUE;
5968 DNS_NAMEATTR_ANSWER;
5969 rdataset->attributes |= aflag;
5972 dns_trust_authanswer;
5973 } else if (external) {
5975 * This data is outside of
5976 * our query domain, and
5977 * may not be cached.
5979 rdataset->attributes |=
5980 DNS_RDATASETATTR_EXTERNAL;
5984 * Mark any additional data related
5987 (void)dns_rdataset_additionaldata(
5995 if (want_chaining) {
5996 wanted_chaining = ISC_TRUE;
5998 DNS_NAMEATTR_CHAINING;
5999 rdataset->attributes |=
6000 DNS_RDATASETATTR_CHAINING;
6005 * We could add an "else" clause here and
6006 * log that we're ignoring this rdataset.
6010 * If wanted_chaining is true, we've done
6011 * some chaining as the result of processing
6012 * this node, and thus we need to set
6015 * We don't set chaining inside of the
6016 * rdataset loop because doing that would
6017 * cause us to ignore the signatures of
6020 if (wanted_chaining)
6021 chaining = ISC_TRUE;
6024 * Look for a DNAME (or its SIG). Anything else is
6027 wanted_chaining = ISC_FALSE;
6028 for (rdataset = ISC_LIST_HEAD(name->list);
6030 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6031 isc_boolean_t found_dname = ISC_FALSE;
6032 dns_name_t *dname_name;
6036 if (rdataset->type == dns_rdatatype_dname) {
6038 * We're looking for something else,
6039 * but we found a DNAME.
6041 * If we're not chaining, then the
6042 * DNAME should not be external.
6044 if (!chaining && external) {
6047 return (DNS_R_FORMERR);
6050 want_chaining = ISC_TRUE;
6051 POST(want_chaining);
6052 aflag = DNS_RDATASETATTR_ANSWER;
6053 result = dname_target(fctx, rdataset,
6056 if (result == ISC_R_NOSPACE) {
6058 * We can't construct the
6059 * DNAME target. Do not
6062 want_chaining = ISC_FALSE;
6063 POST(want_chaining);
6064 } else if (result != ISC_R_SUCCESS)
6067 found_dname = ISC_TRUE;
6069 dname_name = dns_fixedname_name(&dname);
6070 if (!is_answertarget_allowed(view,
6075 return (DNS_R_SERVFAIL);
6077 } else if (rdataset->type == dns_rdatatype_rrsig
6078 && rdataset->covers ==
6079 dns_rdatatype_dname) {
6081 * We've found a signature that
6085 aflag = DNS_RDATASETATTR_ANSWERSIG;
6090 * We've found an answer to our
6095 rdataset->attributes |=
6096 DNS_RDATASETATTR_CACHE;
6097 rdataset->trust = dns_trust_answer;
6100 * This data is "the" answer
6101 * to our question only if
6102 * we're not chaining.
6106 DNS_RDATASETATTR_ANSWER)
6107 have_answer = ISC_TRUE;
6109 DNS_NAMEATTR_ANSWER;
6110 rdataset->attributes |= aflag;
6113 dns_trust_authanswer;
6114 } else if (external) {
6115 rdataset->attributes |=
6116 DNS_RDATASETATTR_EXTERNAL;
6124 * Copy the dname into the
6127 * Although we check for
6128 * failure of the copy
6129 * operation, in practice it
6130 * should never fail since
6131 * we already know that the
6132 * result fits in a fixedname.
6134 dns_fixedname_init(&fqname);
6135 result = dns_name_copy(
6136 dns_fixedname_name(&dname),
6137 dns_fixedname_name(&fqname),
6139 if (result != ISC_R_SUCCESS)
6141 wanted_chaining = ISC_TRUE;
6143 DNS_NAMEATTR_CHAINING;
6144 rdataset->attributes |=
6145 DNS_RDATASETATTR_CHAINING;
6146 qname = dns_fixedname_name(
6151 if (wanted_chaining)
6152 chaining = ISC_TRUE;
6154 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
6156 if (result == ISC_R_NOMORE)
6157 result = ISC_R_SUCCESS;
6158 if (result != ISC_R_SUCCESS)
6162 * We should have found an answer.
6165 log_formerr(fctx, "reply has no answer");
6166 return (DNS_R_FORMERR);
6170 * This response is now potentially cacheable.
6172 fctx->attributes |= FCTX_ATTR_WANTCACHE;
6175 * Did chaining end before we got the final answer?
6179 * Yes. This may be a negative reply, so hand off
6180 * authority section processing to the noanswer code.
6181 * If it isn't a noanswer response, no harm will be
6184 return (noanswer_response(fctx, qname, 0));
6188 * We didn't end with an incomplete chain, so the rcode should be
6191 if (message->rcode != dns_rcode_noerror) {
6192 log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
6194 return (DNS_R_FORMERR);
6198 * Examine the authority section (if there is one).
6200 * We expect there to be only one owner name for all the rdatasets
6201 * in this section, and we expect that it is not external.
6206 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6207 while (!done && result == ISC_R_SUCCESS) {
6209 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6210 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
6213 * We expect to find NS or SIG NS rdatasets, and
6216 for (rdataset = ISC_LIST_HEAD(name->list);
6218 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6219 if (rdataset->type == dns_rdatatype_ns ||
6220 (rdataset->type == dns_rdatatype_rrsig &&
6221 rdataset->covers == dns_rdatatype_ns)) {
6224 rdataset->attributes |=
6225 DNS_RDATASETATTR_CACHE;
6226 if (aa && !chaining)
6228 dns_trust_authauthority;
6231 dns_trust_additional;
6233 if (rdataset->type == dns_rdatatype_ns) {
6235 ns_rdataset = rdataset;
6238 * Mark any additional data related
6241 (void)dns_rdataset_additionaldata(
6249 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
6251 if (result == ISC_R_NOMORE)
6252 result = ISC_R_SUCCESS;
6254 log_ns_ttl(fctx, "answer_response");
6256 if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
6257 !dns_name_equal(ns_name, dns_rootname))
6258 trim_ns_ttl(fctx, ns_name, ns_rdataset);
6263 static isc_boolean_t
6264 fctx_decreference(fetchctx_t *fctx) {
6265 isc_boolean_t bucket_empty = ISC_FALSE;
6267 INSIST(fctx->references > 0);
6269 if (fctx->references == 0) {
6271 * No one cares about the result of this fetch anymore.
6273 if (fctx->pending == 0 && fctx->nqueries == 0 &&
6274 ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
6276 * This fctx is already shutdown; we were just
6277 * waiting for the last reference to go away.
6279 bucket_empty = fctx_unlink(fctx);
6283 * Initiate shutdown.
6285 fctx_shutdown(fctx);
6288 return (bucket_empty);
6292 resume_dslookup(isc_task_t *task, isc_event_t *event) {
6293 dns_fetchevent_t *fevent;
6294 dns_resolver_t *res;
6296 isc_result_t result;
6297 isc_boolean_t bucket_empty;
6298 isc_boolean_t locked = ISC_FALSE;
6299 unsigned int bucketnum;
6300 dns_rdataset_t nameservers;
6301 dns_fixedname_t fixed;
6304 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
6305 fevent = (dns_fetchevent_t *)event;
6306 fctx = event->ev_arg;
6307 REQUIRE(VALID_FCTX(fctx));
6311 FCTXTRACE("resume_dslookup");
6313 if (fevent->node != NULL)
6314 dns_db_detachnode(fevent->db, &fevent->node);
6315 if (fevent->db != NULL)
6316 dns_db_detach(&fevent->db);
6318 dns_rdataset_init(&nameservers);
6320 bucketnum = fctx->bucketnum;
6321 if (fevent->result == ISC_R_CANCELED) {
6322 dns_resolver_destroyfetch(&fctx->nsfetch);
6323 fctx_done(fctx, ISC_R_CANCELED, __LINE__);
6324 } else if (fevent->result == ISC_R_SUCCESS) {
6326 FCTXTRACE("resuming DS lookup");
6328 dns_resolver_destroyfetch(&fctx->nsfetch);
6329 if (dns_rdataset_isassociated(&fctx->nameservers))
6330 dns_rdataset_disassociate(&fctx->nameservers);
6331 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
6332 fctx->ns_ttl = fctx->nameservers.ttl;
6333 fctx->ns_ttl_ok = ISC_TRUE;
6334 log_ns_ttl(fctx, "resume_dslookup");
6335 dns_name_free(&fctx->domain, fctx->mctx);
6336 dns_name_init(&fctx->domain, NULL);
6337 result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
6338 if (result != ISC_R_SUCCESS) {
6339 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6345 fctx_try(fctx, ISC_TRUE, ISC_FALSE);
6348 dns_rdataset_t *nsrdataset = NULL;
6351 * Retrieve state from fctx->nsfetch before we destroy it.
6353 dns_fixedname_init(&fixed);
6354 domain = dns_fixedname_name(&fixed);
6355 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
6356 if (dns_name_equal(&fctx->nsname, domain)) {
6357 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
6358 dns_resolver_destroyfetch(&fctx->nsfetch);
6361 if (dns_rdataset_isassociated(
6362 &fctx->nsfetch->private->nameservers)) {
6364 &fctx->nsfetch->private->nameservers,
6366 nsrdataset = &nameservers;
6369 dns_resolver_destroyfetch(&fctx->nsfetch);
6370 n = dns_name_countlabels(&fctx->nsname);
6371 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
6374 if (dns_rdataset_isassociated(fevent->rdataset))
6375 dns_rdataset_disassociate(fevent->rdataset);
6376 FCTXTRACE("continuing to look for parent's NS records");
6377 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
6378 dns_rdatatype_ns, domain,
6379 nsrdataset, NULL, 0, task,
6380 resume_dslookup, fctx,
6381 &fctx->nsrrset, NULL,
6383 if (result != ISC_R_SUCCESS)
6384 fctx_done(fctx, result, __LINE__);
6386 LOCK(&res->buckets[bucketnum].lock);
6393 if (dns_rdataset_isassociated(&nameservers))
6394 dns_rdataset_disassociate(&nameservers);
6395 if (dns_rdataset_isassociated(fevent->rdataset))
6396 dns_rdataset_disassociate(fevent->rdataset);
6397 INSIST(fevent->sigrdataset == NULL);
6398 isc_event_free(&event);
6400 LOCK(&res->buckets[bucketnum].lock);
6401 bucket_empty = fctx_decreference(fctx);
6402 UNLOCK(&res->buckets[bucketnum].lock);
6408 checknamessection(dns_message_t *message, dns_section_t section) {
6409 isc_result_t result;
6411 dns_rdata_t rdata = DNS_RDATA_INIT;
6412 dns_rdataset_t *rdataset;
6414 for (result = dns_message_firstname(message, section);
6415 result == ISC_R_SUCCESS;
6416 result = dns_message_nextname(message, section))
6419 dns_message_currentname(message, section, &name);
6420 for (rdataset = ISC_LIST_HEAD(name->list);
6422 rdataset = ISC_LIST_NEXT(rdataset, link)) {
6423 for (result = dns_rdataset_first(rdataset);
6424 result == ISC_R_SUCCESS;
6425 result = dns_rdataset_next(rdataset)) {
6426 dns_rdataset_current(rdataset, &rdata);
6427 if (!dns_rdata_checkowner(name, rdata.rdclass,
6430 !dns_rdata_checknames(&rdata, name, NULL))
6432 rdataset->attributes |=
6433 DNS_RDATASETATTR_CHECKNAMES;
6435 dns_rdata_reset(&rdata);
6442 checknames(dns_message_t *message) {
6444 checknamessection(message, DNS_SECTION_ANSWER);
6445 checknamessection(message, DNS_SECTION_AUTHORITY);
6446 checknamessection(message, DNS_SECTION_ADDITIONAL);
6450 * Log server NSID at log level 'level'
6453 log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
6455 static const char hex[17] = "0123456789abcdef";
6456 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6457 isc_uint16_t optcode, nsid_len, buflen, i;
6458 isc_result_t result;
6459 isc_buffer_t nsidbuf;
6461 unsigned char *p, *buf, *nsid;
6463 /* Extract rdata from OPT rdataset */
6464 result = dns_rdataset_first(opt);
6465 if (result != ISC_R_SUCCESS)
6466 return (ISC_R_FAILURE);
6468 dns_rdata_init(&rdata);
6469 dns_rdataset_current(opt, &rdata);
6470 if (rdata.length < 4)
6471 return (ISC_R_FAILURE);
6473 /* Check for NSID */
6474 isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
6475 isc_buffer_add(&nsidbuf, rdata.length);
6476 optcode = isc_buffer_getuint16(&nsidbuf);
6477 nsid_len = isc_buffer_getuint16(&nsidbuf);
6478 if (optcode != DNS_OPT_NSID || nsid_len == 0)
6479 return (ISC_R_FAILURE);
6481 /* Allocate buffer for storing hex version of the NSID */
6482 buflen = nsid_len * 2 + 1;
6483 buf = isc_mem_get(mctx, buflen);
6485 return (ISC_R_NOSPACE);
6487 /* Convert to hex */
6489 nsid = rdata.data + 4;
6490 for (i = 0; i < nsid_len; i++) {
6491 *p++ = hex[(nsid[0] >> 4) & 0xf];
6492 *p++ = hex[nsid[0] & 0xf];
6497 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6499 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6500 DNS_LOGMODULE_RESOLVER, level,
6501 "received NSID '%s' from %s", buf, addrbuf);
6504 isc_mem_put(mctx, buf, buflen);
6505 return (ISC_R_SUCCESS);
6509 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
6510 isc_buffer_t buffer;
6513 isc_result_t result;
6515 if (! isc_log_wouldlog(dns_lctx, level))
6519 * Note that these are multiline debug messages. We want a newline
6520 * to appear in the log after each message.
6524 buf = isc_mem_get(mctx, len);
6527 isc_buffer_init(&buffer, buf, len);
6528 result = dns_message_totext(message, &dns_master_style_debug,
6530 if (result == ISC_R_NOSPACE) {
6531 isc_mem_put(mctx, buf, len);
6533 } else if (result == ISC_R_SUCCESS)
6534 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6535 DNS_LOGMODULE_RESOLVER, level,
6536 "received packet:\n%.*s",
6537 (int)isc_buffer_usedlength(&buffer),
6539 } while (result == ISC_R_NOSPACE);
6542 isc_mem_put(mctx, buf, len);
6545 static isc_boolean_t
6546 iscname(fetchctx_t *fctx) {
6547 isc_result_t result;
6549 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
6550 &fctx->name, dns_rdatatype_cname, 0,
6552 return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
6555 static isc_boolean_t
6556 betterreferral(fetchctx_t *fctx) {
6557 isc_result_t result;
6559 dns_rdataset_t *rdataset;
6560 dns_message_t *message = fctx->rmessage;
6562 for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
6563 result == ISC_R_SUCCESS;
6564 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
6566 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
6567 if (!isstrictsubdomain(name, &fctx->domain))
6569 for (rdataset = ISC_LIST_HEAD(name->list);
6571 rdataset = ISC_LIST_NEXT(rdataset, link))
6572 if (rdataset->type == dns_rdatatype_ns)
6579 resquery_response(isc_task_t *task, isc_event_t *event) {
6580 isc_result_t result = ISC_R_SUCCESS;
6581 resquery_t *query = event->ev_arg;
6582 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
6583 isc_boolean_t keep_trying, get_nameservers, resend;
6584 isc_boolean_t truncated;
6585 dns_message_t *message;
6586 dns_rdataset_t *opt;
6589 dns_fixedname_t foundname;
6591 isc_time_t tnow, *finish;
6592 dns_adbaddrinfo_t *addrinfo;
6593 unsigned int options;
6594 unsigned int findoptions;
6595 isc_result_t broken_server;
6596 badnstype_t broken_type = badns_response;
6597 isc_boolean_t no_response;
6599 REQUIRE(VALID_QUERY(query));
6601 options = query->options;
6602 REQUIRE(VALID_FCTX(fctx));
6603 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
6607 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
6608 inc_stats(fctx->res, dns_resstatscounter_responsev4);
6610 inc_stats(fctx->res, dns_resstatscounter_responsev6);
6612 (void)isc_timer_touch(fctx->timer);
6614 keep_trying = ISC_FALSE;
6615 broken_server = ISC_R_SUCCESS;
6616 get_nameservers = ISC_FALSE;
6618 truncated = ISC_FALSE;
6620 no_response = ISC_FALSE;
6622 if (fctx->res->exiting) {
6623 result = ISC_R_SHUTTINGDOWN;
6628 fctx->timeout = ISC_FALSE;
6629 fctx->addrinfo = query->addrinfo;
6632 * XXXRTH We should really get the current time just once. We
6633 * need a routine to convert from an isc_time_t to an
6638 isc_stdtime_get(&now);
6641 * Did the dispatcher have a problem?
6643 if (devent->result != ISC_R_SUCCESS) {
6644 if (devent->result == ISC_R_EOF &&
6645 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6647 * The problem might be that they
6648 * don't understand EDNS0. Turn it
6649 * off and try again.
6651 options |= DNS_FETCHOPT_NOEDNS0;
6654 * Remember that they don't like EDNS0.
6656 dns_adb_changeflags(fctx->adb,
6658 DNS_FETCHOPT_NOEDNS0,
6659 DNS_FETCHOPT_NOEDNS0);
6662 * There's no hope for this query.
6664 keep_trying = ISC_TRUE;
6667 * If this is a network error on an exclusive query
6668 * socket, mark the server as bad so that we won't try
6669 * it for this fetch again. Also adjust finish and
6670 * no_response so that we penalize this address in SRTT
6673 if (query->exclusivesocket &&
6674 (devent->result == ISC_R_HOSTUNREACH ||
6675 devent->result == ISC_R_NETUNREACH ||
6676 devent->result == ISC_R_CONNREFUSED ||
6677 devent->result == ISC_R_CANCELED)) {
6678 broken_server = devent->result;
6679 broken_type = badns_unreachable;
6681 no_response = ISC_TRUE;
6687 message = fctx->rmessage;
6689 if (query->tsig != NULL) {
6690 result = dns_message_setquerytsig(message, query->tsig);
6691 if (result != ISC_R_SUCCESS)
6695 if (query->tsigkey) {
6696 result = dns_message_settsigkey(message, query->tsigkey);
6697 if (result != ISC_R_SUCCESS)
6701 result = dns_message_parse(message, &devent->buffer, 0);
6702 if (result != ISC_R_SUCCESS) {
6704 case ISC_R_UNEXPECTEDEND:
6705 if (!message->question_ok ||
6706 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
6707 (options & DNS_FETCHOPT_TCP) != 0) {
6709 * Either the message ended prematurely,
6710 * and/or wasn't marked as being truncated,
6711 * and/or this is a response to a query we
6712 * sent over TCP. In all of these cases,
6713 * something is wrong with the remote
6714 * server and we don't want to retry using
6717 if ((query->options & DNS_FETCHOPT_NOEDNS0)
6720 * The problem might be that they
6721 * don't understand EDNS0. Turn it
6722 * off and try again.
6724 options |= DNS_FETCHOPT_NOEDNS0;
6727 * Remember that they don't like EDNS0.
6729 dns_adb_changeflags(
6732 DNS_FETCHOPT_NOEDNS0,
6733 DNS_FETCHOPT_NOEDNS0);
6734 inc_stats(fctx->res,
6735 dns_resstatscounter_edns0fail);
6737 broken_server = result;
6738 keep_trying = ISC_TRUE;
6743 * We defer retrying via TCP for a bit so we can
6744 * check out this message further.
6746 truncated = ISC_TRUE;
6749 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6751 * The problem might be that they
6752 * don't understand EDNS0. Turn it
6753 * off and try again.
6755 options |= DNS_FETCHOPT_NOEDNS0;
6758 * Remember that they don't like EDNS0.
6760 dns_adb_changeflags(fctx->adb,
6762 DNS_FETCHOPT_NOEDNS0,
6763 DNS_FETCHOPT_NOEDNS0);
6764 inc_stats(fctx->res,
6765 dns_resstatscounter_edns0fail);
6767 broken_server = DNS_R_UNEXPECTEDRCODE;
6768 keep_trying = ISC_TRUE;
6773 * Something bad has happened.
6781 * Log the incoming packet.
6783 log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
6786 * Did we request NSID? If so, and if the response contains
6787 * NSID data, log it at INFO level.
6789 opt = dns_message_getopt(message);
6790 if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
6791 log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
6794 * If the message is signed, check the signature. If not, this
6795 * returns success anyway.
6797 result = dns_message_checksig(message, fctx->res->view);
6798 if (result != ISC_R_SUCCESS)
6802 * The dispatcher should ensure we only get responses with QR set.
6804 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
6806 * INSIST() that the message comes from the place we sent it to,
6807 * since the dispatch code should ensure this.
6809 * INSIST() that the message id is correct (this should also be
6810 * ensured by the dispatch code).
6814 * We have an affirmative response to the query and we have
6815 * previously got a response from this server which indicated
6816 * EDNS may not be supported so we can now cache the lack of
6820 (message->rcode == dns_rcode_noerror ||
6821 message->rcode == dns_rcode_nxdomain ||
6822 message->rcode == dns_rcode_refused ||
6823 message->rcode == dns_rcode_yxdomain) &&
6824 bad_edns(fctx, &query->addrinfo->sockaddr)) {
6825 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6826 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
6828 dns_adb_changeflags(fctx->adb, query->addrinfo,
6829 DNS_FETCHOPT_NOEDNS0,
6830 DNS_FETCHOPT_NOEDNS0);
6834 * Deal with truncated responses by retrying using TCP.
6836 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
6837 truncated = ISC_TRUE;
6840 inc_stats(fctx->res, dns_resstatscounter_truncated);
6841 if ((options & DNS_FETCHOPT_TCP) != 0) {
6842 broken_server = DNS_R_TRUNCATEDTCP;
6843 keep_trying = ISC_TRUE;
6845 options |= DNS_FETCHOPT_TCP;
6852 * Is it a query response?
6854 if (message->opcode != dns_opcode_query) {
6856 broken_server = DNS_R_UNEXPECTEDOPCODE;
6857 keep_trying = ISC_TRUE;
6862 * Update statistics about erroneous responses.
6864 if (message->rcode != dns_rcode_noerror) {
6865 switch (message->rcode) {
6866 case dns_rcode_nxdomain:
6867 inc_stats(fctx->res, dns_resstatscounter_nxdomain);
6869 case dns_rcode_servfail:
6870 inc_stats(fctx->res, dns_resstatscounter_servfail);
6872 case dns_rcode_formerr:
6873 inc_stats(fctx->res, dns_resstatscounter_formerr);
6876 inc_stats(fctx->res, dns_resstatscounter_othererror);
6882 * Is the remote server broken, or does it dislike us?
6884 if (message->rcode != dns_rcode_noerror &&
6885 message->rcode != dns_rcode_nxdomain) {
6886 if (((message->rcode == dns_rcode_formerr ||
6887 message->rcode == dns_rcode_notimp) ||
6888 (message->rcode == dns_rcode_servfail &&
6889 dns_message_getopt(message) == NULL)) &&
6890 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
6892 * It's very likely they don't like EDNS0.
6893 * If the response code is SERVFAIL, also check if the
6894 * response contains an OPT RR and don't cache the
6895 * failure since it can be returned for various other
6898 * XXXRTH We should check if the question
6899 * we're asking requires EDNS0, and
6900 * if so, we should bail out.
6902 options |= DNS_FETCHOPT_NOEDNS0;
6905 * Remember that they may not like EDNS0.
6907 add_bad_edns(fctx, &query->addrinfo->sockaddr);
6908 inc_stats(fctx->res, dns_resstatscounter_edns0fail);
6909 } else if (message->rcode == dns_rcode_formerr) {
6910 if (ISFORWARDER(query->addrinfo)) {
6912 * This forwarder doesn't understand us,
6913 * but other forwarders might. Keep trying.
6915 broken_server = DNS_R_REMOTEFORMERR;
6916 keep_trying = ISC_TRUE;
6919 * The server doesn't understand us. Since
6920 * all servers for a zone need similar
6921 * capabilities, we assume that we will get
6922 * FORMERR from all servers, and thus we
6923 * cannot make any more progress with this
6926 log_formerr(fctx, "server sent FORMERR");
6927 result = DNS_R_FORMERR;
6929 } else if (message->rcode == dns_rcode_yxdomain) {
6931 * DNAME mapping failed because the new name
6932 * was too long. There's no chance of success
6935 result = DNS_R_YXDOMAIN;
6936 } else if (message->rcode == dns_rcode_badvers) {
6937 unsigned int flags, mask;
6938 unsigned int version;
6941 INSIST(opt != NULL);
6942 version = (opt->ttl >> 16) & 0xff;
6943 flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
6944 DNS_FETCHOPT_EDNSVERSIONSET;
6945 mask = DNS_FETCHOPT_EDNSVERSIONMASK |
6946 DNS_FETCHOPT_EDNSVERSIONSET;
6949 dns_adb_changeflags(fctx->adb, query->addrinfo,
6953 broken_server = DNS_R_BADVERS;
6954 keep_trying = ISC_TRUE;
6961 broken_server = DNS_R_UNEXPECTEDRCODE;
6962 INSIST(broken_server != ISC_R_SUCCESS);
6963 keep_trying = ISC_TRUE;
6969 * Is the question the same as the one we asked?
6971 result = same_question(fctx);
6972 if (result != ISC_R_SUCCESS) {
6974 if (result == DNS_R_FORMERR)
6975 keep_trying = ISC_TRUE;
6980 * Is the server lame?
6982 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
6984 inc_stats(fctx->res, dns_resstatscounter_lame);
6985 log_lame(fctx, query->addrinfo);
6986 result = dns_adb_marklame(fctx->adb, query->addrinfo,
6987 &fctx->name, fctx->type,
6988 now + fctx->res->lame_ttl);
6989 if (result != ISC_R_SUCCESS)
6990 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6991 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
6992 "could not mark server as lame: %s",
6993 isc_result_totext(result));
6994 broken_server = DNS_R_LAME;
6995 keep_trying = ISC_TRUE;
7000 * Enforce delegations only zones like NET and COM.
7002 if (!ISFORWARDER(query->addrinfo) &&
7003 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
7004 !dns_name_equal(&fctx->domain, &fctx->name) &&
7005 fix_mustbedelegationornxdomain(message, fctx)) {
7006 char namebuf[DNS_NAME_FORMATSIZE];
7007 char domainbuf[DNS_NAME_FORMATSIZE];
7008 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
7012 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
7013 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
7014 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
7015 dns_rdataclass_format(fctx->res->rdclass, classbuf,
7017 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
7020 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
7021 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
7022 "enforced delegation-only for '%s' (%s/%s/%s) "
7024 domainbuf, namebuf, typebuf, classbuf, addrbuf);
7027 if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
7028 checknames(message);
7033 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
7036 * Did we get any answers?
7038 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
7039 (message->rcode == dns_rcode_noerror ||
7040 message->rcode == dns_rcode_nxdomain)) {
7043 * We've got answers. If it has an authoritative answer or an
7044 * answer from a forwarder, we're done.
7046 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
7047 ISFORWARDER(query->addrinfo))
7048 result = answer_response(fctx);
7049 else if (iscname(fctx) &&
7050 fctx->type != dns_rdatatype_any &&
7051 fctx->type != dns_rdatatype_cname) {
7053 * A BIND8 server could return a non-authoritative
7054 * answer when a CNAME is followed. We should treat
7055 * it as a valid answer.
7057 result = answer_response(fctx);
7058 } else if (fctx->type != dns_rdatatype_ns &&
7059 !betterreferral(fctx)) {
7061 * Lame response !!!.
7063 result = answer_response(fctx);
7065 if (fctx->type == dns_rdatatype_ns) {
7067 * A BIND 8 server could incorrectly return a
7068 * non-authoritative answer to an NS query
7069 * instead of a referral. Since this answer
7070 * lacks the SIGs necessary to do DNSSEC
7071 * validation, we must invoke the following
7072 * special kludge to treat it as a referral.
7074 result = noanswer_response(fctx, NULL,
7075 LOOK_FOR_NS_IN_ANSWER);
7078 * Some other servers may still somehow include
7079 * an answer when it should return a referral
7080 * with an empty answer. Check to see if we can
7081 * treat this as a referral by ignoring the
7082 * answer. Further more, there may be an
7083 * implementation that moves A/AAAA glue records
7084 * to the answer section for that type of
7085 * delegation when the query is for that glue
7086 * record. LOOK_FOR_GLUE_IN_ANSWER will handle
7087 * such a corner case.
7089 result = noanswer_response(fctx, NULL,
7090 LOOK_FOR_GLUE_IN_ANSWER);
7092 if (result != DNS_R_DELEGATION) {
7094 * At this point, AA is not set, the response
7095 * is not a referral, and the server is not a
7096 * forwarder. It is technically lame and it's
7097 * easier to treat it as such than to figure out
7098 * some more elaborate course of action.
7100 broken_server = DNS_R_LAME;
7101 keep_trying = ISC_TRUE;
7104 goto force_referral;
7106 if (result != ISC_R_SUCCESS) {
7107 if (result == DNS_R_FORMERR)
7108 keep_trying = ISC_TRUE;
7111 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
7112 message->rcode == dns_rcode_noerror ||
7113 message->rcode == dns_rcode_nxdomain) {
7115 * NXDOMAIN, NXRDATASET, or referral.
7117 result = noanswer_response(fctx, NULL, 0);
7118 if (result == DNS_R_CHASEDSSERVERS) {
7119 } else if (result == DNS_R_DELEGATION) {
7122 * We don't have the answer, but we know a better
7125 get_nameservers = ISC_TRUE;
7126 keep_trying = ISC_TRUE;
7128 * We have a new set of name servers, and it
7129 * has not experienced any restarts yet.
7134 * Update local statistics counters collected for each
7138 fctx->querysent = 0;
7139 fctx->lamecount = 0;
7144 result = ISC_R_SUCCESS;
7145 } else if (result != ISC_R_SUCCESS) {
7147 * Something has gone wrong.
7149 if (result == DNS_R_FORMERR)
7150 keep_trying = ISC_TRUE;
7155 * The server is insane.
7158 broken_server = DNS_R_UNEXPECTEDRCODE;
7159 keep_trying = ISC_TRUE;
7164 * Follow additional section data chains.
7166 chase_additional(fctx);
7169 * Cache the cacheable parts of the message. This may also cause
7170 * work to be queued to the DNSSEC validator.
7172 if (WANTCACHE(fctx)) {
7173 result = cache_message(fctx, query->addrinfo, now);
7174 if (result != ISC_R_SUCCESS)
7179 * Ncache the negatively cacheable parts of the message. This may
7180 * also cause work to be queued to the DNSSEC validator.
7182 if (WANTNCACHE(fctx)) {
7183 dns_rdatatype_t covers;
7184 if (message->rcode == dns_rcode_nxdomain)
7185 covers = dns_rdatatype_any;
7187 covers = fctx->type;
7190 * Cache any negative cache entries in the message.
7192 result = ncache_message(fctx, query->addrinfo, covers, now);
7197 * Remember the query's addrinfo, in case we need to mark the
7200 addrinfo = query->addrinfo;
7205 * XXXRTH Don't cancel the query if waiting for validation?
7207 fctx_cancelquery(&query, &devent, finish, no_response);
7210 if (result == DNS_R_FORMERR)
7211 broken_server = DNS_R_FORMERR;
7212 if (broken_server != ISC_R_SUCCESS) {
7214 * Add this server to the list of bad servers for
7217 add_bad(fctx, addrinfo, broken_server, broken_type);
7220 if (get_nameservers) {
7222 dns_fixedname_init(&foundname);
7223 fname = dns_fixedname_name(&foundname);
7224 if (result != ISC_R_SUCCESS) {
7225 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7229 if (dns_rdatatype_atparent(fctx->type))
7230 findoptions |= DNS_DBFIND_NOEXACT;
7231 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
7234 name = &fctx->domain;
7235 result = dns_view_findzonecut(fctx->res->view,
7241 if (result != ISC_R_SUCCESS) {
7242 FCTXTRACE("couldn't find a zonecut");
7243 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7246 if (!dns_name_issubdomain(fname, &fctx->domain)) {
7248 * The best nameservers are now above our
7251 FCTXTRACE("nameservers now above QDOMAIN");
7252 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7255 dns_name_free(&fctx->domain, fctx->mctx);
7256 dns_name_init(&fctx->domain, NULL);
7257 result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
7258 if (result != ISC_R_SUCCESS) {
7259 fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
7262 fctx->ns_ttl = fctx->nameservers.ttl;
7263 fctx->ns_ttl_ok = ISC_TRUE;
7264 fctx_cancelqueries(fctx, ISC_TRUE);
7265 fctx_cleanupfinds(fctx);
7266 fctx_cleanupaltfinds(fctx);
7267 fctx_cleanupforwaddrs(fctx);
7268 fctx_cleanupaltaddrs(fctx);
7273 fctx_try(fctx, !get_nameservers, ISC_FALSE);
7274 } else if (resend) {
7276 * Resend (probably with changed options).
7278 FCTXTRACE("resend");
7279 inc_stats(fctx->res, dns_resstatscounter_retry);
7280 result = fctx_query(fctx, addrinfo, options);
7281 if (result != ISC_R_SUCCESS)
7282 fctx_done(fctx, result, __LINE__);
7283 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
7285 * All has gone well so far, but we are waiting for the
7286 * DNSSEC validator to validate the answer.
7288 FCTXTRACE("wait for validator");
7289 fctx_cancelqueries(fctx, ISC_TRUE);
7291 * We must not retransmit while the validator is working;
7292 * it has references to the current rmessage.
7294 result = fctx_stopidletimer(fctx);
7295 if (result != ISC_R_SUCCESS)
7296 fctx_done(fctx, result, __LINE__);
7297 } else if (result == DNS_R_CHASEDSSERVERS) {
7299 add_bad(fctx, addrinfo, result, broken_type);
7300 fctx_cancelqueries(fctx, ISC_TRUE);
7301 fctx_cleanupfinds(fctx);
7302 fctx_cleanupforwaddrs(fctx);
7304 n = dns_name_countlabels(&fctx->name);
7305 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
7307 FCTXTRACE("suspending DS lookup to find parent's NS records");
7309 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
7311 NULL, NULL, NULL, 0, task,
7312 resume_dslookup, fctx,
7313 &fctx->nsrrset, NULL,
7315 if (result != ISC_R_SUCCESS)
7316 fctx_done(fctx, result, __LINE__);
7318 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7320 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
7321 result = fctx_stopidletimer(fctx);
7322 if (result != ISC_R_SUCCESS)
7323 fctx_done(fctx, result, __LINE__);
7329 fctx_done(fctx, result, __LINE__);
7335 *** Resolver Methods
7338 destroy_badcache(dns_resolver_t *res) {
7339 dns_badcache_t *bad, *next;
7342 if (res->badcache != NULL) {
7343 for (i = 0; i < res->badhash; i++)
7344 for (bad = res->badcache[i]; bad != NULL;
7347 isc_mem_put(res->mctx, bad, sizeof(*bad) +
7351 isc_mem_put(res->mctx, res->badcache,
7352 sizeof(*res->badcache) * res->badhash);
7353 res->badcache = NULL;
7355 INSIST(res->badcount == 0);
7360 destroy(dns_resolver_t *res) {
7364 REQUIRE(res->references == 0);
7365 REQUIRE(!res->priming);
7366 REQUIRE(res->primefetch == NULL);
7370 INSIST(res->nfctx == 0);
7372 DESTROYLOCK(&res->primelock);
7373 DESTROYLOCK(&res->nlock);
7374 DESTROYLOCK(&res->lock);
7375 for (i = 0; i < res->nbuckets; i++) {
7376 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
7377 isc_task_shutdown(res->buckets[i].task);
7378 isc_task_detach(&res->buckets[i].task);
7379 DESTROYLOCK(&res->buckets[i].lock);
7380 isc_mem_detach(&res->buckets[i].mctx);
7382 isc_mem_put(res->mctx, res->buckets,
7383 res->nbuckets * sizeof(fctxbucket_t));
7384 if (res->dispatchv4 != NULL)
7385 dns_dispatch_detach(&res->dispatchv4);
7386 if (res->dispatchv6 != NULL)
7387 dns_dispatch_detach(&res->dispatchv6);
7388 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
7389 ISC_LIST_UNLINK(res->alternates, a, link);
7391 dns_name_free(&a->_u._n.name, res->mctx);
7392 isc_mem_put(res->mctx, a, sizeof(*a));
7394 dns_resolver_reset_algorithms(res);
7395 destroy_badcache(res);
7396 dns_resolver_resetmustbesecure(res);
7398 isc_rwlock_destroy(&res->alglock);
7401 isc_rwlock_destroy(&res->mbslock);
7403 isc_timer_detach(&res->spillattimer);
7405 isc_mem_put(res->mctx, res, sizeof(*res));
7409 send_shutdown_events(dns_resolver_t *res) {
7410 isc_event_t *event, *next_event;
7414 * Caller must be holding the resolver lock.
7417 for (event = ISC_LIST_HEAD(res->whenshutdown);
7419 event = next_event) {
7420 next_event = ISC_LIST_NEXT(event, ev_link);
7421 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
7422 etask = event->ev_sender;
7423 event->ev_sender = res;
7424 isc_task_sendanddetach(&etask, &event);
7429 empty_bucket(dns_resolver_t *res) {
7430 RTRACE("empty_bucket");
7434 INSIST(res->activebuckets > 0);
7435 res->activebuckets--;
7436 if (res->activebuckets == 0)
7437 send_shutdown_events(res);
7443 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
7444 dns_resolver_t *res = event->ev_arg;
7445 isc_result_t result;
7447 isc_boolean_t logit = ISC_FALSE;
7449 REQUIRE(VALID_RESOLVER(res));
7454 INSIST(!res->exiting);
7455 if (res->spillat > res->spillatmin) {
7459 if (res->spillat <= res->spillatmin) {
7460 result = isc_timer_reset(res->spillattimer,
7461 isc_timertype_inactive, NULL,
7463 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7465 count = res->spillat;
7468 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7469 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
7470 "clients-per-query decreased to %u", count);
7472 isc_event_free(&event);
7476 dns_resolver_create(dns_view_t *view,
7477 isc_taskmgr_t *taskmgr, unsigned int ntasks,
7478 isc_socketmgr_t *socketmgr,
7479 isc_timermgr_t *timermgr,
7480 unsigned int options,
7481 dns_dispatchmgr_t *dispatchmgr,
7482 dns_dispatch_t *dispatchv4,
7483 dns_dispatch_t *dispatchv6,
7484 dns_resolver_t **resp)
7486 dns_resolver_t *res;
7487 isc_result_t result = ISC_R_SUCCESS;
7488 unsigned int i, buckets_created = 0;
7489 isc_task_t *task = NULL;
7494 * Create a resolver.
7497 REQUIRE(DNS_VIEW_VALID(view));
7498 REQUIRE(ntasks > 0);
7499 REQUIRE(resp != NULL && *resp == NULL);
7500 REQUIRE(dispatchmgr != NULL);
7501 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
7503 res = isc_mem_get(view->mctx, sizeof(*res));
7505 return (ISC_R_NOMEMORY);
7507 res->mctx = view->mctx;
7508 res->rdclass = view->rdclass;
7509 res->socketmgr = socketmgr;
7510 res->timermgr = timermgr;
7511 res->taskmgr = taskmgr;
7512 res->dispatchmgr = dispatchmgr;
7514 res->options = options;
7516 ISC_LIST_INIT(res->alternates);
7517 res->udpsize = RECV_BUFFER_SIZE;
7518 res->algorithms = NULL;
7519 res->badcache = NULL;
7523 res->mustbesecure = NULL;
7524 res->spillatmin = res->spillat = 10;
7525 res->spillatmax = 100;
7526 res->spillattimer = NULL;
7527 res->zero_no_soa_ttl = ISC_FALSE;
7528 res->query_timeout = DEFAULT_QUERY_TIMEOUT;
7530 res->nextdisp = 0; /* meaningless at this point, but init it */
7531 res->nbuckets = ntasks;
7532 res->activebuckets = ntasks;
7533 res->buckets = isc_mem_get(view->mctx,
7534 ntasks * sizeof(fctxbucket_t));
7535 if (res->buckets == NULL) {
7536 result = ISC_R_NOMEMORY;
7539 for (i = 0; i < ntasks; i++) {
7540 result = isc_mutex_init(&res->buckets[i].lock);
7541 if (result != ISC_R_SUCCESS)
7542 goto cleanup_buckets;
7543 res->buckets[i].task = NULL;
7544 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
7545 if (result != ISC_R_SUCCESS) {
7546 DESTROYLOCK(&res->buckets[i].lock);
7547 goto cleanup_buckets;
7549 res->buckets[i].mctx = NULL;
7550 snprintf(name, sizeof(name), "res%u", i);
7551 #ifdef ISC_PLATFORM_USETHREADS
7553 * Use a separate memory context for each bucket to reduce
7554 * contention among multiple threads. Do this only when
7555 * enabling threads because it will be require more memory.
7557 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
7558 if (result != ISC_R_SUCCESS) {
7559 isc_task_detach(&res->buckets[i].task);
7560 DESTROYLOCK(&res->buckets[i].lock);
7561 goto cleanup_buckets;
7563 isc_mem_setname(res->buckets[i].mctx, name, NULL);
7565 isc_mem_attach(view->mctx, &res->buckets[i].mctx);
7567 isc_task_setname(res->buckets[i].task, name, res);
7568 ISC_LIST_INIT(res->buckets[i].fctxs);
7569 res->buckets[i].exiting = ISC_FALSE;
7573 res->dispatchv4 = NULL;
7574 if (dispatchv4 != NULL) {
7575 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
7576 dispattr = dns_dispatch_getattributes(dispatchv4);
7578 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7581 res->dispatchv6 = NULL;
7582 if (dispatchv6 != NULL) {
7583 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
7584 dispattr = dns_dispatch_getattributes(dispatchv6);
7586 ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
7589 res->references = 1;
7590 res->exiting = ISC_FALSE;
7591 res->frozen = ISC_FALSE;
7592 ISC_LIST_INIT(res->whenshutdown);
7593 res->priming = ISC_FALSE;
7594 res->primefetch = NULL;
7597 result = isc_mutex_init(&res->lock);
7598 if (result != ISC_R_SUCCESS)
7599 goto cleanup_dispatches;
7601 result = isc_mutex_init(&res->nlock);
7602 if (result != ISC_R_SUCCESS)
7605 result = isc_mutex_init(&res->primelock);
7606 if (result != ISC_R_SUCCESS)
7610 result = isc_task_create(taskmgr, 0, &task);
7611 if (result != ISC_R_SUCCESS)
7612 goto cleanup_primelock;
7614 result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
7615 task, spillattimer_countdown, res,
7616 &res->spillattimer);
7617 isc_task_detach(&task);
7618 if (result != ISC_R_SUCCESS)
7619 goto cleanup_primelock;
7622 result = isc_rwlock_init(&res->alglock, 0, 0);
7623 if (result != ISC_R_SUCCESS)
7624 goto cleanup_spillattimer;
7627 result = isc_rwlock_init(&res->mbslock, 0, 0);
7628 if (result != ISC_R_SUCCESS)
7629 goto cleanup_alglock;
7632 res->magic = RES_MAGIC;
7636 return (ISC_R_SUCCESS);
7641 isc_rwlock_destroy(&res->alglock);
7644 #if USE_ALGLOCK || USE_MBSLOCK
7645 cleanup_spillattimer:
7646 isc_timer_detach(&res->spillattimer);
7650 DESTROYLOCK(&res->primelock);
7653 DESTROYLOCK(&res->nlock);
7656 DESTROYLOCK(&res->lock);
7659 if (res->dispatchv6 != NULL)
7660 dns_dispatch_detach(&res->dispatchv6);
7661 if (res->dispatchv4 != NULL)
7662 dns_dispatch_detach(&res->dispatchv4);
7665 for (i = 0; i < buckets_created; i++) {
7666 isc_mem_detach(&res->buckets[i].mctx);
7667 DESTROYLOCK(&res->buckets[i].lock);
7668 isc_task_shutdown(res->buckets[i].task);
7669 isc_task_detach(&res->buckets[i].task);
7671 isc_mem_put(view->mctx, res->buckets,
7672 res->nbuckets * sizeof(fctxbucket_t));
7675 isc_mem_put(view->mctx, res, sizeof(*res));
7682 prime_done(isc_task_t *task, isc_event_t *event) {
7683 dns_resolver_t *res;
7684 dns_fetchevent_t *fevent;
7686 dns_db_t *db = NULL;
7688 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
7689 fevent = (dns_fetchevent_t *)event;
7690 res = event->ev_arg;
7691 REQUIRE(VALID_RESOLVER(res));
7697 INSIST(res->priming);
7698 res->priming = ISC_FALSE;
7699 LOCK(&res->primelock);
7700 fetch = res->primefetch;
7701 res->primefetch = NULL;
7702 UNLOCK(&res->primelock);
7706 if (fevent->result == ISC_R_SUCCESS &&
7707 res->view->cache != NULL && res->view->hints != NULL) {
7708 dns_cache_attachdb(res->view->cache, &db);
7709 dns_root_checkhints(res->view, res->view->hints, db);
7713 if (fevent->node != NULL)
7714 dns_db_detachnode(fevent->db, &fevent->node);
7715 if (fevent->db != NULL)
7716 dns_db_detach(&fevent->db);
7717 if (dns_rdataset_isassociated(fevent->rdataset))
7718 dns_rdataset_disassociate(fevent->rdataset);
7719 INSIST(fevent->sigrdataset == NULL);
7721 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
7723 isc_event_free(&event);
7724 dns_resolver_destroyfetch(&fetch);
7728 dns_resolver_prime(dns_resolver_t *res) {
7729 isc_boolean_t want_priming = ISC_FALSE;
7730 dns_rdataset_t *rdataset;
7731 isc_result_t result;
7733 REQUIRE(VALID_RESOLVER(res));
7734 REQUIRE(res->frozen);
7736 RTRACE("dns_resolver_prime");
7740 if (!res->exiting && !res->priming) {
7741 INSIST(res->primefetch == NULL);
7742 res->priming = ISC_TRUE;
7743 want_priming = ISC_TRUE;
7750 * To avoid any possible recursive locking problems, we
7751 * start the priming fetch like any other fetch, and holding
7752 * no resolver locks. No one else will try to start it
7753 * because we're the ones who set res->priming to true.
7754 * Any other callers of dns_resolver_prime() while we're
7755 * running will see that res->priming is already true and
7759 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
7760 if (rdataset == NULL) {
7762 INSIST(res->priming);
7763 INSIST(res->primefetch == NULL);
7764 res->priming = ISC_FALSE;
7768 dns_rdataset_init(rdataset);
7769 LOCK(&res->primelock);
7770 result = dns_resolver_createfetch(res, dns_rootname,
7772 NULL, NULL, NULL, 0,
7773 res->buckets[0].task,
7775 res, rdataset, NULL,
7777 UNLOCK(&res->primelock);
7778 if (result != ISC_R_SUCCESS) {
7780 INSIST(res->priming);
7781 res->priming = ISC_FALSE;
7789 dns_resolver_freeze(dns_resolver_t *res) {
7794 REQUIRE(VALID_RESOLVER(res));
7796 res->frozen = ISC_TRUE;
7800 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
7801 REQUIRE(VALID_RESOLVER(source));
7802 REQUIRE(targetp != NULL && *targetp == NULL);
7804 RRTRACE(source, "attach");
7805 LOCK(&source->lock);
7806 REQUIRE(!source->exiting);
7808 INSIST(source->references > 0);
7809 source->references++;
7810 INSIST(source->references != 0);
7811 UNLOCK(&source->lock);
7817 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
7818 isc_event_t **eventp)
7823 REQUIRE(VALID_RESOLVER(res));
7824 REQUIRE(eventp != NULL);
7831 if (res->exiting && res->activebuckets == 0) {
7833 * We're already shutdown. Send the event.
7835 event->ev_sender = res;
7836 isc_task_send(task, &event);
7839 isc_task_attach(task, &clone);
7840 event->ev_sender = clone;
7841 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
7848 dns_resolver_shutdown(dns_resolver_t *res) {
7852 isc_result_t result;
7854 REQUIRE(VALID_RESOLVER(res));
7860 if (!res->exiting) {
7862 res->exiting = ISC_TRUE;
7864 for (i = 0; i < res->nbuckets; i++) {
7865 LOCK(&res->buckets[i].lock);
7866 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
7868 fctx = ISC_LIST_NEXT(fctx, link))
7869 fctx_shutdown(fctx);
7870 if (res->dispatchv4 != NULL && !res->exclusivev4) {
7871 sock = dns_dispatch_getsocket(res->dispatchv4);
7872 isc_socket_cancel(sock, res->buckets[i].task,
7873 ISC_SOCKCANCEL_ALL);
7875 if (res->dispatchv6 != NULL && !res->exclusivev6) {
7876 sock = dns_dispatch_getsocket(res->dispatchv6);
7877 isc_socket_cancel(sock, res->buckets[i].task,
7878 ISC_SOCKCANCEL_ALL);
7880 res->buckets[i].exiting = ISC_TRUE;
7881 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
7882 INSIST(res->activebuckets > 0);
7883 res->activebuckets--;
7885 UNLOCK(&res->buckets[i].lock);
7887 if (res->activebuckets == 0)
7888 send_shutdown_events(res);
7889 result = isc_timer_reset(res->spillattimer,
7890 isc_timertype_inactive, NULL,
7892 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7899 dns_resolver_detach(dns_resolver_t **resp) {
7900 dns_resolver_t *res;
7901 isc_boolean_t need_destroy = ISC_FALSE;
7903 REQUIRE(resp != NULL);
7905 REQUIRE(VALID_RESOLVER(res));
7911 INSIST(res->references > 0);
7913 if (res->references == 0) {
7914 INSIST(res->exiting && res->activebuckets == 0);
7915 need_destroy = ISC_TRUE;
7926 static inline isc_boolean_t
7927 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
7928 unsigned int options)
7931 * Don't match fetch contexts that are shutting down.
7933 if (fctx->cloned || fctx->state == fetchstate_done ||
7934 ISC_LIST_EMPTY(fctx->events))
7937 if (fctx->type != type || fctx->options != options)
7939 return (dns_name_equal(&fctx->name, name));
7943 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
7944 char namebuf[DNS_NAME_FORMATSIZE];
7945 char typebuf[DNS_RDATATYPE_FORMATSIZE];
7946 int level = ISC_LOG_DEBUG(1);
7948 if (! isc_log_wouldlog(dns_lctx, level))
7951 dns_name_format(name, namebuf, sizeof(namebuf));
7952 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
7954 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
7955 DNS_LOGMODULE_RESOLVER, level,
7956 "createfetch: %s %s", namebuf, typebuf);
7960 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
7961 dns_rdatatype_t type,
7962 dns_name_t *domain, dns_rdataset_t *nameservers,
7963 dns_forwarders_t *forwarders,
7964 unsigned int options, isc_task_t *task,
7965 isc_taskaction_t action, void *arg,
7966 dns_rdataset_t *rdataset,
7967 dns_rdataset_t *sigrdataset,
7968 dns_fetch_t **fetchp)
7970 return (dns_resolver_createfetch2(res, name, type, domain,
7971 nameservers, forwarders, NULL, 0,
7972 options, task, action, arg,
7973 rdataset, sigrdataset, fetchp));
7977 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
7978 dns_rdatatype_t type,
7979 dns_name_t *domain, dns_rdataset_t *nameservers,
7980 dns_forwarders_t *forwarders,
7981 isc_sockaddr_t *client, dns_messageid_t id,
7982 unsigned int options, isc_task_t *task,
7983 isc_taskaction_t action, void *arg,
7984 dns_rdataset_t *rdataset,
7985 dns_rdataset_t *sigrdataset,
7986 dns_fetch_t **fetchp)
7989 fetchctx_t *fctx = NULL;
7990 isc_result_t result = ISC_R_SUCCESS;
7991 unsigned int bucketnum;
7992 isc_boolean_t new_fctx = ISC_FALSE;
7994 unsigned int count = 0;
7995 unsigned int spillat;
7996 unsigned int spillatmin;
7997 isc_boolean_t destroy = ISC_FALSE;
8001 REQUIRE(VALID_RESOLVER(res));
8002 REQUIRE(res->frozen);
8003 /* XXXRTH Check for meta type */
8004 if (domain != NULL) {
8005 REQUIRE(DNS_RDATASET_VALID(nameservers));
8006 REQUIRE(nameservers->type == dns_rdatatype_ns);
8008 REQUIRE(nameservers == NULL);
8009 REQUIRE(forwarders == NULL);
8010 REQUIRE(!dns_rdataset_isassociated(rdataset));
8011 REQUIRE(sigrdataset == NULL ||
8012 !dns_rdataset_isassociated(sigrdataset));
8013 REQUIRE(fetchp != NULL && *fetchp == NULL);
8015 log_fetch(name, type);
8018 * XXXRTH use a mempool?
8020 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
8022 return (ISC_R_NOMEMORY);
8024 bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
8027 spillat = res->spillat;
8028 spillatmin = res->spillatmin;
8030 LOCK(&res->buckets[bucketnum].lock);
8032 if (res->buckets[bucketnum].exiting) {
8033 result = ISC_R_SHUTTINGDOWN;
8037 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
8038 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
8040 fctx = ISC_LIST_NEXT(fctx, link)) {
8041 if (fctx_match(fctx, name, type, options))
8047 * Is this a duplicate?
8049 if (fctx != NULL && client != NULL) {
8050 dns_fetchevent_t *fevent;
8051 for (fevent = ISC_LIST_HEAD(fctx->events);
8053 fevent = ISC_LIST_NEXT(fevent, ev_link)) {
8054 if (fevent->client != NULL && fevent->id == id &&
8055 isc_sockaddr_equal(fevent->client, client)) {
8056 result = DNS_R_DUPLICATE;
8062 if (count >= spillatmin && spillatmin != 0) {
8063 INSIST(fctx != NULL);
8064 if (count >= spillat)
8065 fctx->spilled = ISC_TRUE;
8066 if (fctx->spilled) {
8067 result = DNS_R_DROP;
8073 result = fctx_create(res, name, type, domain, nameservers,
8074 options, bucketnum, &fctx);
8075 if (result != ISC_R_SUCCESS)
8077 new_fctx = ISC_TRUE;
8080 result = fctx_join(fctx, task, client, id, action, arg,
8081 rdataset, sigrdataset, fetch);
8083 if (result == ISC_R_SUCCESS) {
8087 event = &fctx->control_event;
8088 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
8089 DNS_EVENT_FETCHCONTROL,
8090 fctx_start, fctx, NULL,
8092 isc_task_send(res->buckets[bucketnum].task, &event);
8095 * We don't care about the result of fctx_unlink()
8096 * since we know we're not exiting.
8098 (void)fctx_unlink(fctx);
8104 UNLOCK(&res->buckets[bucketnum].lock);
8109 if (result == ISC_R_SUCCESS) {
8113 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
8119 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
8121 dns_resolver_t *res;
8122 dns_fetchevent_t *event, *next_event;
8125 REQUIRE(DNS_FETCH_VALID(fetch));
8126 fctx = fetch->private;
8127 REQUIRE(VALID_FCTX(fctx));
8130 FTRACE("cancelfetch");
8132 LOCK(&res->buckets[fctx->bucketnum].lock);
8135 * Find the completion event for this fetch (as opposed
8136 * to those for other fetches that have joined the same
8137 * fctx) and send it with result = ISC_R_CANCELED.
8140 if (fctx->state != fetchstate_done) {
8141 for (event = ISC_LIST_HEAD(fctx->events);
8143 event = next_event) {
8144 next_event = ISC_LIST_NEXT(event, ev_link);
8145 if (event->fetch == fetch) {
8146 ISC_LIST_UNLINK(fctx->events, event, ev_link);
8151 if (event != NULL) {
8152 etask = event->ev_sender;
8153 event->ev_sender = fctx;
8154 event->result = ISC_R_CANCELED;
8155 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
8158 * The fctx continues running even if no fetches remain;
8159 * the answer is still cached.
8162 UNLOCK(&res->buckets[fctx->bucketnum].lock);
8166 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
8168 dns_resolver_t *res;
8169 dns_fetchevent_t *event, *next_event;
8171 unsigned int bucketnum;
8172 isc_boolean_t bucket_empty;
8174 REQUIRE(fetchp != NULL);
8176 REQUIRE(DNS_FETCH_VALID(fetch));
8177 fctx = fetch->private;
8178 REQUIRE(VALID_FCTX(fctx));
8181 FTRACE("destroyfetch");
8183 bucketnum = fctx->bucketnum;
8184 LOCK(&res->buckets[bucketnum].lock);
8187 * Sanity check: the caller should have gotten its event before
8188 * trying to destroy the fetch.
8191 if (fctx->state != fetchstate_done) {
8192 for (event = ISC_LIST_HEAD(fctx->events);
8194 event = next_event) {
8195 next_event = ISC_LIST_NEXT(event, ev_link);
8196 RUNTIME_CHECK(event->fetch != fetch);
8200 bucket_empty = fctx_decreference(fctx);
8202 UNLOCK(&res->buckets[bucketnum].lock);
8204 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
8212 dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
8213 isc_logcategory_t *category, isc_logmodule_t *module,
8214 int level, isc_boolean_t duplicateok)
8217 dns_resolver_t *res;
8218 char domainbuf[DNS_NAME_FORMATSIZE];
8220 REQUIRE(DNS_FETCH_VALID(fetch));
8221 fctx = fetch->private;
8222 REQUIRE(VALID_FCTX(fctx));
8225 LOCK(&res->buckets[fctx->bucketnum].lock);
8227 INSIST(fctx->exitline >= 0);
8228 if (!fctx->logged || duplicateok) {
8229 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
8230 isc_log_write(lctx, category, module, level,
8231 "fetch completed at %s:%d for %s in "
8232 "%" ISC_PRINT_QUADFORMAT "u."
8233 "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
8234 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
8235 "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
8236 "adberr:%u,findfail:%u,valfail:%u]",
8237 __FILE__, fctx->exitline, fctx->info,
8238 fctx->duration / US_PER_SEC,
8239 fctx->duration % US_PER_SEC,
8240 isc_result_totext(fctx->result),
8241 isc_result_totext(fctx->vresult), domainbuf,
8242 fctx->referrals, fctx->restarts,
8243 fctx->querysent, fctx->timeouts, fctx->lamecount,
8244 fctx->neterr, fctx->badresp, fctx->adberr,
8245 fctx->findfail, fctx->valfail);
8246 fctx->logged = ISC_TRUE;
8249 UNLOCK(&res->buckets[fctx->bucketnum].lock);
8253 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
8254 REQUIRE(VALID_RESOLVER(resolver));
8255 return (resolver->dispatchmgr);
8259 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
8260 REQUIRE(VALID_RESOLVER(resolver));
8261 return (resolver->dispatchv4);
8265 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
8266 REQUIRE(VALID_RESOLVER(resolver));
8267 return (resolver->dispatchv6);
8271 dns_resolver_socketmgr(dns_resolver_t *resolver) {
8272 REQUIRE(VALID_RESOLVER(resolver));
8273 return (resolver->socketmgr);
8277 dns_resolver_taskmgr(dns_resolver_t *resolver) {
8278 REQUIRE(VALID_RESOLVER(resolver));
8279 return (resolver->taskmgr);
8283 dns_resolver_getlamettl(dns_resolver_t *resolver) {
8284 REQUIRE(VALID_RESOLVER(resolver));
8285 return (resolver->lame_ttl);
8289 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
8290 REQUIRE(VALID_RESOLVER(resolver));
8291 resolver->lame_ttl = lame_ttl;
8295 dns_resolver_nrunning(dns_resolver_t *resolver) {
8297 LOCK(&resolver->nlock);
8298 n = resolver->nfctx;
8299 UNLOCK(&resolver->nlock);
8304 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
8305 dns_name_t *name, in_port_t port) {
8307 isc_result_t result;
8309 REQUIRE(VALID_RESOLVER(resolver));
8310 REQUIRE(!resolver->frozen);
8311 REQUIRE((alt == NULL) ^ (name == NULL));
8313 a = isc_mem_get(resolver->mctx, sizeof(*a));
8315 return (ISC_R_NOMEMORY);
8317 a->isaddress = ISC_TRUE;
8320 a->isaddress = ISC_FALSE;
8321 a->_u._n.port = port;
8322 dns_name_init(&a->_u._n.name, NULL);
8323 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
8324 if (result != ISC_R_SUCCESS) {
8325 isc_mem_put(resolver->mctx, a, sizeof(*a));
8329 ISC_LINK_INIT(a, link);
8330 ISC_LIST_APPEND(resolver->alternates, a, link);
8332 return (ISC_R_SUCCESS);
8336 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
8337 REQUIRE(VALID_RESOLVER(resolver));
8338 resolver->udpsize = udpsize;
8342 dns_resolver_getudpsize(dns_resolver_t *resolver) {
8343 REQUIRE(VALID_RESOLVER(resolver));
8344 return (resolver->udpsize);
8348 dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
8350 dns_badcache_t *bad, *prev, *next;
8352 REQUIRE(VALID_RESOLVER(resolver));
8354 LOCK(&resolver->lock);
8355 if (resolver->badcache == NULL)
8360 isc_result_t result;
8361 result = isc_time_now(&now);
8362 if (result != ISC_R_SUCCESS)
8363 isc_time_settoepoch(&now);
8364 i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
8366 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8369 n = isc_time_compare(&bad->expire, &now);
8370 if (n < 0 || dns_name_equal(name, &bad->name)) {
8372 resolver->badcache[i] = bad->next;
8374 prev->next = bad->next;
8375 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8377 resolver->badcount--;
8382 destroy_badcache(resolver);
8385 UNLOCK(&resolver->lock);
8390 resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
8391 unsigned int newsize;
8392 dns_badcache_t **new, *bad, *next;
8396 newsize = resolver->badhash * 2 + 1;
8398 newsize = (resolver->badhash - 1) / 2;
8400 new = isc_mem_get(resolver->mctx,
8401 sizeof(*resolver->badcache) * newsize);
8404 memset(new, 0, sizeof(*resolver->badcache) * newsize);
8405 for (i = 0; i < resolver->badhash; i++) {
8406 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8408 if (isc_time_compare(&bad->expire, now) < 0) {
8409 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8411 resolver->badcount--;
8413 bad->next = new[bad->hashval % newsize];
8414 new[bad->hashval % newsize] = bad;
8418 isc_mem_put(resolver->mctx, resolver->badcache,
8419 sizeof(*resolver->badcache) * resolver->badhash);
8420 resolver->badhash = newsize;
8421 resolver->badcache = new;
8425 dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
8426 dns_rdatatype_t type, isc_time_t *expire)
8429 isc_result_t result = ISC_R_SUCCESS;
8430 unsigned int i, hashval;
8431 dns_badcache_t *bad, *prev, *next;
8433 REQUIRE(VALID_RESOLVER(resolver));
8435 LOCK(&resolver->lock);
8436 if (resolver->badcache == NULL) {
8437 resolver->badcache = isc_mem_get(resolver->mctx,
8438 sizeof(*resolver->badcache) *
8440 if (resolver->badcache == NULL)
8442 resolver->badhash = DNS_BADCACHE_SIZE;
8443 memset(resolver->badcache, 0, sizeof(*resolver->badcache) *
8447 result = isc_time_now(&now);
8448 if (result != ISC_R_SUCCESS)
8449 isc_time_settoepoch(&now);
8450 hashval = dns_name_hash(name, ISC_FALSE);
8451 i = hashval % resolver->badhash;
8453 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8455 if (bad->type == type && dns_name_equal(name, &bad->name))
8457 if (isc_time_compare(&bad->expire, &now) < 0) {
8459 resolver->badcache[i] = bad->next;
8461 prev->next = bad->next;
8462 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8464 resolver->badcount--;
8469 isc_buffer_t buffer;
8470 bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
8474 bad->hashval = hashval;
8475 bad->expire = *expire;
8476 isc_buffer_init(&buffer, bad + 1, name->length);
8477 dns_name_init(&bad->name, NULL);
8478 dns_name_copy(name, &bad->name, &buffer);
8479 bad->next = resolver->badcache[i];
8480 resolver->badcache[i] = bad;
8481 resolver->badcount++;
8482 if (resolver->badcount > resolver->badhash * 8)
8483 resizehash(resolver, &now, ISC_TRUE);
8484 if (resolver->badcount < resolver->badhash * 2 &&
8485 resolver->badhash > DNS_BADCACHE_SIZE)
8486 resizehash(resolver, &now, ISC_FALSE);
8488 bad->expire = *expire;
8490 UNLOCK(&resolver->lock);
8494 dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
8495 dns_rdatatype_t type, isc_time_t *now)
8497 dns_badcache_t *bad, *prev, *next;
8498 isc_boolean_t answer = ISC_FALSE;
8501 REQUIRE(VALID_RESOLVER(resolver));
8503 LOCK(&resolver->lock);
8504 if (resolver->badcache == NULL)
8507 i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
8509 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8512 * Search the hash list. Clean out expired records as we go.
8514 if (isc_time_compare(&bad->expire, now) < 0) {
8516 prev->next = bad->next;
8518 resolver->badcache[i] = bad->next;
8519 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8521 resolver->badcount--;
8524 if (bad->type == type && dns_name_equal(name, &bad->name)) {
8532 * Slow sweep to clean out stale records.
8534 i = resolver->badsweep++ % resolver->badhash;
8535 bad = resolver->badcache[i];
8536 if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) {
8537 resolver->badcache[i] = bad->next;
8538 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8540 resolver->badcount--;
8544 UNLOCK(&resolver->lock);
8549 dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
8550 char namebuf[DNS_NAME_FORMATSIZE];
8551 char typebuf[DNS_RDATATYPE_FORMATSIZE];
8552 dns_badcache_t *bad, *next, *prev;
8557 LOCK(&resolver->lock);
8558 fprintf(fp, ";\n; Bad cache\n;\n");
8560 if (resolver->badcache == NULL)
8564 for (i = 0; i < resolver->badhash; i++) {
8566 for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
8568 if (isc_time_compare(&bad->expire, &now) < 0) {
8570 prev->next = bad->next;
8572 resolver->badcache[i] = bad->next;
8573 isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
8575 resolver->badcount--;
8579 dns_name_format(&bad->name, namebuf, sizeof(namebuf));
8580 dns_rdatatype_format(bad->type, typebuf,
8582 t = isc_time_microdiff(&bad->expire, &now);
8584 fprintf(fp, "; %s/%s [ttl "
8585 "%" ISC_PLATFORM_QUADFORMAT "u]\n",
8586 namebuf, typebuf, t);
8591 UNLOCK(&resolver->lock);
8595 free_algorithm(void *node, void *arg) {
8596 unsigned char *algorithms = node;
8597 isc_mem_t *mctx = arg;
8599 isc_mem_put(mctx, algorithms, *algorithms);
8603 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
8605 REQUIRE(VALID_RESOLVER(resolver));
8608 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8610 if (resolver->algorithms != NULL)
8611 dns_rbt_destroy(&resolver->algorithms);
8613 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8618 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
8621 unsigned int len, mask;
8623 unsigned char *algorithms;
8624 isc_result_t result;
8625 dns_rbtnode_t *node = NULL;
8627 REQUIRE(VALID_RESOLVER(resolver));
8629 return (ISC_R_RANGE);
8632 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
8634 if (resolver->algorithms == NULL) {
8635 result = dns_rbt_create(resolver->mctx, free_algorithm,
8636 resolver->mctx, &resolver->algorithms);
8637 if (result != ISC_R_SUCCESS)
8642 mask = 1 << (alg%8);
8644 result = dns_rbt_addnode(resolver->algorithms, name, &node);
8646 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
8647 algorithms = node->data;
8648 if (algorithms == NULL || len > *algorithms) {
8649 new = isc_mem_get(resolver->mctx, len);
8651 result = ISC_R_NOMEMORY;
8654 memset(new, 0, len);
8655 if (algorithms != NULL)
8656 memcpy(new, algorithms, *algorithms);
8660 if (algorithms != NULL)
8661 isc_mem_put(resolver->mctx, algorithms,
8664 algorithms[len-1] |= mask;
8666 result = ISC_R_SUCCESS;
8669 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
8675 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
8678 unsigned int len, mask;
8679 unsigned char *algorithms;
8681 isc_result_t result;
8682 isc_boolean_t found = ISC_FALSE;
8684 REQUIRE(VALID_RESOLVER(resolver));
8687 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
8689 if (resolver->algorithms == NULL)
8691 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
8692 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
8694 mask = 1 << (alg%8);
8696 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
8701 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
8705 return (dst_algorithm_supported(alg));
8709 dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
8712 return (dns_ds_digest_supported(digest));
8716 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
8718 REQUIRE(VALID_RESOLVER(resolver));
8721 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8723 if (resolver->mustbesecure != NULL)
8724 dns_rbt_destroy(&resolver->mustbesecure);
8726 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8730 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
8733 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
8734 isc_boolean_t value)
8736 isc_result_t result;
8738 REQUIRE(VALID_RESOLVER(resolver));
8741 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
8743 if (resolver->mustbesecure == NULL) {
8744 result = dns_rbt_create(resolver->mctx, NULL, NULL,
8745 &resolver->mustbesecure);
8746 if (result != ISC_R_SUCCESS)
8749 result = dns_rbt_addname(resolver->mustbesecure, name,
8750 value ? &yes : &no);
8753 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
8759 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
8761 isc_boolean_t value = ISC_FALSE;
8762 isc_result_t result;
8764 REQUIRE(VALID_RESOLVER(resolver));
8767 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
8769 if (resolver->mustbesecure == NULL)
8771 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
8772 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
8773 value = *(isc_boolean_t*)data;
8776 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
8782 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
8783 isc_uint32_t *min, isc_uint32_t *max)
8785 REQUIRE(VALID_RESOLVER(resolver));
8787 LOCK(&resolver->lock);
8789 *cur = resolver->spillat;
8791 *min = resolver->spillatmin;
8793 *max = resolver->spillatmax;
8794 UNLOCK(&resolver->lock);
8798 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
8801 REQUIRE(VALID_RESOLVER(resolver));
8803 LOCK(&resolver->lock);
8804 resolver->spillatmin = resolver->spillat = min;
8805 resolver->spillatmax = max;
8806 UNLOCK(&resolver->lock);
8810 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
8811 REQUIRE(VALID_RESOLVER(resolver));
8813 return (resolver->zero_no_soa_ttl);
8817 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
8818 REQUIRE(VALID_RESOLVER(resolver));
8820 resolver->zero_no_soa_ttl = state;
8824 dns_resolver_getoptions(dns_resolver_t *resolver) {
8825 REQUIRE(VALID_RESOLVER(resolver));
8827 return (resolver->options);
8831 dns_resolver_gettimeout(dns_resolver_t *resolver) {
8832 REQUIRE(VALID_RESOLVER(resolver));
8834 return (resolver->query_timeout);
8838 dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
8839 REQUIRE(VALID_RESOLVER(resolver));
8842 seconds = DEFAULT_QUERY_TIMEOUT;
8843 if (seconds > MAXIMUM_QUERY_TIMEOUT)
8844 seconds = MAXIMUM_QUERY_TIMEOUT;
8845 if (seconds < MINIMUM_QUERY_TIMEOUT)
8846 seconds = MINIMUM_QUERY_TIMEOUT;
8848 resolver->query_timeout = seconds;