2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
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.
18 /* $Id: resolver.c,v 1.218.2.34 2004/07/03 00:56:55 marka Exp $ */
22 #include <isc/string.h>
24 #include <isc/timer.h>
30 #include <dns/dispatch.h>
31 #include <dns/events.h>
32 #include <dns/forward.h>
33 #include <dns/keytable.h>
35 #include <dns/message.h>
36 #include <dns/ncache.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/resolver.h>
45 #include <dns/result.h>
47 #include <dns/validator.h>
49 #define DNS_RESOLVER_TRACE
50 #ifdef DNS_RESOLVER_TRACE
51 #define RTRACE(m) isc_log_write(dns_lctx, \
52 DNS_LOGCATEGORY_RESOLVER, \
53 DNS_LOGMODULE_RESOLVER, \
55 "res %p: %s", res, (m))
56 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
57 DNS_LOGCATEGORY_RESOLVER, \
58 DNS_LOGMODULE_RESOLVER, \
60 "res %p: %s", (r), (m))
61 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
62 DNS_LOGCATEGORY_RESOLVER, \
63 DNS_LOGMODULE_RESOLVER, \
65 "fctx %p: %s", fctx, (m))
66 #define FCTXTRACE2(m1, m2) \
67 isc_log_write(dns_lctx, \
68 DNS_LOGCATEGORY_RESOLVER, \
69 DNS_LOGMODULE_RESOLVER, \
71 "fctx %p: %s %s", fctx, (m1), (m2))
72 #define FTRACE(m) isc_log_write(dns_lctx, \
73 DNS_LOGCATEGORY_RESOLVER, \
74 DNS_LOGMODULE_RESOLVER, \
76 "fetch %p (fctx %p): %s", \
77 fetch, fetch->private, (m))
78 #define QTRACE(m) isc_log_write(dns_lctx, \
79 DNS_LOGCATEGORY_RESOLVER, \
80 DNS_LOGMODULE_RESOLVER, \
82 "resquery %p (fctx %p): %s", \
83 query, query->fctx, (m))
93 * Maximum EDNS0 input packet size.
95 #define SEND_BUFFER_SIZE 2048 /* XXXRTH Constant. */
98 * This defines the maximum number of timeouts we will permit before we
99 * disable EDNS0 on the query.
101 #define MAX_EDNS0_TIMEOUTS 3
103 typedef struct fetchctx fetchctx_t;
105 typedef struct query {
106 /* Locked by task event serialization. */
110 dns_dispatchmgr_t * dispatchmgr;
111 dns_dispatch_t * dispatch;
112 dns_adbaddrinfo_t * addrinfo;
113 isc_socket_t * tcpsocket;
116 dns_dispentry_t * dispentry;
117 ISC_LINK(struct query) link;
120 dns_tsigkey_t *tsigkey;
121 unsigned int options;
122 unsigned int attributes;
124 unsigned int connects;
125 unsigned char data[512];
128 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
129 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
131 #define RESQUERY_ATTR_CANCELED 0x02
133 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
134 #define RESQUERY_CANCELED(q) (((q)->attributes & \
135 RESQUERY_ATTR_CANCELED) != 0)
136 #define RESQUERY_SENDING(q) ((q)->sends > 0)
139 fetchstate_init = 0, /* Start event has not run yet. */
141 fetchstate_done /* FETCHDONE events posted. */
147 dns_resolver_t * res;
149 dns_rdatatype_t type;
150 unsigned int options;
151 unsigned int bucketnum;
152 /* Locked by appropriate bucket lock. */
154 isc_boolean_t want_shutdown;
155 isc_boolean_t cloned;
156 unsigned int references;
157 isc_event_t control_event;
158 ISC_LINK(struct fetchctx) link;
159 ISC_LIST(dns_fetchevent_t) events;
160 /* Locked by task event serialization. */
162 dns_rdataset_t nameservers;
163 unsigned int attributes;
166 isc_interval_t interval;
167 dns_message_t * qmessage;
168 dns_message_t * rmessage;
169 ISC_LIST(resquery_t) queries;
170 dns_adbfindlist_t finds;
171 dns_adbfind_t * find;
172 dns_adbaddrinfolist_t forwaddrs;
173 isc_sockaddrlist_t forwarders;
174 dns_fwdpolicy_t fwdpolicy;
175 isc_sockaddrlist_t bad;
176 ISC_LIST(dns_validator_t) validators;
181 * The number of events we're waiting for.
183 unsigned int pending;
186 * The number of times we've "restarted" the current
187 * nameserver set. This acts as a failsafe to prevent
188 * us from pounding constantly on a particular set of
189 * servers that, for whatever reason, are not giving
190 * us useful responses, but are responding in such a
191 * way that they are not marked "bad".
193 unsigned int restarts;
196 * The number of timeouts that have occurred since we
197 * last successfully received a response packet. This
198 * is used for EDNS0 black hole detection.
200 unsigned int timeouts;
203 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
204 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
206 #define FCTX_ATTR_HAVEANSWER 0x01
207 #define FCTX_ATTR_GLUING 0x02
208 #define FCTX_ATTR_ADDRWAIT 0x04
209 #define FCTX_ATTR_SHUTTINGDOWN 0x08
210 #define FCTX_ATTR_WANTCACHE 0x10
211 #define FCTX_ATTR_WANTNCACHE 0x20
212 #define FCTX_ATTR_NEEDEDNS0 0x40
214 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
216 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
218 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
220 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
222 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
223 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
224 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
228 fetchctx_t * private;
231 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
232 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
234 typedef struct fctxbucket {
237 ISC_LIST(fetchctx_t) fctxs;
238 isc_boolean_t exiting;
241 struct dns_resolver {
246 isc_mutex_t primelock;
247 dns_rdataclass_t rdclass;
248 isc_socketmgr_t * socketmgr;
249 isc_timermgr_t * timermgr;
250 isc_taskmgr_t * taskmgr;
252 isc_boolean_t frozen;
253 unsigned int options;
254 dns_dispatchmgr_t * dispatchmgr;
255 dns_dispatch_t * dispatchv4;
256 dns_dispatch_t * dispatchv6;
257 unsigned int nbuckets;
258 fctxbucket_t * buckets;
259 isc_uint32_t lame_ttl;
260 /* Locked by lock. */
261 unsigned int references;
262 isc_boolean_t exiting;
263 isc_eventlist_t whenshutdown;
264 unsigned int activebuckets;
265 isc_boolean_t priming;
266 /* Locked by primelock. */
267 dns_fetch_t * primefetch;
270 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
271 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
274 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
275 * which we also use as an addrinfo flag.
277 #define FCTX_ADDRINFO_MARK 0x0001
278 #define FCTX_ADDRINFO_FORWARDER 0x1000
279 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
281 #define ISFORWARDER(a) (((a)->flags & \
282 FCTX_ADDRINFO_FORWARDER) != 0)
284 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
286 static void destroy(dns_resolver_t *res);
287 static void empty_bucket(dns_resolver_t *res);
288 static isc_result_t resquery_send(resquery_t *query);
289 static void resquery_response(isc_task_t *task, isc_event_t *event);
290 static void resquery_connected(isc_task_t *task, isc_event_t *event);
291 static void fctx_try(fetchctx_t *fctx);
292 static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
293 static isc_result_t ncache_adderesult(dns_message_t *message,
294 dns_db_t *cache, dns_dbnode_t *node,
295 dns_rdatatype_t covers,
296 isc_stdtime_t now, dns_ttl_t maxttl,
297 dns_rdataset_t *ardataset,
298 isc_result_t *eresultp);
301 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
303 dns_name_t *domain = &fctx->domain;
304 dns_rdataset_t *rdataset;
305 dns_rdatatype_t type;
307 isc_boolean_t keep_auth = ISC_FALSE;
309 if (message->rcode == dns_rcode_nxdomain)
313 * Look for BIND 8 style delegations.
314 * Also look for answers to ANY queries where the duplicate NS RRset
315 * may have been stripped from the authority section.
317 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
318 (fctx->type == dns_rdatatype_ns ||
319 fctx->type == dns_rdatatype_any)) {
320 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
321 while (result == ISC_R_SUCCESS) {
323 dns_message_currentname(message, DNS_SECTION_ANSWER,
325 for (rdataset = ISC_LIST_HEAD(name->list);
327 rdataset = ISC_LIST_NEXT(rdataset, link)) {
328 type = rdataset->type;
329 if (type != dns_rdatatype_ns)
331 if (dns_name_issubdomain(name, domain))
334 result = dns_message_nextname(message,
339 /* Look for referral. */
340 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
343 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
344 while (result == ISC_R_SUCCESS) {
346 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
347 for (rdataset = ISC_LIST_HEAD(name->list);
349 rdataset = ISC_LIST_NEXT(rdataset, link)) {
350 type = rdataset->type;
351 if (type == dns_rdatatype_soa &&
352 dns_name_equal(name, domain))
353 keep_auth = ISC_TRUE;
354 if (type != dns_rdatatype_ns &&
355 type != dns_rdatatype_soa)
357 if (dns_name_equal(name, domain))
359 if (dns_name_issubdomain(name, domain))
362 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
366 message->rcode = dns_rcode_nxdomain;
367 message->counts[DNS_SECTION_ANSWER] = 0;
369 message->counts[DNS_SECTION_AUTHORITY] = 0;
370 message->counts[DNS_SECTION_ADDITIONAL] = 0;
374 static inline isc_result_t
375 fctx_starttimer(fetchctx_t *fctx) {
377 * Start the lifetime timer for fctx.
379 * This is also used for stopping the idle timer; in that
380 * case we must purge events already posted to ensure that
381 * no further idle events are delivered.
383 return (isc_timer_reset(fctx->timer, isc_timertype_once,
384 &fctx->expires, NULL,
389 fctx_stoptimer(fetchctx_t *fctx) {
393 * We don't return a result if resetting the timer to inactive fails
394 * since there's nothing to be done about it. Resetting to inactive
395 * should never fail anyway, since the code as currently written
396 * cannot fail in that case.
398 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
399 NULL, NULL, ISC_TRUE);
400 if (result != ISC_R_SUCCESS) {
401 UNEXPECTED_ERROR(__FILE__, __LINE__,
402 "isc_timer_reset(): %s",
403 isc_result_totext(result));
408 static inline isc_result_t
409 fctx_startidletimer(fetchctx_t *fctx) {
411 * Start the idle timer for fctx. The lifetime timer continues
414 return (isc_timer_reset(fctx->timer, isc_timertype_once,
415 &fctx->expires, &fctx->interval,
420 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
421 * we use fctx_stopidletimer for readability in the code below.
423 #define fctx_stopidletimer fctx_starttimer
427 resquery_destroy(resquery_t **queryp) {
430 REQUIRE(queryp != NULL);
432 REQUIRE(!ISC_LINK_LINKED(query, link));
434 INSIST(query->tcpsocket == NULL);
437 isc_mem_put(query->mctx, query, sizeof(*query));
442 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
443 isc_time_t *finish, isc_boolean_t no_response)
453 FCTXTRACE("cancelquery");
455 REQUIRE(!RESQUERY_CANCELED(query));
457 query->attributes |= RESQUERY_ATTR_CANCELED;
460 * Should we update the RTT?
462 if (finish != NULL || no_response) {
463 if (finish != NULL) {
465 * We have both the start and finish times for this
466 * packet, so we can compute a real RTT.
468 rtt = (unsigned int)isc_time_microdiff(finish,
470 factor = DNS_ADB_RTTADJDEFAULT;
473 * We don't have an RTT for this query. Maybe the
474 * packet was lost, or maybe this server is very
475 * slow. We don't know. Increase the RTT.
478 rtt = query->addrinfo->srtt +
479 (100000 * fctx->restarts);
483 * Replace the current RTT with our value.
485 factor = DNS_ADB_RTTADJREPLACE;
487 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
491 * Age RTTs of servers not tried.
493 if (finish != NULL) {
495 dns_adbaddrinfo_t *addrinfo;
497 factor = DNS_ADB_RTTADJAGE;
498 for (find = ISC_LIST_HEAD(fctx->finds);
500 find = ISC_LIST_NEXT(find, publink))
501 for (addrinfo = ISC_LIST_HEAD(find->list);
503 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
504 if (UNMARKED(addrinfo))
505 dns_adb_adjustsrtt(fctx->adb, addrinfo,
509 if (query->dispentry != NULL)
510 dns_dispatch_removeresponse(&query->dispentry, deventp);
512 ISC_LIST_UNLINK(fctx->queries, query, link);
514 if (query->tsig != NULL)
515 isc_buffer_free(&query->tsig);
517 if (query->tsigkey != NULL)
518 dns_tsigkey_detach(&query->tsigkey);
521 * Check for any outstanding socket events. If they exist, cancel
522 * them and let the event handlers finish the cleanup. The resolver
523 * only needs to worry about managing the connect and send events;
524 * the dispatcher manages the recv events.
526 if (RESQUERY_CONNECTING(query))
528 * Cancel the connect.
530 isc_socket_cancel(query->tcpsocket, NULL,
531 ISC_SOCKCANCEL_CONNECT);
532 else if (RESQUERY_SENDING(query))
534 * Cancel the pending send.
536 isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
537 NULL, ISC_SOCKCANCEL_SEND);
539 if (query->dispatch != NULL)
540 dns_dispatch_detach(&query->dispatch);
542 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
544 * It's safe to destroy the query now.
546 resquery_destroy(&query);
550 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
551 resquery_t *query, *next_query;
553 FCTXTRACE("cancelqueries");
555 for (query = ISC_LIST_HEAD(fctx->queries);
557 query = next_query) {
558 next_query = ISC_LIST_NEXT(query, link);
559 fctx_cancelquery(&query, NULL, NULL, no_response);
564 fctx_cleanupfinds(fetchctx_t *fctx) {
565 dns_adbfind_t *find, *next_find;
567 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
569 for (find = ISC_LIST_HEAD(fctx->finds);
572 next_find = ISC_LIST_NEXT(find, publink);
573 ISC_LIST_UNLINK(fctx->finds, find, publink);
574 dns_adb_destroyfind(&find);
580 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
581 dns_adbaddrinfo_t *addr, *next_addr;
583 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
585 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
588 next_addr = ISC_LIST_NEXT(addr, publink);
589 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
590 dns_adb_freeaddrinfo(fctx->adb, &addr);
595 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
596 FCTXTRACE("stopeverything");
597 fctx_cancelqueries(fctx, no_response);
598 fctx_cleanupfinds(fctx);
599 fctx_cleanupforwaddrs(fctx);
600 fctx_stoptimer(fctx);
604 fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
605 dns_fetchevent_t *event, *next_event;
609 * Caller must be holding the appropriate bucket lock.
611 REQUIRE(fctx->state == fetchstate_done);
613 FCTXTRACE("sendevents");
615 for (event = ISC_LIST_HEAD(fctx->events);
617 event = next_event) {
618 next_event = ISC_LIST_NEXT(event, ev_link);
619 ISC_LIST_UNLINK(fctx->events, event, ev_link);
620 task = event->ev_sender;
621 event->ev_sender = fctx;
622 if (!HAVE_ANSWER(fctx))
623 event->result = result;
625 INSIST(result != ISC_R_SUCCESS ||
626 dns_rdataset_isassociated(event->rdataset) ||
627 fctx->type == dns_rdatatype_any ||
628 fctx->type == dns_rdatatype_sig);
630 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
635 fctx_done(fetchctx_t *fctx, isc_result_t result) {
637 isc_boolean_t no_response;
643 if (result == ISC_R_SUCCESS)
644 no_response = ISC_TRUE;
646 no_response = ISC_FALSE;
647 fctx_stopeverything(fctx, no_response);
649 LOCK(&res->buckets[fctx->bucketnum].lock);
651 fctx->state = fetchstate_done;
652 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
653 fctx_sendevents(fctx, result);
655 UNLOCK(&res->buckets[fctx->bucketnum].lock);
659 resquery_senddone(isc_task_t *task, isc_event_t *event) {
660 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
661 resquery_t *query = event->ev_arg;
663 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
670 * Currently we don't wait for the senddone event before retrying
671 * a query. This means that if we get really behind, we may end
672 * up doing extra work!
677 INSIST(RESQUERY_SENDING(query));
681 if (RESQUERY_CANCELED(query)) {
682 if (query->sends == 0) {
684 * This query was canceled while the
685 * isc_socket_sendto() was in progress.
687 if (query->tcpsocket != NULL)
688 isc_socket_detach(&query->tcpsocket);
689 resquery_destroy(&query);
691 } else if (sevent->result != ISC_R_SUCCESS)
692 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
694 isc_event_free(&event);
697 static inline isc_result_t
698 fctx_addopt(dns_message_t *message) {
699 dns_rdataset_t *rdataset;
700 dns_rdatalist_t *rdatalist;
705 result = dns_message_gettemprdatalist(message, &rdatalist);
706 if (result != ISC_R_SUCCESS)
709 result = dns_message_gettemprdata(message, &rdata);
710 if (result != ISC_R_SUCCESS)
713 result = dns_message_gettemprdataset(message, &rdataset);
714 if (result != ISC_R_SUCCESS)
716 dns_rdataset_init(rdataset);
718 rdatalist->type = dns_rdatatype_opt;
719 rdatalist->covers = 0;
722 * Set Maximum UDP buffer size.
724 rdatalist->rdclass = SEND_BUFFER_SIZE;
727 * Set EXTENDED-RCODE, VERSION, and Z to 0, and the DO bit to 1.
730 rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO;
740 rdata->rdclass = rdatalist->rdclass;
741 rdata->type = rdatalist->type;
744 ISC_LIST_INIT(rdatalist->rdata);
745 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
746 dns_rdatalist_tordataset(rdatalist, rdataset);
748 return (dns_message_setopt(message, rdataset));
752 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
753 unsigned int seconds;
756 * We retry every 2 seconds the first two times through the address
757 * list, and then we do exponential back-off.
759 if (fctx->restarts < 3)
762 seconds = (2 << (fctx->restarts - 1));
765 * Double the round-trip time and convert to seconds.
770 * Always wait for at least the doubled round-trip time.
776 * But don't ever wait for more than 30 seconds.
781 isc_interval_set(&fctx->interval, seconds, 0);
785 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
786 unsigned int options)
796 task = res->buckets[fctx->bucketnum].task;
798 fctx_setretryinterval(fctx, addrinfo->srtt);
799 result = fctx_startidletimer(fctx);
800 if (result != ISC_R_SUCCESS)
803 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
805 query = isc_mem_get(res->mctx, sizeof *query);
807 result = ISC_R_NOMEMORY;
808 goto stop_idle_timer;
810 query->mctx = res->mctx;
811 query->options = options;
812 query->attributes = 0;
816 * Note that the caller MUST guarantee that 'addrinfo' will remain
817 * valid until this query is canceled.
819 query->addrinfo = addrinfo;
820 result = isc_time_now(&query->start);
821 if (result != ISC_R_SUCCESS)
825 * If this is a TCP query, then we need to make a socket and
826 * a dispatch for it here. Otherwise we use the resolver's
829 query->dispatchmgr = res->dispatchmgr;
830 query->dispatch = NULL;
831 query->tcpsocket = NULL;
832 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
836 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
840 result = dns_dispatch_getlocaladdress(res->dispatchv4,
844 result = dns_dispatch_getlocaladdress(res->dispatchv6,
848 result = ISC_R_NOTIMPLEMENTED;
851 if (result != ISC_R_SUCCESS)
854 isc_sockaddr_setport(&addr, 0);
856 result = isc_socket_create(res->socketmgr, pf,
859 if (result != ISC_R_SUCCESS)
862 result = isc_socket_bind(query->tcpsocket, &addr);
863 if (result != ISC_R_SUCCESS)
867 * A dispatch will be created once the connect succeeds.
870 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
872 dns_dispatch_attach(res->dispatchv4, &query->dispatch);
875 dns_dispatch_attach(res->dispatchv6, &query->dispatch);
878 result = ISC_R_NOTIMPLEMENTED;
882 * We should always have a valid dispatcher here. If we
883 * don't support a protocol family, then its dispatcher
884 * will be NULL, but we shouldn't be finding addresses for
885 * protocol types we don't support, so the dispatcher
886 * we found should never be NULL.
888 INSIST(query->dispatch != NULL);
891 query->dispentry = NULL;
894 query->tsigkey = NULL;
895 ISC_LINK_INIT(query, link);
896 query->magic = QUERY_MAGIC;
898 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
900 * Connect to the remote server.
902 * XXXRTH Should we attach to the socket?
904 result = isc_socket_connect(query->tcpsocket,
905 &addrinfo->sockaddr, task,
906 resquery_connected, query);
907 if (result != ISC_R_SUCCESS)
910 QTRACE("connecting via TCP");
912 result = resquery_send(query);
913 if (result != ISC_R_SUCCESS)
914 goto cleanup_dispatch;
917 ISC_LIST_APPEND(fctx->queries, query, link);
919 return (ISC_R_SUCCESS);
922 isc_socket_detach(&query->tcpsocket);
925 if (query->dispatch != NULL)
926 dns_dispatch_detach(&query->dispatch);
930 isc_mem_put(res->mctx, query, sizeof *query);
933 fctx_stopidletimer(fctx);
939 resquery_send(resquery_t *query) {
942 dns_name_t *qname = NULL;
943 dns_rdataset_t *qrdataset = NULL;
947 isc_socket_t *socket;
948 isc_buffer_t tcpbuffer;
949 isc_sockaddr_t *address;
950 isc_buffer_t *buffer;
951 isc_netaddr_t ipaddr;
952 dns_tsigkey_t *tsigkey = NULL;
953 dns_peer_t *peer = NULL;
954 isc_boolean_t useedns;
956 isc_boolean_t cleanup_cctx = ISC_FALSE;
962 task = res->buckets[fctx->bucketnum].task;
965 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
967 * Reserve space for the TCP message length.
969 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
970 isc_buffer_init(&query->buffer, query->data + 2,
971 sizeof(query->data) - 2);
974 isc_buffer_init(&query->buffer, query->data,
975 sizeof(query->data));
976 buffer = &query->buffer;
979 result = dns_message_gettempname(fctx->qmessage, &qname);
980 if (result != ISC_R_SUCCESS)
982 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
983 if (result != ISC_R_SUCCESS)
987 * Get a query id from the dispatch.
989 result = dns_dispatch_addresponse(query->dispatch,
990 &query->addrinfo->sockaddr,
996 if (result != ISC_R_SUCCESS)
999 fctx->qmessage->opcode = dns_opcode_query;
1004 dns_name_init(qname, NULL);
1005 dns_name_clone(&fctx->name, qname);
1006 dns_rdataset_init(qrdataset);
1007 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1008 ISC_LIST_APPEND(qname->list, qrdataset, link);
1009 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1014 * Set RD if the client has requested that we do a recursive query,
1015 * or if we're sending to a forwarder.
1017 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1018 ISFORWARDER(query->addrinfo))
1019 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1022 * We don't have to set opcode because it defaults to query.
1024 fctx->qmessage->id = query->id;
1027 * Convert the question to wire format.
1029 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1030 if (result != ISC_R_SUCCESS)
1031 goto cleanup_message;
1032 cleanup_cctx = ISC_TRUE;
1034 result = dns_message_renderbegin(fctx->qmessage, &cctx,
1036 if (result != ISC_R_SUCCESS)
1037 goto cleanup_message;
1039 result = dns_message_rendersection(fctx->qmessage,
1040 DNS_SECTION_QUESTION, 0);
1041 if (result != ISC_R_SUCCESS)
1042 goto cleanup_message;
1045 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1046 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1049 * The ADB does not know about servers with "edns no". Check this,
1050 * and then inform the ADB for future use.
1052 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1054 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1057 query->options |= DNS_FETCHOPT_NOEDNS0;
1058 dns_adb_changeflags(fctx->adb,
1060 DNS_FETCHOPT_NOEDNS0,
1061 DNS_FETCHOPT_NOEDNS0);
1065 * Use EDNS0, unless the caller doesn't want it, or we know that
1066 * the remote server doesn't like it.
1068 if (fctx->timeouts >= MAX_EDNS0_TIMEOUTS &&
1069 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1070 query->options |= DNS_FETCHOPT_NOEDNS0;
1071 FCTXTRACE("too many timeouts, disabling EDNS0");
1074 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1075 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1076 result = fctx_addopt(fctx->qmessage);
1077 if (result != ISC_R_SUCCESS) {
1079 * We couldn't add the OPT, but we'll press on.
1080 * We're not using EDNS0, so set the NOEDNS0
1083 query->options |= DNS_FETCHOPT_NOEDNS0;
1087 * We know this server doesn't like EDNS0, so we
1088 * won't use it. Set the NOEDNS0 bit since we're
1091 query->options |= DNS_FETCHOPT_NOEDNS0;
1096 * If we need EDNS0 to do this query and aren't using it, we lose.
1098 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1099 result = DNS_R_SERVFAIL;
1100 goto cleanup_message;
1104 * If we're using EDNS, set CD. CD and EDNS aren't really related,
1105 * but if we send a non EDNS query, there's a chance the server
1106 * won't understand CD either.
1108 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
1109 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1112 * Add TSIG record tailored to the current recipient.
1114 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1115 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1116 goto cleanup_message;
1118 if (tsigkey != NULL) {
1119 dns_message_settsigkey(fctx->qmessage, tsigkey);
1120 dns_tsigkey_detach(&tsigkey);
1123 result = dns_message_rendersection(fctx->qmessage,
1124 DNS_SECTION_ADDITIONAL, 0);
1125 if (result != ISC_R_SUCCESS)
1126 goto cleanup_message;
1128 result = dns_message_renderend(fctx->qmessage);
1129 if (result != ISC_R_SUCCESS)
1130 goto cleanup_message;
1132 dns_compress_invalidate(&cctx);
1133 cleanup_cctx = ISC_FALSE;
1135 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1136 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1138 result = dns_message_getquerytsig(fctx->qmessage,
1141 if (result != ISC_R_SUCCESS)
1142 goto cleanup_message;
1146 * If using TCP, write the length of the message at the beginning
1149 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1150 isc_buffer_usedregion(&query->buffer, &r);
1151 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1152 isc_buffer_add(&tcpbuffer, r.length);
1156 * We're now done with the query message.
1158 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1160 socket = dns_dispatch_getsocket(query->dispatch);
1164 if ((query->options & DNS_FETCHOPT_TCP) == 0)
1165 address = &query->addrinfo->sockaddr;
1166 isc_buffer_usedregion(buffer, &r);
1169 * XXXRTH Make sure we don't send to ourselves! We should probably
1170 * prune out these addresses when we get them from the ADB.
1172 result = isc_socket_sendto(socket, &r, task, resquery_senddone,
1173 query, address, NULL);
1174 if (result != ISC_R_SUCCESS)
1175 goto cleanup_message;
1179 return (ISC_R_SUCCESS);
1183 dns_compress_invalidate(&cctx);
1185 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1188 * Stop the dispatcher from listening.
1190 dns_dispatch_removeresponse(&query->dispentry, NULL);
1194 dns_message_puttempname(fctx->qmessage, &qname);
1195 if (qrdataset != NULL)
1196 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
1202 resquery_connected(isc_task_t *task, isc_event_t *event) {
1203 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1204 resquery_t *query = event->ev_arg;
1205 isc_result_t result;
1207 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1208 REQUIRE(VALID_QUERY(query));
1210 QTRACE("connected");
1217 * Currently we don't wait for the connect event before retrying
1218 * a query. This means that if we get really behind, we may end
1219 * up doing extra work!
1224 if (RESQUERY_CANCELED(query)) {
1226 * This query was canceled while the connect() was in
1229 isc_socket_detach(&query->tcpsocket);
1230 resquery_destroy(&query);
1232 if (sevent->result == ISC_R_SUCCESS) {
1236 * We are connected. Create a dispatcher and
1240 attrs |= DNS_DISPATCHATTR_TCP;
1241 attrs |= DNS_DISPATCHATTR_PRIVATE;
1242 attrs |= DNS_DISPATCHATTR_CONNECTED;
1243 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
1245 attrs |= DNS_DISPATCHATTR_IPV4;
1247 attrs |= DNS_DISPATCHATTR_IPV6;
1248 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
1250 result = dns_dispatch_createtcp(query->dispatchmgr,
1252 query->fctx->res->taskmgr,
1253 4096, 2, 1, 1, 3, attrs,
1257 * Regardless of whether dns_dispatch_create()
1258 * succeeded or not, we don't need our reference
1259 * to the socket anymore.
1261 isc_socket_detach(&query->tcpsocket);
1263 if (result == ISC_R_SUCCESS)
1264 result = resquery_send(query);
1266 if (result != ISC_R_SUCCESS) {
1267 fetchctx_t *fctx = query->fctx;
1268 fctx_cancelquery(&query, NULL, NULL,
1270 fctx_done(fctx, result);
1273 isc_socket_detach(&query->tcpsocket);
1274 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1278 isc_event_free(&event);
1284 fctx_finddone(isc_task_t *task, isc_event_t *event) {
1286 dns_adbfind_t *find;
1287 dns_resolver_t *res;
1288 isc_boolean_t want_try = ISC_FALSE;
1289 isc_boolean_t want_done = ISC_FALSE;
1290 isc_boolean_t bucket_empty = ISC_FALSE;
1291 unsigned int bucketnum;
1293 find = event->ev_sender;
1294 fctx = event->ev_arg;
1295 REQUIRE(VALID_FCTX(fctx));
1300 FCTXTRACE("finddone");
1302 INSIST(fctx->pending > 0);
1305 if (ADDRWAIT(fctx)) {
1307 * The fetch is waiting for a name to be found.
1309 INSIST(!SHUTTINGDOWN(fctx));
1310 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1311 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
1312 want_try = ISC_TRUE;
1313 else if (fctx->pending == 0) {
1315 * We've got nothing else to wait for and don't
1316 * know the answer. There's nothing to do but
1319 want_done = ISC_TRUE;
1321 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
1322 ISC_LIST_EMPTY(fctx->validators)) {
1323 bucketnum = fctx->bucketnum;
1324 LOCK(&res->buckets[bucketnum].lock);
1326 * Note that we had to wait until we had the lock before
1327 * looking at fctx->references.
1329 if (fctx->references == 0)
1330 bucket_empty = fctx_destroy(fctx);
1331 UNLOCK(&res->buckets[bucketnum].lock);
1334 isc_event_free(&event);
1335 dns_adb_destroyfind(&find);
1340 fctx_done(fctx, ISC_R_FAILURE);
1341 else if (bucket_empty)
1346 static inline isc_boolean_t
1347 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
1350 for (sa = ISC_LIST_HEAD(fctx->bad);
1352 sa = ISC_LIST_NEXT(sa, link)) {
1353 if (isc_sockaddr_equal(sa, address))
1360 static inline isc_boolean_t
1361 mark_bad(fetchctx_t *fctx) {
1362 dns_adbfind_t *curr;
1363 dns_adbaddrinfo_t *addrinfo;
1364 isc_boolean_t all_bad = ISC_TRUE;
1367 * Mark all known bad servers, so we don't try to talk to them
1372 * Mark any bad nameservers.
1374 for (curr = ISC_LIST_HEAD(fctx->finds);
1376 curr = ISC_LIST_NEXT(curr, publink)) {
1377 for (addrinfo = ISC_LIST_HEAD(curr->list);
1379 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1380 if (bad_server(fctx, &addrinfo->sockaddr))
1381 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1383 all_bad = ISC_FALSE;
1388 * Mark any bad forwarders.
1390 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
1392 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1393 if (bad_server(fctx, &addrinfo->sockaddr))
1394 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1396 all_bad = ISC_FALSE;
1403 add_bad(fetchctx_t *fctx, isc_sockaddr_t *address) {
1406 if (bad_server(fctx, address)) {
1408 * We already know this server is bad.
1413 FCTXTRACE("add_bad");
1415 sa = isc_mem_get(fctx->res->mctx, sizeof *sa);
1419 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
1423 sort_adbfind(dns_adbfind_t *find) {
1424 dns_adbaddrinfo_t *best, *curr;
1425 dns_adbaddrinfolist_t sorted;
1428 * Lame N^2 bubble sort.
1431 ISC_LIST_INIT(sorted);
1432 while (!ISC_LIST_EMPTY(find->list)) {
1433 best = ISC_LIST_HEAD(find->list);
1434 curr = ISC_LIST_NEXT(best, publink);
1435 while (curr != NULL) {
1436 if (curr->srtt < best->srtt)
1438 curr = ISC_LIST_NEXT(curr, publink);
1440 ISC_LIST_UNLINK(find->list, best, publink);
1441 ISC_LIST_APPEND(sorted, best, publink);
1443 find->list = sorted;
1447 sort_finds(fetchctx_t *fctx) {
1448 dns_adbfind_t *best, *curr;
1449 dns_adbfindlist_t sorted;
1450 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
1453 * Lame N^2 bubble sort.
1456 ISC_LIST_INIT(sorted);
1457 while (!ISC_LIST_EMPTY(fctx->finds)) {
1458 best = ISC_LIST_HEAD(fctx->finds);
1459 bestaddrinfo = ISC_LIST_HEAD(best->list);
1460 INSIST(bestaddrinfo != NULL);
1461 curr = ISC_LIST_NEXT(best, publink);
1462 while (curr != NULL) {
1463 addrinfo = ISC_LIST_HEAD(curr->list);
1464 INSIST(addrinfo != NULL);
1465 if (addrinfo->srtt < bestaddrinfo->srtt) {
1467 bestaddrinfo = addrinfo;
1469 curr = ISC_LIST_NEXT(curr, publink);
1471 ISC_LIST_UNLINK(fctx->finds, best, publink);
1472 ISC_LIST_APPEND(sorted, best, publink);
1474 fctx->finds = sorted;
1478 fctx_getaddresses(fetchctx_t *fctx) {
1479 dns_rdata_t rdata = DNS_RDATA_INIT;
1480 isc_result_t result;
1481 dns_resolver_t *res;
1483 dns_adbfind_t *find;
1484 unsigned int stdoptions, options;
1486 dns_adbaddrinfo_t *ai;
1487 isc_boolean_t pruned, all_bad;
1490 FCTXTRACE("getaddresses");
1493 * Don't pound on remote servers. (Failsafe!)
1496 if (fctx->restarts > 10) {
1497 FCTXTRACE("too many restarts");
1498 return (DNS_R_SERVFAIL);
1503 stdoptions = 0; /* Keep compiler happy. */
1509 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
1512 * If this fctx has forwarders, use them; otherwise use any
1513 * selective forwarders specified in the view; otherwise use the
1514 * resolver's forwarders (if any).
1516 sa = ISC_LIST_HEAD(fctx->forwarders);
1518 dns_forwarders_t *forwarders = NULL;
1519 result = dns_fwdtable_find(fctx->res->view->fwdtable,
1520 &fctx->name, &forwarders);
1521 if (result == ISC_R_SUCCESS) {
1522 sa = ISC_LIST_HEAD(forwarders->addrs);
1523 fctx->fwdpolicy = forwarders->fwdpolicy;
1527 while (sa != NULL) {
1529 result = dns_adb_findaddrinfo(fctx->adb,
1530 sa, &ai, 0); /* XXXMLG */
1531 if (result == ISC_R_SUCCESS) {
1532 ai->flags |= FCTX_ADDRINFO_FORWARDER;
1533 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
1535 sa = ISC_LIST_NEXT(sa, link);
1539 * If the forwarding policy is "only", we don't need the addresses
1540 * of the nameservers.
1542 if (fctx->fwdpolicy == dns_fwdpolicy_only)
1546 * Normal nameservers.
1549 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
1550 if (fctx->restarts == 1) {
1552 * To avoid sending out a flood of queries likely to
1553 * result in NXRRSET, we suppress fetches for address
1554 * families we don't have the first time through,
1555 * provided that we have addresses in some family we
1558 * We don't want to set this option all the time, since
1559 * if fctx->restarts > 1, we've clearly been having trouble
1560 * with the addresses we had, so getting more could help.
1562 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
1564 if (res->dispatchv4 != NULL)
1565 stdoptions |= DNS_ADBFIND_INET;
1566 if (res->dispatchv6 != NULL)
1567 stdoptions |= DNS_ADBFIND_INET6;
1568 isc_stdtime_get(&now);
1571 INSIST(ISC_LIST_EMPTY(fctx->finds));
1573 result = dns_rdataset_first(&fctx->nameservers);
1574 while (result == ISC_R_SUCCESS) {
1575 dns_rdataset_current(&fctx->nameservers, &rdata);
1577 * Extract the name from the NS record.
1579 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1580 if (result != ISC_R_SUCCESS) {
1581 dns_rdataset_next(&fctx->nameservers);
1584 options = stdoptions;
1586 * If this name is a subdomain of the query domain, tell
1587 * the ADB to start looking using zone/hint data. This keeps
1588 * us from getting stuck if the nameserver is beneath the
1589 * zone cut and we don't know its address (e.g. because the
1590 * A record has expired).
1592 if (dns_name_issubdomain(&ns.name, &fctx->domain))
1593 options |= DNS_ADBFIND_STARTATZONE;
1594 options |= DNS_ADBFIND_GLUEOK;
1595 options |= DNS_ADBFIND_HINTOK;
1598 * See what we know about this address.
1601 result = dns_adb_createfind(fctx->adb,
1602 res->buckets[fctx->bucketnum].task,
1603 fctx_finddone, fctx, &ns.name,
1604 &fctx->domain, options, now, NULL,
1605 res->view->dstport, &find);
1606 if (result != ISC_R_SUCCESS) {
1607 if (result == DNS_R_ALIAS) {
1609 * XXXRTH Follow the CNAME/DNAME chain?
1611 dns_adb_destroyfind(&find);
1613 } else if (!ISC_LIST_EMPTY(find->list)) {
1615 * We have at least some of the addresses for the
1618 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
1620 ISC_LIST_APPEND(fctx->finds, find, publink);
1623 * We don't know any of the addresses for this
1626 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
1628 * We're looking for them and will get an
1629 * event about it later.
1634 * And ADB isn't going to send us any events
1635 * either. This find loses.
1637 if ((find->options & DNS_ADBFIND_LAMEPRUNED)
1640 * The ADB pruned lame servers for
1641 * this name. Remember that in case
1642 * we get desperate later on.
1646 dns_adb_destroyfind(&find);
1649 dns_rdata_reset(&rdata);
1650 dns_rdata_freestruct(&ns);
1651 result = dns_rdataset_next(&fctx->nameservers);
1653 if (result != ISC_R_NOMORE)
1658 * Mark all known bad servers.
1660 all_bad = mark_bad(fctx);
1667 * We've got no addresses.
1669 if (fctx->pending > 0) {
1671 * We're fetching the addresses, but don't have any
1672 * yet. Tell the caller to wait for an answer.
1674 result = DNS_R_WAIT;
1675 } else if (pruned) {
1677 * Some addresses were removed by lame pruning.
1678 * Turn pruning off and try again.
1680 FCTXTRACE("restarting with returnlame");
1681 INSIST((stdoptions & DNS_ADBFIND_RETURNLAME) == 0);
1682 stdoptions |= DNS_ADBFIND_RETURNLAME;
1684 fctx_cleanupfinds(fctx);
1688 * We've lost completely. We don't know any
1689 * addresses, and the ADB has told us it can't get
1692 FCTXTRACE("no addresses");
1693 result = ISC_R_FAILURE;
1697 * We've found some addresses. We might still be looking
1698 * for more addresses.
1701 * XXXRTH We could sort the forwaddrs here if the caller
1702 * wants to use the forwaddrs in "best order" as
1703 * opposed to "fixed order".
1706 result = ISC_R_SUCCESS;
1713 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
1716 char buf[ISC_NETADDR_FORMATSIZE];
1718 isc_boolean_t aborted = ISC_FALSE;
1719 isc_boolean_t bogus;
1720 dns_acl_t *blackhole;
1721 isc_netaddr_t ipaddr;
1722 dns_peer_t *peer = NULL;
1723 dns_resolver_t *res;
1724 const char *msg = NULL;
1726 sa = &addr->sockaddr;
1729 isc_netaddr_fromsockaddr(&ipaddr, sa);
1730 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
1731 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
1733 if (blackhole != NULL) {
1736 if (dns_acl_match(&ipaddr, NULL, blackhole,
1738 &match, NULL) == ISC_R_SUCCESS &&
1744 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
1749 addr->flags |= FCTX_ADDRINFO_MARK;
1750 msg = "ignoring blackholed / bogus server: ";
1751 } else if (sa->type.sa.sa_family != AF_INET6) {
1753 } else if (isc_sockaddr_ismulticast(sa)) {
1754 addr->flags |= FCTX_ADDRINFO_MARK;
1755 msg = "ignoring multicast address: ";
1756 } else if (isc_sockaddr_isexperimental(sa)) {
1757 addr->flags |= FCTX_ADDRINFO_MARK;
1758 msg = "ignoring experimental address: ";
1759 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
1760 addr->flags |= FCTX_ADDRINFO_MARK;
1761 msg = "ignoring IPv6 mapped IPV4 address: ";
1762 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
1763 addr->flags |= FCTX_ADDRINFO_MARK;
1764 msg = "ignoring IPv6 compatibility IPV4 address: ";
1768 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
1771 isc_netaddr_fromsockaddr(&na, sa);
1772 isc_netaddr_format(&na, buf, sizeof buf);
1773 FCTXTRACE2(msg, buf);
1776 static inline dns_adbaddrinfo_t *
1777 fctx_nextaddress(fetchctx_t *fctx) {
1778 dns_adbfind_t *find, *start;
1779 dns_adbaddrinfo_t *addrinfo;
1782 * Return the next untried address, if any.
1786 * Find the first unmarked forwarder (if any).
1788 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
1790 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1791 possibly_mark(fctx, addrinfo);
1792 if (UNMARKED(addrinfo)) {
1793 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1800 * No forwarders. Move to the next find.
1804 find = ISC_LIST_HEAD(fctx->finds);
1806 find = ISC_LIST_NEXT(find, publink);
1808 find = ISC_LIST_HEAD(fctx->finds);
1812 * Find the first unmarked addrinfo.
1818 for (addrinfo = ISC_LIST_HEAD(find->list);
1820 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1821 possibly_mark(fctx, addrinfo);
1822 if (UNMARKED(addrinfo)) {
1823 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1827 if (addrinfo != NULL)
1829 find = ISC_LIST_NEXT(find, publink);
1831 find = ISC_LIST_HEAD(fctx->finds);
1832 } while (find != start);
1841 fctx_try(fetchctx_t *fctx) {
1842 isc_result_t result;
1843 dns_adbaddrinfo_t *addrinfo;
1847 REQUIRE(!ADDRWAIT(fctx));
1849 addrinfo = fctx_nextaddress(fctx);
1850 if (addrinfo == NULL) {
1852 * We have no more addresses. Start over.
1854 fctx_cancelqueries(fctx, ISC_TRUE);
1855 fctx_cleanupfinds(fctx);
1856 fctx_cleanupforwaddrs(fctx);
1857 result = fctx_getaddresses(fctx);
1858 if (result == DNS_R_WAIT) {
1860 * Sleep waiting for addresses.
1862 FCTXTRACE("addrwait");
1863 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
1865 } else if (result != ISC_R_SUCCESS) {
1867 * Something bad happened.
1869 fctx_done(fctx, result);
1873 addrinfo = fctx_nextaddress(fctx);
1875 * While we may have addresses from the ADB, they
1876 * might be bad ones. In this case, return SERVFAIL.
1878 if (addrinfo == NULL) {
1879 fctx_done(fctx, DNS_R_SERVFAIL);
1884 result = fctx_query(fctx, addrinfo, fctx->options);
1885 if (result != ISC_R_SUCCESS)
1886 fctx_done(fctx, result);
1889 static isc_boolean_t
1890 fctx_destroy(fetchctx_t *fctx) {
1891 dns_resolver_t *res;
1892 unsigned int bucketnum;
1893 isc_sockaddr_t *sa, *next_sa;
1896 * Caller must be holding the bucket lock.
1899 REQUIRE(VALID_FCTX(fctx));
1900 REQUIRE(fctx->state == fetchstate_done ||
1901 fctx->state == fetchstate_init);
1902 REQUIRE(ISC_LIST_EMPTY(fctx->events));
1903 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
1904 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
1905 REQUIRE(fctx->pending == 0);
1906 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
1907 REQUIRE(fctx->references == 0);
1909 FCTXTRACE("destroy");
1912 bucketnum = fctx->bucketnum;
1914 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
1919 for (sa = ISC_LIST_HEAD(fctx->bad);
1922 next_sa = ISC_LIST_NEXT(sa, link);
1923 ISC_LIST_UNLINK(fctx->bad, sa, link);
1924 isc_mem_put(res->mctx, sa, sizeof *sa);
1927 isc_timer_detach(&fctx->timer);
1928 dns_message_destroy(&fctx->rmessage);
1929 dns_message_destroy(&fctx->qmessage);
1930 if (dns_name_countlabels(&fctx->domain) > 0)
1931 dns_name_free(&fctx->domain, res->mctx);
1932 if (dns_rdataset_isassociated(&fctx->nameservers))
1933 dns_rdataset_disassociate(&fctx->nameservers);
1934 dns_name_free(&fctx->name, res->mctx);
1935 dns_db_detach(&fctx->cache);
1936 dns_adb_detach(&fctx->adb);
1937 isc_mem_put(res->mctx, fctx, sizeof *fctx);
1939 if (res->buckets[bucketnum].exiting &&
1940 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
1947 * Fetch event handlers.
1951 fctx_timeout(isc_task_t *task, isc_event_t *event) {
1952 fetchctx_t *fctx = event->ev_arg;
1954 REQUIRE(VALID_FCTX(fctx));
1958 FCTXTRACE("timeout");
1960 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
1961 fctx_done(fctx, ISC_R_TIMEDOUT);
1965 * We could cancel the running queries here, or we could let
1966 * them keep going. Right now we choose the latter...
1968 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1970 * Our timer has triggered. Reestablish the fctx lifetime
1973 fctx_starttimer(fctx);
1980 isc_event_free(&event);
1984 fctx_shutdown(fetchctx_t *fctx) {
1985 isc_event_t *cevent;
1988 * Start the shutdown process for fctx, if it isn't already underway.
1991 FCTXTRACE("shutdown");
1994 * The caller must be holding the appropriate bucket lock.
1997 if (fctx->want_shutdown)
2000 fctx->want_shutdown = ISC_TRUE;
2003 * Unless we're still initializing (in which case the
2004 * control event is still outstanding), we need to post
2005 * the control event to tell the fetch we want it to
2008 if (fctx->state != fetchstate_init) {
2009 cevent = &fctx->control_event;
2010 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
2016 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
2017 fetchctx_t *fctx = event->ev_arg;
2018 isc_boolean_t bucket_empty = ISC_FALSE;
2019 dns_resolver_t *res;
2020 unsigned int bucketnum;
2021 dns_validator_t *validator;
2023 REQUIRE(VALID_FCTX(fctx));
2028 bucketnum = fctx->bucketnum;
2030 FCTXTRACE("doshutdown");
2033 * An fctx that is shutting down is no longer in ADDRWAIT mode.
2035 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2038 * Cancel all pending validators. Note that this must be done
2039 * without the bucket lock held, since that could cause deadlock.
2041 validator = ISC_LIST_HEAD(fctx->validators);
2042 while (validator != NULL) {
2043 dns_validator_cancel(validator);
2044 validator = ISC_LIST_NEXT(validator, link);
2048 * Shut down anything that is still running on behalf of this
2049 * fetch. To avoid deadlock with the ADB, we must do this
2050 * before we lock the bucket lock.
2052 fctx_stopeverything(fctx, ISC_FALSE);
2054 LOCK(&res->buckets[bucketnum].lock);
2056 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2058 INSIST(fctx->state == fetchstate_active ||
2059 fctx->state == fetchstate_done);
2060 INSIST(fctx->want_shutdown);
2062 if (fctx->state != fetchstate_done) {
2063 fctx->state = fetchstate_done;
2064 fctx_sendevents(fctx, ISC_R_CANCELED);
2067 if (fctx->references == 0 && fctx->pending == 0 &&
2068 ISC_LIST_EMPTY(fctx->validators))
2069 bucket_empty = fctx_destroy(fctx);
2071 UNLOCK(&res->buckets[bucketnum].lock);
2078 fctx_start(isc_task_t *task, isc_event_t *event) {
2079 fetchctx_t *fctx = event->ev_arg;
2080 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
2081 dns_resolver_t *res;
2082 unsigned int bucketnum;
2084 REQUIRE(VALID_FCTX(fctx));
2089 bucketnum = fctx->bucketnum;
2093 LOCK(&res->buckets[bucketnum].lock);
2095 INSIST(fctx->state == fetchstate_init);
2096 if (fctx->want_shutdown) {
2098 * We haven't started this fctx yet, and we've been requested
2101 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2102 fctx->state = fetchstate_done;
2103 fctx_sendevents(fctx, ISC_R_CANCELED);
2105 * Since we haven't started, we INSIST that we have no
2106 * pending ADB finds and no pending validations.
2108 INSIST(fctx->pending == 0);
2109 INSIST(ISC_LIST_EMPTY(fctx->validators));
2110 if (fctx->references == 0) {
2112 * It's now safe to destroy this fctx.
2114 bucket_empty = fctx_destroy(fctx);
2119 * Normal fctx startup.
2121 fctx->state = fetchstate_active;
2123 * Reset the control event for later use in shutting down
2126 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
2127 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
2131 UNLOCK(&res->buckets[bucketnum].lock);
2135 * All is well. Start working on the fetch.
2137 fctx_starttimer(fctx);
2139 } else if (bucket_empty)
2144 * Fetch Creation, Joining, and Cancelation.
2147 static inline isc_result_t
2148 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_taskaction_t action,
2149 void *arg, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
2153 dns_fetchevent_t *event;
2158 * We store the task we're going to send this event to in the
2159 * sender field. We'll make the fetch the sender when we actually
2163 isc_task_attach(task, &clone);
2164 event = (dns_fetchevent_t *)
2165 isc_event_allocate(fctx->res->mctx, clone,
2166 DNS_EVENT_FETCHDONE,
2167 action, arg, sizeof *event);
2168 if (event == NULL) {
2169 isc_task_detach(&clone);
2170 return (ISC_R_NOMEMORY);
2172 event->result = DNS_R_SERVFAIL;
2173 event->qtype = fctx->type;
2176 event->rdataset = rdataset;
2177 event->sigrdataset = sigrdataset;
2178 event->fetch = fetch;
2179 dns_fixedname_init(&event->foundname);
2182 * Make sure that we can store the sigrdataset in the
2183 * first event if it is needed by any of the events.
2185 if (event->sigrdataset != NULL)
2186 ISC_LIST_PREPEND(fctx->events, event, ev_link);
2188 ISC_LIST_APPEND(fctx->events, event, ev_link);
2191 fetch->magic = DNS_FETCH_MAGIC;
2192 fetch->private = fctx;
2194 return (ISC_R_SUCCESS);
2198 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
2199 dns_name_t *domain, dns_rdataset_t *nameservers,
2200 unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
2203 isc_result_t result = ISC_R_SUCCESS;
2204 isc_result_t iresult;
2205 isc_interval_t interval;
2206 dns_fixedname_t qdomain;
2207 unsigned int findoptions = 0;
2210 * Caller must be holding the lock for bucket number 'bucketnum'.
2212 REQUIRE(fctxp != NULL && *fctxp == NULL);
2214 fctx = isc_mem_get(res->mctx, sizeof *fctx);
2216 return (ISC_R_NOMEMORY);
2217 FCTXTRACE("create");
2218 dns_name_init(&fctx->name, NULL);
2219 result = dns_name_dup(name, res->mctx, &fctx->name);
2220 if (result != ISC_R_SUCCESS)
2222 dns_name_init(&fctx->domain, NULL);
2223 dns_rdataset_init(&fctx->nameservers);
2226 fctx->options = options;
2228 * Note! We do not attach to the task. We are relying on the
2229 * resolver to ensure that this task doesn't go away while we are
2233 fctx->references = 0;
2234 fctx->bucketnum = bucketnum;
2235 fctx->state = fetchstate_init;
2236 fctx->want_shutdown = ISC_FALSE;
2237 fctx->cloned = ISC_FALSE;
2238 ISC_LIST_INIT(fctx->queries);
2239 ISC_LIST_INIT(fctx->finds);
2240 ISC_LIST_INIT(fctx->forwaddrs);
2241 ISC_LIST_INIT(fctx->forwarders);
2242 fctx->fwdpolicy = dns_fwdpolicy_none;
2243 ISC_LIST_INIT(fctx->bad);
2244 ISC_LIST_INIT(fctx->validators);
2249 if (dns_name_requiresedns(name))
2250 fctx->attributes = FCTX_ATTR_NEEDEDNS0;
2252 fctx->attributes = 0;
2254 if (domain == NULL) {
2255 dns_forwarders_t *forwarders = NULL;
2256 result = dns_fwdtable_find(fctx->res->view->fwdtable,
2257 &fctx->name, &forwarders);
2258 if (result == ISC_R_SUCCESS)
2259 fctx->fwdpolicy = forwarders->fwdpolicy;
2261 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
2263 * The caller didn't supply a query domain and
2264 * nameservers, and we're not in forward-only mode,
2265 * so find the best nameservers to use.
2267 if (type == dns_rdatatype_key)
2268 findoptions |= DNS_DBFIND_NOEXACT;
2269 dns_fixedname_init(&qdomain);
2270 result = dns_view_findzonecut(res->view, name,
2271 dns_fixedname_name(&qdomain), 0,
2272 findoptions, ISC_TRUE,
2275 if (result != ISC_R_SUCCESS)
2277 result = dns_name_dup(dns_fixedname_name(&qdomain),
2278 res->mctx, &fctx->domain);
2279 if (result != ISC_R_SUCCESS) {
2280 dns_rdataset_disassociate(&fctx->nameservers);
2285 * We're in forward-only mode. Set the query domain
2288 result = dns_name_dup(dns_rootname, res->mctx,
2290 if (result != ISC_R_SUCCESS)
2294 result = dns_name_dup(domain, res->mctx, &fctx->domain);
2295 if (result != ISC_R_SUCCESS)
2297 dns_rdataset_clone(nameservers, &fctx->nameservers);
2300 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
2302 fctx->qmessage = NULL;
2303 result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTRENDER,
2306 if (result != ISC_R_SUCCESS)
2307 goto cleanup_domain;
2309 fctx->rmessage = NULL;
2310 result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTPARSE,
2313 if (result != ISC_R_SUCCESS)
2314 goto cleanup_qmessage;
2317 * Compute an expiration time for the entire fetch.
2319 isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
2320 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
2321 if (iresult != ISC_R_SUCCESS) {
2322 UNEXPECTED_ERROR(__FILE__, __LINE__,
2323 "isc_time_nowplusinterval: %s",
2324 isc_result_totext(iresult));
2325 result = ISC_R_UNEXPECTED;
2326 goto cleanup_rmessage;
2330 * Default retry interval initialization. We set the interval now
2331 * mostly so it won't be uninitialized. It will be set to the
2332 * correct value before a query is issued.
2334 isc_interval_set(&fctx->interval, 2, 0);
2337 * Create an inactive timer. It will be made active when the fetch
2338 * is actually started.
2341 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
2343 res->buckets[bucketnum].task, fctx_timeout,
2344 fctx, &fctx->timer);
2345 if (iresult != ISC_R_SUCCESS) {
2346 UNEXPECTED_ERROR(__FILE__, __LINE__,
2347 "isc_timer_create: %s",
2348 isc_result_totext(iresult));
2349 result = ISC_R_UNEXPECTED;
2350 goto cleanup_rmessage;
2354 * Attach to the view's cache and adb.
2357 dns_db_attach(res->view->cachedb, &fctx->cache);
2359 dns_adb_attach(res->view->adb, &fctx->adb);
2361 ISC_LIST_INIT(fctx->events);
2362 ISC_LINK_INIT(fctx, link);
2363 fctx->magic = FCTX_MAGIC;
2365 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
2369 return (ISC_R_SUCCESS);
2372 dns_message_destroy(&fctx->rmessage);
2375 dns_message_destroy(&fctx->qmessage);
2378 if (dns_name_countlabels(&fctx->domain) > 0)
2379 dns_name_free(&fctx->domain, res->mctx);
2380 if (dns_rdataset_isassociated(&fctx->nameservers))
2381 dns_rdataset_disassociate(&fctx->nameservers);
2384 dns_name_free(&fctx->name, res->mctx);
2387 isc_mem_put(res->mctx, fctx, sizeof *fctx);
2395 static inline isc_boolean_t
2396 is_lame(fetchctx_t *fctx) {
2397 dns_message_t *message = fctx->rmessage;
2399 dns_rdataset_t *rdataset;
2400 isc_result_t result;
2402 if (message->rcode != dns_rcode_noerror &&
2403 message->rcode != dns_rcode_nxdomain)
2406 if (message->counts[DNS_SECTION_ANSWER] != 0)
2409 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
2412 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2413 while (result == ISC_R_SUCCESS) {
2415 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2416 for (rdataset = ISC_LIST_HEAD(name->list);
2418 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2419 dns_namereln_t namereln;
2421 unsigned int labels, bits;
2422 if (rdataset->type != dns_rdatatype_ns)
2424 namereln = dns_name_fullcompare(name, &fctx->domain,
2425 &order, &labels, &bits);
2426 if (namereln == dns_namereln_equal &&
2427 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
2429 if (namereln == dns_namereln_subdomain)
2433 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
2440 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
2441 char namebuf[DNS_NAME_FORMATSIZE];
2442 char domainbuf[DNS_NAME_FORMATSIZE];
2443 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2445 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2446 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
2447 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
2448 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2449 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2450 "lame server resolving '%s' (in '%s'?): %s",
2451 namebuf, domainbuf, addrbuf);
2454 static inline isc_result_t
2455 same_question(fetchctx_t *fctx) {
2456 isc_result_t result;
2457 dns_message_t *message = fctx->rmessage;
2459 dns_rdataset_t *rdataset;
2462 * Caller must be holding the fctx lock.
2466 * XXXRTH Currently we support only one question.
2468 if (message->counts[DNS_SECTION_QUESTION] != 1)
2469 return (DNS_R_FORMERR);
2471 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
2472 if (result != ISC_R_SUCCESS)
2475 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
2476 rdataset = ISC_LIST_HEAD(name->list);
2477 INSIST(rdataset != NULL);
2478 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
2479 if (fctx->type != rdataset->type ||
2480 fctx->res->rdclass != rdataset->rdclass ||
2481 !dns_name_equal(&fctx->name, name))
2482 return (DNS_R_FORMERR);
2484 return (ISC_R_SUCCESS);
2488 clone_results(fetchctx_t *fctx) {
2489 dns_fetchevent_t *event, *hevent;
2490 isc_result_t result;
2491 dns_name_t *name, *hname;
2494 * Set up any other events to have the same data as the first
2497 * Caller must be holding the appropriate lock.
2500 fctx->cloned = ISC_TRUE;
2501 hevent = ISC_LIST_HEAD(fctx->events);
2504 hname = dns_fixedname_name(&hevent->foundname);
2505 for (event = ISC_LIST_NEXT(hevent, ev_link);
2507 event = ISC_LIST_NEXT(event, ev_link)) {
2508 name = dns_fixedname_name(&event->foundname);
2509 result = dns_name_copy(hname, name, NULL);
2510 if (result != ISC_R_SUCCESS)
2511 event->result = result;
2513 event->result = hevent->result;
2514 dns_db_attach(hevent->db, &event->db);
2515 dns_db_attachnode(hevent->db, hevent->node, &event->node);
2516 INSIST(hevent->rdataset != NULL);
2517 INSIST(event->rdataset != NULL);
2518 if (dns_rdataset_isassociated(hevent->rdataset))
2519 dns_rdataset_clone(hevent->rdataset, event->rdataset);
2520 INSIST(! (hevent->sigrdataset == NULL &&
2521 event->sigrdataset != NULL));
2522 if (hevent->sigrdataset != NULL &&
2523 dns_rdataset_isassociated(hevent->sigrdataset) &&
2524 event->sigrdataset != NULL)
2525 dns_rdataset_clone(hevent->sigrdataset,
2526 event->sigrdataset);
2530 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
2531 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
2532 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
2533 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
2534 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
2535 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
2539 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
2540 * no references and is no longer waiting for any events). If this
2541 * was the last fctx in the resolver, destroy the resolver.
2544 * '*fctx' is shutting down.
2547 maybe_destroy(fetchctx_t *fctx) {
2548 unsigned int bucketnum;
2549 isc_boolean_t bucket_empty = ISC_FALSE;
2550 dns_resolver_t *res = fctx->res;
2552 REQUIRE(SHUTTINGDOWN(fctx));
2554 if (fctx->pending != 0 || !ISC_LIST_EMPTY(fctx->validators))
2557 bucketnum = fctx->bucketnum;
2558 LOCK(&res->buckets[bucketnum].lock);
2559 if (fctx->references == 0)
2560 bucket_empty = fctx_destroy(fctx);
2561 UNLOCK(&res->buckets[bucketnum].lock);
2568 * The validator has finished.
2571 validated(isc_task_t *task, isc_event_t *event) {
2572 isc_result_t result = ISC_R_SUCCESS;
2573 isc_result_t eresult = ISC_R_SUCCESS;
2576 dns_validatorevent_t *vevent;
2577 dns_fetchevent_t *hevent;
2578 dns_rdataset_t *ardataset = NULL;
2579 dns_rdataset_t *asigrdataset = NULL;
2580 dns_dbnode_t *node = NULL;
2581 isc_boolean_t negative;
2582 isc_boolean_t chaining;
2583 isc_boolean_t sentresponse;
2586 UNUSED(task); /* for now */
2588 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
2589 fctx = event->ev_arg;
2590 REQUIRE(VALID_FCTX(fctx));
2591 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
2593 vevent = (dns_validatorevent_t *)event;
2595 FCTXTRACE("received validation completion event");
2597 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
2600 * Destroy the validator early so that we can
2601 * destroy the fctx if necessary.
2603 dns_validator_destroy(&vevent->validator);
2605 negative = ISC_TF(vevent->rdataset == NULL);
2607 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
2610 * If shutting down, ignore the results. Check to see if we're
2611 * done waiting for validator completions and ADB pending events; if
2612 * so, destroy the fctx.
2614 if (SHUTTINGDOWN(fctx) && !sentresponse ) {
2615 maybe_destroy(fctx);
2620 * If chaining, we need to make sure that the right result code is
2621 * returned, and that the rdatasets are bound.
2623 if (vevent->result == ISC_R_SUCCESS &&
2625 vevent->rdataset != NULL &&
2626 CHAINING(vevent->rdataset))
2628 if (vevent->rdataset->type == dns_rdatatype_cname)
2629 eresult = DNS_R_CNAME;
2631 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
2632 eresult = DNS_R_DNAME;
2634 chaining = ISC_TRUE;
2636 chaining = ISC_FALSE;
2639 * Either we're not shutting down, or we are shutting down but want
2640 * to cache the result anyway (if this was a validation started by
2641 * a query with cd set)
2644 hevent = ISC_LIST_HEAD(fctx->events);
2645 if (hevent != NULL) {
2646 if (!negative && !chaining &&
2647 (fctx->type == dns_rdatatype_any ||
2648 fctx->type == dns_rdatatype_sig)) {
2650 * Don't bind rdatasets; the caller
2651 * will iterate the node.
2654 ardataset = hevent->rdataset;
2655 asigrdataset = hevent->sigrdataset;
2659 if (vevent->result != ISC_R_SUCCESS) {
2660 FCTXTRACE("validation failed");
2661 if (vevent->rdataset != NULL) {
2662 result = dns_db_findnode(fctx->cache, vevent->name,
2664 if (result != ISC_R_SUCCESS)
2665 goto noanswer_response;
2666 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
2668 if (vevent->sigrdataset != NULL)
2669 (void)dns_db_deleterdataset(fctx->cache,
2674 result = vevent->result;
2675 goto noanswer_response;
2678 isc_stdtime_get(&now);
2681 dns_rdatatype_t covers;
2682 FCTXTRACE("nonexistence validation OK");
2684 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
2685 covers = dns_rdatatype_any;
2687 covers = fctx->type;
2689 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
2691 if (result != ISC_R_SUCCESS)
2692 goto noanswer_response;
2695 * If we are asking for a SOA record set the cache time
2696 * to zero to facilitate locating the containing zone of
2699 ttl = fctx->res->view->maxncachettl;
2700 if (fctx->type == dns_rdatatype_soa &&
2701 covers == dns_rdatatype_any)
2704 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
2706 ardataset, &eresult);
2707 if (result != ISC_R_SUCCESS)
2708 goto noanswer_response;
2710 goto answer_response;
2713 FCTXTRACE("validation OK");
2716 * The data was already cached as pending data.
2717 * Re-cache it as secure and bind the cached
2718 * rdatasets to the first event on the fetch
2721 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
2722 if (result != ISC_R_SUCCESS)
2723 goto noanswer_response;
2725 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
2726 vevent->rdataset, 0, ardataset);
2727 if (result != ISC_R_SUCCESS &&
2728 result != DNS_R_UNCHANGED)
2729 goto noanswer_response;
2730 if (vevent->sigrdataset != NULL) {
2731 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
2732 vevent->sigrdataset, 0,
2734 if (result != ISC_R_SUCCESS &&
2735 result != DNS_R_UNCHANGED)
2736 goto noanswer_response;
2741 * If we only deferred the destroy because we wanted to cache
2742 * the data, destroy now.
2744 if (SHUTTINGDOWN(fctx))
2745 maybe_destroy(fctx);
2750 if (!ISC_LIST_EMPTY(fctx->validators)) {
2752 INSIST(fctx->type == dns_rdatatype_any ||
2753 fctx->type == dns_rdatatype_sig);
2755 * Don't send a response yet - we have
2756 * more rdatasets that still need to
2762 result = ISC_R_SUCCESS;
2766 * Respond with an answer, positive or negative,
2767 * as opposed to an error. 'node' must be non-NULL.
2770 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
2772 if (hevent != NULL) {
2773 hevent->result = eresult;
2774 dns_name_copy(vevent->name,
2775 dns_fixedname_name(&hevent->foundname), NULL);
2776 dns_db_attach(fctx->cache, &hevent->db);
2777 hevent->node = node;
2779 clone_results(fctx);
2784 dns_db_detachnode(fctx->cache, &node);
2786 fctx_done(fctx, result);
2789 isc_event_free(&event);
2792 static inline isc_result_t
2793 cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
2794 dns_rdataset_t *rdataset, *sigrdataset;
2795 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
2796 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
2797 dns_dbnode_t *node, **anodep;
2800 dns_resolver_t *res;
2801 isc_boolean_t need_validation, secure_domain, have_answer;
2802 isc_result_t result, eresult;
2803 dns_fetchevent_t *event;
2804 unsigned int options;
2806 dns_validator_t *validator;
2809 * The appropriate bucket lock must be held.
2813 need_validation = ISC_FALSE;
2814 secure_domain = ISC_FALSE;
2815 have_answer = ISC_FALSE;
2816 eresult = ISC_R_SUCCESS;
2817 task = res->buckets[fctx->bucketnum].task;
2820 * Is DNSSEC validation required for this name?
2822 result = dns_keytable_issecuredomain(res->view->secroots, name,
2824 if (result != ISC_R_SUCCESS)
2827 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
2828 need_validation = ISC_FALSE;
2830 need_validation = secure_domain;
2836 asigrdataset = NULL;
2838 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
2840 have_answer = ISC_TRUE;
2841 event = ISC_LIST_HEAD(fctx->events);
2842 if (event != NULL) {
2844 aname = dns_fixedname_name(&event->foundname);
2845 result = dns_name_copy(name, aname, NULL);
2846 if (result != ISC_R_SUCCESS)
2848 anodep = &event->node;
2850 * If this is an ANY or SIG query, we're not going
2851 * to return any rdatasets, unless we encountered
2852 * a CNAME or DNAME as "the answer". In this case,
2853 * we're going to return DNS_R_CNAME or DNS_R_DNAME
2854 * and we must set up the rdatasets.
2856 if ((fctx->type != dns_rdatatype_any &&
2857 fctx->type != dns_rdatatype_sig) ||
2858 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
2859 ardataset = event->rdataset;
2860 asigrdataset = event->sigrdataset;
2866 * Find or create the cache node.
2869 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
2870 if (result != ISC_R_SUCCESS)
2874 * Cache or validate each cacheable rdataset.
2876 for (rdataset = ISC_LIST_HEAD(name->list);
2878 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2879 if (!CACHE(rdataset))
2883 * Enforce the configure maximum cache TTL.
2885 if (rdataset->ttl > res->view->maxcachettl)
2886 rdataset->ttl = res->view->maxcachettl;
2889 * If this rrset is in a secure domain, do DNSSEC validation
2890 * for it, unless it is glue.
2892 if (secure_domain && rdataset->trust != dns_trust_glue) {
2894 * SIGs are validated as part of validating the
2897 if (rdataset->type == dns_rdatatype_sig)
2900 * Find the SIG for this rdataset, if we have it.
2902 for (sigrdataset = ISC_LIST_HEAD(name->list);
2903 sigrdataset != NULL;
2904 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
2905 if (sigrdataset->type == dns_rdatatype_sig &&
2906 sigrdataset->covers == rdataset->type)
2909 if (sigrdataset == NULL) {
2910 if (!ANSWER(rdataset) && need_validation) {
2912 * Ignore non-answer rdatasets that
2913 * are missing signatures.
2920 * Normalize the rdataset and sigrdataset TTLs.
2922 if (sigrdataset != NULL) {
2923 rdataset->ttl = ISC_MIN(rdataset->ttl,
2925 sigrdataset->ttl = rdataset->ttl;
2929 * Cache this rdataset/sigrdataset pair as
2932 rdataset->trust = dns_trust_pending;
2933 if (sigrdataset != NULL)
2934 sigrdataset->trust = dns_trust_pending;
2935 if (!need_validation)
2936 addedrdataset = ardataset;
2938 addedrdataset = NULL;
2939 result = dns_db_addrdataset(fctx->cache, node, NULL,
2942 if (result == DNS_R_UNCHANGED)
2943 result = ISC_R_SUCCESS;
2944 if (result != ISC_R_SUCCESS)
2946 if (sigrdataset != NULL) {
2947 if (!need_validation)
2948 addedrdataset = asigrdataset;
2950 addedrdataset = NULL;
2951 result = dns_db_addrdataset(fctx->cache,
2955 if (result == DNS_R_UNCHANGED)
2956 result = ISC_R_SUCCESS;
2957 if (result != ISC_R_SUCCESS)
2959 } else if (!ANSWER(rdataset))
2962 if (ANSWER(rdataset) && need_validation) {
2963 if (fctx->type != dns_rdatatype_any &&
2964 fctx->type != dns_rdatatype_sig) {
2966 * This is The Answer. We will
2967 * validate it, but first we cache
2968 * the rest of the response - it may
2969 * contain useful keys.
2971 INSIST(valrdataset == NULL &&
2972 valsigrdataset == NULL);
2973 valrdataset = rdataset;
2974 valsigrdataset = sigrdataset;
2977 * This is one of (potentially)
2978 * multiple answers to an ANY
2979 * or SIG query. To keep things
2980 * simple, we just start the
2981 * validator right away rather
2982 * than caching first and
2983 * having to remember which
2984 * rdatasets needed validation.
2987 result = dns_validator_create(
2999 if (result == ISC_R_SUCCESS)
3005 } else if (!EXTERNAL(rdataset)) {
3007 * It's OK to cache this rdataset now.
3009 if (ANSWER(rdataset))
3010 addedrdataset = ardataset;
3011 else if (ANSWERSIG(rdataset))
3012 addedrdataset = asigrdataset;
3014 addedrdataset = NULL;
3015 if (CHAINING(rdataset)) {
3016 if (rdataset->type == dns_rdatatype_cname)
3017 eresult = DNS_R_CNAME;
3019 INSIST(rdataset->type ==
3020 dns_rdatatype_dname);
3021 eresult = DNS_R_DNAME;
3024 if (rdataset->trust == dns_trust_glue &&
3025 (rdataset->type == dns_rdatatype_ns ||
3026 (rdataset->type == dns_rdatatype_sig &&
3027 rdataset->covers == dns_rdatatype_ns))) {
3029 * If the trust level is 'dns_trust_glue'
3030 * then we are adding data from a referral
3031 * we got while executing the search algorithm.
3032 * New referral data always takes precedence
3033 * over the existing cache contents.
3035 options = DNS_DBADD_FORCE;
3039 * Now we can add the rdataset.
3041 result = dns_db_addrdataset(fctx->cache,
3046 if (result == DNS_R_UNCHANGED) {
3047 if (ANSWER(rdataset) &&
3048 ardataset != NULL &&
3049 ardataset->type == 0) {
3051 * The answer in the cache is better
3052 * than the answer we found, and is
3053 * a negative cache entry, so we
3054 * must set eresult appropriately.
3056 if (NXDOMAIN(ardataset))
3058 DNS_R_NCACHENXDOMAIN;
3061 DNS_R_NCACHENXRRSET;
3063 result = ISC_R_SUCCESS;
3064 } else if (result != ISC_R_SUCCESS)
3069 if (valrdataset != NULL) {
3071 result = dns_validator_create(res->view,
3082 if (result == ISC_R_SUCCESS)
3083 ISC_LIST_APPEND(fctx->validators, validator, link);
3086 if (result == ISC_R_SUCCESS && have_answer) {
3087 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3088 if (event != NULL) {
3089 event->result = eresult;
3090 dns_db_attach(fctx->cache, adbp);
3093 clone_results(fctx);
3098 dns_db_detachnode(fctx->cache, &node);
3103 static inline isc_result_t
3104 cache_message(fetchctx_t *fctx, isc_stdtime_t now) {
3105 isc_result_t result;
3106 dns_section_t section;
3109 FCTXTRACE("cache_message");
3111 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
3113 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3115 for (section = DNS_SECTION_ANSWER;
3116 section <= DNS_SECTION_ADDITIONAL;
3118 result = dns_message_firstname(fctx->rmessage, section);
3119 while (result == ISC_R_SUCCESS) {
3121 dns_message_currentname(fctx->rmessage, section,
3123 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
3124 result = cache_name(fctx, name, now);
3125 if (result != ISC_R_SUCCESS)
3128 result = dns_message_nextname(fctx->rmessage, section);
3130 if (result != ISC_R_NOMORE)
3133 if (result == ISC_R_NOMORE)
3134 result = ISC_R_SUCCESS;
3136 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3142 * Do what dns_ncache_add() does, and then compute an appropriate eresult.
3145 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
3146 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
3147 dns_rdataset_t *ardataset,
3148 isc_result_t *eresultp)
3150 isc_result_t result;
3151 result = dns_ncache_add(message, cache, node, covers, now,
3153 if (result == DNS_R_UNCHANGED) {
3155 * The data in the cache is better than the negative cache
3156 * entry we're trying to add.
3158 if (ardataset != NULL && ardataset->type == 0) {
3160 * The cache data is also a negative cache
3163 if (NXDOMAIN(ardataset))
3164 *eresultp = DNS_R_NCACHENXDOMAIN;
3166 *eresultp = DNS_R_NCACHENXRRSET;
3167 result = ISC_R_SUCCESS;
3170 * Either we don't care about the nature of the
3171 * cache rdataset (because no fetch is interested
3172 * in the outcome), or the cache rdataset is not
3173 * a negative cache entry. Whichever case it is,
3174 * we can return success.
3176 * XXXRTH There's a CNAME/DNAME problem here.
3178 *eresultp = ISC_R_SUCCESS;
3179 result = ISC_R_SUCCESS;
3181 } else if (result == ISC_R_SUCCESS) {
3182 if (NXDOMAIN(ardataset))
3183 *eresultp = DNS_R_NCACHENXDOMAIN;
3185 *eresultp = DNS_R_NCACHENXRRSET;
3191 static inline isc_result_t
3192 ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) {
3193 isc_result_t result, eresult;
3195 dns_resolver_t *res;
3197 dns_dbnode_t *node, **anodep;
3198 dns_rdataset_t *ardataset;
3199 isc_boolean_t need_validation, secure_domain;
3201 dns_fetchevent_t *event;
3204 FCTXTRACE("ncache_message");
3206 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
3209 need_validation = ISC_FALSE;
3210 secure_domain = ISC_FALSE;
3211 eresult = ISC_R_SUCCESS;
3216 * Is DNSSEC validation required for this name?
3218 result = dns_keytable_issecuredomain(res->view->secroots, name,
3220 if (result != ISC_R_SUCCESS)
3223 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
3224 need_validation = ISC_FALSE;
3226 need_validation = secure_domain;
3228 if (secure_domain) {
3230 * Mark all rdatasets as pending.
3232 dns_rdataset_t *trdataset;
3235 result = dns_message_firstname(fctx->rmessage,
3236 DNS_SECTION_AUTHORITY);
3237 while (result == ISC_R_SUCCESS) {
3239 dns_message_currentname(fctx->rmessage,
3240 DNS_SECTION_AUTHORITY,
3242 for (trdataset = ISC_LIST_HEAD(tname->list);
3244 trdataset = ISC_LIST_NEXT(trdataset, link))
3245 trdataset->trust = dns_trust_pending;
3246 result = dns_message_nextname(fctx->rmessage,
3247 DNS_SECTION_AUTHORITY);
3249 if (result != ISC_R_NOMORE)
3254 if (need_validation) {
3256 * Do negative response validation.
3258 dns_validator_t *validator = NULL;
3259 isc_task_t *task = res->buckets[fctx->bucketnum].task;
3261 result = dns_validator_create(res->view, name, fctx->type,
3263 fctx->rmessage, 0, task,
3266 if (result != ISC_R_SUCCESS)
3268 ISC_LIST_APPEND(fctx->validators, validator, link);
3270 * If validation is necessary, return now. Otherwise continue
3271 * to process the message, letting the validation complete
3272 * in its own good time.
3274 return (ISC_R_SUCCESS);
3277 LOCK(&res->buckets[fctx->bucketnum].lock);
3283 if (!HAVE_ANSWER(fctx)) {
3284 event = ISC_LIST_HEAD(fctx->events);
3285 if (event != NULL) {
3287 aname = dns_fixedname_name(&event->foundname);
3288 result = dns_name_copy(name, aname, NULL);
3289 if (result != ISC_R_SUCCESS)
3291 anodep = &event->node;
3292 ardataset = event->rdataset;
3297 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
3298 if (result != ISC_R_SUCCESS)
3302 * If we are asking for a SOA record set the cache time
3303 * to zero to facilitate locating the containing zone of
3306 ttl = fctx->res->view->maxncachettl;
3307 if (fctx->type == dns_rdatatype_soa &&
3308 covers == dns_rdatatype_any)
3311 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
3312 covers, now, ttl, ardataset, &eresult);
3313 if (result != ISC_R_SUCCESS)
3316 if (!HAVE_ANSWER(fctx)) {
3317 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3318 if (event != NULL) {
3319 event->result = eresult;
3320 dns_db_attach(fctx->cache, adbp);
3323 clone_results(fctx);
3328 UNLOCK(&res->buckets[fctx->bucketnum].lock);
3331 dns_db_detachnode(fctx->cache, &node);
3337 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
3338 isc_boolean_t external, isc_boolean_t gluing)
3340 name->attributes |= DNS_NAMEATTR_CACHE;
3342 rdataset->trust = dns_trust_glue;
3344 * Glue with 0 TTL causes problems. We force the TTL to
3345 * 1 second to prevent this.
3347 if (rdataset->ttl == 0)
3350 rdataset->trust = dns_trust_additional;
3352 * Avoid infinite loops by only marking new rdatasets.
3354 if (!CACHE(rdataset)) {
3355 name->attributes |= DNS_NAMEATTR_CHASE;
3356 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
3358 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
3360 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
3364 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
3365 fetchctx_t *fctx = arg;
3366 isc_result_t result;
3368 dns_rdataset_t *rdataset;
3369 isc_boolean_t external;
3370 dns_rdatatype_t rtype;
3371 isc_boolean_t gluing;
3373 REQUIRE(VALID_FCTX(fctx));
3380 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
3381 addname, dns_rdatatype_any, 0, &name,
3383 if (result == ISC_R_SUCCESS) {
3384 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
3385 for (rdataset = ISC_LIST_HEAD(name->list);
3387 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3388 if (rdataset->type == dns_rdatatype_sig)
3389 rtype = rdataset->covers;
3391 rtype = rdataset->type;
3392 if ((type == dns_rdatatype_a &&
3393 (rtype == dns_rdatatype_a ||
3394 rtype == dns_rdatatype_aaaa ||
3395 rtype == dns_rdatatype_a6)) ||
3397 mark_related(name, rdataset, external,
3402 return (ISC_R_SUCCESS);
3406 chase_additional(fetchctx_t *fctx) {
3407 isc_boolean_t rescan;
3408 dns_section_t section = DNS_SECTION_ADDITIONAL;
3409 isc_result_t result;
3414 for (result = dns_message_firstname(fctx->rmessage, section);
3415 result == ISC_R_SUCCESS;
3416 result = dns_message_nextname(fctx->rmessage, section)) {
3417 dns_name_t *name = NULL;
3418 dns_rdataset_t *rdataset;
3419 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
3421 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
3423 name->attributes &= ~DNS_NAMEATTR_CHASE;
3424 for (rdataset = ISC_LIST_HEAD(name->list);
3426 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3427 if (CHASE(rdataset)) {
3428 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
3429 (void)dns_rdataset_additionaldata(rdataset,
3440 static inline isc_result_t
3441 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
3442 isc_result_t result;
3443 dns_rdata_t rdata = DNS_RDATA_INIT;
3444 dns_rdata_cname_t cname;
3446 result = dns_rdataset_first(rdataset);
3447 if (result != ISC_R_SUCCESS)
3449 dns_rdataset_current(rdataset, &rdata);
3450 result = dns_rdata_tostruct(&rdata, &cname, NULL);
3451 if (result != ISC_R_SUCCESS)
3453 dns_name_init(tname, NULL);
3454 dns_name_clone(&cname.cname, tname);
3455 dns_rdata_freestruct(&cname);
3457 return (ISC_R_SUCCESS);
3460 static inline isc_result_t
3461 dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
3462 dns_fixedname_t *fixeddname)
3464 isc_result_t result;
3465 dns_rdata_t rdata = DNS_RDATA_INIT;
3466 unsigned int nlabels, nbits;
3468 dns_namereln_t namereln;
3469 dns_rdata_dname_t dname;
3470 dns_fixedname_t prefix;
3473 * Get the target name of the DNAME.
3476 result = dns_rdataset_first(rdataset);
3477 if (result != ISC_R_SUCCESS)
3479 dns_rdataset_current(rdataset, &rdata);
3480 result = dns_rdata_tostruct(&rdata, &dname, NULL);
3481 if (result != ISC_R_SUCCESS)
3485 * Get the prefix of qname.
3487 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels,
3489 if (namereln != dns_namereln_subdomain) {
3490 dns_rdata_freestruct(&dname);
3491 return (DNS_R_FORMERR);
3493 dns_fixedname_init(&prefix);
3494 result = dns_name_split(qname, nlabels, nbits,
3495 dns_fixedname_name(&prefix), NULL);
3496 if (result != ISC_R_SUCCESS) {
3497 dns_rdata_freestruct(&dname);
3500 dns_fixedname_init(fixeddname);
3501 result = dns_name_concatenate(dns_fixedname_name(&prefix),
3503 dns_fixedname_name(fixeddname), NULL);
3504 dns_rdata_freestruct(&dname);
3509 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname) {
3510 isc_result_t result;
3511 dns_message_t *message;
3512 dns_name_t *name, *qname, *ns_name, *soa_name;
3513 dns_rdataset_t *rdataset, *ns_rdataset;
3514 isc_boolean_t done, aa, negative_response;
3515 dns_rdatatype_t type;
3517 FCTXTRACE("noanswer_response");
3519 message = fctx->rmessage;
3524 if (oqname == NULL) {
3526 * We have a normal, non-chained negative response or
3529 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
3533 qname = &fctx->name;
3536 * We're being invoked by answer_response() after it has
3537 * followed a CNAME/DNAME chain.
3542 * If the current qname is not a subdomain of the query
3543 * domain, there's no point in looking at the authority
3544 * section without doing DNSSEC validation.
3546 * Until we do that validation, we'll just return success
3549 if (!dns_name_issubdomain(qname, &fctx->domain))
3550 return (ISC_R_SUCCESS);
3554 * We have to figure out if this is a negative response, or a
3559 * Sometimes we can tell if its a negative response by looking at
3560 * the message header.
3562 negative_response = ISC_FALSE;
3563 if (message->rcode == dns_rcode_nxdomain ||
3564 (message->counts[DNS_SECTION_ANSWER] == 0 &&
3565 message->counts[DNS_SECTION_AUTHORITY] == 0))
3566 negative_response = ISC_TRUE;
3569 * Process the authority section.
3575 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3576 while (!done && result == ISC_R_SUCCESS) {
3578 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3579 if (dns_name_issubdomain(name, &fctx->domain)) {
3580 for (rdataset = ISC_LIST_HEAD(name->list);
3582 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3583 type = rdataset->type;
3584 if (type == dns_rdatatype_sig)
3585 type = rdataset->covers;
3586 if (type == dns_rdatatype_ns) {
3590 * Only one set of NS RRs is allowed.
3592 if (rdataset->type ==
3594 if (ns_name != NULL &&
3596 return (DNS_R_FORMERR);
3601 rdataset->attributes |=
3602 DNS_RDATASETATTR_CACHE;
3603 rdataset->trust = dns_trust_glue;
3604 ns_rdataset = rdataset;
3607 for (rdataset = ISC_LIST_HEAD(name->list);
3609 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3610 type = rdataset->type;
3611 if (type == dns_rdatatype_sig)
3612 type = rdataset->covers;
3613 if (type == dns_rdatatype_soa ||
3614 type == dns_rdatatype_nxt) {
3616 * SOA, SIG SOA, NXT, or SIG NXT.
3618 * Only one SOA is allowed.
3620 if (rdataset->type ==
3621 dns_rdatatype_soa) {
3622 if (soa_name != NULL &&
3624 return (DNS_R_FORMERR);
3627 if (ns_name == NULL) {
3628 negative_response = ISC_TRUE;
3630 DNS_NAMEATTR_NCACHE;
3631 rdataset->attributes |=
3632 DNS_RDATASETATTR_NCACHE;
3636 rdataset->attributes |=
3637 DNS_RDATASETATTR_CACHE;
3641 dns_trust_authauthority;
3644 dns_trust_additional;
3646 * No additional data needs to be
3652 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
3653 if (result == ISC_R_NOMORE)
3655 else if (result != ISC_R_SUCCESS)
3660 * Did we find anything?
3662 if (!negative_response && ns_name == NULL) {
3666 if (oqname != NULL) {
3668 * We've already got a partial CNAME/DNAME chain,
3669 * and haven't found else anything useful here, but
3670 * no error has occurred since we have an answer.
3672 return (ISC_R_SUCCESS);
3675 * The responder is insane.
3677 return (DNS_R_FORMERR);
3682 * If we found both NS and SOA, they should be the same name.
3684 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name)
3685 return (DNS_R_FORMERR);
3688 * Do we have a referral? (We only want to follow a referral if
3689 * we're not following a chain.)
3691 if (!negative_response && ns_name != NULL && oqname == NULL) {
3693 * We already know ns_name is a subdomain of fctx->domain.
3694 * If ns_name is equal to fctx->domain, we're not making
3695 * progress. We return DNS_R_FORMERR so that we'll keep
3696 * keep trying other servers.
3698 if (dns_name_equal(ns_name, &fctx->domain))
3699 return (DNS_R_FORMERR);
3702 * If the referral name is not a parent of the query
3703 * name, consider the responder insane.
3705 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
3706 FCTXTRACE("referral to non-parent");
3707 return (DNS_R_FORMERR);
3711 * Mark any additional data related to this rdataset.
3712 * It's important that we do this before we change the
3715 INSIST(ns_rdataset != NULL);
3716 fctx->attributes |= FCTX_ATTR_GLUING;
3717 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
3719 fctx->attributes &= ~FCTX_ATTR_GLUING;
3721 * NS rdatasets with 0 TTL cause problems.
3722 * dns_view_findzonecut() will not find them when we
3723 * try to follow the referral, and we'll SERVFAIL
3724 * because the best nameservers are now above QDOMAIN.
3725 * We force the TTL to 1 second to prevent this.
3727 if (ns_rdataset->ttl == 0)
3728 ns_rdataset->ttl = 1;
3730 * Set the current query domain to the referral name.
3732 * XXXRTH We should check if we're in forward-only mode, and
3733 * if so we should bail out.
3735 INSIST(dns_name_countlabels(&fctx->domain) > 0);
3736 dns_name_free(&fctx->domain, fctx->res->mctx);
3737 if (dns_rdataset_isassociated(&fctx->nameservers))
3738 dns_rdataset_disassociate(&fctx->nameservers);
3739 dns_name_init(&fctx->domain, NULL);
3740 result = dns_name_dup(ns_name, fctx->res->mctx, &fctx->domain);
3741 if (result != ISC_R_SUCCESS)
3743 fctx->attributes |= FCTX_ATTR_WANTCACHE;
3744 return (DNS_R_DELEGATION);
3748 * Since we're not doing a referral, we don't want to cache any
3749 * NS RRs we may have found.
3751 if (ns_name != NULL)
3752 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
3754 if (negative_response && oqname == NULL)
3755 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
3757 return (ISC_R_SUCCESS);
3761 answer_response(fetchctx_t *fctx) {
3762 isc_result_t result;
3763 dns_message_t *message;
3764 dns_name_t *name, *qname, tname;
3765 dns_rdataset_t *rdataset;
3766 isc_boolean_t done, external, chaining, aa, found, want_chaining;
3767 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
3769 dns_rdatatype_t type;
3770 dns_fixedname_t dname, fqname;
3772 FCTXTRACE("answer_response");
3774 message = fctx->rmessage;
3777 * Examine the answer section, marking those rdatasets which are
3778 * part of the answer and should be cached.
3782 found_cname = ISC_FALSE;
3783 found_type = ISC_FALSE;
3784 chaining = ISC_FALSE;
3785 have_answer = ISC_FALSE;
3786 want_chaining = ISC_FALSE;
3787 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
3791 qname = &fctx->name;
3793 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
3794 while (!done && result == ISC_R_SUCCESS) {
3796 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
3797 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
3798 if (dns_name_equal(name, qname)) {
3799 wanted_chaining = ISC_FALSE;
3800 for (rdataset = ISC_LIST_HEAD(name->list);
3802 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3804 want_chaining = ISC_FALSE;
3806 if (rdataset->type == type && !found_cname) {
3808 * We've found an ordinary answer.
3811 found_type = ISC_TRUE;
3813 aflag = DNS_RDATASETATTR_ANSWER;
3814 } else if (type == dns_rdatatype_any) {
3816 * We've found an answer matching
3817 * an ANY query. There may be
3821 aflag = DNS_RDATASETATTR_ANSWER;
3822 } else if (rdataset->type == dns_rdatatype_sig
3823 && rdataset->covers == type
3826 * We've found a signature that
3827 * covers the type we're looking for.
3830 found_type = ISC_TRUE;
3831 aflag = DNS_RDATASETATTR_ANSWERSIG;
3832 } else if (rdataset->type ==
3836 * We're looking for something else,
3837 * but we found a CNAME.
3839 * Getting a CNAME response for some
3840 * query types is an error.
3842 if (type == dns_rdatatype_sig ||
3843 type == dns_rdatatype_key ||
3844 type == dns_rdatatype_nxt)
3845 return (DNS_R_FORMERR);
3847 found_cname = ISC_TRUE;
3848 want_chaining = ISC_TRUE;
3849 aflag = DNS_RDATASETATTR_ANSWER;
3850 result = cname_target(rdataset,
3852 if (result != ISC_R_SUCCESS)
3854 } else if (rdataset->type == dns_rdatatype_sig
3855 && rdataset->covers ==
3859 * We're looking for something else,
3860 * but we found a SIG CNAME.
3863 found_cname = ISC_TRUE;
3864 aflag = DNS_RDATASETATTR_ANSWERSIG;
3869 * We've found an answer to our
3874 rdataset->attributes |=
3875 DNS_RDATASETATTR_CACHE;
3876 rdataset->trust = dns_trust_answer;
3879 * This data is "the" answer
3880 * to our question only if
3881 * we're not chaining (i.e.
3882 * if we haven't followed
3883 * a CNAME or DNAME).
3887 DNS_RDATASETATTR_ANSWER)
3888 have_answer = ISC_TRUE;
3890 DNS_NAMEATTR_ANSWER;
3891 rdataset->attributes |= aflag;
3894 dns_trust_authanswer;
3895 } else if (external) {
3897 * This data is outside of
3898 * our query domain, and
3899 * may only be cached if it
3900 * comes from a secure zone
3903 rdataset->attributes |=
3904 DNS_RDATASETATTR_EXTERNAL;
3908 * Mark any additional data related
3911 (void)dns_rdataset_additionaldata(
3919 if (want_chaining) {
3920 wanted_chaining = ISC_TRUE;
3922 DNS_NAMEATTR_CHAINING;
3923 rdataset->attributes |=
3924 DNS_RDATASETATTR_CHAINING;
3929 * We could add an "else" clause here and
3930 * log that we're ignoring this rdataset.
3934 * If wanted_chaining is true, we've done
3935 * some chaining as the result of processing
3936 * this node, and thus we need to set
3939 * We don't set chaining inside of the
3940 * rdataset loop because doing that would
3941 * cause us to ignore the signatures of
3944 if (wanted_chaining)
3945 chaining = ISC_TRUE;
3948 * Look for a DNAME (or its SIG). Anything else is
3951 wanted_chaining = ISC_FALSE;
3952 for (rdataset = ISC_LIST_HEAD(name->list);
3954 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3955 isc_boolean_t found_dname = ISC_FALSE;
3958 if (rdataset->type == dns_rdatatype_dname) {
3960 * We're looking for something else,
3961 * but we found a DNAME.
3963 * If we're not chaining, then the
3964 * DNAME should not be external.
3966 if (!chaining && external)
3967 return (DNS_R_FORMERR);
3969 want_chaining = ISC_TRUE;
3970 aflag = DNS_RDATASETATTR_ANSWER;
3971 result = dname_target(rdataset,
3974 if (result == ISC_R_NOSPACE) {
3976 * We can't construct the
3977 * DNAME target. Do not
3980 want_chaining = ISC_FALSE;
3981 } else if (result != ISC_R_SUCCESS)
3984 found_dname = ISC_TRUE;
3985 } else if (rdataset->type == dns_rdatatype_sig
3986 && rdataset->covers ==
3987 dns_rdatatype_dname) {
3989 * We've found a signature that
3993 aflag = DNS_RDATASETATTR_ANSWERSIG;
3998 * We've found an answer to our
4003 rdataset->attributes |=
4004 DNS_RDATASETATTR_CACHE;
4005 rdataset->trust = dns_trust_answer;
4008 * This data is "the" answer
4009 * to our question only if
4010 * we're not chaining.
4014 DNS_RDATASETATTR_ANSWER)
4015 have_answer = ISC_TRUE;
4017 DNS_NAMEATTR_ANSWER;
4018 rdataset->attributes |= aflag;
4021 dns_trust_authanswer;
4022 } else if (external) {
4023 rdataset->attributes |=
4024 DNS_RDATASETATTR_EXTERNAL;
4032 * Copy the the dname into the
4035 * Although we check for
4036 * failure of the copy
4037 * operation, in practice it
4038 * should never fail since
4039 * we already know that the
4040 * result fits in a fixedname.
4042 dns_fixedname_init(&fqname);
4043 result = dns_name_copy(
4044 dns_fixedname_name(&dname),
4045 dns_fixedname_name(&fqname),
4047 if (result != ISC_R_SUCCESS)
4049 wanted_chaining = ISC_TRUE;
4051 DNS_NAMEATTR_CHAINING;
4052 rdataset->attributes |=
4053 DNS_RDATASETATTR_CHAINING;
4054 qname = dns_fixedname_name(
4059 if (wanted_chaining)
4060 chaining = ISC_TRUE;
4062 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
4064 if (result == ISC_R_NOMORE)
4065 result = ISC_R_SUCCESS;
4066 if (result != ISC_R_SUCCESS)
4070 * We should have found an answer.
4073 return (DNS_R_FORMERR);
4076 * This response is now potentially cacheable.
4078 fctx->attributes |= FCTX_ATTR_WANTCACHE;
4081 * Did chaining end before we got the final answer?
4085 * Yes. This may be a negative reply, so hand off
4086 * authority section processing to the noanswer code.
4087 * If it isn't a noanswer response, no harm will be
4090 return (noanswer_response(fctx, qname));
4094 * We didn't end with an incomplete chain, so the rcode should be
4097 if (message->rcode != dns_rcode_noerror)
4098 return (DNS_R_FORMERR);
4101 * Examine the authority section (if there is one).
4103 * We expect there to be only one owner name for all the rdatasets
4104 * in this section, and we expect that it is not external.
4107 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
4108 while (!done && result == ISC_R_SUCCESS) {
4110 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
4111 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4114 * We expect to find NS or SIG NS rdatasets, and
4117 for (rdataset = ISC_LIST_HEAD(name->list);
4119 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4120 if (rdataset->type == dns_rdatatype_ns ||
4121 (rdataset->type == dns_rdatatype_sig &&
4122 rdataset->covers == dns_rdatatype_ns)) {
4125 rdataset->attributes |=
4126 DNS_RDATASETATTR_CACHE;
4127 if (aa && !chaining)
4129 dns_trust_authauthority;
4132 dns_trust_additional;
4135 * Mark any additional data related
4138 (void)dns_rdataset_additionaldata(
4145 * Since we've found a non-external name in the
4146 * authority section, we should stop looking, even
4147 * if we didn't find any NS or SIG NS.
4151 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
4153 if (result == ISC_R_NOMORE)
4154 result = ISC_R_SUCCESS;
4160 resquery_response(isc_task_t *task, isc_event_t *event) {
4161 isc_result_t result;
4162 resquery_t *query = event->ev_arg;
4163 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
4164 isc_boolean_t keep_trying, broken_server, get_nameservers, resend;
4165 isc_boolean_t truncated;
4166 dns_message_t *message;
4169 dns_fixedname_t foundname;
4171 isc_time_t tnow, *finish;
4172 dns_adbaddrinfo_t *addrinfo;
4173 unsigned int options;
4175 REQUIRE(VALID_QUERY(query));
4177 options = query->options;
4178 REQUIRE(VALID_FCTX(fctx));
4179 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
4184 (void)isc_timer_touch(fctx->timer);
4186 keep_trying = ISC_FALSE;
4187 broken_server = ISC_FALSE;
4188 get_nameservers = ISC_FALSE;
4190 truncated = ISC_FALSE;
4193 if (fctx->res->exiting) {
4194 result = ISC_R_SHUTTINGDOWN;
4201 * XXXRTH We should really get the current time just once. We
4202 * need a routine to convert from an isc_time_t to an
4205 result = isc_time_now(&tnow);
4206 if (result != ISC_R_SUCCESS)
4209 isc_stdtime_get(&now);
4212 * Did the dispatcher have a problem?
4214 if (devent->result != ISC_R_SUCCESS) {
4215 if (devent->result == ISC_R_EOF &&
4216 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
4218 * The problem might be that they
4219 * don't understand EDNS0. Turn it
4220 * off and try again.
4222 options |= DNS_FETCHOPT_NOEDNS0;
4225 * Remember that they don't like EDNS0.
4227 dns_adb_changeflags(fctx->adb,
4229 DNS_FETCHOPT_NOEDNS0,
4230 DNS_FETCHOPT_NOEDNS0);
4233 * There's no hope for this query.
4235 keep_trying = ISC_TRUE;
4240 message = fctx->rmessage;
4242 if (query->tsig != NULL) {
4243 result = dns_message_setquerytsig(message, query->tsig);
4244 if (result != ISC_R_SUCCESS)
4248 if (query->tsigkey) {
4249 result = dns_message_settsigkey(message, query->tsigkey);
4250 if (result != ISC_R_SUCCESS)
4254 result = dns_message_parse(message, &devent->buffer, 0);
4255 if (result != ISC_R_SUCCESS) {
4257 case ISC_R_UNEXPECTEDEND:
4258 if (!message->question_ok ||
4259 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
4260 (options & DNS_FETCHOPT_TCP) != 0) {
4262 * Either the message ended prematurely,
4263 * and/or wasn't marked as being truncated,
4264 * and/or this is a response to a query we
4265 * sent over TCP. In all of these cases,
4266 * something is wrong with the remote
4267 * server and we don't want to retry using
4270 if ((query->options & DNS_FETCHOPT_NOEDNS0)
4273 * The problem might be that they
4274 * don't understand EDNS0. Turn it
4275 * off and try again.
4277 options |= DNS_FETCHOPT_NOEDNS0;
4280 * Remember that they don't like EDNS0.
4282 dns_adb_changeflags(
4285 DNS_FETCHOPT_NOEDNS0,
4286 DNS_FETCHOPT_NOEDNS0);
4288 broken_server = ISC_TRUE;
4289 keep_trying = ISC_TRUE;
4294 * We defer retrying via TCP for a bit so we can
4295 * check out this message further.
4297 truncated = ISC_TRUE;
4300 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
4302 * The problem might be that they
4303 * don't understand EDNS0. Turn it
4304 * off and try again.
4306 options |= DNS_FETCHOPT_NOEDNS0;
4309 * Remember that they don't like EDNS0.
4311 dns_adb_changeflags(fctx->adb,
4313 DNS_FETCHOPT_NOEDNS0,
4314 DNS_FETCHOPT_NOEDNS0);
4316 broken_server = ISC_TRUE;
4317 keep_trying = ISC_TRUE;
4322 * Something bad has happened.
4329 * If the message is signed, check the signature. If not, this
4330 * returns success anyway.
4332 result = dns_message_checksig(message, fctx->res->view);
4333 if (result != ISC_R_SUCCESS)
4337 * The dispatcher should ensure we only get responses with QR set.
4339 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
4341 * INSIST() that the message comes from the place we sent it to,
4342 * since the dispatch code should ensure this.
4344 * INSIST() that the message id is correct (this should also be
4345 * ensured by the dispatch code).
4350 * Deal with truncated responses by retrying using TCP.
4352 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
4353 truncated = ISC_TRUE;
4356 if ((options & DNS_FETCHOPT_TCP) != 0) {
4357 broken_server = ISC_TRUE;
4358 keep_trying = ISC_TRUE;
4360 options |= DNS_FETCHOPT_TCP;
4367 * Is it a query response?
4369 if (message->opcode != dns_opcode_query) {
4371 broken_server = ISC_TRUE;
4372 keep_trying = ISC_TRUE;
4377 * Is the remote server broken, or does it dislike us?
4379 if (message->rcode != dns_rcode_noerror &&
4380 message->rcode != dns_rcode_nxdomain) {
4381 if ((message->rcode == dns_rcode_formerr ||
4382 message->rcode == dns_rcode_notimp ||
4383 message->rcode == dns_rcode_servfail) &&
4384 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
4386 * It's very likely they don't like EDNS0.
4388 * XXXRTH We should check if the question
4389 * we're asking requires EDNS0, and
4390 * if so, we should bail out.
4392 options |= DNS_FETCHOPT_NOEDNS0;
4395 * Remember that they don't like EDNS0.
4397 if (message->rcode != dns_rcode_servfail)
4398 dns_adb_changeflags(fctx->adb, query->addrinfo,
4399 DNS_FETCHOPT_NOEDNS0,
4400 DNS_FETCHOPT_NOEDNS0);
4401 } else if (message->rcode == dns_rcode_formerr) {
4402 if (ISFORWARDER(query->addrinfo)) {
4404 * This forwarder doesn't understand us,
4405 * but other forwarders might. Keep trying.
4407 broken_server = ISC_TRUE;
4408 keep_trying = ISC_TRUE;
4411 * The server doesn't understand us. Since
4412 * all servers for a zone need similar
4413 * capabilities, we assume that we will get
4414 * FORMERR from all servers, and thus we
4415 * cannot make any more progress with this
4418 result = DNS_R_FORMERR;
4420 } else if (message->rcode == dns_rcode_yxdomain) {
4422 * DNAME mapping failed because the new name
4423 * was too long. There's no chance of success
4426 result = DNS_R_YXDOMAIN;
4431 broken_server = ISC_TRUE;
4432 keep_trying = ISC_TRUE;
4438 * Is the question the same as the one we asked?
4440 result = same_question(fctx);
4441 if (result != ISC_R_SUCCESS) {
4443 if (result == DNS_R_FORMERR)
4444 keep_trying = ISC_TRUE;
4449 * Is the server lame?
4451 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
4453 log_lame(fctx, query->addrinfo);
4454 dns_adb_marklame(fctx->adb, query->addrinfo,
4455 &fctx->domain, now + fctx->res->lame_ttl);
4456 broken_server = ISC_TRUE;
4457 keep_trying = ISC_TRUE;
4462 * Enforce delegations only zones like NET and COM.
4464 if (!ISFORWARDER(query->addrinfo) &&
4465 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
4466 !dns_name_equal(&fctx->domain, &fctx->name) &&
4467 fix_mustbedelegationornxdomain(message, fctx)) {
4468 char namebuf[DNS_NAME_FORMATSIZE];
4469 char domainbuf[DNS_NAME_FORMATSIZE];
4470 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4474 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
4475 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
4476 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
4477 dns_rdataclass_format(fctx->res->rdclass, classbuf,
4479 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
4482 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
4483 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
4484 "enforced delegation-only for '%s' (%s/%s/%s) "
4486 domainbuf, namebuf, typebuf, classbuf, addrbuf);
4490 * Did we get any answers?
4492 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
4493 (message->rcode == dns_rcode_noerror ||
4494 message->rcode == dns_rcode_nxdomain)) {
4496 * We've got answers.
4498 result = answer_response(fctx);
4499 if (result != ISC_R_SUCCESS) {
4500 if (result == DNS_R_FORMERR)
4501 keep_trying = ISC_TRUE;
4504 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
4505 message->rcode == dns_rcode_noerror ||
4506 message->rcode == dns_rcode_nxdomain) {
4508 * NXDOMAIN, NXRDATASET, or referral.
4510 result = noanswer_response(fctx, NULL);
4511 if (result == DNS_R_DELEGATION) {
4513 * We don't have the answer, but we know a better
4516 get_nameservers = ISC_TRUE;
4517 keep_trying = ISC_TRUE;
4519 * We have a new set of name servers, and it
4520 * has not experienced any restarts yet.
4523 result = ISC_R_SUCCESS;
4524 } else if (result != ISC_R_SUCCESS) {
4526 * Something has gone wrong.
4528 if (result == DNS_R_FORMERR)
4529 keep_trying = ISC_TRUE;
4534 * The server is insane.
4537 broken_server = ISC_TRUE;
4538 keep_trying = ISC_TRUE;
4543 * Follow A6 and other additional section data chains.
4545 chase_additional(fctx);
4548 * Cache the cacheable parts of the message. This may also cause
4549 * work to be queued to the DNSSEC validator.
4551 if (WANTCACHE(fctx)) {
4552 result = cache_message(fctx, now);
4553 if (result != ISC_R_SUCCESS)
4558 * Ncache the negatively cacheable parts of the message. This may
4559 * also cause work to be queued to the DNSSEC validator.
4561 if (WANTNCACHE(fctx)) {
4562 dns_rdatatype_t covers;
4563 if (message->rcode == dns_rcode_nxdomain)
4564 covers = dns_rdatatype_any;
4566 covers = fctx->type;
4569 * Cache any negative cache entries in the message.
4571 result = ncache_message(fctx, covers, now);
4576 * Remember the query's addrinfo, in case we need to mark the
4579 addrinfo = query->addrinfo;
4584 * XXXRTH Don't cancel the query if waiting for validation?
4586 fctx_cancelquery(&query, &devent, finish, ISC_FALSE);
4589 if (result == DNS_R_FORMERR)
4590 broken_server = ISC_TRUE;
4591 if (broken_server) {
4593 * Add this server to the list of bad servers for
4596 add_bad(fctx, &addrinfo->sockaddr);
4599 if (get_nameservers) {
4601 dns_fixedname_init(&foundname);
4602 fname = dns_fixedname_name(&foundname);
4603 if (result != ISC_R_SUCCESS) {
4604 fctx_done(fctx, DNS_R_SERVFAIL);
4607 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
4610 name = &fctx->domain;
4611 result = dns_view_findzonecut(fctx->res->view,
4616 if (result != ISC_R_SUCCESS) {
4617 FCTXTRACE("couldn't find a zonecut");
4618 fctx_done(fctx, DNS_R_SERVFAIL);
4621 if (!dns_name_issubdomain(fname, &fctx->domain)) {
4623 * The best nameservers are now above our
4626 FCTXTRACE("nameservers now above QDOMAIN");
4627 fctx_done(fctx, DNS_R_SERVFAIL);
4630 dns_name_free(&fctx->domain, fctx->res->mctx);
4631 dns_name_init(&fctx->domain, NULL);
4632 result = dns_name_dup(fname, fctx->res->mctx,
4634 if (result != ISC_R_SUCCESS) {
4635 fctx_done(fctx, DNS_R_SERVFAIL);
4638 fctx_cancelqueries(fctx, ISC_TRUE);
4639 fctx_cleanupfinds(fctx);
4640 fctx_cleanupforwaddrs(fctx);
4646 } else if (resend) {
4648 * Resend (probably with changed options).
4650 FCTXTRACE("resend");
4651 result = fctx_query(fctx, addrinfo, options);
4652 if (result != ISC_R_SUCCESS)
4653 fctx_done(fctx, result);
4654 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
4656 * All has gone well so far, but we are waiting for the
4657 * DNSSEC validator to validate the answer.
4659 FCTXTRACE("wait for validator");
4660 fctx_cancelqueries(fctx, ISC_TRUE);
4662 * We must not retransmit while the validator is working;
4663 * it has references to the current rmessage.
4665 result = fctx_stopidletimer(fctx);
4666 if (result != ISC_R_SUCCESS)
4667 fctx_done(fctx, result);
4672 fctx_done(fctx, result);
4678 *** Resolver Methods
4682 destroy(dns_resolver_t *res) {
4685 REQUIRE(res->references == 0);
4686 REQUIRE(!res->priming);
4687 REQUIRE(res->primefetch == NULL);
4691 DESTROYLOCK(&res->primelock);
4692 DESTROYLOCK(&res->lock);
4693 for (i = 0; i < res->nbuckets; i++) {
4694 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
4695 isc_task_shutdown(res->buckets[i].task);
4696 isc_task_detach(&res->buckets[i].task);
4697 DESTROYLOCK(&res->buckets[i].lock);
4699 isc_mem_put(res->mctx, res->buckets,
4700 res->nbuckets * sizeof (fctxbucket_t));
4701 if (res->dispatchv4 != NULL)
4702 dns_dispatch_detach(&res->dispatchv4);
4703 if (res->dispatchv6 != NULL)
4704 dns_dispatch_detach(&res->dispatchv6);
4706 isc_mem_put(res->mctx, res, sizeof *res);
4710 send_shutdown_events(dns_resolver_t *res) {
4711 isc_event_t *event, *next_event;
4715 * Caller must be holding the resolver lock.
4718 for (event = ISC_LIST_HEAD(res->whenshutdown);
4720 event = next_event) {
4721 next_event = ISC_LIST_NEXT(event, ev_link);
4722 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
4723 etask = event->ev_sender;
4724 event->ev_sender = res;
4725 isc_task_sendanddetach(&etask, &event);
4730 empty_bucket(dns_resolver_t *res) {
4731 RTRACE("empty_bucket");
4735 INSIST(res->activebuckets > 0);
4736 res->activebuckets--;
4737 if (res->activebuckets == 0)
4738 send_shutdown_events(res);
4744 dns_resolver_create(dns_view_t *view,
4745 isc_taskmgr_t *taskmgr, unsigned int ntasks,
4746 isc_socketmgr_t *socketmgr,
4747 isc_timermgr_t *timermgr,
4748 unsigned int options,
4749 dns_dispatchmgr_t *dispatchmgr,
4750 dns_dispatch_t *dispatchv4,
4751 dns_dispatch_t *dispatchv6,
4752 dns_resolver_t **resp)
4754 dns_resolver_t *res;
4755 isc_result_t result = ISC_R_SUCCESS;
4756 unsigned int i, buckets_created = 0;
4760 * Create a resolver.
4763 REQUIRE(DNS_VIEW_VALID(view));
4764 REQUIRE(ntasks > 0);
4765 REQUIRE(resp != NULL && *resp == NULL);
4766 REQUIRE(dispatchmgr != NULL);
4767 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
4769 res = isc_mem_get(view->mctx, sizeof *res);
4771 return (ISC_R_NOMEMORY);
4773 res->mctx = view->mctx;
4774 res->rdclass = view->rdclass;
4775 res->socketmgr = socketmgr;
4776 res->timermgr = timermgr;
4777 res->taskmgr = taskmgr;
4778 res->dispatchmgr = dispatchmgr;
4780 res->options = options;
4783 res->nbuckets = ntasks;
4784 res->activebuckets = ntasks;
4785 res->buckets = isc_mem_get(view->mctx,
4786 ntasks * sizeof (fctxbucket_t));
4787 if (res->buckets == NULL) {
4788 result = ISC_R_NOMEMORY;
4791 for (i = 0; i < ntasks; i++) {
4792 result = isc_mutex_init(&res->buckets[i].lock);
4793 if (result != ISC_R_SUCCESS)
4794 goto cleanup_buckets;
4795 res->buckets[i].task = NULL;
4796 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
4797 if (result != ISC_R_SUCCESS) {
4798 DESTROYLOCK(&res->buckets[i].lock);
4799 goto cleanup_buckets;
4801 sprintf(name, "res%u", i);
4802 isc_task_setname(res->buckets[i].task, name, res);
4803 ISC_LIST_INIT(res->buckets[i].fctxs);
4804 res->buckets[i].exiting = ISC_FALSE;
4808 res->dispatchv4 = NULL;
4809 if (dispatchv4 != NULL)
4810 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
4811 res->dispatchv6 = NULL;
4812 if (dispatchv6 != NULL)
4813 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
4815 res->references = 1;
4816 res->exiting = ISC_FALSE;
4817 res->frozen = ISC_FALSE;
4818 ISC_LIST_INIT(res->whenshutdown);
4819 res->priming = ISC_FALSE;
4820 res->primefetch = NULL;
4822 result = isc_mutex_init(&res->lock);
4823 if (result != ISC_R_SUCCESS)
4824 goto cleanup_dispatches;
4826 result = isc_mutex_init(&res->primelock);
4827 if (result != ISC_R_SUCCESS)
4830 res->magic = RES_MAGIC;
4834 return (ISC_R_SUCCESS);
4837 DESTROYLOCK(&res->lock);
4840 if (res->dispatchv6 != NULL)
4841 dns_dispatch_detach(&res->dispatchv6);
4842 if (res->dispatchv4 != NULL)
4843 dns_dispatch_detach(&res->dispatchv4);
4846 for (i = 0; i < buckets_created; i++) {
4847 DESTROYLOCK(&res->buckets[i].lock);
4848 isc_task_shutdown(res->buckets[i].task);
4849 isc_task_detach(&res->buckets[i].task);
4851 isc_mem_put(view->mctx, res->buckets,
4852 res->nbuckets * sizeof (fctxbucket_t));
4855 isc_mem_put(view->mctx, res, sizeof *res);
4861 prime_done(isc_task_t *task, isc_event_t *event) {
4862 dns_resolver_t *res;
4863 dns_fetchevent_t *fevent;
4866 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
4867 fevent = (dns_fetchevent_t *)event;
4868 res = event->ev_arg;
4869 REQUIRE(VALID_RESOLVER(res));
4875 INSIST(res->priming);
4876 res->priming = ISC_FALSE;
4877 LOCK(&res->primelock);
4878 fetch = res->primefetch;
4879 res->primefetch = NULL;
4880 UNLOCK(&res->primelock);
4884 if (fevent->node != NULL)
4885 dns_db_detachnode(fevent->db, &fevent->node);
4886 if (fevent->db != NULL)
4887 dns_db_detach(&fevent->db);
4888 if (dns_rdataset_isassociated(fevent->rdataset))
4889 dns_rdataset_disassociate(fevent->rdataset);
4890 INSIST(fevent->sigrdataset == NULL);
4892 isc_mem_put(res->mctx, fevent->rdataset, sizeof *fevent->rdataset);
4894 isc_event_free(&event);
4895 dns_resolver_destroyfetch(&fetch);
4899 dns_resolver_prime(dns_resolver_t *res) {
4900 isc_boolean_t want_priming = ISC_FALSE;
4901 dns_rdataset_t *rdataset;
4902 isc_result_t result;
4904 REQUIRE(VALID_RESOLVER(res));
4905 REQUIRE(res->frozen);
4907 RTRACE("dns_resolver_prime");
4911 if (!res->exiting && !res->priming) {
4912 INSIST(res->primefetch == NULL);
4913 res->priming = ISC_TRUE;
4914 want_priming = ISC_TRUE;
4921 * To avoid any possible recursive locking problems, we
4922 * start the priming fetch like any other fetch, and holding
4923 * no resolver locks. No one else will try to start it
4924 * because we're the ones who set res->priming to true.
4925 * Any other callers of dns_resolver_prime() while we're
4926 * running will see that res->priming is already true and
4930 rdataset = isc_mem_get(res->mctx, sizeof *rdataset);
4931 if (rdataset == NULL) {
4933 INSIST(res->priming);
4934 INSIST(res->primefetch == NULL);
4935 res->priming = ISC_FALSE;
4939 dns_rdataset_init(rdataset);
4940 LOCK(&res->primelock);
4941 result = dns_resolver_createfetch(res, dns_rootname,
4943 NULL, NULL, NULL, 0,
4944 res->buckets[0].task,
4946 res, rdataset, NULL,
4948 UNLOCK(&res->primelock);
4949 if (result != ISC_R_SUCCESS) {
4951 INSIST(res->priming);
4952 res->priming = ISC_FALSE;
4959 dns_resolver_freeze(dns_resolver_t *res) {
4965 REQUIRE(VALID_RESOLVER(res));
4966 REQUIRE(!res->frozen);
4968 res->frozen = ISC_TRUE;
4972 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
4973 REQUIRE(VALID_RESOLVER(source));
4974 REQUIRE(targetp != NULL && *targetp == NULL);
4976 RRTRACE(source, "attach");
4977 LOCK(&source->lock);
4978 REQUIRE(!source->exiting);
4980 INSIST(source->references > 0);
4981 source->references++;
4982 INSIST(source->references != 0);
4983 UNLOCK(&source->lock);
4989 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
4990 isc_event_t **eventp)
4995 REQUIRE(VALID_RESOLVER(res));
4996 REQUIRE(eventp != NULL);
5003 if (res->exiting && res->activebuckets == 0) {
5005 * We're already shutdown. Send the event.
5007 event->ev_sender = res;
5008 isc_task_send(task, &event);
5011 isc_task_attach(task, &clone);
5012 event->ev_sender = clone;
5013 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
5020 dns_resolver_shutdown(dns_resolver_t *res) {
5025 REQUIRE(VALID_RESOLVER(res));
5031 if (!res->exiting) {
5033 res->exiting = ISC_TRUE;
5035 for (i = 0; i < res->nbuckets; i++) {
5036 LOCK(&res->buckets[i].lock);
5037 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
5039 fctx = ISC_LIST_NEXT(fctx, link))
5040 fctx_shutdown(fctx);
5041 if (res->dispatchv4 != NULL) {
5042 sock = dns_dispatch_getsocket(res->dispatchv4);
5043 isc_socket_cancel(sock, res->buckets[i].task,
5044 ISC_SOCKCANCEL_ALL);
5046 if (res->dispatchv6 != NULL) {
5047 sock = dns_dispatch_getsocket(res->dispatchv6);
5048 isc_socket_cancel(sock, res->buckets[i].task,
5049 ISC_SOCKCANCEL_ALL);
5051 res->buckets[i].exiting = ISC_TRUE;
5052 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
5053 INSIST(res->activebuckets > 0);
5054 res->activebuckets--;
5056 UNLOCK(&res->buckets[i].lock);
5058 if (res->activebuckets == 0)
5059 send_shutdown_events(res);
5066 dns_resolver_detach(dns_resolver_t **resp) {
5067 dns_resolver_t *res;
5068 isc_boolean_t need_destroy = ISC_FALSE;
5070 REQUIRE(resp != NULL);
5072 REQUIRE(VALID_RESOLVER(res));
5078 INSIST(res->references > 0);
5080 if (res->references == 0) {
5081 INSIST(res->exiting && res->activebuckets == 0);
5082 need_destroy = ISC_TRUE;
5093 static inline isc_boolean_t
5094 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
5095 unsigned int options)
5097 if (fctx->type != type || fctx->options != options)
5099 return (dns_name_equal(&fctx->name, name));
5103 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
5104 char namebuf[DNS_NAME_FORMATSIZE];
5105 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5106 int level = ISC_LOG_DEBUG(1);
5108 if (! isc_log_wouldlog(dns_lctx, level))
5111 dns_name_format(name, namebuf, sizeof(namebuf));
5112 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
5114 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5115 DNS_LOGMODULE_RESOLVER, level,
5116 "createfetch: %s %s", namebuf, typebuf);
5120 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
5121 dns_rdatatype_t type,
5122 dns_name_t *domain, dns_rdataset_t *nameservers,
5123 dns_forwarders_t *forwarders,
5124 unsigned int options, isc_task_t *task,
5125 isc_taskaction_t action, void *arg,
5126 dns_rdataset_t *rdataset,
5127 dns_rdataset_t *sigrdataset,
5128 dns_fetch_t **fetchp)
5131 fetchctx_t *fctx = NULL;
5132 isc_result_t result;
5133 unsigned int bucketnum;
5134 isc_boolean_t new_fctx = ISC_FALSE;
5139 REQUIRE(VALID_RESOLVER(res));
5140 REQUIRE(res->frozen);
5141 /* XXXRTH Check for meta type */
5142 if (domain != NULL) {
5143 REQUIRE(DNS_RDATASET_VALID(nameservers));
5144 REQUIRE(nameservers->type == dns_rdatatype_ns);
5146 REQUIRE(nameservers == NULL);
5147 REQUIRE(forwarders == NULL);
5148 REQUIRE(!dns_rdataset_isassociated(rdataset));
5149 REQUIRE(sigrdataset == NULL ||
5150 !dns_rdataset_isassociated(sigrdataset));
5151 REQUIRE(fetchp != NULL && *fetchp == NULL);
5153 log_fetch(name, type);
5156 * XXXRTH use a mempool?
5158 fetch = isc_mem_get(res->mctx, sizeof *fetch);
5160 return (ISC_R_NOMEMORY);
5162 bucketnum = dns_name_hash(name, ISC_FALSE) % res->nbuckets;
5164 LOCK(&res->buckets[bucketnum].lock);
5166 if (res->buckets[bucketnum].exiting) {
5167 result = ISC_R_SHUTTINGDOWN;
5171 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
5172 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
5174 fctx = ISC_LIST_NEXT(fctx, link)) {
5175 if (fctx_match(fctx, name, type, options))
5181 * If we didn't have a fetch, would attach to a done fetch, this
5182 * fetch has already cloned its results, or if the fetch has gone
5183 * "idle" (no one was interested in it), we need to start a new
5184 * fetch instead of joining with the existing one.
5187 fctx->state == fetchstate_done ||
5189 ISC_LIST_EMPTY(fctx->events)) {
5191 result = fctx_create(res, name, type, domain, nameservers,
5192 options, bucketnum, &fctx);
5193 if (result != ISC_R_SUCCESS)
5195 new_fctx = ISC_TRUE;
5198 result = fctx_join(fctx, task, action, arg,
5199 rdataset, sigrdataset, fetch);
5201 if (result == ISC_R_SUCCESS) {
5205 event = &fctx->control_event;
5206 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
5207 DNS_EVENT_FETCHCONTROL,
5208 fctx_start, fctx, NULL,
5210 isc_task_send(res->buckets[bucketnum].task, &event);
5213 * We don't care about the result of fctx_destroy()
5214 * since we know we're not exiting.
5216 (void)fctx_destroy(fctx);
5221 UNLOCK(&res->buckets[bucketnum].lock);
5223 if (result == ISC_R_SUCCESS) {
5227 isc_mem_put(res->mctx, fetch, sizeof *fetch);
5233 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
5235 dns_resolver_t *res;
5236 dns_fetchevent_t *event, *next_event;
5239 REQUIRE(DNS_FETCH_VALID(fetch));
5240 fctx = fetch->private;
5241 REQUIRE(VALID_FCTX(fctx));
5244 FTRACE("cancelfetch");
5246 LOCK(&res->buckets[fctx->bucketnum].lock);
5249 * Find the completion event for this fetch (as opposed
5250 * to those for other fetches that have joined the same
5251 * fctx) and send it with result = ISC_R_CANCELED.
5254 if (fctx->state != fetchstate_done) {
5255 for (event = ISC_LIST_HEAD(fctx->events);
5257 event = next_event) {
5258 next_event = ISC_LIST_NEXT(event, ev_link);
5259 if (event->fetch == fetch) {
5260 ISC_LIST_UNLINK(fctx->events, event, ev_link);
5265 if (event != NULL) {
5266 etask = event->ev_sender;
5267 event->ev_sender = fctx;
5268 event->result = ISC_R_CANCELED;
5269 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
5272 * The fctx continues running even if no fetches remain;
5273 * the answer is still cached.
5276 UNLOCK(&res->buckets[fctx->bucketnum].lock);
5280 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
5282 dns_resolver_t *res;
5283 dns_fetchevent_t *event, *next_event;
5285 unsigned int bucketnum;
5286 isc_boolean_t bucket_empty = ISC_FALSE;
5288 REQUIRE(fetchp != NULL);
5290 REQUIRE(DNS_FETCH_VALID(fetch));
5291 fctx = fetch->private;
5292 REQUIRE(VALID_FCTX(fctx));
5295 FTRACE("destroyfetch");
5297 bucketnum = fctx->bucketnum;
5298 LOCK(&res->buckets[bucketnum].lock);
5301 * Sanity check: the caller should have gotten its event before
5302 * trying to destroy the fetch.
5305 if (fctx->state != fetchstate_done) {
5306 for (event = ISC_LIST_HEAD(fctx->events);
5308 event = next_event) {
5309 next_event = ISC_LIST_NEXT(event, ev_link);
5310 RUNTIME_CHECK(event->fetch != fetch);
5314 INSIST(fctx->references > 0);
5316 if (fctx->references == 0) {
5318 * No one cares about the result of this fetch anymore.
5320 if (fctx->pending == 0 && ISC_LIST_EMPTY(fctx->validators) &&
5321 SHUTTINGDOWN(fctx)) {
5323 * This fctx is already shutdown; we were just
5324 * waiting for the last reference to go away.
5326 bucket_empty = fctx_destroy(fctx);
5329 * Initiate shutdown.
5331 fctx_shutdown(fctx);
5335 UNLOCK(&res->buckets[bucketnum].lock);
5337 isc_mem_put(res->mctx, fetch, sizeof *fetch);
5345 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
5346 REQUIRE(VALID_RESOLVER(resolver));
5347 return (resolver->dispatchmgr);
5351 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
5352 REQUIRE(VALID_RESOLVER(resolver));
5353 return (resolver->dispatchv4);
5357 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
5358 REQUIRE(VALID_RESOLVER(resolver));
5359 return (resolver->dispatchv6);
5363 dns_resolver_socketmgr(dns_resolver_t *resolver) {
5364 REQUIRE(VALID_RESOLVER(resolver));
5365 return (resolver->socketmgr);
5369 dns_resolver_taskmgr(dns_resolver_t *resolver) {
5370 REQUIRE(VALID_RESOLVER(resolver));
5371 return (resolver->taskmgr);
5375 dns_resolver_getlamettl(dns_resolver_t *resolver) {
5376 REQUIRE(VALID_RESOLVER(resolver));
5377 return (resolver->lame_ttl);
5381 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
5382 REQUIRE(VALID_RESOLVER(resolver));
5383 resolver->lame_ttl = lame_ttl;