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