2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: resolver.c,v 1.218.2.18.4.64.4.2 2007/01/11 05:05:10 marka Exp $ */
22 #include <isc/print.h>
23 #include <isc/string.h>
25 #include <isc/timer.h>
30 #include <dns/cache.h>
32 #include <dns/dispatch.h>
34 #include <dns/events.h>
35 #include <dns/forward.h>
36 #include <dns/keytable.h>
38 #include <dns/message.h>
39 #include <dns/ncache.h>
40 #include <dns/opcode.h>
43 #include <dns/rcode.h>
44 #include <dns/rdata.h>
45 #include <dns/rdataclass.h>
46 #include <dns/rdatalist.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatastruct.h>
49 #include <dns/rdatatype.h>
50 #include <dns/resolver.h>
51 #include <dns/result.h>
52 #include <dns/rootns.h>
54 #include <dns/validator.h>
56 #define DNS_RESOLVER_TRACE
57 #ifdef DNS_RESOLVER_TRACE
58 #define RTRACE(m) isc_log_write(dns_lctx, \
59 DNS_LOGCATEGORY_RESOLVER, \
60 DNS_LOGMODULE_RESOLVER, \
62 "res %p: %s", res, (m))
63 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
64 DNS_LOGCATEGORY_RESOLVER, \
65 DNS_LOGMODULE_RESOLVER, \
67 "res %p: %s", (r), (m))
68 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
69 DNS_LOGCATEGORY_RESOLVER, \
70 DNS_LOGMODULE_RESOLVER, \
72 "fctx %p(%s'): %s", fctx, fctx->info, (m))
73 #define FCTXTRACE2(m1, m2) \
74 isc_log_write(dns_lctx, \
75 DNS_LOGCATEGORY_RESOLVER, \
76 DNS_LOGMODULE_RESOLVER, \
78 "fctx %p(%s): %s %s", \
79 fctx, fctx->info, (m1), (m2))
80 #define FTRACE(m) isc_log_write(dns_lctx, \
81 DNS_LOGCATEGORY_RESOLVER, \
82 DNS_LOGMODULE_RESOLVER, \
84 "fetch %p (fctx %p(%s)): %s", \
85 fetch, fetch->private, \
86 fetch->private->info, (m))
87 #define QTRACE(m) isc_log_write(dns_lctx, \
88 DNS_LOGCATEGORY_RESOLVER, \
89 DNS_LOGMODULE_RESOLVER, \
91 "resquery %p (fctx %p(%s)): %s", \
93 query->fctx->info, (m))
103 * Maximum EDNS0 input packet size.
105 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
108 * This defines the maximum number of timeouts we will permit before we
109 * disable EDNS0 on the query.
111 #define MAX_EDNS0_TIMEOUTS 3
113 typedef struct fetchctx fetchctx_t
;
115 typedef struct query
{
116 /* Locked by task event serialization. */
120 dns_dispatchmgr_t
* dispatchmgr
;
121 dns_dispatch_t
* dispatch
;
122 dns_adbaddrinfo_t
* addrinfo
;
123 isc_socket_t
* tcpsocket
;
126 dns_dispentry_t
* dispentry
;
127 ISC_LINK(struct query
) link
;
130 dns_tsigkey_t
*tsigkey
;
131 unsigned int options
;
132 unsigned int attributes
;
134 unsigned int connects
;
135 unsigned char data
[512];
138 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
139 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
141 #define RESQUERY_ATTR_CANCELED 0x02
143 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
144 #define RESQUERY_CANCELED(q) (((q)->attributes & \
145 RESQUERY_ATTR_CANCELED) != 0)
146 #define RESQUERY_SENDING(q) ((q)->sends > 0)
149 fetchstate_init
= 0, /* Start event has not run yet. */
151 fetchstate_done
/* FETCHDONE events posted. */
157 dns_resolver_t
* res
;
159 dns_rdatatype_t type
;
160 unsigned int options
;
161 unsigned int bucketnum
;
163 /* Locked by appropriate bucket lock. */
165 isc_boolean_t want_shutdown
;
166 isc_boolean_t cloned
;
167 unsigned int references
;
168 isc_event_t control_event
;
169 ISC_LINK(struct fetchctx
) link
;
170 ISC_LIST(dns_fetchevent_t
) events
;
171 /* Locked by task event serialization. */
173 dns_rdataset_t nameservers
;
174 unsigned int attributes
;
177 isc_interval_t interval
;
178 dns_message_t
* qmessage
;
179 dns_message_t
* rmessage
;
180 ISC_LIST(resquery_t
) queries
;
181 dns_adbfindlist_t finds
;
182 dns_adbfind_t
* find
;
183 dns_adbfindlist_t altfinds
;
184 dns_adbfind_t
* altfind
;
185 dns_adbaddrinfolist_t forwaddrs
;
186 dns_adbaddrinfolist_t altaddrs
;
187 isc_sockaddrlist_t forwarders
;
188 dns_fwdpolicy_t fwdpolicy
;
189 isc_sockaddrlist_t bad
;
190 ISC_LIST(dns_validator_t
) validators
;
195 * The number of events we're waiting for.
197 unsigned int pending
;
200 * The number of times we've "restarted" the current
201 * nameserver set. This acts as a failsafe to prevent
202 * us from pounding constantly on a particular set of
203 * servers that, for whatever reason, are not giving
204 * us useful responses, but are responding in such a
205 * way that they are not marked "bad".
207 unsigned int restarts
;
210 * The number of timeouts that have occurred since we
211 * last successfully received a response packet. This
212 * is used for EDNS0 black hole detection.
214 unsigned int timeouts
;
216 * Look aside state for DS lookups.
219 dns_fetch_t
* nsfetch
;
220 dns_rdataset_t nsrrset
;
223 * Number of queries that reference this context.
225 unsigned int nqueries
;
228 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
229 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
231 #define FCTX_ATTR_HAVEANSWER 0x0001
232 #define FCTX_ATTR_GLUING 0x0002
233 #define FCTX_ATTR_ADDRWAIT 0x0004
234 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
235 #define FCTX_ATTR_WANTCACHE 0x0010
236 #define FCTX_ATTR_WANTNCACHE 0x0020
237 #define FCTX_ATTR_NEEDEDNS0 0x0040
238 #define FCTX_ATTR_TRIEDFIND 0x0080
239 #define FCTX_ATTR_TRIEDALT 0x0100
241 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
243 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
245 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
247 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
249 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
250 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
251 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
252 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
253 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
256 dns_adbaddrinfo_t
* addrinfo
;
262 fetchctx_t
* private;
265 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
266 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
268 typedef struct fctxbucket
{
271 ISC_LIST(fetchctx_t
) fctxs
;
272 isc_boolean_t exiting
;
275 typedef struct alternate
{
276 isc_boolean_t isaddress
;
284 ISC_LINK(struct alternate
) link
;
287 struct dns_resolver
{
293 isc_mutex_t primelock
;
294 dns_rdataclass_t rdclass
;
295 isc_socketmgr_t
* socketmgr
;
296 isc_timermgr_t
* timermgr
;
297 isc_taskmgr_t
* taskmgr
;
299 isc_boolean_t frozen
;
300 unsigned int options
;
301 dns_dispatchmgr_t
* dispatchmgr
;
302 dns_dispatch_t
* dispatchv4
;
303 dns_dispatch_t
* dispatchv6
;
304 unsigned int nbuckets
;
305 fctxbucket_t
* buckets
;
306 isc_uint32_t lame_ttl
;
307 ISC_LIST(alternate_t
) alternates
;
308 isc_uint16_t udpsize
;
310 isc_rwlock_t alglock
;
312 dns_rbt_t
* algorithms
;
314 isc_rwlock_t mbslock
;
316 dns_rbt_t
* mustbesecure
;
317 /* Locked by lock. */
318 unsigned int references
;
319 isc_boolean_t exiting
;
320 isc_eventlist_t whenshutdown
;
321 unsigned int activebuckets
;
322 isc_boolean_t priming
;
323 /* Locked by primelock. */
324 dns_fetch_t
* primefetch
;
325 /* Locked by nlock. */
329 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
330 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
333 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
334 * which we also use as an addrinfo flag.
336 #define FCTX_ADDRINFO_MARK 0x0001
337 #define FCTX_ADDRINFO_FORWARDER 0x1000
338 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
340 #define ISFORWARDER(a) (((a)->flags & \
341 FCTX_ADDRINFO_FORWARDER) != 0)
343 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
345 static void destroy(dns_resolver_t
*res
);
346 static void empty_bucket(dns_resolver_t
*res
);
347 static isc_result_t
resquery_send(resquery_t
*query
);
348 static void resquery_response(isc_task_t
*task
, isc_event_t
*event
);
349 static void resquery_connected(isc_task_t
*task
, isc_event_t
*event
);
350 static void fctx_try(fetchctx_t
*fctx
);
351 static isc_boolean_t
fctx_destroy(fetchctx_t
*fctx
);
352 static isc_result_t
ncache_adderesult(dns_message_t
*message
,
353 dns_db_t
*cache
, dns_dbnode_t
*node
,
354 dns_rdatatype_t covers
,
355 isc_stdtime_t now
, dns_ttl_t maxttl
,
356 dns_rdataset_t
*ardataset
,
357 isc_result_t
*eresultp
);
358 static void validated(isc_task_t
*task
, isc_event_t
*event
);
359 static void maybe_destroy(fetchctx_t
*fctx
);
362 valcreate(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, dns_name_t
*name
,
363 dns_rdatatype_t type
, dns_rdataset_t
*rdataset
,
364 dns_rdataset_t
*sigrdataset
, unsigned int valoptions
,
367 dns_validator_t
*validator
= NULL
;
368 dns_valarg_t
*valarg
;
371 valarg
= isc_mem_get(fctx
->res
->mctx
, sizeof(*valarg
));
373 return (ISC_R_NOMEMORY
);
376 valarg
->addrinfo
= addrinfo
;
378 if (!ISC_LIST_EMPTY(fctx
->validators
))
379 INSIST((valoptions
& DNS_VALIDATOR_DEFER
) != 0);
381 result
= dns_validator_create(fctx
->res
->view
, name
, type
, rdataset
,
382 sigrdataset
, fctx
->rmessage
,
383 valoptions
, task
, validated
, valarg
,
385 if (result
== ISC_R_SUCCESS
)
386 ISC_LIST_APPEND(fctx
->validators
, validator
, link
);
388 isc_mem_put(fctx
->res
->mctx
, valarg
, sizeof(*valarg
));
393 fix_mustbedelegationornxdomain(dns_message_t
*message
, fetchctx_t
*fctx
) {
395 dns_name_t
*domain
= &fctx
->domain
;
396 dns_rdataset_t
*rdataset
;
397 dns_rdatatype_t type
;
399 isc_boolean_t keep_auth
= ISC_FALSE
;
401 if (message
->rcode
== dns_rcode_nxdomain
)
405 * Look for BIND 8 style delegations.
406 * Also look for answers to ANY queries where the duplicate NS RRset
407 * may have been stripped from the authority section.
409 if (message
->counts
[DNS_SECTION_ANSWER
] != 0 &&
410 (fctx
->type
== dns_rdatatype_ns
||
411 fctx
->type
== dns_rdatatype_any
)) {
412 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
413 while (result
== ISC_R_SUCCESS
) {
415 dns_message_currentname(message
, DNS_SECTION_ANSWER
,
417 for (rdataset
= ISC_LIST_HEAD(name
->list
);
419 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
420 type
= rdataset
->type
;
421 if (type
!= dns_rdatatype_ns
)
423 if (dns_name_issubdomain(name
, domain
))
426 result
= dns_message_nextname(message
,
431 /* Look for referral. */
432 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
435 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
436 while (result
== ISC_R_SUCCESS
) {
438 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
439 for (rdataset
= ISC_LIST_HEAD(name
->list
);
441 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
442 type
= rdataset
->type
;
443 if (type
== dns_rdatatype_soa
&&
444 dns_name_equal(name
, domain
))
445 keep_auth
= ISC_TRUE
;
446 if (type
!= dns_rdatatype_ns
&&
447 type
!= dns_rdatatype_soa
)
449 if (dns_name_equal(name
, domain
))
451 if (dns_name_issubdomain(name
, domain
))
454 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
458 message
->rcode
= dns_rcode_nxdomain
;
459 message
->counts
[DNS_SECTION_ANSWER
] = 0;
461 message
->counts
[DNS_SECTION_AUTHORITY
] = 0;
462 message
->counts
[DNS_SECTION_ADDITIONAL
] = 0;
466 static inline isc_result_t
467 fctx_starttimer(fetchctx_t
*fctx
) {
469 * Start the lifetime timer for fctx.
471 * This is also used for stopping the idle timer; in that
472 * case we must purge events already posted to ensure that
473 * no further idle events are delivered.
475 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
476 &fctx
->expires
, NULL
, ISC_TRUE
));
480 fctx_stoptimer(fetchctx_t
*fctx
) {
484 * We don't return a result if resetting the timer to inactive fails
485 * since there's nothing to be done about it. Resetting to inactive
486 * should never fail anyway, since the code as currently written
487 * cannot fail in that case.
489 result
= isc_timer_reset(fctx
->timer
, isc_timertype_inactive
,
490 NULL
, NULL
, ISC_TRUE
);
491 if (result
!= ISC_R_SUCCESS
) {
492 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
493 "isc_timer_reset(): %s",
494 isc_result_totext(result
));
499 static inline isc_result_t
500 fctx_startidletimer(fetchctx_t
*fctx
) {
502 * Start the idle timer for fctx. The lifetime timer continues
505 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
506 &fctx
->expires
, &fctx
->interval
,
511 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
512 * we use fctx_stopidletimer for readability in the code below.
514 #define fctx_stopidletimer fctx_starttimer
518 resquery_destroy(resquery_t
**queryp
) {
521 REQUIRE(queryp
!= NULL
);
523 REQUIRE(!ISC_LINK_LINKED(query
, link
));
525 INSIST(query
->tcpsocket
== NULL
);
527 query
->fctx
->nqueries
--;
528 if (SHUTTINGDOWN(query
->fctx
))
529 maybe_destroy(query
->fctx
); /* Locks bucket. */
531 isc_mem_put(query
->mctx
, query
, sizeof(*query
));
536 fctx_cancelquery(resquery_t
**queryp
, dns_dispatchevent_t
**deventp
,
537 isc_time_t
*finish
, isc_boolean_t no_response
)
544 dns_adbaddrinfo_t
*addrinfo
;
549 FCTXTRACE("cancelquery");
551 REQUIRE(!RESQUERY_CANCELED(query
));
553 query
->attributes
|= RESQUERY_ATTR_CANCELED
;
556 * Should we update the RTT?
558 if (finish
!= NULL
|| no_response
) {
559 if (finish
!= NULL
) {
561 * We have both the start and finish times for this
562 * packet, so we can compute a real RTT.
564 rtt
= (unsigned int)isc_time_microdiff(finish
,
566 factor
= DNS_ADB_RTTADJDEFAULT
;
569 * We don't have an RTT for this query. Maybe the
570 * packet was lost, or maybe this server is very
571 * slow. We don't know. Increase the RTT.
574 rtt
= query
->addrinfo
->srtt
+
575 (200000 * fctx
->restarts
);
579 * Replace the current RTT with our value.
581 factor
= DNS_ADB_RTTADJREPLACE
;
583 dns_adb_adjustsrtt(fctx
->adb
, query
->addrinfo
, rtt
, factor
);
587 * Age RTTs of servers not tried.
589 factor
= DNS_ADB_RTTADJAGE
;
591 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
593 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
594 if (UNMARKED(addrinfo
))
595 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
598 if (finish
!= NULL
&& TRIEDFIND(fctx
))
599 for (find
= ISC_LIST_HEAD(fctx
->finds
);
601 find
= ISC_LIST_NEXT(find
, publink
))
602 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
604 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
605 if (UNMARKED(addrinfo
))
606 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
609 if (finish
!= NULL
&& TRIEDALT(fctx
)) {
610 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
612 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
613 if (UNMARKED(addrinfo
))
614 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
616 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
618 find
= ISC_LIST_NEXT(find
, publink
))
619 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
621 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
622 if (UNMARKED(addrinfo
))
623 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
627 if (query
->dispentry
!= NULL
)
628 dns_dispatch_removeresponse(&query
->dispentry
, deventp
);
630 ISC_LIST_UNLINK(fctx
->queries
, query
, link
);
632 if (query
->tsig
!= NULL
)
633 isc_buffer_free(&query
->tsig
);
635 if (query
->tsigkey
!= NULL
)
636 dns_tsigkey_detach(&query
->tsigkey
);
639 * Check for any outstanding socket events. If they exist, cancel
640 * them and let the event handlers finish the cleanup. The resolver
641 * only needs to worry about managing the connect and send events;
642 * the dispatcher manages the recv events.
644 if (RESQUERY_CONNECTING(query
))
646 * Cancel the connect.
648 isc_socket_cancel(query
->tcpsocket
, NULL
,
649 ISC_SOCKCANCEL_CONNECT
);
650 else if (RESQUERY_SENDING(query
))
652 * Cancel the pending send.
654 isc_socket_cancel(dns_dispatch_getsocket(query
->dispatch
),
655 NULL
, ISC_SOCKCANCEL_SEND
);
657 if (query
->dispatch
!= NULL
)
658 dns_dispatch_detach(&query
->dispatch
);
660 if (! (RESQUERY_CONNECTING(query
) || RESQUERY_SENDING(query
)))
662 * It's safe to destroy the query now.
664 resquery_destroy(&query
);
668 fctx_cancelqueries(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
669 resquery_t
*query
, *next_query
;
671 FCTXTRACE("cancelqueries");
673 for (query
= ISC_LIST_HEAD(fctx
->queries
);
675 query
= next_query
) {
676 next_query
= ISC_LIST_NEXT(query
, link
);
677 fctx_cancelquery(&query
, NULL
, NULL
, no_response
);
682 fctx_cleanupfinds(fetchctx_t
*fctx
) {
683 dns_adbfind_t
*find
, *next_find
;
685 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
687 for (find
= ISC_LIST_HEAD(fctx
->finds
);
690 next_find
= ISC_LIST_NEXT(find
, publink
);
691 ISC_LIST_UNLINK(fctx
->finds
, find
, publink
);
692 dns_adb_destroyfind(&find
);
698 fctx_cleanupaltfinds(fetchctx_t
*fctx
) {
699 dns_adbfind_t
*find
, *next_find
;
701 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
703 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
706 next_find
= ISC_LIST_NEXT(find
, publink
);
707 ISC_LIST_UNLINK(fctx
->altfinds
, find
, publink
);
708 dns_adb_destroyfind(&find
);
710 fctx
->altfind
= NULL
;
714 fctx_cleanupforwaddrs(fetchctx_t
*fctx
) {
715 dns_adbaddrinfo_t
*addr
, *next_addr
;
717 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
719 for (addr
= ISC_LIST_HEAD(fctx
->forwaddrs
);
722 next_addr
= ISC_LIST_NEXT(addr
, publink
);
723 ISC_LIST_UNLINK(fctx
->forwaddrs
, addr
, publink
);
724 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
729 fctx_cleanupaltaddrs(fetchctx_t
*fctx
) {
730 dns_adbaddrinfo_t
*addr
, *next_addr
;
732 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
734 for (addr
= ISC_LIST_HEAD(fctx
->altaddrs
);
737 next_addr
= ISC_LIST_NEXT(addr
, publink
);
738 ISC_LIST_UNLINK(fctx
->altaddrs
, addr
, publink
);
739 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
744 fctx_stopeverything(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
745 FCTXTRACE("stopeverything");
746 fctx_cancelqueries(fctx
, no_response
);
747 fctx_cleanupfinds(fctx
);
748 fctx_cleanupaltfinds(fctx
);
749 fctx_cleanupforwaddrs(fctx
);
750 fctx_cleanupaltaddrs(fctx
);
751 fctx_stoptimer(fctx
);
755 fctx_sendevents(fetchctx_t
*fctx
, isc_result_t result
) {
756 dns_fetchevent_t
*event
, *next_event
;
760 * Caller must be holding the appropriate bucket lock.
762 REQUIRE(fctx
->state
== fetchstate_done
);
764 FCTXTRACE("sendevents");
766 for (event
= ISC_LIST_HEAD(fctx
->events
);
768 event
= next_event
) {
769 next_event
= ISC_LIST_NEXT(event
, ev_link
);
770 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
771 task
= event
->ev_sender
;
772 event
->ev_sender
= fctx
;
773 if (!HAVE_ANSWER(fctx
))
774 event
->result
= result
;
776 INSIST(result
!= ISC_R_SUCCESS
||
777 dns_rdataset_isassociated(event
->rdataset
) ||
778 fctx
->type
== dns_rdatatype_any
||
779 fctx
->type
== dns_rdatatype_rrsig
||
780 fctx
->type
== dns_rdatatype_sig
);
782 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&event
));
787 fctx_done(fetchctx_t
*fctx
, isc_result_t result
) {
789 isc_boolean_t no_response
;
795 if (result
== ISC_R_SUCCESS
)
796 no_response
= ISC_TRUE
;
798 no_response
= ISC_FALSE
;
799 fctx_stopeverything(fctx
, no_response
);
801 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
803 fctx
->state
= fetchstate_done
;
804 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
805 fctx_sendevents(fctx
, result
);
807 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
811 resquery_senddone(isc_task_t
*task
, isc_event_t
*event
) {
812 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
813 resquery_t
*query
= event
->ev_arg
;
814 isc_boolean_t retry
= ISC_FALSE
;
818 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
825 * Currently we don't wait for the senddone event before retrying
826 * a query. This means that if we get really behind, we may end
827 * up doing extra work!
832 INSIST(RESQUERY_SENDING(query
));
837 if (RESQUERY_CANCELED(query
)) {
838 if (query
->sends
== 0) {
840 * This query was canceled while the
841 * isc_socket_sendto() was in progress.
843 if (query
->tcpsocket
!= NULL
)
844 isc_socket_detach(&query
->tcpsocket
);
845 resquery_destroy(&query
);
848 switch (sevent
->result
) {
852 case ISC_R_HOSTUNREACH
:
853 case ISC_R_NETUNREACH
:
855 case ISC_R_ADDRNOTAVAIL
:
856 case ISC_R_CONNREFUSED
:
859 * No route to remote.
861 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
866 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
870 isc_event_free(&event
);
874 * Behave as if the idle timer has expired. For TCP
875 * this may not actually reflect the latest timer.
877 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
878 result
= fctx_stopidletimer(fctx
);
879 if (result
!= ISC_R_SUCCESS
)
880 fctx_done(fctx
, result
);
886 static inline isc_result_t
887 fctx_addopt(dns_message_t
*message
, dns_resolver_t
*res
) {
888 dns_rdataset_t
*rdataset
;
889 dns_rdatalist_t
*rdatalist
;
894 result
= dns_message_gettemprdatalist(message
, &rdatalist
);
895 if (result
!= ISC_R_SUCCESS
)
898 result
= dns_message_gettemprdata(message
, &rdata
);
899 if (result
!= ISC_R_SUCCESS
)
902 result
= dns_message_gettemprdataset(message
, &rdataset
);
903 if (result
!= ISC_R_SUCCESS
)
905 dns_rdataset_init(rdataset
);
907 rdatalist
->type
= dns_rdatatype_opt
;
908 rdatalist
->covers
= 0;
911 * Set Maximum UDP buffer size.
913 rdatalist
->rdclass
= res
->udpsize
;
916 * Set EXTENDED-RCODE, VERSION, and Z to 0, and the DO bit to 1.
918 rdatalist
->ttl
= DNS_MESSAGEEXTFLAG_DO
;
925 rdata
->rdclass
= rdatalist
->rdclass
;
926 rdata
->type
= rdatalist
->type
;
929 ISC_LIST_INIT(rdatalist
->rdata
);
930 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
931 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
) == ISC_R_SUCCESS
);
933 return (dns_message_setopt(message
, rdataset
));
937 fctx_setretryinterval(fetchctx_t
*fctx
, unsigned int rtt
) {
938 unsigned int seconds
;
941 * We retry every 2 seconds the first two times through the address
942 * list, and then we do exponential back-off.
944 if (fctx
->restarts
< 3)
947 seconds
= (2 << (fctx
->restarts
- 1));
950 * Double the round-trip time and convert to seconds.
955 * Always wait for at least the doubled round-trip time.
961 * But don't ever wait for more than 30 seconds.
966 isc_interval_set(&fctx
->interval
, seconds
, 0);
970 fctx_query(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
971 unsigned int options
)
981 task
= res
->buckets
[fctx
->bucketnum
].task
;
983 fctx_setretryinterval(fctx
, addrinfo
->srtt
);
984 result
= fctx_startidletimer(fctx
);
985 if (result
!= ISC_R_SUCCESS
)
988 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
990 dns_message_reset(fctx
->rmessage
, DNS_MESSAGE_INTENTPARSE
);
992 query
= isc_mem_get(res
->mctx
, sizeof(*query
));
994 result
= ISC_R_NOMEMORY
;
995 goto stop_idle_timer
;
997 query
->mctx
= res
->mctx
;
998 query
->options
= options
;
999 query
->attributes
= 0;
1001 query
->connects
= 0;
1003 * Note that the caller MUST guarantee that 'addrinfo' will remain
1004 * valid until this query is canceled.
1006 query
->addrinfo
= addrinfo
;
1007 TIME_NOW(&query
->start
);
1010 * If this is a TCP query, then we need to make a socket and
1011 * a dispatch for it here. Otherwise we use the resolver's
1014 query
->dispatchmgr
= res
->dispatchmgr
;
1015 query
->dispatch
= NULL
;
1016 query
->tcpsocket
= NULL
;
1017 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1018 isc_sockaddr_t addr
;
1021 pf
= isc_sockaddr_pf(&addrinfo
->sockaddr
);
1025 result
= dns_dispatch_getlocaladdress(res
->dispatchv4
,
1029 result
= dns_dispatch_getlocaladdress(res
->dispatchv6
,
1033 result
= ISC_R_NOTIMPLEMENTED
;
1036 if (result
!= ISC_R_SUCCESS
)
1039 isc_sockaddr_setport(&addr
, 0);
1041 result
= isc_socket_create(res
->socketmgr
, pf
,
1044 if (result
!= ISC_R_SUCCESS
)
1047 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1048 result
= isc_socket_bind(query
->tcpsocket
, &addr
);
1049 if (result
!= ISC_R_SUCCESS
)
1050 goto cleanup_socket
;
1054 * A dispatch will be created once the connect succeeds.
1057 switch (isc_sockaddr_pf(&addrinfo
->sockaddr
)) {
1059 dns_dispatch_attach(res
->dispatchv4
, &query
->dispatch
);
1062 dns_dispatch_attach(res
->dispatchv6
, &query
->dispatch
);
1065 result
= ISC_R_NOTIMPLEMENTED
;
1069 * We should always have a valid dispatcher here. If we
1070 * don't support a protocol family, then its dispatcher
1071 * will be NULL, but we shouldn't be finding addresses for
1072 * protocol types we don't support, so the dispatcher
1073 * we found should never be NULL.
1075 INSIST(query
->dispatch
!= NULL
);
1078 query
->dispentry
= NULL
;
1081 query
->tsigkey
= NULL
;
1082 ISC_LINK_INIT(query
, link
);
1083 query
->magic
= QUERY_MAGIC
;
1085 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1087 * Connect to the remote server.
1089 * XXXRTH Should we attach to the socket?
1091 result
= isc_socket_connect(query
->tcpsocket
,
1092 &addrinfo
->sockaddr
, task
,
1093 resquery_connected
, query
);
1094 if (result
!= ISC_R_SUCCESS
)
1095 goto cleanup_socket
;
1097 QTRACE("connecting via TCP");
1099 result
= resquery_send(query
);
1100 if (result
!= ISC_R_SUCCESS
)
1101 goto cleanup_dispatch
;
1104 ISC_LIST_APPEND(fctx
->queries
, query
, link
);
1105 query
->fctx
->nqueries
++;
1107 return (ISC_R_SUCCESS
);
1110 isc_socket_detach(&query
->tcpsocket
);
1113 if (query
->dispatch
!= NULL
)
1114 dns_dispatch_detach(&query
->dispatch
);
1118 isc_mem_put(res
->mctx
, query
, sizeof(*query
));
1121 RUNTIME_CHECK(fctx_stopidletimer(fctx
) == ISC_R_SUCCESS
);
1127 resquery_send(resquery_t
*query
) {
1129 isc_result_t result
;
1130 dns_name_t
*qname
= NULL
;
1131 dns_rdataset_t
*qrdataset
= NULL
;
1133 dns_resolver_t
*res
;
1135 isc_socket_t
*socket
;
1136 isc_buffer_t tcpbuffer
;
1137 isc_sockaddr_t
*address
;
1138 isc_buffer_t
*buffer
;
1139 isc_netaddr_t ipaddr
;
1140 dns_tsigkey_t
*tsigkey
= NULL
;
1141 dns_peer_t
*peer
= NULL
;
1142 isc_boolean_t useedns
;
1143 dns_compress_t cctx
;
1144 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
1145 isc_boolean_t secure_domain
;
1151 task
= res
->buckets
[fctx
->bucketnum
].task
;
1154 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1156 * Reserve space for the TCP message length.
1158 isc_buffer_init(&tcpbuffer
, query
->data
, sizeof(query
->data
));
1159 isc_buffer_init(&query
->buffer
, query
->data
+ 2,
1160 sizeof(query
->data
) - 2);
1161 buffer
= &tcpbuffer
;
1163 isc_buffer_init(&query
->buffer
, query
->data
,
1164 sizeof(query
->data
));
1165 buffer
= &query
->buffer
;
1168 result
= dns_message_gettempname(fctx
->qmessage
, &qname
);
1169 if (result
!= ISC_R_SUCCESS
)
1171 result
= dns_message_gettemprdataset(fctx
->qmessage
, &qrdataset
);
1172 if (result
!= ISC_R_SUCCESS
)
1176 * Get a query id from the dispatch.
1178 result
= dns_dispatch_addresponse(query
->dispatch
,
1179 &query
->addrinfo
->sockaddr
,
1185 if (result
!= ISC_R_SUCCESS
)
1188 fctx
->qmessage
->opcode
= dns_opcode_query
;
1193 dns_name_init(qname
, NULL
);
1194 dns_name_clone(&fctx
->name
, qname
);
1195 dns_rdataset_init(qrdataset
);
1196 dns_rdataset_makequestion(qrdataset
, res
->rdclass
, fctx
->type
);
1197 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
1198 dns_message_addname(fctx
->qmessage
, qname
, DNS_SECTION_QUESTION
);
1203 * Set RD if the client has requested that we do a recursive query,
1204 * or if we're sending to a forwarder.
1206 if ((query
->options
& DNS_FETCHOPT_RECURSIVE
) != 0 ||
1207 ISFORWARDER(query
->addrinfo
))
1208 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_RD
;
1211 * Set CD if the client says don't validate or the question is
1212 * under a secure entry point.
1214 if ((query
->options
& DNS_FETCHOPT_NOVALIDATE
) == 0) {
1215 result
= dns_keytable_issecuredomain(res
->view
->secroots
,
1218 if (result
!= ISC_R_SUCCESS
)
1219 secure_domain
= ISC_FALSE
;
1220 if (res
->view
->dlv
!= NULL
)
1221 secure_domain
= ISC_TRUE
;
1223 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1225 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1228 * We don't have to set opcode because it defaults to query.
1230 fctx
->qmessage
->id
= query
->id
;
1233 * Convert the question to wire format.
1235 result
= dns_compress_init(&cctx
, -1, fctx
->res
->mctx
);
1236 if (result
!= ISC_R_SUCCESS
)
1237 goto cleanup_message
;
1238 cleanup_cctx
= ISC_TRUE
;
1240 result
= dns_message_renderbegin(fctx
->qmessage
, &cctx
,
1242 if (result
!= ISC_R_SUCCESS
)
1243 goto cleanup_message
;
1245 result
= dns_message_rendersection(fctx
->qmessage
,
1246 DNS_SECTION_QUESTION
, 0);
1247 if (result
!= ISC_R_SUCCESS
)
1248 goto cleanup_message
;
1251 isc_netaddr_fromsockaddr(&ipaddr
, &query
->addrinfo
->sockaddr
);
1252 (void) dns_peerlist_peerbyaddr(fctx
->res
->view
->peers
, &ipaddr
, &peer
);
1255 * The ADB does not know about servers with "edns no". Check this,
1256 * and then inform the ADB for future use.
1258 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0 &&
1260 dns_peer_getsupportedns(peer
, &useedns
) == ISC_R_SUCCESS
&&
1263 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1264 dns_adb_changeflags(fctx
->adb
,
1266 DNS_FETCHOPT_NOEDNS0
,
1267 DNS_FETCHOPT_NOEDNS0
);
1271 * Use EDNS0, unless the caller doesn't want it, or we know that
1272 * the remote server doesn't like it.
1274 if (fctx
->timeouts
>= MAX_EDNS0_TIMEOUTS
&&
1275 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1276 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1277 FCTXTRACE("too many timeouts, disabling EDNS0");
1280 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1281 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1282 result
= fctx_addopt(fctx
->qmessage
, res
);
1283 if (result
!= ISC_R_SUCCESS
) {
1285 * We couldn't add the OPT, but we'll press on.
1286 * We're not using EDNS0, so set the NOEDNS0
1289 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1293 * We know this server doesn't like EDNS0, so we
1294 * won't use it. Set the NOEDNS0 bit since we're
1297 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1302 * If we need EDNS0 to do this query and aren't using it, we lose.
1304 if (NEEDEDNS0(fctx
) && (query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0) {
1305 result
= DNS_R_SERVFAIL
;
1306 goto cleanup_message
;
1310 * Clear CD if EDNS is not in use.
1312 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0)
1313 fctx
->qmessage
->flags
&= ~DNS_MESSAGEFLAG_CD
;
1316 * Add TSIG record tailored to the current recipient.
1318 result
= dns_view_getpeertsig(fctx
->res
->view
, &ipaddr
, &tsigkey
);
1319 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
1320 goto cleanup_message
;
1322 if (tsigkey
!= NULL
) {
1323 result
= dns_message_settsigkey(fctx
->qmessage
, tsigkey
);
1324 dns_tsigkey_detach(&tsigkey
);
1325 if (result
!= ISC_R_SUCCESS
)
1326 goto cleanup_message
;
1329 result
= dns_message_rendersection(fctx
->qmessage
,
1330 DNS_SECTION_ADDITIONAL
, 0);
1331 if (result
!= ISC_R_SUCCESS
)
1332 goto cleanup_message
;
1334 result
= dns_message_renderend(fctx
->qmessage
);
1335 if (result
!= ISC_R_SUCCESS
)
1336 goto cleanup_message
;
1338 dns_compress_invalidate(&cctx
);
1339 cleanup_cctx
= ISC_FALSE
;
1341 if (dns_message_gettsigkey(fctx
->qmessage
) != NULL
) {
1342 dns_tsigkey_attach(dns_message_gettsigkey(fctx
->qmessage
),
1344 result
= dns_message_getquerytsig(fctx
->qmessage
,
1347 if (result
!= ISC_R_SUCCESS
)
1348 goto cleanup_message
;
1352 * If using TCP, write the length of the message at the beginning
1355 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1356 isc_buffer_usedregion(&query
->buffer
, &r
);
1357 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
)r
.length
);
1358 isc_buffer_add(&tcpbuffer
, r
.length
);
1362 * We're now done with the query message.
1364 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1366 socket
= dns_dispatch_getsocket(query
->dispatch
);
1370 if ((query
->options
& DNS_FETCHOPT_TCP
) == 0)
1371 address
= &query
->addrinfo
->sockaddr
;
1372 isc_buffer_usedregion(buffer
, &r
);
1375 * XXXRTH Make sure we don't send to ourselves! We should probably
1376 * prune out these addresses when we get them from the ADB.
1378 result
= isc_socket_sendto(socket
, &r
, task
, resquery_senddone
,
1379 query
, address
, NULL
);
1380 if (result
!= ISC_R_SUCCESS
)
1381 goto cleanup_message
;
1385 return (ISC_R_SUCCESS
);
1389 dns_compress_invalidate(&cctx
);
1391 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1394 * Stop the dispatcher from listening.
1396 dns_dispatch_removeresponse(&query
->dispentry
, NULL
);
1400 dns_message_puttempname(fctx
->qmessage
, &qname
);
1401 if (qrdataset
!= NULL
)
1402 dns_message_puttemprdataset(fctx
->qmessage
, &qrdataset
);
1408 resquery_connected(isc_task_t
*task
, isc_event_t
*event
) {
1409 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1410 resquery_t
*query
= event
->ev_arg
;
1411 isc_boolean_t retry
= ISC_FALSE
;
1412 isc_result_t result
;
1416 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1417 REQUIRE(VALID_QUERY(query
));
1419 QTRACE("connected");
1426 * Currently we don't wait for the connect event before retrying
1427 * a query. This means that if we get really behind, we may end
1428 * up doing extra work!
1434 if (RESQUERY_CANCELED(query
)) {
1436 * This query was canceled while the connect() was in
1439 isc_socket_detach(&query
->tcpsocket
);
1440 resquery_destroy(&query
);
1442 switch (sevent
->result
) {
1445 * We are connected. Create a dispatcher and
1449 attrs
|= DNS_DISPATCHATTR_TCP
;
1450 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
1451 attrs
|= DNS_DISPATCHATTR_CONNECTED
;
1452 if (isc_sockaddr_pf(&query
->addrinfo
->sockaddr
) ==
1454 attrs
|= DNS_DISPATCHATTR_IPV4
;
1456 attrs
|= DNS_DISPATCHATTR_IPV6
;
1457 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
1459 result
= dns_dispatch_createtcp(query
->dispatchmgr
,
1461 query
->fctx
->res
->taskmgr
,
1462 4096, 2, 1, 1, 3, attrs
,
1466 * Regardless of whether dns_dispatch_create()
1467 * succeeded or not, we don't need our reference
1468 * to the socket anymore.
1470 isc_socket_detach(&query
->tcpsocket
);
1472 if (result
== ISC_R_SUCCESS
)
1473 result
= resquery_send(query
);
1475 if (result
!= ISC_R_SUCCESS
) {
1476 fctx_cancelquery(&query
, NULL
, NULL
,
1478 fctx_done(fctx
, result
);
1482 case ISC_R_NETUNREACH
:
1483 case ISC_R_HOSTUNREACH
:
1484 case ISC_R_CONNREFUSED
:
1486 case ISC_R_ADDRNOTAVAIL
:
1487 case ISC_R_CONNECTIONRESET
:
1489 * No route to remote.
1491 isc_socket_detach(&query
->tcpsocket
);
1492 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
1497 isc_socket_detach(&query
->tcpsocket
);
1498 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
1503 isc_event_free(&event
);
1507 * Behave as if the idle timer has expired. For TCP
1508 * connections this may not actually reflect the latest timer.
1510 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1511 result
= fctx_stopidletimer(fctx
);
1512 if (result
!= ISC_R_SUCCESS
)
1513 fctx_done(fctx
, result
);
1520 fctx_finddone(isc_task_t
*task
, isc_event_t
*event
) {
1522 dns_adbfind_t
*find
;
1523 dns_resolver_t
*res
;
1524 isc_boolean_t want_try
= ISC_FALSE
;
1525 isc_boolean_t want_done
= ISC_FALSE
;
1526 isc_boolean_t bucket_empty
= ISC_FALSE
;
1527 unsigned int bucketnum
;
1529 find
= event
->ev_sender
;
1530 fctx
= event
->ev_arg
;
1531 REQUIRE(VALID_FCTX(fctx
));
1536 FCTXTRACE("finddone");
1538 INSIST(fctx
->pending
> 0);
1541 if (ADDRWAIT(fctx
)) {
1543 * The fetch is waiting for a name to be found.
1545 INSIST(!SHUTTINGDOWN(fctx
));
1546 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1547 if (event
->ev_type
== DNS_EVENT_ADBMOREADDRESSES
)
1548 want_try
= ISC_TRUE
;
1549 else if (fctx
->pending
== 0) {
1551 * We've got nothing else to wait for and don't
1552 * know the answer. There's nothing to do but
1555 want_done
= ISC_TRUE
;
1557 } else if (SHUTTINGDOWN(fctx
) && fctx
->pending
== 0 &&
1558 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
)) {
1559 bucketnum
= fctx
->bucketnum
;
1560 LOCK(&res
->buckets
[bucketnum
].lock
);
1562 * Note that we had to wait until we had the lock before
1563 * looking at fctx->references.
1565 if (fctx
->references
== 0)
1566 bucket_empty
= fctx_destroy(fctx
);
1567 UNLOCK(&res
->buckets
[bucketnum
].lock
);
1570 isc_event_free(&event
);
1571 dns_adb_destroyfind(&find
);
1576 fctx_done(fctx
, ISC_R_FAILURE
);
1577 else if (bucket_empty
)
1582 static inline isc_boolean_t
1583 bad_server(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1586 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
1588 sa
= ISC_LIST_NEXT(sa
, link
)) {
1589 if (isc_sockaddr_equal(sa
, address
))
1596 static inline isc_boolean_t
1597 mark_bad(fetchctx_t
*fctx
) {
1598 dns_adbfind_t
*curr
;
1599 dns_adbaddrinfo_t
*addrinfo
;
1600 isc_boolean_t all_bad
= ISC_TRUE
;
1603 * Mark all known bad servers, so we don't try to talk to them
1608 * Mark any bad nameservers.
1610 for (curr
= ISC_LIST_HEAD(fctx
->finds
);
1612 curr
= ISC_LIST_NEXT(curr
, publink
)) {
1613 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
1615 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
1616 if (bad_server(fctx
, &addrinfo
->sockaddr
))
1617 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
1619 all_bad
= ISC_FALSE
;
1624 * Mark any bad forwarders.
1626 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
1628 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
1629 if (bad_server(fctx
, &addrinfo
->sockaddr
))
1630 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
1632 all_bad
= ISC_FALSE
;
1636 * Mark any bad alternates.
1638 for (curr
= ISC_LIST_HEAD(fctx
->altfinds
);
1640 curr
= ISC_LIST_NEXT(curr
, publink
)) {
1641 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
1643 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
1644 if (bad_server(fctx
, &addrinfo
->sockaddr
))
1645 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
1647 all_bad
= ISC_FALSE
;
1651 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
1653 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
1654 if (bad_server(fctx
, &addrinfo
->sockaddr
))
1655 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
1657 all_bad
= ISC_FALSE
;
1664 add_bad(fetchctx_t
*fctx
, isc_sockaddr_t
*address
, isc_result_t reason
) {
1665 char namebuf
[DNS_NAME_FORMATSIZE
];
1666 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
1672 const char *sep1
, *sep2
;
1674 if (bad_server(fctx
, address
)) {
1676 * We already know this server is bad.
1681 FCTXTRACE("add_bad");
1683 sa
= isc_mem_get(fctx
->res
->mctx
, sizeof(*sa
));
1687 ISC_LIST_INITANDAPPEND(fctx
->bad
, sa
, link
);
1689 if (reason
== DNS_R_LAME
) /* already logged */
1692 if (reason
== DNS_R_UNEXPECTEDRCODE
) {
1693 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
1694 dns_rcode_totext(fctx
->rmessage
->rcode
, &b
);
1695 code
[isc_buffer_usedlength(&b
)] = '\0';
1698 } else if (reason
== DNS_R_UNEXPECTEDOPCODE
) {
1699 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
1700 dns_opcode_totext((dns_opcode_t
)fctx
->rmessage
->opcode
, &b
);
1701 code
[isc_buffer_usedlength(&b
)] = '\0';
1709 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
1710 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
1711 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
, sizeof(classbuf
));
1712 isc_sockaddr_format(address
, addrbuf
, sizeof(addrbuf
));
1713 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
1714 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
1715 "%s %s%s%sresolving '%s/%s/%s': %s",
1716 dns_result_totext(reason
), sep1
, code
, sep2
,
1717 namebuf
, typebuf
, classbuf
, addrbuf
);
1721 sort_adbfind(dns_adbfind_t
*find
) {
1722 dns_adbaddrinfo_t
*best
, *curr
;
1723 dns_adbaddrinfolist_t sorted
;
1726 * Lame N^2 bubble sort.
1729 ISC_LIST_INIT(sorted
);
1730 while (!ISC_LIST_EMPTY(find
->list
)) {
1731 best
= ISC_LIST_HEAD(find
->list
);
1732 curr
= ISC_LIST_NEXT(best
, publink
);
1733 while (curr
!= NULL
) {
1734 if (curr
->srtt
< best
->srtt
)
1736 curr
= ISC_LIST_NEXT(curr
, publink
);
1738 ISC_LIST_UNLINK(find
->list
, best
, publink
);
1739 ISC_LIST_APPEND(sorted
, best
, publink
);
1741 find
->list
= sorted
;
1745 sort_finds(fetchctx_t
*fctx
) {
1746 dns_adbfind_t
*best
, *curr
;
1747 dns_adbfindlist_t sorted
;
1748 dns_adbaddrinfo_t
*addrinfo
, *bestaddrinfo
;
1751 * Lame N^2 bubble sort.
1754 ISC_LIST_INIT(sorted
);
1755 while (!ISC_LIST_EMPTY(fctx
->finds
)) {
1756 best
= ISC_LIST_HEAD(fctx
->finds
);
1757 bestaddrinfo
= ISC_LIST_HEAD(best
->list
);
1758 INSIST(bestaddrinfo
!= NULL
);
1759 curr
= ISC_LIST_NEXT(best
, publink
);
1760 while (curr
!= NULL
) {
1761 addrinfo
= ISC_LIST_HEAD(curr
->list
);
1762 INSIST(addrinfo
!= NULL
);
1763 if (addrinfo
->srtt
< bestaddrinfo
->srtt
) {
1765 bestaddrinfo
= addrinfo
;
1767 curr
= ISC_LIST_NEXT(curr
, publink
);
1769 ISC_LIST_UNLINK(fctx
->finds
, best
, publink
);
1770 ISC_LIST_APPEND(sorted
, best
, publink
);
1772 fctx
->finds
= sorted
;
1774 ISC_LIST_INIT(sorted
);
1775 while (!ISC_LIST_EMPTY(fctx
->altfinds
)) {
1776 best
= ISC_LIST_HEAD(fctx
->altfinds
);
1777 bestaddrinfo
= ISC_LIST_HEAD(best
->list
);
1778 INSIST(bestaddrinfo
!= NULL
);
1779 curr
= ISC_LIST_NEXT(best
, publink
);
1780 while (curr
!= NULL
) {
1781 addrinfo
= ISC_LIST_HEAD(curr
->list
);
1782 INSIST(addrinfo
!= NULL
);
1783 if (addrinfo
->srtt
< bestaddrinfo
->srtt
) {
1785 bestaddrinfo
= addrinfo
;
1787 curr
= ISC_LIST_NEXT(curr
, publink
);
1789 ISC_LIST_UNLINK(fctx
->altfinds
, best
, publink
);
1790 ISC_LIST_APPEND(sorted
, best
, publink
);
1792 fctx
->altfinds
= sorted
;
1796 findname(fetchctx_t
*fctx
, dns_name_t
*name
, in_port_t port
,
1797 unsigned int options
, unsigned int flags
, isc_stdtime_t now
,
1798 isc_boolean_t
*pruned
, isc_boolean_t
*need_alternate
)
1800 dns_adbaddrinfo_t
*ai
;
1801 dns_adbfind_t
*find
;
1802 dns_resolver_t
*res
;
1803 isc_boolean_t unshared
;
1804 isc_result_t result
;
1807 unshared
= ISC_TF((fctx
->options
| DNS_FETCHOPT_UNSHARED
) != 0);
1809 * If this name is a subdomain of the query domain, tell
1810 * the ADB to start looking using zone/hint data. This keeps us
1811 * from getting stuck if the nameserver is beneath the zone cut
1812 * and we don't know its address (e.g. because the A record has
1815 if (dns_name_issubdomain(name
, &fctx
->domain
))
1816 options
|= DNS_ADBFIND_STARTATZONE
;
1817 options
|= DNS_ADBFIND_GLUEOK
;
1818 options
|= DNS_ADBFIND_HINTOK
;
1821 * See what we know about this address.
1824 result
= dns_adb_createfind(fctx
->adb
,
1825 res
->buckets
[fctx
->bucketnum
].task
,
1826 fctx_finddone
, fctx
, name
,
1827 &fctx
->domain
, options
, now
, NULL
,
1828 res
->view
->dstport
, &find
);
1829 if (result
!= ISC_R_SUCCESS
) {
1830 if (result
== DNS_R_ALIAS
) {
1832 * XXXRTH Follow the CNAME/DNAME chain?
1834 dns_adb_destroyfind(&find
);
1836 } else if (!ISC_LIST_EMPTY(find
->list
)) {
1838 * We have at least some of the addresses for the
1841 INSIST((find
->options
& DNS_ADBFIND_WANTEVENT
) == 0);
1843 if (flags
!= 0 || port
!= 0) {
1844 for (ai
= ISC_LIST_HEAD(find
->list
);
1846 ai
= ISC_LIST_NEXT(ai
, publink
)) {
1849 isc_sockaddr_setport(&ai
->sockaddr
,
1853 if ((flags
& FCTX_ADDRINFO_FORWARDER
) != 0)
1854 ISC_LIST_APPEND(fctx
->altfinds
, find
, publink
);
1856 ISC_LIST_APPEND(fctx
->finds
, find
, publink
);
1859 * We don't know any of the addresses for this
1862 if ((find
->options
& DNS_ADBFIND_WANTEVENT
) != 0) {
1864 * We're looking for them and will get an
1865 * event about it later.
1871 if (need_alternate
!= NULL
&&
1872 !*need_alternate
&& unshared
&&
1873 ((res
->dispatchv4
== NULL
&&
1874 find
->result_v6
!= DNS_R_NXDOMAIN
) ||
1875 (res
->dispatchv6
== NULL
&&
1876 find
->result_v4
!= DNS_R_NXDOMAIN
)))
1877 *need_alternate
= ISC_TRUE
;
1880 * If we know there are no addresses for
1881 * the family we are using then try to add
1882 * an alternative server.
1884 if (need_alternate
!= NULL
&& !*need_alternate
&&
1885 ((res
->dispatchv4
== NULL
&&
1886 find
->result_v6
== DNS_R_NXRRSET
) ||
1887 (res
->dispatchv6
== NULL
&&
1888 find
->result_v4
== DNS_R_NXRRSET
)))
1889 *need_alternate
= ISC_TRUE
;
1891 * And ADB isn't going to send us any events
1892 * either. This find loses.
1894 if ((find
->options
& DNS_ADBFIND_LAMEPRUNED
) != 0) {
1896 * The ADB pruned lame servers for
1897 * this name. Remember that in case
1898 * we get desperate later on.
1902 dns_adb_destroyfind(&find
);
1908 fctx_getaddresses(fetchctx_t
*fctx
) {
1909 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1910 isc_result_t result
;
1911 dns_resolver_t
*res
;
1913 unsigned int stdoptions
;
1915 dns_adbaddrinfo_t
*ai
;
1916 isc_boolean_t pruned
, all_bad
;
1918 isc_boolean_t need_alternate
= ISC_FALSE
;
1920 FCTXTRACE("getaddresses");
1923 * Don't pound on remote servers. (Failsafe!)
1926 if (fctx
->restarts
> 10) {
1927 FCTXTRACE("too many restarts");
1928 return (DNS_R_SERVFAIL
);
1933 stdoptions
= 0; /* Keep compiler happy. */
1939 INSIST(ISC_LIST_EMPTY(fctx
->forwaddrs
));
1940 INSIST(ISC_LIST_EMPTY(fctx
->altaddrs
));
1943 * If this fctx has forwarders, use them; otherwise use any
1944 * selective forwarders specified in the view; otherwise use the
1945 * resolver's forwarders (if any).
1947 sa
= ISC_LIST_HEAD(fctx
->forwarders
);
1949 dns_forwarders_t
*forwarders
= NULL
;
1950 dns_name_t
*name
= &fctx
->name
;
1952 unsigned int labels
;
1955 * DS records are found in the parent server.
1956 * Strip label to get the correct forwarder (if any).
1958 if (fctx
->type
== dns_rdatatype_ds
&&
1959 dns_name_countlabels(name
) > 1) {
1960 dns_name_init(&suffix
, NULL
);
1961 labels
= dns_name_countlabels(name
);
1962 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
1965 result
= dns_fwdtable_find(fctx
->res
->view
->fwdtable
, name
,
1967 if (result
== ISC_R_SUCCESS
) {
1968 sa
= ISC_LIST_HEAD(forwarders
->addrs
);
1969 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
1973 while (sa
!= NULL
) {
1975 result
= dns_adb_findaddrinfo(fctx
->adb
,
1976 sa
, &ai
, 0); /* XXXMLG */
1977 if (result
== ISC_R_SUCCESS
) {
1978 dns_adbaddrinfo_t
*cur
;
1979 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
1980 cur
= ISC_LIST_HEAD(fctx
->forwaddrs
);
1981 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
1982 cur
= ISC_LIST_NEXT(cur
, publink
);
1984 ISC_LIST_INSERTBEFORE(fctx
->forwaddrs
, cur
,
1987 ISC_LIST_APPEND(fctx
->forwaddrs
, ai
, publink
);
1989 sa
= ISC_LIST_NEXT(sa
, link
);
1993 * If the forwarding policy is "only", we don't need the addresses
1994 * of the nameservers.
1996 if (fctx
->fwdpolicy
== dns_fwdpolicy_only
)
2000 * Normal nameservers.
2003 stdoptions
= DNS_ADBFIND_WANTEVENT
| DNS_ADBFIND_EMPTYEVENT
;
2004 if (fctx
->restarts
== 1) {
2006 * To avoid sending out a flood of queries likely to
2007 * result in NXRRSET, we suppress fetches for address
2008 * families we don't have the first time through,
2009 * provided that we have addresses in some family we
2012 * We don't want to set this option all the time, since
2013 * if fctx->restarts > 1, we've clearly been having trouble
2014 * with the addresses we had, so getting more could help.
2016 stdoptions
|= DNS_ADBFIND_AVOIDFETCHES
;
2018 if (res
->dispatchv4
!= NULL
)
2019 stdoptions
|= DNS_ADBFIND_INET
;
2020 if (res
->dispatchv6
!= NULL
)
2021 stdoptions
|= DNS_ADBFIND_INET6
;
2022 isc_stdtime_get(&now
);
2025 INSIST(ISC_LIST_EMPTY(fctx
->finds
));
2026 INSIST(ISC_LIST_EMPTY(fctx
->altfinds
));
2028 for (result
= dns_rdataset_first(&fctx
->nameservers
);
2029 result
== ISC_R_SUCCESS
;
2030 result
= dns_rdataset_next(&fctx
->nameservers
))
2032 dns_rdataset_current(&fctx
->nameservers
, &rdata
);
2034 * Extract the name from the NS record.
2036 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
2037 if (result
!= ISC_R_SUCCESS
)
2040 findname(fctx
, &ns
.name
, 0, stdoptions
, 0, now
,
2041 &pruned
, &need_alternate
);
2042 dns_rdata_reset(&rdata
);
2043 dns_rdata_freestruct(&ns
);
2045 if (result
!= ISC_R_NOMORE
)
2049 * Do we need to use 6 to 4?
2051 if (need_alternate
) {
2054 family
= (res
->dispatchv6
!= NULL
) ? AF_INET6
: AF_INET
;
2055 for (a
= ISC_LIST_HEAD(fctx
->res
->alternates
);
2057 a
= ISC_LIST_NEXT(a
, link
)) {
2058 if (!a
->isaddress
) {
2059 findname(fctx
, &a
->_u
._n
.name
, a
->_u
._n
.port
,
2060 stdoptions
, FCTX_ADDRINFO_FORWARDER
,
2061 now
, &pruned
, NULL
);
2064 if (isc_sockaddr_pf(&a
->_u
.addr
) != family
)
2067 result
= dns_adb_findaddrinfo(fctx
->adb
, &a
->_u
.addr
,
2069 if (result
== ISC_R_SUCCESS
) {
2070 dns_adbaddrinfo_t
*cur
;
2071 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
2072 cur
= ISC_LIST_HEAD(fctx
->altaddrs
);
2073 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
2074 cur
= ISC_LIST_NEXT(cur
, publink
);
2076 ISC_LIST_INSERTBEFORE(fctx
->altaddrs
,
2079 ISC_LIST_APPEND(fctx
->altaddrs
, ai
,
2087 * Mark all known bad servers.
2089 all_bad
= mark_bad(fctx
);
2096 * We've got no addresses.
2098 if (fctx
->pending
> 0) {
2100 * We're fetching the addresses, but don't have any
2101 * yet. Tell the caller to wait for an answer.
2103 result
= DNS_R_WAIT
;
2104 } else if (pruned
) {
2106 * Some addresses were removed by lame pruning.
2107 * Turn pruning off and try again.
2109 FCTXTRACE("restarting with returnlame");
2110 INSIST((stdoptions
& DNS_ADBFIND_RETURNLAME
) == 0);
2111 stdoptions
|= DNS_ADBFIND_RETURNLAME
;
2113 fctx_cleanupaltfinds(fctx
);
2114 fctx_cleanupfinds(fctx
);
2118 * We've lost completely. We don't know any
2119 * addresses, and the ADB has told us it can't get
2122 FCTXTRACE("no addresses");
2123 result
= ISC_R_FAILURE
;
2127 * We've found some addresses. We might still be looking
2128 * for more addresses.
2131 result
= ISC_R_SUCCESS
;
2138 possibly_mark(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addr
)
2141 char buf
[ISC_NETADDR_FORMATSIZE
];
2143 isc_boolean_t aborted
= ISC_FALSE
;
2144 isc_boolean_t bogus
;
2145 dns_acl_t
*blackhole
;
2146 isc_netaddr_t ipaddr
;
2147 dns_peer_t
*peer
= NULL
;
2148 dns_resolver_t
*res
;
2149 const char *msg
= NULL
;
2151 sa
= &addr
->sockaddr
;
2154 isc_netaddr_fromsockaddr(&ipaddr
, sa
);
2155 blackhole
= dns_dispatchmgr_getblackhole(res
->dispatchmgr
);
2156 (void) dns_peerlist_peerbyaddr(res
->view
->peers
, &ipaddr
, &peer
);
2158 if (blackhole
!= NULL
) {
2161 if (dns_acl_match(&ipaddr
, NULL
, blackhole
,
2163 &match
, NULL
) == ISC_R_SUCCESS
&&
2169 dns_peer_getbogus(peer
, &bogus
) == ISC_R_SUCCESS
&&
2174 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2175 msg
= "ignoring blackholed / bogus server: ";
2176 } else if (isc_sockaddr_ismulticast(sa
)) {
2177 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2178 msg
= "ignoring multicast address: ";
2179 } else if (isc_sockaddr_isexperimental(sa
)) {
2180 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2181 msg
= "ignoring experimental address: ";
2182 } else if (sa
->type
.sa
.sa_family
!= AF_INET6
) {
2184 } else if (IN6_IS_ADDR_V4MAPPED(&sa
->type
.sin6
.sin6_addr
)) {
2185 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2186 msg
= "ignoring IPv6 mapped IPV4 address: ";
2187 } else if (IN6_IS_ADDR_V4COMPAT(&sa
->type
.sin6
.sin6_addr
)) {
2188 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2189 msg
= "ignoring IPv6 compatibility IPV4 address: ";
2193 if (!isc_log_wouldlog(dns_lctx
, ISC_LOG_DEBUG(3)))
2196 isc_netaddr_fromsockaddr(&na
, sa
);
2197 isc_netaddr_format(&na
, buf
, sizeof(buf
));
2198 FCTXTRACE2(msg
, buf
);
2201 static inline dns_adbaddrinfo_t
*
2202 fctx_nextaddress(fetchctx_t
*fctx
) {
2203 dns_adbfind_t
*find
, *start
;
2204 dns_adbaddrinfo_t
*addrinfo
;
2205 dns_adbaddrinfo_t
*faddrinfo
;
2208 * Return the next untried address, if any.
2212 * Find the first unmarked forwarder (if any).
2214 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2216 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2217 if (!UNMARKED(addrinfo
))
2219 possibly_mark(fctx
, addrinfo
);
2220 if (UNMARKED(addrinfo
)) {
2221 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2228 * No forwarders. Move to the next find.
2231 fctx
->attributes
|= FCTX_ATTR_TRIEDFIND
;
2235 find
= ISC_LIST_HEAD(fctx
->finds
);
2237 find
= ISC_LIST_NEXT(find
, publink
);
2239 find
= ISC_LIST_HEAD(fctx
->finds
);
2243 * Find the first unmarked addrinfo.
2249 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2251 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2252 if (!UNMARKED(addrinfo
))
2254 possibly_mark(fctx
, addrinfo
);
2255 if (UNMARKED(addrinfo
)) {
2256 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2260 if (addrinfo
!= NULL
)
2262 find
= ISC_LIST_NEXT(find
, publink
);
2264 find
= ISC_LIST_HEAD(fctx
->finds
);
2265 } while (find
!= start
);
2269 if (addrinfo
!= NULL
)
2273 * No nameservers left. Try alternates.
2276 fctx
->attributes
|= FCTX_ATTR_TRIEDALT
;
2278 find
= fctx
->altfind
;
2280 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2282 find
= ISC_LIST_NEXT(find
, publink
);
2284 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2288 * Find the first unmarked addrinfo.
2294 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2296 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2297 if (!UNMARKED(addrinfo
))
2299 possibly_mark(fctx
, addrinfo
);
2300 if (UNMARKED(addrinfo
)) {
2301 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2305 if (addrinfo
!= NULL
)
2307 find
= ISC_LIST_NEXT(find
, publink
);
2309 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2310 } while (find
!= start
);
2313 faddrinfo
= addrinfo
;
2316 * See if we have a better alternate server by address.
2319 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
2321 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2322 if (!UNMARKED(addrinfo
))
2324 possibly_mark(fctx
, addrinfo
);
2325 if (UNMARKED(addrinfo
) &&
2326 (faddrinfo
== NULL
||
2327 addrinfo
->srtt
< faddrinfo
->srtt
)) {
2328 if (faddrinfo
!= NULL
)
2329 faddrinfo
->flags
&= ~FCTX_ADDRINFO_MARK
;
2330 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2335 if (addrinfo
== NULL
) {
2336 addrinfo
= faddrinfo
;
2337 fctx
->altfind
= find
;
2344 fctx_try(fetchctx_t
*fctx
) {
2345 isc_result_t result
;
2346 dns_adbaddrinfo_t
*addrinfo
;
2350 REQUIRE(!ADDRWAIT(fctx
));
2352 addrinfo
= fctx_nextaddress(fctx
);
2353 if (addrinfo
== NULL
) {
2355 * We have no more addresses. Start over.
2357 fctx_cancelqueries(fctx
, ISC_TRUE
);
2358 fctx_cleanupfinds(fctx
);
2359 fctx_cleanupaltfinds(fctx
);
2360 fctx_cleanupforwaddrs(fctx
);
2361 fctx_cleanupaltaddrs(fctx
);
2362 result
= fctx_getaddresses(fctx
);
2363 if (result
== DNS_R_WAIT
) {
2365 * Sleep waiting for addresses.
2367 FCTXTRACE("addrwait");
2368 fctx
->attributes
|= FCTX_ATTR_ADDRWAIT
;
2370 } else if (result
!= ISC_R_SUCCESS
) {
2372 * Something bad happened.
2374 fctx_done(fctx
, result
);
2378 addrinfo
= fctx_nextaddress(fctx
);
2380 * While we may have addresses from the ADB, they
2381 * might be bad ones. In this case, return SERVFAIL.
2383 if (addrinfo
== NULL
) {
2384 fctx_done(fctx
, DNS_R_SERVFAIL
);
2389 result
= fctx_query(fctx
, addrinfo
, fctx
->options
);
2390 if (result
!= ISC_R_SUCCESS
)
2391 fctx_done(fctx
, result
);
2394 static isc_boolean_t
2395 fctx_destroy(fetchctx_t
*fctx
) {
2396 dns_resolver_t
*res
;
2397 unsigned int bucketnum
;
2398 isc_sockaddr_t
*sa
, *next_sa
;
2401 * Caller must be holding the bucket lock.
2404 REQUIRE(VALID_FCTX(fctx
));
2405 REQUIRE(fctx
->state
== fetchstate_done
||
2406 fctx
->state
== fetchstate_init
);
2407 REQUIRE(ISC_LIST_EMPTY(fctx
->events
));
2408 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
2409 REQUIRE(ISC_LIST_EMPTY(fctx
->finds
));
2410 REQUIRE(ISC_LIST_EMPTY(fctx
->altfinds
));
2411 REQUIRE(fctx
->pending
== 0);
2412 REQUIRE(fctx
->references
== 0);
2413 REQUIRE(ISC_LIST_EMPTY(fctx
->validators
));
2415 FCTXTRACE("destroy");
2418 bucketnum
= fctx
->bucketnum
;
2420 ISC_LIST_UNLINK(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
2425 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
2428 next_sa
= ISC_LIST_NEXT(sa
, link
);
2429 ISC_LIST_UNLINK(fctx
->bad
, sa
, link
);
2430 isc_mem_put(res
->mctx
, sa
, sizeof(*sa
));
2433 isc_timer_detach(&fctx
->timer
);
2434 dns_message_destroy(&fctx
->rmessage
);
2435 dns_message_destroy(&fctx
->qmessage
);
2436 if (dns_name_countlabels(&fctx
->domain
) > 0)
2437 dns_name_free(&fctx
->domain
, res
->mctx
);
2438 if (dns_rdataset_isassociated(&fctx
->nameservers
))
2439 dns_rdataset_disassociate(&fctx
->nameservers
);
2440 dns_name_free(&fctx
->name
, res
->mctx
);
2441 dns_db_detach(&fctx
->cache
);
2442 dns_adb_detach(&fctx
->adb
);
2443 isc_mem_free(res
->mctx
, fctx
->info
);
2444 isc_mem_put(res
->mctx
, fctx
, sizeof(*fctx
));
2448 UNLOCK(&res
->nlock
);
2450 if (res
->buckets
[bucketnum
].exiting
&&
2451 ISC_LIST_EMPTY(res
->buckets
[bucketnum
].fctxs
))
2458 * Fetch event handlers.
2462 fctx_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2463 fetchctx_t
*fctx
= event
->ev_arg
;
2465 REQUIRE(VALID_FCTX(fctx
));
2469 FCTXTRACE("timeout");
2471 if (event
->ev_type
== ISC_TIMEREVENT_LIFE
) {
2472 fctx_done(fctx
, ISC_R_TIMEDOUT
);
2474 isc_result_t result
;
2478 * We could cancel the running queries here, or we could let
2479 * them keep going. Right now we choose the latter...
2481 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2483 * Our timer has triggered. Reestablish the fctx lifetime
2486 result
= fctx_starttimer(fctx
);
2487 if (result
!= ISC_R_SUCCESS
)
2488 fctx_done(fctx
, result
);
2496 isc_event_free(&event
);
2500 fctx_shutdown(fetchctx_t
*fctx
) {
2501 isc_event_t
*cevent
;
2504 * Start the shutdown process for fctx, if it isn't already underway.
2507 FCTXTRACE("shutdown");
2510 * The caller must be holding the appropriate bucket lock.
2513 if (fctx
->want_shutdown
)
2516 fctx
->want_shutdown
= ISC_TRUE
;
2519 * Unless we're still initializing (in which case the
2520 * control event is still outstanding), we need to post
2521 * the control event to tell the fetch we want it to
2524 if (fctx
->state
!= fetchstate_init
) {
2525 cevent
= &fctx
->control_event
;
2526 isc_task_send(fctx
->res
->buckets
[fctx
->bucketnum
].task
,
2532 fctx_doshutdown(isc_task_t
*task
, isc_event_t
*event
) {
2533 fetchctx_t
*fctx
= event
->ev_arg
;
2534 isc_boolean_t bucket_empty
= ISC_FALSE
;
2535 dns_resolver_t
*res
;
2536 unsigned int bucketnum
;
2537 dns_validator_t
*validator
;
2539 REQUIRE(VALID_FCTX(fctx
));
2544 bucketnum
= fctx
->bucketnum
;
2546 FCTXTRACE("doshutdown");
2549 * An fctx that is shutting down is no longer in ADDRWAIT mode.
2551 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2554 * Cancel all pending validators. Note that this must be done
2555 * without the bucket lock held, since that could cause deadlock.
2557 validator
= ISC_LIST_HEAD(fctx
->validators
);
2558 while (validator
!= NULL
) {
2559 dns_validator_cancel(validator
);
2560 validator
= ISC_LIST_NEXT(validator
, link
);
2563 if (fctx
->nsfetch
!= NULL
)
2564 dns_resolver_cancelfetch(fctx
->nsfetch
);
2567 * Shut down anything that is still running on behalf of this
2568 * fetch. To avoid deadlock with the ADB, we must do this
2569 * before we lock the bucket lock.
2571 fctx_stopeverything(fctx
, ISC_FALSE
);
2573 LOCK(&res
->buckets
[bucketnum
].lock
);
2575 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
2577 INSIST(fctx
->state
== fetchstate_active
||
2578 fctx
->state
== fetchstate_done
);
2579 INSIST(fctx
->want_shutdown
);
2581 if (fctx
->state
!= fetchstate_done
) {
2582 fctx
->state
= fetchstate_done
;
2583 fctx_sendevents(fctx
, ISC_R_CANCELED
);
2586 if (fctx
->references
== 0 && fctx
->pending
== 0 &&
2587 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
))
2588 bucket_empty
= fctx_destroy(fctx
);
2590 UNLOCK(&res
->buckets
[bucketnum
].lock
);
2597 fctx_start(isc_task_t
*task
, isc_event_t
*event
) {
2598 fetchctx_t
*fctx
= event
->ev_arg
;
2599 isc_boolean_t done
= ISC_FALSE
, bucket_empty
= ISC_FALSE
;
2600 dns_resolver_t
*res
;
2601 unsigned int bucketnum
;
2603 REQUIRE(VALID_FCTX(fctx
));
2608 bucketnum
= fctx
->bucketnum
;
2612 LOCK(&res
->buckets
[bucketnum
].lock
);
2614 INSIST(fctx
->state
== fetchstate_init
);
2615 if (fctx
->want_shutdown
) {
2617 * We haven't started this fctx yet, and we've been requested
2620 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
2621 fctx
->state
= fetchstate_done
;
2622 fctx_sendevents(fctx
, ISC_R_CANCELED
);
2624 * Since we haven't started, we INSIST that we have no
2625 * pending ADB finds and no pending validations.
2627 INSIST(fctx
->pending
== 0);
2628 INSIST(fctx
->nqueries
== 0);
2629 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
2630 if (fctx
->references
== 0) {
2632 * It's now safe to destroy this fctx.
2634 bucket_empty
= fctx_destroy(fctx
);
2639 * Normal fctx startup.
2641 fctx
->state
= fetchstate_active
;
2643 * Reset the control event for later use in shutting down
2646 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
2647 DNS_EVENT_FETCHCONTROL
, fctx_doshutdown
, fctx
,
2651 UNLOCK(&res
->buckets
[bucketnum
].lock
);
2654 isc_result_t result
;
2657 * All is well. Start working on the fetch.
2659 result
= fctx_starttimer(fctx
);
2660 if (result
!= ISC_R_SUCCESS
)
2661 fctx_done(fctx
, result
);
2664 } else if (bucket_empty
)
2669 * Fetch Creation, Joining, and Cancelation.
2672 static inline isc_result_t
2673 fctx_join(fetchctx_t
*fctx
, isc_task_t
*task
, isc_taskaction_t action
,
2674 void *arg
, dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
2678 dns_fetchevent_t
*event
;
2683 * We store the task we're going to send this event to in the
2684 * sender field. We'll make the fetch the sender when we actually
2688 isc_task_attach(task
, &clone
);
2689 event
= (dns_fetchevent_t
*)
2690 isc_event_allocate(fctx
->res
->mctx
, clone
,
2691 DNS_EVENT_FETCHDONE
,
2692 action
, arg
, sizeof(*event
));
2693 if (event
== NULL
) {
2694 isc_task_detach(&clone
);
2695 return (ISC_R_NOMEMORY
);
2697 event
->result
= DNS_R_SERVFAIL
;
2698 event
->qtype
= fctx
->type
;
2701 event
->rdataset
= rdataset
;
2702 event
->sigrdataset
= sigrdataset
;
2703 event
->fetch
= fetch
;
2704 dns_fixedname_init(&event
->foundname
);
2707 * Make sure that we can store the sigrdataset in the
2708 * first event if it is needed by any of the events.
2710 if (event
->sigrdataset
!= NULL
)
2711 ISC_LIST_PREPEND(fctx
->events
, event
, ev_link
);
2713 ISC_LIST_APPEND(fctx
->events
, event
, ev_link
);
2716 fetch
->magic
= DNS_FETCH_MAGIC
;
2717 fetch
->private = fctx
;
2719 return (ISC_R_SUCCESS
);
2723 fctx_create(dns_resolver_t
*res
, dns_name_t
*name
, dns_rdatatype_t type
,
2724 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
2725 unsigned int options
, unsigned int bucketnum
, fetchctx_t
**fctxp
)
2728 isc_result_t result
;
2729 isc_result_t iresult
;
2730 isc_interval_t interval
;
2731 dns_fixedname_t fixed
;
2732 unsigned int findoptions
= 0;
2733 char buf
[DNS_NAME_FORMATSIZE
+ DNS_RDATATYPE_FORMATSIZE
];
2734 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
2738 * Caller must be holding the lock for bucket number 'bucketnum'.
2740 REQUIRE(fctxp
!= NULL
&& *fctxp
== NULL
);
2742 fctx
= isc_mem_get(res
->mctx
, sizeof(*fctx
));
2744 return (ISC_R_NOMEMORY
);
2745 dns_name_format(name
, buf
, sizeof(buf
));
2746 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
2747 strcat(buf
, "/"); /* checked */
2748 strcat(buf
, typebuf
); /* checked */
2749 fctx
->info
= isc_mem_strdup(res
->mctx
, buf
);
2750 if (fctx
->info
== NULL
) {
2751 result
= ISC_R_NOMEMORY
;
2754 FCTXTRACE("create");
2755 dns_name_init(&fctx
->name
, NULL
);
2756 result
= dns_name_dup(name
, res
->mctx
, &fctx
->name
);
2757 if (result
!= ISC_R_SUCCESS
)
2759 dns_name_init(&fctx
->domain
, NULL
);
2760 dns_rdataset_init(&fctx
->nameservers
);
2763 fctx
->options
= options
;
2765 * Note! We do not attach to the task. We are relying on the
2766 * resolver to ensure that this task doesn't go away while we are
2770 fctx
->references
= 0;
2771 fctx
->bucketnum
= bucketnum
;
2772 fctx
->state
= fetchstate_init
;
2773 fctx
->want_shutdown
= ISC_FALSE
;
2774 fctx
->cloned
= ISC_FALSE
;
2775 ISC_LIST_INIT(fctx
->queries
);
2776 ISC_LIST_INIT(fctx
->finds
);
2777 ISC_LIST_INIT(fctx
->altfinds
);
2778 ISC_LIST_INIT(fctx
->forwaddrs
);
2779 ISC_LIST_INIT(fctx
->altaddrs
);
2780 ISC_LIST_INIT(fctx
->forwarders
);
2781 fctx
->fwdpolicy
= dns_fwdpolicy_none
;
2782 ISC_LIST_INIT(fctx
->bad
);
2783 ISC_LIST_INIT(fctx
->validators
);
2785 fctx
->altfind
= NULL
;
2789 fctx
->attributes
= 0;
2792 dns_name_init(&fctx
->nsname
, NULL
);
2793 fctx
->nsfetch
= NULL
;
2794 dns_rdataset_init(&fctx
->nsrrset
);
2796 if (domain
== NULL
) {
2797 dns_forwarders_t
*forwarders
= NULL
;
2798 unsigned int labels
;
2801 * DS records are found in the parent server.
2802 * Strip label to get the correct forwarder (if any).
2804 if (fctx
->type
== dns_rdatatype_ds
&&
2805 dns_name_countlabels(name
) > 1) {
2806 dns_name_init(&suffix
, NULL
);
2807 labels
= dns_name_countlabels(name
);
2808 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
2811 dns_fixedname_init(&fixed
);
2812 domain
= dns_fixedname_name(&fixed
);
2813 result
= dns_fwdtable_find2(fctx
->res
->view
->fwdtable
, name
,
2814 domain
, &forwarders
);
2815 if (result
== ISC_R_SUCCESS
)
2816 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
2818 if (fctx
->fwdpolicy
!= dns_fwdpolicy_only
) {
2820 * The caller didn't supply a query domain and
2821 * nameservers, and we're not in forward-only mode,
2822 * so find the best nameservers to use.
2824 if (dns_rdatatype_atparent(type
))
2825 findoptions
|= DNS_DBFIND_NOEXACT
;
2826 result
= dns_view_findzonecut(res
->view
, name
, domain
,
2827 0, findoptions
, ISC_TRUE
,
2830 if (result
!= ISC_R_SUCCESS
)
2832 result
= dns_name_dup(domain
, res
->mctx
, &fctx
->domain
);
2833 if (result
!= ISC_R_SUCCESS
) {
2834 dns_rdataset_disassociate(&fctx
->nameservers
);
2839 * We're in forward-only mode. Set the query domain.
2841 result
= dns_name_dup(domain
, res
->mctx
, &fctx
->domain
);
2842 if (result
!= ISC_R_SUCCESS
)
2846 result
= dns_name_dup(domain
, res
->mctx
, &fctx
->domain
);
2847 if (result
!= ISC_R_SUCCESS
)
2849 dns_rdataset_clone(nameservers
, &fctx
->nameservers
);
2852 INSIST(dns_name_issubdomain(&fctx
->name
, &fctx
->domain
));
2854 fctx
->qmessage
= NULL
;
2855 result
= dns_message_create(res
->mctx
, DNS_MESSAGE_INTENTRENDER
,
2858 if (result
!= ISC_R_SUCCESS
)
2859 goto cleanup_domain
;
2861 fctx
->rmessage
= NULL
;
2862 result
= dns_message_create(res
->mctx
, DNS_MESSAGE_INTENTPARSE
,
2865 if (result
!= ISC_R_SUCCESS
)
2866 goto cleanup_qmessage
;
2869 * Compute an expiration time for the entire fetch.
2871 isc_interval_set(&interval
, 30, 0); /* XXXRTH constant */
2872 iresult
= isc_time_nowplusinterval(&fctx
->expires
, &interval
);
2873 if (iresult
!= ISC_R_SUCCESS
) {
2874 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2875 "isc_time_nowplusinterval: %s",
2876 isc_result_totext(iresult
));
2877 result
= ISC_R_UNEXPECTED
;
2878 goto cleanup_rmessage
;
2882 * Default retry interval initialization. We set the interval now
2883 * mostly so it won't be uninitialized. It will be set to the
2884 * correct value before a query is issued.
2886 isc_interval_set(&fctx
->interval
, 2, 0);
2889 * Create an inactive timer. It will be made active when the fetch
2890 * is actually started.
2893 iresult
= isc_timer_create(res
->timermgr
, isc_timertype_inactive
,
2895 res
->buckets
[bucketnum
].task
, fctx_timeout
,
2896 fctx
, &fctx
->timer
);
2897 if (iresult
!= ISC_R_SUCCESS
) {
2898 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2899 "isc_timer_create: %s",
2900 isc_result_totext(iresult
));
2901 result
= ISC_R_UNEXPECTED
;
2902 goto cleanup_rmessage
;
2906 * Attach to the view's cache and adb.
2909 dns_db_attach(res
->view
->cachedb
, &fctx
->cache
);
2911 dns_adb_attach(res
->view
->adb
, &fctx
->adb
);
2913 ISC_LIST_INIT(fctx
->events
);
2914 ISC_LINK_INIT(fctx
, link
);
2915 fctx
->magic
= FCTX_MAGIC
;
2917 ISC_LIST_APPEND(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
2921 UNLOCK(&res
->nlock
);
2925 return (ISC_R_SUCCESS
);
2928 dns_message_destroy(&fctx
->rmessage
);
2931 dns_message_destroy(&fctx
->qmessage
);
2934 if (dns_name_countlabels(&fctx
->domain
) > 0)
2935 dns_name_free(&fctx
->domain
, res
->mctx
);
2936 if (dns_rdataset_isassociated(&fctx
->nameservers
))
2937 dns_rdataset_disassociate(&fctx
->nameservers
);
2940 dns_name_free(&fctx
->name
, res
->mctx
);
2943 isc_mem_free(res
->mctx
, fctx
->info
);
2946 isc_mem_put(res
->mctx
, fctx
, sizeof(*fctx
));
2954 static inline isc_boolean_t
2955 is_lame(fetchctx_t
*fctx
) {
2956 dns_message_t
*message
= fctx
->rmessage
;
2958 dns_rdataset_t
*rdataset
;
2959 isc_result_t result
;
2961 if (message
->rcode
!= dns_rcode_noerror
&&
2962 message
->rcode
!= dns_rcode_nxdomain
)
2965 if (message
->counts
[DNS_SECTION_ANSWER
] != 0)
2968 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
2971 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
2972 while (result
== ISC_R_SUCCESS
) {
2974 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
2975 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2977 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2978 dns_namereln_t namereln
;
2980 unsigned int labels
;
2981 if (rdataset
->type
!= dns_rdatatype_ns
)
2983 namereln
= dns_name_fullcompare(name
, &fctx
->domain
,
2985 if (namereln
== dns_namereln_equal
&&
2986 (message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
2988 if (namereln
== dns_namereln_subdomain
)
2992 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
2999 log_lame(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
) {
3000 char namebuf
[DNS_NAME_FORMATSIZE
];
3001 char domainbuf
[DNS_NAME_FORMATSIZE
];
3002 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
3004 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
3005 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
3006 isc_sockaddr_format(&addrinfo
->sockaddr
, addrbuf
, sizeof(addrbuf
));
3007 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
3008 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
3009 "lame server resolving '%s' (in '%s'?): %s",
3010 namebuf
, domainbuf
, addrbuf
);
3013 static inline isc_result_t
3014 same_question(fetchctx_t
*fctx
) {
3015 isc_result_t result
;
3016 dns_message_t
*message
= fctx
->rmessage
;
3018 dns_rdataset_t
*rdataset
;
3021 * Caller must be holding the fctx lock.
3025 * XXXRTH Currently we support only one question.
3027 if (message
->counts
[DNS_SECTION_QUESTION
] != 1)
3028 return (DNS_R_FORMERR
);
3030 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
3031 if (result
!= ISC_R_SUCCESS
)
3034 dns_message_currentname(message
, DNS_SECTION_QUESTION
, &name
);
3035 rdataset
= ISC_LIST_HEAD(name
->list
);
3036 INSIST(rdataset
!= NULL
);
3037 INSIST(ISC_LIST_NEXT(rdataset
, link
) == NULL
);
3038 if (fctx
->type
!= rdataset
->type
||
3039 fctx
->res
->rdclass
!= rdataset
->rdclass
||
3040 !dns_name_equal(&fctx
->name
, name
))
3041 return (DNS_R_FORMERR
);
3043 return (ISC_R_SUCCESS
);
3047 clone_results(fetchctx_t
*fctx
) {
3048 dns_fetchevent_t
*event
, *hevent
;
3049 isc_result_t result
;
3050 dns_name_t
*name
, *hname
;
3052 FCTXTRACE("clone_results");
3055 * Set up any other events to have the same data as the first
3058 * Caller must be holding the appropriate lock.
3061 fctx
->cloned
= ISC_TRUE
;
3062 hevent
= ISC_LIST_HEAD(fctx
->events
);
3065 hname
= dns_fixedname_name(&hevent
->foundname
);
3066 for (event
= ISC_LIST_NEXT(hevent
, ev_link
);
3068 event
= ISC_LIST_NEXT(event
, ev_link
)) {
3069 name
= dns_fixedname_name(&event
->foundname
);
3070 result
= dns_name_copy(hname
, name
, NULL
);
3071 if (result
!= ISC_R_SUCCESS
)
3072 event
->result
= result
;
3074 event
->result
= hevent
->result
;
3075 dns_db_attach(hevent
->db
, &event
->db
);
3076 dns_db_attachnode(hevent
->db
, hevent
->node
, &event
->node
);
3077 INSIST(hevent
->rdataset
!= NULL
);
3078 INSIST(event
->rdataset
!= NULL
);
3079 if (dns_rdataset_isassociated(hevent
->rdataset
))
3080 dns_rdataset_clone(hevent
->rdataset
, event
->rdataset
);
3081 INSIST(! (hevent
->sigrdataset
== NULL
&&
3082 event
->sigrdataset
!= NULL
));
3083 if (hevent
->sigrdataset
!= NULL
&&
3084 dns_rdataset_isassociated(hevent
->sigrdataset
) &&
3085 event
->sigrdataset
!= NULL
)
3086 dns_rdataset_clone(hevent
->sigrdataset
,
3087 event
->sigrdataset
);
3091 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3092 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3093 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3094 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3095 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3096 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3097 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3101 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3102 * no references and is no longer waiting for any events). If this
3103 * was the last fctx in the resolver, destroy the resolver.
3106 * '*fctx' is shutting down.
3109 maybe_destroy(fetchctx_t
*fctx
) {
3110 unsigned int bucketnum
;
3111 isc_boolean_t bucket_empty
= ISC_FALSE
;
3112 dns_resolver_t
*res
= fctx
->res
;
3113 dns_validator_t
*validator
;
3115 REQUIRE(SHUTTINGDOWN(fctx
));
3117 if (fctx
->pending
!= 0 || fctx
->nqueries
!= 0)
3120 for (validator
= ISC_LIST_HEAD(fctx
->validators
);
3122 validator
= ISC_LIST_HEAD(fctx
->validators
)) {
3123 ISC_LIST_UNLINK(fctx
->validators
, validator
, link
);
3124 dns_validator_cancel(validator
);
3125 dns_validator_destroy(&validator
);
3128 bucketnum
= fctx
->bucketnum
;
3129 LOCK(&res
->buckets
[bucketnum
].lock
);
3130 if (fctx
->references
== 0)
3131 bucket_empty
= fctx_destroy(fctx
);
3132 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3139 * The validator has finished.
3142 validated(isc_task_t
*task
, isc_event_t
*event
) {
3143 isc_result_t result
= ISC_R_SUCCESS
;
3144 isc_result_t eresult
= ISC_R_SUCCESS
;
3147 dns_validatorevent_t
*vevent
;
3148 dns_fetchevent_t
*hevent
;
3149 dns_rdataset_t
*ardataset
= NULL
;
3150 dns_rdataset_t
*asigrdataset
= NULL
;
3151 dns_dbnode_t
*node
= NULL
;
3152 isc_boolean_t negative
;
3153 isc_boolean_t chaining
;
3154 isc_boolean_t sentresponse
;
3156 dns_dbnode_t
*nsnode
= NULL
;
3158 dns_rdataset_t
*rdataset
;
3159 dns_rdataset_t
*sigrdataset
;
3160 dns_valarg_t
*valarg
;
3161 dns_adbaddrinfo_t
*addrinfo
;
3163 UNUSED(task
); /* for now */
3165 REQUIRE(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
3166 valarg
= event
->ev_arg
;
3167 fctx
= valarg
->fctx
;
3168 addrinfo
= valarg
->addrinfo
;
3169 REQUIRE(VALID_FCTX(fctx
));
3170 REQUIRE(!ISC_LIST_EMPTY(fctx
->validators
));
3172 vevent
= (dns_validatorevent_t
*)event
;
3174 FCTXTRACE("received validation completion event");
3176 ISC_LIST_UNLINK(fctx
->validators
, vevent
->validator
, link
);
3179 * Destroy the validator early so that we can
3180 * destroy the fctx if necessary.
3182 dns_validator_destroy(&vevent
->validator
);
3183 isc_mem_put(fctx
->res
->mctx
, valarg
, sizeof(*valarg
));
3185 negative
= ISC_TF(vevent
->rdataset
== NULL
);
3187 sentresponse
= ISC_TF((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0);
3190 * If shutting down, ignore the results. Check to see if we're
3191 * done waiting for validator completions and ADB pending events; if
3192 * so, destroy the fctx.
3194 if (SHUTTINGDOWN(fctx
) && !sentresponse
) {
3195 maybe_destroy(fctx
); /* Locks bucket. */
3199 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3202 * If chaining, we need to make sure that the right result code is
3203 * returned, and that the rdatasets are bound.
3205 if (vevent
->result
== ISC_R_SUCCESS
&&
3207 vevent
->rdataset
!= NULL
&&
3208 CHAINING(vevent
->rdataset
))
3210 if (vevent
->rdataset
->type
== dns_rdatatype_cname
)
3211 eresult
= DNS_R_CNAME
;
3213 INSIST(vevent
->rdataset
->type
== dns_rdatatype_dname
);
3214 eresult
= DNS_R_DNAME
;
3216 chaining
= ISC_TRUE
;
3218 chaining
= ISC_FALSE
;
3221 * Either we're not shutting down, or we are shutting down but want
3222 * to cache the result anyway (if this was a validation started by
3223 * a query with cd set)
3226 hevent
= ISC_LIST_HEAD(fctx
->events
);
3227 if (hevent
!= NULL
) {
3228 if (!negative
&& !chaining
&&
3229 (fctx
->type
== dns_rdatatype_any
||
3230 fctx
->type
== dns_rdatatype_rrsig
||
3231 fctx
->type
== dns_rdatatype_sig
)) {
3233 * Don't bind rdatasets; the caller
3234 * will iterate the node.
3237 ardataset
= hevent
->rdataset
;
3238 asigrdataset
= hevent
->sigrdataset
;
3242 if (vevent
->result
!= ISC_R_SUCCESS
) {
3243 FCTXTRACE("validation failed");
3244 result
= ISC_R_NOTFOUND
;
3245 if (vevent
->rdataset
!= NULL
)
3246 result
= dns_db_findnode(fctx
->cache
, vevent
->name
,
3248 if (result
== ISC_R_SUCCESS
)
3249 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
3251 if (result
== ISC_R_SUCCESS
&& vevent
->sigrdataset
!= NULL
)
3252 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
3253 dns_rdatatype_rrsig
,
3255 if (result
== ISC_R_SUCCESS
)
3256 dns_db_detachnode(fctx
->cache
, &node
);
3257 result
= vevent
->result
;
3258 add_bad(fctx
, &addrinfo
->sockaddr
, result
);
3259 isc_event_free(&event
);
3260 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3261 if (!ISC_LIST_EMPTY(fctx
->validators
))
3262 dns_validator_send(ISC_LIST_HEAD(fctx
->validators
));
3263 else if (sentresponse
)
3264 fctx_done(fctx
, result
); /* Locks bucket. */
3266 fctx_try(fctx
); /* Locks bucket. */
3270 isc_stdtime_get(&now
);
3273 dns_rdatatype_t covers
;
3274 FCTXTRACE("nonexistence validation OK");
3276 if (fctx
->rmessage
->rcode
== dns_rcode_nxdomain
)
3277 covers
= dns_rdatatype_any
;
3279 covers
= fctx
->type
;
3281 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
,
3283 if (result
!= ISC_R_SUCCESS
)
3284 goto noanswer_response
;
3287 * If we are asking for a SOA record set the cache time
3288 * to zero to facilitate locating the containing zone of
3291 ttl
= fctx
->res
->view
->maxncachettl
;
3292 if (fctx
->type
== dns_rdatatype_soa
&&
3293 covers
== dns_rdatatype_any
)
3296 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
3298 ardataset
, &eresult
);
3299 if (result
!= ISC_R_SUCCESS
)
3300 goto noanswer_response
;
3301 goto answer_response
;
3304 FCTXTRACE("validation OK");
3306 if (vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] != NULL
) {
3308 result
= dns_rdataset_addnoqname(vevent
->rdataset
,
3309 vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
]);
3310 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3311 INSIST(vevent
->sigrdataset
!= NULL
);
3312 vevent
->sigrdataset
->ttl
= vevent
->rdataset
->ttl
;
3316 * The data was already cached as pending data.
3317 * Re-cache it as secure and bind the cached
3318 * rdatasets to the first event on the fetch
3321 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
, &node
);
3322 if (result
!= ISC_R_SUCCESS
)
3323 goto noanswer_response
;
3325 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
3326 vevent
->rdataset
, 0, ardataset
);
3327 if (result
!= ISC_R_SUCCESS
&&
3328 result
!= DNS_R_UNCHANGED
)
3329 goto noanswer_response
;
3330 if (vevent
->sigrdataset
!= NULL
) {
3331 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
3332 vevent
->sigrdataset
, 0,
3334 if (result
!= ISC_R_SUCCESS
&&
3335 result
!= DNS_R_UNCHANGED
)
3336 goto noanswer_response
;
3341 * If we only deferred the destroy because we wanted to cache
3342 * the data, destroy now.
3344 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3345 if (SHUTTINGDOWN(fctx
))
3346 maybe_destroy(fctx
); /* Locks bucket. */
3350 if (!ISC_LIST_EMPTY(fctx
->validators
)) {
3352 INSIST(fctx
->type
== dns_rdatatype_any
||
3353 fctx
->type
== dns_rdatatype_rrsig
||
3354 fctx
->type
== dns_rdatatype_sig
);
3356 * Don't send a response yet - we have
3357 * more rdatasets that still need to
3360 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3361 dns_validator_send(ISC_LIST_HEAD(fctx
->validators
));
3367 * Cache any NS/NSEC records that happened to be validated.
3369 result
= dns_message_firstname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
);
3370 while (result
== ISC_R_SUCCESS
) {
3372 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
,
3374 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3376 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3377 if ((rdataset
->type
!= dns_rdatatype_ns
&&
3378 rdataset
->type
!= dns_rdatatype_nsec
) ||
3379 rdataset
->trust
!= dns_trust_secure
)
3381 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
3382 sigrdataset
!= NULL
;
3383 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
3384 if (sigrdataset
->type
!= dns_rdatatype_rrsig
||
3385 sigrdataset
->covers
!= rdataset
->type
)
3389 if (sigrdataset
== NULL
||
3390 sigrdataset
->trust
!= dns_trust_secure
)
3392 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
,
3394 if (result
!= ISC_R_SUCCESS
)
3397 result
= dns_db_addrdataset(fctx
->cache
, nsnode
, NULL
,
3398 now
, rdataset
, 0, NULL
);
3399 if (result
== ISC_R_SUCCESS
)
3400 result
= dns_db_addrdataset(fctx
->cache
, nsnode
,
3404 dns_db_detachnode(fctx
->cache
, &nsnode
);
3406 result
= dns_message_nextname(fctx
->rmessage
,
3407 DNS_SECTION_AUTHORITY
);
3410 result
= ISC_R_SUCCESS
;
3413 * Respond with an answer, positive or negative,
3414 * as opposed to an error. 'node' must be non-NULL.
3417 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
3419 if (hevent
!= NULL
) {
3420 hevent
->result
= eresult
;
3421 RUNTIME_CHECK(dns_name_copy(vevent
->name
,
3422 dns_fixedname_name(&hevent
->foundname
), NULL
)
3424 dns_db_attach(fctx
->cache
, &hevent
->db
);
3425 hevent
->node
= node
;
3427 clone_results(fctx
);
3432 dns_db_detachnode(fctx
->cache
, &node
);
3434 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3436 fctx_done(fctx
, result
); /* Locks bucket. */
3439 isc_event_free(&event
);
3442 static inline isc_result_t
3443 cache_name(fetchctx_t
*fctx
, dns_name_t
*name
, dns_adbaddrinfo_t
*addrinfo
,
3444 isc_stdtime_t now
) {
3445 dns_rdataset_t
*rdataset
, *sigrdataset
;
3446 dns_rdataset_t
*addedrdataset
, *ardataset
, *asigrdataset
;
3447 dns_rdataset_t
*valrdataset
= NULL
, *valsigrdataset
= NULL
;
3448 dns_dbnode_t
*node
, **anodep
;
3451 dns_resolver_t
*res
;
3452 isc_boolean_t need_validation
, secure_domain
, have_answer
;
3453 isc_result_t result
, eresult
;
3454 dns_fetchevent_t
*event
;
3455 unsigned int options
;
3458 unsigned int valoptions
= 0;
3461 * The appropriate bucket lock must be held.
3465 need_validation
= ISC_FALSE
;
3466 secure_domain
= ISC_FALSE
;
3467 have_answer
= ISC_FALSE
;
3468 eresult
= ISC_R_SUCCESS
;
3469 task
= res
->buckets
[fctx
->bucketnum
].task
;
3472 * Is DNSSEC validation required for this name?
3474 result
= dns_keytable_issecuredomain(res
->view
->secroots
, name
,
3476 if (result
!= ISC_R_SUCCESS
)
3479 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
3480 valoptions
= DNS_VALIDATOR_DLV
;
3481 secure_domain
= ISC_TRUE
;
3484 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
3485 need_validation
= ISC_FALSE
;
3487 need_validation
= secure_domain
;
3493 asigrdataset
= NULL
;
3495 if ((name
->attributes
& DNS_NAMEATTR_ANSWER
) != 0 &&
3497 have_answer
= ISC_TRUE
;
3498 event
= ISC_LIST_HEAD(fctx
->events
);
3499 if (event
!= NULL
) {
3501 aname
= dns_fixedname_name(&event
->foundname
);
3502 result
= dns_name_copy(name
, aname
, NULL
);
3503 if (result
!= ISC_R_SUCCESS
)
3505 anodep
= &event
->node
;
3507 * If this is an ANY, SIG or RRSIG query, we're not
3508 * going to return any rdatasets, unless we encountered
3509 * a CNAME or DNAME as "the answer". In this case,
3510 * we're going to return DNS_R_CNAME or DNS_R_DNAME
3511 * and we must set up the rdatasets.
3513 if ((fctx
->type
!= dns_rdatatype_any
&&
3514 fctx
->type
!= dns_rdatatype_rrsig
&&
3515 fctx
->type
!= dns_rdatatype_sig
) ||
3516 (name
->attributes
& DNS_NAMEATTR_CHAINING
) != 0) {
3517 ardataset
= event
->rdataset
;
3518 asigrdataset
= event
->sigrdataset
;
3524 * Find or create the cache node.
3527 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
3528 if (result
!= ISC_R_SUCCESS
)
3532 * Cache or validate each cacheable rdataset.
3534 fail
= ISC_TF((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMESFAIL
) != 0);
3535 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3537 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3538 if (!CACHE(rdataset
))
3540 if (CHECKNAMES(rdataset
)) {
3541 char namebuf
[DNS_NAME_FORMATSIZE
];
3542 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3543 char classbuf
[DNS_RDATATYPE_FORMATSIZE
];
3545 dns_name_format(name
, namebuf
, sizeof(namebuf
));
3546 dns_rdatatype_format(rdataset
->type
, typebuf
,
3548 dns_rdataclass_format(rdataset
->rdclass
, classbuf
,
3550 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
3551 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
3552 "check-names %s %s/%s/%s",
3553 fail
? "failure" : "warning",
3554 namebuf
, typebuf
, classbuf
);
3556 if (ANSWER(rdataset
))
3557 return (DNS_R_BADNAME
);
3563 * Enforce the configure maximum cache TTL.
3565 if (rdataset
->ttl
> res
->view
->maxcachettl
)
3566 rdataset
->ttl
= res
->view
->maxcachettl
;
3569 * If this rrset is in a secure domain, do DNSSEC validation
3570 * for it, unless it is glue.
3572 if (secure_domain
&& rdataset
->trust
!= dns_trust_glue
) {
3574 * RRSIGs are validated as part of validating the
3577 if (rdataset
->type
== dns_rdatatype_rrsig
)
3580 * Find the SIG for this rdataset, if we have it.
3582 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
3583 sigrdataset
!= NULL
;
3584 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
3585 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
3586 sigrdataset
->covers
== rdataset
->type
)
3589 if (sigrdataset
== NULL
) {
3590 if (!ANSWER(rdataset
) && need_validation
) {
3592 * Ignore non-answer rdatasets that
3593 * are missing signatures.
3600 * Normalize the rdataset and sigrdataset TTLs.
3602 if (sigrdataset
!= NULL
) {
3603 rdataset
->ttl
= ISC_MIN(rdataset
->ttl
,
3605 sigrdataset
->ttl
= rdataset
->ttl
;
3609 * Cache this rdataset/sigrdataset pair as
3612 rdataset
->trust
= dns_trust_pending
;
3613 if (sigrdataset
!= NULL
)
3614 sigrdataset
->trust
= dns_trust_pending
;
3615 if (!need_validation
)
3616 addedrdataset
= ardataset
;
3618 addedrdataset
= NULL
;
3619 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
,
3622 if (result
== DNS_R_UNCHANGED
)
3623 result
= ISC_R_SUCCESS
;
3624 if (result
!= ISC_R_SUCCESS
)
3626 if (sigrdataset
!= NULL
) {
3627 if (!need_validation
)
3628 addedrdataset
= asigrdataset
;
3630 addedrdataset
= NULL
;
3631 result
= dns_db_addrdataset(fctx
->cache
,
3635 if (result
== DNS_R_UNCHANGED
)
3636 result
= ISC_R_SUCCESS
;
3637 if (result
!= ISC_R_SUCCESS
)
3639 } else if (!ANSWER(rdataset
))
3642 if (ANSWER(rdataset
) && need_validation
) {
3643 if (fctx
->type
!= dns_rdatatype_any
&&
3644 fctx
->type
!= dns_rdatatype_rrsig
&&
3645 fctx
->type
!= dns_rdatatype_sig
) {
3647 * This is The Answer. We will
3648 * validate it, but first we cache
3649 * the rest of the response - it may
3650 * contain useful keys.
3652 INSIST(valrdataset
== NULL
&&
3653 valsigrdataset
== NULL
);
3654 valrdataset
= rdataset
;
3655 valsigrdataset
= sigrdataset
;
3658 * This is one of (potentially)
3659 * multiple answers to an ANY
3660 * or SIG query. To keep things
3661 * simple, we just start the
3662 * validator right away rather
3663 * than caching first and
3664 * having to remember which
3665 * rdatasets needed validation.
3667 result
= valcreate(fctx
, addrinfo
,
3668 name
, rdataset
->type
,
3673 * Defer any further validations.
3674 * This prevents multiple validators
3675 * from manipulating fctx->rmessage
3678 valoptions
|= DNS_VALIDATOR_DEFER
;
3680 } else if (CHAINING(rdataset
)) {
3681 if (rdataset
->type
== dns_rdatatype_cname
)
3682 eresult
= DNS_R_CNAME
;
3684 INSIST(rdataset
->type
==
3685 dns_rdatatype_dname
);
3686 eresult
= DNS_R_DNAME
;
3689 } else if (!EXTERNAL(rdataset
)) {
3691 * It's OK to cache this rdataset now.
3693 if (ANSWER(rdataset
))
3694 addedrdataset
= ardataset
;
3695 else if (ANSWERSIG(rdataset
))
3696 addedrdataset
= asigrdataset
;
3698 addedrdataset
= NULL
;
3699 if (CHAINING(rdataset
)) {
3700 if (rdataset
->type
== dns_rdatatype_cname
)
3701 eresult
= DNS_R_CNAME
;
3703 INSIST(rdataset
->type
==
3704 dns_rdatatype_dname
);
3705 eresult
= DNS_R_DNAME
;
3708 if (rdataset
->trust
== dns_trust_glue
&&
3709 (rdataset
->type
== dns_rdatatype_ns
||
3710 (rdataset
->type
== dns_rdatatype_rrsig
&&
3711 rdataset
->covers
== dns_rdatatype_ns
))) {
3713 * If the trust level is 'dns_trust_glue'
3714 * then we are adding data from a referral
3715 * we got while executing the search algorithm.
3716 * New referral data always takes precedence
3717 * over the existing cache contents.
3719 options
= DNS_DBADD_FORCE
;
3723 * Now we can add the rdataset.
3725 result
= dns_db_addrdataset(fctx
->cache
,
3730 if (result
== DNS_R_UNCHANGED
) {
3731 if (ANSWER(rdataset
) &&
3732 ardataset
!= NULL
&&
3733 ardataset
->type
== 0) {
3735 * The answer in the cache is better
3736 * than the answer we found, and is
3737 * a negative cache entry, so we
3738 * must set eresult appropriately.
3740 if (NXDOMAIN(ardataset
))
3742 DNS_R_NCACHENXDOMAIN
;
3745 DNS_R_NCACHENXRRSET
;
3747 result
= ISC_R_SUCCESS
;
3748 } else if (result
!= ISC_R_SUCCESS
)
3753 if (valrdataset
!= NULL
)
3754 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
3755 valrdataset
, valsigrdataset
, valoptions
,
3758 if (result
== ISC_R_SUCCESS
&& have_answer
) {
3759 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
3760 if (event
!= NULL
) {
3761 event
->result
= eresult
;
3762 dns_db_attach(fctx
->cache
, adbp
);
3765 clone_results(fctx
);
3770 dns_db_detachnode(fctx
->cache
, &node
);
3775 static inline isc_result_t
3776 cache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, isc_stdtime_t now
)
3778 isc_result_t result
;
3779 dns_section_t section
;
3782 FCTXTRACE("cache_message");
3784 fctx
->attributes
&= ~FCTX_ATTR_WANTCACHE
;
3786 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3788 for (section
= DNS_SECTION_ANSWER
;
3789 section
<= DNS_SECTION_ADDITIONAL
;
3791 result
= dns_message_firstname(fctx
->rmessage
, section
);
3792 while (result
== ISC_R_SUCCESS
) {
3794 dns_message_currentname(fctx
->rmessage
, section
,
3796 if ((name
->attributes
& DNS_NAMEATTR_CACHE
) != 0) {
3797 result
= cache_name(fctx
, name
, addrinfo
, now
);
3798 if (result
!= ISC_R_SUCCESS
)
3801 result
= dns_message_nextname(fctx
->rmessage
, section
);
3803 if (result
!= ISC_R_NOMORE
)
3806 if (result
== ISC_R_NOMORE
)
3807 result
= ISC_R_SUCCESS
;
3809 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3815 * Do what dns_ncache_add() does, and then compute an appropriate eresult.
3818 ncache_adderesult(dns_message_t
*message
, dns_db_t
*cache
, dns_dbnode_t
*node
,
3819 dns_rdatatype_t covers
, isc_stdtime_t now
, dns_ttl_t maxttl
,
3820 dns_rdataset_t
*ardataset
,
3821 isc_result_t
*eresultp
)
3823 isc_result_t result
;
3824 dns_rdataset_t rdataset
;
3826 if (ardataset
== NULL
) {
3827 dns_rdataset_init(&rdataset
);
3828 ardataset
= &rdataset
;
3830 result
= dns_ncache_add(message
, cache
, node
, covers
, now
,
3832 if (result
== DNS_R_UNCHANGED
|| result
== ISC_R_SUCCESS
) {
3834 * If the cache now contains a negative entry and we
3835 * care about whether it is DNS_R_NCACHENXDOMAIN or
3836 * DNS_R_NCACHENXRRSET then extract it.
3838 if (ardataset
->type
== 0) {
3840 * The cache data is a negative cache entry.
3842 if (NXDOMAIN(ardataset
))
3843 *eresultp
= DNS_R_NCACHENXDOMAIN
;
3845 *eresultp
= DNS_R_NCACHENXRRSET
;
3848 * Either we don't care about the nature of the
3849 * cache rdataset (because no fetch is interested
3850 * in the outcome), or the cache rdataset is not
3851 * a negative cache entry. Whichever case it is,
3852 * we can return success.
3854 * XXXRTH There's a CNAME/DNAME problem here.
3856 *eresultp
= ISC_R_SUCCESS
;
3858 result
= ISC_R_SUCCESS
;
3860 if (ardataset
== &rdataset
&& dns_rdataset_isassociated(ardataset
))
3861 dns_rdataset_disassociate(ardataset
);
3866 static inline isc_result_t
3867 ncache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
3868 dns_rdatatype_t covers
, isc_stdtime_t now
)
3870 isc_result_t result
, eresult
;
3872 dns_resolver_t
*res
;
3874 dns_dbnode_t
*node
, **anodep
;
3875 dns_rdataset_t
*ardataset
;
3876 isc_boolean_t need_validation
, secure_domain
;
3878 dns_fetchevent_t
*event
;
3880 unsigned int valoptions
= 0;
3882 FCTXTRACE("ncache_message");
3884 fctx
->attributes
&= ~FCTX_ATTR_WANTNCACHE
;
3887 need_validation
= ISC_FALSE
;
3888 secure_domain
= ISC_FALSE
;
3889 eresult
= ISC_R_SUCCESS
;
3894 * XXXMPA remove when we follow cnames and adjust the setting
3895 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
3897 INSIST(fctx
->rmessage
->counts
[DNS_SECTION_ANSWER
] == 0);
3900 * Is DNSSEC validation required for this name?
3902 result
= dns_keytable_issecuredomain(res
->view
->secroots
, name
,
3904 if (result
!= ISC_R_SUCCESS
)
3907 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
3908 valoptions
= DNS_VALIDATOR_DLV
;
3909 secure_domain
= ISC_TRUE
;
3912 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
3913 need_validation
= ISC_FALSE
;
3915 need_validation
= secure_domain
;
3917 if (secure_domain
) {
3919 * Mark all rdatasets as pending.
3921 dns_rdataset_t
*trdataset
;
3924 result
= dns_message_firstname(fctx
->rmessage
,
3925 DNS_SECTION_AUTHORITY
);
3926 while (result
== ISC_R_SUCCESS
) {
3928 dns_message_currentname(fctx
->rmessage
,
3929 DNS_SECTION_AUTHORITY
,
3931 for (trdataset
= ISC_LIST_HEAD(tname
->list
);
3933 trdataset
= ISC_LIST_NEXT(trdataset
, link
))
3934 trdataset
->trust
= dns_trust_pending
;
3935 result
= dns_message_nextname(fctx
->rmessage
,
3936 DNS_SECTION_AUTHORITY
);
3938 if (result
!= ISC_R_NOMORE
)
3943 if (need_validation
) {
3945 * Do negative response validation.
3947 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
3948 NULL
, NULL
, valoptions
,
3949 res
->buckets
[fctx
->bucketnum
].task
);
3951 * If validation is necessary, return now. Otherwise continue
3952 * to process the message, letting the validation complete
3953 * in its own good time.
3958 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
3964 if (!HAVE_ANSWER(fctx
)) {
3965 event
= ISC_LIST_HEAD(fctx
->events
);
3966 if (event
!= NULL
) {
3968 aname
= dns_fixedname_name(&event
->foundname
);
3969 result
= dns_name_copy(name
, aname
, NULL
);
3970 if (result
!= ISC_R_SUCCESS
)
3972 anodep
= &event
->node
;
3973 ardataset
= event
->rdataset
;
3978 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
3979 if (result
!= ISC_R_SUCCESS
)
3983 * If we are asking for a SOA record set the cache time
3984 * to zero to facilitate locating the containing zone of
3987 ttl
= fctx
->res
->view
->maxncachettl
;
3988 if (fctx
->type
== dns_rdatatype_soa
&&
3989 covers
== dns_rdatatype_any
)
3992 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
3993 covers
, now
, ttl
, ardataset
, &eresult
);
3994 if (result
!= ISC_R_SUCCESS
)
3997 if (!HAVE_ANSWER(fctx
)) {
3998 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
3999 if (event
!= NULL
) {
4000 event
->result
= eresult
;
4001 dns_db_attach(fctx
->cache
, adbp
);
4004 clone_results(fctx
);
4009 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
4012 dns_db_detachnode(fctx
->cache
, &node
);
4018 mark_related(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4019 isc_boolean_t external
, isc_boolean_t gluing
)
4021 name
->attributes
|= DNS_NAMEATTR_CACHE
;
4023 rdataset
->trust
= dns_trust_glue
;
4025 * Glue with 0 TTL causes problems. We force the TTL to
4026 * 1 second to prevent this.
4028 if (rdataset
->ttl
== 0)
4031 rdataset
->trust
= dns_trust_additional
;
4033 * Avoid infinite loops by only marking new rdatasets.
4035 if (!CACHE(rdataset
)) {
4036 name
->attributes
|= DNS_NAMEATTR_CHASE
;
4037 rdataset
->attributes
|= DNS_RDATASETATTR_CHASE
;
4039 rdataset
->attributes
|= DNS_RDATASETATTR_CACHE
;
4041 rdataset
->attributes
|= DNS_RDATASETATTR_EXTERNAL
;
4045 check_related(void *arg
, dns_name_t
*addname
, dns_rdatatype_t type
) {
4046 fetchctx_t
*fctx
= arg
;
4047 isc_result_t result
;
4049 dns_rdataset_t
*rdataset
;
4050 isc_boolean_t external
;
4051 dns_rdatatype_t rtype
;
4052 isc_boolean_t gluing
;
4054 REQUIRE(VALID_FCTX(fctx
));
4062 result
= dns_message_findname(fctx
->rmessage
, DNS_SECTION_ADDITIONAL
,
4063 addname
, dns_rdatatype_any
, 0, &name
,
4065 if (result
== ISC_R_SUCCESS
) {
4066 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
4067 if (type
== dns_rdatatype_a
) {
4068 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4070 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4071 if (rdataset
->type
== dns_rdatatype_rrsig
)
4072 rtype
= rdataset
->covers
;
4074 rtype
= rdataset
->type
;
4075 if (rtype
== dns_rdatatype_a
||
4076 rtype
== dns_rdatatype_aaaa
)
4077 mark_related(name
, rdataset
, external
,
4081 result
= dns_message_findtype(name
, type
, 0,
4083 if (result
== ISC_R_SUCCESS
) {
4084 mark_related(name
, rdataset
, external
, gluing
);
4086 * Do we have its SIG too?
4089 result
= dns_message_findtype(name
,
4090 dns_rdatatype_rrsig
,
4092 if (result
== ISC_R_SUCCESS
)
4093 mark_related(name
, rdataset
, external
,
4099 return (ISC_R_SUCCESS
);
4103 chase_additional(fetchctx_t
*fctx
) {
4104 isc_boolean_t rescan
;
4105 dns_section_t section
= DNS_SECTION_ADDITIONAL
;
4106 isc_result_t result
;
4111 for (result
= dns_message_firstname(fctx
->rmessage
, section
);
4112 result
== ISC_R_SUCCESS
;
4113 result
= dns_message_nextname(fctx
->rmessage
, section
)) {
4114 dns_name_t
*name
= NULL
;
4115 dns_rdataset_t
*rdataset
;
4116 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_ADDITIONAL
,
4118 if ((name
->attributes
& DNS_NAMEATTR_CHASE
) == 0)
4120 name
->attributes
&= ~DNS_NAMEATTR_CHASE
;
4121 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4123 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4124 if (CHASE(rdataset
)) {
4125 rdataset
->attributes
&= ~DNS_RDATASETATTR_CHASE
;
4126 (void)dns_rdataset_additionaldata(rdataset
,
4137 static inline isc_result_t
4138 cname_target(dns_rdataset_t
*rdataset
, dns_name_t
*tname
) {
4139 isc_result_t result
;
4140 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4141 dns_rdata_cname_t cname
;
4143 result
= dns_rdataset_first(rdataset
);
4144 if (result
!= ISC_R_SUCCESS
)
4146 dns_rdataset_current(rdataset
, &rdata
);
4147 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
4148 if (result
!= ISC_R_SUCCESS
)
4150 dns_name_init(tname
, NULL
);
4151 dns_name_clone(&cname
.cname
, tname
);
4152 dns_rdata_freestruct(&cname
);
4154 return (ISC_R_SUCCESS
);
4157 static inline isc_result_t
4158 dname_target(dns_rdataset_t
*rdataset
, dns_name_t
*qname
, dns_name_t
*oname
,
4159 dns_fixedname_t
*fixeddname
)
4161 isc_result_t result
;
4162 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4163 unsigned int nlabels
;
4165 dns_namereln_t namereln
;
4166 dns_rdata_dname_t dname
;
4167 dns_fixedname_t prefix
;
4170 * Get the target name of the DNAME.
4173 result
= dns_rdataset_first(rdataset
);
4174 if (result
!= ISC_R_SUCCESS
)
4176 dns_rdataset_current(rdataset
, &rdata
);
4177 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
4178 if (result
!= ISC_R_SUCCESS
)
4182 * Get the prefix of qname.
4184 namereln
= dns_name_fullcompare(qname
, oname
, &order
, &nlabels
);
4185 if (namereln
!= dns_namereln_subdomain
) {
4186 dns_rdata_freestruct(&dname
);
4187 return (DNS_R_FORMERR
);
4189 dns_fixedname_init(&prefix
);
4190 dns_name_split(qname
, nlabels
, dns_fixedname_name(&prefix
), NULL
);
4191 dns_fixedname_init(fixeddname
);
4192 result
= dns_name_concatenate(dns_fixedname_name(&prefix
),
4194 dns_fixedname_name(fixeddname
), NULL
);
4195 dns_rdata_freestruct(&dname
);
4200 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
4201 * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
4202 * response to an NS query that should be treated as a referral
4203 * even though the NS records occur in the answer section
4204 * rather than the authority section.
4207 noanswer_response(fetchctx_t
*fctx
, dns_name_t
*oqname
,
4208 isc_boolean_t bind8_ns_resp
)
4210 isc_result_t result
;
4211 dns_message_t
*message
;
4212 dns_name_t
*name
, *qname
, *ns_name
, *soa_name
, *ds_name
;
4213 dns_rdataset_t
*rdataset
, *ns_rdataset
;
4214 isc_boolean_t done
, aa
, negative_response
;
4215 dns_rdatatype_t type
;
4216 dns_section_t section
=
4217 bind8_ns_resp
? DNS_SECTION_ANSWER
: DNS_SECTION_AUTHORITY
;
4219 FCTXTRACE("noanswer_response");
4221 message
= fctx
->rmessage
;
4226 if (oqname
== NULL
) {
4228 * We have a normal, non-chained negative response or
4231 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
4235 qname
= &fctx
->name
;
4238 * We're being invoked by answer_response() after it has
4239 * followed a CNAME/DNAME chain.
4244 * If the current qname is not a subdomain of the query
4245 * domain, there's no point in looking at the authority
4246 * section without doing DNSSEC validation.
4248 * Until we do that validation, we'll just return success
4251 if (!dns_name_issubdomain(qname
, &fctx
->domain
))
4252 return (ISC_R_SUCCESS
);
4256 * We have to figure out if this is a negative response, or a
4261 * Sometimes we can tell if its a negative response by looking at
4262 * the message header.
4264 negative_response
= ISC_FALSE
;
4265 if (message
->rcode
== dns_rcode_nxdomain
||
4266 (message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
4267 message
->counts
[DNS_SECTION_AUTHORITY
] == 0))
4268 negative_response
= ISC_TRUE
;
4271 * Process the authority section.
4278 result
= dns_message_firstname(message
, section
);
4279 while (!done
&& result
== ISC_R_SUCCESS
) {
4281 dns_message_currentname(message
, section
, &name
);
4282 if (dns_name_issubdomain(name
, &fctx
->domain
)) {
4284 * Look for NS/SOA RRsets first.
4286 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4288 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4289 type
= rdataset
->type
;
4290 if (type
== dns_rdatatype_rrsig
)
4291 type
= rdataset
->covers
;
4292 if (((type
== dns_rdatatype_ns
||
4293 type
== dns_rdatatype_soa
) &&
4294 !dns_name_issubdomain(qname
, name
)))
4295 return (DNS_R_FORMERR
);
4296 if (type
== dns_rdatatype_ns
) {
4300 * Only one set of NS RRs is allowed.
4302 if (rdataset
->type
==
4304 if (ns_name
!= NULL
&&
4306 return (DNS_R_FORMERR
);
4308 ns_rdataset
= rdataset
;
4312 rdataset
->attributes
|=
4313 DNS_RDATASETATTR_CACHE
;
4314 rdataset
->trust
= dns_trust_glue
;
4316 if (type
== dns_rdatatype_soa
) {
4318 * SOA, or RRSIG SOA.
4320 * Only one SOA is allowed.
4322 if (rdataset
->type
==
4323 dns_rdatatype_soa
) {
4324 if (soa_name
!= NULL
&&
4326 return (DNS_R_FORMERR
);
4330 DNS_NAMEATTR_NCACHE
;
4331 rdataset
->attributes
|=
4332 DNS_RDATASETATTR_NCACHE
;
4335 dns_trust_authauthority
;
4338 dns_trust_additional
;
4342 * A negative response has a SOA record (Type 2)
4343 * and a optional NS RRset (Type 1) or it has neither
4344 * a SOA or a NS RRset (Type 3, handled above) or
4345 * rcode is NXDOMAIN (handled above) in which case
4346 * the NS RRset is allowed (Type 4).
4348 if (soa_name
!= NULL
)
4349 negative_response
= ISC_TRUE
;
4350 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4352 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4353 type
= rdataset
->type
;
4354 if (type
== dns_rdatatype_rrsig
)
4355 type
= rdataset
->covers
;
4356 if (type
== dns_rdatatype_nsec
) {
4358 * NSEC or RRSIG NSEC.
4360 if (negative_response
) {
4362 DNS_NAMEATTR_NCACHE
;
4363 rdataset
->attributes
|=
4364 DNS_RDATASETATTR_NCACHE
;
4368 rdataset
->attributes
|=
4369 DNS_RDATASETATTR_CACHE
;
4373 dns_trust_authauthority
;
4376 dns_trust_additional
;
4378 * No additional data needs to be
4381 } else if (type
== dns_rdatatype_ds
) {
4385 * These should only be here if
4386 * this is a referral, and there
4387 * should only be one DS.
4389 if (ns_name
== NULL
)
4390 return (DNS_R_FORMERR
);
4391 if (rdataset
->type
==
4393 if (ds_name
!= NULL
&&
4395 return (DNS_R_FORMERR
);
4400 rdataset
->attributes
|=
4401 DNS_RDATASETATTR_CACHE
;
4404 dns_trust_authauthority
;
4407 dns_trust_additional
;
4411 result
= dns_message_nextname(message
, section
);
4412 if (result
== ISC_R_NOMORE
)
4414 else if (result
!= ISC_R_SUCCESS
)
4419 * Trigger lookups for DNS nameservers.
4421 if (negative_response
&& message
->rcode
== dns_rcode_noerror
&&
4422 fctx
->type
== dns_rdatatype_ds
&& soa_name
!= NULL
&&
4423 dns_name_equal(soa_name
, qname
) &&
4424 !dns_name_equal(qname
, dns_rootname
))
4425 return (DNS_R_CHASEDSSERVERS
);
4428 * Did we find anything?
4430 if (!negative_response
&& ns_name
== NULL
) {
4434 if (oqname
!= NULL
) {
4436 * We've already got a partial CNAME/DNAME chain,
4437 * and haven't found else anything useful here, but
4438 * no error has occurred since we have an answer.
4440 return (ISC_R_SUCCESS
);
4443 * The responder is insane.
4445 return (DNS_R_FORMERR
);
4450 * If we found both NS and SOA, they should be the same name.
4452 if (ns_name
!= NULL
&& soa_name
!= NULL
&& ns_name
!= soa_name
)
4453 return (DNS_R_FORMERR
);
4456 * Do we have a referral? (We only want to follow a referral if
4457 * we're not following a chain.)
4459 if (!negative_response
&& ns_name
!= NULL
&& oqname
== NULL
) {
4461 * We already know ns_name is a subdomain of fctx->domain.
4462 * If ns_name is equal to fctx->domain, we're not making
4463 * progress. We return DNS_R_FORMERR so that we'll keep
4464 * trying other servers.
4466 if (dns_name_equal(ns_name
, &fctx
->domain
))
4467 return (DNS_R_FORMERR
);
4470 * If the referral name is not a parent of the query
4471 * name, consider the responder insane.
4473 if (! dns_name_issubdomain(&fctx
->name
, ns_name
)) {
4474 FCTXTRACE("referral to non-parent");
4475 return (DNS_R_FORMERR
);
4479 * Mark any additional data related to this rdataset.
4480 * It's important that we do this before we change the
4483 INSIST(ns_rdataset
!= NULL
);
4484 fctx
->attributes
|= FCTX_ATTR_GLUING
;
4485 (void)dns_rdataset_additionaldata(ns_rdataset
, check_related
,
4487 fctx
->attributes
&= ~FCTX_ATTR_GLUING
;
4489 * NS rdatasets with 0 TTL cause problems.
4490 * dns_view_findzonecut() will not find them when we
4491 * try to follow the referral, and we'll SERVFAIL
4492 * because the best nameservers are now above QDOMAIN.
4493 * We force the TTL to 1 second to prevent this.
4495 if (ns_rdataset
->ttl
== 0)
4496 ns_rdataset
->ttl
= 1;
4498 * Set the current query domain to the referral name.
4500 * XXXRTH We should check if we're in forward-only mode, and
4501 * if so we should bail out.
4503 INSIST(dns_name_countlabels(&fctx
->domain
) > 0);
4504 dns_name_free(&fctx
->domain
, fctx
->res
->mctx
);
4505 if (dns_rdataset_isassociated(&fctx
->nameservers
))
4506 dns_rdataset_disassociate(&fctx
->nameservers
);
4507 dns_name_init(&fctx
->domain
, NULL
);
4508 result
= dns_name_dup(ns_name
, fctx
->res
->mctx
, &fctx
->domain
);
4509 if (result
!= ISC_R_SUCCESS
)
4511 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
4512 return (DNS_R_DELEGATION
);
4516 * Since we're not doing a referral, we don't want to cache any
4517 * NS RRs we may have found.
4519 if (ns_name
!= NULL
)
4520 ns_name
->attributes
&= ~DNS_NAMEATTR_CACHE
;
4522 if (negative_response
&& oqname
== NULL
)
4523 fctx
->attributes
|= FCTX_ATTR_WANTNCACHE
;
4525 return (ISC_R_SUCCESS
);
4529 answer_response(fetchctx_t
*fctx
) {
4530 isc_result_t result
;
4531 dns_message_t
*message
;
4532 dns_name_t
*name
, *qname
, tname
;
4533 dns_rdataset_t
*rdataset
;
4534 isc_boolean_t done
, external
, chaining
, aa
, found
, want_chaining
;
4535 isc_boolean_t have_answer
, found_cname
, found_type
, wanted_chaining
;
4537 dns_rdatatype_t type
;
4538 dns_fixedname_t dname
, fqname
;
4540 FCTXTRACE("answer_response");
4542 message
= fctx
->rmessage
;
4545 * Examine the answer section, marking those rdatasets which are
4546 * part of the answer and should be cached.
4550 found_cname
= ISC_FALSE
;
4551 found_type
= ISC_FALSE
;
4552 chaining
= ISC_FALSE
;
4553 have_answer
= ISC_FALSE
;
4554 want_chaining
= ISC_FALSE
;
4555 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
4559 qname
= &fctx
->name
;
4561 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
4562 while (!done
&& result
== ISC_R_SUCCESS
) {
4564 dns_message_currentname(message
, DNS_SECTION_ANSWER
, &name
);
4565 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
4566 if (dns_name_equal(name
, qname
)) {
4567 wanted_chaining
= ISC_FALSE
;
4568 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4570 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4572 want_chaining
= ISC_FALSE
;
4574 if (rdataset
->type
== type
&& !found_cname
) {
4576 * We've found an ordinary answer.
4579 found_type
= ISC_TRUE
;
4581 aflag
= DNS_RDATASETATTR_ANSWER
;
4582 } else if (type
== dns_rdatatype_any
) {
4584 * We've found an answer matching
4585 * an ANY query. There may be
4589 aflag
= DNS_RDATASETATTR_ANSWER
;
4590 } else if (rdataset
->type
== dns_rdatatype_rrsig
4591 && rdataset
->covers
== type
4594 * We've found a signature that
4595 * covers the type we're looking for.
4598 found_type
= ISC_TRUE
;
4599 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
4600 } else if (rdataset
->type
==
4604 * We're looking for something else,
4605 * but we found a CNAME.
4607 * Getting a CNAME response for some
4608 * query types is an error.
4610 if (type
== dns_rdatatype_rrsig
||
4611 type
== dns_rdatatype_dnskey
||
4612 type
== dns_rdatatype_nsec
)
4613 return (DNS_R_FORMERR
);
4615 found_cname
= ISC_TRUE
;
4616 want_chaining
= ISC_TRUE
;
4617 aflag
= DNS_RDATASETATTR_ANSWER
;
4618 result
= cname_target(rdataset
,
4620 if (result
!= ISC_R_SUCCESS
)
4622 } else if (rdataset
->type
== dns_rdatatype_rrsig
4623 && rdataset
->covers
==
4627 * We're looking for something else,
4628 * but we found a SIG CNAME.
4631 found_cname
= ISC_TRUE
;
4632 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
4637 * We've found an answer to our
4642 rdataset
->attributes
|=
4643 DNS_RDATASETATTR_CACHE
;
4644 rdataset
->trust
= dns_trust_answer
;
4647 * This data is "the" answer
4648 * to our question only if
4649 * we're not chaining (i.e.
4650 * if we haven't followed
4651 * a CNAME or DNAME).
4655 DNS_RDATASETATTR_ANSWER
)
4656 have_answer
= ISC_TRUE
;
4658 DNS_NAMEATTR_ANSWER
;
4659 rdataset
->attributes
|= aflag
;
4662 dns_trust_authanswer
;
4663 } else if (external
) {
4665 * This data is outside of
4666 * our query domain, and
4667 * may only be cached if it
4668 * comes from a secure zone
4671 rdataset
->attributes
|=
4672 DNS_RDATASETATTR_EXTERNAL
;
4676 * Mark any additional data related
4679 (void)dns_rdataset_additionaldata(
4687 if (want_chaining
) {
4688 wanted_chaining
= ISC_TRUE
;
4690 DNS_NAMEATTR_CHAINING
;
4691 rdataset
->attributes
|=
4692 DNS_RDATASETATTR_CHAINING
;
4697 * We could add an "else" clause here and
4698 * log that we're ignoring this rdataset.
4702 * If wanted_chaining is true, we've done
4703 * some chaining as the result of processing
4704 * this node, and thus we need to set
4707 * We don't set chaining inside of the
4708 * rdataset loop because doing that would
4709 * cause us to ignore the signatures of
4712 if (wanted_chaining
)
4713 chaining
= ISC_TRUE
;
4716 * Look for a DNAME (or its SIG). Anything else is
4719 wanted_chaining
= ISC_FALSE
;
4720 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4722 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4723 isc_boolean_t found_dname
= ISC_FALSE
;
4726 if (rdataset
->type
== dns_rdatatype_dname
) {
4728 * We're looking for something else,
4729 * but we found a DNAME.
4731 * If we're not chaining, then the
4732 * DNAME should not be external.
4734 if (!chaining
&& external
)
4735 return (DNS_R_FORMERR
);
4737 want_chaining
= ISC_TRUE
;
4738 aflag
= DNS_RDATASETATTR_ANSWER
;
4739 result
= dname_target(rdataset
,
4742 if (result
== ISC_R_NOSPACE
) {
4744 * We can't construct the
4745 * DNAME target. Do not
4748 want_chaining
= ISC_FALSE
;
4749 } else if (result
!= ISC_R_SUCCESS
)
4752 found_dname
= ISC_TRUE
;
4753 } else if (rdataset
->type
== dns_rdatatype_rrsig
4754 && rdataset
->covers
==
4755 dns_rdatatype_dname
) {
4757 * We've found a signature that
4761 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
4766 * We've found an answer to our
4771 rdataset
->attributes
|=
4772 DNS_RDATASETATTR_CACHE
;
4773 rdataset
->trust
= dns_trust_answer
;
4776 * This data is "the" answer
4777 * to our question only if
4778 * we're not chaining.
4782 DNS_RDATASETATTR_ANSWER
)
4783 have_answer
= ISC_TRUE
;
4785 DNS_NAMEATTR_ANSWER
;
4786 rdataset
->attributes
|= aflag
;
4789 dns_trust_authanswer
;
4790 } else if (external
) {
4791 rdataset
->attributes
|=
4792 DNS_RDATASETATTR_EXTERNAL
;
4800 * Copy the the dname into the
4803 * Although we check for
4804 * failure of the copy
4805 * operation, in practice it
4806 * should never fail since
4807 * we already know that the
4808 * result fits in a fixedname.
4810 dns_fixedname_init(&fqname
);
4811 result
= dns_name_copy(
4812 dns_fixedname_name(&dname
),
4813 dns_fixedname_name(&fqname
),
4815 if (result
!= ISC_R_SUCCESS
)
4817 wanted_chaining
= ISC_TRUE
;
4819 DNS_NAMEATTR_CHAINING
;
4820 rdataset
->attributes
|=
4821 DNS_RDATASETATTR_CHAINING
;
4822 qname
= dns_fixedname_name(
4827 if (wanted_chaining
)
4828 chaining
= ISC_TRUE
;
4830 result
= dns_message_nextname(message
, DNS_SECTION_ANSWER
);
4832 if (result
== ISC_R_NOMORE
)
4833 result
= ISC_R_SUCCESS
;
4834 if (result
!= ISC_R_SUCCESS
)
4838 * We should have found an answer.
4841 return (DNS_R_FORMERR
);
4844 * This response is now potentially cacheable.
4846 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
4849 * Did chaining end before we got the final answer?
4853 * Yes. This may be a negative reply, so hand off
4854 * authority section processing to the noanswer code.
4855 * If it isn't a noanswer response, no harm will be
4858 return (noanswer_response(fctx
, qname
, ISC_FALSE
));
4862 * We didn't end with an incomplete chain, so the rcode should be
4865 if (message
->rcode
!= dns_rcode_noerror
)
4866 return (DNS_R_FORMERR
);
4869 * Examine the authority section (if there is one).
4871 * We expect there to be only one owner name for all the rdatasets
4872 * in this section, and we expect that it is not external.
4875 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
4876 while (!done
&& result
== ISC_R_SUCCESS
) {
4878 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
4879 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
4882 * We expect to find NS or SIG NS rdatasets, and
4885 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4887 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4888 if (rdataset
->type
== dns_rdatatype_ns
||
4889 (rdataset
->type
== dns_rdatatype_rrsig
&&
4890 rdataset
->covers
== dns_rdatatype_ns
)) {
4893 rdataset
->attributes
|=
4894 DNS_RDATASETATTR_CACHE
;
4895 if (aa
&& !chaining
)
4897 dns_trust_authauthority
;
4900 dns_trust_additional
;
4903 * Mark any additional data related
4906 (void)dns_rdataset_additionaldata(
4914 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
4916 if (result
== ISC_R_NOMORE
)
4917 result
= ISC_R_SUCCESS
;
4923 resume_dslookup(isc_task_t
*task
, isc_event_t
*event
) {
4924 dns_fetchevent_t
*fevent
;
4925 dns_resolver_t
*res
;
4927 isc_result_t result
;
4928 isc_boolean_t bucket_empty
= ISC_FALSE
;
4929 isc_boolean_t locked
= ISC_FALSE
;
4930 unsigned int bucketnum
;
4931 dns_rdataset_t nameservers
;
4932 dns_fixedname_t fixed
;
4935 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
4936 fevent
= (dns_fetchevent_t
*)event
;
4937 fctx
= event
->ev_arg
;
4938 REQUIRE(VALID_FCTX(fctx
));
4942 FCTXTRACE("resume_dslookup");
4944 if (fevent
->node
!= NULL
)
4945 dns_db_detachnode(fevent
->db
, &fevent
->node
);
4946 if (fevent
->db
!= NULL
)
4947 dns_db_detach(&fevent
->db
);
4949 dns_rdataset_init(&nameservers
);
4951 bucketnum
= fctx
->bucketnum
;
4952 if (fevent
->result
== ISC_R_CANCELED
) {
4953 dns_resolver_destroyfetch(&fctx
->nsfetch
);
4954 fctx_done(fctx
, ISC_R_CANCELED
);
4955 } else if (fevent
->result
== ISC_R_SUCCESS
) {
4957 FCTXTRACE("resuming DS lookup");
4959 dns_resolver_destroyfetch(&fctx
->nsfetch
);
4960 if (dns_rdataset_isassociated(&fctx
->nameservers
))
4961 dns_rdataset_disassociate(&fctx
->nameservers
);
4962 dns_rdataset_clone(fevent
->rdataset
, &fctx
->nameservers
);
4963 dns_name_free(&fctx
->domain
, fctx
->res
->mctx
);
4964 dns_name_init(&fctx
->domain
, NULL
);
4965 result
= dns_name_dup(&fctx
->nsname
, fctx
->res
->mctx
,
4967 if (result
!= ISC_R_SUCCESS
) {
4968 fctx_done(fctx
, DNS_R_SERVFAIL
);
4977 dns_rdataset_t
*nsrdataset
= NULL
;
4980 * Retrieve state from fctx->nsfetch before we destroy it.
4982 dns_fixedname_init(&fixed
);
4983 domain
= dns_fixedname_name(&fixed
);
4984 dns_name_copy(&fctx
->nsfetch
->private->domain
, domain
, NULL
);
4985 if (dns_name_equal(&fctx
->nsname
, domain
)) {
4986 fctx_done(fctx
, DNS_R_SERVFAIL
);
4987 dns_resolver_destroyfetch(&fctx
->nsfetch
);
4990 if (dns_rdataset_isassociated(
4991 &fctx
->nsfetch
->private->nameservers
)) {
4993 &fctx
->nsfetch
->private->nameservers
,
4995 nsrdataset
= &nameservers
;
4998 dns_resolver_destroyfetch(&fctx
->nsfetch
);
4999 n
= dns_name_countlabels(&fctx
->nsname
);
5000 dns_name_getlabelsequence(&fctx
->nsname
, 1, n
- 1,
5003 if (dns_rdataset_isassociated(fevent
->rdataset
))
5004 dns_rdataset_disassociate(fevent
->rdataset
);
5005 FCTXTRACE("continuing to look for parent's NS records");
5006 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
5007 dns_rdatatype_ns
, domain
,
5008 nsrdataset
, NULL
, 0, task
,
5009 resume_dslookup
, fctx
,
5010 &fctx
->nsrrset
, NULL
,
5012 if (result
!= ISC_R_SUCCESS
)
5013 fctx_done(fctx
, result
);
5015 LOCK(&res
->buckets
[bucketnum
].lock
);
5022 if (dns_rdataset_isassociated(&nameservers
))
5023 dns_rdataset_disassociate(&nameservers
);
5024 if (dns_rdataset_isassociated(fevent
->rdataset
))
5025 dns_rdataset_disassociate(fevent
->rdataset
);
5026 INSIST(fevent
->sigrdataset
== NULL
);
5027 isc_event_free(&event
);
5029 LOCK(&res
->buckets
[bucketnum
].lock
);
5031 if (fctx
->references
== 0)
5032 bucket_empty
= fctx_destroy(fctx
);
5033 UNLOCK(&res
->buckets
[bucketnum
].lock
);
5039 checknamessection(dns_message_t
*message
, dns_section_t section
) {
5040 isc_result_t result
;
5042 dns_rdata_t rdata
= DNS_RDATA_INIT
;
5043 dns_rdataset_t
*rdataset
;
5045 for (result
= dns_message_firstname(message
, section
);
5046 result
== ISC_R_SUCCESS
;
5047 result
= dns_message_nextname(message
, section
))
5050 dns_message_currentname(message
, section
, &name
);
5051 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5053 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5054 for (result
= dns_rdataset_first(rdataset
);
5055 result
== ISC_R_SUCCESS
;
5056 result
= dns_rdataset_next(rdataset
)) {
5057 dns_rdataset_current(rdataset
, &rdata
);
5058 if (!dns_rdata_checkowner(name
, rdata
.rdclass
,
5061 !dns_rdata_checknames(&rdata
, name
, NULL
))
5063 rdataset
->attributes
|=
5064 DNS_RDATASETATTR_CHECKNAMES
;
5066 dns_rdata_reset(&rdata
);
5073 checknames(dns_message_t
*message
) {
5075 checknamessection(message
, DNS_SECTION_ANSWER
);
5076 checknamessection(message
, DNS_SECTION_AUTHORITY
);
5077 checknamessection(message
, DNS_SECTION_ADDITIONAL
);
5081 log_packet(dns_message_t
*message
, int level
, isc_mem_t
*mctx
) {
5082 isc_buffer_t buffer
;
5085 isc_result_t result
;
5087 if (! isc_log_wouldlog(dns_lctx
, level
))
5091 * Note that these are multiline debug messages. We want a newline
5092 * to appear in the log after each message.
5096 buf
= isc_mem_get(mctx
, len
);
5099 isc_buffer_init(&buffer
, buf
, len
);
5100 result
= dns_message_totext(message
, &dns_master_style_debug
,
5102 if (result
== ISC_R_NOSPACE
) {
5103 isc_mem_put(mctx
, buf
, len
);
5105 } else if (result
== ISC_R_SUCCESS
)
5106 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5107 DNS_LOGMODULE_RESOLVER
, level
,
5108 "received packet:\n%.*s",
5109 (int)isc_buffer_usedlength(&buffer
),
5111 } while (result
== ISC_R_NOSPACE
);
5114 isc_mem_put(mctx
, buf
, len
);
5118 resquery_response(isc_task_t
*task
, isc_event_t
*event
) {
5119 isc_result_t result
= ISC_R_SUCCESS
;
5120 resquery_t
*query
= event
->ev_arg
;
5121 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
5122 isc_boolean_t keep_trying
, get_nameservers
, resend
;
5123 isc_boolean_t truncated
;
5124 dns_message_t
*message
;
5127 dns_fixedname_t foundname
;
5129 isc_time_t tnow
, *finish
;
5130 dns_adbaddrinfo_t
*addrinfo
;
5131 unsigned int options
;
5132 unsigned int findoptions
;
5133 isc_result_t broken_server
;
5135 REQUIRE(VALID_QUERY(query
));
5137 options
= query
->options
;
5138 REQUIRE(VALID_FCTX(fctx
));
5139 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
5143 (void)isc_timer_touch(fctx
->timer
);
5145 keep_trying
= ISC_FALSE
;
5146 broken_server
= ISC_R_SUCCESS
;
5147 get_nameservers
= ISC_FALSE
;
5149 truncated
= ISC_FALSE
;
5152 if (fctx
->res
->exiting
) {
5153 result
= ISC_R_SHUTTINGDOWN
;
5160 * XXXRTH We should really get the current time just once. We
5161 * need a routine to convert from an isc_time_t to an
5166 isc_stdtime_get(&now
);
5169 * Did the dispatcher have a problem?
5171 if (devent
->result
!= ISC_R_SUCCESS
) {
5172 if (devent
->result
== ISC_R_EOF
&&
5173 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
5175 * The problem might be that they
5176 * don't understand EDNS0. Turn it
5177 * off and try again.
5179 options
|= DNS_FETCHOPT_NOEDNS0
;
5182 * Remember that they don't like EDNS0.
5184 dns_adb_changeflags(fctx
->adb
,
5186 DNS_FETCHOPT_NOEDNS0
,
5187 DNS_FETCHOPT_NOEDNS0
);
5190 * There's no hope for this query.
5192 keep_trying
= ISC_TRUE
;
5197 message
= fctx
->rmessage
;
5199 if (query
->tsig
!= NULL
) {
5200 result
= dns_message_setquerytsig(message
, query
->tsig
);
5201 if (result
!= ISC_R_SUCCESS
)
5205 if (query
->tsigkey
) {
5206 result
= dns_message_settsigkey(message
, query
->tsigkey
);
5207 if (result
!= ISC_R_SUCCESS
)
5211 result
= dns_message_parse(message
, &devent
->buffer
, 0);
5212 if (result
!= ISC_R_SUCCESS
) {
5214 case ISC_R_UNEXPECTEDEND
:
5215 if (!message
->question_ok
||
5216 (message
->flags
& DNS_MESSAGEFLAG_TC
) == 0 ||
5217 (options
& DNS_FETCHOPT_TCP
) != 0) {
5219 * Either the message ended prematurely,
5220 * and/or wasn't marked as being truncated,
5221 * and/or this is a response to a query we
5222 * sent over TCP. In all of these cases,
5223 * something is wrong with the remote
5224 * server and we don't want to retry using
5227 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
)
5230 * The problem might be that they
5231 * don't understand EDNS0. Turn it
5232 * off and try again.
5234 options
|= DNS_FETCHOPT_NOEDNS0
;
5237 * Remember that they don't like EDNS0.
5239 dns_adb_changeflags(
5242 DNS_FETCHOPT_NOEDNS0
,
5243 DNS_FETCHOPT_NOEDNS0
);
5245 broken_server
= result
;
5246 keep_trying
= ISC_TRUE
;
5251 * We defer retrying via TCP for a bit so we can
5252 * check out this message further.
5254 truncated
= ISC_TRUE
;
5257 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
5259 * The problem might be that they
5260 * don't understand EDNS0. Turn it
5261 * off and try again.
5263 options
|= DNS_FETCHOPT_NOEDNS0
;
5266 * Remember that they don't like EDNS0.
5268 dns_adb_changeflags(fctx
->adb
,
5270 DNS_FETCHOPT_NOEDNS0
,
5271 DNS_FETCHOPT_NOEDNS0
);
5273 broken_server
= DNS_R_UNEXPECTEDRCODE
;
5274 keep_trying
= ISC_TRUE
;
5279 * Something bad has happened.
5286 * Log the incoming packet.
5288 log_packet(message
, ISC_LOG_DEBUG(10), fctx
->res
->mctx
);
5291 * If the message is signed, check the signature. If not, this
5292 * returns success anyway.
5294 result
= dns_message_checksig(message
, fctx
->res
->view
);
5295 if (result
!= ISC_R_SUCCESS
)
5299 * The dispatcher should ensure we only get responses with QR set.
5301 INSIST((message
->flags
& DNS_MESSAGEFLAG_QR
) != 0);
5303 * INSIST() that the message comes from the place we sent it to,
5304 * since the dispatch code should ensure this.
5306 * INSIST() that the message id is correct (this should also be
5307 * ensured by the dispatch code).
5312 * Deal with truncated responses by retrying using TCP.
5314 if ((message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
5315 truncated
= ISC_TRUE
;
5318 if ((options
& DNS_FETCHOPT_TCP
) != 0) {
5319 broken_server
= DNS_R_TRUNCATEDTCP
;
5320 keep_trying
= ISC_TRUE
;
5322 options
|= DNS_FETCHOPT_TCP
;
5329 * Is it a query response?
5331 if (message
->opcode
!= dns_opcode_query
) {
5333 broken_server
= DNS_R_UNEXPECTEDOPCODE
;
5334 keep_trying
= ISC_TRUE
;
5339 * Is the remote server broken, or does it dislike us?
5341 if (message
->rcode
!= dns_rcode_noerror
&&
5342 message
->rcode
!= dns_rcode_nxdomain
) {
5343 if ((message
->rcode
== dns_rcode_formerr
||
5344 message
->rcode
== dns_rcode_notimp
||
5345 message
->rcode
== dns_rcode_servfail
) &&
5346 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
5348 * It's very likely they don't like EDNS0.
5350 * XXXRTH We should check if the question
5351 * we're asking requires EDNS0, and
5352 * if so, we should bail out.
5354 options
|= DNS_FETCHOPT_NOEDNS0
;
5357 * Remember that they don't like EDNS0.
5359 if (message
->rcode
!= dns_rcode_servfail
)
5360 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
5361 DNS_FETCHOPT_NOEDNS0
,
5362 DNS_FETCHOPT_NOEDNS0
);
5363 } else if (message
->rcode
== dns_rcode_formerr
) {
5364 if (ISFORWARDER(query
->addrinfo
)) {
5366 * This forwarder doesn't understand us,
5367 * but other forwarders might. Keep trying.
5369 broken_server
= DNS_R_REMOTEFORMERR
;
5370 keep_trying
= ISC_TRUE
;
5373 * The server doesn't understand us. Since
5374 * all servers for a zone need similar
5375 * capabilities, we assume that we will get
5376 * FORMERR from all servers, and thus we
5377 * cannot make any more progress with this
5380 result
= DNS_R_FORMERR
;
5382 } else if (message
->rcode
== dns_rcode_yxdomain
) {
5384 * DNAME mapping failed because the new name
5385 * was too long. There's no chance of success
5388 result
= DNS_R_YXDOMAIN
;
5393 broken_server
= DNS_R_UNEXPECTEDRCODE
;
5394 INSIST(broken_server
!= ISC_R_SUCCESS
);
5395 keep_trying
= ISC_TRUE
;
5401 * Is the question the same as the one we asked?
5403 result
= same_question(fctx
);
5404 if (result
!= ISC_R_SUCCESS
) {
5406 if (result
== DNS_R_FORMERR
)
5407 keep_trying
= ISC_TRUE
;
5412 * Is the server lame?
5414 if (fctx
->res
->lame_ttl
!= 0 && !ISFORWARDER(query
->addrinfo
) &&
5416 log_lame(fctx
, query
->addrinfo
);
5417 result
= dns_adb_marklame(fctx
->adb
, query
->addrinfo
,
5419 now
+ fctx
->res
->lame_ttl
);
5420 if (result
!= ISC_R_SUCCESS
)
5421 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5422 DNS_LOGMODULE_RESOLVER
, ISC_LOG_ERROR
,
5423 "could not mark server as lame: %s",
5424 isc_result_totext(result
));
5425 broken_server
= DNS_R_LAME
;
5426 keep_trying
= ISC_TRUE
;
5431 * Enforce delegations only zones like NET and COM.
5433 if (!ISFORWARDER(query
->addrinfo
) &&
5434 dns_view_isdelegationonly(fctx
->res
->view
, &fctx
->domain
) &&
5435 !dns_name_equal(&fctx
->domain
, &fctx
->name
) &&
5436 fix_mustbedelegationornxdomain(message
, fctx
)) {
5437 char namebuf
[DNS_NAME_FORMATSIZE
];
5438 char domainbuf
[DNS_NAME_FORMATSIZE
];
5439 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
5443 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
5444 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
5445 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
5446 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
,
5448 isc_sockaddr_format(&query
->addrinfo
->sockaddr
, addrbuf
,
5451 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DELEGATION_ONLY
,
5452 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
5453 "enforced delegation-only for '%s' (%s/%s/%s) "
5455 domainbuf
, namebuf
, typebuf
, classbuf
, addrbuf
);
5458 if ((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMES
) != 0)
5459 checknames(message
);
5464 fctx
->attributes
&= ~(FCTX_ATTR_WANTNCACHE
| FCTX_ATTR_WANTCACHE
);
5467 * Did we get any answers?
5469 if (message
->counts
[DNS_SECTION_ANSWER
] > 0 &&
5470 (message
->rcode
== dns_rcode_noerror
||
5471 message
->rcode
== dns_rcode_nxdomain
)) {
5473 * We've got answers. However, if we sent
5474 * a BIND 8 server an NS query, it may have
5475 * incorrectly responded with a non-authoritative
5476 * answer instead of a referral. Since this
5477 * answer lacks the SIGs necessary to do DNSSEC
5478 * validation, we must invoke the following special
5479 * kludge to treat it as a referral.
5481 if (fctx
->type
== dns_rdatatype_ns
&&
5482 (message
->flags
& DNS_MESSAGEFLAG_AA
) == 0 &&
5483 !ISFORWARDER(query
->addrinfo
))
5485 result
= noanswer_response(fctx
, NULL
, ISC_TRUE
);
5486 if (result
!= DNS_R_DELEGATION
) {
5488 * The answer section must have contained
5489 * something other than the NS records
5490 * we asked for. Since AA is not set
5491 * and the server is not a forwarder,
5492 * it is technically lame and it's easier
5493 * to treat it as such than to figure out
5494 * some more elaborate course of action.
5496 broken_server
= DNS_R_LAME
;
5497 keep_trying
= ISC_TRUE
;
5500 goto force_referral
;
5502 result
= answer_response(fctx
);
5503 if (result
!= ISC_R_SUCCESS
) {
5504 if (result
== DNS_R_FORMERR
)
5505 keep_trying
= ISC_TRUE
;
5508 } else if (message
->counts
[DNS_SECTION_AUTHORITY
] > 0 ||
5509 message
->rcode
== dns_rcode_noerror
||
5510 message
->rcode
== dns_rcode_nxdomain
) {
5512 * NXDOMAIN, NXRDATASET, or referral.
5514 result
= noanswer_response(fctx
, NULL
, ISC_FALSE
);
5515 if (result
== DNS_R_CHASEDSSERVERS
) {
5516 } else if (result
== DNS_R_DELEGATION
) {
5519 * We don't have the answer, but we know a better
5522 get_nameservers
= ISC_TRUE
;
5523 keep_trying
= ISC_TRUE
;
5525 * We have a new set of name servers, and it
5526 * has not experienced any restarts yet.
5529 result
= ISC_R_SUCCESS
;
5530 } else if (result
!= ISC_R_SUCCESS
) {
5532 * Something has gone wrong.
5534 if (result
== DNS_R_FORMERR
)
5535 keep_trying
= ISC_TRUE
;
5540 * The server is insane.
5543 broken_server
= DNS_R_UNEXPECTEDRCODE
;
5544 keep_trying
= ISC_TRUE
;
5549 * Follow additional section data chains.
5551 chase_additional(fctx
);
5554 * Cache the cacheable parts of the message. This may also cause
5555 * work to be queued to the DNSSEC validator.
5557 if (WANTCACHE(fctx
)) {
5558 result
= cache_message(fctx
, query
->addrinfo
, now
);
5559 if (result
!= ISC_R_SUCCESS
)
5564 * Ncache the negatively cacheable parts of the message. This may
5565 * also cause work to be queued to the DNSSEC validator.
5567 if (WANTNCACHE(fctx
)) {
5568 dns_rdatatype_t covers
;
5569 if (message
->rcode
== dns_rcode_nxdomain
)
5570 covers
= dns_rdatatype_any
;
5572 covers
= fctx
->type
;
5575 * Cache any negative cache entries in the message.
5577 result
= ncache_message(fctx
, query
->addrinfo
, covers
, now
);
5582 * Remember the query's addrinfo, in case we need to mark the
5585 addrinfo
= query
->addrinfo
;
5590 * XXXRTH Don't cancel the query if waiting for validation?
5592 fctx_cancelquery(&query
, &devent
, finish
, ISC_FALSE
);
5595 if (result
== DNS_R_FORMERR
)
5596 broken_server
= DNS_R_FORMERR
;
5597 if (broken_server
!= ISC_R_SUCCESS
) {
5599 * Add this server to the list of bad servers for
5602 add_bad(fctx
, &addrinfo
->sockaddr
, broken_server
);
5605 if (get_nameservers
) {
5607 dns_fixedname_init(&foundname
);
5608 fname
= dns_fixedname_name(&foundname
);
5609 if (result
!= ISC_R_SUCCESS
) {
5610 fctx_done(fctx
, DNS_R_SERVFAIL
);
5614 if (dns_rdatatype_atparent(fctx
->type
))
5615 findoptions
|= DNS_DBFIND_NOEXACT
;
5616 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0)
5619 name
= &fctx
->domain
;
5620 result
= dns_view_findzonecut(fctx
->res
->view
,
5626 if (result
!= ISC_R_SUCCESS
) {
5627 FCTXTRACE("couldn't find a zonecut");
5628 fctx_done(fctx
, DNS_R_SERVFAIL
);
5631 if (!dns_name_issubdomain(fname
, &fctx
->domain
)) {
5633 * The best nameservers are now above our
5636 FCTXTRACE("nameservers now above QDOMAIN");
5637 fctx_done(fctx
, DNS_R_SERVFAIL
);
5640 dns_name_free(&fctx
->domain
, fctx
->res
->mctx
);
5641 dns_name_init(&fctx
->domain
, NULL
);
5642 result
= dns_name_dup(fname
, fctx
->res
->mctx
,
5644 if (result
!= ISC_R_SUCCESS
) {
5645 fctx_done(fctx
, DNS_R_SERVFAIL
);
5648 fctx_cancelqueries(fctx
, ISC_TRUE
);
5649 fctx_cleanupfinds(fctx
);
5650 fctx_cleanupaltfinds(fctx
);
5651 fctx_cleanupforwaddrs(fctx
);
5652 fctx_cleanupaltaddrs(fctx
);
5658 } else if (resend
) {
5660 * Resend (probably with changed options).
5662 FCTXTRACE("resend");
5663 result
= fctx_query(fctx
, addrinfo
, options
);
5664 if (result
!= ISC_R_SUCCESS
)
5665 fctx_done(fctx
, result
);
5666 } else if (result
== ISC_R_SUCCESS
&& !HAVE_ANSWER(fctx
)) {
5668 * All has gone well so far, but we are waiting for the
5669 * DNSSEC validator to validate the answer.
5671 FCTXTRACE("wait for validator");
5672 fctx_cancelqueries(fctx
, ISC_TRUE
);
5674 * We must not retransmit while the validator is working;
5675 * it has references to the current rmessage.
5677 result
= fctx_stopidletimer(fctx
);
5678 if (result
!= ISC_R_SUCCESS
)
5679 fctx_done(fctx
, result
);
5680 } else if (result
== DNS_R_CHASEDSSERVERS
) {
5682 add_bad(fctx
, &addrinfo
->sockaddr
, result
);
5683 fctx_cancelqueries(fctx
, ISC_TRUE
);
5684 fctx_cleanupfinds(fctx
);
5685 fctx_cleanupforwaddrs(fctx
);
5687 n
= dns_name_countlabels(&fctx
->name
);
5688 dns_name_getlabelsequence(&fctx
->name
, 1, n
- 1, &fctx
->nsname
);
5690 FCTXTRACE("suspending DS lookup to find parent's NS records");
5692 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
5694 NULL
, NULL
, NULL
, 0, task
,
5695 resume_dslookup
, fctx
,
5696 &fctx
->nsrrset
, NULL
,
5698 if (result
!= ISC_R_SUCCESS
)
5699 fctx_done(fctx
, result
);
5700 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
5702 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
5703 result
= fctx_stopidletimer(fctx
);
5704 if (result
!= ISC_R_SUCCESS
)
5705 fctx_done(fctx
, result
);
5710 fctx_done(fctx
, result
);
5716 *** Resolver Methods
5720 destroy(dns_resolver_t
*res
) {
5724 REQUIRE(res
->references
== 0);
5725 REQUIRE(!res
->priming
);
5726 REQUIRE(res
->primefetch
== NULL
);
5730 INSIST(res
->nfctx
== 0);
5732 DESTROYLOCK(&res
->primelock
);
5733 DESTROYLOCK(&res
->nlock
);
5734 DESTROYLOCK(&res
->lock
);
5735 for (i
= 0; i
< res
->nbuckets
; i
++) {
5736 INSIST(ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
));
5737 isc_task_shutdown(res
->buckets
[i
].task
);
5738 isc_task_detach(&res
->buckets
[i
].task
);
5739 DESTROYLOCK(&res
->buckets
[i
].lock
);
5741 isc_mem_put(res
->mctx
, res
->buckets
,
5742 res
->nbuckets
* sizeof(fctxbucket_t
));
5743 if (res
->dispatchv4
!= NULL
)
5744 dns_dispatch_detach(&res
->dispatchv4
);
5745 if (res
->dispatchv6
!= NULL
)
5746 dns_dispatch_detach(&res
->dispatchv6
);
5747 while ((a
= ISC_LIST_HEAD(res
->alternates
)) != NULL
) {
5748 ISC_LIST_UNLINK(res
->alternates
, a
, link
);
5750 dns_name_free(&a
->_u
._n
.name
, res
->mctx
);
5751 isc_mem_put(res
->mctx
, a
, sizeof(*a
));
5753 dns_resolver_reset_algorithms(res
);
5754 dns_resolver_resetmustbesecure(res
);
5756 isc_rwlock_destroy(&res
->alglock
);
5759 isc_rwlock_destroy(&res
->mbslock
);
5762 isc_mem_put(res
->mctx
, res
, sizeof(*res
));
5766 send_shutdown_events(dns_resolver_t
*res
) {
5767 isc_event_t
*event
, *next_event
;
5771 * Caller must be holding the resolver lock.
5774 for (event
= ISC_LIST_HEAD(res
->whenshutdown
);
5776 event
= next_event
) {
5777 next_event
= ISC_LIST_NEXT(event
, ev_link
);
5778 ISC_LIST_UNLINK(res
->whenshutdown
, event
, ev_link
);
5779 etask
= event
->ev_sender
;
5780 event
->ev_sender
= res
;
5781 isc_task_sendanddetach(&etask
, &event
);
5786 empty_bucket(dns_resolver_t
*res
) {
5787 RTRACE("empty_bucket");
5791 INSIST(res
->activebuckets
> 0);
5792 res
->activebuckets
--;
5793 if (res
->activebuckets
== 0)
5794 send_shutdown_events(res
);
5800 dns_resolver_create(dns_view_t
*view
,
5801 isc_taskmgr_t
*taskmgr
, unsigned int ntasks
,
5802 isc_socketmgr_t
*socketmgr
,
5803 isc_timermgr_t
*timermgr
,
5804 unsigned int options
,
5805 dns_dispatchmgr_t
*dispatchmgr
,
5806 dns_dispatch_t
*dispatchv4
,
5807 dns_dispatch_t
*dispatchv6
,
5808 dns_resolver_t
**resp
)
5810 dns_resolver_t
*res
;
5811 isc_result_t result
= ISC_R_SUCCESS
;
5812 unsigned int i
, buckets_created
= 0;
5816 * Create a resolver.
5819 REQUIRE(DNS_VIEW_VALID(view
));
5820 REQUIRE(ntasks
> 0);
5821 REQUIRE(resp
!= NULL
&& *resp
== NULL
);
5822 REQUIRE(dispatchmgr
!= NULL
);
5823 REQUIRE(dispatchv4
!= NULL
|| dispatchv6
!= NULL
);
5825 res
= isc_mem_get(view
->mctx
, sizeof(*res
));
5827 return (ISC_R_NOMEMORY
);
5829 res
->mctx
= view
->mctx
;
5830 res
->rdclass
= view
->rdclass
;
5831 res
->socketmgr
= socketmgr
;
5832 res
->timermgr
= timermgr
;
5833 res
->taskmgr
= taskmgr
;
5834 res
->dispatchmgr
= dispatchmgr
;
5836 res
->options
= options
;
5838 ISC_LIST_INIT(res
->alternates
);
5839 res
->udpsize
= RECV_BUFFER_SIZE
;
5840 res
->algorithms
= NULL
;
5841 res
->mustbesecure
= NULL
;
5843 res
->nbuckets
= ntasks
;
5844 res
->activebuckets
= ntasks
;
5845 res
->buckets
= isc_mem_get(view
->mctx
,
5846 ntasks
* sizeof(fctxbucket_t
));
5847 if (res
->buckets
== NULL
) {
5848 result
= ISC_R_NOMEMORY
;
5851 for (i
= 0; i
< ntasks
; i
++) {
5852 result
= isc_mutex_init(&res
->buckets
[i
].lock
);
5853 if (result
!= ISC_R_SUCCESS
)
5854 goto cleanup_buckets
;
5855 res
->buckets
[i
].task
= NULL
;
5856 result
= isc_task_create(taskmgr
, 0, &res
->buckets
[i
].task
);
5857 if (result
!= ISC_R_SUCCESS
) {
5858 DESTROYLOCK(&res
->buckets
[i
].lock
);
5859 goto cleanup_buckets
;
5861 snprintf(name
, sizeof(name
), "res%u", i
);
5862 isc_task_setname(res
->buckets
[i
].task
, name
, res
);
5863 ISC_LIST_INIT(res
->buckets
[i
].fctxs
);
5864 res
->buckets
[i
].exiting
= ISC_FALSE
;
5868 res
->dispatchv4
= NULL
;
5869 if (dispatchv4
!= NULL
)
5870 dns_dispatch_attach(dispatchv4
, &res
->dispatchv4
);
5871 res
->dispatchv6
= NULL
;
5872 if (dispatchv6
!= NULL
)
5873 dns_dispatch_attach(dispatchv6
, &res
->dispatchv6
);
5875 res
->references
= 1;
5876 res
->exiting
= ISC_FALSE
;
5877 res
->frozen
= ISC_FALSE
;
5878 ISC_LIST_INIT(res
->whenshutdown
);
5879 res
->priming
= ISC_FALSE
;
5880 res
->primefetch
= NULL
;
5883 result
= isc_mutex_init(&res
->lock
);
5884 if (result
!= ISC_R_SUCCESS
)
5885 goto cleanup_dispatches
;
5887 result
= isc_mutex_init(&res
->nlock
);
5888 if (result
!= ISC_R_SUCCESS
)
5891 result
= isc_mutex_init(&res
->primelock
);
5892 if (result
!= ISC_R_SUCCESS
)
5896 result
= isc_rwlock_init(&res
->alglock
, 0, 0);
5897 if (result
!= ISC_R_SUCCESS
)
5898 goto cleanup_primelock
;
5901 result
= isc_rwlock_init(&res
->mbslock
, 0, 0);
5902 if (result
!= ISC_R_SUCCESS
)
5903 goto cleanup_alglock
;
5906 res
->magic
= RES_MAGIC
;
5910 return (ISC_R_SUCCESS
);
5915 isc_rwlock_destroy(&res
->alglock
);
5918 #if USE_ALGLOCK || USE_MBSLOCK
5920 DESTROYLOCK(&res
->primelock
);
5924 DESTROYLOCK(&res
->nlock
);
5927 DESTROYLOCK(&res
->lock
);
5930 if (res
->dispatchv6
!= NULL
)
5931 dns_dispatch_detach(&res
->dispatchv6
);
5932 if (res
->dispatchv4
!= NULL
)
5933 dns_dispatch_detach(&res
->dispatchv4
);
5936 for (i
= 0; i
< buckets_created
; i
++) {
5937 DESTROYLOCK(&res
->buckets
[i
].lock
);
5938 isc_task_shutdown(res
->buckets
[i
].task
);
5939 isc_task_detach(&res
->buckets
[i
].task
);
5941 isc_mem_put(view
->mctx
, res
->buckets
,
5942 res
->nbuckets
* sizeof(fctxbucket_t
));
5945 isc_mem_put(view
->mctx
, res
, sizeof(*res
));
5951 prime_done(isc_task_t
*task
, isc_event_t
*event
) {
5952 dns_resolver_t
*res
;
5953 dns_fetchevent_t
*fevent
;
5956 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
5957 fevent
= (dns_fetchevent_t
*)event
;
5958 res
= event
->ev_arg
;
5959 REQUIRE(VALID_RESOLVER(res
));
5965 INSIST(res
->priming
);
5966 res
->priming
= ISC_FALSE
;
5967 LOCK(&res
->primelock
);
5968 fetch
= res
->primefetch
;
5969 res
->primefetch
= NULL
;
5970 UNLOCK(&res
->primelock
);
5974 if (fevent
->node
!= NULL
)
5975 dns_db_detachnode(fevent
->db
, &fevent
->node
);
5976 if (fevent
->db
!= NULL
)
5977 dns_db_detach(&fevent
->db
);
5978 if (dns_rdataset_isassociated(fevent
->rdataset
))
5979 dns_rdataset_disassociate(fevent
->rdataset
);
5980 INSIST(fevent
->sigrdataset
== NULL
);
5982 isc_mem_put(res
->mctx
, fevent
->rdataset
, sizeof(*fevent
->rdataset
));
5984 isc_event_free(&event
);
5985 dns_resolver_destroyfetch(&fetch
);
5989 dns_resolver_prime(dns_resolver_t
*res
) {
5990 isc_boolean_t want_priming
= ISC_FALSE
;
5991 dns_rdataset_t
*rdataset
;
5992 isc_result_t result
;
5994 REQUIRE(VALID_RESOLVER(res
));
5995 REQUIRE(res
->frozen
);
5997 RTRACE("dns_resolver_prime");
6001 if (!res
->exiting
&& !res
->priming
) {
6002 INSIST(res
->primefetch
== NULL
);
6003 res
->priming
= ISC_TRUE
;
6004 want_priming
= ISC_TRUE
;
6011 * To avoid any possible recursive locking problems, we
6012 * start the priming fetch like any other fetch, and holding
6013 * no resolver locks. No one else will try to start it
6014 * because we're the ones who set res->priming to true.
6015 * Any other callers of dns_resolver_prime() while we're
6016 * running will see that res->priming is already true and
6020 rdataset
= isc_mem_get(res
->mctx
, sizeof(*rdataset
));
6021 if (rdataset
== NULL
) {
6023 INSIST(res
->priming
);
6024 INSIST(res
->primefetch
== NULL
);
6025 res
->priming
= ISC_FALSE
;
6029 dns_rdataset_init(rdataset
);
6030 LOCK(&res
->primelock
);
6031 result
= dns_resolver_createfetch(res
, dns_rootname
,
6033 NULL
, NULL
, NULL
, 0,
6034 res
->buckets
[0].task
,
6036 res
, rdataset
, NULL
,
6038 UNLOCK(&res
->primelock
);
6039 if (result
!= ISC_R_SUCCESS
) {
6041 INSIST(res
->priming
);
6042 res
->priming
= ISC_FALSE
;
6049 dns_resolver_freeze(dns_resolver_t
*res
) {
6055 REQUIRE(VALID_RESOLVER(res
));
6056 REQUIRE(!res
->frozen
);
6058 res
->frozen
= ISC_TRUE
;
6062 dns_resolver_attach(dns_resolver_t
*source
, dns_resolver_t
**targetp
) {
6063 REQUIRE(VALID_RESOLVER(source
));
6064 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
6066 RRTRACE(source
, "attach");
6067 LOCK(&source
->lock
);
6068 REQUIRE(!source
->exiting
);
6070 INSIST(source
->references
> 0);
6071 source
->references
++;
6072 INSIST(source
->references
!= 0);
6073 UNLOCK(&source
->lock
);
6079 dns_resolver_whenshutdown(dns_resolver_t
*res
, isc_task_t
*task
,
6080 isc_event_t
**eventp
)
6085 REQUIRE(VALID_RESOLVER(res
));
6086 REQUIRE(eventp
!= NULL
);
6093 if (res
->exiting
&& res
->activebuckets
== 0) {
6095 * We're already shutdown. Send the event.
6097 event
->ev_sender
= res
;
6098 isc_task_send(task
, &event
);
6101 isc_task_attach(task
, &clone
);
6102 event
->ev_sender
= clone
;
6103 ISC_LIST_APPEND(res
->whenshutdown
, event
, ev_link
);
6110 dns_resolver_shutdown(dns_resolver_t
*res
) {
6115 REQUIRE(VALID_RESOLVER(res
));
6121 if (!res
->exiting
) {
6123 res
->exiting
= ISC_TRUE
;
6125 for (i
= 0; i
< res
->nbuckets
; i
++) {
6126 LOCK(&res
->buckets
[i
].lock
);
6127 for (fctx
= ISC_LIST_HEAD(res
->buckets
[i
].fctxs
);
6129 fctx
= ISC_LIST_NEXT(fctx
, link
))
6130 fctx_shutdown(fctx
);
6131 if (res
->dispatchv4
!= NULL
) {
6132 sock
= dns_dispatch_getsocket(res
->dispatchv4
);
6133 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
6134 ISC_SOCKCANCEL_ALL
);
6136 if (res
->dispatchv6
!= NULL
) {
6137 sock
= dns_dispatch_getsocket(res
->dispatchv6
);
6138 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
6139 ISC_SOCKCANCEL_ALL
);
6141 res
->buckets
[i
].exiting
= ISC_TRUE
;
6142 if (ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
)) {
6143 INSIST(res
->activebuckets
> 0);
6144 res
->activebuckets
--;
6146 UNLOCK(&res
->buckets
[i
].lock
);
6148 if (res
->activebuckets
== 0)
6149 send_shutdown_events(res
);
6156 dns_resolver_detach(dns_resolver_t
**resp
) {
6157 dns_resolver_t
*res
;
6158 isc_boolean_t need_destroy
= ISC_FALSE
;
6160 REQUIRE(resp
!= NULL
);
6162 REQUIRE(VALID_RESOLVER(res
));
6168 INSIST(res
->references
> 0);
6170 if (res
->references
== 0) {
6171 INSIST(res
->exiting
&& res
->activebuckets
== 0);
6172 need_destroy
= ISC_TRUE
;
6183 static inline isc_boolean_t
6184 fctx_match(fetchctx_t
*fctx
, dns_name_t
*name
, dns_rdatatype_t type
,
6185 unsigned int options
)
6187 if (fctx
->type
!= type
|| fctx
->options
!= options
)
6189 return (dns_name_equal(&fctx
->name
, name
));
6193 log_fetch(dns_name_t
*name
, dns_rdatatype_t type
) {
6194 char namebuf
[DNS_NAME_FORMATSIZE
];
6195 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
6196 int level
= ISC_LOG_DEBUG(1);
6198 if (! isc_log_wouldlog(dns_lctx
, level
))
6201 dns_name_format(name
, namebuf
, sizeof(namebuf
));
6202 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
6204 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6205 DNS_LOGMODULE_RESOLVER
, level
,
6206 "createfetch: %s %s", namebuf
, typebuf
);
6210 dns_resolver_createfetch(dns_resolver_t
*res
, dns_name_t
*name
,
6211 dns_rdatatype_t type
,
6212 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
6213 dns_forwarders_t
*forwarders
,
6214 unsigned int options
, isc_task_t
*task
,
6215 isc_taskaction_t action
, void *arg
,
6216 dns_rdataset_t
*rdataset
,
6217 dns_rdataset_t
*sigrdataset
,
6218 dns_fetch_t
**fetchp
)
6221 fetchctx_t
*fctx
= NULL
;
6222 isc_result_t result
;
6223 unsigned int bucketnum
;
6224 isc_boolean_t new_fctx
= ISC_FALSE
;
6229 REQUIRE(VALID_RESOLVER(res
));
6230 REQUIRE(res
->frozen
);
6231 /* XXXRTH Check for meta type */
6232 if (domain
!= NULL
) {
6233 REQUIRE(DNS_RDATASET_VALID(nameservers
));
6234 REQUIRE(nameservers
->type
== dns_rdatatype_ns
);
6236 REQUIRE(nameservers
== NULL
);
6237 REQUIRE(forwarders
== NULL
);
6238 REQUIRE(!dns_rdataset_isassociated(rdataset
));
6239 REQUIRE(sigrdataset
== NULL
||
6240 !dns_rdataset_isassociated(sigrdataset
));
6241 REQUIRE(fetchp
!= NULL
&& *fetchp
== NULL
);
6243 log_fetch(name
, type
);
6246 * XXXRTH use a mempool?
6248 fetch
= isc_mem_get(res
->mctx
, sizeof(*fetch
));
6250 return (ISC_R_NOMEMORY
);
6252 bucketnum
= dns_name_hash(name
, ISC_FALSE
) % res
->nbuckets
;
6254 LOCK(&res
->buckets
[bucketnum
].lock
);
6256 if (res
->buckets
[bucketnum
].exiting
) {
6257 result
= ISC_R_SHUTTINGDOWN
;
6261 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0) {
6262 for (fctx
= ISC_LIST_HEAD(res
->buckets
[bucketnum
].fctxs
);
6264 fctx
= ISC_LIST_NEXT(fctx
, link
)) {
6265 if (fctx_match(fctx
, name
, type
, options
))
6271 * If we didn't have a fetch, would attach to a done fetch, this
6272 * fetch has already cloned its results, or if the fetch has gone
6273 * "idle" (no one was interested in it), we need to start a new
6274 * fetch instead of joining with the existing one.
6277 fctx
->state
== fetchstate_done
||
6279 ISC_LIST_EMPTY(fctx
->events
)) {
6281 result
= fctx_create(res
, name
, type
, domain
, nameservers
,
6282 options
, bucketnum
, &fctx
);
6283 if (result
!= ISC_R_SUCCESS
)
6285 new_fctx
= ISC_TRUE
;
6288 result
= fctx_join(fctx
, task
, action
, arg
,
6289 rdataset
, sigrdataset
, fetch
);
6291 if (result
== ISC_R_SUCCESS
) {
6295 event
= &fctx
->control_event
;
6296 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
6297 DNS_EVENT_FETCHCONTROL
,
6298 fctx_start
, fctx
, NULL
,
6300 isc_task_send(res
->buckets
[bucketnum
].task
, &event
);
6303 * We don't care about the result of fctx_destroy()
6304 * since we know we're not exiting.
6306 (void)fctx_destroy(fctx
);
6311 UNLOCK(&res
->buckets
[bucketnum
].lock
);
6313 if (result
== ISC_R_SUCCESS
) {
6317 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
6323 dns_resolver_cancelfetch(dns_fetch_t
*fetch
) {
6325 dns_resolver_t
*res
;
6326 dns_fetchevent_t
*event
, *next_event
;
6329 REQUIRE(DNS_FETCH_VALID(fetch
));
6330 fctx
= fetch
->private;
6331 REQUIRE(VALID_FCTX(fctx
));
6334 FTRACE("cancelfetch");
6336 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
6339 * Find the completion event for this fetch (as opposed
6340 * to those for other fetches that have joined the same
6341 * fctx) and send it with result = ISC_R_CANCELED.
6344 if (fctx
->state
!= fetchstate_done
) {
6345 for (event
= ISC_LIST_HEAD(fctx
->events
);
6347 event
= next_event
) {
6348 next_event
= ISC_LIST_NEXT(event
, ev_link
);
6349 if (event
->fetch
== fetch
) {
6350 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
6355 if (event
!= NULL
) {
6356 etask
= event
->ev_sender
;
6357 event
->ev_sender
= fctx
;
6358 event
->result
= ISC_R_CANCELED
;
6359 isc_task_sendanddetach(&etask
, ISC_EVENT_PTR(&event
));
6362 * The fctx continues running even if no fetches remain;
6363 * the answer is still cached.
6366 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
6370 dns_resolver_destroyfetch(dns_fetch_t
**fetchp
) {
6372 dns_resolver_t
*res
;
6373 dns_fetchevent_t
*event
, *next_event
;
6375 unsigned int bucketnum
;
6376 isc_boolean_t bucket_empty
= ISC_FALSE
;
6378 REQUIRE(fetchp
!= NULL
);
6380 REQUIRE(DNS_FETCH_VALID(fetch
));
6381 fctx
= fetch
->private;
6382 REQUIRE(VALID_FCTX(fctx
));
6385 FTRACE("destroyfetch");
6387 bucketnum
= fctx
->bucketnum
;
6388 LOCK(&res
->buckets
[bucketnum
].lock
);
6391 * Sanity check: the caller should have gotten its event before
6392 * trying to destroy the fetch.
6395 if (fctx
->state
!= fetchstate_done
) {
6396 for (event
= ISC_LIST_HEAD(fctx
->events
);
6398 event
= next_event
) {
6399 next_event
= ISC_LIST_NEXT(event
, ev_link
);
6400 RUNTIME_CHECK(event
->fetch
!= fetch
);
6404 INSIST(fctx
->references
> 0);
6406 if (fctx
->references
== 0) {
6408 * No one cares about the result of this fetch anymore.
6410 if (fctx
->pending
== 0 && fctx
->nqueries
== 0 &&
6411 ISC_LIST_EMPTY(fctx
->validators
) &&
6412 SHUTTINGDOWN(fctx
)) {
6414 * This fctx is already shutdown; we were just
6415 * waiting for the last reference to go away.
6417 bucket_empty
= fctx_destroy(fctx
);
6420 * Initiate shutdown.
6422 fctx_shutdown(fctx
);
6426 UNLOCK(&res
->buckets
[bucketnum
].lock
);
6428 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
6436 dns_resolver_dispatchmgr(dns_resolver_t
*resolver
) {
6437 REQUIRE(VALID_RESOLVER(resolver
));
6438 return (resolver
->dispatchmgr
);
6442 dns_resolver_dispatchv4(dns_resolver_t
*resolver
) {
6443 REQUIRE(VALID_RESOLVER(resolver
));
6444 return (resolver
->dispatchv4
);
6448 dns_resolver_dispatchv6(dns_resolver_t
*resolver
) {
6449 REQUIRE(VALID_RESOLVER(resolver
));
6450 return (resolver
->dispatchv6
);
6454 dns_resolver_socketmgr(dns_resolver_t
*resolver
) {
6455 REQUIRE(VALID_RESOLVER(resolver
));
6456 return (resolver
->socketmgr
);
6460 dns_resolver_taskmgr(dns_resolver_t
*resolver
) {
6461 REQUIRE(VALID_RESOLVER(resolver
));
6462 return (resolver
->taskmgr
);
6466 dns_resolver_getlamettl(dns_resolver_t
*resolver
) {
6467 REQUIRE(VALID_RESOLVER(resolver
));
6468 return (resolver
->lame_ttl
);
6472 dns_resolver_setlamettl(dns_resolver_t
*resolver
, isc_uint32_t lame_ttl
) {
6473 REQUIRE(VALID_RESOLVER(resolver
));
6474 resolver
->lame_ttl
= lame_ttl
;
6478 dns_resolver_nrunning(dns_resolver_t
*resolver
) {
6480 LOCK(&resolver
->nlock
);
6481 n
= resolver
->nfctx
;
6482 UNLOCK(&resolver
->nlock
);
6487 dns_resolver_addalternate(dns_resolver_t
*resolver
, isc_sockaddr_t
*alt
,
6488 dns_name_t
*name
, in_port_t port
) {
6490 isc_result_t result
;
6492 REQUIRE(VALID_RESOLVER(resolver
));
6493 REQUIRE(!resolver
->frozen
);
6494 REQUIRE((alt
== NULL
) ^ (name
== NULL
));
6496 a
= isc_mem_get(resolver
->mctx
, sizeof(*a
));
6498 return (ISC_R_NOMEMORY
);
6500 a
->isaddress
= ISC_TRUE
;
6503 a
->isaddress
= ISC_FALSE
;
6504 a
->_u
._n
.port
= port
;
6505 dns_name_init(&a
->_u
._n
.name
, NULL
);
6506 result
= dns_name_dup(name
, resolver
->mctx
, &a
->_u
._n
.name
);
6507 if (result
!= ISC_R_SUCCESS
) {
6508 isc_mem_put(resolver
->mctx
, a
, sizeof(*a
));
6512 ISC_LINK_INIT(a
, link
);
6513 ISC_LIST_APPEND(resolver
->alternates
, a
, link
);
6515 return (ISC_R_SUCCESS
);
6519 dns_resolver_setudpsize(dns_resolver_t
*resolver
, isc_uint16_t udpsize
) {
6520 REQUIRE(VALID_RESOLVER(resolver
));
6521 resolver
->udpsize
= udpsize
;
6525 dns_resolver_getudpsize(dns_resolver_t
*resolver
) {
6526 REQUIRE(VALID_RESOLVER(resolver
));
6527 return (resolver
->udpsize
);
6531 free_algorithm(void *node
, void *arg
) {
6532 unsigned char *algorithms
= node
;
6533 isc_mem_t
*mctx
= arg
;
6535 isc_mem_put(mctx
, algorithms
, *algorithms
);
6539 dns_resolver_reset_algorithms(dns_resolver_t
*resolver
) {
6541 REQUIRE(VALID_RESOLVER(resolver
));
6544 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
6546 if (resolver
->algorithms
!= NULL
)
6547 dns_rbt_destroy(&resolver
->algorithms
);
6549 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
6554 dns_resolver_disable_algorithm(dns_resolver_t
*resolver
, dns_name_t
*name
,
6557 unsigned int len
, mask
;
6559 unsigned char *algorithms
;
6560 isc_result_t result
;
6561 dns_rbtnode_t
*node
= NULL
;
6563 REQUIRE(VALID_RESOLVER(resolver
));
6565 return (ISC_R_RANGE
);
6568 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
6570 if (resolver
->algorithms
== NULL
) {
6571 result
= dns_rbt_create(resolver
->mctx
, free_algorithm
,
6572 resolver
->mctx
, &resolver
->algorithms
);
6573 if (result
!= ISC_R_SUCCESS
)
6578 mask
= 1 << (alg
%8);
6580 result
= dns_rbt_addnode(resolver
->algorithms
, name
, &node
);
6582 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_EXISTS
) {
6583 algorithms
= node
->data
;
6584 if (algorithms
== NULL
|| len
> *algorithms
) {
6585 new = isc_mem_get(resolver
->mctx
, len
);
6587 result
= ISC_R_NOMEMORY
;
6590 memset(new, 0, len
);
6591 if (algorithms
!= NULL
)
6592 memcpy(new, algorithms
, *algorithms
);
6596 if (algorithms
!= NULL
)
6597 isc_mem_put(resolver
->mctx
, algorithms
,
6600 algorithms
[len
-1] |= mask
;
6602 result
= ISC_R_SUCCESS
;
6605 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
6611 dns_resolver_algorithm_supported(dns_resolver_t
*resolver
, dns_name_t
*name
,
6614 unsigned int len
, mask
;
6615 unsigned char *algorithms
;
6617 isc_result_t result
;
6618 isc_boolean_t found
= ISC_FALSE
;
6620 REQUIRE(VALID_RESOLVER(resolver
));
6623 RWLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
6625 if (resolver
->algorithms
== NULL
)
6627 result
= dns_rbt_findname(resolver
->algorithms
, name
, 0, NULL
, &data
);
6628 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
6630 mask
= 1 << (alg
%8);
6632 if (len
<= *algorithms
&& (algorithms
[len
-1] & mask
) != 0)
6637 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
6641 return (dst_algorithm_supported(alg
));
6645 dns_resolver_resetmustbesecure(dns_resolver_t
*resolver
) {
6647 REQUIRE(VALID_RESOLVER(resolver
));
6650 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
6652 if (resolver
->mustbesecure
!= NULL
)
6653 dns_rbt_destroy(&resolver
->mustbesecure
);
6655 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
6659 static isc_boolean_t yes
= ISC_TRUE
, no
= ISC_FALSE
;
6662 dns_resolver_setmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
,
6663 isc_boolean_t value
)
6665 isc_result_t result
;
6667 REQUIRE(VALID_RESOLVER(resolver
));
6670 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
6672 if (resolver
->mustbesecure
== NULL
) {
6673 result
= dns_rbt_create(resolver
->mctx
, NULL
, NULL
,
6674 &resolver
->mustbesecure
);
6675 if (result
!= ISC_R_SUCCESS
)
6678 result
= dns_rbt_addname(resolver
->mustbesecure
, name
,
6679 value
? &yes
: &no
);
6682 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
6688 dns_resolver_getmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
) {
6690 isc_boolean_t value
= ISC_FALSE
;
6691 isc_result_t result
;
6693 REQUIRE(VALID_RESOLVER(resolver
));
6696 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);
6698 if (resolver
->mustbesecure
== NULL
)
6700 result
= dns_rbt_findname(resolver
->mustbesecure
, name
, 0, NULL
, &data
);
6701 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
6702 value
= *(isc_boolean_t
*)data
;
6705 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);