2 * Copyright (C) 2004, 2005 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.18.4.56.4.1 2006/08/17 07:12:31 marka Exp $ */
22 #include <isc/print.h>
23 #include <isc/string.h>
25 #include <isc/timer.h>
31 #include <dns/dispatch.h>
32 #include <dns/events.h>
33 #include <dns/forward.h>
34 #include <dns/keytable.h>
36 #include <dns/message.h>
37 #include <dns/ncache.h>
38 #include <dns/opcode.h>
41 #include <dns/rcode.h>
42 #include <dns/rdata.h>
43 #include <dns/rdataclass.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/rdatatype.h>
48 #include <dns/resolver.h>
49 #include <dns/result.h>
51 #include <dns/validator.h>
53 #define DNS_RESOLVER_TRACE
54 #ifdef DNS_RESOLVER_TRACE
55 #define RTRACE(m) isc_log_write(dns_lctx, \
56 DNS_LOGCATEGORY_RESOLVER, \
57 DNS_LOGMODULE_RESOLVER, \
59 "res %p: %s", res, (m))
60 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
61 DNS_LOGCATEGORY_RESOLVER, \
62 DNS_LOGMODULE_RESOLVER, \
64 "res %p: %s", (r), (m))
65 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
66 DNS_LOGCATEGORY_RESOLVER, \
67 DNS_LOGMODULE_RESOLVER, \
69 "fctx %p(%s'): %s", fctx, fctx->info, (m))
70 #define FCTXTRACE2(m1, m2) \
71 isc_log_write(dns_lctx, \
72 DNS_LOGCATEGORY_RESOLVER, \
73 DNS_LOGMODULE_RESOLVER, \
75 "fctx %p(%s): %s %s", \
76 fctx, fctx->info, (m1), (m2))
77 #define FTRACE(m) isc_log_write(dns_lctx, \
78 DNS_LOGCATEGORY_RESOLVER, \
79 DNS_LOGMODULE_RESOLVER, \
81 "fetch %p (fctx %p(%s)): %s", \
82 fetch, fetch->private, \
83 fetch->private->info, (m))
84 #define QTRACE(m) isc_log_write(dns_lctx, \
85 DNS_LOGCATEGORY_RESOLVER, \
86 DNS_LOGMODULE_RESOLVER, \
88 "resquery %p (fctx %p(%s)): %s", \
90 query->fctx->info, (m))
100 * Maximum EDNS0 input packet size.
102 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
105 * This defines the maximum number of timeouts we will permit before we
106 * disable EDNS0 on the query.
108 #define MAX_EDNS0_TIMEOUTS 3
110 typedef struct fetchctx fetchctx_t;
112 typedef struct query {
113 /* Locked by task event serialization. */
117 dns_dispatchmgr_t * dispatchmgr;
118 dns_dispatch_t * dispatch;
119 dns_adbaddrinfo_t * addrinfo;
120 isc_socket_t * tcpsocket;
123 dns_dispentry_t * dispentry;
124 ISC_LINK(struct query) link;
127 dns_tsigkey_t *tsigkey;
128 unsigned int options;
129 unsigned int attributes;
131 unsigned int connects;
132 unsigned char data[512];
135 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
136 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
138 #define RESQUERY_ATTR_CANCELED 0x02
140 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
141 #define RESQUERY_CANCELED(q) (((q)->attributes & \
142 RESQUERY_ATTR_CANCELED) != 0)
143 #define RESQUERY_SENDING(q) ((q)->sends > 0)
146 fetchstate_init = 0, /* Start event has not run yet. */
148 fetchstate_done /* FETCHDONE events posted. */
154 dns_resolver_t * res;
156 dns_rdatatype_t type;
157 unsigned int options;
158 unsigned int bucketnum;
160 /* Locked by appropriate bucket lock. */
162 isc_boolean_t want_shutdown;
163 isc_boolean_t cloned;
164 unsigned int references;
165 isc_event_t control_event;
166 ISC_LINK(struct fetchctx) link;
167 ISC_LIST(dns_fetchevent_t) events;
168 /* Locked by task event serialization. */
170 dns_rdataset_t nameservers;
171 unsigned int attributes;
174 isc_interval_t interval;
175 dns_message_t * qmessage;
176 dns_message_t * rmessage;
177 ISC_LIST(resquery_t) queries;
178 dns_adbfindlist_t finds;
179 dns_adbfind_t * find;
180 dns_adbfindlist_t altfinds;
181 dns_adbfind_t * altfind;
182 dns_adbaddrinfolist_t forwaddrs;
183 dns_adbaddrinfolist_t altaddrs;
184 isc_sockaddrlist_t forwarders;
185 dns_fwdpolicy_t fwdpolicy;
186 isc_sockaddrlist_t bad;
187 ISC_LIST(dns_validator_t) validators;
192 * The number of events we're waiting for.
194 unsigned int pending;
197 * The number of times we've "restarted" the current
198 * nameserver set. This acts as a failsafe to prevent
199 * us from pounding constantly on a particular set of
200 * servers that, for whatever reason, are not giving
201 * us useful responses, but are responding in such a
202 * way that they are not marked "bad".
204 unsigned int restarts;
207 * The number of timeouts that have occurred since we
208 * last successfully received a response packet. This
209 * is used for EDNS0 black hole detection.
211 unsigned int timeouts;
213 * Look aside state for DS lookups.
216 dns_fetch_t * nsfetch;
217 dns_rdataset_t nsrrset;
220 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
221 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
223 #define FCTX_ATTR_HAVEANSWER 0x0001
224 #define FCTX_ATTR_GLUING 0x0002
225 #define FCTX_ATTR_ADDRWAIT 0x0004
226 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
227 #define FCTX_ATTR_WANTCACHE 0x0010
228 #define FCTX_ATTR_WANTNCACHE 0x0020
229 #define FCTX_ATTR_NEEDEDNS0 0x0040
230 #define FCTX_ATTR_TRIEDFIND 0x0080
231 #define FCTX_ATTR_TRIEDALT 0x0100
233 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
235 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
237 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
239 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
241 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
242 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
243 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
244 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
245 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
248 dns_adbaddrinfo_t * addrinfo;
254 fetchctx_t * private;
257 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
258 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
260 typedef struct fctxbucket {
263 ISC_LIST(fetchctx_t) fctxs;
264 isc_boolean_t exiting;
267 typedef struct alternate {
268 isc_boolean_t isaddress;
276 ISC_LINK(struct alternate) link;
279 struct dns_resolver {
285 isc_mutex_t primelock;
286 dns_rdataclass_t rdclass;
287 isc_socketmgr_t * socketmgr;
288 isc_timermgr_t * timermgr;
289 isc_taskmgr_t * taskmgr;
291 isc_boolean_t frozen;
292 unsigned int options;
293 dns_dispatchmgr_t * dispatchmgr;
294 dns_dispatch_t * dispatchv4;
295 dns_dispatch_t * dispatchv6;
296 unsigned int nbuckets;
297 fctxbucket_t * buckets;
298 isc_uint32_t lame_ttl;
299 ISC_LIST(alternate_t) alternates;
300 isc_uint16_t udpsize;
302 isc_rwlock_t alglock;
304 dns_rbt_t * algorithms;
306 isc_rwlock_t mbslock;
308 dns_rbt_t * mustbesecure;
309 /* Locked by lock. */
310 unsigned int references;
311 isc_boolean_t exiting;
312 isc_eventlist_t whenshutdown;
313 unsigned int activebuckets;
314 isc_boolean_t priming;
315 /* Locked by primelock. */
316 dns_fetch_t * primefetch;
317 /* Locked by nlock. */
321 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
322 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
325 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
326 * which we also use as an addrinfo flag.
328 #define FCTX_ADDRINFO_MARK 0x0001
329 #define FCTX_ADDRINFO_FORWARDER 0x1000
330 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
332 #define ISFORWARDER(a) (((a)->flags & \
333 FCTX_ADDRINFO_FORWARDER) != 0)
335 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
337 static void destroy(dns_resolver_t *res);
338 static void empty_bucket(dns_resolver_t *res);
339 static isc_result_t resquery_send(resquery_t *query);
340 static void resquery_response(isc_task_t *task, isc_event_t *event);
341 static void resquery_connected(isc_task_t *task, isc_event_t *event);
342 static void fctx_try(fetchctx_t *fctx);
343 static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
344 static isc_result_t ncache_adderesult(dns_message_t *message,
345 dns_db_t *cache, dns_dbnode_t *node,
346 dns_rdatatype_t covers,
347 isc_stdtime_t now, dns_ttl_t maxttl,
348 dns_rdataset_t *ardataset,
349 isc_result_t *eresultp);
350 static void validated(isc_task_t *task, isc_event_t *event);
353 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
354 dns_rdatatype_t type, dns_rdataset_t *rdataset,
355 dns_rdataset_t *sigrdataset, unsigned int valoptions,
358 dns_validator_t *validator = NULL;
359 dns_valarg_t *valarg;
362 valarg = isc_mem_get(fctx->res->mctx, sizeof(*valarg));
364 return (ISC_R_NOMEMORY);
367 valarg->addrinfo = addrinfo;
369 result = dns_validator_create(fctx->res->view, name, type, rdataset,
370 sigrdataset, fctx->rmessage,
371 valoptions, task, validated, valarg,
373 if (result == ISC_R_SUCCESS)
374 ISC_LIST_APPEND(fctx->validators, validator, link);
376 isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg));
381 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
383 dns_name_t *domain = &fctx->domain;
384 dns_rdataset_t *rdataset;
385 dns_rdatatype_t type;
387 isc_boolean_t keep_auth = ISC_FALSE;
389 if (message->rcode == dns_rcode_nxdomain)
393 * Look for BIND 8 style delegations.
394 * Also look for answers to ANY queries where the duplicate NS RRset
395 * may have been stripped from the authority section.
397 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
398 (fctx->type == dns_rdatatype_ns ||
399 fctx->type == dns_rdatatype_any)) {
400 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
401 while (result == ISC_R_SUCCESS) {
403 dns_message_currentname(message, DNS_SECTION_ANSWER,
405 for (rdataset = ISC_LIST_HEAD(name->list);
407 rdataset = ISC_LIST_NEXT(rdataset, link)) {
408 type = rdataset->type;
409 if (type != dns_rdatatype_ns)
411 if (dns_name_issubdomain(name, domain))
414 result = dns_message_nextname(message,
419 /* Look for referral. */
420 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
423 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
424 while (result == ISC_R_SUCCESS) {
426 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
427 for (rdataset = ISC_LIST_HEAD(name->list);
429 rdataset = ISC_LIST_NEXT(rdataset, link)) {
430 type = rdataset->type;
431 if (type == dns_rdatatype_soa &&
432 dns_name_equal(name, domain))
433 keep_auth = ISC_TRUE;
434 if (type != dns_rdatatype_ns &&
435 type != dns_rdatatype_soa)
437 if (dns_name_equal(name, domain))
439 if (dns_name_issubdomain(name, domain))
442 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
446 message->rcode = dns_rcode_nxdomain;
447 message->counts[DNS_SECTION_ANSWER] = 0;
449 message->counts[DNS_SECTION_AUTHORITY] = 0;
450 message->counts[DNS_SECTION_ADDITIONAL] = 0;
454 static inline isc_result_t
455 fctx_starttimer(fetchctx_t *fctx) {
457 * Start the lifetime timer for fctx.
459 * This is also used for stopping the idle timer; in that
460 * case we must purge events already posted to ensure that
461 * no further idle events are delivered.
463 return (isc_timer_reset(fctx->timer, isc_timertype_once,
464 &fctx->expires, NULL,
469 fctx_stoptimer(fetchctx_t *fctx) {
473 * We don't return a result if resetting the timer to inactive fails
474 * since there's nothing to be done about it. Resetting to inactive
475 * should never fail anyway, since the code as currently written
476 * cannot fail in that case.
478 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
479 NULL, NULL, ISC_TRUE);
480 if (result != ISC_R_SUCCESS) {
481 UNEXPECTED_ERROR(__FILE__, __LINE__,
482 "isc_timer_reset(): %s",
483 isc_result_totext(result));
488 static inline isc_result_t
489 fctx_startidletimer(fetchctx_t *fctx) {
491 * Start the idle timer for fctx. The lifetime timer continues
494 return (isc_timer_reset(fctx->timer, isc_timertype_once,
495 &fctx->expires, &fctx->interval,
500 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
501 * we use fctx_stopidletimer for readability in the code below.
503 #define fctx_stopidletimer fctx_starttimer
507 resquery_destroy(resquery_t **queryp) {
510 REQUIRE(queryp != NULL);
512 REQUIRE(!ISC_LINK_LINKED(query, link));
514 INSIST(query->tcpsocket == NULL);
517 isc_mem_put(query->mctx, query, sizeof(*query));
522 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
523 isc_time_t *finish, isc_boolean_t no_response)
530 dns_adbaddrinfo_t *addrinfo;
535 FCTXTRACE("cancelquery");
537 REQUIRE(!RESQUERY_CANCELED(query));
539 query->attributes |= RESQUERY_ATTR_CANCELED;
542 * Should we update the RTT?
544 if (finish != NULL || no_response) {
545 if (finish != NULL) {
547 * We have both the start and finish times for this
548 * packet, so we can compute a real RTT.
550 rtt = (unsigned int)isc_time_microdiff(finish,
552 factor = DNS_ADB_RTTADJDEFAULT;
555 * We don't have an RTT for this query. Maybe the
556 * packet was lost, or maybe this server is very
557 * slow. We don't know. Increase the RTT.
560 rtt = query->addrinfo->srtt +
561 (200000 * fctx->restarts);
565 * Replace the current RTT with our value.
567 factor = DNS_ADB_RTTADJREPLACE;
569 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
573 * Age RTTs of servers not tried.
575 factor = DNS_ADB_RTTADJAGE;
577 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
579 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
580 if (UNMARKED(addrinfo))
581 dns_adb_adjustsrtt(fctx->adb, addrinfo,
584 if (finish != NULL && TRIEDFIND(fctx))
585 for (find = ISC_LIST_HEAD(fctx->finds);
587 find = ISC_LIST_NEXT(find, publink))
588 for (addrinfo = ISC_LIST_HEAD(find->list);
590 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
591 if (UNMARKED(addrinfo))
592 dns_adb_adjustsrtt(fctx->adb, addrinfo,
595 if (finish != NULL && TRIEDALT(fctx)) {
596 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
598 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
599 if (UNMARKED(addrinfo))
600 dns_adb_adjustsrtt(fctx->adb, addrinfo,
602 for (find = ISC_LIST_HEAD(fctx->altfinds);
604 find = ISC_LIST_NEXT(find, publink))
605 for (addrinfo = ISC_LIST_HEAD(find->list);
607 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
608 if (UNMARKED(addrinfo))
609 dns_adb_adjustsrtt(fctx->adb, addrinfo,
613 if (query->dispentry != NULL)
614 dns_dispatch_removeresponse(&query->dispentry, deventp);
616 ISC_LIST_UNLINK(fctx->queries, query, link);
618 if (query->tsig != NULL)
619 isc_buffer_free(&query->tsig);
621 if (query->tsigkey != NULL)
622 dns_tsigkey_detach(&query->tsigkey);
625 * Check for any outstanding socket events. If they exist, cancel
626 * them and let the event handlers finish the cleanup. The resolver
627 * only needs to worry about managing the connect and send events;
628 * the dispatcher manages the recv events.
630 if (RESQUERY_CONNECTING(query))
632 * Cancel the connect.
634 isc_socket_cancel(query->tcpsocket, NULL,
635 ISC_SOCKCANCEL_CONNECT);
636 else if (RESQUERY_SENDING(query))
638 * Cancel the pending send.
640 isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
641 NULL, ISC_SOCKCANCEL_SEND);
643 if (query->dispatch != NULL)
644 dns_dispatch_detach(&query->dispatch);
646 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
648 * It's safe to destroy the query now.
650 resquery_destroy(&query);
654 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
655 resquery_t *query, *next_query;
657 FCTXTRACE("cancelqueries");
659 for (query = ISC_LIST_HEAD(fctx->queries);
661 query = next_query) {
662 next_query = ISC_LIST_NEXT(query, link);
663 fctx_cancelquery(&query, NULL, NULL, no_response);
668 fctx_cleanupfinds(fetchctx_t *fctx) {
669 dns_adbfind_t *find, *next_find;
671 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
673 for (find = ISC_LIST_HEAD(fctx->finds);
676 next_find = ISC_LIST_NEXT(find, publink);
677 ISC_LIST_UNLINK(fctx->finds, find, publink);
678 dns_adb_destroyfind(&find);
684 fctx_cleanupaltfinds(fetchctx_t *fctx) {
685 dns_adbfind_t *find, *next_find;
687 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
689 for (find = ISC_LIST_HEAD(fctx->altfinds);
692 next_find = ISC_LIST_NEXT(find, publink);
693 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
694 dns_adb_destroyfind(&find);
696 fctx->altfind = NULL;
700 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
701 dns_adbaddrinfo_t *addr, *next_addr;
703 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
705 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
708 next_addr = ISC_LIST_NEXT(addr, publink);
709 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
710 dns_adb_freeaddrinfo(fctx->adb, &addr);
715 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
716 dns_adbaddrinfo_t *addr, *next_addr;
718 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
720 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
723 next_addr = ISC_LIST_NEXT(addr, publink);
724 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
725 dns_adb_freeaddrinfo(fctx->adb, &addr);
730 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
731 FCTXTRACE("stopeverything");
732 fctx_cancelqueries(fctx, no_response);
733 fctx_cleanupfinds(fctx);
734 fctx_cleanupaltfinds(fctx);
735 fctx_cleanupforwaddrs(fctx);
736 fctx_cleanupaltaddrs(fctx);
737 fctx_stoptimer(fctx);
741 fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
742 dns_fetchevent_t *event, *next_event;
746 * Caller must be holding the appropriate bucket lock.
748 REQUIRE(fctx->state == fetchstate_done);
750 FCTXTRACE("sendevents");
752 for (event = ISC_LIST_HEAD(fctx->events);
754 event = next_event) {
755 next_event = ISC_LIST_NEXT(event, ev_link);
756 ISC_LIST_UNLINK(fctx->events, event, ev_link);
757 task = event->ev_sender;
758 event->ev_sender = fctx;
759 if (!HAVE_ANSWER(fctx))
760 event->result = result;
762 INSIST(result != ISC_R_SUCCESS ||
763 dns_rdataset_isassociated(event->rdataset) ||
764 fctx->type == dns_rdatatype_any ||
765 fctx->type == dns_rdatatype_rrsig ||
766 fctx->type == dns_rdatatype_sig);
768 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
773 fctx_done(fetchctx_t *fctx, isc_result_t result) {
775 isc_boolean_t no_response;
781 if (result == ISC_R_SUCCESS)
782 no_response = ISC_TRUE;
784 no_response = ISC_FALSE;
785 fctx_stopeverything(fctx, no_response);
787 LOCK(&res->buckets[fctx->bucketnum].lock);
789 fctx->state = fetchstate_done;
790 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
791 fctx_sendevents(fctx, result);
793 UNLOCK(&res->buckets[fctx->bucketnum].lock);
797 resquery_senddone(isc_task_t *task, isc_event_t *event) {
798 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
799 resquery_t *query = event->ev_arg;
800 isc_boolean_t retry = ISC_FALSE;
804 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
811 * Currently we don't wait for the senddone event before retrying
812 * a query. This means that if we get really behind, we may end
813 * up doing extra work!
818 INSIST(RESQUERY_SENDING(query));
823 if (RESQUERY_CANCELED(query)) {
824 if (query->sends == 0) {
826 * This query was canceled while the
827 * isc_socket_sendto() was in progress.
829 if (query->tcpsocket != NULL)
830 isc_socket_detach(&query->tcpsocket);
831 resquery_destroy(&query);
834 switch (sevent->result) {
838 case ISC_R_HOSTUNREACH:
839 case ISC_R_NETUNREACH:
841 case ISC_R_ADDRNOTAVAIL:
842 case ISC_R_CONNREFUSED:
845 * No route to remote.
847 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
852 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
856 isc_event_free(&event);
860 * Behave as if the idle timer has expired. For TCP
861 * this may not actually reflect the latest timer.
863 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
864 result = fctx_stopidletimer(fctx);
865 if (result != ISC_R_SUCCESS)
866 fctx_done(fctx, result);
872 static inline isc_result_t
873 fctx_addopt(dns_message_t *message, dns_resolver_t *res) {
874 dns_rdataset_t *rdataset;
875 dns_rdatalist_t *rdatalist;
880 result = dns_message_gettemprdatalist(message, &rdatalist);
881 if (result != ISC_R_SUCCESS)
884 result = dns_message_gettemprdata(message, &rdata);
885 if (result != ISC_R_SUCCESS)
888 result = dns_message_gettemprdataset(message, &rdataset);
889 if (result != ISC_R_SUCCESS)
891 dns_rdataset_init(rdataset);
893 rdatalist->type = dns_rdatatype_opt;
894 rdatalist->covers = 0;
897 * Set Maximum UDP buffer size.
899 rdatalist->rdclass = res->udpsize;
902 * Set EXTENDED-RCODE, VERSION, and Z to 0, and the DO bit to 1.
904 rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO;
911 rdata->rdclass = rdatalist->rdclass;
912 rdata->type = rdatalist->type;
915 ISC_LIST_INIT(rdatalist->rdata);
916 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
917 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
919 return (dns_message_setopt(message, rdataset));
923 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
924 unsigned int seconds;
927 * We retry every 2 seconds the first two times through the address
928 * list, and then we do exponential back-off.
930 if (fctx->restarts < 3)
933 seconds = (2 << (fctx->restarts - 1));
936 * Double the round-trip time and convert to seconds.
941 * Always wait for at least the doubled round-trip time.
947 * But don't ever wait for more than 30 seconds.
952 isc_interval_set(&fctx->interval, seconds, 0);
956 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
957 unsigned int options)
967 task = res->buckets[fctx->bucketnum].task;
969 fctx_setretryinterval(fctx, addrinfo->srtt);
970 result = fctx_startidletimer(fctx);
971 if (result != ISC_R_SUCCESS)
974 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
976 query = isc_mem_get(res->mctx, sizeof(*query));
978 result = ISC_R_NOMEMORY;
979 goto stop_idle_timer;
981 query->mctx = res->mctx;
982 query->options = options;
983 query->attributes = 0;
987 * Note that the caller MUST guarantee that 'addrinfo' will remain
988 * valid until this query is canceled.
990 query->addrinfo = addrinfo;
991 TIME_NOW(&query->start);
994 * If this is a TCP query, then we need to make a socket and
995 * a dispatch for it here. Otherwise we use the resolver's
998 query->dispatchmgr = res->dispatchmgr;
999 query->dispatch = NULL;
1000 query->tcpsocket = NULL;
1001 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1002 isc_sockaddr_t addr;
1005 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1009 result = dns_dispatch_getlocaladdress(res->dispatchv4,
1013 result = dns_dispatch_getlocaladdress(res->dispatchv6,
1017 result = ISC_R_NOTIMPLEMENTED;
1020 if (result != ISC_R_SUCCESS)
1023 isc_sockaddr_setport(&addr, 0);
1025 result = isc_socket_create(res->socketmgr, pf,
1028 if (result != ISC_R_SUCCESS)
1031 result = isc_socket_bind(query->tcpsocket, &addr);
1032 if (result != ISC_R_SUCCESS)
1033 goto cleanup_socket;
1036 * A dispatch will be created once the connect succeeds.
1039 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1041 dns_dispatch_attach(res->dispatchv4, &query->dispatch);
1044 dns_dispatch_attach(res->dispatchv6, &query->dispatch);
1047 result = ISC_R_NOTIMPLEMENTED;
1051 * We should always have a valid dispatcher here. If we
1052 * don't support a protocol family, then its dispatcher
1053 * will be NULL, but we shouldn't be finding addresses for
1054 * protocol types we don't support, so the dispatcher
1055 * we found should never be NULL.
1057 INSIST(query->dispatch != NULL);
1060 query->dispentry = NULL;
1063 query->tsigkey = NULL;
1064 ISC_LINK_INIT(query, link);
1065 query->magic = QUERY_MAGIC;
1067 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1069 * Connect to the remote server.
1071 * XXXRTH Should we attach to the socket?
1073 result = isc_socket_connect(query->tcpsocket,
1074 &addrinfo->sockaddr, task,
1075 resquery_connected, query);
1076 if (result != ISC_R_SUCCESS)
1077 goto cleanup_socket;
1079 QTRACE("connecting via TCP");
1081 result = resquery_send(query);
1082 if (result != ISC_R_SUCCESS)
1083 goto cleanup_dispatch;
1086 ISC_LIST_APPEND(fctx->queries, query, link);
1088 return (ISC_R_SUCCESS);
1091 isc_socket_detach(&query->tcpsocket);
1094 if (query->dispatch != NULL)
1095 dns_dispatch_detach(&query->dispatch);
1099 isc_mem_put(res->mctx, query, sizeof(*query));
1102 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1108 resquery_send(resquery_t *query) {
1110 isc_result_t result;
1111 dns_name_t *qname = NULL;
1112 dns_rdataset_t *qrdataset = NULL;
1114 dns_resolver_t *res;
1116 isc_socket_t *socket;
1117 isc_buffer_t tcpbuffer;
1118 isc_sockaddr_t *address;
1119 isc_buffer_t *buffer;
1120 isc_netaddr_t ipaddr;
1121 dns_tsigkey_t *tsigkey = NULL;
1122 dns_peer_t *peer = NULL;
1123 isc_boolean_t useedns;
1124 dns_compress_t cctx;
1125 isc_boolean_t cleanup_cctx = ISC_FALSE;
1126 isc_boolean_t secure_domain;
1132 task = res->buckets[fctx->bucketnum].task;
1135 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1137 * Reserve space for the TCP message length.
1139 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1140 isc_buffer_init(&query->buffer, query->data + 2,
1141 sizeof(query->data) - 2);
1142 buffer = &tcpbuffer;
1144 isc_buffer_init(&query->buffer, query->data,
1145 sizeof(query->data));
1146 buffer = &query->buffer;
1149 result = dns_message_gettempname(fctx->qmessage, &qname);
1150 if (result != ISC_R_SUCCESS)
1152 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1153 if (result != ISC_R_SUCCESS)
1157 * Get a query id from the dispatch.
1159 result = dns_dispatch_addresponse(query->dispatch,
1160 &query->addrinfo->sockaddr,
1166 if (result != ISC_R_SUCCESS)
1169 fctx->qmessage->opcode = dns_opcode_query;
1174 dns_name_init(qname, NULL);
1175 dns_name_clone(&fctx->name, qname);
1176 dns_rdataset_init(qrdataset);
1177 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1178 ISC_LIST_APPEND(qname->list, qrdataset, link);
1179 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1184 * Set RD if the client has requested that we do a recursive query,
1185 * or if we're sending to a forwarder.
1187 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1188 ISFORWARDER(query->addrinfo))
1189 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1192 * Set CD if the client says don't validate or the question is
1193 * under a secure entry point.
1195 if ((query->options & DNS_FETCHOPT_NOVALIDATE) == 0) {
1196 result = dns_keytable_issecuredomain(res->view->secroots,
1199 if (result != ISC_R_SUCCESS)
1200 secure_domain = ISC_FALSE;
1201 if (res->view->dlv != NULL)
1202 secure_domain = ISC_TRUE;
1204 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1206 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1209 * We don't have to set opcode because it defaults to query.
1211 fctx->qmessage->id = query->id;
1214 * Convert the question to wire format.
1216 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1217 if (result != ISC_R_SUCCESS)
1218 goto cleanup_message;
1219 cleanup_cctx = ISC_TRUE;
1221 result = dns_message_renderbegin(fctx->qmessage, &cctx,
1223 if (result != ISC_R_SUCCESS)
1224 goto cleanup_message;
1226 result = dns_message_rendersection(fctx->qmessage,
1227 DNS_SECTION_QUESTION, 0);
1228 if (result != ISC_R_SUCCESS)
1229 goto cleanup_message;
1232 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1233 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1236 * The ADB does not know about servers with "edns no". Check this,
1237 * and then inform the ADB for future use.
1239 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1241 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1244 query->options |= DNS_FETCHOPT_NOEDNS0;
1245 dns_adb_changeflags(fctx->adb,
1247 DNS_FETCHOPT_NOEDNS0,
1248 DNS_FETCHOPT_NOEDNS0);
1252 * Use EDNS0, unless the caller doesn't want it, or we know that
1253 * the remote server doesn't like it.
1255 if (fctx->timeouts >= MAX_EDNS0_TIMEOUTS &&
1256 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1257 query->options |= DNS_FETCHOPT_NOEDNS0;
1258 FCTXTRACE("too many timeouts, disabling EDNS0");
1261 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1262 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1263 result = fctx_addopt(fctx->qmessage, res);
1264 if (result != ISC_R_SUCCESS) {
1266 * We couldn't add the OPT, but we'll press on.
1267 * We're not using EDNS0, so set the NOEDNS0
1270 query->options |= DNS_FETCHOPT_NOEDNS0;
1274 * We know this server doesn't like EDNS0, so we
1275 * won't use it. Set the NOEDNS0 bit since we're
1278 query->options |= DNS_FETCHOPT_NOEDNS0;
1283 * If we need EDNS0 to do this query and aren't using it, we lose.
1285 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1286 result = DNS_R_SERVFAIL;
1287 goto cleanup_message;
1291 * Add TSIG record tailored to the current recipient.
1293 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1294 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1295 goto cleanup_message;
1297 if (tsigkey != NULL) {
1298 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
1299 dns_tsigkey_detach(&tsigkey);
1300 if (result != ISC_R_SUCCESS)
1301 goto cleanup_message;
1304 result = dns_message_rendersection(fctx->qmessage,
1305 DNS_SECTION_ADDITIONAL, 0);
1306 if (result != ISC_R_SUCCESS)
1307 goto cleanup_message;
1309 result = dns_message_renderend(fctx->qmessage);
1310 if (result != ISC_R_SUCCESS)
1311 goto cleanup_message;
1313 dns_compress_invalidate(&cctx);
1314 cleanup_cctx = ISC_FALSE;
1316 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1317 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1319 result = dns_message_getquerytsig(fctx->qmessage,
1322 if (result != ISC_R_SUCCESS)
1323 goto cleanup_message;
1327 * If using TCP, write the length of the message at the beginning
1330 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1331 isc_buffer_usedregion(&query->buffer, &r);
1332 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1333 isc_buffer_add(&tcpbuffer, r.length);
1337 * We're now done with the query message.
1339 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1341 socket = dns_dispatch_getsocket(query->dispatch);
1345 if ((query->options & DNS_FETCHOPT_TCP) == 0)
1346 address = &query->addrinfo->sockaddr;
1347 isc_buffer_usedregion(buffer, &r);
1350 * XXXRTH Make sure we don't send to ourselves! We should probably
1351 * prune out these addresses when we get them from the ADB.
1353 result = isc_socket_sendto(socket, &r, task, resquery_senddone,
1354 query, address, NULL);
1355 if (result != ISC_R_SUCCESS)
1356 goto cleanup_message;
1360 return (ISC_R_SUCCESS);
1364 dns_compress_invalidate(&cctx);
1366 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1369 * Stop the dispatcher from listening.
1371 dns_dispatch_removeresponse(&query->dispentry, NULL);
1375 dns_message_puttempname(fctx->qmessage, &qname);
1376 if (qrdataset != NULL)
1377 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
1383 resquery_connected(isc_task_t *task, isc_event_t *event) {
1384 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1385 resquery_t *query = event->ev_arg;
1386 isc_boolean_t retry = ISC_FALSE;
1387 isc_result_t result;
1391 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1392 REQUIRE(VALID_QUERY(query));
1394 QTRACE("connected");
1401 * Currently we don't wait for the connect event before retrying
1402 * a query. This means that if we get really behind, we may end
1403 * up doing extra work!
1409 if (RESQUERY_CANCELED(query)) {
1411 * This query was canceled while the connect() was in
1414 isc_socket_detach(&query->tcpsocket);
1415 resquery_destroy(&query);
1417 switch (sevent->result) {
1420 * We are connected. Create a dispatcher and
1424 attrs |= DNS_DISPATCHATTR_TCP;
1425 attrs |= DNS_DISPATCHATTR_PRIVATE;
1426 attrs |= DNS_DISPATCHATTR_CONNECTED;
1427 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
1429 attrs |= DNS_DISPATCHATTR_IPV4;
1431 attrs |= DNS_DISPATCHATTR_IPV6;
1432 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
1434 result = dns_dispatch_createtcp(query->dispatchmgr,
1436 query->fctx->res->taskmgr,
1437 4096, 2, 1, 1, 3, attrs,
1441 * Regardless of whether dns_dispatch_create()
1442 * succeeded or not, we don't need our reference
1443 * to the socket anymore.
1445 isc_socket_detach(&query->tcpsocket);
1447 if (result == ISC_R_SUCCESS)
1448 result = resquery_send(query);
1450 if (result != ISC_R_SUCCESS) {
1451 fctx_cancelquery(&query, NULL, NULL,
1453 fctx_done(fctx, result);
1457 case ISC_R_NETUNREACH:
1458 case ISC_R_HOSTUNREACH:
1459 case ISC_R_CONNREFUSED:
1461 case ISC_R_ADDRNOTAVAIL:
1462 case ISC_R_CONNECTIONRESET:
1464 * No route to remote.
1466 isc_socket_detach(&query->tcpsocket);
1467 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
1472 isc_socket_detach(&query->tcpsocket);
1473 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1478 isc_event_free(&event);
1482 * Behave as if the idle timer has expired. For TCP
1483 * connections this may not actually reflect the latest timer.
1485 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1486 result = fctx_stopidletimer(fctx);
1487 if (result != ISC_R_SUCCESS)
1488 fctx_done(fctx, result);
1495 fctx_finddone(isc_task_t *task, isc_event_t *event) {
1497 dns_adbfind_t *find;
1498 dns_resolver_t *res;
1499 isc_boolean_t want_try = ISC_FALSE;
1500 isc_boolean_t want_done = ISC_FALSE;
1501 isc_boolean_t bucket_empty = ISC_FALSE;
1502 unsigned int bucketnum;
1504 find = event->ev_sender;
1505 fctx = event->ev_arg;
1506 REQUIRE(VALID_FCTX(fctx));
1511 FCTXTRACE("finddone");
1513 INSIST(fctx->pending > 0);
1516 if (ADDRWAIT(fctx)) {
1518 * The fetch is waiting for a name to be found.
1520 INSIST(!SHUTTINGDOWN(fctx));
1521 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1522 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
1523 want_try = ISC_TRUE;
1524 else if (fctx->pending == 0) {
1526 * We've got nothing else to wait for and don't
1527 * know the answer. There's nothing to do but
1530 want_done = ISC_TRUE;
1532 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
1533 ISC_LIST_EMPTY(fctx->validators)) {
1534 bucketnum = fctx->bucketnum;
1535 LOCK(&res->buckets[bucketnum].lock);
1537 * Note that we had to wait until we had the lock before
1538 * looking at fctx->references.
1540 if (fctx->references == 0)
1541 bucket_empty = fctx_destroy(fctx);
1542 UNLOCK(&res->buckets[bucketnum].lock);
1545 isc_event_free(&event);
1546 dns_adb_destroyfind(&find);
1551 fctx_done(fctx, ISC_R_FAILURE);
1552 else if (bucket_empty)
1557 static inline isc_boolean_t
1558 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
1561 for (sa = ISC_LIST_HEAD(fctx->bad);
1563 sa = ISC_LIST_NEXT(sa, link)) {
1564 if (isc_sockaddr_equal(sa, address))
1571 static inline isc_boolean_t
1572 mark_bad(fetchctx_t *fctx) {
1573 dns_adbfind_t *curr;
1574 dns_adbaddrinfo_t *addrinfo;
1575 isc_boolean_t all_bad = ISC_TRUE;
1578 * Mark all known bad servers, so we don't try to talk to them
1583 * Mark any bad nameservers.
1585 for (curr = ISC_LIST_HEAD(fctx->finds);
1587 curr = ISC_LIST_NEXT(curr, publink)) {
1588 for (addrinfo = ISC_LIST_HEAD(curr->list);
1590 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1591 if (bad_server(fctx, &addrinfo->sockaddr))
1592 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1594 all_bad = ISC_FALSE;
1599 * Mark any bad forwarders.
1601 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
1603 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1604 if (bad_server(fctx, &addrinfo->sockaddr))
1605 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1607 all_bad = ISC_FALSE;
1611 * Mark any bad alternates.
1613 for (curr = ISC_LIST_HEAD(fctx->altfinds);
1615 curr = ISC_LIST_NEXT(curr, publink)) {
1616 for (addrinfo = ISC_LIST_HEAD(curr->list);
1618 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1619 if (bad_server(fctx, &addrinfo->sockaddr))
1620 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1622 all_bad = ISC_FALSE;
1626 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
1628 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1629 if (bad_server(fctx, &addrinfo->sockaddr))
1630 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1632 all_bad = ISC_FALSE;
1639 add_bad(fetchctx_t *fctx, isc_sockaddr_t *address, isc_result_t reason) {
1640 char namebuf[DNS_NAME_FORMATSIZE];
1641 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
1647 const char *sep1, *sep2;
1649 if (bad_server(fctx, address)) {
1651 * We already know this server is bad.
1656 FCTXTRACE("add_bad");
1658 sa = isc_mem_get(fctx->res->mctx, sizeof(*sa));
1662 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
1664 if (reason == DNS_R_LAME) /* already logged */
1667 if (reason == DNS_R_UNEXPECTEDRCODE) {
1668 isc_buffer_init(&b, code, sizeof(code) - 1);
1669 dns_rcode_totext(fctx->rmessage->rcode, &b);
1670 code[isc_buffer_usedlength(&b)] = '\0';
1673 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
1674 isc_buffer_init(&b, code, sizeof(code) - 1);
1675 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
1676 code[isc_buffer_usedlength(&b)] = '\0';
1684 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
1685 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
1686 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
1687 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
1688 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
1689 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1690 "%s %s%s%sresolving '%s/%s/%s': %s",
1691 dns_result_totext(reason), sep1, code, sep2,
1692 namebuf, typebuf, classbuf, addrbuf);
1696 sort_adbfind(dns_adbfind_t *find) {
1697 dns_adbaddrinfo_t *best, *curr;
1698 dns_adbaddrinfolist_t sorted;
1701 * Lame N^2 bubble sort.
1704 ISC_LIST_INIT(sorted);
1705 while (!ISC_LIST_EMPTY(find->list)) {
1706 best = ISC_LIST_HEAD(find->list);
1707 curr = ISC_LIST_NEXT(best, publink);
1708 while (curr != NULL) {
1709 if (curr->srtt < best->srtt)
1711 curr = ISC_LIST_NEXT(curr, publink);
1713 ISC_LIST_UNLINK(find->list, best, publink);
1714 ISC_LIST_APPEND(sorted, best, publink);
1716 find->list = sorted;
1720 sort_finds(fetchctx_t *fctx) {
1721 dns_adbfind_t *best, *curr;
1722 dns_adbfindlist_t sorted;
1723 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
1726 * Lame N^2 bubble sort.
1729 ISC_LIST_INIT(sorted);
1730 while (!ISC_LIST_EMPTY(fctx->finds)) {
1731 best = ISC_LIST_HEAD(fctx->finds);
1732 bestaddrinfo = ISC_LIST_HEAD(best->list);
1733 INSIST(bestaddrinfo != NULL);
1734 curr = ISC_LIST_NEXT(best, publink);
1735 while (curr != NULL) {
1736 addrinfo = ISC_LIST_HEAD(curr->list);
1737 INSIST(addrinfo != NULL);
1738 if (addrinfo->srtt < bestaddrinfo->srtt) {
1740 bestaddrinfo = addrinfo;
1742 curr = ISC_LIST_NEXT(curr, publink);
1744 ISC_LIST_UNLINK(fctx->finds, best, publink);
1745 ISC_LIST_APPEND(sorted, best, publink);
1747 fctx->finds = sorted;
1749 ISC_LIST_INIT(sorted);
1750 while (!ISC_LIST_EMPTY(fctx->altfinds)) {
1751 best = ISC_LIST_HEAD(fctx->altfinds);
1752 bestaddrinfo = ISC_LIST_HEAD(best->list);
1753 INSIST(bestaddrinfo != NULL);
1754 curr = ISC_LIST_NEXT(best, publink);
1755 while (curr != NULL) {
1756 addrinfo = ISC_LIST_HEAD(curr->list);
1757 INSIST(addrinfo != NULL);
1758 if (addrinfo->srtt < bestaddrinfo->srtt) {
1760 bestaddrinfo = addrinfo;
1762 curr = ISC_LIST_NEXT(curr, publink);
1764 ISC_LIST_UNLINK(fctx->altfinds, best, publink);
1765 ISC_LIST_APPEND(sorted, best, publink);
1767 fctx->altfinds = sorted;
1771 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
1772 unsigned int options, unsigned int flags, isc_stdtime_t now,
1773 isc_boolean_t *pruned, isc_boolean_t *need_alternate)
1775 dns_adbaddrinfo_t *ai;
1776 dns_adbfind_t *find;
1777 dns_resolver_t *res;
1778 isc_boolean_t unshared;
1779 isc_result_t result;
1782 unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
1784 * If this name is a subdomain of the query domain, tell
1785 * the ADB to start looking using zone/hint data. This keeps us
1786 * from getting stuck if the nameserver is beneath the zone cut
1787 * and we don't know its address (e.g. because the A record has
1790 if (dns_name_issubdomain(name, &fctx->domain))
1791 options |= DNS_ADBFIND_STARTATZONE;
1792 options |= DNS_ADBFIND_GLUEOK;
1793 options |= DNS_ADBFIND_HINTOK;
1796 * See what we know about this address.
1799 result = dns_adb_createfind(fctx->adb,
1800 res->buckets[fctx->bucketnum].task,
1801 fctx_finddone, fctx, name,
1802 &fctx->domain, options, now, NULL,
1803 res->view->dstport, &find);
1804 if (result != ISC_R_SUCCESS) {
1805 if (result == DNS_R_ALIAS) {
1807 * XXXRTH Follow the CNAME/DNAME chain?
1809 dns_adb_destroyfind(&find);
1811 } else if (!ISC_LIST_EMPTY(find->list)) {
1813 * We have at least some of the addresses for the
1816 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
1818 if (flags != 0 || port != 0) {
1819 for (ai = ISC_LIST_HEAD(find->list);
1821 ai = ISC_LIST_NEXT(ai, publink)) {
1824 isc_sockaddr_setport(&ai->sockaddr,
1828 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
1829 ISC_LIST_APPEND(fctx->altfinds, find, publink);
1831 ISC_LIST_APPEND(fctx->finds, find, publink);
1834 * We don't know any of the addresses for this
1837 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
1839 * We're looking for them and will get an
1840 * event about it later.
1846 if (need_alternate != NULL &&
1847 !*need_alternate && unshared &&
1848 ((res->dispatchv4 == NULL &&
1849 find->result_v6 != DNS_R_NXDOMAIN) ||
1850 (res->dispatchv6 == NULL &&
1851 find->result_v4 != DNS_R_NXDOMAIN)))
1852 *need_alternate = ISC_TRUE;
1855 * If we know there are no addresses for
1856 * the family we are using then try to add
1857 * an alternative server.
1859 if (need_alternate != NULL && !*need_alternate &&
1860 ((res->dispatchv4 == NULL &&
1861 find->result_v6 == DNS_R_NXRRSET) ||
1862 (res->dispatchv6 == NULL &&
1863 find->result_v4 == DNS_R_NXRRSET)))
1864 *need_alternate = ISC_TRUE;
1866 * And ADB isn't going to send us any events
1867 * either. This find loses.
1869 if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0) {
1871 * The ADB pruned lame servers for
1872 * this name. Remember that in case
1873 * we get desperate later on.
1877 dns_adb_destroyfind(&find);
1883 fctx_getaddresses(fetchctx_t *fctx) {
1884 dns_rdata_t rdata = DNS_RDATA_INIT;
1885 isc_result_t result;
1886 dns_resolver_t *res;
1888 unsigned int stdoptions;
1890 dns_adbaddrinfo_t *ai;
1891 isc_boolean_t pruned, all_bad;
1893 isc_boolean_t need_alternate = ISC_FALSE;
1895 FCTXTRACE("getaddresses");
1898 * Don't pound on remote servers. (Failsafe!)
1901 if (fctx->restarts > 10) {
1902 FCTXTRACE("too many restarts");
1903 return (DNS_R_SERVFAIL);
1908 stdoptions = 0; /* Keep compiler happy. */
1914 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
1915 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
1918 * If this fctx has forwarders, use them; otherwise use any
1919 * selective forwarders specified in the view; otherwise use the
1920 * resolver's forwarders (if any).
1922 sa = ISC_LIST_HEAD(fctx->forwarders);
1924 dns_forwarders_t *forwarders = NULL;
1925 dns_name_t *name = &fctx->name;
1927 unsigned int labels;
1930 * DS records are found in the parent server.
1931 * Strip label to get the correct forwarder (if any).
1933 if (fctx->type == dns_rdatatype_ds &&
1934 dns_name_countlabels(name) > 1) {
1935 dns_name_init(&suffix, NULL);
1936 labels = dns_name_countlabels(name);
1937 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
1940 result = dns_fwdtable_find(fctx->res->view->fwdtable, name,
1942 if (result == ISC_R_SUCCESS) {
1943 sa = ISC_LIST_HEAD(forwarders->addrs);
1944 fctx->fwdpolicy = forwarders->fwdpolicy;
1948 while (sa != NULL) {
1950 result = dns_adb_findaddrinfo(fctx->adb,
1951 sa, &ai, 0); /* XXXMLG */
1952 if (result == ISC_R_SUCCESS) {
1953 dns_adbaddrinfo_t *cur;
1954 ai->flags |= FCTX_ADDRINFO_FORWARDER;
1955 cur = ISC_LIST_HEAD(fctx->forwaddrs);
1956 while (cur != NULL && cur->srtt < ai->srtt)
1957 cur = ISC_LIST_NEXT(cur, publink);
1959 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
1962 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
1964 sa = ISC_LIST_NEXT(sa, link);
1968 * If the forwarding policy is "only", we don't need the addresses
1969 * of the nameservers.
1971 if (fctx->fwdpolicy == dns_fwdpolicy_only)
1975 * Normal nameservers.
1978 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
1979 if (fctx->restarts == 1) {
1981 * To avoid sending out a flood of queries likely to
1982 * result in NXRRSET, we suppress fetches for address
1983 * families we don't have the first time through,
1984 * provided that we have addresses in some family we
1987 * We don't want to set this option all the time, since
1988 * if fctx->restarts > 1, we've clearly been having trouble
1989 * with the addresses we had, so getting more could help.
1991 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
1993 if (res->dispatchv4 != NULL)
1994 stdoptions |= DNS_ADBFIND_INET;
1995 if (res->dispatchv6 != NULL)
1996 stdoptions |= DNS_ADBFIND_INET6;
1997 isc_stdtime_get(&now);
2000 INSIST(ISC_LIST_EMPTY(fctx->finds));
2001 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
2003 for (result = dns_rdataset_first(&fctx->nameservers);
2004 result == ISC_R_SUCCESS;
2005 result = dns_rdataset_next(&fctx->nameservers))
2007 dns_rdataset_current(&fctx->nameservers, &rdata);
2009 * Extract the name from the NS record.
2011 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2012 if (result != ISC_R_SUCCESS)
2015 findname(fctx, &ns.name, 0, stdoptions, 0, now,
2016 &pruned, &need_alternate);
2017 dns_rdata_reset(&rdata);
2018 dns_rdata_freestruct(&ns);
2020 if (result != ISC_R_NOMORE)
2024 * Do we need to use 6 to 4?
2026 if (need_alternate) {
2029 family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
2030 for (a = ISC_LIST_HEAD(fctx->res->alternates);
2032 a = ISC_LIST_NEXT(a, link)) {
2033 if (!a->isaddress) {
2034 findname(fctx, &a->_u._n.name, a->_u._n.port,
2035 stdoptions, FCTX_ADDRINFO_FORWARDER,
2036 now, &pruned, NULL);
2039 if (isc_sockaddr_pf(&a->_u.addr) != family)
2042 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
2044 if (result == ISC_R_SUCCESS) {
2045 dns_adbaddrinfo_t *cur;
2046 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2047 cur = ISC_LIST_HEAD(fctx->altaddrs);
2048 while (cur != NULL && cur->srtt < ai->srtt)
2049 cur = ISC_LIST_NEXT(cur, publink);
2051 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
2054 ISC_LIST_APPEND(fctx->altaddrs, ai,
2062 * Mark all known bad servers.
2064 all_bad = mark_bad(fctx);
2071 * We've got no addresses.
2073 if (fctx->pending > 0) {
2075 * We're fetching the addresses, but don't have any
2076 * yet. Tell the caller to wait for an answer.
2078 result = DNS_R_WAIT;
2079 } else if (pruned) {
2081 * Some addresses were removed by lame pruning.
2082 * Turn pruning off and try again.
2084 FCTXTRACE("restarting with returnlame");
2085 INSIST((stdoptions & DNS_ADBFIND_RETURNLAME) == 0);
2086 stdoptions |= DNS_ADBFIND_RETURNLAME;
2088 fctx_cleanupaltfinds(fctx);
2089 fctx_cleanupfinds(fctx);
2093 * We've lost completely. We don't know any
2094 * addresses, and the ADB has told us it can't get
2097 FCTXTRACE("no addresses");
2098 result = ISC_R_FAILURE;
2102 * We've found some addresses. We might still be looking
2103 * for more addresses.
2106 result = ISC_R_SUCCESS;
2113 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
2116 char buf[ISC_NETADDR_FORMATSIZE];
2118 isc_boolean_t aborted = ISC_FALSE;
2119 isc_boolean_t bogus;
2120 dns_acl_t *blackhole;
2121 isc_netaddr_t ipaddr;
2122 dns_peer_t *peer = NULL;
2123 dns_resolver_t *res;
2124 const char *msg = NULL;
2126 sa = &addr->sockaddr;
2129 isc_netaddr_fromsockaddr(&ipaddr, sa);
2130 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
2131 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
2133 if (blackhole != NULL) {
2136 if (dns_acl_match(&ipaddr, NULL, blackhole,
2138 &match, NULL) == ISC_R_SUCCESS &&
2144 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
2149 addr->flags |= FCTX_ADDRINFO_MARK;
2150 msg = "ignoring blackholed / bogus server: ";
2151 } else if (isc_sockaddr_ismulticast(sa)) {
2152 addr->flags |= FCTX_ADDRINFO_MARK;
2153 msg = "ignoring multicast address: ";
2154 } else if (isc_sockaddr_isexperimental(sa)) {
2155 addr->flags |= FCTX_ADDRINFO_MARK;
2156 msg = "ignoring experimental address: ";
2157 } else if (sa->type.sa.sa_family != AF_INET6) {
2159 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
2160 addr->flags |= FCTX_ADDRINFO_MARK;
2161 msg = "ignoring IPv6 mapped IPV4 address: ";
2162 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
2163 addr->flags |= FCTX_ADDRINFO_MARK;
2164 msg = "ignoring IPv6 compatibility IPV4 address: ";
2168 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
2171 isc_netaddr_fromsockaddr(&na, sa);
2172 isc_netaddr_format(&na, buf, sizeof(buf));
2173 FCTXTRACE2(msg, buf);
2176 static inline dns_adbaddrinfo_t *
2177 fctx_nextaddress(fetchctx_t *fctx) {
2178 dns_adbfind_t *find, *start;
2179 dns_adbaddrinfo_t *addrinfo;
2180 dns_adbaddrinfo_t *faddrinfo;
2183 * Return the next untried address, if any.
2187 * Find the first unmarked forwarder (if any).
2189 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2191 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2192 if (!UNMARKED(addrinfo))
2194 possibly_mark(fctx, addrinfo);
2195 if (UNMARKED(addrinfo)) {
2196 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2203 * No forwarders. Move to the next find.
2206 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
2210 find = ISC_LIST_HEAD(fctx->finds);
2212 find = ISC_LIST_NEXT(find, publink);
2214 find = ISC_LIST_HEAD(fctx->finds);
2218 * Find the first unmarked addrinfo.
2224 for (addrinfo = ISC_LIST_HEAD(find->list);
2226 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2227 if (!UNMARKED(addrinfo))
2229 possibly_mark(fctx, addrinfo);
2230 if (UNMARKED(addrinfo)) {
2231 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2235 if (addrinfo != NULL)
2237 find = ISC_LIST_NEXT(find, publink);
2239 find = ISC_LIST_HEAD(fctx->finds);
2240 } while (find != start);
2244 if (addrinfo != NULL)
2248 * No nameservers left. Try alternates.
2251 fctx->attributes |= FCTX_ATTR_TRIEDALT;
2253 find = fctx->altfind;
2255 find = ISC_LIST_HEAD(fctx->altfinds);
2257 find = ISC_LIST_NEXT(find, publink);
2259 find = ISC_LIST_HEAD(fctx->altfinds);
2263 * Find the first unmarked addrinfo.
2269 for (addrinfo = ISC_LIST_HEAD(find->list);
2271 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2272 if (!UNMARKED(addrinfo))
2274 possibly_mark(fctx, addrinfo);
2275 if (UNMARKED(addrinfo)) {
2276 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2280 if (addrinfo != NULL)
2282 find = ISC_LIST_NEXT(find, publink);
2284 find = ISC_LIST_HEAD(fctx->altfinds);
2285 } while (find != start);
2288 faddrinfo = addrinfo;
2291 * See if we have a better alternate server by address.
2294 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2296 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2297 if (!UNMARKED(addrinfo))
2299 possibly_mark(fctx, addrinfo);
2300 if (UNMARKED(addrinfo) &&
2301 (faddrinfo == NULL ||
2302 addrinfo->srtt < faddrinfo->srtt)) {
2303 if (faddrinfo != NULL)
2304 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
2305 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2310 if (addrinfo == NULL) {
2311 addrinfo = faddrinfo;
2312 fctx->altfind = find;
2319 fctx_try(fetchctx_t *fctx) {
2320 isc_result_t result;
2321 dns_adbaddrinfo_t *addrinfo;
2325 REQUIRE(!ADDRWAIT(fctx));
2327 addrinfo = fctx_nextaddress(fctx);
2328 if (addrinfo == NULL) {
2330 * We have no more addresses. Start over.
2332 fctx_cancelqueries(fctx, ISC_TRUE);
2333 fctx_cleanupfinds(fctx);
2334 fctx_cleanupaltfinds(fctx);
2335 fctx_cleanupforwaddrs(fctx);
2336 fctx_cleanupaltaddrs(fctx);
2337 result = fctx_getaddresses(fctx);
2338 if (result == DNS_R_WAIT) {
2340 * Sleep waiting for addresses.
2342 FCTXTRACE("addrwait");
2343 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
2345 } else if (result != ISC_R_SUCCESS) {
2347 * Something bad happened.
2349 fctx_done(fctx, result);
2353 addrinfo = fctx_nextaddress(fctx);
2355 * While we may have addresses from the ADB, they
2356 * might be bad ones. In this case, return SERVFAIL.
2358 if (addrinfo == NULL) {
2359 fctx_done(fctx, DNS_R_SERVFAIL);
2364 result = fctx_query(fctx, addrinfo, fctx->options);
2365 if (result != ISC_R_SUCCESS)
2366 fctx_done(fctx, result);
2369 static isc_boolean_t
2370 fctx_destroy(fetchctx_t *fctx) {
2371 dns_resolver_t *res;
2372 unsigned int bucketnum;
2373 isc_sockaddr_t *sa, *next_sa;
2376 * Caller must be holding the bucket lock.
2379 REQUIRE(VALID_FCTX(fctx));
2380 REQUIRE(fctx->state == fetchstate_done ||
2381 fctx->state == fetchstate_init);
2382 REQUIRE(ISC_LIST_EMPTY(fctx->events));
2383 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
2384 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
2385 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
2386 REQUIRE(fctx->pending == 0);
2387 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
2388 REQUIRE(fctx->references == 0);
2390 FCTXTRACE("destroy");
2393 bucketnum = fctx->bucketnum;
2395 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
2400 for (sa = ISC_LIST_HEAD(fctx->bad);
2403 next_sa = ISC_LIST_NEXT(sa, link);
2404 ISC_LIST_UNLINK(fctx->bad, sa, link);
2405 isc_mem_put(res->mctx, sa, sizeof(*sa));
2408 isc_timer_detach(&fctx->timer);
2409 dns_message_destroy(&fctx->rmessage);
2410 dns_message_destroy(&fctx->qmessage);
2411 if (dns_name_countlabels(&fctx->domain) > 0)
2412 dns_name_free(&fctx->domain, res->mctx);
2413 if (dns_rdataset_isassociated(&fctx->nameservers))
2414 dns_rdataset_disassociate(&fctx->nameservers);
2415 dns_name_free(&fctx->name, res->mctx);
2416 dns_db_detach(&fctx->cache);
2417 dns_adb_detach(&fctx->adb);
2418 isc_mem_free(res->mctx, fctx->info);
2419 isc_mem_put(res->mctx, fctx, sizeof(*fctx));
2423 UNLOCK(&res->nlock);
2425 if (res->buckets[bucketnum].exiting &&
2426 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
2433 * Fetch event handlers.
2437 fctx_timeout(isc_task_t *task, isc_event_t *event) {
2438 fetchctx_t *fctx = event->ev_arg;
2440 REQUIRE(VALID_FCTX(fctx));
2444 FCTXTRACE("timeout");
2446 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
2447 fctx_done(fctx, ISC_R_TIMEDOUT);
2449 isc_result_t result;
2453 * We could cancel the running queries here, or we could let
2454 * them keep going. Right now we choose the latter...
2456 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2458 * Our timer has triggered. Reestablish the fctx lifetime
2461 result = fctx_starttimer(fctx);
2462 if (result != ISC_R_SUCCESS)
2463 fctx_done(fctx, result);
2471 isc_event_free(&event);
2475 fctx_shutdown(fetchctx_t *fctx) {
2476 isc_event_t *cevent;
2479 * Start the shutdown process for fctx, if it isn't already underway.
2482 FCTXTRACE("shutdown");
2485 * The caller must be holding the appropriate bucket lock.
2488 if (fctx->want_shutdown)
2491 fctx->want_shutdown = ISC_TRUE;
2494 * Unless we're still initializing (in which case the
2495 * control event is still outstanding), we need to post
2496 * the control event to tell the fetch we want it to
2499 if (fctx->state != fetchstate_init) {
2500 cevent = &fctx->control_event;
2501 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
2507 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
2508 fetchctx_t *fctx = event->ev_arg;
2509 isc_boolean_t bucket_empty = ISC_FALSE;
2510 dns_resolver_t *res;
2511 unsigned int bucketnum;
2512 dns_validator_t *validator;
2514 REQUIRE(VALID_FCTX(fctx));
2519 bucketnum = fctx->bucketnum;
2521 FCTXTRACE("doshutdown");
2524 * An fctx that is shutting down is no longer in ADDRWAIT mode.
2526 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2529 * Cancel all pending validators. Note that this must be done
2530 * without the bucket lock held, since that could cause deadlock.
2532 validator = ISC_LIST_HEAD(fctx->validators);
2533 while (validator != NULL) {
2534 dns_validator_cancel(validator);
2535 validator = ISC_LIST_NEXT(validator, link);
2538 if (fctx->nsfetch != NULL)
2539 dns_resolver_cancelfetch(fctx->nsfetch);
2542 * Shut down anything that is still running on behalf of this
2543 * fetch. To avoid deadlock with the ADB, we must do this
2544 * before we lock the bucket lock.
2546 fctx_stopeverything(fctx, ISC_FALSE);
2548 LOCK(&res->buckets[bucketnum].lock);
2550 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2552 INSIST(fctx->state == fetchstate_active ||
2553 fctx->state == fetchstate_done);
2554 INSIST(fctx->want_shutdown);
2556 if (fctx->state != fetchstate_done) {
2557 fctx->state = fetchstate_done;
2558 fctx_sendevents(fctx, ISC_R_CANCELED);
2561 if (fctx->references == 0 && fctx->pending == 0 &&
2562 ISC_LIST_EMPTY(fctx->validators))
2563 bucket_empty = fctx_destroy(fctx);
2565 UNLOCK(&res->buckets[bucketnum].lock);
2572 fctx_start(isc_task_t *task, isc_event_t *event) {
2573 fetchctx_t *fctx = event->ev_arg;
2574 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
2575 dns_resolver_t *res;
2576 unsigned int bucketnum;
2578 REQUIRE(VALID_FCTX(fctx));
2583 bucketnum = fctx->bucketnum;
2587 LOCK(&res->buckets[bucketnum].lock);
2589 INSIST(fctx->state == fetchstate_init);
2590 if (fctx->want_shutdown) {
2592 * We haven't started this fctx yet, and we've been requested
2595 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2596 fctx->state = fetchstate_done;
2597 fctx_sendevents(fctx, ISC_R_CANCELED);
2599 * Since we haven't started, we INSIST that we have no
2600 * pending ADB finds and no pending validations.
2602 INSIST(fctx->pending == 0);
2603 INSIST(ISC_LIST_EMPTY(fctx->validators));
2604 if (fctx->references == 0) {
2606 * It's now safe to destroy this fctx.
2608 bucket_empty = fctx_destroy(fctx);
2613 * Normal fctx startup.
2615 fctx->state = fetchstate_active;
2617 * Reset the control event for later use in shutting down
2620 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
2621 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
2625 UNLOCK(&res->buckets[bucketnum].lock);
2628 isc_result_t result;
2631 * All is well. Start working on the fetch.
2633 result = fctx_starttimer(fctx);
2634 if (result != ISC_R_SUCCESS)
2635 fctx_done(fctx, result);
2638 } else if (bucket_empty)
2643 * Fetch Creation, Joining, and Cancelation.
2646 static inline isc_result_t
2647 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_taskaction_t action,
2648 void *arg, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
2652 dns_fetchevent_t *event;
2657 * We store the task we're going to send this event to in the
2658 * sender field. We'll make the fetch the sender when we actually
2662 isc_task_attach(task, &clone);
2663 event = (dns_fetchevent_t *)
2664 isc_event_allocate(fctx->res->mctx, clone,
2665 DNS_EVENT_FETCHDONE,
2666 action, arg, sizeof(*event));
2667 if (event == NULL) {
2668 isc_task_detach(&clone);
2669 return (ISC_R_NOMEMORY);
2671 event->result = DNS_R_SERVFAIL;
2672 event->qtype = fctx->type;
2675 event->rdataset = rdataset;
2676 event->sigrdataset = sigrdataset;
2677 event->fetch = fetch;
2678 dns_fixedname_init(&event->foundname);
2681 * Make sure that we can store the sigrdataset in the
2682 * first event if it is needed by any of the events.
2684 if (event->sigrdataset != NULL)
2685 ISC_LIST_PREPEND(fctx->events, event, ev_link);
2687 ISC_LIST_APPEND(fctx->events, event, ev_link);
2690 fetch->magic = DNS_FETCH_MAGIC;
2691 fetch->private = fctx;
2693 return (ISC_R_SUCCESS);
2697 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
2698 dns_name_t *domain, dns_rdataset_t *nameservers,
2699 unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
2702 isc_result_t result;
2703 isc_result_t iresult;
2704 isc_interval_t interval;
2705 dns_fixedname_t fixed;
2706 unsigned int findoptions = 0;
2707 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
2708 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2712 * Caller must be holding the lock for bucket number 'bucketnum'.
2714 REQUIRE(fctxp != NULL && *fctxp == NULL);
2716 fctx = isc_mem_get(res->mctx, sizeof(*fctx));
2718 return (ISC_R_NOMEMORY);
2719 dns_name_format(name, buf, sizeof(buf));
2720 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2721 strcat(buf, "/"); /* checked */
2722 strcat(buf, typebuf); /* checked */
2723 fctx->info = isc_mem_strdup(res->mctx, buf);
2724 if (fctx->info == NULL) {
2725 result = ISC_R_NOMEMORY;
2728 FCTXTRACE("create");
2729 dns_name_init(&fctx->name, NULL);
2730 result = dns_name_dup(name, res->mctx, &fctx->name);
2731 if (result != ISC_R_SUCCESS)
2733 dns_name_init(&fctx->domain, NULL);
2734 dns_rdataset_init(&fctx->nameservers);
2737 fctx->options = options;
2739 * Note! We do not attach to the task. We are relying on the
2740 * resolver to ensure that this task doesn't go away while we are
2744 fctx->references = 0;
2745 fctx->bucketnum = bucketnum;
2746 fctx->state = fetchstate_init;
2747 fctx->want_shutdown = ISC_FALSE;
2748 fctx->cloned = ISC_FALSE;
2749 ISC_LIST_INIT(fctx->queries);
2750 ISC_LIST_INIT(fctx->finds);
2751 ISC_LIST_INIT(fctx->altfinds);
2752 ISC_LIST_INIT(fctx->forwaddrs);
2753 ISC_LIST_INIT(fctx->altaddrs);
2754 ISC_LIST_INIT(fctx->forwarders);
2755 fctx->fwdpolicy = dns_fwdpolicy_none;
2756 ISC_LIST_INIT(fctx->bad);
2757 ISC_LIST_INIT(fctx->validators);
2759 fctx->altfind = NULL;
2763 fctx->attributes = 0;
2765 dns_name_init(&fctx->nsname, NULL);
2766 fctx->nsfetch = NULL;
2767 dns_rdataset_init(&fctx->nsrrset);
2769 if (domain == NULL) {
2770 dns_forwarders_t *forwarders = NULL;
2771 unsigned int labels;
2774 * DS records are found in the parent server.
2775 * Strip label to get the correct forwarder (if any).
2777 if (fctx->type == dns_rdatatype_ds &&
2778 dns_name_countlabels(name) > 1) {
2779 dns_name_init(&suffix, NULL);
2780 labels = dns_name_countlabels(name);
2781 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2784 dns_fixedname_init(&fixed);
2785 domain = dns_fixedname_name(&fixed);
2786 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
2787 domain, &forwarders);
2788 if (result == ISC_R_SUCCESS)
2789 fctx->fwdpolicy = forwarders->fwdpolicy;
2791 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
2793 * The caller didn't supply a query domain and
2794 * nameservers, and we're not in forward-only mode,
2795 * so find the best nameservers to use.
2797 if (dns_rdatatype_atparent(type))
2798 findoptions |= DNS_DBFIND_NOEXACT;
2799 result = dns_view_findzonecut(res->view, name, domain,
2800 0, findoptions, ISC_TRUE,
2803 if (result != ISC_R_SUCCESS)
2805 result = dns_name_dup(domain, res->mctx, &fctx->domain);
2806 if (result != ISC_R_SUCCESS) {
2807 dns_rdataset_disassociate(&fctx->nameservers);
2812 * We're in forward-only mode. Set the query domain.
2814 result = dns_name_dup(domain, res->mctx, &fctx->domain);
2815 if (result != ISC_R_SUCCESS)
2819 result = dns_name_dup(domain, res->mctx, &fctx->domain);
2820 if (result != ISC_R_SUCCESS)
2822 dns_rdataset_clone(nameservers, &fctx->nameservers);
2825 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
2827 fctx->qmessage = NULL;
2828 result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTRENDER,
2831 if (result != ISC_R_SUCCESS)
2832 goto cleanup_domain;
2834 fctx->rmessage = NULL;
2835 result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTPARSE,
2838 if (result != ISC_R_SUCCESS)
2839 goto cleanup_qmessage;
2842 * Compute an expiration time for the entire fetch.
2844 isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
2845 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
2846 if (iresult != ISC_R_SUCCESS) {
2847 UNEXPECTED_ERROR(__FILE__, __LINE__,
2848 "isc_time_nowplusinterval: %s",
2849 isc_result_totext(iresult));
2850 result = ISC_R_UNEXPECTED;
2851 goto cleanup_rmessage;
2855 * Default retry interval initialization. We set the interval now
2856 * mostly so it won't be uninitialized. It will be set to the
2857 * correct value before a query is issued.
2859 isc_interval_set(&fctx->interval, 2, 0);
2862 * Create an inactive timer. It will be made active when the fetch
2863 * is actually started.
2866 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
2868 res->buckets[bucketnum].task, fctx_timeout,
2869 fctx, &fctx->timer);
2870 if (iresult != ISC_R_SUCCESS) {
2871 UNEXPECTED_ERROR(__FILE__, __LINE__,
2872 "isc_timer_create: %s",
2873 isc_result_totext(iresult));
2874 result = ISC_R_UNEXPECTED;
2875 goto cleanup_rmessage;
2879 * Attach to the view's cache and adb.
2882 dns_db_attach(res->view->cachedb, &fctx->cache);
2884 dns_adb_attach(res->view->adb, &fctx->adb);
2886 ISC_LIST_INIT(fctx->events);
2887 ISC_LINK_INIT(fctx, link);
2888 fctx->magic = FCTX_MAGIC;
2890 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
2894 UNLOCK(&res->nlock);
2898 return (ISC_R_SUCCESS);
2901 dns_message_destroy(&fctx->rmessage);
2904 dns_message_destroy(&fctx->qmessage);
2907 if (dns_name_countlabels(&fctx->domain) > 0)
2908 dns_name_free(&fctx->domain, res->mctx);
2909 if (dns_rdataset_isassociated(&fctx->nameservers))
2910 dns_rdataset_disassociate(&fctx->nameservers);
2913 dns_name_free(&fctx->name, res->mctx);
2916 isc_mem_free(res->mctx, fctx->info);
2919 isc_mem_put(res->mctx, fctx, sizeof(*fctx));
2927 static inline isc_boolean_t
2928 is_lame(fetchctx_t *fctx) {
2929 dns_message_t *message = fctx->rmessage;
2931 dns_rdataset_t *rdataset;
2932 isc_result_t result;
2934 if (message->rcode != dns_rcode_noerror &&
2935 message->rcode != dns_rcode_nxdomain)
2938 if (message->counts[DNS_SECTION_ANSWER] != 0)
2941 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
2944 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2945 while (result == ISC_R_SUCCESS) {
2947 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2948 for (rdataset = ISC_LIST_HEAD(name->list);
2950 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2951 dns_namereln_t namereln;
2953 unsigned int labels;
2954 if (rdataset->type != dns_rdatatype_ns)
2956 namereln = dns_name_fullcompare(name, &fctx->domain,
2958 if (namereln == dns_namereln_equal &&
2959 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
2961 if (namereln == dns_namereln_subdomain)
2965 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
2972 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
2973 char namebuf[DNS_NAME_FORMATSIZE];
2974 char domainbuf[DNS_NAME_FORMATSIZE];
2975 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2977 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
2978 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
2979 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
2980 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
2981 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
2982 "lame server resolving '%s' (in '%s'?): %s",
2983 namebuf, domainbuf, addrbuf);
2986 static inline isc_result_t
2987 same_question(fetchctx_t *fctx) {
2988 isc_result_t result;
2989 dns_message_t *message = fctx->rmessage;
2991 dns_rdataset_t *rdataset;
2994 * Caller must be holding the fctx lock.
2998 * XXXRTH Currently we support only one question.
3000 if (message->counts[DNS_SECTION_QUESTION] != 1)
3001 return (DNS_R_FORMERR);
3003 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3004 if (result != ISC_R_SUCCESS)
3007 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
3008 rdataset = ISC_LIST_HEAD(name->list);
3009 INSIST(rdataset != NULL);
3010 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
3011 if (fctx->type != rdataset->type ||
3012 fctx->res->rdclass != rdataset->rdclass ||
3013 !dns_name_equal(&fctx->name, name))
3014 return (DNS_R_FORMERR);
3016 return (ISC_R_SUCCESS);
3020 clone_results(fetchctx_t *fctx) {
3021 dns_fetchevent_t *event, *hevent;
3022 isc_result_t result;
3023 dns_name_t *name, *hname;
3025 FCTXTRACE("clone_results");
3028 * Set up any other events to have the same data as the first
3031 * Caller must be holding the appropriate lock.
3034 fctx->cloned = ISC_TRUE;
3035 hevent = ISC_LIST_HEAD(fctx->events);
3038 hname = dns_fixedname_name(&hevent->foundname);
3039 for (event = ISC_LIST_NEXT(hevent, ev_link);
3041 event = ISC_LIST_NEXT(event, ev_link)) {
3042 name = dns_fixedname_name(&event->foundname);
3043 result = dns_name_copy(hname, name, NULL);
3044 if (result != ISC_R_SUCCESS)
3045 event->result = result;
3047 event->result = hevent->result;
3048 dns_db_attach(hevent->db, &event->db);
3049 dns_db_attachnode(hevent->db, hevent->node, &event->node);
3050 INSIST(hevent->rdataset != NULL);
3051 INSIST(event->rdataset != NULL);
3052 if (dns_rdataset_isassociated(hevent->rdataset))
3053 dns_rdataset_clone(hevent->rdataset, event->rdataset);
3054 INSIST(! (hevent->sigrdataset == NULL &&
3055 event->sigrdataset != NULL));
3056 if (hevent->sigrdataset != NULL &&
3057 dns_rdataset_isassociated(hevent->sigrdataset) &&
3058 event->sigrdataset != NULL)
3059 dns_rdataset_clone(hevent->sigrdataset,
3060 event->sigrdataset);
3064 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3065 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3066 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3067 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3068 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3069 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3070 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3074 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3075 * no references and is no longer waiting for any events). If this
3076 * was the last fctx in the resolver, destroy the resolver.
3079 * '*fctx' is shutting down.
3082 maybe_destroy(fetchctx_t *fctx) {
3083 unsigned int bucketnum;
3084 isc_boolean_t bucket_empty = ISC_FALSE;
3085 dns_resolver_t *res = fctx->res;
3087 REQUIRE(SHUTTINGDOWN(fctx));
3089 if (fctx->pending != 0 || !ISC_LIST_EMPTY(fctx->validators))
3092 bucketnum = fctx->bucketnum;
3093 LOCK(&res->buckets[bucketnum].lock);
3094 if (fctx->references == 0)
3095 bucket_empty = fctx_destroy(fctx);
3096 UNLOCK(&res->buckets[bucketnum].lock);
3103 * The validator has finished.
3106 validated(isc_task_t *task, isc_event_t *event) {
3107 isc_result_t result = ISC_R_SUCCESS;
3108 isc_result_t eresult = ISC_R_SUCCESS;
3111 dns_validatorevent_t *vevent;
3112 dns_fetchevent_t *hevent;
3113 dns_rdataset_t *ardataset = NULL;
3114 dns_rdataset_t *asigrdataset = NULL;
3115 dns_dbnode_t *node = NULL;
3116 isc_boolean_t negative;
3117 isc_boolean_t chaining;
3118 isc_boolean_t sentresponse;
3120 dns_dbnode_t *nsnode = NULL;
3122 dns_rdataset_t *rdataset;
3123 dns_rdataset_t *sigrdataset;
3124 dns_valarg_t *valarg;
3125 dns_adbaddrinfo_t *addrinfo;
3127 UNUSED(task); /* for now */
3129 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
3130 valarg = event->ev_arg;
3131 fctx = valarg->fctx;
3132 addrinfo = valarg->addrinfo;
3133 REQUIRE(VALID_FCTX(fctx));
3134 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
3136 vevent = (dns_validatorevent_t *)event;
3138 FCTXTRACE("received validation completion event");
3140 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
3143 * Destroy the validator early so that we can
3144 * destroy the fctx if necessary.
3146 dns_validator_destroy(&vevent->validator);
3147 isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg));
3149 negative = ISC_TF(vevent->rdataset == NULL);
3151 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
3154 * If shutting down, ignore the results. Check to see if we're
3155 * done waiting for validator completions and ADB pending events; if
3156 * so, destroy the fctx.
3158 if (SHUTTINGDOWN(fctx) && !sentresponse) {
3159 maybe_destroy(fctx);
3164 * If chaining, we need to make sure that the right result code is
3165 * returned, and that the rdatasets are bound.
3167 if (vevent->result == ISC_R_SUCCESS &&
3169 vevent->rdataset != NULL &&
3170 CHAINING(vevent->rdataset))
3172 if (vevent->rdataset->type == dns_rdatatype_cname)
3173 eresult = DNS_R_CNAME;
3175 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
3176 eresult = DNS_R_DNAME;
3178 chaining = ISC_TRUE;
3180 chaining = ISC_FALSE;
3183 * Either we're not shutting down, or we are shutting down but want
3184 * to cache the result anyway (if this was a validation started by
3185 * a query with cd set)
3188 hevent = ISC_LIST_HEAD(fctx->events);
3189 if (hevent != NULL) {
3190 if (!negative && !chaining &&
3191 (fctx->type == dns_rdatatype_any ||
3192 fctx->type == dns_rdatatype_rrsig ||
3193 fctx->type == dns_rdatatype_sig)) {
3195 * Don't bind rdatasets; the caller
3196 * will iterate the node.
3199 ardataset = hevent->rdataset;
3200 asigrdataset = hevent->sigrdataset;
3204 if (vevent->result != ISC_R_SUCCESS) {
3205 FCTXTRACE("validation failed");
3206 result = ISC_R_NOTFOUND;
3207 if (vevent->rdataset != NULL)
3208 result = dns_db_findnode(fctx->cache, vevent->name,
3210 if (result == ISC_R_SUCCESS)
3211 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
3213 if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
3214 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
3215 dns_rdatatype_rrsig,
3217 if (result == ISC_R_SUCCESS)
3218 dns_db_detachnode(fctx->cache, &node);
3219 result = vevent->result;
3220 add_bad(fctx, &addrinfo->sockaddr, result);
3221 isc_event_free(&event);
3223 fctx_done(fctx, result);
3229 isc_stdtime_get(&now);
3232 dns_rdatatype_t covers;
3233 FCTXTRACE("nonexistence validation OK");
3235 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
3236 covers = dns_rdatatype_any;
3238 covers = fctx->type;
3240 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
3242 if (result != ISC_R_SUCCESS)
3243 goto noanswer_response;
3246 * If we are asking for a SOA record set the cache time
3247 * to zero to facilitate locating the containing zone of
3250 ttl = fctx->res->view->maxncachettl;
3251 if (fctx->type == dns_rdatatype_soa &&
3252 covers == dns_rdatatype_any)
3255 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
3257 ardataset, &eresult);
3258 if (result != ISC_R_SUCCESS)
3259 goto noanswer_response;
3260 goto answer_response;
3263 FCTXTRACE("validation OK");
3265 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
3267 result = dns_rdataset_addnoqname(vevent->rdataset,
3268 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
3269 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3270 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
3274 * The data was already cached as pending data.
3275 * Re-cache it as secure and bind the cached
3276 * rdatasets to the first event on the fetch
3279 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
3280 if (result != ISC_R_SUCCESS)
3281 goto noanswer_response;
3283 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
3284 vevent->rdataset, 0, ardataset);
3285 if (result != ISC_R_SUCCESS &&
3286 result != DNS_R_UNCHANGED)
3287 goto noanswer_response;
3288 if (vevent->sigrdataset != NULL) {
3289 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
3290 vevent->sigrdataset, 0,
3292 if (result != ISC_R_SUCCESS &&
3293 result != DNS_R_UNCHANGED)
3294 goto noanswer_response;
3299 * If we only deferred the destroy because we wanted to cache
3300 * the data, destroy now.
3302 if (SHUTTINGDOWN(fctx))
3303 maybe_destroy(fctx);
3308 if (!ISC_LIST_EMPTY(fctx->validators)) {
3310 INSIST(fctx->type == dns_rdatatype_any ||
3311 fctx->type == dns_rdatatype_rrsig ||
3312 fctx->type == dns_rdatatype_sig);
3314 * Don't send a response yet - we have
3315 * more rdatasets that still need to
3323 * Cache any NS/NSEC records that happened to be validated.
3325 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
3326 while (result == ISC_R_SUCCESS) {
3328 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
3330 for (rdataset = ISC_LIST_HEAD(name->list);
3332 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3333 if ((rdataset->type != dns_rdatatype_ns &&
3334 rdataset->type != dns_rdatatype_nsec) ||
3335 rdataset->trust != dns_trust_secure)
3337 for (sigrdataset = ISC_LIST_HEAD(name->list);
3338 sigrdataset != NULL;
3339 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
3340 if (sigrdataset->type != dns_rdatatype_rrsig ||
3341 sigrdataset->covers != rdataset->type)
3345 if (sigrdataset == NULL ||
3346 sigrdataset->trust != dns_trust_secure)
3348 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
3350 if (result != ISC_R_SUCCESS)
3353 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
3354 now, rdataset, 0, NULL);
3355 if (result == ISC_R_SUCCESS)
3356 result = dns_db_addrdataset(fctx->cache, nsnode,
3360 dns_db_detachnode(fctx->cache, &nsnode);
3362 result = dns_message_nextname(fctx->rmessage,
3363 DNS_SECTION_AUTHORITY);
3366 result = ISC_R_SUCCESS;
3369 * Respond with an answer, positive or negative,
3370 * as opposed to an error. 'node' must be non-NULL.
3373 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3375 if (hevent != NULL) {
3376 hevent->result = eresult;
3377 RUNTIME_CHECK(dns_name_copy(vevent->name,
3378 dns_fixedname_name(&hevent->foundname), NULL)
3380 dns_db_attach(fctx->cache, &hevent->db);
3381 hevent->node = node;
3383 clone_results(fctx);
3388 dns_db_detachnode(fctx->cache, &node);
3390 fctx_done(fctx, result);
3393 isc_event_free(&event);
3396 static inline isc_result_t
3397 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
3398 isc_stdtime_t now) {
3399 dns_rdataset_t *rdataset, *sigrdataset;
3400 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
3401 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
3402 dns_dbnode_t *node, **anodep;
3405 dns_resolver_t *res;
3406 isc_boolean_t need_validation, secure_domain, have_answer;
3407 isc_result_t result, eresult;
3408 dns_fetchevent_t *event;
3409 unsigned int options;
3412 unsigned int valoptions = 0;
3415 * The appropriate bucket lock must be held.
3419 need_validation = ISC_FALSE;
3420 secure_domain = ISC_FALSE;
3421 have_answer = ISC_FALSE;
3422 eresult = ISC_R_SUCCESS;
3423 task = res->buckets[fctx->bucketnum].task;
3426 * Is DNSSEC validation required for this name?
3428 result = dns_keytable_issecuredomain(res->view->secroots, name,
3430 if (result != ISC_R_SUCCESS)
3433 if (!secure_domain && res->view->dlv != NULL) {
3434 valoptions = DNS_VALIDATOR_DLV;
3435 secure_domain = ISC_TRUE;
3438 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
3439 need_validation = ISC_FALSE;
3441 need_validation = secure_domain;
3447 asigrdataset = NULL;
3449 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
3451 have_answer = ISC_TRUE;
3452 event = ISC_LIST_HEAD(fctx->events);
3453 if (event != NULL) {
3455 aname = dns_fixedname_name(&event->foundname);
3456 result = dns_name_copy(name, aname, NULL);
3457 if (result != ISC_R_SUCCESS)
3459 anodep = &event->node;
3461 * If this is an ANY, SIG or RRSIG query, we're not
3462 * going to return any rdatasets, unless we encountered
3463 * a CNAME or DNAME as "the answer". In this case,
3464 * we're going to return DNS_R_CNAME or DNS_R_DNAME
3465 * and we must set up the rdatasets.
3467 if ((fctx->type != dns_rdatatype_any &&
3468 fctx->type != dns_rdatatype_rrsig &&
3469 fctx->type != dns_rdatatype_sig) ||
3470 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
3471 ardataset = event->rdataset;
3472 asigrdataset = event->sigrdataset;
3478 * Find or create the cache node.
3481 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
3482 if (result != ISC_R_SUCCESS)
3486 * Cache or validate each cacheable rdataset.
3488 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
3489 for (rdataset = ISC_LIST_HEAD(name->list);
3491 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3492 if (!CACHE(rdataset))
3494 if (CHECKNAMES(rdataset)) {
3495 char namebuf[DNS_NAME_FORMATSIZE];
3496 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3497 char classbuf[DNS_RDATATYPE_FORMATSIZE];
3499 dns_name_format(name, namebuf, sizeof(namebuf));
3500 dns_rdatatype_format(rdataset->type, typebuf,
3502 dns_rdataclass_format(rdataset->rdclass, classbuf,
3504 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3505 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
3506 "check-names %s %s/%s/%s",
3507 fail ? "failure" : "warning",
3508 namebuf, typebuf, classbuf);
3510 if (ANSWER(rdataset))
3511 return (DNS_R_BADNAME);
3517 * Enforce the configure maximum cache TTL.
3519 if (rdataset->ttl > res->view->maxcachettl)
3520 rdataset->ttl = res->view->maxcachettl;
3523 * If this rrset is in a secure domain, do DNSSEC validation
3524 * for it, unless it is glue.
3526 if (secure_domain && rdataset->trust != dns_trust_glue) {
3528 * RRSIGs are validated as part of validating the
3531 if (rdataset->type == dns_rdatatype_rrsig)
3534 * Find the SIG for this rdataset, if we have it.
3536 for (sigrdataset = ISC_LIST_HEAD(name->list);
3537 sigrdataset != NULL;
3538 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
3539 if (sigrdataset->type == dns_rdatatype_rrsig &&
3540 sigrdataset->covers == rdataset->type)
3543 if (sigrdataset == NULL) {
3544 if (!ANSWER(rdataset) && need_validation) {
3546 * Ignore non-answer rdatasets that
3547 * are missing signatures.
3554 * Normalize the rdataset and sigrdataset TTLs.
3556 if (sigrdataset != NULL) {
3557 rdataset->ttl = ISC_MIN(rdataset->ttl,
3559 sigrdataset->ttl = rdataset->ttl;
3563 * Cache this rdataset/sigrdataset pair as
3566 rdataset->trust = dns_trust_pending;
3567 if (sigrdataset != NULL)
3568 sigrdataset->trust = dns_trust_pending;
3569 if (!need_validation)
3570 addedrdataset = ardataset;
3572 addedrdataset = NULL;
3573 result = dns_db_addrdataset(fctx->cache, node, NULL,
3576 if (result == DNS_R_UNCHANGED)
3577 result = ISC_R_SUCCESS;
3578 if (result != ISC_R_SUCCESS)
3580 if (sigrdataset != NULL) {
3581 if (!need_validation)
3582 addedrdataset = asigrdataset;
3584 addedrdataset = NULL;
3585 result = dns_db_addrdataset(fctx->cache,
3589 if (result == DNS_R_UNCHANGED)
3590 result = ISC_R_SUCCESS;
3591 if (result != ISC_R_SUCCESS)
3593 } else if (!ANSWER(rdataset))
3596 if (ANSWER(rdataset) && need_validation) {
3597 if (fctx->type != dns_rdatatype_any &&
3598 fctx->type != dns_rdatatype_rrsig &&
3599 fctx->type != dns_rdatatype_sig) {
3601 * This is The Answer. We will
3602 * validate it, but first we cache
3603 * the rest of the response - it may
3604 * contain useful keys.
3606 INSIST(valrdataset == NULL &&
3607 valsigrdataset == NULL);
3608 valrdataset = rdataset;
3609 valsigrdataset = sigrdataset;
3612 * This is one of (potentially)
3613 * multiple answers to an ANY
3614 * or SIG query. To keep things
3615 * simple, we just start the
3616 * validator right away rather
3617 * than caching first and
3618 * having to remember which
3619 * rdatasets needed validation.
3621 result = valcreate(fctx, addrinfo,
3622 name, rdataset->type,
3627 } else if (CHAINING(rdataset)) {
3628 if (rdataset->type == dns_rdatatype_cname)
3629 eresult = DNS_R_CNAME;
3631 INSIST(rdataset->type ==
3632 dns_rdatatype_dname);
3633 eresult = DNS_R_DNAME;
3636 } else if (!EXTERNAL(rdataset)) {
3638 * It's OK to cache this rdataset now.
3640 if (ANSWER(rdataset))
3641 addedrdataset = ardataset;
3642 else if (ANSWERSIG(rdataset))
3643 addedrdataset = asigrdataset;
3645 addedrdataset = NULL;
3646 if (CHAINING(rdataset)) {
3647 if (rdataset->type == dns_rdatatype_cname)
3648 eresult = DNS_R_CNAME;
3650 INSIST(rdataset->type ==
3651 dns_rdatatype_dname);
3652 eresult = DNS_R_DNAME;
3655 if (rdataset->trust == dns_trust_glue &&
3656 (rdataset->type == dns_rdatatype_ns ||
3657 (rdataset->type == dns_rdatatype_rrsig &&
3658 rdataset->covers == dns_rdatatype_ns))) {
3660 * If the trust level is 'dns_trust_glue'
3661 * then we are adding data from a referral
3662 * we got while executing the search algorithm.
3663 * New referral data always takes precedence
3664 * over the existing cache contents.
3666 options = DNS_DBADD_FORCE;
3670 * Now we can add the rdataset.
3672 result = dns_db_addrdataset(fctx->cache,
3677 if (result == DNS_R_UNCHANGED) {
3678 if (ANSWER(rdataset) &&
3679 ardataset != NULL &&
3680 ardataset->type == 0) {
3682 * The answer in the cache is better
3683 * than the answer we found, and is
3684 * a negative cache entry, so we
3685 * must set eresult appropriately.
3687 if (NXDOMAIN(ardataset))
3689 DNS_R_NCACHENXDOMAIN;
3692 DNS_R_NCACHENXRRSET;
3694 result = ISC_R_SUCCESS;
3695 } else if (result != ISC_R_SUCCESS)
3700 if (valrdataset != NULL)
3701 result = valcreate(fctx, addrinfo, name, fctx->type,
3702 valrdataset, valsigrdataset, valoptions,
3705 if (result == ISC_R_SUCCESS && have_answer) {
3706 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3707 if (event != NULL) {
3708 event->result = eresult;
3709 dns_db_attach(fctx->cache, adbp);
3712 clone_results(fctx);
3717 dns_db_detachnode(fctx->cache, &node);
3722 static inline isc_result_t
3723 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
3725 isc_result_t result;
3726 dns_section_t section;
3729 FCTXTRACE("cache_message");
3731 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
3733 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3735 for (section = DNS_SECTION_ANSWER;
3736 section <= DNS_SECTION_ADDITIONAL;
3738 result = dns_message_firstname(fctx->rmessage, section);
3739 while (result == ISC_R_SUCCESS) {
3741 dns_message_currentname(fctx->rmessage, section,
3743 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
3744 result = cache_name(fctx, name, addrinfo, now);
3745 if (result != ISC_R_SUCCESS)
3748 result = dns_message_nextname(fctx->rmessage, section);
3750 if (result != ISC_R_NOMORE)
3753 if (result == ISC_R_NOMORE)
3754 result = ISC_R_SUCCESS;
3756 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3762 * Do what dns_ncache_add() does, and then compute an appropriate eresult.
3765 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
3766 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
3767 dns_rdataset_t *ardataset,
3768 isc_result_t *eresultp)
3770 isc_result_t result;
3771 dns_rdataset_t rdataset;
3773 if (ardataset == NULL) {
3774 dns_rdataset_init(&rdataset);
3775 ardataset = &rdataset;
3777 result = dns_ncache_add(message, cache, node, covers, now,
3779 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
3781 * If the cache now contains a negative entry and we
3782 * care about whether it is DNS_R_NCACHENXDOMAIN or
3783 * DNS_R_NCACHENXRRSET then extract it.
3785 if (ardataset->type == 0) {
3787 * The cache data is a negative cache entry.
3789 if (NXDOMAIN(ardataset))
3790 *eresultp = DNS_R_NCACHENXDOMAIN;
3792 *eresultp = DNS_R_NCACHENXRRSET;
3795 * Either we don't care about the nature of the
3796 * cache rdataset (because no fetch is interested
3797 * in the outcome), or the cache rdataset is not
3798 * a negative cache entry. Whichever case it is,
3799 * we can return success.
3801 * XXXRTH There's a CNAME/DNAME problem here.
3803 *eresultp = ISC_R_SUCCESS;
3805 result = ISC_R_SUCCESS;
3807 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
3808 dns_rdataset_disassociate(ardataset);
3813 static inline isc_result_t
3814 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
3815 dns_rdatatype_t covers, isc_stdtime_t now)
3817 isc_result_t result, eresult;
3819 dns_resolver_t *res;
3821 dns_dbnode_t *node, **anodep;
3822 dns_rdataset_t *ardataset;
3823 isc_boolean_t need_validation, secure_domain;
3825 dns_fetchevent_t *event;
3827 unsigned int valoptions = 0;
3829 FCTXTRACE("ncache_message");
3831 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
3834 need_validation = ISC_FALSE;
3835 secure_domain = ISC_FALSE;
3836 eresult = ISC_R_SUCCESS;
3841 * XXXMPA remove when we follow cnames and adjust the setting
3842 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
3844 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
3847 * Is DNSSEC validation required for this name?
3849 result = dns_keytable_issecuredomain(res->view->secroots, name,
3851 if (result != ISC_R_SUCCESS)
3854 if (!secure_domain && res->view->dlv != NULL) {
3855 valoptions = DNS_VALIDATOR_DLV;
3856 secure_domain = ISC_TRUE;
3859 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
3860 need_validation = ISC_FALSE;
3862 need_validation = secure_domain;
3864 if (secure_domain) {
3866 * Mark all rdatasets as pending.
3868 dns_rdataset_t *trdataset;
3871 result = dns_message_firstname(fctx->rmessage,
3872 DNS_SECTION_AUTHORITY);
3873 while (result == ISC_R_SUCCESS) {
3875 dns_message_currentname(fctx->rmessage,
3876 DNS_SECTION_AUTHORITY,
3878 for (trdataset = ISC_LIST_HEAD(tname->list);
3880 trdataset = ISC_LIST_NEXT(trdataset, link))
3881 trdataset->trust = dns_trust_pending;
3882 result = dns_message_nextname(fctx->rmessage,
3883 DNS_SECTION_AUTHORITY);
3885 if (result != ISC_R_NOMORE)
3890 if (need_validation) {
3892 * Do negative response validation.
3894 result = valcreate(fctx, addrinfo, name, fctx->type,
3895 NULL, NULL, valoptions,
3896 res->buckets[fctx->bucketnum].task);
3898 * If validation is necessary, return now. Otherwise continue
3899 * to process the message, letting the validation complete
3900 * in its own good time.
3905 LOCK(&res->buckets[fctx->bucketnum].lock);
3911 if (!HAVE_ANSWER(fctx)) {
3912 event = ISC_LIST_HEAD(fctx->events);
3913 if (event != NULL) {
3915 aname = dns_fixedname_name(&event->foundname);
3916 result = dns_name_copy(name, aname, NULL);
3917 if (result != ISC_R_SUCCESS)
3919 anodep = &event->node;
3920 ardataset = event->rdataset;
3925 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
3926 if (result != ISC_R_SUCCESS)
3930 * If we are asking for a SOA record set the cache time
3931 * to zero to facilitate locating the containing zone of
3934 ttl = fctx->res->view->maxncachettl;
3935 if (fctx->type == dns_rdatatype_soa &&
3936 covers == dns_rdatatype_any)
3939 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
3940 covers, now, ttl, ardataset, &eresult);
3941 if (result != ISC_R_SUCCESS)
3944 if (!HAVE_ANSWER(fctx)) {
3945 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3946 if (event != NULL) {
3947 event->result = eresult;
3948 dns_db_attach(fctx->cache, adbp);
3951 clone_results(fctx);
3956 UNLOCK(&res->buckets[fctx->bucketnum].lock);
3959 dns_db_detachnode(fctx->cache, &node);
3965 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
3966 isc_boolean_t external, isc_boolean_t gluing)
3968 name->attributes |= DNS_NAMEATTR_CACHE;
3970 rdataset->trust = dns_trust_glue;
3972 * Glue with 0 TTL causes problems. We force the TTL to
3973 * 1 second to prevent this.
3975 if (rdataset->ttl == 0)
3978 rdataset->trust = dns_trust_additional;
3980 * Avoid infinite loops by only marking new rdatasets.
3982 if (!CACHE(rdataset)) {
3983 name->attributes |= DNS_NAMEATTR_CHASE;
3984 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
3986 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
3988 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
3992 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
3993 fetchctx_t *fctx = arg;
3994 isc_result_t result;
3996 dns_rdataset_t *rdataset;
3997 isc_boolean_t external;
3998 dns_rdatatype_t rtype;
3999 isc_boolean_t gluing;
4001 REQUIRE(VALID_FCTX(fctx));
4009 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
4010 addname, dns_rdatatype_any, 0, &name,
4012 if (result == ISC_R_SUCCESS) {
4013 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4014 if (type == dns_rdatatype_a) {
4015 for (rdataset = ISC_LIST_HEAD(name->list);
4017 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4018 if (rdataset->type == dns_rdatatype_rrsig)
4019 rtype = rdataset->covers;
4021 rtype = rdataset->type;
4022 if (rtype == dns_rdatatype_a ||
4023 rtype == dns_rdatatype_aaaa)
4024 mark_related(name, rdataset, external,
4028 result = dns_message_findtype(name, type, 0,
4030 if (result == ISC_R_SUCCESS) {
4031 mark_related(name, rdataset, external, gluing);
4033 * Do we have its SIG too?
4036 result = dns_message_findtype(name,
4037 dns_rdatatype_rrsig,
4039 if (result == ISC_R_SUCCESS)
4040 mark_related(name, rdataset, external,
4046 return (ISC_R_SUCCESS);
4050 chase_additional(fetchctx_t *fctx) {
4051 isc_boolean_t rescan;
4052 dns_section_t section = DNS_SECTION_ADDITIONAL;
4053 isc_result_t result;
4058 for (result = dns_message_firstname(fctx->rmessage, section);
4059 result == ISC_R_SUCCESS;
4060 result = dns_message_nextname(fctx->rmessage, section)) {
4061 dns_name_t *name = NULL;
4062 dns_rdataset_t *rdataset;
4063 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
4065 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
4067 name->attributes &= ~DNS_NAMEATTR_CHASE;
4068 for (rdataset = ISC_LIST_HEAD(name->list);
4070 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4071 if (CHASE(rdataset)) {
4072 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
4073 (void)dns_rdataset_additionaldata(rdataset,
4084 static inline isc_result_t
4085 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
4086 isc_result_t result;
4087 dns_rdata_t rdata = DNS_RDATA_INIT;
4088 dns_rdata_cname_t cname;
4090 result = dns_rdataset_first(rdataset);
4091 if (result != ISC_R_SUCCESS)
4093 dns_rdataset_current(rdataset, &rdata);
4094 result = dns_rdata_tostruct(&rdata, &cname, NULL);
4095 if (result != ISC_R_SUCCESS)
4097 dns_name_init(tname, NULL);
4098 dns_name_clone(&cname.cname, tname);
4099 dns_rdata_freestruct(&cname);
4101 return (ISC_R_SUCCESS);
4104 static inline isc_result_t
4105 dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
4106 dns_fixedname_t *fixeddname)
4108 isc_result_t result;
4109 dns_rdata_t rdata = DNS_RDATA_INIT;
4110 unsigned int nlabels;
4112 dns_namereln_t namereln;
4113 dns_rdata_dname_t dname;
4114 dns_fixedname_t prefix;
4117 * Get the target name of the DNAME.
4120 result = dns_rdataset_first(rdataset);
4121 if (result != ISC_R_SUCCESS)
4123 dns_rdataset_current(rdataset, &rdata);
4124 result = dns_rdata_tostruct(&rdata, &dname, NULL);
4125 if (result != ISC_R_SUCCESS)
4129 * Get the prefix of qname.
4131 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
4132 if (namereln != dns_namereln_subdomain) {
4133 dns_rdata_freestruct(&dname);
4134 return (DNS_R_FORMERR);
4136 dns_fixedname_init(&prefix);
4137 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
4138 dns_fixedname_init(fixeddname);
4139 result = dns_name_concatenate(dns_fixedname_name(&prefix),
4141 dns_fixedname_name(fixeddname), NULL);
4142 dns_rdata_freestruct(&dname);
4147 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
4148 * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
4149 * response to an NS query that should be treated as a referral
4150 * even though the NS records occur in the answer section
4151 * rather than the authority section.
4154 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
4155 isc_boolean_t bind8_ns_resp)
4157 isc_result_t result;
4158 dns_message_t *message;
4159 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
4160 dns_rdataset_t *rdataset, *ns_rdataset;
4161 isc_boolean_t done, aa, negative_response;
4162 dns_rdatatype_t type;
4163 dns_section_t section =
4164 bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
4166 FCTXTRACE("noanswer_response");
4168 message = fctx->rmessage;
4173 if (oqname == NULL) {
4175 * We have a normal, non-chained negative response or
4178 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
4182 qname = &fctx->name;
4185 * We're being invoked by answer_response() after it has
4186 * followed a CNAME/DNAME chain.
4191 * If the current qname is not a subdomain of the query
4192 * domain, there's no point in looking at the authority
4193 * section without doing DNSSEC validation.
4195 * Until we do that validation, we'll just return success
4198 if (!dns_name_issubdomain(qname, &fctx->domain))
4199 return (ISC_R_SUCCESS);
4203 * We have to figure out if this is a negative response, or a
4208 * Sometimes we can tell if its a negative response by looking at
4209 * the message header.
4211 negative_response = ISC_FALSE;
4212 if (message->rcode == dns_rcode_nxdomain ||
4213 (message->counts[DNS_SECTION_ANSWER] == 0 &&
4214 message->counts[DNS_SECTION_AUTHORITY] == 0))
4215 negative_response = ISC_TRUE;
4218 * Process the authority section.
4225 result = dns_message_firstname(message, section);
4226 while (!done && result == ISC_R_SUCCESS) {
4228 dns_message_currentname(message, section, &name);
4229 if (dns_name_issubdomain(name, &fctx->domain)) {
4231 * Look for NS/SOA RRsets first.
4233 for (rdataset = ISC_LIST_HEAD(name->list);
4235 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4236 type = rdataset->type;
4237 if (type == dns_rdatatype_rrsig)
4238 type = rdataset->covers;
4239 if (((type == dns_rdatatype_ns ||
4240 type == dns_rdatatype_soa) &&
4241 !dns_name_issubdomain(qname, name)))
4242 return (DNS_R_FORMERR);
4243 if (type == dns_rdatatype_ns) {
4247 * Only one set of NS RRs is allowed.
4249 if (rdataset->type ==
4251 if (ns_name != NULL &&
4253 return (DNS_R_FORMERR);
4255 ns_rdataset = rdataset;
4259 rdataset->attributes |=
4260 DNS_RDATASETATTR_CACHE;
4261 rdataset->trust = dns_trust_glue;
4263 if (type == dns_rdatatype_soa) {
4265 * SOA, or RRSIG SOA.
4267 * Only one SOA is allowed.
4269 if (rdataset->type ==
4270 dns_rdatatype_soa) {
4271 if (soa_name != NULL &&
4273 return (DNS_R_FORMERR);
4277 DNS_NAMEATTR_NCACHE;
4278 rdataset->attributes |=
4279 DNS_RDATASETATTR_NCACHE;
4282 dns_trust_authauthority;
4285 dns_trust_additional;
4289 * A negative response has a SOA record (Type 2)
4290 * and a optional NS RRset (Type 1) or it has neither
4291 * a SOA or a NS RRset (Type 3, handled above) or
4292 * rcode is NXDOMAIN (handled above) in which case
4293 * the NS RRset is allowed (Type 4).
4295 if (soa_name != NULL)
4296 negative_response = ISC_TRUE;
4297 for (rdataset = ISC_LIST_HEAD(name->list);
4299 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4300 type = rdataset->type;
4301 if (type == dns_rdatatype_rrsig)
4302 type = rdataset->covers;
4303 if (type == dns_rdatatype_nsec) {
4305 * NSEC or RRSIG NSEC.
4307 if (negative_response) {
4309 DNS_NAMEATTR_NCACHE;
4310 rdataset->attributes |=
4311 DNS_RDATASETATTR_NCACHE;
4315 rdataset->attributes |=
4316 DNS_RDATASETATTR_CACHE;
4320 dns_trust_authauthority;
4323 dns_trust_additional;
4325 * No additional data needs to be
4328 } else if (type == dns_rdatatype_ds) {
4332 * These should only be here if
4333 * this is a referral, and there
4334 * should only be one DS.
4336 if (ns_name == NULL)
4337 return (DNS_R_FORMERR);
4338 if (rdataset->type ==
4340 if (ds_name != NULL &&
4342 return (DNS_R_FORMERR);
4347 rdataset->attributes |=
4348 DNS_RDATASETATTR_CACHE;
4351 dns_trust_authauthority;
4354 dns_trust_additional;
4358 result = dns_message_nextname(message, section);
4359 if (result == ISC_R_NOMORE)
4361 else if (result != ISC_R_SUCCESS)
4366 * Trigger lookups for DNS nameservers.
4368 if (negative_response && message->rcode == dns_rcode_noerror &&
4369 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
4370 dns_name_equal(soa_name, qname) &&
4371 !dns_name_equal(qname, dns_rootname))
4372 return (DNS_R_CHASEDSSERVERS);
4375 * Did we find anything?
4377 if (!negative_response && ns_name == NULL) {
4381 if (oqname != NULL) {
4383 * We've already got a partial CNAME/DNAME chain,
4384 * and haven't found else anything useful here, but
4385 * no error has occurred since we have an answer.
4387 return (ISC_R_SUCCESS);
4390 * The responder is insane.
4392 return (DNS_R_FORMERR);
4397 * If we found both NS and SOA, they should be the same name.
4399 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name)
4400 return (DNS_R_FORMERR);
4403 * Do we have a referral? (We only want to follow a referral if
4404 * we're not following a chain.)
4406 if (!negative_response && ns_name != NULL && oqname == NULL) {
4408 * We already know ns_name is a subdomain of fctx->domain.
4409 * If ns_name is equal to fctx->domain, we're not making
4410 * progress. We return DNS_R_FORMERR so that we'll keep
4411 * trying other servers.
4413 if (dns_name_equal(ns_name, &fctx->domain))
4414 return (DNS_R_FORMERR);
4417 * If the referral name is not a parent of the query
4418 * name, consider the responder insane.
4420 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
4421 FCTXTRACE("referral to non-parent");
4422 return (DNS_R_FORMERR);
4426 * Mark any additional data related to this rdataset.
4427 * It's important that we do this before we change the
4430 INSIST(ns_rdataset != NULL);
4431 fctx->attributes |= FCTX_ATTR_GLUING;
4432 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
4434 fctx->attributes &= ~FCTX_ATTR_GLUING;
4436 * NS rdatasets with 0 TTL cause problems.
4437 * dns_view_findzonecut() will not find them when we
4438 * try to follow the referral, and we'll SERVFAIL
4439 * because the best nameservers are now above QDOMAIN.
4440 * We force the TTL to 1 second to prevent this.
4442 if (ns_rdataset->ttl == 0)
4443 ns_rdataset->ttl = 1;
4445 * Set the current query domain to the referral name.
4447 * XXXRTH We should check if we're in forward-only mode, and
4448 * if so we should bail out.
4450 INSIST(dns_name_countlabels(&fctx->domain) > 0);
4451 dns_name_free(&fctx->domain, fctx->res->mctx);
4452 if (dns_rdataset_isassociated(&fctx->nameservers))
4453 dns_rdataset_disassociate(&fctx->nameservers);
4454 dns_name_init(&fctx->domain, NULL);
4455 result = dns_name_dup(ns_name, fctx->res->mctx, &fctx->domain);
4456 if (result != ISC_R_SUCCESS)
4458 fctx->attributes |= FCTX_ATTR_WANTCACHE;
4459 return (DNS_R_DELEGATION);
4463 * Since we're not doing a referral, we don't want to cache any
4464 * NS RRs we may have found.
4466 if (ns_name != NULL)
4467 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
4469 if (negative_response && oqname == NULL)
4470 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
4472 return (ISC_R_SUCCESS);
4476 answer_response(fetchctx_t *fctx) {
4477 isc_result_t result;
4478 dns_message_t *message;
4479 dns_name_t *name, *qname, tname;
4480 dns_rdataset_t *rdataset;
4481 isc_boolean_t done, external, chaining, aa, found, want_chaining;
4482 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
4484 dns_rdatatype_t type;
4485 dns_fixedname_t dname, fqname;
4487 FCTXTRACE("answer_response");
4489 message = fctx->rmessage;
4492 * Examine the answer section, marking those rdatasets which are
4493 * part of the answer and should be cached.
4497 found_cname = ISC_FALSE;
4498 found_type = ISC_FALSE;
4499 chaining = ISC_FALSE;
4500 have_answer = ISC_FALSE;
4501 want_chaining = ISC_FALSE;
4502 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
4506 qname = &fctx->name;
4508 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
4509 while (!done && result == ISC_R_SUCCESS) {
4511 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
4512 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4513 if (dns_name_equal(name, qname)) {
4514 wanted_chaining = ISC_FALSE;
4515 for (rdataset = ISC_LIST_HEAD(name->list);
4517 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4519 want_chaining = ISC_FALSE;
4521 if (rdataset->type == type && !found_cname) {
4523 * We've found an ordinary answer.
4526 found_type = ISC_TRUE;
4528 aflag = DNS_RDATASETATTR_ANSWER;
4529 } else if (type == dns_rdatatype_any) {
4531 * We've found an answer matching
4532 * an ANY query. There may be
4536 aflag = DNS_RDATASETATTR_ANSWER;
4537 } else if (rdataset->type == dns_rdatatype_rrsig
4538 && rdataset->covers == type
4541 * We've found a signature that
4542 * covers the type we're looking for.
4545 found_type = ISC_TRUE;
4546 aflag = DNS_RDATASETATTR_ANSWERSIG;
4547 } else if (rdataset->type ==
4551 * We're looking for something else,
4552 * but we found a CNAME.
4554 * Getting a CNAME response for some
4555 * query types is an error.
4557 if (type == dns_rdatatype_rrsig ||
4558 type == dns_rdatatype_dnskey ||
4559 type == dns_rdatatype_nsec)
4560 return (DNS_R_FORMERR);
4562 found_cname = ISC_TRUE;
4563 want_chaining = ISC_TRUE;
4564 aflag = DNS_RDATASETATTR_ANSWER;
4565 result = cname_target(rdataset,
4567 if (result != ISC_R_SUCCESS)
4569 } else if (rdataset->type == dns_rdatatype_rrsig
4570 && rdataset->covers ==
4574 * We're looking for something else,
4575 * but we found a SIG CNAME.
4578 found_cname = ISC_TRUE;
4579 aflag = DNS_RDATASETATTR_ANSWERSIG;
4584 * We've found an answer to our
4589 rdataset->attributes |=
4590 DNS_RDATASETATTR_CACHE;
4591 rdataset->trust = dns_trust_answer;
4594 * This data is "the" answer
4595 * to our question only if
4596 * we're not chaining (i.e.
4597 * if we haven't followed
4598 * a CNAME or DNAME).
4602 DNS_RDATASETATTR_ANSWER)
4603 have_answer = ISC_TRUE;
4605 DNS_NAMEATTR_ANSWER;
4606 rdataset->attributes |= aflag;
4609 dns_trust_authanswer;
4610 } else if (external) {
4612 * This data is outside of
4613 * our query domain, and
4614 * may only be cached if it
4615 * comes from a secure zone
4618 rdataset->attributes |=
4619 DNS_RDATASETATTR_EXTERNAL;
4623 * Mark any additional data related
4626 (void)dns_rdataset_additionaldata(
4634 if (want_chaining) {
4635 wanted_chaining = ISC_TRUE;
4637 DNS_NAMEATTR_CHAINING;
4638 rdataset->attributes |=
4639 DNS_RDATASETATTR_CHAINING;
4644 * We could add an "else" clause here and
4645 * log that we're ignoring this rdataset.
4649 * If wanted_chaining is true, we've done
4650 * some chaining as the result of processing
4651 * this node, and thus we need to set
4654 * We don't set chaining inside of the
4655 * rdataset loop because doing that would
4656 * cause us to ignore the signatures of
4659 if (wanted_chaining)
4660 chaining = ISC_TRUE;
4663 * Look for a DNAME (or its SIG). Anything else is
4666 wanted_chaining = ISC_FALSE;
4667 for (rdataset = ISC_LIST_HEAD(name->list);
4669 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4670 isc_boolean_t found_dname = ISC_FALSE;
4673 if (rdataset->type == dns_rdatatype_dname) {
4675 * We're looking for something else,
4676 * but we found a DNAME.
4678 * If we're not chaining, then the
4679 * DNAME should not be external.
4681 if (!chaining && external)
4682 return (DNS_R_FORMERR);
4684 want_chaining = ISC_TRUE;
4685 aflag = DNS_RDATASETATTR_ANSWER;
4686 result = dname_target(rdataset,
4689 if (result == ISC_R_NOSPACE) {
4691 * We can't construct the
4692 * DNAME target. Do not
4695 want_chaining = ISC_FALSE;
4696 } else if (result != ISC_R_SUCCESS)
4699 found_dname = ISC_TRUE;
4700 } else if (rdataset->type == dns_rdatatype_rrsig
4701 && rdataset->covers ==
4702 dns_rdatatype_dname) {
4704 * We've found a signature that
4708 aflag = DNS_RDATASETATTR_ANSWERSIG;
4713 * We've found an answer to our
4718 rdataset->attributes |=
4719 DNS_RDATASETATTR_CACHE;
4720 rdataset->trust = dns_trust_answer;
4723 * This data is "the" answer
4724 * to our question only if
4725 * we're not chaining.
4729 DNS_RDATASETATTR_ANSWER)
4730 have_answer = ISC_TRUE;
4732 DNS_NAMEATTR_ANSWER;
4733 rdataset->attributes |= aflag;
4736 dns_trust_authanswer;
4737 } else if (external) {
4738 rdataset->attributes |=
4739 DNS_RDATASETATTR_EXTERNAL;
4747 * Copy the the dname into the
4750 * Although we check for
4751 * failure of the copy
4752 * operation, in practice it
4753 * should never fail since
4754 * we already know that the
4755 * result fits in a fixedname.
4757 dns_fixedname_init(&fqname);
4758 result = dns_name_copy(
4759 dns_fixedname_name(&dname),
4760 dns_fixedname_name(&fqname),
4762 if (result != ISC_R_SUCCESS)
4764 wanted_chaining = ISC_TRUE;
4766 DNS_NAMEATTR_CHAINING;
4767 rdataset->attributes |=
4768 DNS_RDATASETATTR_CHAINING;
4769 qname = dns_fixedname_name(
4774 if (wanted_chaining)
4775 chaining = ISC_TRUE;
4777 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
4779 if (result == ISC_R_NOMORE)
4780 result = ISC_R_SUCCESS;
4781 if (result != ISC_R_SUCCESS)
4785 * We should have found an answer.
4788 return (DNS_R_FORMERR);
4791 * This response is now potentially cacheable.
4793 fctx->attributes |= FCTX_ATTR_WANTCACHE;
4796 * Did chaining end before we got the final answer?
4800 * Yes. This may be a negative reply, so hand off
4801 * authority section processing to the noanswer code.
4802 * If it isn't a noanswer response, no harm will be
4805 return (noanswer_response(fctx, qname, ISC_FALSE));
4809 * We didn't end with an incomplete chain, so the rcode should be
4812 if (message->rcode != dns_rcode_noerror)
4813 return (DNS_R_FORMERR);
4816 * Examine the authority section (if there is one).
4818 * We expect there to be only one owner name for all the rdatasets
4819 * in this section, and we expect that it is not external.
4822 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
4823 while (!done && result == ISC_R_SUCCESS) {
4825 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
4826 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4829 * We expect to find NS or SIG NS rdatasets, and
4832 for (rdataset = ISC_LIST_HEAD(name->list);
4834 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4835 if (rdataset->type == dns_rdatatype_ns ||
4836 (rdataset->type == dns_rdatatype_rrsig &&
4837 rdataset->covers == dns_rdatatype_ns)) {
4840 rdataset->attributes |=
4841 DNS_RDATASETATTR_CACHE;
4842 if (aa && !chaining)
4844 dns_trust_authauthority;
4847 dns_trust_additional;
4850 * Mark any additional data related
4853 (void)dns_rdataset_additionaldata(
4861 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
4863 if (result == ISC_R_NOMORE)
4864 result = ISC_R_SUCCESS;
4870 resume_dslookup(isc_task_t *task, isc_event_t *event) {
4871 dns_fetchevent_t *fevent;
4872 dns_resolver_t *res;
4874 isc_result_t result;
4875 isc_boolean_t bucket_empty = ISC_FALSE;
4876 isc_boolean_t locked = ISC_FALSE;
4877 unsigned int bucketnum;
4878 dns_rdataset_t nameservers;
4879 dns_fixedname_t fixed;
4882 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
4883 fevent = (dns_fetchevent_t *)event;
4884 fctx = event->ev_arg;
4885 REQUIRE(VALID_FCTX(fctx));
4889 FCTXTRACE("resume_dslookup");
4891 if (fevent->node != NULL)
4892 dns_db_detachnode(fevent->db, &fevent->node);
4893 if (fevent->db != NULL)
4894 dns_db_detach(&fevent->db);
4896 dns_rdataset_init(&nameservers);
4898 bucketnum = fctx->bucketnum;
4899 if (fevent->result == ISC_R_CANCELED) {
4900 dns_resolver_destroyfetch(&fctx->nsfetch);
4901 fctx_done(fctx, ISC_R_CANCELED);
4902 } else if (fevent->result == ISC_R_SUCCESS) {
4904 FCTXTRACE("resuming DS lookup");
4906 dns_resolver_destroyfetch(&fctx->nsfetch);
4907 if (dns_rdataset_isassociated(&fctx->nameservers))
4908 dns_rdataset_disassociate(&fctx->nameservers);
4909 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
4910 dns_name_free(&fctx->domain, fctx->res->mctx);
4911 dns_name_init(&fctx->domain, NULL);
4912 result = dns_name_dup(&fctx->nsname, fctx->res->mctx,
4914 if (result != ISC_R_SUCCESS) {
4915 fctx_done(fctx, DNS_R_SERVFAIL);
4926 * Retrieve state from fctx->nsfetch before we destroy it.
4928 dns_fixedname_init(&fixed);
4929 domain = dns_fixedname_name(&fixed);
4930 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
4931 dns_rdataset_clone(&fctx->nsfetch->private->nameservers,
4933 dns_resolver_destroyfetch(&fctx->nsfetch);
4934 if (dns_name_equal(&fctx->nsname, domain)) {
4935 fctx_done(fctx, DNS_R_SERVFAIL);
4938 n = dns_name_countlabels(&fctx->nsname);
4939 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
4942 if (dns_rdataset_isassociated(fevent->rdataset))
4943 dns_rdataset_disassociate(fevent->rdataset);
4944 FCTXTRACE("continuing to look for parent's NS records");
4945 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
4946 dns_rdatatype_ns, domain,
4947 &nameservers, NULL, 0, task,
4948 resume_dslookup, fctx,
4949 &fctx->nsrrset, NULL,
4951 if (result != ISC_R_SUCCESS)
4952 fctx_done(fctx, result);
4954 LOCK(&res->buckets[bucketnum].lock);
4961 if (dns_rdataset_isassociated(&nameservers))
4962 dns_rdataset_disassociate(&nameservers);
4963 if (dns_rdataset_isassociated(fevent->rdataset))
4964 dns_rdataset_disassociate(fevent->rdataset);
4965 INSIST(fevent->sigrdataset == NULL);
4966 isc_event_free(&event);
4968 LOCK(&res->buckets[bucketnum].lock);
4970 if (fctx->references == 0)
4971 bucket_empty = fctx_destroy(fctx);
4972 UNLOCK(&res->buckets[bucketnum].lock);
4978 checknamessection(dns_message_t *message, dns_section_t section) {
4979 isc_result_t result;
4981 dns_rdata_t rdata = DNS_RDATA_INIT;
4982 dns_rdataset_t *rdataset;
4984 for (result = dns_message_firstname(message, section);
4985 result == ISC_R_SUCCESS;
4986 result = dns_message_nextname(message, section))
4989 dns_message_currentname(message, section, &name);
4990 for (rdataset = ISC_LIST_HEAD(name->list);
4992 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4993 for (result = dns_rdataset_first(rdataset);
4994 result == ISC_R_SUCCESS;
4995 result = dns_rdataset_next(rdataset)) {
4996 dns_rdataset_current(rdataset, &rdata);
4997 if (!dns_rdata_checkowner(name, rdata.rdclass,
5000 !dns_rdata_checknames(&rdata, name, NULL))
5002 rdataset->attributes |=
5003 DNS_RDATASETATTR_CHECKNAMES;
5005 dns_rdata_reset(&rdata);
5012 checknames(dns_message_t *message) {
5014 checknamessection(message, DNS_SECTION_ANSWER);
5015 checknamessection(message, DNS_SECTION_AUTHORITY);
5016 checknamessection(message, DNS_SECTION_ADDITIONAL);
5020 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
5021 isc_buffer_t buffer;
5024 isc_result_t result;
5026 if (! isc_log_wouldlog(dns_lctx, level))
5030 * Note that these are multiline debug messages. We want a newline
5031 * to appear in the log after each message.
5035 buf = isc_mem_get(mctx, len);
5038 isc_buffer_init(&buffer, buf, len);
5039 result = dns_message_totext(message, &dns_master_style_debug,
5041 if (result == ISC_R_NOSPACE) {
5042 isc_mem_put(mctx, buf, len);
5044 } else if (result == ISC_R_SUCCESS)
5045 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5046 DNS_LOGMODULE_RESOLVER, level,
5047 "received packet:\n%.*s",
5048 (int)isc_buffer_usedlength(&buffer),
5050 } while (result == ISC_R_NOSPACE);
5053 isc_mem_put(mctx, buf, len);
5057 resquery_response(isc_task_t *task, isc_event_t *event) {
5058 isc_result_t result = ISC_R_SUCCESS;
5059 resquery_t *query = event->ev_arg;
5060 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
5061 isc_boolean_t keep_trying, get_nameservers, resend;
5062 isc_boolean_t truncated;
5063 dns_message_t *message;
5066 dns_fixedname_t foundname;
5068 isc_time_t tnow, *finish;
5069 dns_adbaddrinfo_t *addrinfo;
5070 unsigned int options;
5071 unsigned int findoptions;
5072 isc_result_t broken_server;
5074 REQUIRE(VALID_QUERY(query));
5076 options = query->options;
5077 REQUIRE(VALID_FCTX(fctx));
5078 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
5082 (void)isc_timer_touch(fctx->timer);
5084 keep_trying = ISC_FALSE;
5085 broken_server = ISC_R_SUCCESS;
5086 get_nameservers = ISC_FALSE;
5088 truncated = ISC_FALSE;
5091 if (fctx->res->exiting) {
5092 result = ISC_R_SHUTTINGDOWN;
5099 * XXXRTH We should really get the current time just once. We
5100 * need a routine to convert from an isc_time_t to an
5105 isc_stdtime_get(&now);
5108 * Did the dispatcher have a problem?
5110 if (devent->result != ISC_R_SUCCESS) {
5111 if (devent->result == ISC_R_EOF &&
5112 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5114 * The problem might be that they
5115 * don't understand EDNS0. Turn it
5116 * off and try again.
5118 options |= DNS_FETCHOPT_NOEDNS0;
5121 * Remember that they don't like EDNS0.
5123 dns_adb_changeflags(fctx->adb,
5125 DNS_FETCHOPT_NOEDNS0,
5126 DNS_FETCHOPT_NOEDNS0);
5129 * There's no hope for this query.
5131 keep_trying = ISC_TRUE;
5136 message = fctx->rmessage;
5138 if (query->tsig != NULL) {
5139 result = dns_message_setquerytsig(message, query->tsig);
5140 if (result != ISC_R_SUCCESS)
5144 if (query->tsigkey) {
5145 result = dns_message_settsigkey(message, query->tsigkey);
5146 if (result != ISC_R_SUCCESS)
5150 result = dns_message_parse(message, &devent->buffer, 0);
5151 if (result != ISC_R_SUCCESS) {
5153 case ISC_R_UNEXPECTEDEND:
5154 if (!message->question_ok ||
5155 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
5156 (options & DNS_FETCHOPT_TCP) != 0) {
5158 * Either the message ended prematurely,
5159 * and/or wasn't marked as being truncated,
5160 * and/or this is a response to a query we
5161 * sent over TCP. In all of these cases,
5162 * something is wrong with the remote
5163 * server and we don't want to retry using
5166 if ((query->options & DNS_FETCHOPT_NOEDNS0)
5169 * The problem might be that they
5170 * don't understand EDNS0. Turn it
5171 * off and try again.
5173 options |= DNS_FETCHOPT_NOEDNS0;
5176 * Remember that they don't like EDNS0.
5178 dns_adb_changeflags(
5181 DNS_FETCHOPT_NOEDNS0,
5182 DNS_FETCHOPT_NOEDNS0);
5184 broken_server = result;
5185 keep_trying = ISC_TRUE;
5190 * We defer retrying via TCP for a bit so we can
5191 * check out this message further.
5193 truncated = ISC_TRUE;
5196 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5198 * The problem might be that they
5199 * don't understand EDNS0. Turn it
5200 * off and try again.
5202 options |= DNS_FETCHOPT_NOEDNS0;
5205 * Remember that they don't like EDNS0.
5207 dns_adb_changeflags(fctx->adb,
5209 DNS_FETCHOPT_NOEDNS0,
5210 DNS_FETCHOPT_NOEDNS0);
5212 broken_server = DNS_R_UNEXPECTEDRCODE;
5213 keep_trying = ISC_TRUE;
5218 * Something bad has happened.
5225 * Log the incoming packet.
5227 log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
5230 * If the message is signed, check the signature. If not, this
5231 * returns success anyway.
5233 result = dns_message_checksig(message, fctx->res->view);
5234 if (result != ISC_R_SUCCESS)
5238 * The dispatcher should ensure we only get responses with QR set.
5240 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
5242 * INSIST() that the message comes from the place we sent it to,
5243 * since the dispatch code should ensure this.
5245 * INSIST() that the message id is correct (this should also be
5246 * ensured by the dispatch code).
5251 * Deal with truncated responses by retrying using TCP.
5253 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
5254 truncated = ISC_TRUE;
5257 if ((options & DNS_FETCHOPT_TCP) != 0) {
5258 broken_server = DNS_R_TRUNCATEDTCP;
5259 keep_trying = ISC_TRUE;
5261 options |= DNS_FETCHOPT_TCP;
5268 * Is it a query response?
5270 if (message->opcode != dns_opcode_query) {
5272 broken_server = DNS_R_UNEXPECTEDOPCODE;
5273 keep_trying = ISC_TRUE;
5278 * Is the remote server broken, or does it dislike us?
5280 if (message->rcode != dns_rcode_noerror &&
5281 message->rcode != dns_rcode_nxdomain) {
5282 if ((message->rcode == dns_rcode_formerr ||
5283 message->rcode == dns_rcode_notimp ||
5284 message->rcode == dns_rcode_servfail) &&
5285 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5287 * It's very likely they don't like EDNS0.
5289 * XXXRTH We should check if the question
5290 * we're asking requires EDNS0, and
5291 * if so, we should bail out.
5293 options |= DNS_FETCHOPT_NOEDNS0;
5296 * Remember that they don't like EDNS0.
5298 if (message->rcode != dns_rcode_servfail)
5299 dns_adb_changeflags(fctx->adb, query->addrinfo,
5300 DNS_FETCHOPT_NOEDNS0,
5301 DNS_FETCHOPT_NOEDNS0);
5302 } else if (message->rcode == dns_rcode_formerr) {
5303 if (ISFORWARDER(query->addrinfo)) {
5305 * This forwarder doesn't understand us,
5306 * but other forwarders might. Keep trying.
5308 broken_server = DNS_R_REMOTEFORMERR;
5309 keep_trying = ISC_TRUE;
5312 * The server doesn't understand us. Since
5313 * all servers for a zone need similar
5314 * capabilities, we assume that we will get
5315 * FORMERR from all servers, and thus we
5316 * cannot make any more progress with this
5319 result = DNS_R_FORMERR;
5321 } else if (message->rcode == dns_rcode_yxdomain) {
5323 * DNAME mapping failed because the new name
5324 * was too long. There's no chance of success
5327 result = DNS_R_YXDOMAIN;
5332 broken_server = DNS_R_UNEXPECTEDRCODE;
5333 INSIST(broken_server != ISC_R_SUCCESS);
5334 keep_trying = ISC_TRUE;
5340 * Is the question the same as the one we asked?
5342 result = same_question(fctx);
5343 if (result != ISC_R_SUCCESS) {
5345 if (result == DNS_R_FORMERR)
5346 keep_trying = ISC_TRUE;
5351 * Is the server lame?
5353 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
5355 log_lame(fctx, query->addrinfo);
5356 result = dns_adb_marklame(fctx->adb, query->addrinfo,
5358 now + fctx->res->lame_ttl);
5359 if (result != ISC_R_SUCCESS)
5360 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5361 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
5362 "could not mark server as lame: %s",
5363 isc_result_totext(result));
5364 broken_server = DNS_R_LAME;
5365 keep_trying = ISC_TRUE;
5370 * Enforce delegations only zones like NET and COM.
5372 if (!ISFORWARDER(query->addrinfo) &&
5373 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
5374 !dns_name_equal(&fctx->domain, &fctx->name) &&
5375 fix_mustbedelegationornxdomain(message, fctx)) {
5376 char namebuf[DNS_NAME_FORMATSIZE];
5377 char domainbuf[DNS_NAME_FORMATSIZE];
5378 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
5382 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
5383 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
5384 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
5385 dns_rdataclass_format(fctx->res->rdclass, classbuf,
5387 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
5390 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
5391 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5392 "enforced delegation-only for '%s' (%s/%s/%s) "
5394 domainbuf, namebuf, typebuf, classbuf, addrbuf);
5397 if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
5398 checknames(message);
5403 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
5406 * Did we get any answers?
5408 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
5409 (message->rcode == dns_rcode_noerror ||
5410 message->rcode == dns_rcode_nxdomain)) {
5412 * We've got answers. However, if we sent
5413 * a BIND 8 server an NS query, it may have
5414 * incorrectly responded with a non-authoritative
5415 * answer instead of a referral. Since this
5416 * answer lacks the SIGs necessary to do DNSSEC
5417 * validation, we must invoke the following special
5418 * kludge to treat it as a referral.
5420 if (fctx->type == dns_rdatatype_ns &&
5421 (message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
5422 !ISFORWARDER(query->addrinfo))
5424 result = noanswer_response(fctx, NULL, ISC_TRUE);
5425 if (result != DNS_R_DELEGATION) {
5427 * The answer section must have contained
5428 * something other than the NS records
5429 * we asked for. Since AA is not set
5430 * and the server is not a forwarder,
5431 * it is technically lame and it's easier
5432 * to treat it as such than to figure out
5433 * some more elaborate course of action.
5435 broken_server = DNS_R_LAME;
5436 keep_trying = ISC_TRUE;
5439 goto force_referral;
5441 result = answer_response(fctx);
5442 if (result != ISC_R_SUCCESS) {
5443 if (result == DNS_R_FORMERR)
5444 keep_trying = ISC_TRUE;
5447 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
5448 message->rcode == dns_rcode_noerror ||
5449 message->rcode == dns_rcode_nxdomain) {
5451 * NXDOMAIN, NXRDATASET, or referral.
5453 result = noanswer_response(fctx, NULL, ISC_FALSE);
5454 if (result == DNS_R_CHASEDSSERVERS) {
5455 } else if (result == DNS_R_DELEGATION) {
5458 * We don't have the answer, but we know a better
5461 get_nameservers = ISC_TRUE;
5462 keep_trying = ISC_TRUE;
5464 * We have a new set of name servers, and it
5465 * has not experienced any restarts yet.
5468 result = ISC_R_SUCCESS;
5469 } else if (result != ISC_R_SUCCESS) {
5471 * Something has gone wrong.
5473 if (result == DNS_R_FORMERR)
5474 keep_trying = ISC_TRUE;
5479 * The server is insane.
5482 broken_server = DNS_R_UNEXPECTEDRCODE;
5483 keep_trying = ISC_TRUE;
5488 * Follow additional section data chains.
5490 chase_additional(fctx);
5493 * Cache the cacheable parts of the message. This may also cause
5494 * work to be queued to the DNSSEC validator.
5496 if (WANTCACHE(fctx)) {
5497 result = cache_message(fctx, query->addrinfo, now);
5498 if (result != ISC_R_SUCCESS)
5503 * Ncache the negatively cacheable parts of the message. This may
5504 * also cause work to be queued to the DNSSEC validator.
5506 if (WANTNCACHE(fctx)) {
5507 dns_rdatatype_t covers;
5508 if (message->rcode == dns_rcode_nxdomain)
5509 covers = dns_rdatatype_any;
5511 covers = fctx->type;
5514 * Cache any negative cache entries in the message.
5516 result = ncache_message(fctx, query->addrinfo, covers, now);
5521 * Remember the query's addrinfo, in case we need to mark the
5524 addrinfo = query->addrinfo;
5529 * XXXRTH Don't cancel the query if waiting for validation?
5531 fctx_cancelquery(&query, &devent, finish, ISC_FALSE);
5534 if (result == DNS_R_FORMERR)
5535 broken_server = DNS_R_FORMERR;
5536 if (broken_server != ISC_R_SUCCESS) {
5538 * Add this server to the list of bad servers for
5541 add_bad(fctx, &addrinfo->sockaddr, broken_server);
5544 if (get_nameservers) {
5546 dns_fixedname_init(&foundname);
5547 fname = dns_fixedname_name(&foundname);
5548 if (result != ISC_R_SUCCESS) {
5549 fctx_done(fctx, DNS_R_SERVFAIL);
5553 if (dns_rdatatype_atparent(fctx->type))
5554 findoptions |= DNS_DBFIND_NOEXACT;
5555 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
5558 name = &fctx->domain;
5559 result = dns_view_findzonecut(fctx->res->view,
5565 if (result != ISC_R_SUCCESS) {
5566 FCTXTRACE("couldn't find a zonecut");
5567 fctx_done(fctx, DNS_R_SERVFAIL);
5570 if (!dns_name_issubdomain(fname, &fctx->domain)) {
5572 * The best nameservers are now above our
5575 FCTXTRACE("nameservers now above QDOMAIN");
5576 fctx_done(fctx, DNS_R_SERVFAIL);
5579 dns_name_free(&fctx->domain, fctx->res->mctx);
5580 dns_name_init(&fctx->domain, NULL);
5581 result = dns_name_dup(fname, fctx->res->mctx,
5583 if (result != ISC_R_SUCCESS) {
5584 fctx_done(fctx, DNS_R_SERVFAIL);
5587 fctx_cancelqueries(fctx, ISC_TRUE);
5588 fctx_cleanupfinds(fctx);
5589 fctx_cleanupaltfinds(fctx);
5590 fctx_cleanupforwaddrs(fctx);
5591 fctx_cleanupaltaddrs(fctx);
5597 } else if (resend) {
5599 * Resend (probably with changed options).
5601 FCTXTRACE("resend");
5602 result = fctx_query(fctx, addrinfo, options);
5603 if (result != ISC_R_SUCCESS)
5604 fctx_done(fctx, result);
5605 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
5607 * All has gone well so far, but we are waiting for the
5608 * DNSSEC validator to validate the answer.
5610 FCTXTRACE("wait for validator");
5611 fctx_cancelqueries(fctx, ISC_TRUE);
5613 * We must not retransmit while the validator is working;
5614 * it has references to the current rmessage.
5616 result = fctx_stopidletimer(fctx);
5617 if (result != ISC_R_SUCCESS)
5618 fctx_done(fctx, result);
5619 } else if (result == DNS_R_CHASEDSSERVERS) {
5621 add_bad(fctx, &addrinfo->sockaddr, result);
5622 fctx_cancelqueries(fctx, ISC_TRUE);
5623 fctx_cleanupfinds(fctx);
5624 fctx_cleanupforwaddrs(fctx);
5626 n = dns_name_countlabels(&fctx->name);
5627 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
5629 FCTXTRACE("suspending DS lookup to find parent's NS records");
5631 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
5633 NULL, NULL, NULL, 0, task,
5634 resume_dslookup, fctx,
5635 &fctx->nsrrset, NULL,
5637 if (result != ISC_R_SUCCESS)
5638 fctx_done(fctx, result);
5639 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
5641 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
5642 result = fctx_stopidletimer(fctx);
5643 if (result != ISC_R_SUCCESS)
5644 fctx_done(fctx, result);
5649 fctx_done(fctx, result);
5655 *** Resolver Methods
5659 destroy(dns_resolver_t *res) {
5663 REQUIRE(res->references == 0);
5664 REQUIRE(!res->priming);
5665 REQUIRE(res->primefetch == NULL);
5669 INSIST(res->nfctx == 0);
5671 DESTROYLOCK(&res->primelock);
5672 DESTROYLOCK(&res->nlock);
5673 DESTROYLOCK(&res->lock);
5674 for (i = 0; i < res->nbuckets; i++) {
5675 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
5676 isc_task_shutdown(res->buckets[i].task);
5677 isc_task_detach(&res->buckets[i].task);
5678 DESTROYLOCK(&res->buckets[i].lock);
5680 isc_mem_put(res->mctx, res->buckets,
5681 res->nbuckets * sizeof(fctxbucket_t));
5682 if (res->dispatchv4 != NULL)
5683 dns_dispatch_detach(&res->dispatchv4);
5684 if (res->dispatchv6 != NULL)
5685 dns_dispatch_detach(&res->dispatchv6);
5686 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
5687 ISC_LIST_UNLINK(res->alternates, a, link);
5689 dns_name_free(&a->_u._n.name, res->mctx);
5690 isc_mem_put(res->mctx, a, sizeof(*a));
5692 dns_resolver_reset_algorithms(res);
5693 dns_resolver_resetmustbesecure(res);
5695 isc_rwlock_destroy(&res->alglock);
5698 isc_rwlock_destroy(&res->mbslock);
5701 isc_mem_put(res->mctx, res, sizeof(*res));
5705 send_shutdown_events(dns_resolver_t *res) {
5706 isc_event_t *event, *next_event;
5710 * Caller must be holding the resolver lock.
5713 for (event = ISC_LIST_HEAD(res->whenshutdown);
5715 event = next_event) {
5716 next_event = ISC_LIST_NEXT(event, ev_link);
5717 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
5718 etask = event->ev_sender;
5719 event->ev_sender = res;
5720 isc_task_sendanddetach(&etask, &event);
5725 empty_bucket(dns_resolver_t *res) {
5726 RTRACE("empty_bucket");
5730 INSIST(res->activebuckets > 0);
5731 res->activebuckets--;
5732 if (res->activebuckets == 0)
5733 send_shutdown_events(res);
5739 dns_resolver_create(dns_view_t *view,
5740 isc_taskmgr_t *taskmgr, unsigned int ntasks,
5741 isc_socketmgr_t *socketmgr,
5742 isc_timermgr_t *timermgr,
5743 unsigned int options,
5744 dns_dispatchmgr_t *dispatchmgr,
5745 dns_dispatch_t *dispatchv4,
5746 dns_dispatch_t *dispatchv6,
5747 dns_resolver_t **resp)
5749 dns_resolver_t *res;
5750 isc_result_t result = ISC_R_SUCCESS;
5751 unsigned int i, buckets_created = 0;
5755 * Create a resolver.
5758 REQUIRE(DNS_VIEW_VALID(view));
5759 REQUIRE(ntasks > 0);
5760 REQUIRE(resp != NULL && *resp == NULL);
5761 REQUIRE(dispatchmgr != NULL);
5762 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
5764 res = isc_mem_get(view->mctx, sizeof(*res));
5766 return (ISC_R_NOMEMORY);
5768 res->mctx = view->mctx;
5769 res->rdclass = view->rdclass;
5770 res->socketmgr = socketmgr;
5771 res->timermgr = timermgr;
5772 res->taskmgr = taskmgr;
5773 res->dispatchmgr = dispatchmgr;
5775 res->options = options;
5777 ISC_LIST_INIT(res->alternates);
5778 res->udpsize = RECV_BUFFER_SIZE;
5779 res->algorithms = NULL;
5780 res->mustbesecure = NULL;
5782 res->nbuckets = ntasks;
5783 res->activebuckets = ntasks;
5784 res->buckets = isc_mem_get(view->mctx,
5785 ntasks * sizeof(fctxbucket_t));
5786 if (res->buckets == NULL) {
5787 result = ISC_R_NOMEMORY;
5790 for (i = 0; i < ntasks; i++) {
5791 result = isc_mutex_init(&res->buckets[i].lock);
5792 if (result != ISC_R_SUCCESS)
5793 goto cleanup_buckets;
5794 res->buckets[i].task = NULL;
5795 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
5796 if (result != ISC_R_SUCCESS) {
5797 DESTROYLOCK(&res->buckets[i].lock);
5798 goto cleanup_buckets;
5800 snprintf(name, sizeof(name), "res%u", i);
5801 isc_task_setname(res->buckets[i].task, name, res);
5802 ISC_LIST_INIT(res->buckets[i].fctxs);
5803 res->buckets[i].exiting = ISC_FALSE;
5807 res->dispatchv4 = NULL;
5808 if (dispatchv4 != NULL)
5809 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
5810 res->dispatchv6 = NULL;
5811 if (dispatchv6 != NULL)
5812 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
5814 res->references = 1;
5815 res->exiting = ISC_FALSE;
5816 res->frozen = ISC_FALSE;
5817 ISC_LIST_INIT(res->whenshutdown);
5818 res->priming = ISC_FALSE;
5819 res->primefetch = NULL;
5822 result = isc_mutex_init(&res->lock);
5823 if (result != ISC_R_SUCCESS)
5824 goto cleanup_dispatches;
5826 result = isc_mutex_init(&res->nlock);
5827 if (result != ISC_R_SUCCESS)
5830 result = isc_mutex_init(&res->primelock);
5831 if (result != ISC_R_SUCCESS)
5835 result = isc_rwlock_init(&res->alglock, 0, 0);
5836 if (result != ISC_R_SUCCESS)
5837 goto cleanup_primelock;
5840 result = isc_rwlock_init(&res->mbslock, 0, 0);
5841 if (result != ISC_R_SUCCESS)
5842 goto cleanup_alglock;
5845 res->magic = RES_MAGIC;
5849 return (ISC_R_SUCCESS);
5854 isc_rwlock_destroy(&res->alglock);
5857 #if USE_ALGLOCK || USE_MBSLOCK
5859 DESTROYLOCK(&res->primelock);
5863 DESTROYLOCK(&res->nlock);
5866 DESTROYLOCK(&res->lock);
5869 if (res->dispatchv6 != NULL)
5870 dns_dispatch_detach(&res->dispatchv6);
5871 if (res->dispatchv4 != NULL)
5872 dns_dispatch_detach(&res->dispatchv4);
5875 for (i = 0; i < buckets_created; i++) {
5876 DESTROYLOCK(&res->buckets[i].lock);
5877 isc_task_shutdown(res->buckets[i].task);
5878 isc_task_detach(&res->buckets[i].task);
5880 isc_mem_put(view->mctx, res->buckets,
5881 res->nbuckets * sizeof(fctxbucket_t));
5884 isc_mem_put(view->mctx, res, sizeof(*res));
5890 prime_done(isc_task_t *task, isc_event_t *event) {
5891 dns_resolver_t *res;
5892 dns_fetchevent_t *fevent;
5895 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
5896 fevent = (dns_fetchevent_t *)event;
5897 res = event->ev_arg;
5898 REQUIRE(VALID_RESOLVER(res));
5904 INSIST(res->priming);
5905 res->priming = ISC_FALSE;
5906 LOCK(&res->primelock);
5907 fetch = res->primefetch;
5908 res->primefetch = NULL;
5909 UNLOCK(&res->primelock);
5913 if (fevent->node != NULL)
5914 dns_db_detachnode(fevent->db, &fevent->node);
5915 if (fevent->db != NULL)
5916 dns_db_detach(&fevent->db);
5917 if (dns_rdataset_isassociated(fevent->rdataset))
5918 dns_rdataset_disassociate(fevent->rdataset);
5919 INSIST(fevent->sigrdataset == NULL);
5921 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
5923 isc_event_free(&event);
5924 dns_resolver_destroyfetch(&fetch);
5928 dns_resolver_prime(dns_resolver_t *res) {
5929 isc_boolean_t want_priming = ISC_FALSE;
5930 dns_rdataset_t *rdataset;
5931 isc_result_t result;
5933 REQUIRE(VALID_RESOLVER(res));
5934 REQUIRE(res->frozen);
5936 RTRACE("dns_resolver_prime");
5940 if (!res->exiting && !res->priming) {
5941 INSIST(res->primefetch == NULL);
5942 res->priming = ISC_TRUE;
5943 want_priming = ISC_TRUE;
5950 * To avoid any possible recursive locking problems, we
5951 * start the priming fetch like any other fetch, and holding
5952 * no resolver locks. No one else will try to start it
5953 * because we're the ones who set res->priming to true.
5954 * Any other callers of dns_resolver_prime() while we're
5955 * running will see that res->priming is already true and
5959 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
5960 if (rdataset == NULL) {
5962 INSIST(res->priming);
5963 INSIST(res->primefetch == NULL);
5964 res->priming = ISC_FALSE;
5968 dns_rdataset_init(rdataset);
5969 LOCK(&res->primelock);
5970 result = dns_resolver_createfetch(res, dns_rootname,
5972 NULL, NULL, NULL, 0,
5973 res->buckets[0].task,
5975 res, rdataset, NULL,
5977 UNLOCK(&res->primelock);
5978 if (result != ISC_R_SUCCESS) {
5980 INSIST(res->priming);
5981 res->priming = ISC_FALSE;
5988 dns_resolver_freeze(dns_resolver_t *res) {
5994 REQUIRE(VALID_RESOLVER(res));
5995 REQUIRE(!res->frozen);
5997 res->frozen = ISC_TRUE;
6001 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
6002 REQUIRE(VALID_RESOLVER(source));
6003 REQUIRE(targetp != NULL && *targetp == NULL);
6005 RRTRACE(source, "attach");
6006 LOCK(&source->lock);
6007 REQUIRE(!source->exiting);
6009 INSIST(source->references > 0);
6010 source->references++;
6011 INSIST(source->references != 0);
6012 UNLOCK(&source->lock);
6018 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
6019 isc_event_t **eventp)
6024 REQUIRE(VALID_RESOLVER(res));
6025 REQUIRE(eventp != NULL);
6032 if (res->exiting && res->activebuckets == 0) {
6034 * We're already shutdown. Send the event.
6036 event->ev_sender = res;
6037 isc_task_send(task, &event);
6040 isc_task_attach(task, &clone);
6041 event->ev_sender = clone;
6042 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
6049 dns_resolver_shutdown(dns_resolver_t *res) {
6054 REQUIRE(VALID_RESOLVER(res));
6060 if (!res->exiting) {
6062 res->exiting = ISC_TRUE;
6064 for (i = 0; i < res->nbuckets; i++) {
6065 LOCK(&res->buckets[i].lock);
6066 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
6068 fctx = ISC_LIST_NEXT(fctx, link))
6069 fctx_shutdown(fctx);
6070 if (res->dispatchv4 != NULL) {
6071 sock = dns_dispatch_getsocket(res->dispatchv4);
6072 isc_socket_cancel(sock, res->buckets[i].task,
6073 ISC_SOCKCANCEL_ALL);
6075 if (res->dispatchv6 != NULL) {
6076 sock = dns_dispatch_getsocket(res->dispatchv6);
6077 isc_socket_cancel(sock, res->buckets[i].task,
6078 ISC_SOCKCANCEL_ALL);
6080 res->buckets[i].exiting = ISC_TRUE;
6081 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
6082 INSIST(res->activebuckets > 0);
6083 res->activebuckets--;
6085 UNLOCK(&res->buckets[i].lock);
6087 if (res->activebuckets == 0)
6088 send_shutdown_events(res);
6095 dns_resolver_detach(dns_resolver_t **resp) {
6096 dns_resolver_t *res;
6097 isc_boolean_t need_destroy = ISC_FALSE;
6099 REQUIRE(resp != NULL);
6101 REQUIRE(VALID_RESOLVER(res));
6107 INSIST(res->references > 0);
6109 if (res->references == 0) {
6110 INSIST(res->exiting && res->activebuckets == 0);
6111 need_destroy = ISC_TRUE;
6122 static inline isc_boolean_t
6123 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
6124 unsigned int options)
6126 if (fctx->type != type || fctx->options != options)
6128 return (dns_name_equal(&fctx->name, name));
6132 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
6133 char namebuf[DNS_NAME_FORMATSIZE];
6134 char typebuf[DNS_RDATATYPE_FORMATSIZE];
6135 int level = ISC_LOG_DEBUG(1);
6137 if (! isc_log_wouldlog(dns_lctx, level))
6140 dns_name_format(name, namebuf, sizeof(namebuf));
6141 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
6143 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6144 DNS_LOGMODULE_RESOLVER, level,
6145 "createfetch: %s %s", namebuf, typebuf);
6149 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
6150 dns_rdatatype_t type,
6151 dns_name_t *domain, dns_rdataset_t *nameservers,
6152 dns_forwarders_t *forwarders,
6153 unsigned int options, isc_task_t *task,
6154 isc_taskaction_t action, void *arg,
6155 dns_rdataset_t *rdataset,
6156 dns_rdataset_t *sigrdataset,
6157 dns_fetch_t **fetchp)
6160 fetchctx_t *fctx = NULL;
6161 isc_result_t result;
6162 unsigned int bucketnum;
6163 isc_boolean_t new_fctx = ISC_FALSE;
6168 REQUIRE(VALID_RESOLVER(res));
6169 REQUIRE(res->frozen);
6170 /* XXXRTH Check for meta type */
6171 if (domain != NULL) {
6172 REQUIRE(DNS_RDATASET_VALID(nameservers));
6173 REQUIRE(nameservers->type == dns_rdatatype_ns);
6175 REQUIRE(nameservers == NULL);
6176 REQUIRE(forwarders == NULL);
6177 REQUIRE(!dns_rdataset_isassociated(rdataset));
6178 REQUIRE(sigrdataset == NULL ||
6179 !dns_rdataset_isassociated(sigrdataset));
6180 REQUIRE(fetchp != NULL && *fetchp == NULL);
6182 log_fetch(name, type);
6185 * XXXRTH use a mempool?
6187 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
6189 return (ISC_R_NOMEMORY);
6191 bucketnum = dns_name_hash(name, ISC_FALSE) % res->nbuckets;
6193 LOCK(&res->buckets[bucketnum].lock);
6195 if (res->buckets[bucketnum].exiting) {
6196 result = ISC_R_SHUTTINGDOWN;
6200 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
6201 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
6203 fctx = ISC_LIST_NEXT(fctx, link)) {
6204 if (fctx_match(fctx, name, type, options))
6210 * If we didn't have a fetch, would attach to a done fetch, this
6211 * fetch has already cloned its results, or if the fetch has gone
6212 * "idle" (no one was interested in it), we need to start a new
6213 * fetch instead of joining with the existing one.
6216 fctx->state == fetchstate_done ||
6218 ISC_LIST_EMPTY(fctx->events)) {
6220 result = fctx_create(res, name, type, domain, nameservers,
6221 options, bucketnum, &fctx);
6222 if (result != ISC_R_SUCCESS)
6224 new_fctx = ISC_TRUE;
6227 result = fctx_join(fctx, task, action, arg,
6228 rdataset, sigrdataset, fetch);
6230 if (result == ISC_R_SUCCESS) {
6234 event = &fctx->control_event;
6235 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
6236 DNS_EVENT_FETCHCONTROL,
6237 fctx_start, fctx, NULL,
6239 isc_task_send(res->buckets[bucketnum].task, &event);
6242 * We don't care about the result of fctx_destroy()
6243 * since we know we're not exiting.
6245 (void)fctx_destroy(fctx);
6250 UNLOCK(&res->buckets[bucketnum].lock);
6252 if (result == ISC_R_SUCCESS) {
6256 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
6262 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
6264 dns_resolver_t *res;
6265 dns_fetchevent_t *event, *next_event;
6268 REQUIRE(DNS_FETCH_VALID(fetch));
6269 fctx = fetch->private;
6270 REQUIRE(VALID_FCTX(fctx));
6273 FTRACE("cancelfetch");
6275 LOCK(&res->buckets[fctx->bucketnum].lock);
6278 * Find the completion event for this fetch (as opposed
6279 * to those for other fetches that have joined the same
6280 * fctx) and send it with result = ISC_R_CANCELED.
6283 if (fctx->state != fetchstate_done) {
6284 for (event = ISC_LIST_HEAD(fctx->events);
6286 event = next_event) {
6287 next_event = ISC_LIST_NEXT(event, ev_link);
6288 if (event->fetch == fetch) {
6289 ISC_LIST_UNLINK(fctx->events, event, ev_link);
6294 if (event != NULL) {
6295 etask = event->ev_sender;
6296 event->ev_sender = fctx;
6297 event->result = ISC_R_CANCELED;
6298 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
6301 * The fctx continues running even if no fetches remain;
6302 * the answer is still cached.
6305 UNLOCK(&res->buckets[fctx->bucketnum].lock);
6309 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
6311 dns_resolver_t *res;
6312 dns_fetchevent_t *event, *next_event;
6314 unsigned int bucketnum;
6315 isc_boolean_t bucket_empty = ISC_FALSE;
6317 REQUIRE(fetchp != NULL);
6319 REQUIRE(DNS_FETCH_VALID(fetch));
6320 fctx = fetch->private;
6321 REQUIRE(VALID_FCTX(fctx));
6324 FTRACE("destroyfetch");
6326 bucketnum = fctx->bucketnum;
6327 LOCK(&res->buckets[bucketnum].lock);
6330 * Sanity check: the caller should have gotten its event before
6331 * trying to destroy the fetch.
6334 if (fctx->state != fetchstate_done) {
6335 for (event = ISC_LIST_HEAD(fctx->events);
6337 event = next_event) {
6338 next_event = ISC_LIST_NEXT(event, ev_link);
6339 RUNTIME_CHECK(event->fetch != fetch);
6343 INSIST(fctx->references > 0);
6345 if (fctx->references == 0) {
6347 * No one cares about the result of this fetch anymore.
6349 if (fctx->pending == 0 && ISC_LIST_EMPTY(fctx->validators) &&
6350 SHUTTINGDOWN(fctx)) {
6352 * This fctx is already shutdown; we were just
6353 * waiting for the last reference to go away.
6355 bucket_empty = fctx_destroy(fctx);
6358 * Initiate shutdown.
6360 fctx_shutdown(fctx);
6364 UNLOCK(&res->buckets[bucketnum].lock);
6366 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
6374 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
6375 REQUIRE(VALID_RESOLVER(resolver));
6376 return (resolver->dispatchmgr);
6380 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
6381 REQUIRE(VALID_RESOLVER(resolver));
6382 return (resolver->dispatchv4);
6386 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
6387 REQUIRE(VALID_RESOLVER(resolver));
6388 return (resolver->dispatchv6);
6392 dns_resolver_socketmgr(dns_resolver_t *resolver) {
6393 REQUIRE(VALID_RESOLVER(resolver));
6394 return (resolver->socketmgr);
6398 dns_resolver_taskmgr(dns_resolver_t *resolver) {
6399 REQUIRE(VALID_RESOLVER(resolver));
6400 return (resolver->taskmgr);
6404 dns_resolver_getlamettl(dns_resolver_t *resolver) {
6405 REQUIRE(VALID_RESOLVER(resolver));
6406 return (resolver->lame_ttl);
6410 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
6411 REQUIRE(VALID_RESOLVER(resolver));
6412 resolver->lame_ttl = lame_ttl;
6416 dns_resolver_nrunning(dns_resolver_t *resolver) {
6418 LOCK(&resolver->nlock);
6419 n = resolver->nfctx;
6420 UNLOCK(&resolver->nlock);
6425 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
6426 dns_name_t *name, in_port_t port) {
6428 isc_result_t result;
6430 REQUIRE(VALID_RESOLVER(resolver));
6431 REQUIRE(!resolver->frozen);
6432 REQUIRE((alt == NULL) ^ (name == NULL));
6434 a = isc_mem_get(resolver->mctx, sizeof(*a));
6436 return (ISC_R_NOMEMORY);
6438 a->isaddress = ISC_TRUE;
6441 a->isaddress = ISC_FALSE;
6442 a->_u._n.port = port;
6443 dns_name_init(&a->_u._n.name, NULL);
6444 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
6445 if (result != ISC_R_SUCCESS) {
6446 isc_mem_put(resolver->mctx, a, sizeof(*a));
6450 ISC_LINK_INIT(a, link);
6451 ISC_LIST_APPEND(resolver->alternates, a, link);
6453 return (ISC_R_SUCCESS);
6457 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
6458 REQUIRE(VALID_RESOLVER(resolver));
6459 resolver->udpsize = udpsize;
6463 dns_resolver_getudpsize(dns_resolver_t *resolver) {
6464 REQUIRE(VALID_RESOLVER(resolver));
6465 return (resolver->udpsize);
6469 free_algorithm(void *node, void *arg) {
6470 unsigned char *algorithms = node;
6471 isc_mem_t *mctx = arg;
6473 isc_mem_put(mctx, algorithms, *algorithms);
6477 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
6479 REQUIRE(VALID_RESOLVER(resolver));
6482 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
6484 if (resolver->algorithms != NULL)
6485 dns_rbt_destroy(&resolver->algorithms);
6487 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
6492 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
6495 unsigned int len, mask;
6497 unsigned char *algorithms;
6498 isc_result_t result;
6499 dns_rbtnode_t *node = NULL;
6501 REQUIRE(VALID_RESOLVER(resolver));
6503 return (ISC_R_RANGE);
6506 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
6508 if (resolver->algorithms == NULL) {
6509 result = dns_rbt_create(resolver->mctx, free_algorithm,
6510 resolver->mctx, &resolver->algorithms);
6511 if (result != ISC_R_SUCCESS)
6516 mask = 1 << (alg%8);
6518 result = dns_rbt_addnode(resolver->algorithms, name, &node);
6520 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
6521 algorithms = node->data;
6522 if (algorithms == NULL || len > *algorithms) {
6523 new = isc_mem_get(resolver->mctx, len);
6525 result = ISC_R_NOMEMORY;
6528 memset(new, 0, len);
6529 if (algorithms != NULL)
6530 memcpy(new, algorithms, *algorithms);
6534 if (algorithms != NULL)
6535 isc_mem_put(resolver->mctx, algorithms,
6538 algorithms[len-1] |= mask;
6540 result = ISC_R_SUCCESS;
6543 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
6549 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
6552 unsigned int len, mask;
6553 unsigned char *algorithms;
6555 isc_result_t result;
6556 isc_boolean_t found = ISC_FALSE;
6558 REQUIRE(VALID_RESOLVER(resolver));
6561 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
6563 if (resolver->algorithms == NULL)
6565 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
6566 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
6568 mask = 1 << (alg%8);
6570 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
6575 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
6579 return (dst_algorithm_supported(alg));
6583 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
6585 REQUIRE(VALID_RESOLVER(resolver));
6588 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
6590 if (resolver->mustbesecure != NULL)
6591 dns_rbt_destroy(&resolver->mustbesecure);
6593 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
6597 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
6600 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
6601 isc_boolean_t value)
6603 isc_result_t result;
6605 REQUIRE(VALID_RESOLVER(resolver));
6608 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
6610 if (resolver->mustbesecure == NULL) {
6611 result = dns_rbt_create(resolver->mctx, NULL, NULL,
6612 &resolver->mustbesecure);
6613 if (result != ISC_R_SUCCESS)
6616 result = dns_rbt_addname(resolver->mustbesecure, name,
6617 value ? &yes : &no);
6620 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
6626 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
6628 isc_boolean_t value = ISC_FALSE;
6629 isc_result_t result;
6631 REQUIRE(VALID_RESOLVER(resolver));
6634 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
6636 if (resolver->mustbesecure == NULL)
6638 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
6639 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
6640 value = *(isc_boolean_t*)data;
6643 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);