1 /* $NetBSD: resolver.c,v 1.1.1.4 2009/12/26 22:24:56 christos Exp $ */
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: resolver.c,v 1.413 2009/11/18 23:48:07 tbox Exp */
26 #include <isc/platform.h>
27 #include <isc/print.h>
28 #include <isc/string.h>
29 #include <isc/random.h>
31 #include <isc/stats.h>
32 #include <isc/timer.h>
37 #include <dns/cache.h>
39 #include <dns/dispatch.h>
41 #include <dns/events.h>
42 #include <dns/forward.h>
43 #include <dns/keytable.h>
45 #include <dns/message.h>
46 #include <dns/ncache.h>
47 #include <dns/opcode.h>
50 #include <dns/rcode.h>
51 #include <dns/rdata.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdatalist.h>
54 #include <dns/rdataset.h>
55 #include <dns/rdatastruct.h>
56 #include <dns/rdatatype.h>
57 #include <dns/resolver.h>
58 #include <dns/result.h>
59 #include <dns/rootns.h>
60 #include <dns/stats.h>
62 #include <dns/validator.h>
64 #define DNS_RESOLVER_TRACE
65 #ifdef DNS_RESOLVER_TRACE
66 #define RTRACE(m) isc_log_write(dns_lctx, \
67 DNS_LOGCATEGORY_RESOLVER, \
68 DNS_LOGMODULE_RESOLVER, \
70 "res %p: %s", res, (m))
71 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
72 DNS_LOGCATEGORY_RESOLVER, \
73 DNS_LOGMODULE_RESOLVER, \
75 "res %p: %s", (r), (m))
76 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
77 DNS_LOGCATEGORY_RESOLVER, \
78 DNS_LOGMODULE_RESOLVER, \
80 "fctx %p(%s'): %s", fctx, fctx->info, (m))
81 #define FCTXTRACE2(m1, m2) \
82 isc_log_write(dns_lctx, \
83 DNS_LOGCATEGORY_RESOLVER, \
84 DNS_LOGMODULE_RESOLVER, \
86 "fctx %p(%s): %s %s", \
87 fctx, fctx->info, (m1), (m2))
88 #define FTRACE(m) isc_log_write(dns_lctx, \
89 DNS_LOGCATEGORY_RESOLVER, \
90 DNS_LOGMODULE_RESOLVER, \
92 "fetch %p (fctx %p(%s)): %s", \
93 fetch, fetch->private, \
94 fetch->private->info, (m))
95 #define QTRACE(m) isc_log_write(dns_lctx, \
96 DNS_LOGCATEGORY_RESOLVER, \
97 DNS_LOGMODULE_RESOLVER, \
99 "resquery %p (fctx %p(%s)): %s", \
100 query, query->fctx, \
101 query->fctx->info, (m))
104 #define RRTRACE(r, m)
111 * Maximum EDNS0 input packet size.
113 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
116 * This defines the maximum number of timeouts we will permit before we
117 * disable EDNS0 on the query.
119 #define MAX_EDNS0_TIMEOUTS 3
121 typedef struct fetchctx fetchctx_t
;
123 typedef struct query
{
124 /* Locked by task event serialization. */
128 dns_dispatchmgr_t
* dispatchmgr
;
129 dns_dispatch_t
* dispatch
;
130 isc_boolean_t exclusivesocket
;
131 dns_adbaddrinfo_t
* addrinfo
;
132 isc_socket_t
* tcpsocket
;
135 dns_dispentry_t
* dispentry
;
136 ISC_LINK(struct query
) link
;
139 dns_tsigkey_t
*tsigkey
;
140 unsigned int options
;
141 unsigned int attributes
;
143 unsigned int connects
;
144 unsigned char data
[512];
147 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
148 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
150 #define RESQUERY_ATTR_CANCELED 0x02
152 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
153 #define RESQUERY_CANCELED(q) (((q)->attributes & \
154 RESQUERY_ATTR_CANCELED) != 0)
155 #define RESQUERY_SENDING(q) ((q)->sends > 0)
158 fetchstate_init
= 0, /*%< Start event has not run yet. */
160 fetchstate_done
/*%< FETCHDONE events posted. */
164 badns_unreachable
= 0,
172 dns_resolver_t
* res
;
174 dns_rdatatype_t type
;
175 unsigned int options
;
176 unsigned int bucketnum
;
178 /*% Locked by appropriate bucket lock. */
180 isc_boolean_t want_shutdown
;
181 isc_boolean_t cloned
;
182 isc_boolean_t spilled
;
183 unsigned int references
;
184 isc_event_t control_event
;
185 ISC_LINK(struct fetchctx
) link
;
186 ISC_LIST(dns_fetchevent_t
) events
;
187 /*% Locked by task event serialization. */
189 dns_rdataset_t nameservers
;
190 unsigned int attributes
;
193 isc_interval_t interval
;
194 dns_message_t
* qmessage
;
195 dns_message_t
* rmessage
;
196 ISC_LIST(resquery_t
) queries
;
197 dns_adbfindlist_t finds
;
198 dns_adbfind_t
* find
;
199 dns_adbfindlist_t altfinds
;
200 dns_adbfind_t
* altfind
;
201 dns_adbaddrinfolist_t forwaddrs
;
202 dns_adbaddrinfolist_t altaddrs
;
203 isc_sockaddrlist_t forwarders
;
204 dns_fwdpolicy_t fwdpolicy
;
205 isc_sockaddrlist_t bad
;
206 isc_sockaddrlist_t edns
;
207 isc_sockaddrlist_t edns512
;
208 dns_validator_t
*validator
;
209 ISC_LIST(dns_validator_t
) validators
;
214 * The number of events we're waiting for.
216 unsigned int pending
;
219 * The number of times we've "restarted" the current
220 * nameserver set. This acts as a failsafe to prevent
221 * us from pounding constantly on a particular set of
222 * servers that, for whatever reason, are not giving
223 * us useful responses, but are responding in such a
224 * way that they are not marked "bad".
226 unsigned int restarts
;
229 * The number of timeouts that have occurred since we
230 * last successfully received a response packet. This
231 * is used for EDNS0 black hole detection.
233 unsigned int timeouts
;
236 * Look aside state for DS lookups.
239 dns_fetch_t
* nsfetch
;
240 dns_rdataset_t nsrrset
;
243 * Number of queries that reference this context.
245 unsigned int nqueries
;
248 * The reason to print when logging a successful
249 * response to a query.
254 * Random numbers to use for mixing up server addresses.
256 isc_uint32_t rand_buf
;
257 isc_uint32_t rand_bits
;
260 * Fetch-local statistics for detailed logging.
262 isc_result_t result
; /*%< fetch result */
263 isc_result_t vresult
; /*%< validation result */
266 isc_uint64_t duration
;
267 isc_boolean_t logged
;
268 unsigned int querysent
;
269 unsigned int referrals
;
270 unsigned int lamecount
;
272 unsigned int badresp
;
274 unsigned int findfail
;
275 unsigned int valfail
;
276 isc_boolean_t timeout
;
277 dns_adbaddrinfo_t
*addrinfo
;
278 isc_sockaddr_t
*client
;
281 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
282 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
284 #define FCTX_ATTR_HAVEANSWER 0x0001
285 #define FCTX_ATTR_GLUING 0x0002
286 #define FCTX_ATTR_ADDRWAIT 0x0004
287 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
288 #define FCTX_ATTR_WANTCACHE 0x0010
289 #define FCTX_ATTR_WANTNCACHE 0x0020
290 #define FCTX_ATTR_NEEDEDNS0 0x0040
291 #define FCTX_ATTR_TRIEDFIND 0x0080
292 #define FCTX_ATTR_TRIEDALT 0x0100
294 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
296 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
298 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
300 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
302 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
303 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
304 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
305 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
306 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
309 dns_adbaddrinfo_t
* addrinfo
;
315 fetchctx_t
* private;
318 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
319 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
321 typedef struct fctxbucket
{
324 ISC_LIST(fetchctx_t
) fctxs
;
325 isc_boolean_t exiting
;
329 typedef struct alternate
{
330 isc_boolean_t isaddress
;
338 ISC_LINK(struct alternate
) link
;
341 struct dns_resolver
{
347 isc_mutex_t primelock
;
348 dns_rdataclass_t rdclass
;
349 isc_socketmgr_t
* socketmgr
;
350 isc_timermgr_t
* timermgr
;
351 isc_taskmgr_t
* taskmgr
;
353 isc_boolean_t frozen
;
354 unsigned int options
;
355 dns_dispatchmgr_t
* dispatchmgr
;
356 dns_dispatch_t
* dispatchv4
;
357 isc_boolean_t exclusivev4
;
358 dns_dispatch_t
* dispatchv6
;
359 isc_boolean_t exclusivev6
;
361 unsigned int nbuckets
;
362 fctxbucket_t
* buckets
;
363 isc_uint32_t lame_ttl
;
364 ISC_LIST(alternate_t
) alternates
;
365 isc_uint16_t udpsize
;
367 isc_rwlock_t alglock
;
369 dns_rbt_t
* algorithms
;
371 isc_rwlock_t mbslock
;
373 dns_rbt_t
* mustbesecure
;
374 unsigned int spillatmax
;
375 unsigned int spillatmin
;
376 isc_timer_t
* spillattimer
;
377 isc_boolean_t zero_no_soa_ttl
;
379 /* Locked by lock. */
380 unsigned int references
;
381 isc_boolean_t exiting
;
382 isc_eventlist_t whenshutdown
;
383 unsigned int activebuckets
;
384 isc_boolean_t priming
;
385 unsigned int spillat
; /* clients-per-query */
386 unsigned int nextdisp
;
387 /* Locked by primelock. */
388 dns_fetch_t
* primefetch
;
389 /* Locked by nlock. */
393 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
394 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
397 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
398 * which we also use as an addrinfo flag.
400 #define FCTX_ADDRINFO_MARK 0x0001
401 #define FCTX_ADDRINFO_FORWARDER 0x1000
402 #define FCTX_ADDRINFO_TRIED 0x2000
403 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
405 #define ISFORWARDER(a) (((a)->flags & \
406 FCTX_ADDRINFO_FORWARDER) != 0)
407 #define TRIED(a) (((a)->flags & \
408 FCTX_ADDRINFO_TRIED) != 0)
410 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
412 static void destroy(dns_resolver_t
*res
);
413 static void empty_bucket(dns_resolver_t
*res
);
414 static isc_result_t
resquery_send(resquery_t
*query
);
415 static void resquery_response(isc_task_t
*task
, isc_event_t
*event
);
416 static void resquery_connected(isc_task_t
*task
, isc_event_t
*event
);
417 static void fctx_try(fetchctx_t
*fctx
, isc_boolean_t retrying
);
418 static isc_boolean_t
fctx_destroy(fetchctx_t
*fctx
);
419 static isc_result_t
ncache_adderesult(dns_message_t
*message
,
420 dns_db_t
*cache
, dns_dbnode_t
*node
,
421 dns_rdatatype_t covers
,
422 isc_stdtime_t now
, dns_ttl_t maxttl
,
423 isc_boolean_t optout
,
424 dns_rdataset_t
*ardataset
,
425 isc_result_t
*eresultp
);
426 static void validated(isc_task_t
*task
, isc_event_t
*event
);
427 static void maybe_destroy(fetchctx_t
*fctx
);
428 static void add_bad(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
429 isc_result_t reason
, badnstype_t badtype
);
432 * Increment resolver-related statistics counters.
435 inc_stats(dns_resolver_t
*res
, isc_statscounter_t counter
) {
436 if (res
->view
->resstats
!= NULL
)
437 isc_stats_increment(res
->view
->resstats
, counter
);
441 valcreate(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, dns_name_t
*name
,
442 dns_rdatatype_t type
, dns_rdataset_t
*rdataset
,
443 dns_rdataset_t
*sigrdataset
, unsigned int valoptions
,
446 dns_validator_t
*validator
= NULL
;
447 dns_valarg_t
*valarg
;
450 valarg
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
453 return (ISC_R_NOMEMORY
);
456 valarg
->addrinfo
= addrinfo
;
458 if (!ISC_LIST_EMPTY(fctx
->validators
))
459 INSIST((valoptions
& DNS_VALIDATOR_DEFER
) != 0);
461 result
= dns_validator_create(fctx
->res
->view
, name
, type
, rdataset
,
462 sigrdataset
, fctx
->rmessage
,
463 valoptions
, task
, validated
, valarg
,
465 if (result
== ISC_R_SUCCESS
) {
466 inc_stats(fctx
->res
, dns_resstatscounter_val
);
467 if ((valoptions
& DNS_VALIDATOR_DEFER
) == 0) {
468 INSIST(fctx
->validator
== NULL
);
469 fctx
->validator
= validator
;
471 ISC_LIST_APPEND(fctx
->validators
, validator
, link
);
473 isc_mem_put(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
474 valarg
, sizeof(*valarg
));
479 rrsig_fromchildzone(fetchctx_t
*fctx
, dns_rdataset_t
*rdataset
) {
480 dns_namereln_t namereln
;
481 dns_rdata_rrsig_t rrsig
;
482 dns_rdata_t rdata
= DNS_RDATA_INIT
;
487 for (result
= dns_rdataset_first(rdataset
);
488 result
== ISC_R_SUCCESS
;
489 result
= dns_rdataset_next(rdataset
)) {
490 dns_rdataset_current(rdataset
, &rdata
);
491 result
= dns_rdata_tostruct(&rdata
, &rrsig
, NULL
);
492 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
493 namereln
= dns_name_fullcompare(&rrsig
.signer
, &fctx
->domain
,
495 if (namereln
== dns_namereln_subdomain
)
497 dns_rdata_reset(&rdata
);
503 fix_mustbedelegationornxdomain(dns_message_t
*message
, fetchctx_t
*fctx
) {
505 dns_name_t
*domain
= &fctx
->domain
;
506 dns_rdataset_t
*rdataset
;
507 dns_rdatatype_t type
;
509 isc_boolean_t keep_auth
= ISC_FALSE
;
511 if (message
->rcode
== dns_rcode_nxdomain
)
515 * A DS RRset can appear anywhere in a zone, even for a delegation-only
516 * zone. So a response to an explicit query for this type should be
517 * excluded from delegation-only fixup.
519 * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
520 * response to a query for these types can never violate the
521 * delegation-only assumption: if the query name is below a
522 * zone cut, the response should normally be a referral, which should
523 * be accepted; if the query name is below a zone cut but the server
524 * happens to have authority for the zone of the query name, the
525 * response is a (non-referral) answer. But this does not violate
526 * delegation-only because the query name must be in a different zone
527 * due to the "apex-only" nature of these types. Note that if the
528 * remote server happens to have authority for a child zone of a
529 * delegation-only zone, we may still incorrectly "fix" the response
530 * with NXDOMAIN for queries for other types. Unfortunately it's
531 * generally impossible to differentiate this case from violation of
532 * the delegation-only assumption. Once the resolver learns the
533 * correct zone cut, possibly via a separate query for an "apex-only"
534 * type, queries for other types will be resolved correctly.
536 * A query for type ANY will be accepted if it hits an exceptional
537 * type above in the answer section as it should be from a child
540 * Also accept answers with RRSIG records from the child zone.
541 * Direct queries for RRSIG records should not be answered from
545 if (message
->counts
[DNS_SECTION_ANSWER
] != 0 &&
546 (fctx
->type
== dns_rdatatype_ns
||
547 fctx
->type
== dns_rdatatype_ds
||
548 fctx
->type
== dns_rdatatype_soa
||
549 fctx
->type
== dns_rdatatype_any
||
550 fctx
->type
== dns_rdatatype_rrsig
||
551 fctx
->type
== dns_rdatatype_dnskey
)) {
552 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
553 while (result
== ISC_R_SUCCESS
) {
555 dns_message_currentname(message
, DNS_SECTION_ANSWER
,
557 for (rdataset
= ISC_LIST_HEAD(name
->list
);
559 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
560 if (!dns_name_equal(name
, &fctx
->name
))
562 type
= rdataset
->type
;
566 if (type
== dns_rdatatype_rrsig
&&
567 rrsig_fromchildzone(fctx
, rdataset
))
570 * Direct query for apex records or DS.
572 if (fctx
->type
== type
&&
573 (type
== dns_rdatatype_ds
||
574 type
== dns_rdatatype_ns
||
575 type
== dns_rdatatype_soa
||
576 type
== dns_rdatatype_dnskey
))
579 * Indirect query for apex records or DS.
581 if (fctx
->type
== dns_rdatatype_any
&&
582 (type
== dns_rdatatype_ns
||
583 type
== dns_rdatatype_ds
||
584 type
== dns_rdatatype_soa
||
585 type
== dns_rdatatype_dnskey
))
588 result
= dns_message_nextname(message
,
594 * A NODATA response to a DS query?
596 if (fctx
->type
== dns_rdatatype_ds
&&
597 message
->counts
[DNS_SECTION_ANSWER
] == 0)
600 /* Look for referral or indication of answer from child zone? */
601 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
604 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
605 while (result
== ISC_R_SUCCESS
) {
607 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
608 for (rdataset
= ISC_LIST_HEAD(name
->list
);
610 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
611 type
= rdataset
->type
;
612 if (type
== dns_rdatatype_soa
&&
613 dns_name_equal(name
, domain
))
614 keep_auth
= ISC_TRUE
;
616 if (type
!= dns_rdatatype_ns
&&
617 type
!= dns_rdatatype_soa
&&
618 type
!= dns_rdatatype_rrsig
)
621 if (type
== dns_rdatatype_rrsig
) {
622 if (rrsig_fromchildzone(fctx
, rdataset
))
628 /* NS or SOA records. */
629 if (dns_name_equal(name
, domain
)) {
631 * If a query for ANY causes a negative
632 * response, we can be sure that this is
633 * an empty node. For other type of queries
634 * we cannot differentiate an empty node
635 * from a node that just doesn't have that
636 * type of record. We only accept the former
639 if (message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
640 fctx
->type
== dns_rdatatype_any
)
642 } else if (dns_name_issubdomain(name
, domain
)) {
643 /* Referral or answer from child zone. */
647 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
651 message
->rcode
= dns_rcode_nxdomain
;
652 message
->counts
[DNS_SECTION_ANSWER
] = 0;
654 message
->counts
[DNS_SECTION_AUTHORITY
] = 0;
655 message
->counts
[DNS_SECTION_ADDITIONAL
] = 0;
659 static inline isc_result_t
660 fctx_starttimer(fetchctx_t
*fctx
) {
662 * Start the lifetime timer for fctx.
664 * This is also used for stopping the idle timer; in that
665 * case we must purge events already posted to ensure that
666 * no further idle events are delivered.
668 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
669 &fctx
->expires
, NULL
, ISC_TRUE
));
673 fctx_stoptimer(fetchctx_t
*fctx
) {
677 * We don't return a result if resetting the timer to inactive fails
678 * since there's nothing to be done about it. Resetting to inactive
679 * should never fail anyway, since the code as currently written
680 * cannot fail in that case.
682 result
= isc_timer_reset(fctx
->timer
, isc_timertype_inactive
,
683 NULL
, NULL
, ISC_TRUE
);
684 if (result
!= ISC_R_SUCCESS
) {
685 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
686 "isc_timer_reset(): %s",
687 isc_result_totext(result
));
692 static inline isc_result_t
693 fctx_startidletimer(fetchctx_t
*fctx
, isc_interval_t
*interval
) {
695 * Start the idle timer for fctx. The lifetime timer continues
698 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
699 &fctx
->expires
, interval
, ISC_FALSE
));
703 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
704 * we use fctx_stopidletimer for readability in the code below.
706 #define fctx_stopidletimer fctx_starttimer
710 resquery_destroy(resquery_t
**queryp
) {
713 REQUIRE(queryp
!= NULL
);
715 REQUIRE(!ISC_LINK_LINKED(query
, link
));
717 INSIST(query
->tcpsocket
== NULL
);
719 query
->fctx
->nqueries
--;
720 if (SHUTTINGDOWN(query
->fctx
))
721 maybe_destroy(query
->fctx
); /* Locks bucket. */
723 isc_mem_put(query
->mctx
, query
, sizeof(*query
));
728 fctx_cancelquery(resquery_t
**queryp
, dns_dispatchevent_t
**deventp
,
729 isc_time_t
*finish
, isc_boolean_t no_response
)
733 unsigned int rtt
, rttms
;
736 dns_adbaddrinfo_t
*addrinfo
;
737 isc_socket_t
*socket
;
742 FCTXTRACE("cancelquery");
744 REQUIRE(!RESQUERY_CANCELED(query
));
746 query
->attributes
|= RESQUERY_ATTR_CANCELED
;
749 * Should we update the RTT?
751 if (finish
!= NULL
|| no_response
) {
752 if (finish
!= NULL
) {
754 * We have both the start and finish times for this
755 * packet, so we can compute a real RTT.
757 rtt
= (unsigned int)isc_time_microdiff(finish
,
759 factor
= DNS_ADB_RTTADJDEFAULT
;
762 if (rttms
< DNS_RESOLVER_QRYRTTCLASS0
) {
764 dns_resstatscounter_queryrtt0
);
765 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS1
) {
767 dns_resstatscounter_queryrtt1
);
768 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS2
) {
770 dns_resstatscounter_queryrtt2
);
771 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS3
) {
773 dns_resstatscounter_queryrtt3
);
774 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS4
) {
776 dns_resstatscounter_queryrtt4
);
779 dns_resstatscounter_queryrtt5
);
783 * We don't have an RTT for this query. Maybe the
784 * packet was lost, or maybe this server is very
785 * slow. We don't know. Increase the RTT.
788 rtt
= query
->addrinfo
->srtt
+ 200000;
792 * Replace the current RTT with our value.
794 factor
= DNS_ADB_RTTADJREPLACE
;
796 dns_adb_adjustsrtt(fctx
->adb
, query
->addrinfo
, rtt
, factor
);
799 /* Remember that the server has been tried. */
800 if (!TRIED(query
->addrinfo
)) {
801 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
802 FCTX_ADDRINFO_TRIED
, FCTX_ADDRINFO_TRIED
);
806 * Age RTTs of servers not tried.
808 factor
= DNS_ADB_RTTADJAGE
;
810 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
812 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
813 if (UNMARKED(addrinfo
))
814 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
817 if (finish
!= NULL
&& TRIEDFIND(fctx
))
818 for (find
= ISC_LIST_HEAD(fctx
->finds
);
820 find
= ISC_LIST_NEXT(find
, publink
))
821 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
823 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
824 if (UNMARKED(addrinfo
))
825 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
828 if (finish
!= NULL
&& TRIEDALT(fctx
)) {
829 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
831 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
832 if (UNMARKED(addrinfo
))
833 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
835 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
837 find
= ISC_LIST_NEXT(find
, publink
))
838 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
840 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
841 if (UNMARKED(addrinfo
))
842 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
847 * Check for any outstanding socket events. If they exist, cancel
848 * them and let the event handlers finish the cleanup. The resolver
849 * only needs to worry about managing the connect and send events;
850 * the dispatcher manages the recv events.
852 if (RESQUERY_CONNECTING(query
)) {
854 * Cancel the connect.
856 if (query
->tcpsocket
!= NULL
) {
857 isc_socket_cancel(query
->tcpsocket
, NULL
,
858 ISC_SOCKCANCEL_CONNECT
);
859 } else if (query
->dispentry
!= NULL
) {
860 INSIST(query
->exclusivesocket
);
861 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
863 isc_socket_cancel(socket
, NULL
,
864 ISC_SOCKCANCEL_CONNECT
);
866 } else if (RESQUERY_SENDING(query
)) {
868 * Cancel the pending send.
870 if (query
->exclusivesocket
&& query
->dispentry
!= NULL
)
871 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
873 socket
= dns_dispatch_getsocket(query
->dispatch
);
875 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_SEND
);
878 if (query
->dispentry
!= NULL
)
879 dns_dispatch_removeresponse(&query
->dispentry
, deventp
);
881 ISC_LIST_UNLINK(fctx
->queries
, query
, link
);
883 if (query
->tsig
!= NULL
)
884 isc_buffer_free(&query
->tsig
);
886 if (query
->tsigkey
!= NULL
)
887 dns_tsigkey_detach(&query
->tsigkey
);
889 if (query
->dispatch
!= NULL
)
890 dns_dispatch_detach(&query
->dispatch
);
892 if (! (RESQUERY_CONNECTING(query
) || RESQUERY_SENDING(query
)))
894 * It's safe to destroy the query now.
896 resquery_destroy(&query
);
900 fctx_cancelqueries(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
901 resquery_t
*query
, *next_query
;
903 FCTXTRACE("cancelqueries");
905 for (query
= ISC_LIST_HEAD(fctx
->queries
);
907 query
= next_query
) {
908 next_query
= ISC_LIST_NEXT(query
, link
);
909 fctx_cancelquery(&query
, NULL
, NULL
, no_response
);
914 fctx_cleanupfinds(fetchctx_t
*fctx
) {
915 dns_adbfind_t
*find
, *next_find
;
917 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
919 for (find
= ISC_LIST_HEAD(fctx
->finds
);
922 next_find
= ISC_LIST_NEXT(find
, publink
);
923 ISC_LIST_UNLINK(fctx
->finds
, find
, publink
);
924 dns_adb_destroyfind(&find
);
930 fctx_cleanupaltfinds(fetchctx_t
*fctx
) {
931 dns_adbfind_t
*find
, *next_find
;
933 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
935 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
938 next_find
= ISC_LIST_NEXT(find
, publink
);
939 ISC_LIST_UNLINK(fctx
->altfinds
, find
, publink
);
940 dns_adb_destroyfind(&find
);
942 fctx
->altfind
= NULL
;
946 fctx_cleanupforwaddrs(fetchctx_t
*fctx
) {
947 dns_adbaddrinfo_t
*addr
, *next_addr
;
949 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
951 for (addr
= ISC_LIST_HEAD(fctx
->forwaddrs
);
954 next_addr
= ISC_LIST_NEXT(addr
, publink
);
955 ISC_LIST_UNLINK(fctx
->forwaddrs
, addr
, publink
);
956 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
961 fctx_cleanupaltaddrs(fetchctx_t
*fctx
) {
962 dns_adbaddrinfo_t
*addr
, *next_addr
;
964 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
966 for (addr
= ISC_LIST_HEAD(fctx
->altaddrs
);
969 next_addr
= ISC_LIST_NEXT(addr
, publink
);
970 ISC_LIST_UNLINK(fctx
->altaddrs
, addr
, publink
);
971 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
976 fctx_stopeverything(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
977 FCTXTRACE("stopeverything");
978 fctx_cancelqueries(fctx
, no_response
);
979 fctx_cleanupfinds(fctx
);
980 fctx_cleanupaltfinds(fctx
);
981 fctx_cleanupforwaddrs(fctx
);
982 fctx_cleanupaltaddrs(fctx
);
983 fctx_stoptimer(fctx
);
987 fctx_sendevents(fetchctx_t
*fctx
, isc_result_t result
, int line
) {
988 dns_fetchevent_t
*event
, *next_event
;
990 unsigned int count
= 0;
992 isc_boolean_t logit
= ISC_FALSE
;
994 unsigned int old_spillat
;
995 unsigned int new_spillat
= 0; /* initialized to silence
999 * Caller must be holding the appropriate bucket lock.
1001 REQUIRE(fctx
->state
== fetchstate_done
);
1003 FCTXTRACE("sendevents");
1006 * Keep some record of fetch result for logging later (if required).
1008 fctx
->result
= result
;
1009 fctx
->exitline
= line
;
1011 fctx
->duration
= isc_time_microdiff(&now
, &fctx
->start
);
1013 for (event
= ISC_LIST_HEAD(fctx
->events
);
1015 event
= next_event
) {
1016 next_event
= ISC_LIST_NEXT(event
, ev_link
);
1017 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
1018 task
= event
->ev_sender
;
1019 event
->ev_sender
= fctx
;
1020 event
->vresult
= fctx
->vresult
;
1021 if (!HAVE_ANSWER(fctx
))
1022 event
->result
= result
;
1024 INSIST(result
!= ISC_R_SUCCESS
||
1025 dns_rdataset_isassociated(event
->rdataset
) ||
1026 fctx
->type
== dns_rdatatype_any
||
1027 fctx
->type
== dns_rdatatype_rrsig
||
1028 fctx
->type
== dns_rdatatype_sig
);
1031 * Negative results must be indicated in event->result.
1033 if (dns_rdataset_isassociated(event
->rdataset
) &&
1034 event
->rdataset
->type
== dns_rdatatype_none
) {
1035 INSIST(event
->result
== DNS_R_NCACHENXDOMAIN
||
1036 event
->result
== DNS_R_NCACHENXRRSET
);
1039 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&event
));
1043 if ((fctx
->attributes
& FCTX_ATTR_HAVEANSWER
) != 0 &&
1045 (count
< fctx
->res
->spillatmax
|| fctx
->res
->spillatmax
== 0)) {
1046 LOCK(&fctx
->res
->lock
);
1047 if (count
== fctx
->res
->spillat
&& !fctx
->res
->exiting
) {
1048 old_spillat
= fctx
->res
->spillat
;
1049 fctx
->res
->spillat
+= 5;
1050 if (fctx
->res
->spillat
> fctx
->res
->spillatmax
&&
1051 fctx
->res
->spillatmax
!= 0)
1052 fctx
->res
->spillat
= fctx
->res
->spillatmax
;
1053 new_spillat
= fctx
->res
->spillat
;
1054 if (new_spillat
!= old_spillat
) {
1057 isc_interval_set(&i
, 20 * 60, 0);
1058 result
= isc_timer_reset(fctx
->res
->spillattimer
,
1059 isc_timertype_ticker
, NULL
,
1061 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1063 UNLOCK(&fctx
->res
->lock
);
1065 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
1066 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
1067 "clients-per-query increased to %u",
1073 log_edns(fetchctx_t
*fctx
) {
1074 char domainbuf
[DNS_NAME_FORMATSIZE
];
1076 if (fctx
->reason
== NULL
)
1079 if (!isc_log_wouldlog(dns_lctx
, ISC_LOG_DEBUG(3)))
1081 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
1082 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_EDNS_DISABLED
,
1083 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
1084 "success resolving '%s' (in '%s'?) after %s",
1085 fctx
->info
, domainbuf
, fctx
->reason
);
1087 fctx
->reason
= NULL
;
1091 fctx_done(fetchctx_t
*fctx
, isc_result_t result
, int line
) {
1092 dns_resolver_t
*res
;
1093 isc_boolean_t no_response
;
1101 if (result
== ISC_R_SUCCESS
) {
1103 * Log any deferred EDNS timeout messages.
1106 no_response
= ISC_TRUE
;
1108 no_response
= ISC_FALSE
;
1110 fctx
->reason
= NULL
;
1111 fctx_stopeverything(fctx
, no_response
);
1113 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
1115 fctx
->state
= fetchstate_done
;
1116 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1117 fctx_sendevents(fctx
, result
, line
);
1119 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
1123 process_sendevent(resquery_t
*query
, isc_event_t
*event
) {
1124 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1125 isc_boolean_t retry
= ISC_FALSE
;
1126 isc_result_t result
;
1131 if (RESQUERY_CANCELED(query
)) {
1132 if (query
->sends
== 0 && query
->connects
== 0) {
1134 * This query was canceled while the
1135 * isc_socket_sendto/connect() was in progress.
1137 if (query
->tcpsocket
!= NULL
)
1138 isc_socket_detach(&query
->tcpsocket
);
1139 resquery_destroy(&query
);
1142 switch (sevent
->result
) {
1146 case ISC_R_HOSTUNREACH
:
1147 case ISC_R_NETUNREACH
:
1149 case ISC_R_ADDRNOTAVAIL
:
1150 case ISC_R_CONNREFUSED
:
1153 * No route to remote.
1155 add_bad(fctx
, query
->addrinfo
, sevent
->result
,
1157 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
1162 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
1167 isc_event_free(&event
);
1171 * Behave as if the idle timer has expired. For TCP
1172 * this may not actually reflect the latest timer.
1174 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1175 result
= fctx_stopidletimer(fctx
);
1176 if (result
!= ISC_R_SUCCESS
)
1177 fctx_done(fctx
, result
, __LINE__
);
1179 fctx_try(fctx
, ISC_TRUE
);
1184 resquery_udpconnected(isc_task_t
*task
, isc_event_t
*event
) {
1185 resquery_t
*query
= event
->ev_arg
;
1187 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1189 QTRACE("udpconnected");
1193 INSIST(RESQUERY_CONNECTING(query
));
1197 process_sendevent(query
, event
);
1201 resquery_senddone(isc_task_t
*task
, isc_event_t
*event
) {
1202 resquery_t
*query
= event
->ev_arg
;
1204 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1211 * Currently we don't wait for the senddone event before retrying
1212 * a query. This means that if we get really behind, we may end
1213 * up doing extra work!
1218 INSIST(RESQUERY_SENDING(query
));
1222 process_sendevent(query
, event
);
1225 static inline isc_result_t
1226 fctx_addopt(dns_message_t
*message
, unsigned int version
,
1227 isc_uint16_t udpsize
, isc_boolean_t request_nsid
)
1229 dns_rdataset_t
*rdataset
;
1230 dns_rdatalist_t
*rdatalist
;
1232 isc_result_t result
;
1235 result
= dns_message_gettemprdatalist(message
, &rdatalist
);
1236 if (result
!= ISC_R_SUCCESS
)
1239 result
= dns_message_gettemprdata(message
, &rdata
);
1240 if (result
!= ISC_R_SUCCESS
)
1243 result
= dns_message_gettemprdataset(message
, &rdataset
);
1244 if (result
!= ISC_R_SUCCESS
)
1246 dns_rdataset_init(rdataset
);
1248 rdatalist
->type
= dns_rdatatype_opt
;
1249 rdatalist
->covers
= 0;
1252 * Set Maximum UDP buffer size.
1254 rdatalist
->rdclass
= udpsize
;
1257 * Set EXTENDED-RCODE and Z to 0, DO to 1.
1259 rdatalist
->ttl
= (version
<< 16);
1260 rdatalist
->ttl
|= DNS_MESSAGEEXTFLAG_DO
;
1263 * Set EDNS options if applicable
1266 /* Send empty NSID option (RFC5001) */
1267 unsigned char data
[4];
1270 isc_buffer_init(&buf
, data
, sizeof(data
));
1271 isc_buffer_putuint16(&buf
, DNS_OPT_NSID
);
1272 isc_buffer_putuint16(&buf
, 0);
1274 rdata
->length
= sizeof(data
);
1280 rdata
->rdclass
= rdatalist
->rdclass
;
1281 rdata
->type
= rdatalist
->type
;
1284 ISC_LIST_INIT(rdatalist
->rdata
);
1285 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1286 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
) == ISC_R_SUCCESS
);
1288 return (dns_message_setopt(message
, rdataset
));
1292 fctx_setretryinterval(fetchctx_t
*fctx
, unsigned int rtt
) {
1293 unsigned int seconds
;
1297 * We retry every .8 seconds the first two times through the address
1298 * list, and then we do exponential back-off.
1300 if (fctx
->restarts
< 3)
1303 us
= (800000 << (fctx
->restarts
- 2));
1306 * Double the round-trip time.
1311 * Always wait for at least the doubled round-trip time.
1317 * But don't ever wait for more than 10 seconds.
1322 seconds
= us
/ 1000000;
1323 us
-= seconds
* 1000000;
1324 isc_interval_set(&fctx
->interval
, seconds
, us
* 1000);
1328 fctx_query(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
1329 unsigned int options
)
1331 dns_resolver_t
*res
;
1333 isc_result_t result
;
1335 isc_sockaddr_t addr
;
1336 isc_boolean_t have_addr
= ISC_FALSE
;
1342 task
= res
->buckets
[fctx
->bucketnum
].task
;
1344 srtt
= addrinfo
->srtt
;
1345 if (ISFORWARDER(addrinfo
) && srtt
< 1000000)
1348 fctx_setretryinterval(fctx
, srtt
);
1349 result
= fctx_startidletimer(fctx
, &fctx
->interval
);
1350 if (result
!= ISC_R_SUCCESS
)
1353 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
1355 dns_message_reset(fctx
->rmessage
, DNS_MESSAGE_INTENTPARSE
);
1357 query
= isc_mem_get(res
->buckets
[fctx
->bucketnum
].mctx
,
1359 if (query
== NULL
) {
1360 result
= ISC_R_NOMEMORY
;
1361 goto stop_idle_timer
;
1363 query
->mctx
= res
->buckets
[fctx
->bucketnum
].mctx
;
1364 query
->options
= options
;
1365 query
->attributes
= 0;
1367 query
->connects
= 0;
1369 * Note that the caller MUST guarantee that 'addrinfo' will remain
1370 * valid until this query is canceled.
1372 query
->addrinfo
= addrinfo
;
1373 TIME_NOW(&query
->start
);
1376 * If this is a TCP query, then we need to make a socket and
1377 * a dispatch for it here. Otherwise we use the resolver's
1380 query
->dispatchmgr
= res
->dispatchmgr
;
1381 query
->dispatch
= NULL
;
1382 query
->exclusivesocket
= ISC_FALSE
;
1383 query
->tcpsocket
= NULL
;
1384 if (res
->view
->peers
!= NULL
) {
1385 dns_peer_t
*peer
= NULL
;
1386 isc_netaddr_t dstip
;
1387 isc_netaddr_fromsockaddr(&dstip
, &addrinfo
->sockaddr
);
1388 result
= dns_peerlist_peerbyaddr(res
->view
->peers
,
1390 if (result
== ISC_R_SUCCESS
) {
1391 result
= dns_peer_getquerysource(peer
, &addr
);
1392 if (result
== ISC_R_SUCCESS
)
1393 have_addr
= ISC_TRUE
;
1397 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1400 pf
= isc_sockaddr_pf(&addrinfo
->sockaddr
);
1405 dns_dispatch_getlocaladdress(res
->dispatchv4
,
1410 dns_dispatch_getlocaladdress(res
->dispatchv6
,
1414 result
= ISC_R_NOTIMPLEMENTED
;
1417 if (result
!= ISC_R_SUCCESS
)
1420 isc_sockaddr_setport(&addr
, 0);
1422 result
= isc_socket_create(res
->socketmgr
, pf
,
1425 if (result
!= ISC_R_SUCCESS
)
1428 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1429 result
= isc_socket_bind(query
->tcpsocket
, &addr
, 0);
1430 if (result
!= ISC_R_SUCCESS
)
1431 goto cleanup_socket
;
1435 * A dispatch will be created once the connect succeeds.
1439 unsigned int attrs
, attrmask
;
1440 attrs
= DNS_DISPATCHATTR_UDP
;
1441 switch (isc_sockaddr_pf(&addr
)) {
1443 attrs
|= DNS_DISPATCHATTR_IPV4
;
1446 attrs
|= DNS_DISPATCHATTR_IPV6
;
1449 result
= ISC_R_NOTIMPLEMENTED
;
1452 attrmask
= DNS_DISPATCHATTR_UDP
;
1453 attrmask
|= DNS_DISPATCHATTR_TCP
;
1454 attrmask
|= DNS_DISPATCHATTR_IPV4
;
1455 attrmask
|= DNS_DISPATCHATTR_IPV6
;
1456 result
= dns_dispatch_getudp(res
->dispatchmgr
,
1458 res
->taskmgr
, &addr
,
1459 4096, 1000, 32768, 16411,
1460 16433, attrs
, attrmask
,
1462 if (result
!= ISC_R_SUCCESS
)
1465 switch (isc_sockaddr_pf(&addrinfo
->sockaddr
)) {
1467 dns_dispatch_attach(res
->dispatchv4
,
1469 query
->exclusivesocket
= res
->exclusivev4
;
1472 dns_dispatch_attach(res
->dispatchv6
,
1474 query
->exclusivesocket
= res
->exclusivev6
;
1477 result
= ISC_R_NOTIMPLEMENTED
;
1482 * We should always have a valid dispatcher here. If we
1483 * don't support a protocol family, then its dispatcher
1484 * will be NULL, but we shouldn't be finding addresses for
1485 * protocol types we don't support, so the dispatcher
1486 * we found should never be NULL.
1488 INSIST(query
->dispatch
!= NULL
);
1491 query
->dispentry
= NULL
;
1494 query
->tsigkey
= NULL
;
1495 ISC_LINK_INIT(query
, link
);
1496 query
->magic
= QUERY_MAGIC
;
1498 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1500 * Connect to the remote server.
1502 * XXXRTH Should we attach to the socket?
1504 result
= isc_socket_connect(query
->tcpsocket
,
1505 &addrinfo
->sockaddr
, task
,
1506 resquery_connected
, query
);
1507 if (result
!= ISC_R_SUCCESS
)
1508 goto cleanup_socket
;
1510 QTRACE("connecting via TCP");
1512 result
= resquery_send(query
);
1513 if (result
!= ISC_R_SUCCESS
)
1514 goto cleanup_dispatch
;
1518 ISC_LIST_APPEND(fctx
->queries
, query
, link
);
1519 query
->fctx
->nqueries
++;
1520 if (isc_sockaddr_pf(&addrinfo
->sockaddr
) == PF_INET
)
1521 inc_stats(res
, dns_resstatscounter_queryv4
);
1523 inc_stats(res
, dns_resstatscounter_queryv6
);
1524 if (res
->view
->resquerystats
!= NULL
)
1525 dns_rdatatypestats_increment(res
->view
->resquerystats
,
1528 return (ISC_R_SUCCESS
);
1531 isc_socket_detach(&query
->tcpsocket
);
1534 if (query
->dispatch
!= NULL
)
1535 dns_dispatch_detach(&query
->dispatch
);
1539 isc_mem_put(res
->buckets
[fctx
->bucketnum
].mctx
,
1540 query
, sizeof(*query
));
1543 RUNTIME_CHECK(fctx_stopidletimer(fctx
) == ISC_R_SUCCESS
);
1548 static isc_boolean_t
1549 triededns(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1552 for (sa
= ISC_LIST_HEAD(fctx
->edns
);
1554 sa
= ISC_LIST_NEXT(sa
, link
)) {
1555 if (isc_sockaddr_equal(sa
, address
))
1563 add_triededns(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1566 if (triededns(fctx
, address
))
1569 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
1575 ISC_LIST_INITANDAPPEND(fctx
->edns
, sa
, link
);
1578 static isc_boolean_t
1579 triededns512(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1582 for (sa
= ISC_LIST_HEAD(fctx
->edns512
);
1584 sa
= ISC_LIST_NEXT(sa
, link
)) {
1585 if (isc_sockaddr_equal(sa
, address
))
1593 add_triededns512(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1596 if (triededns512(fctx
, address
))
1599 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
1605 ISC_LIST_INITANDAPPEND(fctx
->edns512
, sa
, link
);
1609 resquery_send(resquery_t
*query
) {
1611 isc_result_t result
;
1612 dns_name_t
*qname
= NULL
;
1613 dns_rdataset_t
*qrdataset
= NULL
;
1615 dns_resolver_t
*res
;
1617 isc_socket_t
*socket
;
1618 isc_buffer_t tcpbuffer
;
1619 isc_sockaddr_t
*address
;
1620 isc_buffer_t
*buffer
;
1621 isc_netaddr_t ipaddr
;
1622 dns_tsigkey_t
*tsigkey
= NULL
;
1623 dns_peer_t
*peer
= NULL
;
1624 isc_boolean_t useedns
;
1625 dns_compress_t cctx
;
1626 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
1627 isc_boolean_t secure_domain
;
1633 task
= res
->buckets
[fctx
->bucketnum
].task
;
1636 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1638 * Reserve space for the TCP message length.
1640 isc_buffer_init(&tcpbuffer
, query
->data
, sizeof(query
->data
));
1641 isc_buffer_init(&query
->buffer
, query
->data
+ 2,
1642 sizeof(query
->data
) - 2);
1643 buffer
= &tcpbuffer
;
1645 isc_buffer_init(&query
->buffer
, query
->data
,
1646 sizeof(query
->data
));
1647 buffer
= &query
->buffer
;
1650 result
= dns_message_gettempname(fctx
->qmessage
, &qname
);
1651 if (result
!= ISC_R_SUCCESS
)
1653 result
= dns_message_gettemprdataset(fctx
->qmessage
, &qrdataset
);
1654 if (result
!= ISC_R_SUCCESS
)
1658 * Get a query id from the dispatch.
1660 result
= dns_dispatch_addresponse2(query
->dispatch
,
1661 &query
->addrinfo
->sockaddr
,
1668 if (result
!= ISC_R_SUCCESS
)
1671 fctx
->qmessage
->opcode
= dns_opcode_query
;
1676 dns_name_init(qname
, NULL
);
1677 dns_name_clone(&fctx
->name
, qname
);
1678 dns_rdataset_init(qrdataset
);
1679 dns_rdataset_makequestion(qrdataset
, res
->rdclass
, fctx
->type
);
1680 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
1681 dns_message_addname(fctx
->qmessage
, qname
, DNS_SECTION_QUESTION
);
1686 * Set RD if the client has requested that we do a recursive query,
1687 * or if we're sending to a forwarder.
1689 if ((query
->options
& DNS_FETCHOPT_RECURSIVE
) != 0 ||
1690 ISFORWARDER(query
->addrinfo
))
1691 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_RD
;
1694 * Set CD if the client says don't validate or the question is
1695 * under a secure entry point.
1697 if ((query
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0) {
1698 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1699 } else if (res
->view
->enablevalidation
) {
1700 result
= dns_view_issecuredomain(res
->view
, &fctx
->name
,
1702 if (result
!= ISC_R_SUCCESS
)
1703 secure_domain
= ISC_FALSE
;
1704 if (res
->view
->dlv
!= NULL
)
1705 secure_domain
= ISC_TRUE
;
1707 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1711 * We don't have to set opcode because it defaults to query.
1713 fctx
->qmessage
->id
= query
->id
;
1716 * Convert the question to wire format.
1718 result
= dns_compress_init(&cctx
, -1, fctx
->res
->mctx
);
1719 if (result
!= ISC_R_SUCCESS
)
1720 goto cleanup_message
;
1721 cleanup_cctx
= ISC_TRUE
;
1723 result
= dns_message_renderbegin(fctx
->qmessage
, &cctx
,
1725 if (result
!= ISC_R_SUCCESS
)
1726 goto cleanup_message
;
1728 result
= dns_message_rendersection(fctx
->qmessage
,
1729 DNS_SECTION_QUESTION
, 0);
1730 if (result
!= ISC_R_SUCCESS
)
1731 goto cleanup_message
;
1734 isc_netaddr_fromsockaddr(&ipaddr
, &query
->addrinfo
->sockaddr
);
1735 (void) dns_peerlist_peerbyaddr(fctx
->res
->view
->peers
, &ipaddr
, &peer
);
1738 * The ADB does not know about servers with "edns no". Check this,
1739 * and then inform the ADB for future use.
1741 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0 &&
1743 dns_peer_getsupportedns(peer
, &useedns
) == ISC_R_SUCCESS
&&
1746 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1747 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
1748 DNS_FETCHOPT_NOEDNS0
,
1749 DNS_FETCHOPT_NOEDNS0
);
1752 /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
1753 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) != 0)
1754 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1757 * Handle timeouts by reducing the UDP response size to 512 bytes
1758 * then if that doesn't work disabling EDNS (includes DO) and CD.
1760 * These timeout can be due to:
1761 * * broken nameservers that don't respond to EDNS queries.
1762 * * broken/misconfigured firewalls and NAT implementations
1763 * that don't handle IP fragmentation.
1764 * * broken/misconfigured firewalls that don't handle responses
1765 * greater than 512 bytes.
1766 * * broken/misconfigured firewalls that don't handle EDNS, DO
1768 * * packet loss / link outage.
1770 if (fctx
->timeout
) {
1771 if ((triededns512(fctx
, &query
->addrinfo
->sockaddr
) ||
1772 fctx
->timeouts
>= (MAX_EDNS0_TIMEOUTS
* 2)) &&
1773 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1774 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1775 fctx
->reason
= "disabling EDNS";
1776 } else if ((triededns(fctx
, &query
->addrinfo
->sockaddr
) ||
1777 fctx
->timeouts
>= MAX_EDNS0_TIMEOUTS
) &&
1778 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1779 query
->options
|= DNS_FETCHOPT_EDNS512
;
1780 fctx
->reason
= "reducing the advertised EDNS UDP "
1781 "packet size to 512 octets";
1783 fctx
->timeout
= ISC_FALSE
;
1787 * Use EDNS0, unless the caller doesn't want it, or we know that
1788 * the remote server doesn't like it.
1790 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1791 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1792 unsigned int version
= 0; /* Default version. */
1794 isc_uint16_t udpsize
= res
->udpsize
;
1795 isc_boolean_t reqnsid
= res
->view
->requestnsid
;
1797 flags
= query
->addrinfo
->flags
;
1798 if ((flags
& DNS_FETCHOPT_EDNSVERSIONSET
) != 0) {
1799 version
= flags
& DNS_FETCHOPT_EDNSVERSIONMASK
;
1800 version
>>= DNS_FETCHOPT_EDNSVERSIONSHIFT
;
1802 if ((query
->options
& DNS_FETCHOPT_EDNS512
) != 0)
1804 else if (peer
!= NULL
)
1805 (void)dns_peer_getudpsize(peer
, &udpsize
);
1807 /* request NSID for current view or peer? */
1809 (void) dns_peer_getrequestnsid(peer
, &reqnsid
);
1810 result
= fctx_addopt(fctx
->qmessage
, version
,
1812 if (reqnsid
&& result
== ISC_R_SUCCESS
) {
1813 query
->options
|= DNS_FETCHOPT_WANTNSID
;
1814 } else if (result
!= ISC_R_SUCCESS
) {
1816 * We couldn't add the OPT, but we'll press on.
1817 * We're not using EDNS0, so set the NOEDNS0
1820 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1824 * We know this server doesn't like EDNS0, so we
1825 * won't use it. Set the NOEDNS0 bit since we're
1828 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1833 * If we need EDNS0 to do this query and aren't using it, we lose.
1835 if (NEEDEDNS0(fctx
) && (query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0) {
1836 result
= DNS_R_SERVFAIL
;
1837 goto cleanup_message
;
1840 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0)
1841 add_triededns(fctx
, &query
->addrinfo
->sockaddr
);
1843 if ((query
->options
& DNS_FETCHOPT_EDNS512
) != 0)
1844 add_triededns512(fctx
, &query
->addrinfo
->sockaddr
);
1847 * Clear CD if EDNS is not in use.
1849 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0)
1850 fctx
->qmessage
->flags
&= ~DNS_MESSAGEFLAG_CD
;
1853 * Add TSIG record tailored to the current recipient.
1855 result
= dns_view_getpeertsig(fctx
->res
->view
, &ipaddr
, &tsigkey
);
1856 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
1857 goto cleanup_message
;
1859 if (tsigkey
!= NULL
) {
1860 result
= dns_message_settsigkey(fctx
->qmessage
, tsigkey
);
1861 dns_tsigkey_detach(&tsigkey
);
1862 if (result
!= ISC_R_SUCCESS
)
1863 goto cleanup_message
;
1866 result
= dns_message_rendersection(fctx
->qmessage
,
1867 DNS_SECTION_ADDITIONAL
, 0);
1868 if (result
!= ISC_R_SUCCESS
)
1869 goto cleanup_message
;
1871 result
= dns_message_renderend(fctx
->qmessage
);
1872 if (result
!= ISC_R_SUCCESS
)
1873 goto cleanup_message
;
1875 dns_compress_invalidate(&cctx
);
1876 cleanup_cctx
= ISC_FALSE
;
1878 if (dns_message_gettsigkey(fctx
->qmessage
) != NULL
) {
1879 dns_tsigkey_attach(dns_message_gettsigkey(fctx
->qmessage
),
1881 result
= dns_message_getquerytsig(fctx
->qmessage
,
1884 if (result
!= ISC_R_SUCCESS
)
1885 goto cleanup_message
;
1889 * If using TCP, write the length of the message at the beginning
1892 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1893 isc_buffer_usedregion(&query
->buffer
, &r
);
1894 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
)r
.length
);
1895 isc_buffer_add(&tcpbuffer
, r
.length
);
1899 * We're now done with the query message.
1901 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1903 if (query
->exclusivesocket
)
1904 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
1906 socket
= dns_dispatch_getsocket(query
->dispatch
);
1910 if ((query
->options
& DNS_FETCHOPT_TCP
) == 0) {
1911 address
= &query
->addrinfo
->sockaddr
;
1912 if (query
->exclusivesocket
) {
1913 result
= isc_socket_connect(socket
, address
, task
,
1914 resquery_udpconnected
,
1916 if (result
!= ISC_R_SUCCESS
)
1917 goto cleanup_message
;
1921 isc_buffer_usedregion(buffer
, &r
);
1924 * XXXRTH Make sure we don't send to ourselves! We should probably
1925 * prune out these addresses when we get them from the ADB.
1927 result
= isc_socket_sendto(socket
, &r
, task
, resquery_senddone
,
1928 query
, address
, NULL
);
1929 if (result
!= ISC_R_SUCCESS
)
1930 goto cleanup_message
;
1936 return (ISC_R_SUCCESS
);
1940 dns_compress_invalidate(&cctx
);
1942 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1945 * Stop the dispatcher from listening.
1947 dns_dispatch_removeresponse(&query
->dispentry
, NULL
);
1951 dns_message_puttempname(fctx
->qmessage
, &qname
);
1952 if (qrdataset
!= NULL
)
1953 dns_message_puttemprdataset(fctx
->qmessage
, &qrdataset
);
1959 resquery_connected(isc_task_t
*task
, isc_event_t
*event
) {
1960 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1961 resquery_t
*query
= event
->ev_arg
;
1962 isc_boolean_t retry
= ISC_FALSE
;
1963 isc_interval_t interval
;
1964 isc_result_t result
;
1968 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1969 REQUIRE(VALID_QUERY(query
));
1971 QTRACE("connected");
1978 * Currently we don't wait for the connect event before retrying
1979 * a query. This means that if we get really behind, we may end
1980 * up doing extra work!
1986 if (RESQUERY_CANCELED(query
)) {
1988 * This query was canceled while the connect() was in
1991 isc_socket_detach(&query
->tcpsocket
);
1992 resquery_destroy(&query
);
1994 switch (sevent
->result
) {
1998 * Extend the idle timer for TCP. 20 seconds
1999 * should be long enough for a TCP connection to be
2000 * established, a single DNS request to be sent,
2001 * and the response received.
2003 isc_interval_set(&interval
, 20, 0);
2004 result
= fctx_startidletimer(query
->fctx
, &interval
);
2005 if (result
!= ISC_R_SUCCESS
) {
2006 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
2007 fctx_done(fctx
, result
, __LINE__
);
2011 * We are connected. Create a dispatcher and
2015 attrs
|= DNS_DISPATCHATTR_TCP
;
2016 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
2017 attrs
|= DNS_DISPATCHATTR_CONNECTED
;
2018 if (isc_sockaddr_pf(&query
->addrinfo
->sockaddr
) ==
2020 attrs
|= DNS_DISPATCHATTR_IPV4
;
2022 attrs
|= DNS_DISPATCHATTR_IPV6
;
2023 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
2025 result
= dns_dispatch_createtcp(query
->dispatchmgr
,
2027 query
->fctx
->res
->taskmgr
,
2028 4096, 2, 1, 1, 3, attrs
,
2032 * Regardless of whether dns_dispatch_create()
2033 * succeeded or not, we don't need our reference
2034 * to the socket anymore.
2036 isc_socket_detach(&query
->tcpsocket
);
2038 if (result
== ISC_R_SUCCESS
)
2039 result
= resquery_send(query
);
2041 if (result
!= ISC_R_SUCCESS
) {
2042 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
2043 fctx_done(fctx
, result
, __LINE__
);
2047 case ISC_R_NETUNREACH
:
2048 case ISC_R_HOSTUNREACH
:
2049 case ISC_R_CONNREFUSED
:
2051 case ISC_R_ADDRNOTAVAIL
:
2052 case ISC_R_CONNECTIONRESET
:
2054 * No route to remote.
2056 isc_socket_detach(&query
->tcpsocket
);
2057 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
2062 isc_socket_detach(&query
->tcpsocket
);
2063 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
2068 isc_event_free(&event
);
2072 * Behave as if the idle timer has expired. For TCP
2073 * connections this may not actually reflect the latest timer.
2075 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2076 result
= fctx_stopidletimer(fctx
);
2077 if (result
!= ISC_R_SUCCESS
)
2078 fctx_done(fctx
, result
, __LINE__
);
2080 fctx_try(fctx
, ISC_TRUE
);
2085 fctx_finddone(isc_task_t
*task
, isc_event_t
*event
) {
2087 dns_adbfind_t
*find
;
2088 dns_resolver_t
*res
;
2089 isc_boolean_t want_try
= ISC_FALSE
;
2090 isc_boolean_t want_done
= ISC_FALSE
;
2091 isc_boolean_t bucket_empty
= ISC_FALSE
;
2092 unsigned int bucketnum
;
2094 find
= event
->ev_sender
;
2095 fctx
= event
->ev_arg
;
2096 REQUIRE(VALID_FCTX(fctx
));
2101 FCTXTRACE("finddone");
2103 INSIST(fctx
->pending
> 0);
2106 if (ADDRWAIT(fctx
)) {
2108 * The fetch is waiting for a name to be found.
2110 INSIST(!SHUTTINGDOWN(fctx
));
2111 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2112 if (event
->ev_type
== DNS_EVENT_ADBMOREADDRESSES
)
2113 want_try
= ISC_TRUE
;
2116 if (fctx
->pending
== 0) {
2118 * We've got nothing else to wait for and don't
2119 * know the answer. There's nothing to do but
2122 want_done
= ISC_TRUE
;
2125 } else if (SHUTTINGDOWN(fctx
) && fctx
->pending
== 0 &&
2126 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
)) {
2127 bucketnum
= fctx
->bucketnum
;
2128 LOCK(&res
->buckets
[bucketnum
].lock
);
2130 * Note that we had to wait until we had the lock before
2131 * looking at fctx->references.
2133 if (fctx
->references
== 0)
2134 bucket_empty
= fctx_destroy(fctx
);
2135 UNLOCK(&res
->buckets
[bucketnum
].lock
);
2138 isc_event_free(&event
);
2139 dns_adb_destroyfind(&find
);
2142 fctx_try(fctx
, ISC_TRUE
);
2144 fctx_done(fctx
, ISC_R_FAILURE
, __LINE__
);
2145 else if (bucket_empty
)
2150 static inline isc_boolean_t
2151 bad_server(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
2154 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
2156 sa
= ISC_LIST_NEXT(sa
, link
)) {
2157 if (isc_sockaddr_equal(sa
, address
))
2164 static inline isc_boolean_t
2165 mark_bad(fetchctx_t
*fctx
) {
2166 dns_adbfind_t
*curr
;
2167 dns_adbaddrinfo_t
*addrinfo
;
2168 isc_boolean_t all_bad
= ISC_TRUE
;
2171 * Mark all known bad servers, so we don't try to talk to them
2176 * Mark any bad nameservers.
2178 for (curr
= ISC_LIST_HEAD(fctx
->finds
);
2180 curr
= ISC_LIST_NEXT(curr
, publink
)) {
2181 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
2183 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2184 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2185 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2187 all_bad
= ISC_FALSE
;
2192 * Mark any bad forwarders.
2194 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2196 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2197 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2198 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2200 all_bad
= ISC_FALSE
;
2204 * Mark any bad alternates.
2206 for (curr
= ISC_LIST_HEAD(fctx
->altfinds
);
2208 curr
= ISC_LIST_NEXT(curr
, publink
)) {
2209 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
2211 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2212 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2213 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2215 all_bad
= ISC_FALSE
;
2219 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
2221 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2222 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2223 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2225 all_bad
= ISC_FALSE
;
2232 add_bad(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, isc_result_t reason
,
2233 badnstype_t badtype
)
2235 char namebuf
[DNS_NAME_FORMATSIZE
];
2236 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2242 const char *spc
= "";
2243 isc_sockaddr_t
*address
= &addrinfo
->sockaddr
;
2245 if (reason
== DNS_R_LAME
)
2249 case badns_unreachable
:
2252 case badns_response
:
2255 case badns_validation
:
2256 break; /* counted as 'valfail' */
2260 if (bad_server(fctx
, address
)) {
2262 * We already know this server is bad.
2267 FCTXTRACE("add_bad");
2269 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
2274 ISC_LIST_INITANDAPPEND(fctx
->bad
, sa
, link
);
2276 if (reason
== DNS_R_LAME
) /* already logged */
2279 if (reason
== DNS_R_UNEXPECTEDRCODE
&&
2280 fctx
->rmessage
->rcode
== dns_rcode_servfail
&&
2281 ISFORWARDER(addrinfo
))
2284 if (reason
== DNS_R_UNEXPECTEDRCODE
) {
2285 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
2286 dns_rcode_totext(fctx
->rmessage
->rcode
, &b
);
2287 code
[isc_buffer_usedlength(&b
)] = '\0';
2289 } else if (reason
== DNS_R_UNEXPECTEDOPCODE
) {
2290 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
2291 dns_opcode_totext((dns_opcode_t
)fctx
->rmessage
->opcode
, &b
);
2292 code
[isc_buffer_usedlength(&b
)] = '\0';
2297 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
2298 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
2299 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
, sizeof(classbuf
));
2300 isc_sockaddr_format(address
, addrbuf
, sizeof(addrbuf
));
2301 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
2302 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
2303 "error (%s%s%s) resolving '%s/%s/%s': %s",
2304 dns_result_totext(reason
), spc
, code
,
2305 namebuf
, typebuf
, classbuf
, addrbuf
);
2309 * Return 'bits' bits of random entropy from fctx->rand_buf,
2310 * refreshing it by calling isc_random_get() whenever the requested
2311 * number of bits is greater than the number in the buffer.
2313 static inline isc_uint32_t
2314 random_bits(fetchctx_t
*fctx
, isc_uint32_t bits
) {
2315 isc_uint32_t ret
= 0;
2317 REQUIRE(VALID_FCTX(fctx
));
2318 REQUIRE(bits
<= 32);
2322 if (bits
>= fctx
->rand_bits
) {
2323 /* if rand_bits == 0, this is unnecessary but harmless */
2324 bits
-= fctx
->rand_bits
;
2325 ret
= fctx
->rand_buf
<< bits
;
2327 /* refresh random buffer now */
2328 isc_random_get(&fctx
->rand_buf
);
2329 fctx
->rand_bits
= sizeof(fctx
->rand_buf
) * CHAR_BIT
;
2333 isc_uint32_t mask
= 0xffffffff;
2335 mask
= (1 << bits
) - 1;
2338 ret
|= fctx
->rand_buf
& mask
;
2339 fctx
->rand_buf
>>= bits
;
2340 fctx
->rand_bits
-= bits
;
2347 * Add some random jitter to a server's RTT value so that the
2348 * order of queries will be unpredictable.
2350 * RTT values of servers which have been tried are fuzzed by 128 ms.
2351 * Servers that haven't been tried yet have their RTT set to a random
2352 * value between 0 ms and 7 ms; they should get to go first, but in
2353 * unpredictable order.
2356 randomize_srtt(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*ai
) {
2358 ai
->srtt
>>= 10; /* convert to milliseconds, near enough */
2359 ai
->srtt
|= (ai
->srtt
& 0x80) | random_bits(fctx
, 7);
2360 ai
->srtt
<<= 10; /* now back to microseconds */
2362 ai
->srtt
= random_bits(fctx
, 3) << 10;
2366 * Sort addrinfo list by RTT (with random jitter)
2369 sort_adbfind(fetchctx_t
*fctx
, dns_adbfind_t
*find
) {
2370 dns_adbaddrinfo_t
*best
, *curr
;
2371 dns_adbaddrinfolist_t sorted
;
2373 /* Add jitter to SRTT values */
2374 curr
= ISC_LIST_HEAD(find
->list
);
2375 while (curr
!= NULL
) {
2376 randomize_srtt(fctx
, curr
);
2377 curr
= ISC_LIST_NEXT(curr
, publink
);
2380 /* Lame N^2 bubble sort. */
2381 ISC_LIST_INIT(sorted
);
2382 while (!ISC_LIST_EMPTY(find
->list
)) {
2383 best
= ISC_LIST_HEAD(find
->list
);
2384 curr
= ISC_LIST_NEXT(best
, publink
);
2385 while (curr
!= NULL
) {
2386 if (curr
->srtt
< best
->srtt
)
2388 curr
= ISC_LIST_NEXT(curr
, publink
);
2390 ISC_LIST_UNLINK(find
->list
, best
, publink
);
2391 ISC_LIST_APPEND(sorted
, best
, publink
);
2393 find
->list
= sorted
;
2397 * Sort a list of finds by server RTT (with random jitter)
2400 sort_finds(fetchctx_t
*fctx
, dns_adbfindlist_t
*findlist
) {
2401 dns_adbfind_t
*best
, *curr
;
2402 dns_adbfindlist_t sorted
;
2403 dns_adbaddrinfo_t
*addrinfo
, *bestaddrinfo
;
2405 /* Sort each find's addrinfo list by SRTT (after adding jitter) */
2406 for (curr
= ISC_LIST_HEAD(*findlist
);
2408 curr
= ISC_LIST_NEXT(curr
, publink
))
2409 sort_adbfind(fctx
, curr
);
2411 /* Lame N^2 bubble sort. */
2412 ISC_LIST_INIT(sorted
);
2413 while (!ISC_LIST_EMPTY(*findlist
)) {
2414 best
= ISC_LIST_HEAD(*findlist
);
2415 bestaddrinfo
= ISC_LIST_HEAD(best
->list
);
2416 INSIST(bestaddrinfo
!= NULL
);
2417 curr
= ISC_LIST_NEXT(best
, publink
);
2418 while (curr
!= NULL
) {
2419 addrinfo
= ISC_LIST_HEAD(curr
->list
);
2420 INSIST(addrinfo
!= NULL
);
2421 if (addrinfo
->srtt
< bestaddrinfo
->srtt
) {
2423 bestaddrinfo
= addrinfo
;
2425 curr
= ISC_LIST_NEXT(curr
, publink
);
2427 ISC_LIST_UNLINK(*findlist
, best
, publink
);
2428 ISC_LIST_APPEND(sorted
, best
, publink
);
2434 findname(fetchctx_t
*fctx
, dns_name_t
*name
, in_port_t port
,
2435 unsigned int options
, unsigned int flags
, isc_stdtime_t now
,
2436 isc_boolean_t
*need_alternate
)
2438 dns_adbaddrinfo_t
*ai
;
2439 dns_adbfind_t
*find
;
2440 dns_resolver_t
*res
;
2441 isc_boolean_t unshared
;
2442 isc_result_t result
;
2445 unshared
= ISC_TF((fctx
->options
| DNS_FETCHOPT_UNSHARED
) != 0);
2447 * If this name is a subdomain of the query domain, tell
2448 * the ADB to start looking using zone/hint data. This keeps us
2449 * from getting stuck if the nameserver is beneath the zone cut
2450 * and we don't know its address (e.g. because the A record has
2453 if (dns_name_issubdomain(name
, &fctx
->domain
))
2454 options
|= DNS_ADBFIND_STARTATZONE
;
2455 options
|= DNS_ADBFIND_GLUEOK
;
2456 options
|= DNS_ADBFIND_HINTOK
;
2459 * See what we know about this address.
2462 result
= dns_adb_createfind(fctx
->adb
,
2463 res
->buckets
[fctx
->bucketnum
].task
,
2464 fctx_finddone
, fctx
, name
,
2465 &fctx
->name
, fctx
->type
,
2467 res
->view
->dstport
, &find
);
2468 if (result
!= ISC_R_SUCCESS
) {
2469 if (result
== DNS_R_ALIAS
) {
2471 * XXXRTH Follow the CNAME/DNAME chain?
2473 dns_adb_destroyfind(&find
);
2476 } else if (!ISC_LIST_EMPTY(find
->list
)) {
2478 * We have at least some of the addresses for the
2481 INSIST((find
->options
& DNS_ADBFIND_WANTEVENT
) == 0);
2482 if (flags
!= 0 || port
!= 0) {
2483 for (ai
= ISC_LIST_HEAD(find
->list
);
2485 ai
= ISC_LIST_NEXT(ai
, publink
)) {
2488 isc_sockaddr_setport(&ai
->sockaddr
,
2492 if ((flags
& FCTX_ADDRINFO_FORWARDER
) != 0)
2493 ISC_LIST_APPEND(fctx
->altfinds
, find
, publink
);
2495 ISC_LIST_APPEND(fctx
->finds
, find
, publink
);
2498 * We don't know any of the addresses for this
2501 if ((find
->options
& DNS_ADBFIND_WANTEVENT
) != 0) {
2503 * We're looking for them and will get an
2504 * event about it later.
2510 if (need_alternate
!= NULL
&&
2511 !*need_alternate
&& unshared
&&
2512 ((res
->dispatchv4
== NULL
&&
2513 find
->result_v6
!= DNS_R_NXDOMAIN
) ||
2514 (res
->dispatchv6
== NULL
&&
2515 find
->result_v4
!= DNS_R_NXDOMAIN
)))
2516 *need_alternate
= ISC_TRUE
;
2518 if ((find
->options
& DNS_ADBFIND_LAMEPRUNED
) != 0)
2519 fctx
->lamecount
++; /* cached lame server */
2521 fctx
->adberr
++; /* unreachable server, etc. */
2524 * If we know there are no addresses for
2525 * the family we are using then try to add
2526 * an alternative server.
2528 if (need_alternate
!= NULL
&& !*need_alternate
&&
2529 ((res
->dispatchv4
== NULL
&&
2530 find
->result_v6
== DNS_R_NXRRSET
) ||
2531 (res
->dispatchv6
== NULL
&&
2532 find
->result_v4
== DNS_R_NXRRSET
)))
2533 *need_alternate
= ISC_TRUE
;
2534 dns_adb_destroyfind(&find
);
2539 static isc_boolean_t
2540 isstrictsubdomain(dns_name_t
*name1
, dns_name_t
*name2
) {
2542 unsigned int nlabels
;
2543 dns_namereln_t namereln
;
2545 namereln
= dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
2546 return (ISC_TF(namereln
== dns_namereln_subdomain
));
2550 fctx_getaddresses(fetchctx_t
*fctx
) {
2551 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2552 isc_result_t result
;
2553 dns_resolver_t
*res
;
2555 unsigned int stdoptions
;
2557 dns_adbaddrinfo_t
*ai
;
2558 isc_boolean_t all_bad
;
2560 isc_boolean_t need_alternate
= ISC_FALSE
;
2562 FCTXTRACE("getaddresses");
2565 * Don't pound on remote servers. (Failsafe!)
2568 if (fctx
->restarts
> 10) {
2569 FCTXTRACE("too many restarts");
2570 return (DNS_R_SERVFAIL
);
2574 stdoptions
= 0; /* Keep compiler happy. */
2580 INSIST(ISC_LIST_EMPTY(fctx
->forwaddrs
));
2581 INSIST(ISC_LIST_EMPTY(fctx
->altaddrs
));
2584 * If this fctx has forwarders, use them; otherwise use any
2585 * selective forwarders specified in the view; otherwise use the
2586 * resolver's forwarders (if any).
2588 sa
= ISC_LIST_HEAD(fctx
->forwarders
);
2590 dns_forwarders_t
*forwarders
= NULL
;
2591 dns_name_t
*name
= &fctx
->name
;
2593 unsigned int labels
;
2594 dns_fixedname_t fixed
;
2598 * DS records are found in the parent server.
2599 * Strip label to get the correct forwarder (if any).
2601 if (dns_rdatatype_atparent(fctx
->type
) &&
2602 dns_name_countlabels(name
) > 1) {
2603 dns_name_init(&suffix
, NULL
);
2604 labels
= dns_name_countlabels(name
);
2605 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
2609 dns_fixedname_init(&fixed
);
2610 domain
= dns_fixedname_name(&fixed
);
2611 result
= dns_fwdtable_find2(fctx
->res
->view
->fwdtable
, name
,
2612 domain
, &forwarders
);
2613 if (result
== ISC_R_SUCCESS
) {
2614 sa
= ISC_LIST_HEAD(forwarders
->addrs
);
2615 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
2616 if (fctx
->fwdpolicy
== dns_fwdpolicy_only
&&
2617 isstrictsubdomain(domain
, &fctx
->domain
)) {
2620 mctx
= res
->buckets
[fctx
->bucketnum
].mctx
;
2621 dns_name_free(&fctx
->domain
, mctx
);
2622 dns_name_init(&fctx
->domain
, NULL
);
2623 result
= dns_name_dup(domain
, mctx
,
2625 if (result
!= ISC_R_SUCCESS
)
2631 while (sa
!= NULL
) {
2632 if ((isc_sockaddr_pf(sa
) == AF_INET
&&
2633 fctx
->res
->dispatchv4
== NULL
) ||
2634 (isc_sockaddr_pf(sa
) == AF_INET6
&&
2635 fctx
->res
->dispatchv6
== NULL
)) {
2636 sa
= ISC_LIST_NEXT(sa
, link
);
2640 result
= dns_adb_findaddrinfo(fctx
->adb
,
2641 sa
, &ai
, 0); /* XXXMLG */
2642 if (result
== ISC_R_SUCCESS
) {
2643 dns_adbaddrinfo_t
*cur
;
2644 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
2645 cur
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2646 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
2647 cur
= ISC_LIST_NEXT(cur
, publink
);
2649 ISC_LIST_INSERTBEFORE(fctx
->forwaddrs
, cur
,
2652 ISC_LIST_APPEND(fctx
->forwaddrs
, ai
, publink
);
2654 sa
= ISC_LIST_NEXT(sa
, link
);
2658 * If the forwarding policy is "only", we don't need the addresses
2659 * of the nameservers.
2661 if (fctx
->fwdpolicy
== dns_fwdpolicy_only
)
2665 * Normal nameservers.
2668 stdoptions
= DNS_ADBFIND_WANTEVENT
| DNS_ADBFIND_EMPTYEVENT
;
2669 if (fctx
->restarts
== 1) {
2671 * To avoid sending out a flood of queries likely to
2672 * result in NXRRSET, we suppress fetches for address
2673 * families we don't have the first time through,
2674 * provided that we have addresses in some family we
2677 * We don't want to set this option all the time, since
2678 * if fctx->restarts > 1, we've clearly been having trouble
2679 * with the addresses we had, so getting more could help.
2681 stdoptions
|= DNS_ADBFIND_AVOIDFETCHES
;
2683 if (res
->dispatchv4
!= NULL
)
2684 stdoptions
|= DNS_ADBFIND_INET
;
2685 if (res
->dispatchv6
!= NULL
)
2686 stdoptions
|= DNS_ADBFIND_INET6
;
2687 isc_stdtime_get(&now
);
2689 INSIST(ISC_LIST_EMPTY(fctx
->finds
));
2690 INSIST(ISC_LIST_EMPTY(fctx
->altfinds
));
2692 for (result
= dns_rdataset_first(&fctx
->nameservers
);
2693 result
== ISC_R_SUCCESS
;
2694 result
= dns_rdataset_next(&fctx
->nameservers
))
2696 dns_rdataset_current(&fctx
->nameservers
, &rdata
);
2698 * Extract the name from the NS record.
2700 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
2701 if (result
!= ISC_R_SUCCESS
)
2704 findname(fctx
, &ns
.name
, 0, stdoptions
, 0, now
,
2706 dns_rdata_reset(&rdata
);
2707 dns_rdata_freestruct(&ns
);
2709 if (result
!= ISC_R_NOMORE
)
2713 * Do we need to use 6 to 4?
2715 if (need_alternate
) {
2718 family
= (res
->dispatchv6
!= NULL
) ? AF_INET6
: AF_INET
;
2719 for (a
= ISC_LIST_HEAD(fctx
->res
->alternates
);
2721 a
= ISC_LIST_NEXT(a
, link
)) {
2722 if (!a
->isaddress
) {
2723 findname(fctx
, &a
->_u
._n
.name
, a
->_u
._n
.port
,
2724 stdoptions
, FCTX_ADDRINFO_FORWARDER
,
2728 if (isc_sockaddr_pf(&a
->_u
.addr
) != family
)
2731 result
= dns_adb_findaddrinfo(fctx
->adb
, &a
->_u
.addr
,
2733 if (result
== ISC_R_SUCCESS
) {
2734 dns_adbaddrinfo_t
*cur
;
2735 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
2736 cur
= ISC_LIST_HEAD(fctx
->altaddrs
);
2737 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
2738 cur
= ISC_LIST_NEXT(cur
, publink
);
2740 ISC_LIST_INSERTBEFORE(fctx
->altaddrs
,
2743 ISC_LIST_APPEND(fctx
->altaddrs
, ai
,
2751 * Mark all known bad servers.
2753 all_bad
= mark_bad(fctx
);
2760 * We've got no addresses.
2762 if (fctx
->pending
> 0) {
2764 * We're fetching the addresses, but don't have any
2765 * yet. Tell the caller to wait for an answer.
2767 result
= DNS_R_WAIT
;
2770 * We've lost completely. We don't know any
2771 * addresses, and the ADB has told us it can't get
2774 FCTXTRACE("no addresses");
2775 result
= ISC_R_FAILURE
;
2779 * We've found some addresses. We might still be looking
2780 * for more addresses.
2782 sort_finds(fctx
, &fctx
->finds
);
2783 sort_finds(fctx
, &fctx
->altfinds
);
2784 result
= ISC_R_SUCCESS
;
2791 possibly_mark(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addr
)
2794 char buf
[ISC_NETADDR_FORMATSIZE
];
2796 isc_boolean_t aborted
= ISC_FALSE
;
2797 isc_boolean_t bogus
;
2798 dns_acl_t
*blackhole
;
2799 isc_netaddr_t ipaddr
;
2800 dns_peer_t
*peer
= NULL
;
2801 dns_resolver_t
*res
;
2802 const char *msg
= NULL
;
2804 sa
= &addr
->sockaddr
;
2807 isc_netaddr_fromsockaddr(&ipaddr
, sa
);
2808 blackhole
= dns_dispatchmgr_getblackhole(res
->dispatchmgr
);
2809 (void) dns_peerlist_peerbyaddr(res
->view
->peers
, &ipaddr
, &peer
);
2811 if (blackhole
!= NULL
) {
2814 if (dns_acl_match(&ipaddr
, NULL
, blackhole
,
2816 &match
, NULL
) == ISC_R_SUCCESS
&&
2822 dns_peer_getbogus(peer
, &bogus
) == ISC_R_SUCCESS
&&
2827 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2828 msg
= "ignoring blackholed / bogus server: ";
2829 } else if (isc_sockaddr_ismulticast(sa
)) {
2830 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2831 msg
= "ignoring multicast address: ";
2832 } else if (isc_sockaddr_isexperimental(sa
)) {
2833 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2834 msg
= "ignoring experimental address: ";
2835 } else if (sa
->type
.sa
.sa_family
!= AF_INET6
) {
2837 } else if (IN6_IS_ADDR_V4MAPPED(&sa
->type
.sin6
.sin6_addr
)) {
2838 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2839 msg
= "ignoring IPv6 mapped IPV4 address: ";
2840 } else if (IN6_IS_ADDR_V4COMPAT(&sa
->type
.sin6
.sin6_addr
)) {
2841 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2842 msg
= "ignoring IPv6 compatibility IPV4 address: ";
2846 if (!isc_log_wouldlog(dns_lctx
, ISC_LOG_DEBUG(3)))
2849 isc_netaddr_fromsockaddr(&na
, sa
);
2850 isc_netaddr_format(&na
, buf
, sizeof(buf
));
2851 FCTXTRACE2(msg
, buf
);
2854 static inline dns_adbaddrinfo_t
*
2855 fctx_nextaddress(fetchctx_t
*fctx
) {
2856 dns_adbfind_t
*find
, *start
;
2857 dns_adbaddrinfo_t
*addrinfo
;
2858 dns_adbaddrinfo_t
*faddrinfo
;
2861 * Return the next untried address, if any.
2865 * Find the first unmarked forwarder (if any).
2867 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2869 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2870 if (!UNMARKED(addrinfo
))
2872 possibly_mark(fctx
, addrinfo
);
2873 if (UNMARKED(addrinfo
)) {
2874 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2881 * No forwarders. Move to the next find.
2884 fctx
->attributes
|= FCTX_ATTR_TRIEDFIND
;
2888 find
= ISC_LIST_HEAD(fctx
->finds
);
2890 find
= ISC_LIST_NEXT(find
, publink
);
2892 find
= ISC_LIST_HEAD(fctx
->finds
);
2896 * Find the first unmarked addrinfo.
2902 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2904 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2905 if (!UNMARKED(addrinfo
))
2907 possibly_mark(fctx
, addrinfo
);
2908 if (UNMARKED(addrinfo
)) {
2909 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2913 if (addrinfo
!= NULL
)
2915 find
= ISC_LIST_NEXT(find
, publink
);
2917 find
= ISC_LIST_HEAD(fctx
->finds
);
2918 } while (find
!= start
);
2922 if (addrinfo
!= NULL
)
2926 * No nameservers left. Try alternates.
2929 fctx
->attributes
|= FCTX_ATTR_TRIEDALT
;
2931 find
= fctx
->altfind
;
2933 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2935 find
= ISC_LIST_NEXT(find
, publink
);
2937 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2941 * Find the first unmarked addrinfo.
2947 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2949 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2950 if (!UNMARKED(addrinfo
))
2952 possibly_mark(fctx
, addrinfo
);
2953 if (UNMARKED(addrinfo
)) {
2954 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2958 if (addrinfo
!= NULL
)
2960 find
= ISC_LIST_NEXT(find
, publink
);
2962 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2963 } while (find
!= start
);
2966 faddrinfo
= addrinfo
;
2969 * See if we have a better alternate server by address.
2972 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
2974 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2975 if (!UNMARKED(addrinfo
))
2977 possibly_mark(fctx
, addrinfo
);
2978 if (UNMARKED(addrinfo
) &&
2979 (faddrinfo
== NULL
||
2980 addrinfo
->srtt
< faddrinfo
->srtt
)) {
2981 if (faddrinfo
!= NULL
)
2982 faddrinfo
->flags
&= ~FCTX_ADDRINFO_MARK
;
2983 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2988 if (addrinfo
== NULL
) {
2989 addrinfo
= faddrinfo
;
2990 fctx
->altfind
= find
;
2997 fctx_try(fetchctx_t
*fctx
, isc_boolean_t retrying
) {
2998 isc_result_t result
;
2999 dns_adbaddrinfo_t
*addrinfo
;
3003 REQUIRE(!ADDRWAIT(fctx
));
3005 addrinfo
= fctx_nextaddress(fctx
);
3006 if (addrinfo
== NULL
) {
3008 * We have no more addresses. Start over.
3010 fctx_cancelqueries(fctx
, ISC_TRUE
);
3011 fctx_cleanupfinds(fctx
);
3012 fctx_cleanupaltfinds(fctx
);
3013 fctx_cleanupforwaddrs(fctx
);
3014 fctx_cleanupaltaddrs(fctx
);
3015 result
= fctx_getaddresses(fctx
);
3016 if (result
== DNS_R_WAIT
) {
3018 * Sleep waiting for addresses.
3020 FCTXTRACE("addrwait");
3021 fctx
->attributes
|= FCTX_ATTR_ADDRWAIT
;
3023 } else if (result
!= ISC_R_SUCCESS
) {
3025 * Something bad happened.
3027 fctx_done(fctx
, result
, __LINE__
);
3031 addrinfo
= fctx_nextaddress(fctx
);
3033 * While we may have addresses from the ADB, they
3034 * might be bad ones. In this case, return SERVFAIL.
3036 if (addrinfo
== NULL
) {
3037 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
3042 result
= fctx_query(fctx
, addrinfo
, fctx
->options
);
3043 if (result
!= ISC_R_SUCCESS
)
3044 fctx_done(fctx
, result
, __LINE__
);
3046 inc_stats(fctx
->res
, dns_resstatscounter_retry
);
3049 static isc_boolean_t
3050 fctx_destroy(fetchctx_t
*fctx
) {
3051 dns_resolver_t
*res
;
3052 unsigned int bucketnum
;
3053 isc_sockaddr_t
*sa
, *next_sa
;
3056 * Caller must be holding the bucket lock.
3059 REQUIRE(VALID_FCTX(fctx
));
3060 REQUIRE(fctx
->state
== fetchstate_done
||
3061 fctx
->state
== fetchstate_init
);
3062 REQUIRE(ISC_LIST_EMPTY(fctx
->events
));
3063 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
3064 REQUIRE(ISC_LIST_EMPTY(fctx
->finds
));
3065 REQUIRE(ISC_LIST_EMPTY(fctx
->altfinds
));
3066 REQUIRE(fctx
->pending
== 0);
3067 REQUIRE(fctx
->references
== 0);
3068 REQUIRE(ISC_LIST_EMPTY(fctx
->validators
));
3070 FCTXTRACE("destroy");
3073 bucketnum
= fctx
->bucketnum
;
3075 ISC_LIST_UNLINK(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
3080 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
3083 next_sa
= ISC_LIST_NEXT(sa
, link
);
3084 ISC_LIST_UNLINK(fctx
->bad
, sa
, link
);
3085 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3088 for (sa
= ISC_LIST_HEAD(fctx
->edns
);
3091 next_sa
= ISC_LIST_NEXT(sa
, link
);
3092 ISC_LIST_UNLINK(fctx
->edns
, sa
, link
);
3093 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3096 for (sa
= ISC_LIST_HEAD(fctx
->edns512
);
3099 next_sa
= ISC_LIST_NEXT(sa
, link
);
3100 ISC_LIST_UNLINK(fctx
->edns512
, sa
, link
);
3101 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3104 isc_timer_detach(&fctx
->timer
);
3105 dns_message_destroy(&fctx
->rmessage
);
3106 dns_message_destroy(&fctx
->qmessage
);
3107 if (dns_name_countlabels(&fctx
->domain
) > 0)
3108 dns_name_free(&fctx
->domain
, res
->buckets
[bucketnum
].mctx
);
3109 if (dns_rdataset_isassociated(&fctx
->nameservers
))
3110 dns_rdataset_disassociate(&fctx
->nameservers
);
3111 dns_name_free(&fctx
->name
, res
->buckets
[bucketnum
].mctx
);
3112 dns_db_detach(&fctx
->cache
);
3113 dns_adb_detach(&fctx
->adb
);
3114 isc_mem_free(res
->buckets
[bucketnum
].mctx
, fctx
->info
);
3115 isc_mem_put(res
->buckets
[bucketnum
].mctx
, fctx
, sizeof(*fctx
));
3119 UNLOCK(&res
->nlock
);
3121 if (res
->buckets
[bucketnum
].exiting
&&
3122 ISC_LIST_EMPTY(res
->buckets
[bucketnum
].fctxs
))
3129 * Fetch event handlers.
3133 fctx_timeout(isc_task_t
*task
, isc_event_t
*event
) {
3134 fetchctx_t
*fctx
= event
->ev_arg
;
3135 isc_timerevent_t
*tevent
= (isc_timerevent_t
*)event
;
3138 REQUIRE(VALID_FCTX(fctx
));
3142 FCTXTRACE("timeout");
3144 inc_stats(fctx
->res
, dns_resstatscounter_querytimeout
);
3146 if (event
->ev_type
== ISC_TIMEREVENT_LIFE
) {
3147 fctx
->reason
= NULL
;
3148 fctx_done(fctx
, ISC_R_TIMEDOUT
, __LINE__
);
3150 isc_result_t result
;
3153 fctx
->timeout
= ISC_TRUE
;
3155 * We could cancel the running queries here, or we could let
3156 * them keep going. Since we normally use separate sockets for
3157 * different queries, we adopt the former approach to reduce
3158 * the number of open sockets: cancel the oldest query if it
3159 * expired after the query had started (this is usually the
3160 * case but is not always so, depending on the task schedule
3163 query
= ISC_LIST_HEAD(fctx
->queries
);
3164 if (query
!= NULL
&&
3165 isc_time_compare(&tevent
->due
, &query
->start
) >= 0) {
3166 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
3168 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
3170 * Our timer has triggered. Reestablish the fctx lifetime
3173 result
= fctx_starttimer(fctx
);
3174 if (result
!= ISC_R_SUCCESS
)
3175 fctx_done(fctx
, result
, __LINE__
);
3180 fctx_try(fctx
, ISC_TRUE
);
3183 isc_event_free(&event
);
3187 fctx_shutdown(fetchctx_t
*fctx
) {
3188 isc_event_t
*cevent
;
3191 * Start the shutdown process for fctx, if it isn't already underway.
3194 FCTXTRACE("shutdown");
3197 * The caller must be holding the appropriate bucket lock.
3200 if (fctx
->want_shutdown
)
3203 fctx
->want_shutdown
= ISC_TRUE
;
3206 * Unless we're still initializing (in which case the
3207 * control event is still outstanding), we need to post
3208 * the control event to tell the fetch we want it to
3211 if (fctx
->state
!= fetchstate_init
) {
3212 cevent
= &fctx
->control_event
;
3213 isc_task_send(fctx
->res
->buckets
[fctx
->bucketnum
].task
,
3219 fctx_doshutdown(isc_task_t
*task
, isc_event_t
*event
) {
3220 fetchctx_t
*fctx
= event
->ev_arg
;
3221 isc_boolean_t bucket_empty
= ISC_FALSE
;
3222 dns_resolver_t
*res
;
3223 unsigned int bucketnum
;
3224 dns_validator_t
*validator
;
3226 REQUIRE(VALID_FCTX(fctx
));
3231 bucketnum
= fctx
->bucketnum
;
3233 FCTXTRACE("doshutdown");
3236 * An fctx that is shutting down is no longer in ADDRWAIT mode.
3238 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
3241 * Cancel all pending validators. Note that this must be done
3242 * without the bucket lock held, since that could cause deadlock.
3244 validator
= ISC_LIST_HEAD(fctx
->validators
);
3245 while (validator
!= NULL
) {
3246 dns_validator_cancel(validator
);
3247 validator
= ISC_LIST_NEXT(validator
, link
);
3250 if (fctx
->nsfetch
!= NULL
)
3251 dns_resolver_cancelfetch(fctx
->nsfetch
);
3254 * Shut down anything that is still running on behalf of this
3255 * fetch. To avoid deadlock with the ADB, we must do this
3256 * before we lock the bucket lock.
3258 fctx_stopeverything(fctx
, ISC_FALSE
);
3260 LOCK(&res
->buckets
[bucketnum
].lock
);
3262 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
3264 INSIST(fctx
->state
== fetchstate_active
||
3265 fctx
->state
== fetchstate_done
);
3266 INSIST(fctx
->want_shutdown
);
3268 if (fctx
->state
!= fetchstate_done
) {
3269 fctx
->state
= fetchstate_done
;
3270 fctx_sendevents(fctx
, ISC_R_CANCELED
, __LINE__
);
3273 if (fctx
->references
== 0 && fctx
->pending
== 0 &&
3274 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
))
3275 bucket_empty
= fctx_destroy(fctx
);
3277 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3284 fctx_start(isc_task_t
*task
, isc_event_t
*event
) {
3285 fetchctx_t
*fctx
= event
->ev_arg
;
3286 isc_boolean_t done
= ISC_FALSE
, bucket_empty
= ISC_FALSE
;
3287 dns_resolver_t
*res
;
3288 unsigned int bucketnum
;
3290 REQUIRE(VALID_FCTX(fctx
));
3295 bucketnum
= fctx
->bucketnum
;
3299 LOCK(&res
->buckets
[bucketnum
].lock
);
3301 INSIST(fctx
->state
== fetchstate_init
);
3302 if (fctx
->want_shutdown
) {
3304 * We haven't started this fctx yet, and we've been requested
3307 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
3308 fctx
->state
= fetchstate_done
;
3309 fctx_sendevents(fctx
, ISC_R_CANCELED
, __LINE__
);
3311 * Since we haven't started, we INSIST that we have no
3312 * pending ADB finds and no pending validations.
3314 INSIST(fctx
->pending
== 0);
3315 INSIST(fctx
->nqueries
== 0);
3316 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
3317 if (fctx
->references
== 0) {
3319 * It's now safe to destroy this fctx.
3321 bucket_empty
= fctx_destroy(fctx
);
3326 * Normal fctx startup.
3328 fctx
->state
= fetchstate_active
;
3330 * Reset the control event for later use in shutting down
3333 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
3334 DNS_EVENT_FETCHCONTROL
, fctx_doshutdown
, fctx
,
3338 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3341 isc_result_t result
;
3344 * All is well. Start working on the fetch.
3346 result
= fctx_starttimer(fctx
);
3347 if (result
!= ISC_R_SUCCESS
)
3348 fctx_done(fctx
, result
, __LINE__
);
3350 fctx_try(fctx
, ISC_FALSE
);
3351 } else if (bucket_empty
)
3356 * Fetch Creation, Joining, and Cancelation.
3359 static inline isc_result_t
3360 fctx_join(fetchctx_t
*fctx
, isc_task_t
*task
, isc_sockaddr_t
*client
,
3361 dns_messageid_t id
, isc_taskaction_t action
, void *arg
,
3362 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
3366 dns_fetchevent_t
*event
;
3371 * We store the task we're going to send this event to in the
3372 * sender field. We'll make the fetch the sender when we actually
3376 isc_task_attach(task
, &clone
);
3377 event
= (dns_fetchevent_t
*)
3378 isc_event_allocate(fctx
->res
->mctx
, clone
, DNS_EVENT_FETCHDONE
,
3379 action
, arg
, sizeof(*event
));
3380 if (event
== NULL
) {
3381 isc_task_detach(&clone
);
3382 return (ISC_R_NOMEMORY
);
3384 event
->result
= DNS_R_SERVFAIL
;
3385 event
->qtype
= fctx
->type
;
3388 event
->rdataset
= rdataset
;
3389 event
->sigrdataset
= sigrdataset
;
3390 event
->fetch
= fetch
;
3391 event
->client
= client
;
3393 dns_fixedname_init(&event
->foundname
);
3396 * Make sure that we can store the sigrdataset in the
3397 * first event if it is needed by any of the events.
3399 if (event
->sigrdataset
!= NULL
)
3400 ISC_LIST_PREPEND(fctx
->events
, event
, ev_link
);
3402 ISC_LIST_APPEND(fctx
->events
, event
, ev_link
);
3404 fctx
->client
= client
;
3406 fetch
->magic
= DNS_FETCH_MAGIC
;
3407 fetch
->private = fctx
;
3409 return (ISC_R_SUCCESS
);
3413 fctx_create(dns_resolver_t
*res
, dns_name_t
*name
, dns_rdatatype_t type
,
3414 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
3415 unsigned int options
, unsigned int bucketnum
, fetchctx_t
**fctxp
)
3418 isc_result_t result
;
3419 isc_result_t iresult
;
3420 isc_interval_t interval
;
3421 dns_fixedname_t fixed
;
3422 unsigned int findoptions
= 0;
3423 char buf
[DNS_NAME_FORMATSIZE
+ DNS_RDATATYPE_FORMATSIZE
];
3424 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3428 * Caller must be holding the lock for bucket number 'bucketnum'.
3430 REQUIRE(fctxp
!= NULL
&& *fctxp
== NULL
);
3432 fctx
= isc_mem_get(res
->buckets
[bucketnum
].mctx
, sizeof(*fctx
));
3434 return (ISC_R_NOMEMORY
);
3435 dns_name_format(name
, buf
, sizeof(buf
));
3436 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
3437 strcat(buf
, "/"); /* checked */
3438 strcat(buf
, typebuf
); /* checked */
3439 fctx
->info
= isc_mem_strdup(res
->buckets
[bucketnum
].mctx
, buf
);
3440 if (fctx
->info
== NULL
) {
3441 result
= ISC_R_NOMEMORY
;
3444 FCTXTRACE("create");
3445 dns_name_init(&fctx
->name
, NULL
);
3446 result
= dns_name_dup(name
, res
->buckets
[bucketnum
].mctx
, &fctx
->name
);
3447 if (result
!= ISC_R_SUCCESS
)
3449 dns_name_init(&fctx
->domain
, NULL
);
3450 dns_rdataset_init(&fctx
->nameservers
);
3453 fctx
->options
= options
;
3455 * Note! We do not attach to the task. We are relying on the
3456 * resolver to ensure that this task doesn't go away while we are
3460 fctx
->references
= 0;
3461 fctx
->bucketnum
= bucketnum
;
3462 fctx
->state
= fetchstate_init
;
3463 fctx
->want_shutdown
= ISC_FALSE
;
3464 fctx
->cloned
= ISC_FALSE
;
3465 ISC_LIST_INIT(fctx
->queries
);
3466 ISC_LIST_INIT(fctx
->finds
);
3467 ISC_LIST_INIT(fctx
->altfinds
);
3468 ISC_LIST_INIT(fctx
->forwaddrs
);
3469 ISC_LIST_INIT(fctx
->altaddrs
);
3470 ISC_LIST_INIT(fctx
->forwarders
);
3471 fctx
->fwdpolicy
= dns_fwdpolicy_none
;
3472 ISC_LIST_INIT(fctx
->bad
);
3473 ISC_LIST_INIT(fctx
->edns
);
3474 ISC_LIST_INIT(fctx
->edns512
);
3475 ISC_LIST_INIT(fctx
->validators
);
3476 fctx
->validator
= NULL
;
3478 fctx
->altfind
= NULL
;
3481 fctx
->querysent
= 0;
3482 fctx
->referrals
= 0;
3483 TIME_NOW(&fctx
->start
);
3485 fctx
->lamecount
= 0;
3491 fctx
->result
= ISC_R_FAILURE
;
3492 fctx
->vresult
= ISC_R_SUCCESS
;
3493 fctx
->exitline
= -1; /* sentinel */
3494 fctx
->logged
= ISC_FALSE
;
3495 fctx
->attributes
= 0;
3496 fctx
->spilled
= ISC_FALSE
;
3498 fctx
->reason
= NULL
;
3500 fctx
->rand_bits
= 0;
3501 fctx
->timeout
= ISC_FALSE
;
3502 fctx
->addrinfo
= NULL
;
3503 fctx
->client
= NULL
;
3505 dns_name_init(&fctx
->nsname
, NULL
);
3506 fctx
->nsfetch
= NULL
;
3507 dns_rdataset_init(&fctx
->nsrrset
);
3509 if (domain
== NULL
) {
3510 dns_forwarders_t
*forwarders
= NULL
;
3511 unsigned int labels
;
3512 dns_name_t
*fwdname
= name
;
3515 * DS records are found in the parent server.
3516 * Strip label to get the correct forwarder (if any).
3518 if (dns_rdatatype_atparent(fctx
->type
) &&
3519 dns_name_countlabels(name
) > 1) {
3520 dns_name_init(&suffix
, NULL
);
3521 labels
= dns_name_countlabels(name
);
3522 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
3525 dns_fixedname_init(&fixed
);
3526 domain
= dns_fixedname_name(&fixed
);
3527 result
= dns_fwdtable_find2(fctx
->res
->view
->fwdtable
, fwdname
,
3528 domain
, &forwarders
);
3529 if (result
== ISC_R_SUCCESS
)
3530 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
3532 if (fctx
->fwdpolicy
!= dns_fwdpolicy_only
) {
3534 * The caller didn't supply a query domain and
3535 * nameservers, and we're not in forward-only mode,
3536 * so find the best nameservers to use.
3538 if (dns_rdatatype_atparent(fctx
->type
))
3539 findoptions
|= DNS_DBFIND_NOEXACT
;
3540 result
= dns_view_findzonecut(res
->view
, name
, domain
,
3541 0, findoptions
, ISC_TRUE
,
3544 if (result
!= ISC_R_SUCCESS
)
3546 result
= dns_name_dup(domain
,
3547 res
->buckets
[bucketnum
].mctx
,
3549 if (result
!= ISC_R_SUCCESS
) {
3550 dns_rdataset_disassociate(&fctx
->nameservers
);
3555 * We're in forward-only mode. Set the query domain.
3557 result
= dns_name_dup(domain
,
3558 res
->buckets
[bucketnum
].mctx
,
3560 if (result
!= ISC_R_SUCCESS
)
3564 result
= dns_name_dup(domain
,
3565 res
->buckets
[bucketnum
].mctx
,
3567 if (result
!= ISC_R_SUCCESS
)
3569 dns_rdataset_clone(nameservers
, &fctx
->nameservers
);
3572 INSIST(dns_name_issubdomain(&fctx
->name
, &fctx
->domain
));
3574 fctx
->qmessage
= NULL
;
3575 result
= dns_message_create(res
->buckets
[bucketnum
].mctx
,
3576 DNS_MESSAGE_INTENTRENDER
,
3579 if (result
!= ISC_R_SUCCESS
)
3580 goto cleanup_domain
;
3582 fctx
->rmessage
= NULL
;
3583 result
= dns_message_create(res
->buckets
[bucketnum
].mctx
,
3584 DNS_MESSAGE_INTENTPARSE
,
3587 if (result
!= ISC_R_SUCCESS
)
3588 goto cleanup_qmessage
;
3591 * Compute an expiration time for the entire fetch.
3593 isc_interval_set(&interval
, 30, 0); /* XXXRTH constant */
3594 iresult
= isc_time_nowplusinterval(&fctx
->expires
, &interval
);
3595 if (iresult
!= ISC_R_SUCCESS
) {
3596 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
3597 "isc_time_nowplusinterval: %s",
3598 isc_result_totext(iresult
));
3599 result
= ISC_R_UNEXPECTED
;
3600 goto cleanup_rmessage
;
3604 * Default retry interval initialization. We set the interval now
3605 * mostly so it won't be uninitialized. It will be set to the
3606 * correct value before a query is issued.
3608 isc_interval_set(&fctx
->interval
, 2, 0);
3611 * Create an inactive timer. It will be made active when the fetch
3612 * is actually started.
3615 iresult
= isc_timer_create(res
->timermgr
, isc_timertype_inactive
,
3617 res
->buckets
[bucketnum
].task
, fctx_timeout
,
3618 fctx
, &fctx
->timer
);
3619 if (iresult
!= ISC_R_SUCCESS
) {
3620 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
3621 "isc_timer_create: %s",
3622 isc_result_totext(iresult
));
3623 result
= ISC_R_UNEXPECTED
;
3624 goto cleanup_rmessage
;
3628 * Attach to the view's cache and adb.
3631 dns_db_attach(res
->view
->cachedb
, &fctx
->cache
);
3633 dns_adb_attach(res
->view
->adb
, &fctx
->adb
);
3635 ISC_LIST_INIT(fctx
->events
);
3636 ISC_LINK_INIT(fctx
, link
);
3637 fctx
->magic
= FCTX_MAGIC
;
3639 ISC_LIST_APPEND(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
3643 UNLOCK(&res
->nlock
);
3647 return (ISC_R_SUCCESS
);
3650 dns_message_destroy(&fctx
->rmessage
);
3653 dns_message_destroy(&fctx
->qmessage
);
3656 if (dns_name_countlabels(&fctx
->domain
) > 0)
3657 dns_name_free(&fctx
->domain
, res
->buckets
[bucketnum
].mctx
);
3658 if (dns_rdataset_isassociated(&fctx
->nameservers
))
3659 dns_rdataset_disassociate(&fctx
->nameservers
);
3662 dns_name_free(&fctx
->name
, res
->buckets
[bucketnum
].mctx
);
3665 isc_mem_free(res
->buckets
[bucketnum
].mctx
, fctx
->info
);
3668 isc_mem_put(res
->buckets
[bucketnum
].mctx
, fctx
, sizeof(*fctx
));
3676 static inline isc_boolean_t
3677 is_lame(fetchctx_t
*fctx
) {
3678 dns_message_t
*message
= fctx
->rmessage
;
3680 dns_rdataset_t
*rdataset
;
3681 isc_result_t result
;
3683 if (message
->rcode
!= dns_rcode_noerror
&&
3684 message
->rcode
!= dns_rcode_nxdomain
)
3687 if (message
->counts
[DNS_SECTION_ANSWER
] != 0)
3690 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
3693 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
3694 while (result
== ISC_R_SUCCESS
) {
3696 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
3697 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3699 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3700 dns_namereln_t namereln
;
3702 unsigned int labels
;
3703 if (rdataset
->type
!= dns_rdatatype_ns
)
3705 namereln
= dns_name_fullcompare(name
, &fctx
->domain
,
3707 if (namereln
== dns_namereln_equal
&&
3708 (message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3710 if (namereln
== dns_namereln_subdomain
)
3714 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
3721 log_lame(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
) {
3722 char namebuf
[DNS_NAME_FORMATSIZE
];
3723 char domainbuf
[DNS_NAME_FORMATSIZE
];
3724 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
3726 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
3727 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
3728 isc_sockaddr_format(&addrinfo
->sockaddr
, addrbuf
, sizeof(addrbuf
));
3729 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
3730 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
3731 "lame server resolving '%s' (in '%s'?): %s",
3732 namebuf
, domainbuf
, addrbuf
);
3736 log_formerr(fetchctx_t
*fctx
, const char *format
, ...) {
3737 char nsbuf
[ISC_SOCKADDR_FORMATSIZE
];
3738 char clbuf
[ISC_SOCKADDR_FORMATSIZE
];
3739 const char *clmsg
= "";
3743 va_start(args
, format
);
3744 vsnprintf(msgbuf
, sizeof(msgbuf
), format
, args
);
3747 isc_sockaddr_format(&fctx
->addrinfo
->sockaddr
, nsbuf
, sizeof(nsbuf
));
3749 if (fctx
->client
!= NULL
) {
3750 clmsg
= " for client ";
3751 isc_sockaddr_format(fctx
->client
, clbuf
, sizeof(clbuf
));
3756 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
3757 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
3758 "DNS format error from %s resolving %s%s%s: %s",
3759 nsbuf
, fctx
->info
, clmsg
, clbuf
, msgbuf
);
3762 static inline isc_result_t
3763 same_question(fetchctx_t
*fctx
) {
3764 isc_result_t result
;
3765 dns_message_t
*message
= fctx
->rmessage
;
3767 dns_rdataset_t
*rdataset
;
3770 * Caller must be holding the fctx lock.
3774 * XXXRTH Currently we support only one question.
3776 if (message
->counts
[DNS_SECTION_QUESTION
] != 1) {
3777 log_formerr(fctx
, "too many questions");
3778 return (DNS_R_FORMERR
);
3781 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
3782 if (result
!= ISC_R_SUCCESS
)
3785 dns_message_currentname(message
, DNS_SECTION_QUESTION
, &name
);
3786 rdataset
= ISC_LIST_HEAD(name
->list
);
3787 INSIST(rdataset
!= NULL
);
3788 INSIST(ISC_LIST_NEXT(rdataset
, link
) == NULL
);
3790 if (fctx
->type
!= rdataset
->type
||
3791 fctx
->res
->rdclass
!= rdataset
->rdclass
||
3792 !dns_name_equal(&fctx
->name
, name
)) {
3793 char namebuf
[DNS_NAME_FORMATSIZE
];
3794 char class[DNS_RDATACLASS_FORMATSIZE
];
3795 char type
[DNS_RDATATYPE_FORMATSIZE
];
3797 dns_name_format(name
, namebuf
, sizeof(namebuf
));
3798 dns_rdataclass_format(rdataset
->rdclass
, class, sizeof(class));
3799 dns_rdatatype_format(rdataset
->type
, type
, sizeof(type
));
3800 log_formerr(fctx
, "question section mismatch: got %s/%s/%s",
3801 namebuf
, class, type
);
3802 return (DNS_R_FORMERR
);
3805 return (ISC_R_SUCCESS
);
3809 clone_results(fetchctx_t
*fctx
) {
3810 dns_fetchevent_t
*event
, *hevent
;
3811 isc_result_t result
;
3812 dns_name_t
*name
, *hname
;
3814 FCTXTRACE("clone_results");
3817 * Set up any other events to have the same data as the first
3820 * Caller must be holding the appropriate lock.
3823 fctx
->cloned
= ISC_TRUE
;
3824 hevent
= ISC_LIST_HEAD(fctx
->events
);
3827 hname
= dns_fixedname_name(&hevent
->foundname
);
3828 for (event
= ISC_LIST_NEXT(hevent
, ev_link
);
3830 event
= ISC_LIST_NEXT(event
, ev_link
)) {
3831 name
= dns_fixedname_name(&event
->foundname
);
3832 result
= dns_name_copy(hname
, name
, NULL
);
3833 if (result
!= ISC_R_SUCCESS
)
3834 event
->result
= result
;
3836 event
->result
= hevent
->result
;
3837 dns_db_attach(hevent
->db
, &event
->db
);
3838 dns_db_attachnode(hevent
->db
, hevent
->node
, &event
->node
);
3839 INSIST(hevent
->rdataset
!= NULL
);
3840 INSIST(event
->rdataset
!= NULL
);
3841 if (dns_rdataset_isassociated(hevent
->rdataset
))
3842 dns_rdataset_clone(hevent
->rdataset
, event
->rdataset
);
3843 INSIST(! (hevent
->sigrdataset
== NULL
&&
3844 event
->sigrdataset
!= NULL
));
3845 if (hevent
->sigrdataset
!= NULL
&&
3846 dns_rdataset_isassociated(hevent
->sigrdataset
) &&
3847 event
->sigrdataset
!= NULL
)
3848 dns_rdataset_clone(hevent
->sigrdataset
,
3849 event
->sigrdataset
);
3853 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3854 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3855 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3856 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3857 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3858 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3859 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3863 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3864 * no references and is no longer waiting for any events). If this
3865 * was the last fctx in the resolver, destroy the resolver.
3868 * '*fctx' is shutting down.
3871 maybe_destroy(fetchctx_t
*fctx
) {
3872 unsigned int bucketnum
;
3873 isc_boolean_t bucket_empty
= ISC_FALSE
;
3874 dns_resolver_t
*res
= fctx
->res
;
3875 dns_validator_t
*validator
, *next_validator
;
3877 REQUIRE(SHUTTINGDOWN(fctx
));
3879 if (fctx
->pending
!= 0 || fctx
->nqueries
!= 0)
3882 for (validator
= ISC_LIST_HEAD(fctx
->validators
);
3883 validator
!= NULL
; validator
= next_validator
) {
3884 next_validator
= ISC_LIST_NEXT(validator
, link
);
3885 dns_validator_cancel(validator
);
3887 * If this is a active validator wait for the cancel
3888 * to complete before calling dns_validator_destroy().
3890 if (validator
== fctx
->validator
)
3892 ISC_LIST_UNLINK(fctx
->validators
, validator
, link
);
3893 dns_validator_destroy(&validator
);
3896 bucketnum
= fctx
->bucketnum
;
3897 LOCK(&res
->buckets
[bucketnum
].lock
);
3898 if (fctx
->references
== 0 && ISC_LIST_EMPTY(fctx
->validators
))
3899 bucket_empty
= fctx_destroy(fctx
);
3900 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3907 * The validator has finished.
3910 validated(isc_task_t
*task
, isc_event_t
*event
) {
3911 isc_result_t result
= ISC_R_SUCCESS
;
3912 isc_result_t eresult
= ISC_R_SUCCESS
;
3915 dns_validatorevent_t
*vevent
;
3916 dns_fetchevent_t
*hevent
;
3917 dns_rdataset_t
*ardataset
= NULL
;
3918 dns_rdataset_t
*asigrdataset
= NULL
;
3919 dns_dbnode_t
*node
= NULL
;
3920 isc_boolean_t negative
;
3921 isc_boolean_t chaining
;
3922 isc_boolean_t sentresponse
;
3924 dns_dbnode_t
*nsnode
= NULL
;
3926 dns_rdataset_t
*rdataset
;
3927 dns_rdataset_t
*sigrdataset
;
3928 dns_valarg_t
*valarg
;
3929 dns_adbaddrinfo_t
*addrinfo
;
3931 UNUSED(task
); /* for now */
3933 REQUIRE(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
3934 valarg
= event
->ev_arg
;
3935 fctx
= valarg
->fctx
;
3936 addrinfo
= valarg
->addrinfo
;
3937 REQUIRE(VALID_FCTX(fctx
));
3938 REQUIRE(!ISC_LIST_EMPTY(fctx
->validators
));
3940 vevent
= (dns_validatorevent_t
*)event
;
3941 fctx
->vresult
= vevent
->result
;
3943 FCTXTRACE("received validation completion event");
3945 ISC_LIST_UNLINK(fctx
->validators
, vevent
->validator
, link
);
3946 fctx
->validator
= NULL
;
3949 * Destroy the validator early so that we can
3950 * destroy the fctx if necessary.
3952 dns_validator_destroy(&vevent
->validator
);
3953 isc_mem_put(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
3954 valarg
, sizeof(*valarg
));
3956 negative
= ISC_TF(vevent
->rdataset
== NULL
);
3958 sentresponse
= ISC_TF((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0);
3961 * If shutting down, ignore the results. Check to see if we're
3962 * done waiting for validator completions and ADB pending events; if
3963 * so, destroy the fctx.
3965 if (SHUTTINGDOWN(fctx
) && !sentresponse
) {
3966 maybe_destroy(fctx
); /* Locks bucket. */
3970 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3973 * If chaining, we need to make sure that the right result code is
3974 * returned, and that the rdatasets are bound.
3976 if (vevent
->result
== ISC_R_SUCCESS
&&
3978 vevent
->rdataset
!= NULL
&&
3979 CHAINING(vevent
->rdataset
))
3981 if (vevent
->rdataset
->type
== dns_rdatatype_cname
)
3982 eresult
= DNS_R_CNAME
;
3984 INSIST(vevent
->rdataset
->type
== dns_rdatatype_dname
);
3985 eresult
= DNS_R_DNAME
;
3987 chaining
= ISC_TRUE
;
3989 chaining
= ISC_FALSE
;
3992 * Either we're not shutting down, or we are shutting down but want
3993 * to cache the result anyway (if this was a validation started by
3994 * a query with cd set)
3997 hevent
= ISC_LIST_HEAD(fctx
->events
);
3998 if (hevent
!= NULL
) {
3999 if (!negative
&& !chaining
&&
4000 (fctx
->type
== dns_rdatatype_any
||
4001 fctx
->type
== dns_rdatatype_rrsig
||
4002 fctx
->type
== dns_rdatatype_sig
)) {
4004 * Don't bind rdatasets; the caller
4005 * will iterate the node.
4008 ardataset
= hevent
->rdataset
;
4009 asigrdataset
= hevent
->sigrdataset
;
4013 if (vevent
->result
!= ISC_R_SUCCESS
) {
4014 FCTXTRACE("validation failed");
4015 inc_stats(fctx
->res
, dns_resstatscounter_valfail
);
4017 fctx
->vresult
= vevent
->result
;
4018 result
= ISC_R_NOTFOUND
;
4019 if (vevent
->rdataset
!= NULL
)
4020 result
= dns_db_findnode(fctx
->cache
, vevent
->name
,
4022 if (result
== ISC_R_SUCCESS
)
4023 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
4025 if (result
== ISC_R_SUCCESS
&& vevent
->sigrdataset
!= NULL
)
4026 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
4027 dns_rdatatype_rrsig
,
4029 if (result
== ISC_R_SUCCESS
)
4030 dns_db_detachnode(fctx
->cache
, &node
);
4031 result
= vevent
->result
;
4032 add_bad(fctx
, addrinfo
, result
, badns_validation
);
4033 isc_event_free(&event
);
4034 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4035 INSIST(fctx
->validator
== NULL
);
4036 fctx
->validator
= ISC_LIST_HEAD(fctx
->validators
);
4037 if (fctx
->validator
!= NULL
) {
4038 dns_validator_send(fctx
->validator
);
4039 } else if (sentresponse
)
4040 fctx_done(fctx
, result
, __LINE__
); /* Locks bucket. */
4042 fctx_try(fctx
, ISC_TRUE
); /* Locks bucket. */
4046 isc_stdtime_get(&now
);
4049 dns_rdatatype_t covers
;
4050 FCTXTRACE("nonexistence validation OK");
4052 inc_stats(fctx
->res
, dns_resstatscounter_valnegsuccess
);
4054 if (fctx
->rmessage
->rcode
== dns_rcode_nxdomain
)
4055 covers
= dns_rdatatype_any
;
4057 covers
= fctx
->type
;
4059 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
,
4061 if (result
!= ISC_R_SUCCESS
)
4062 goto noanswer_response
;
4065 * If we are asking for a SOA record set the cache time
4066 * to zero to facilitate locating the containing zone of
4069 ttl
= fctx
->res
->view
->maxncachettl
;
4070 if (fctx
->type
== dns_rdatatype_soa
&&
4071 covers
== dns_rdatatype_any
&&
4072 fctx
->res
->zero_no_soa_ttl
)
4075 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
4076 covers
, now
, ttl
, vevent
->optout
,
4077 ardataset
, &eresult
);
4078 if (result
!= ISC_R_SUCCESS
)
4079 goto noanswer_response
;
4080 goto answer_response
;
4082 inc_stats(fctx
->res
, dns_resstatscounter_valsuccess
);
4084 FCTXTRACE("validation OK");
4086 if (vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] != NULL
) {
4088 result
= dns_rdataset_addnoqname(vevent
->rdataset
,
4089 vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
]);
4090 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4091 INSIST(vevent
->sigrdataset
!= NULL
);
4092 vevent
->sigrdataset
->ttl
= vevent
->rdataset
->ttl
;
4093 if (vevent
->proofs
[DNS_VALIDATOR_CLOSESTENCLOSER
] != NULL
) {
4094 result
= dns_rdataset_addclosest(vevent
->rdataset
,
4095 vevent
->proofs
[DNS_VALIDATOR_CLOSESTENCLOSER
]);
4096 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
4101 * The data was already cached as pending data.
4102 * Re-cache it as secure and bind the cached
4103 * rdatasets to the first event on the fetch
4106 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
, &node
);
4107 if (result
!= ISC_R_SUCCESS
)
4108 goto noanswer_response
;
4110 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
4111 vevent
->rdataset
, 0, ardataset
);
4112 if (result
!= ISC_R_SUCCESS
&&
4113 result
!= DNS_R_UNCHANGED
)
4114 goto noanswer_response
;
4115 if (ardataset
!= NULL
&& ardataset
->type
== 0) {
4116 if (NXDOMAIN(ardataset
))
4117 eresult
= DNS_R_NCACHENXDOMAIN
;
4119 eresult
= DNS_R_NCACHENXRRSET
;
4120 } else if (vevent
->sigrdataset
!= NULL
) {
4121 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
4122 vevent
->sigrdataset
, 0,
4124 if (result
!= ISC_R_SUCCESS
&&
4125 result
!= DNS_R_UNCHANGED
)
4126 goto noanswer_response
;
4131 * If we only deferred the destroy because we wanted to cache
4132 * the data, destroy now.
4134 dns_db_detachnode(fctx
->cache
, &node
);
4135 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4136 if (SHUTTINGDOWN(fctx
))
4137 maybe_destroy(fctx
); /* Locks bucket. */
4141 if (!ISC_LIST_EMPTY(fctx
->validators
)) {
4143 INSIST(fctx
->type
== dns_rdatatype_any
||
4144 fctx
->type
== dns_rdatatype_rrsig
||
4145 fctx
->type
== dns_rdatatype_sig
);
4147 * Don't send a response yet - we have
4148 * more rdatasets that still need to
4151 dns_db_detachnode(fctx
->cache
, &node
);
4152 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4153 dns_validator_send(ISC_LIST_HEAD(fctx
->validators
));
4159 * Cache any NS/NSEC records that happened to be validated.
4161 result
= dns_message_firstname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
);
4162 while (result
== ISC_R_SUCCESS
) {
4164 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
,
4166 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4168 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4169 if ((rdataset
->type
!= dns_rdatatype_ns
&&
4170 rdataset
->type
!= dns_rdatatype_nsec
) ||
4171 rdataset
->trust
!= dns_trust_secure
)
4173 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
4174 sigrdataset
!= NULL
;
4175 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
4176 if (sigrdataset
->type
!= dns_rdatatype_rrsig
||
4177 sigrdataset
->covers
!= rdataset
->type
)
4181 if (sigrdataset
== NULL
||
4182 sigrdataset
->trust
!= dns_trust_secure
)
4184 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
,
4186 if (result
!= ISC_R_SUCCESS
)
4189 result
= dns_db_addrdataset(fctx
->cache
, nsnode
, NULL
,
4190 now
, rdataset
, 0, NULL
);
4191 if (result
== ISC_R_SUCCESS
)
4192 result
= dns_db_addrdataset(fctx
->cache
, nsnode
,
4196 dns_db_detachnode(fctx
->cache
, &nsnode
);
4198 result
= dns_message_nextname(fctx
->rmessage
,
4199 DNS_SECTION_AUTHORITY
);
4202 result
= ISC_R_SUCCESS
;
4205 * Respond with an answer, positive or negative,
4206 * as opposed to an error. 'node' must be non-NULL.
4209 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4211 if (hevent
!= NULL
) {
4212 hevent
->result
= eresult
;
4213 RUNTIME_CHECK(dns_name_copy(vevent
->name
,
4214 dns_fixedname_name(&hevent
->foundname
), NULL
)
4216 dns_db_attach(fctx
->cache
, &hevent
->db
);
4217 dns_db_transfernode(fctx
->cache
, &node
, &hevent
->node
);
4218 clone_results(fctx
);
4223 dns_db_detachnode(fctx
->cache
, &node
);
4225 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4227 fctx_done(fctx
, result
, __LINE__
); /* Locks bucket. */
4230 INSIST(node
== NULL
);
4231 isc_event_free(&event
);
4234 static inline isc_result_t
4235 cache_name(fetchctx_t
*fctx
, dns_name_t
*name
, dns_adbaddrinfo_t
*addrinfo
,
4238 dns_rdataset_t
*rdataset
, *sigrdataset
;
4239 dns_rdataset_t
*addedrdataset
, *ardataset
, *asigrdataset
;
4240 dns_rdataset_t
*valrdataset
= NULL
, *valsigrdataset
= NULL
;
4241 dns_dbnode_t
*node
, **anodep
;
4244 dns_resolver_t
*res
;
4245 isc_boolean_t need_validation
, secure_domain
, have_answer
;
4246 isc_result_t result
, eresult
;
4247 dns_fetchevent_t
*event
;
4248 unsigned int options
;
4251 unsigned int valoptions
= 0;
4254 * The appropriate bucket lock must be held.
4258 need_validation
= ISC_FALSE
;
4259 secure_domain
= ISC_FALSE
;
4260 have_answer
= ISC_FALSE
;
4261 eresult
= ISC_R_SUCCESS
;
4262 task
= res
->buckets
[fctx
->bucketnum
].task
;
4265 * Is DNSSEC validation required for this name?
4267 if (res
->view
->enablevalidation
) {
4268 result
= dns_view_issecuredomain(res
->view
, name
,
4270 if (result
!= ISC_R_SUCCESS
)
4273 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
4274 valoptions
= DNS_VALIDATOR_DLV
;
4275 secure_domain
= ISC_TRUE
;
4279 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
4280 need_validation
= ISC_FALSE
;
4282 need_validation
= secure_domain
;
4288 asigrdataset
= NULL
;
4290 if ((name
->attributes
& DNS_NAMEATTR_ANSWER
) != 0 &&
4292 have_answer
= ISC_TRUE
;
4293 event
= ISC_LIST_HEAD(fctx
->events
);
4294 if (event
!= NULL
) {
4296 aname
= dns_fixedname_name(&event
->foundname
);
4297 result
= dns_name_copy(name
, aname
, NULL
);
4298 if (result
!= ISC_R_SUCCESS
)
4300 anodep
= &event
->node
;
4302 * If this is an ANY, SIG or RRSIG query, we're not
4303 * going to return any rdatasets, unless we encountered
4304 * a CNAME or DNAME as "the answer". In this case,
4305 * we're going to return DNS_R_CNAME or DNS_R_DNAME
4306 * and we must set up the rdatasets.
4308 if ((fctx
->type
!= dns_rdatatype_any
&&
4309 fctx
->type
!= dns_rdatatype_rrsig
&&
4310 fctx
->type
!= dns_rdatatype_sig
) ||
4311 (name
->attributes
& DNS_NAMEATTR_CHAINING
) != 0) {
4312 ardataset
= event
->rdataset
;
4313 asigrdataset
= event
->sigrdataset
;
4319 * Find or create the cache node.
4322 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
4323 if (result
!= ISC_R_SUCCESS
)
4327 * Cache or validate each cacheable rdataset.
4329 fail
= ISC_TF((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMESFAIL
) != 0);
4330 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4332 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4333 if (!CACHE(rdataset
))
4335 if (CHECKNAMES(rdataset
)) {
4336 char namebuf
[DNS_NAME_FORMATSIZE
];
4337 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
4338 char classbuf
[DNS_RDATATYPE_FORMATSIZE
];
4340 dns_name_format(name
, namebuf
, sizeof(namebuf
));
4341 dns_rdatatype_format(rdataset
->type
, typebuf
,
4343 dns_rdataclass_format(rdataset
->rdclass
, classbuf
,
4345 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
4346 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
4347 "check-names %s %s/%s/%s",
4348 fail
? "failure" : "warning",
4349 namebuf
, typebuf
, classbuf
);
4351 if (ANSWER(rdataset
)) {
4352 dns_db_detachnode(fctx
->cache
, &node
);
4353 return (DNS_R_BADNAME
);
4360 * Enforce the configure maximum cache TTL.
4362 if (rdataset
->ttl
> res
->view
->maxcachettl
)
4363 rdataset
->ttl
= res
->view
->maxcachettl
;
4366 * If this rrset is in a secure domain, do DNSSEC validation
4367 * for it, unless it is glue.
4369 if (secure_domain
&& rdataset
->trust
!= dns_trust_glue
) {
4372 * RRSIGs are validated as part of validating the
4375 if (rdataset
->type
== dns_rdatatype_rrsig
)
4378 * Find the SIG for this rdataset, if we have it.
4380 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
4381 sigrdataset
!= NULL
;
4382 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
4383 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
4384 sigrdataset
->covers
== rdataset
->type
)
4387 if (sigrdataset
== NULL
) {
4388 if (!ANSWER(rdataset
) && need_validation
) {
4390 * Ignore non-answer rdatasets that
4391 * are missing signatures.
4398 * Normalize the rdataset and sigrdataset TTLs.
4400 if (sigrdataset
!= NULL
) {
4401 rdataset
->ttl
= ISC_MIN(rdataset
->ttl
,
4403 sigrdataset
->ttl
= rdataset
->ttl
;
4407 * Reject out of bailiwick additional records
4408 * without RRSIGs as they can't possibly validate
4409 * as "secure" and as we will never never want to
4410 * store these as "answers" after validation.
4412 if (rdataset
->trust
== dns_trust_additional
&&
4413 sigrdataset
== NULL
&& EXTERNAL(rdataset
))
4417 * XXXMPA: If we store as "answer" after validating
4418 * then we need to do bailiwick processing and
4419 * also need to track whether RRsets are in or
4420 * out of bailiwick. This will require a another
4421 * pending trust level.
4423 * Cache this rdataset/sigrdataset pair as
4424 * pending data. Track whether it was additional
4427 if (rdataset
->trust
== dns_trust_additional
)
4428 trust
= dns_trust_pending_additional
;
4430 trust
= dns_trust_pending_answer
;
4432 rdataset
->trust
= trust
;
4433 if (sigrdataset
!= NULL
)
4434 sigrdataset
->trust
= trust
;
4435 if (!need_validation
|| !ANSWER(rdataset
)) {
4436 addedrdataset
= ardataset
;
4437 result
= dns_db_addrdataset(fctx
->cache
, node
,
4438 NULL
, now
, rdataset
,
4440 if (result
== DNS_R_UNCHANGED
) {
4441 result
= ISC_R_SUCCESS
;
4442 if (!need_validation
&&
4443 ardataset
!= NULL
&&
4444 ardataset
->type
== 0) {
4446 * The answer in the cache is
4447 * better than the answer we
4448 * found, and is a negative
4449 * cache entry, so we must set
4450 * eresult appropriately.
4452 if (NXDOMAIN(ardataset
))
4454 DNS_R_NCACHENXDOMAIN
;
4457 DNS_R_NCACHENXRRSET
;
4459 * We have a negative response
4460 * from the cache so don't
4461 * attempt to add the RRSIG
4467 if (result
!= ISC_R_SUCCESS
)
4469 if (sigrdataset
!= NULL
) {
4470 addedrdataset
= asigrdataset
;
4471 result
= dns_db_addrdataset(fctx
->cache
,
4475 if (result
== DNS_R_UNCHANGED
)
4476 result
= ISC_R_SUCCESS
;
4477 if (result
!= ISC_R_SUCCESS
)
4479 } else if (!ANSWER(rdataset
))
4483 if (ANSWER(rdataset
) && need_validation
) {
4484 if (fctx
->type
!= dns_rdatatype_any
&&
4485 fctx
->type
!= dns_rdatatype_rrsig
&&
4486 fctx
->type
!= dns_rdatatype_sig
) {
4488 * This is The Answer. We will
4489 * validate it, but first we cache
4490 * the rest of the response - it may
4491 * contain useful keys.
4493 INSIST(valrdataset
== NULL
&&
4494 valsigrdataset
== NULL
);
4495 valrdataset
= rdataset
;
4496 valsigrdataset
= sigrdataset
;
4499 * This is one of (potentially)
4500 * multiple answers to an ANY
4501 * or SIG query. To keep things
4502 * simple, we just start the
4503 * validator right away rather
4504 * than caching first and
4505 * having to remember which
4506 * rdatasets needed validation.
4508 result
= valcreate(fctx
, addrinfo
,
4509 name
, rdataset
->type
,
4514 * Defer any further validations.
4515 * This prevents multiple validators
4516 * from manipulating fctx->rmessage
4519 valoptions
|= DNS_VALIDATOR_DEFER
;
4521 } else if (CHAINING(rdataset
)) {
4522 if (rdataset
->type
== dns_rdatatype_cname
)
4523 eresult
= DNS_R_CNAME
;
4525 INSIST(rdataset
->type
==
4526 dns_rdatatype_dname
);
4527 eresult
= DNS_R_DNAME
;
4530 } else if (!EXTERNAL(rdataset
)) {
4532 * It's OK to cache this rdataset now.
4534 if (ANSWER(rdataset
))
4535 addedrdataset
= ardataset
;
4536 else if (ANSWERSIG(rdataset
))
4537 addedrdataset
= asigrdataset
;
4539 addedrdataset
= NULL
;
4540 if (CHAINING(rdataset
)) {
4541 if (rdataset
->type
== dns_rdatatype_cname
)
4542 eresult
= DNS_R_CNAME
;
4544 INSIST(rdataset
->type
==
4545 dns_rdatatype_dname
);
4546 eresult
= DNS_R_DNAME
;
4549 if (rdataset
->trust
== dns_trust_glue
&&
4550 (rdataset
->type
== dns_rdatatype_ns
||
4551 (rdataset
->type
== dns_rdatatype_rrsig
&&
4552 rdataset
->covers
== dns_rdatatype_ns
))) {
4554 * If the trust level is 'dns_trust_glue'
4555 * then we are adding data from a referral
4556 * we got while executing the search algorithm.
4557 * New referral data always takes precedence
4558 * over the existing cache contents.
4560 options
= DNS_DBADD_FORCE
;
4564 * Now we can add the rdataset.
4566 result
= dns_db_addrdataset(fctx
->cache
,
4571 if (result
== DNS_R_UNCHANGED
) {
4572 if (ANSWER(rdataset
) &&
4573 ardataset
!= NULL
&&
4574 ardataset
->type
== 0) {
4576 * The answer in the cache is better
4577 * than the answer we found, and is
4578 * a negative cache entry, so we
4579 * must set eresult appropriately.
4581 if (NXDOMAIN(ardataset
))
4582 eresult
= DNS_R_NCACHENXDOMAIN
;
4584 eresult
= DNS_R_NCACHENXRRSET
;
4586 result
= ISC_R_SUCCESS
;
4587 } else if (result
!= ISC_R_SUCCESS
)
4592 if (valrdataset
!= NULL
)
4593 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
4594 valrdataset
, valsigrdataset
, valoptions
,
4597 if (result
== ISC_R_SUCCESS
&& have_answer
) {
4598 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4599 if (event
!= NULL
) {
4601 * Negative results must be indicated in event->result.
4603 if (dns_rdataset_isassociated(event
->rdataset
) &&
4604 event
->rdataset
->type
== dns_rdatatype_none
) {
4605 INSIST(eresult
== DNS_R_NCACHENXDOMAIN
||
4606 eresult
== DNS_R_NCACHENXRRSET
);
4608 event
->result
= eresult
;
4609 dns_db_attach(fctx
->cache
, adbp
);
4610 dns_db_transfernode(fctx
->cache
, &node
, anodep
);
4611 clone_results(fctx
);
4616 dns_db_detachnode(fctx
->cache
, &node
);
4621 static inline isc_result_t
4622 cache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, isc_stdtime_t now
)
4624 isc_result_t result
;
4625 dns_section_t section
;
4628 FCTXTRACE("cache_message");
4630 fctx
->attributes
&= ~FCTX_ATTR_WANTCACHE
;
4632 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4634 for (section
= DNS_SECTION_ANSWER
;
4635 section
<= DNS_SECTION_ADDITIONAL
;
4637 result
= dns_message_firstname(fctx
->rmessage
, section
);
4638 while (result
== ISC_R_SUCCESS
) {
4640 dns_message_currentname(fctx
->rmessage
, section
,
4642 if ((name
->attributes
& DNS_NAMEATTR_CACHE
) != 0) {
4643 result
= cache_name(fctx
, name
, addrinfo
, now
);
4644 if (result
!= ISC_R_SUCCESS
)
4647 result
= dns_message_nextname(fctx
->rmessage
, section
);
4649 if (result
!= ISC_R_NOMORE
)
4652 if (result
== ISC_R_NOMORE
)
4653 result
= ISC_R_SUCCESS
;
4655 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4661 * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
4664 ncache_adderesult(dns_message_t
*message
, dns_db_t
*cache
, dns_dbnode_t
*node
,
4665 dns_rdatatype_t covers
, isc_stdtime_t now
, dns_ttl_t maxttl
,
4666 isc_boolean_t optout
, dns_rdataset_t
*ardataset
,
4667 isc_result_t
*eresultp
)
4669 isc_result_t result
;
4670 dns_rdataset_t rdataset
;
4672 if (ardataset
== NULL
) {
4673 dns_rdataset_init(&rdataset
);
4674 ardataset
= &rdataset
;
4676 result
= dns_ncache_addoptout(message
, cache
, node
, covers
, now
,
4677 maxttl
, optout
, ardataset
);
4678 if (result
== DNS_R_UNCHANGED
|| result
== ISC_R_SUCCESS
) {
4680 * If the cache now contains a negative entry and we
4681 * care about whether it is DNS_R_NCACHENXDOMAIN or
4682 * DNS_R_NCACHENXRRSET then extract it.
4684 if (ardataset
->type
== 0) {
4686 * The cache data is a negative cache entry.
4688 if (NXDOMAIN(ardataset
))
4689 *eresultp
= DNS_R_NCACHENXDOMAIN
;
4691 *eresultp
= DNS_R_NCACHENXRRSET
;
4694 * Either we don't care about the nature of the
4695 * cache rdataset (because no fetch is interested
4696 * in the outcome), or the cache rdataset is not
4697 * a negative cache entry. Whichever case it is,
4698 * we can return success.
4700 * XXXRTH There's a CNAME/DNAME problem here.
4702 *eresultp
= ISC_R_SUCCESS
;
4704 result
= ISC_R_SUCCESS
;
4706 if (ardataset
== &rdataset
&& dns_rdataset_isassociated(ardataset
))
4707 dns_rdataset_disassociate(ardataset
);
4712 static inline isc_result_t
4713 ncache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
4714 dns_rdatatype_t covers
, isc_stdtime_t now
)
4716 isc_result_t result
, eresult
;
4718 dns_resolver_t
*res
;
4720 dns_dbnode_t
*node
, **anodep
;
4721 dns_rdataset_t
*ardataset
;
4722 isc_boolean_t need_validation
, secure_domain
;
4724 dns_fetchevent_t
*event
;
4726 unsigned int valoptions
= 0;
4728 FCTXTRACE("ncache_message");
4730 fctx
->attributes
&= ~FCTX_ATTR_WANTNCACHE
;
4733 need_validation
= ISC_FALSE
;
4734 secure_domain
= ISC_FALSE
;
4735 eresult
= ISC_R_SUCCESS
;
4740 * XXXMPA remove when we follow cnames and adjust the setting
4741 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4743 INSIST(fctx
->rmessage
->counts
[DNS_SECTION_ANSWER
] == 0);
4746 * Is DNSSEC validation required for this name?
4748 if (fctx
->res
->view
->enablevalidation
) {
4749 result
= dns_view_issecuredomain(res
->view
, name
,
4751 if (result
!= ISC_R_SUCCESS
)
4754 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
4755 valoptions
= DNS_VALIDATOR_DLV
;
4756 secure_domain
= ISC_TRUE
;
4760 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
4761 need_validation
= ISC_FALSE
;
4763 need_validation
= secure_domain
;
4765 if (secure_domain
) {
4767 * Mark all rdatasets as pending.
4769 dns_rdataset_t
*trdataset
;
4772 result
= dns_message_firstname(fctx
->rmessage
,
4773 DNS_SECTION_AUTHORITY
);
4774 while (result
== ISC_R_SUCCESS
) {
4776 dns_message_currentname(fctx
->rmessage
,
4777 DNS_SECTION_AUTHORITY
,
4779 for (trdataset
= ISC_LIST_HEAD(tname
->list
);
4781 trdataset
= ISC_LIST_NEXT(trdataset
, link
))
4782 trdataset
->trust
= dns_trust_pending_answer
;
4783 result
= dns_message_nextname(fctx
->rmessage
,
4784 DNS_SECTION_AUTHORITY
);
4786 if (result
!= ISC_R_NOMORE
)
4791 if (need_validation
) {
4793 * Do negative response validation.
4795 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
4796 NULL
, NULL
, valoptions
,
4797 res
->buckets
[fctx
->bucketnum
].task
);
4799 * If validation is necessary, return now. Otherwise continue
4800 * to process the message, letting the validation complete
4801 * in its own good time.
4806 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
4812 if (!HAVE_ANSWER(fctx
)) {
4813 event
= ISC_LIST_HEAD(fctx
->events
);
4814 if (event
!= NULL
) {
4816 aname
= dns_fixedname_name(&event
->foundname
);
4817 result
= dns_name_copy(name
, aname
, NULL
);
4818 if (result
!= ISC_R_SUCCESS
)
4820 anodep
= &event
->node
;
4821 ardataset
= event
->rdataset
;
4826 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
4827 if (result
!= ISC_R_SUCCESS
)
4831 * If we are asking for a SOA record set the cache time
4832 * to zero to facilitate locating the containing zone of
4835 ttl
= fctx
->res
->view
->maxncachettl
;
4836 if (fctx
->type
== dns_rdatatype_soa
&&
4837 covers
== dns_rdatatype_any
&&
4838 fctx
->res
->zero_no_soa_ttl
)
4841 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
4842 covers
, now
, ttl
, ISC_FALSE
,
4843 ardataset
, &eresult
);
4844 if (result
!= ISC_R_SUCCESS
)
4847 if (!HAVE_ANSWER(fctx
)) {
4848 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4849 if (event
!= NULL
) {
4850 event
->result
= eresult
;
4851 dns_db_attach(fctx
->cache
, adbp
);
4852 dns_db_transfernode(fctx
->cache
, &node
, anodep
);
4853 clone_results(fctx
);
4858 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
4861 dns_db_detachnode(fctx
->cache
, &node
);
4867 mark_related(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4868 isc_boolean_t external
, isc_boolean_t gluing
)
4870 name
->attributes
|= DNS_NAMEATTR_CACHE
;
4872 rdataset
->trust
= dns_trust_glue
;
4874 * Glue with 0 TTL causes problems. We force the TTL to
4875 * 1 second to prevent this.
4877 if (rdataset
->ttl
== 0)
4880 rdataset
->trust
= dns_trust_additional
;
4882 * Avoid infinite loops by only marking new rdatasets.
4884 if (!CACHE(rdataset
)) {
4885 name
->attributes
|= DNS_NAMEATTR_CHASE
;
4886 rdataset
->attributes
|= DNS_RDATASETATTR_CHASE
;
4888 rdataset
->attributes
|= DNS_RDATASETATTR_CACHE
;
4890 rdataset
->attributes
|= DNS_RDATASETATTR_EXTERNAL
;
4894 check_section(void *arg
, dns_name_t
*addname
, dns_rdatatype_t type
,
4895 dns_section_t section
)
4897 fetchctx_t
*fctx
= arg
;
4898 isc_result_t result
;
4900 dns_rdataset_t
*rdataset
;
4901 isc_boolean_t external
;
4902 dns_rdatatype_t rtype
;
4903 isc_boolean_t gluing
;
4905 REQUIRE(VALID_FCTX(fctx
));
4907 #if CHECK_FOR_GLUE_IN_ANSWER
4908 if (section
== DNS_SECTION_ANSWER
&& type
!= dns_rdatatype_a
)
4909 return (ISC_R_SUCCESS
);
4918 result
= dns_message_findname(fctx
->rmessage
, section
, addname
,
4919 dns_rdatatype_any
, 0, &name
, NULL
);
4920 if (result
== ISC_R_SUCCESS
) {
4921 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
4922 if (type
== dns_rdatatype_a
) {
4923 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4925 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4926 if (rdataset
->type
== dns_rdatatype_rrsig
)
4927 rtype
= rdataset
->covers
;
4929 rtype
= rdataset
->type
;
4930 if (rtype
== dns_rdatatype_a
||
4931 rtype
== dns_rdatatype_aaaa
)
4932 mark_related(name
, rdataset
, external
,
4936 result
= dns_message_findtype(name
, type
, 0,
4938 if (result
== ISC_R_SUCCESS
) {
4939 mark_related(name
, rdataset
, external
, gluing
);
4941 * Do we have its SIG too?
4944 result
= dns_message_findtype(name
,
4945 dns_rdatatype_rrsig
,
4947 if (result
== ISC_R_SUCCESS
)
4948 mark_related(name
, rdataset
, external
,
4954 return (ISC_R_SUCCESS
);
4958 check_related(void *arg
, dns_name_t
*addname
, dns_rdatatype_t type
) {
4959 return (check_section(arg
, addname
, type
, DNS_SECTION_ADDITIONAL
));
4962 #ifndef CHECK_FOR_GLUE_IN_ANSWER
4963 #define CHECK_FOR_GLUE_IN_ANSWER 0
4965 #if CHECK_FOR_GLUE_IN_ANSWER
4967 check_answer(void *arg
, dns_name_t
*addname
, dns_rdatatype_t type
) {
4968 return (check_section(arg
, addname
, type
, DNS_SECTION_ANSWER
));
4973 chase_additional(fetchctx_t
*fctx
) {
4974 isc_boolean_t rescan
;
4975 dns_section_t section
= DNS_SECTION_ADDITIONAL
;
4976 isc_result_t result
;
4981 for (result
= dns_message_firstname(fctx
->rmessage
, section
);
4982 result
== ISC_R_SUCCESS
;
4983 result
= dns_message_nextname(fctx
->rmessage
, section
)) {
4984 dns_name_t
*name
= NULL
;
4985 dns_rdataset_t
*rdataset
;
4986 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_ADDITIONAL
,
4988 if ((name
->attributes
& DNS_NAMEATTR_CHASE
) == 0)
4990 name
->attributes
&= ~DNS_NAMEATTR_CHASE
;
4991 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4993 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4994 if (CHASE(rdataset
)) {
4995 rdataset
->attributes
&= ~DNS_RDATASETATTR_CHASE
;
4996 (void)dns_rdataset_additionaldata(rdataset
,
5007 static inline isc_result_t
5008 cname_target(dns_rdataset_t
*rdataset
, dns_name_t
*tname
) {
5009 isc_result_t result
;
5010 dns_rdata_t rdata
= DNS_RDATA_INIT
;
5011 dns_rdata_cname_t cname
;
5013 result
= dns_rdataset_first(rdataset
);
5014 if (result
!= ISC_R_SUCCESS
)
5016 dns_rdataset_current(rdataset
, &rdata
);
5017 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
5018 if (result
!= ISC_R_SUCCESS
)
5020 dns_name_init(tname
, NULL
);
5021 dns_name_clone(&cname
.cname
, tname
);
5022 dns_rdata_freestruct(&cname
);
5024 return (ISC_R_SUCCESS
);
5027 static inline isc_result_t
5028 dname_target(fetchctx_t
*fctx
, dns_rdataset_t
*rdataset
, dns_name_t
*qname
,
5029 dns_name_t
*oname
, dns_fixedname_t
*fixeddname
)
5031 isc_result_t result
;
5032 dns_rdata_t rdata
= DNS_RDATA_INIT
;
5033 unsigned int nlabels
;
5035 dns_namereln_t namereln
;
5036 dns_rdata_dname_t dname
;
5037 dns_fixedname_t prefix
;
5040 * Get the target name of the DNAME.
5042 result
= dns_rdataset_first(rdataset
);
5043 if (result
!= ISC_R_SUCCESS
)
5045 dns_rdataset_current(rdataset
, &rdata
);
5046 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
5047 if (result
!= ISC_R_SUCCESS
)
5051 * Get the prefix of qname.
5053 namereln
= dns_name_fullcompare(qname
, oname
, &order
, &nlabels
);
5054 if (namereln
!= dns_namereln_subdomain
) {
5055 char qbuf
[DNS_NAME_FORMATSIZE
];
5056 char obuf
[DNS_NAME_FORMATSIZE
];
5058 dns_rdata_freestruct(&dname
);
5059 dns_name_format(qname
, qbuf
, sizeof(qbuf
));
5060 dns_name_format(oname
, obuf
, sizeof(obuf
));
5061 log_formerr(fctx
, "unrelated DNAME in answer: "
5062 "%s is not in %s", qbuf
, obuf
);
5063 return (DNS_R_FORMERR
);
5065 dns_fixedname_init(&prefix
);
5066 dns_name_split(qname
, nlabels
, dns_fixedname_name(&prefix
), NULL
);
5067 dns_fixedname_init(fixeddname
);
5068 result
= dns_name_concatenate(dns_fixedname_name(&prefix
),
5070 dns_fixedname_name(fixeddname
), NULL
);
5071 dns_rdata_freestruct(&dname
);
5075 static isc_boolean_t
5076 is_answeraddress_allowed(dns_view_t
*view
, dns_name_t
*name
,
5077 dns_rdataset_t
*rdataset
)
5079 isc_result_t result
;
5080 dns_rdata_t rdata
= DNS_RDATA_INIT
;
5082 struct in6_addr in6a
;
5083 isc_netaddr_t netaddr
;
5084 char addrbuf
[ISC_NETADDR_FORMATSIZE
];
5085 char namebuf
[DNS_NAME_FORMATSIZE
];
5090 /* By default, we allow any addresses. */
5091 if (view
->denyansweracl
== NULL
)
5095 * If the owner name matches one in the exclusion list, either exactly
5096 * or partially, allow it.
5098 if (view
->answeracl_exclude
!= NULL
) {
5099 dns_rbtnode_t
*node
= NULL
;
5101 result
= dns_rbt_findnode(view
->answeracl_exclude
, name
, NULL
,
5102 &node
, NULL
, 0, NULL
, NULL
);
5104 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
5109 * Otherwise, search the filter list for a match for each address
5110 * record. If a match is found, the address should be filtered,
5111 * so should the entire answer.
5113 for (result
= dns_rdataset_first(rdataset
);
5114 result
== ISC_R_SUCCESS
;
5115 result
= dns_rdataset_next(rdataset
)) {
5116 dns_rdata_reset(&rdata
);
5117 dns_rdataset_current(rdataset
, &rdata
);
5118 if (rdataset
->type
== dns_rdatatype_a
) {
5119 INSIST(rdata
.length
== sizeof(ina
.s_addr
));
5120 memcpy(&ina
.s_addr
, rdata
.data
, sizeof(ina
.s_addr
));
5121 isc_netaddr_fromin(&netaddr
, &ina
);
5123 INSIST(rdata
.length
== sizeof(in6a
.s6_addr
));
5124 memcpy(in6a
.s6_addr
, rdata
.data
, sizeof(in6a
.s6_addr
));
5125 isc_netaddr_fromin6(&netaddr
, &in6a
);
5128 result
= dns_acl_match(&netaddr
, NULL
, view
->denyansweracl
,
5129 &view
->aclenv
, &match
, NULL
);
5131 if (result
== ISC_R_SUCCESS
&& match
> 0) {
5132 isc_netaddr_format(&netaddr
, addrbuf
, sizeof(addrbuf
));
5133 dns_name_format(name
, namebuf
, sizeof(namebuf
));
5134 dns_rdatatype_format(rdataset
->type
, typebuf
,
5136 dns_rdataclass_format(rdataset
->rdclass
, classbuf
,
5138 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5139 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
5140 "answer address %s denied for %s/%s/%s",
5141 addrbuf
, namebuf
, typebuf
, classbuf
);
5149 static isc_boolean_t
5150 is_answertarget_allowed(dns_view_t
*view
, dns_name_t
*name
,
5151 dns_rdatatype_t type
, dns_name_t
*tname
,
5154 isc_result_t result
;
5155 dns_rbtnode_t
*node
= NULL
;
5156 char qnamebuf
[DNS_NAME_FORMATSIZE
];
5157 char tnamebuf
[DNS_NAME_FORMATSIZE
];
5161 /* By default, we allow any target name. */
5162 if (view
->denyanswernames
== NULL
)
5166 * If the owner name matches one in the exclusion list, either exactly
5167 * or partially, allow it.
5169 if (view
->answernames_exclude
!= NULL
) {
5170 result
= dns_rbt_findnode(view
->answernames_exclude
, name
, NULL
,
5171 &node
, NULL
, 0, NULL
, NULL
);
5172 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
5177 * If the target name is a subdomain of the search domain, allow it.
5179 if (dns_name_issubdomain(tname
, domain
))
5183 * Otherwise, apply filters.
5185 result
= dns_rbt_findnode(view
->denyanswernames
, tname
, NULL
, &node
,
5186 NULL
, 0, NULL
, NULL
);
5187 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
5188 dns_name_format(name
, qnamebuf
, sizeof(qnamebuf
));
5189 dns_name_format(tname
, tnamebuf
, sizeof(tnamebuf
));
5190 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
5191 dns_rdataclass_format(view
->rdclass
, classbuf
,
5193 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5194 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
5195 "%s target %s denied for %s/%s",
5196 typebuf
, tnamebuf
, qnamebuf
, classbuf
);
5204 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
5205 * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
5206 * section for the NS RRset if the query type is NS; if it has
5207 * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
5208 * section for A and AAAA queries.
5210 #define LOOK_FOR_NS_IN_ANSWER 0x1
5211 #define LOOK_FOR_GLUE_IN_ANSWER 0x2
5214 noanswer_response(fetchctx_t
*fctx
, dns_name_t
*oqname
,
5215 unsigned int look_in_options
)
5217 isc_result_t result
;
5218 dns_message_t
*message
;
5219 dns_name_t
*name
, *qname
, *ns_name
, *soa_name
, *ds_name
;
5220 dns_rdataset_t
*rdataset
, *ns_rdataset
;
5221 isc_boolean_t aa
, negative_response
;
5222 dns_rdatatype_t type
;
5223 dns_section_t section
;
5225 FCTXTRACE("noanswer_response");
5227 if ((look_in_options
& LOOK_FOR_NS_IN_ANSWER
) != 0) {
5228 INSIST(fctx
->type
== dns_rdatatype_ns
);
5229 section
= DNS_SECTION_ANSWER
;
5231 section
= DNS_SECTION_AUTHORITY
;
5233 message
= fctx
->rmessage
;
5238 if (oqname
== NULL
) {
5240 * We have a normal, non-chained negative response or
5243 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
5247 qname
= &fctx
->name
;
5250 * We're being invoked by answer_response() after it has
5251 * followed a CNAME/DNAME chain.
5256 * If the current qname is not a subdomain of the query
5257 * domain, there's no point in looking at the authority
5258 * section without doing DNSSEC validation.
5260 * Until we do that validation, we'll just return success
5263 if (!dns_name_issubdomain(qname
, &fctx
->domain
))
5264 return (ISC_R_SUCCESS
);
5268 * We have to figure out if this is a negative response, or a
5273 * Sometimes we can tell if its a negative response by looking at
5274 * the message header.
5276 negative_response
= ISC_FALSE
;
5277 if (message
->rcode
== dns_rcode_nxdomain
||
5278 (message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
5279 message
->counts
[DNS_SECTION_AUTHORITY
] == 0))
5280 negative_response
= ISC_TRUE
;
5283 * Process the authority section.
5289 result
= dns_message_firstname(message
, section
);
5290 while (result
== ISC_R_SUCCESS
) {
5292 dns_message_currentname(message
, section
, &name
);
5293 if (dns_name_issubdomain(name
, &fctx
->domain
)) {
5295 * Look for NS/SOA RRsets first.
5297 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5299 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5300 type
= rdataset
->type
;
5301 if (type
== dns_rdatatype_rrsig
)
5302 type
= rdataset
->covers
;
5303 if (((type
== dns_rdatatype_ns
||
5304 type
== dns_rdatatype_soa
) &&
5305 !dns_name_issubdomain(qname
, name
))) {
5306 char qbuf
[DNS_NAME_FORMATSIZE
];
5307 char nbuf
[DNS_NAME_FORMATSIZE
];
5308 char tbuf
[DNS_RDATATYPE_FORMATSIZE
];
5309 dns_rdatatype_format(fctx
->type
, tbuf
,
5311 dns_name_format(name
, nbuf
,
5313 dns_name_format(qname
, qbuf
,
5316 "unrelated %s %s in "
5317 "%s authority section",
5319 return (DNS_R_FORMERR
);
5321 if (type
== dns_rdatatype_ns
) {
5325 * Only one set of NS RRs is allowed.
5327 if (rdataset
->type
==
5329 if (ns_name
!= NULL
&&
5336 return (DNS_R_FORMERR
);
5339 ns_rdataset
= rdataset
;
5343 rdataset
->attributes
|=
5344 DNS_RDATASETATTR_CACHE
;
5345 rdataset
->trust
= dns_trust_glue
;
5347 if (type
== dns_rdatatype_soa
) {
5349 * SOA, or RRSIG SOA.
5351 * Only one SOA is allowed.
5353 if (rdataset
->type
==
5354 dns_rdatatype_soa
) {
5355 if (soa_name
!= NULL
&&
5362 return (DNS_R_FORMERR
);
5367 DNS_NAMEATTR_NCACHE
;
5368 rdataset
->attributes
|=
5369 DNS_RDATASETATTR_NCACHE
;
5372 dns_trust_authauthority
;
5375 dns_trust_additional
;
5379 result
= dns_message_nextname(message
, section
);
5380 if (result
== ISC_R_NOMORE
)
5382 else if (result
!= ISC_R_SUCCESS
)
5387 * A negative response has a SOA record (Type 2)
5388 * and a optional NS RRset (Type 1) or it has neither
5389 * a SOA or a NS RRset (Type 3, handled above) or
5390 * rcode is NXDOMAIN (handled above) in which case
5391 * the NS RRset is allowed (Type 4).
5393 if (soa_name
!= NULL
)
5394 negative_response
= ISC_TRUE
;
5396 result
= dns_message_firstname(message
, section
);
5397 while (result
== ISC_R_SUCCESS
) {
5399 dns_message_currentname(message
, section
, &name
);
5400 if (dns_name_issubdomain(name
, &fctx
->domain
)) {
5401 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5403 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5404 type
= rdataset
->type
;
5405 if (type
== dns_rdatatype_rrsig
)
5406 type
= rdataset
->covers
;
5407 if (type
== dns_rdatatype_nsec
||
5408 type
== dns_rdatatype_nsec3
) {
5410 * NSEC or RRSIG NSEC.
5412 if (negative_response
) {
5414 DNS_NAMEATTR_NCACHE
;
5415 rdataset
->attributes
|=
5416 DNS_RDATASETATTR_NCACHE
;
5417 } else if (type
== dns_rdatatype_nsec
) {
5420 rdataset
->attributes
|=
5421 DNS_RDATASETATTR_CACHE
;
5425 dns_trust_authauthority
;
5428 dns_trust_additional
;
5430 * No additional data needs to be
5433 } else if (type
== dns_rdatatype_ds
) {
5437 * These should only be here if
5438 * this is a referral, and there
5439 * should only be one DS RRset.
5441 if (ns_name
== NULL
) {
5445 return (DNS_R_FORMERR
);
5447 if (rdataset
->type
==
5449 if (ds_name
!= NULL
&&
5456 return (DNS_R_FORMERR
);
5462 rdataset
->attributes
|=
5463 DNS_RDATASETATTR_CACHE
;
5466 dns_trust_authauthority
;
5469 dns_trust_additional
;
5473 result
= dns_message_nextname(message
, section
);
5474 if (result
== ISC_R_NOMORE
)
5476 else if (result
!= ISC_R_SUCCESS
)
5481 * Trigger lookups for DNS nameservers.
5483 if (negative_response
&& message
->rcode
== dns_rcode_noerror
&&
5484 fctx
->type
== dns_rdatatype_ds
&& soa_name
!= NULL
&&
5485 dns_name_equal(soa_name
, qname
) &&
5486 !dns_name_equal(qname
, dns_rootname
))
5487 return (DNS_R_CHASEDSSERVERS
);
5490 * Did we find anything?
5492 if (!negative_response
&& ns_name
== NULL
) {
5496 if (oqname
!= NULL
) {
5498 * We've already got a partial CNAME/DNAME chain,
5499 * and haven't found else anything useful here, but
5500 * no error has occurred since we have an answer.
5502 return (ISC_R_SUCCESS
);
5505 * The responder is insane.
5507 log_formerr(fctx
, "invalid response");
5508 return (DNS_R_FORMERR
);
5513 * If we found both NS and SOA, they should be the same name.
5515 if (ns_name
!= NULL
&& soa_name
!= NULL
&& ns_name
!= soa_name
) {
5516 log_formerr(fctx
, "NS/SOA mismatch");
5517 return (DNS_R_FORMERR
);
5521 * Do we have a referral? (We only want to follow a referral if
5522 * we're not following a chain.)
5524 if (!negative_response
&& ns_name
!= NULL
&& oqname
== NULL
) {
5526 * We already know ns_name is a subdomain of fctx->domain.
5527 * If ns_name is equal to fctx->domain, we're not making
5528 * progress. We return DNS_R_FORMERR so that we'll keep
5529 * trying other servers.
5531 if (dns_name_equal(ns_name
, &fctx
->domain
)) {
5532 log_formerr(fctx
, "sideways referral");
5533 return (DNS_R_FORMERR
);
5537 * If the referral name is not a parent of the query
5538 * name, consider the responder insane.
5540 if (! dns_name_issubdomain(&fctx
->name
, ns_name
)) {
5542 log_formerr(fctx
, "referral to non-parent");
5543 FCTXTRACE("referral to non-parent");
5544 return (DNS_R_FORMERR
);
5548 * Mark any additional data related to this rdataset.
5549 * It's important that we do this before we change the
5552 INSIST(ns_rdataset
!= NULL
);
5553 fctx
->attributes
|= FCTX_ATTR_GLUING
;
5554 (void)dns_rdataset_additionaldata(ns_rdataset
, check_related
,
5556 #if CHECK_FOR_GLUE_IN_ANSWER
5558 * Look in the answer section for "glue" that is incorrectly
5559 * returned as a answer. This is needed if the server also
5560 * minimizes the response size by not adding records to the
5561 * additional section that are in the answer section or if
5562 * the record gets dropped due to message size constraints.
5564 if ((look_in_options
& LOOK_FOR_GLUE_IN_ANSWER
) != 0 &&
5565 (fctx
->type
== dns_rdatatype_aaaa
||
5566 fctx
->type
== dns_rdatatype_a
))
5567 (void)dns_rdataset_additionaldata(ns_rdataset
,
5568 check_answer
, fctx
);
5570 fctx
->attributes
&= ~FCTX_ATTR_GLUING
;
5572 * NS rdatasets with 0 TTL cause problems.
5573 * dns_view_findzonecut() will not find them when we
5574 * try to follow the referral, and we'll SERVFAIL
5575 * because the best nameservers are now above QDOMAIN.
5576 * We force the TTL to 1 second to prevent this.
5578 if (ns_rdataset
->ttl
== 0)
5579 ns_rdataset
->ttl
= 1;
5581 * Set the current query domain to the referral name.
5583 * XXXRTH We should check if we're in forward-only mode, and
5584 * if so we should bail out.
5586 INSIST(dns_name_countlabels(&fctx
->domain
) > 0);
5587 dns_name_free(&fctx
->domain
,
5588 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
);
5589 if (dns_rdataset_isassociated(&fctx
->nameservers
))
5590 dns_rdataset_disassociate(&fctx
->nameservers
);
5591 dns_name_init(&fctx
->domain
, NULL
);
5592 result
= dns_name_dup(ns_name
,
5593 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
5595 if (result
!= ISC_R_SUCCESS
)
5597 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
5598 return (DNS_R_DELEGATION
);
5602 * Since we're not doing a referral, we don't want to cache any
5603 * NS RRs we may have found.
5605 if (ns_name
!= NULL
)
5606 ns_name
->attributes
&= ~DNS_NAMEATTR_CACHE
;
5608 if (negative_response
&& oqname
== NULL
)
5609 fctx
->attributes
|= FCTX_ATTR_WANTNCACHE
;
5611 return (ISC_R_SUCCESS
);
5615 answer_response(fetchctx_t
*fctx
) {
5616 isc_result_t result
;
5617 dns_message_t
*message
;
5618 dns_name_t
*name
, *qname
, tname
;
5619 dns_rdataset_t
*rdataset
;
5620 isc_boolean_t done
, external
, chaining
, aa
, found
, want_chaining
;
5621 isc_boolean_t have_answer
, found_cname
, found_type
, wanted_chaining
;
5623 dns_rdatatype_t type
;
5624 dns_fixedname_t dname
, fqname
;
5627 FCTXTRACE("answer_response");
5629 message
= fctx
->rmessage
;
5632 * Examine the answer section, marking those rdatasets which are
5633 * part of the answer and should be cached.
5637 found_cname
= ISC_FALSE
;
5638 found_type
= ISC_FALSE
;
5639 chaining
= ISC_FALSE
;
5640 have_answer
= ISC_FALSE
;
5641 want_chaining
= ISC_FALSE
;
5642 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
5646 qname
= &fctx
->name
;
5648 view
= fctx
->res
->view
;
5649 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
5650 while (!done
&& result
== ISC_R_SUCCESS
) {
5652 dns_message_currentname(message
, DNS_SECTION_ANSWER
, &name
);
5653 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
5654 if (dns_name_equal(name
, qname
)) {
5655 wanted_chaining
= ISC_FALSE
;
5656 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5658 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5660 want_chaining
= ISC_FALSE
;
5662 if (rdataset
->type
== dns_rdatatype_nsec3
) {
5664 * NSEC3 records are not allowed to
5665 * appear in the answer section.
5667 log_formerr(fctx
, "NSEC3 in answer");
5668 return (DNS_R_FORMERR
);
5672 * Apply filters, if given, on answers to reject
5673 * a malicious attempt of rebinding.
5675 if ((rdataset
->type
== dns_rdatatype_a
||
5676 rdataset
->type
== dns_rdatatype_aaaa
) &&
5677 !is_answeraddress_allowed(view
, name
,
5679 return (DNS_R_SERVFAIL
);
5682 if (rdataset
->type
== type
&& !found_cname
) {
5684 * We've found an ordinary answer.
5687 found_type
= ISC_TRUE
;
5689 aflag
= DNS_RDATASETATTR_ANSWER
;
5690 } else if (type
== dns_rdatatype_any
) {
5692 * We've found an answer matching
5693 * an ANY query. There may be
5697 aflag
= DNS_RDATASETATTR_ANSWER
;
5698 } else if (rdataset
->type
== dns_rdatatype_rrsig
5699 && rdataset
->covers
== type
5702 * We've found a signature that
5703 * covers the type we're looking for.
5706 found_type
= ISC_TRUE
;
5707 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5708 } else if (rdataset
->type
==
5712 * We're looking for something else,
5713 * but we found a CNAME.
5715 * Getting a CNAME response for some
5716 * query types is an error.
5718 if (type
== dns_rdatatype_rrsig
||
5719 type
== dns_rdatatype_dnskey
||
5720 type
== dns_rdatatype_nsec
||
5721 type
== dns_rdatatype_nsec3
) {
5722 char buf
[DNS_RDATATYPE_FORMATSIZE
];
5723 dns_rdatatype_format(fctx
->type
,
5728 return (DNS_R_FORMERR
);
5731 found_cname
= ISC_TRUE
;
5732 want_chaining
= ISC_TRUE
;
5733 aflag
= DNS_RDATASETATTR_ANSWER
;
5734 result
= cname_target(rdataset
,
5736 if (result
!= ISC_R_SUCCESS
)
5738 /* Apply filters on the target name. */
5739 if (!is_answertarget_allowed(view
,
5744 return (DNS_R_SERVFAIL
);
5746 } else if (rdataset
->type
== dns_rdatatype_rrsig
5747 && rdataset
->covers
==
5751 * We're looking for something else,
5752 * but we found a SIG CNAME.
5755 found_cname
= ISC_TRUE
;
5756 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5761 * We've found an answer to our
5766 rdataset
->attributes
|=
5767 DNS_RDATASETATTR_CACHE
;
5768 rdataset
->trust
= dns_trust_answer
;
5771 * This data is "the" answer
5772 * to our question only if
5773 * we're not chaining (i.e.
5774 * if we haven't followed
5775 * a CNAME or DNAME).
5779 DNS_RDATASETATTR_ANSWER
)
5780 have_answer
= ISC_TRUE
;
5782 DNS_NAMEATTR_ANSWER
;
5783 rdataset
->attributes
|= aflag
;
5786 dns_trust_authanswer
;
5787 } else if (external
) {
5789 * This data is outside of
5790 * our query domain, and
5791 * may only be cached if it
5792 * comes from a secure zone
5795 rdataset
->attributes
|=
5796 DNS_RDATASETATTR_EXTERNAL
;
5800 * Mark any additional data related
5803 (void)dns_rdataset_additionaldata(
5811 if (want_chaining
) {
5812 wanted_chaining
= ISC_TRUE
;
5814 DNS_NAMEATTR_CHAINING
;
5815 rdataset
->attributes
|=
5816 DNS_RDATASETATTR_CHAINING
;
5821 * We could add an "else" clause here and
5822 * log that we're ignoring this rdataset.
5826 * If wanted_chaining is true, we've done
5827 * some chaining as the result of processing
5828 * this node, and thus we need to set
5831 * We don't set chaining inside of the
5832 * rdataset loop because doing that would
5833 * cause us to ignore the signatures of
5836 if (wanted_chaining
)
5837 chaining
= ISC_TRUE
;
5840 * Look for a DNAME (or its SIG). Anything else is
5843 wanted_chaining
= ISC_FALSE
;
5844 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5846 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5847 isc_boolean_t found_dname
= ISC_FALSE
;
5848 dns_name_t
*dname_name
;
5852 if (rdataset
->type
== dns_rdatatype_dname
) {
5854 * We're looking for something else,
5855 * but we found a DNAME.
5857 * If we're not chaining, then the
5858 * DNAME should not be external.
5860 if (!chaining
&& external
) {
5863 return (DNS_R_FORMERR
);
5866 want_chaining
= ISC_TRUE
;
5867 aflag
= DNS_RDATASETATTR_ANSWER
;
5868 result
= dname_target(fctx
, rdataset
,
5871 if (result
== ISC_R_NOSPACE
) {
5873 * We can't construct the
5874 * DNAME target. Do not
5877 want_chaining
= ISC_FALSE
;
5878 } else if (result
!= ISC_R_SUCCESS
)
5881 found_dname
= ISC_TRUE
;
5883 dname_name
= dns_fixedname_name(&dname
);
5884 if (!is_answertarget_allowed(view
,
5889 return (DNS_R_SERVFAIL
);
5891 } else if (rdataset
->type
== dns_rdatatype_rrsig
5892 && rdataset
->covers
==
5893 dns_rdatatype_dname
) {
5895 * We've found a signature that
5899 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5904 * We've found an answer to our
5909 rdataset
->attributes
|=
5910 DNS_RDATASETATTR_CACHE
;
5911 rdataset
->trust
= dns_trust_answer
;
5914 * This data is "the" answer
5915 * to our question only if
5916 * we're not chaining.
5920 DNS_RDATASETATTR_ANSWER
)
5921 have_answer
= ISC_TRUE
;
5923 DNS_NAMEATTR_ANSWER
;
5924 rdataset
->attributes
|= aflag
;
5927 dns_trust_authanswer
;
5928 } else if (external
) {
5929 rdataset
->attributes
|=
5930 DNS_RDATASETATTR_EXTERNAL
;
5938 * Copy the dname into the
5941 * Although we check for
5942 * failure of the copy
5943 * operation, in practice it
5944 * should never fail since
5945 * we already know that the
5946 * result fits in a fixedname.
5948 dns_fixedname_init(&fqname
);
5949 result
= dns_name_copy(
5950 dns_fixedname_name(&dname
),
5951 dns_fixedname_name(&fqname
),
5953 if (result
!= ISC_R_SUCCESS
)
5955 wanted_chaining
= ISC_TRUE
;
5957 DNS_NAMEATTR_CHAINING
;
5958 rdataset
->attributes
|=
5959 DNS_RDATASETATTR_CHAINING
;
5960 qname
= dns_fixedname_name(
5965 if (wanted_chaining
)
5966 chaining
= ISC_TRUE
;
5968 result
= dns_message_nextname(message
, DNS_SECTION_ANSWER
);
5970 if (result
== ISC_R_NOMORE
)
5971 result
= ISC_R_SUCCESS
;
5972 if (result
!= ISC_R_SUCCESS
)
5976 * We should have found an answer.
5979 log_formerr(fctx
, "reply has no answer");
5980 return (DNS_R_FORMERR
);
5984 * This response is now potentially cacheable.
5986 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
5989 * Did chaining end before we got the final answer?
5993 * Yes. This may be a negative reply, so hand off
5994 * authority section processing to the noanswer code.
5995 * If it isn't a noanswer response, no harm will be
5998 return (noanswer_response(fctx
, qname
, 0));
6002 * We didn't end with an incomplete chain, so the rcode should be
6005 if (message
->rcode
!= dns_rcode_noerror
) {
6006 log_formerr(fctx
, "CNAME/DNAME chain complete, but RCODE "
6008 return (DNS_R_FORMERR
);
6012 * Examine the authority section (if there is one).
6014 * We expect there to be only one owner name for all the rdatasets
6015 * in this section, and we expect that it is not external.
6018 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
6019 while (!done
&& result
== ISC_R_SUCCESS
) {
6021 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
6022 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
6025 * We expect to find NS or SIG NS rdatasets, and
6028 for (rdataset
= ISC_LIST_HEAD(name
->list
);
6030 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
6031 if (rdataset
->type
== dns_rdatatype_ns
||
6032 (rdataset
->type
== dns_rdatatype_rrsig
&&
6033 rdataset
->covers
== dns_rdatatype_ns
)) {
6036 rdataset
->attributes
|=
6037 DNS_RDATASETATTR_CACHE
;
6038 if (aa
&& !chaining
)
6040 dns_trust_authauthority
;
6043 dns_trust_additional
;
6046 * Mark any additional data related
6049 (void)dns_rdataset_additionaldata(
6057 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
6059 if (result
== ISC_R_NOMORE
)
6060 result
= ISC_R_SUCCESS
;
6066 resume_dslookup(isc_task_t
*task
, isc_event_t
*event
) {
6067 dns_fetchevent_t
*fevent
;
6068 dns_resolver_t
*res
;
6070 isc_result_t result
;
6071 isc_boolean_t bucket_empty
= ISC_FALSE
;
6072 isc_boolean_t locked
= ISC_FALSE
;
6073 unsigned int bucketnum
;
6074 dns_rdataset_t nameservers
;
6075 dns_fixedname_t fixed
;
6078 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
6079 fevent
= (dns_fetchevent_t
*)event
;
6080 fctx
= event
->ev_arg
;
6081 REQUIRE(VALID_FCTX(fctx
));
6085 FCTXTRACE("resume_dslookup");
6087 if (fevent
->node
!= NULL
)
6088 dns_db_detachnode(fevent
->db
, &fevent
->node
);
6089 if (fevent
->db
!= NULL
)
6090 dns_db_detach(&fevent
->db
);
6092 dns_rdataset_init(&nameservers
);
6094 bucketnum
= fctx
->bucketnum
;
6095 if (fevent
->result
== ISC_R_CANCELED
) {
6096 dns_resolver_destroyfetch(&fctx
->nsfetch
);
6097 fctx_done(fctx
, ISC_R_CANCELED
, __LINE__
);
6098 } else if (fevent
->result
== ISC_R_SUCCESS
) {
6100 FCTXTRACE("resuming DS lookup");
6102 dns_resolver_destroyfetch(&fctx
->nsfetch
);
6103 if (dns_rdataset_isassociated(&fctx
->nameservers
))
6104 dns_rdataset_disassociate(&fctx
->nameservers
);
6105 dns_rdataset_clone(fevent
->rdataset
, &fctx
->nameservers
);
6106 dns_name_free(&fctx
->domain
,
6107 fctx
->res
->buckets
[bucketnum
].mctx
);
6108 dns_name_init(&fctx
->domain
, NULL
);
6109 result
= dns_name_dup(&fctx
->nsname
,
6110 fctx
->res
->buckets
[bucketnum
].mctx
,
6112 if (result
!= ISC_R_SUCCESS
) {
6113 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6119 fctx_try(fctx
, ISC_TRUE
);
6122 dns_rdataset_t
*nsrdataset
= NULL
;
6125 * Retrieve state from fctx->nsfetch before we destroy it.
6127 dns_fixedname_init(&fixed
);
6128 domain
= dns_fixedname_name(&fixed
);
6129 dns_name_copy(&fctx
->nsfetch
->private->domain
, domain
, NULL
);
6130 if (dns_name_equal(&fctx
->nsname
, domain
)) {
6131 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6132 dns_resolver_destroyfetch(&fctx
->nsfetch
);
6135 if (dns_rdataset_isassociated(
6136 &fctx
->nsfetch
->private->nameservers
)) {
6138 &fctx
->nsfetch
->private->nameservers
,
6140 nsrdataset
= &nameservers
;
6143 dns_resolver_destroyfetch(&fctx
->nsfetch
);
6144 n
= dns_name_countlabels(&fctx
->nsname
);
6145 dns_name_getlabelsequence(&fctx
->nsname
, 1, n
- 1,
6148 if (dns_rdataset_isassociated(fevent
->rdataset
))
6149 dns_rdataset_disassociate(fevent
->rdataset
);
6150 FCTXTRACE("continuing to look for parent's NS records");
6151 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
6152 dns_rdatatype_ns
, domain
,
6153 nsrdataset
, NULL
, 0, task
,
6154 resume_dslookup
, fctx
,
6155 &fctx
->nsrrset
, NULL
,
6157 if (result
!= ISC_R_SUCCESS
)
6158 fctx_done(fctx
, result
, __LINE__
);
6160 LOCK(&res
->buckets
[bucketnum
].lock
);
6167 if (dns_rdataset_isassociated(&nameservers
))
6168 dns_rdataset_disassociate(&nameservers
);
6169 if (dns_rdataset_isassociated(fevent
->rdataset
))
6170 dns_rdataset_disassociate(fevent
->rdataset
);
6171 INSIST(fevent
->sigrdataset
== NULL
);
6172 isc_event_free(&event
);
6174 LOCK(&res
->buckets
[bucketnum
].lock
);
6176 if (fctx
->references
== 0)
6177 bucket_empty
= fctx_destroy(fctx
);
6178 UNLOCK(&res
->buckets
[bucketnum
].lock
);
6184 checknamessection(dns_message_t
*message
, dns_section_t section
) {
6185 isc_result_t result
;
6187 dns_rdata_t rdata
= DNS_RDATA_INIT
;
6188 dns_rdataset_t
*rdataset
;
6190 for (result
= dns_message_firstname(message
, section
);
6191 result
== ISC_R_SUCCESS
;
6192 result
= dns_message_nextname(message
, section
))
6195 dns_message_currentname(message
, section
, &name
);
6196 for (rdataset
= ISC_LIST_HEAD(name
->list
);
6198 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
6199 for (result
= dns_rdataset_first(rdataset
);
6200 result
== ISC_R_SUCCESS
;
6201 result
= dns_rdataset_next(rdataset
)) {
6202 dns_rdataset_current(rdataset
, &rdata
);
6203 if (!dns_rdata_checkowner(name
, rdata
.rdclass
,
6206 !dns_rdata_checknames(&rdata
, name
, NULL
))
6208 rdataset
->attributes
|=
6209 DNS_RDATASETATTR_CHECKNAMES
;
6211 dns_rdata_reset(&rdata
);
6218 checknames(dns_message_t
*message
) {
6220 checknamessection(message
, DNS_SECTION_ANSWER
);
6221 checknamessection(message
, DNS_SECTION_AUTHORITY
);
6222 checknamessection(message
, DNS_SECTION_ADDITIONAL
);
6226 * Log server NSID at log level 'level'
6229 log_nsid(dns_rdataset_t
*opt
, resquery_t
*query
, int level
, isc_mem_t
*mctx
)
6231 static const char hex
[17] = "0123456789abcdef";
6232 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
6233 isc_uint16_t optcode
, nsid_len
, buflen
, i
;
6234 isc_result_t result
;
6235 isc_buffer_t nsidbuf
;
6237 unsigned char *p
, *buf
, *nsid
;
6239 /* Extract rdata from OPT rdataset */
6240 result
= dns_rdataset_first(opt
);
6241 if (result
!= ISC_R_SUCCESS
)
6242 return (ISC_R_FAILURE
);
6244 dns_rdata_init(&rdata
);
6245 dns_rdataset_current(opt
, &rdata
);
6246 if (rdata
.length
< 4)
6247 return (ISC_R_FAILURE
);
6249 /* Check for NSID */
6250 isc_buffer_init(&nsidbuf
, rdata
.data
, rdata
.length
);
6251 isc_buffer_add(&nsidbuf
, rdata
.length
);
6252 optcode
= isc_buffer_getuint16(&nsidbuf
);
6253 nsid_len
= isc_buffer_getuint16(&nsidbuf
);
6254 if (optcode
!= DNS_OPT_NSID
|| nsid_len
== 0)
6255 return (ISC_R_FAILURE
);
6257 /* Allocate buffer for storing hex version of the NSID */
6258 buflen
= nsid_len
* 2 + 1;
6259 buf
= isc_mem_get(mctx
, buflen
);
6261 return (ISC_R_NOSPACE
);
6263 /* Convert to hex */
6265 nsid
= rdata
.data
+ 4;
6266 for (i
= 0; i
< nsid_len
; i
++) {
6267 *p
++ = hex
[(nsid
[0] >> 4) & 0xf];
6268 *p
++ = hex
[nsid
[0] & 0xf];
6273 isc_sockaddr_format(&query
->addrinfo
->sockaddr
, addrbuf
,
6275 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6276 DNS_LOGMODULE_RESOLVER
, level
,
6277 "received NSID '%s' from %s", buf
, addrbuf
);
6280 isc_mem_put(mctx
, buf
, buflen
);
6281 return (ISC_R_SUCCESS
);
6285 log_packet(dns_message_t
*message
, int level
, isc_mem_t
*mctx
) {
6286 isc_buffer_t buffer
;
6289 isc_result_t result
;
6291 if (! isc_log_wouldlog(dns_lctx
, level
))
6295 * Note that these are multiline debug messages. We want a newline
6296 * to appear in the log after each message.
6300 buf
= isc_mem_get(mctx
, len
);
6303 isc_buffer_init(&buffer
, buf
, len
);
6304 result
= dns_message_totext(message
, &dns_master_style_debug
,
6306 if (result
== ISC_R_NOSPACE
) {
6307 isc_mem_put(mctx
, buf
, len
);
6309 } else if (result
== ISC_R_SUCCESS
)
6310 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6311 DNS_LOGMODULE_RESOLVER
, level
,
6312 "received packet:\n%.*s",
6313 (int)isc_buffer_usedlength(&buffer
),
6315 } while (result
== ISC_R_NOSPACE
);
6318 isc_mem_put(mctx
, buf
, len
);
6321 static isc_boolean_t
6322 iscname(fetchctx_t
*fctx
) {
6323 isc_result_t result
;
6325 result
= dns_message_findname(fctx
->rmessage
, DNS_SECTION_ANSWER
,
6326 &fctx
->name
, dns_rdatatype_cname
, 0,
6328 return (result
== ISC_R_SUCCESS
? ISC_TRUE
: ISC_FALSE
);
6332 resquery_response(isc_task_t
*task
, isc_event_t
*event
) {
6333 isc_result_t result
= ISC_R_SUCCESS
;
6334 resquery_t
*query
= event
->ev_arg
;
6335 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
6336 isc_boolean_t keep_trying
, get_nameservers
, resend
;
6337 isc_boolean_t truncated
;
6338 dns_message_t
*message
;
6339 dns_rdataset_t
*opt
;
6342 dns_fixedname_t foundname
;
6344 isc_time_t tnow
, *finish
;
6345 dns_adbaddrinfo_t
*addrinfo
;
6346 unsigned int options
;
6347 unsigned int findoptions
;
6348 isc_result_t broken_server
;
6349 badnstype_t broken_type
= badns_response
;
6351 REQUIRE(VALID_QUERY(query
));
6353 options
= query
->options
;
6354 REQUIRE(VALID_FCTX(fctx
));
6355 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
6359 if (isc_sockaddr_pf(&query
->addrinfo
->sockaddr
) == PF_INET
)
6360 inc_stats(fctx
->res
, dns_resstatscounter_responsev4
);
6362 inc_stats(fctx
->res
, dns_resstatscounter_responsev6
);
6364 (void)isc_timer_touch(fctx
->timer
);
6366 keep_trying
= ISC_FALSE
;
6367 broken_server
= ISC_R_SUCCESS
;
6368 get_nameservers
= ISC_FALSE
;
6370 truncated
= ISC_FALSE
;
6373 if (fctx
->res
->exiting
) {
6374 result
= ISC_R_SHUTTINGDOWN
;
6379 fctx
->timeout
= ISC_FALSE
;
6380 fctx
->addrinfo
= query
->addrinfo
;
6383 * XXXRTH We should really get the current time just once. We
6384 * need a routine to convert from an isc_time_t to an
6389 isc_stdtime_get(&now
);
6392 * Did the dispatcher have a problem?
6394 if (devent
->result
!= ISC_R_SUCCESS
) {
6395 if (devent
->result
== ISC_R_EOF
&&
6396 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
6398 * The problem might be that they
6399 * don't understand EDNS0. Turn it
6400 * off and try again.
6402 options
|= DNS_FETCHOPT_NOEDNS0
;
6405 * Remember that they don't like EDNS0.
6407 dns_adb_changeflags(fctx
->adb
,
6409 DNS_FETCHOPT_NOEDNS0
,
6410 DNS_FETCHOPT_NOEDNS0
);
6413 * There's no hope for this query.
6415 keep_trying
= ISC_TRUE
;
6418 * If this is a network error on an exclusive query
6419 * socket, mark the server as bad so that we won't try
6420 * it for this fetch again.
6422 if (query
->exclusivesocket
&&
6423 (devent
->result
== ISC_R_HOSTUNREACH
||
6424 devent
->result
== ISC_R_NETUNREACH
||
6425 devent
->result
== ISC_R_CONNREFUSED
||
6426 devent
->result
== ISC_R_CANCELED
)) {
6427 broken_server
= devent
->result
;
6428 broken_type
= badns_unreachable
;
6434 message
= fctx
->rmessage
;
6436 if (query
->tsig
!= NULL
) {
6437 result
= dns_message_setquerytsig(message
, query
->tsig
);
6438 if (result
!= ISC_R_SUCCESS
)
6442 if (query
->tsigkey
) {
6443 result
= dns_message_settsigkey(message
, query
->tsigkey
);
6444 if (result
!= ISC_R_SUCCESS
)
6448 result
= dns_message_parse(message
, &devent
->buffer
, 0);
6449 if (result
!= ISC_R_SUCCESS
) {
6451 case ISC_R_UNEXPECTEDEND
:
6452 if (!message
->question_ok
||
6453 (message
->flags
& DNS_MESSAGEFLAG_TC
) == 0 ||
6454 (options
& DNS_FETCHOPT_TCP
) != 0) {
6456 * Either the message ended prematurely,
6457 * and/or wasn't marked as being truncated,
6458 * and/or this is a response to a query we
6459 * sent over TCP. In all of these cases,
6460 * something is wrong with the remote
6461 * server and we don't want to retry using
6464 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
)
6467 * The problem might be that they
6468 * don't understand EDNS0. Turn it
6469 * off and try again.
6471 options
|= DNS_FETCHOPT_NOEDNS0
;
6474 * Remember that they don't like EDNS0.
6476 dns_adb_changeflags(
6479 DNS_FETCHOPT_NOEDNS0
,
6480 DNS_FETCHOPT_NOEDNS0
);
6481 inc_stats(fctx
->res
,
6482 dns_resstatscounter_edns0fail
);
6484 broken_server
= result
;
6485 keep_trying
= ISC_TRUE
;
6490 * We defer retrying via TCP for a bit so we can
6491 * check out this message further.
6493 truncated
= ISC_TRUE
;
6496 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
6498 * The problem might be that they
6499 * don't understand EDNS0. Turn it
6500 * off and try again.
6502 options
|= DNS_FETCHOPT_NOEDNS0
;
6505 * Remember that they don't like EDNS0.
6507 dns_adb_changeflags(fctx
->adb
,
6509 DNS_FETCHOPT_NOEDNS0
,
6510 DNS_FETCHOPT_NOEDNS0
);
6511 inc_stats(fctx
->res
,
6512 dns_resstatscounter_edns0fail
);
6514 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6515 keep_trying
= ISC_TRUE
;
6520 * Something bad has happened.
6528 * Log the incoming packet.
6530 log_packet(message
, ISC_LOG_DEBUG(10), fctx
->res
->mctx
);
6533 * Did we request NSID? If so, and if the response contains
6534 * NSID data, log it at INFO level.
6536 opt
= dns_message_getopt(message
);
6537 if (opt
!= NULL
&& (query
->options
& DNS_FETCHOPT_WANTNSID
) != 0)
6538 log_nsid(opt
, query
, ISC_LOG_INFO
, fctx
->res
->mctx
);
6541 * If the message is signed, check the signature. If not, this
6542 * returns success anyway.
6544 result
= dns_message_checksig(message
, fctx
->res
->view
);
6545 if (result
!= ISC_R_SUCCESS
)
6549 * The dispatcher should ensure we only get responses with QR set.
6551 INSIST((message
->flags
& DNS_MESSAGEFLAG_QR
) != 0);
6553 * INSIST() that the message comes from the place we sent it to,
6554 * since the dispatch code should ensure this.
6556 * INSIST() that the message id is correct (this should also be
6557 * ensured by the dispatch code).
6562 * Deal with truncated responses by retrying using TCP.
6564 if ((message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
6565 truncated
= ISC_TRUE
;
6568 inc_stats(fctx
->res
, dns_resstatscounter_truncated
);
6569 if ((options
& DNS_FETCHOPT_TCP
) != 0) {
6570 broken_server
= DNS_R_TRUNCATEDTCP
;
6571 keep_trying
= ISC_TRUE
;
6573 options
|= DNS_FETCHOPT_TCP
;
6580 * Is it a query response?
6582 if (message
->opcode
!= dns_opcode_query
) {
6584 broken_server
= DNS_R_UNEXPECTEDOPCODE
;
6585 keep_trying
= ISC_TRUE
;
6590 * Update statistics about erroneous responses.
6592 if (message
->rcode
!= dns_rcode_noerror
) {
6593 switch (message
->rcode
) {
6594 case dns_rcode_nxdomain
:
6595 inc_stats(fctx
->res
, dns_resstatscounter_nxdomain
);
6597 case dns_rcode_servfail
:
6598 inc_stats(fctx
->res
, dns_resstatscounter_servfail
);
6600 case dns_rcode_formerr
:
6601 inc_stats(fctx
->res
, dns_resstatscounter_formerr
);
6604 inc_stats(fctx
->res
, dns_resstatscounter_othererror
);
6610 * Is the remote server broken, or does it dislike us?
6612 if (message
->rcode
!= dns_rcode_noerror
&&
6613 message
->rcode
!= dns_rcode_nxdomain
) {
6614 if (((message
->rcode
== dns_rcode_formerr
||
6615 message
->rcode
== dns_rcode_notimp
) ||
6616 (message
->rcode
== dns_rcode_servfail
&&
6617 dns_message_getopt(message
) == NULL
)) &&
6618 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
6620 * It's very likely they don't like EDNS0.
6621 * If the response code is SERVFAIL, also check if the
6622 * response contains an OPT RR and don't cache the
6623 * failure since it can be returned for various other
6626 * XXXRTH We should check if the question
6627 * we're asking requires EDNS0, and
6628 * if so, we should bail out.
6630 options
|= DNS_FETCHOPT_NOEDNS0
;
6633 * Remember that they don't like EDNS0.
6635 if (message
->rcode
!= dns_rcode_servfail
)
6636 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
6637 DNS_FETCHOPT_NOEDNS0
,
6638 DNS_FETCHOPT_NOEDNS0
);
6639 inc_stats(fctx
->res
, dns_resstatscounter_edns0fail
);
6640 } else if (message
->rcode
== dns_rcode_formerr
) {
6641 if (ISFORWARDER(query
->addrinfo
)) {
6643 * This forwarder doesn't understand us,
6644 * but other forwarders might. Keep trying.
6646 broken_server
= DNS_R_REMOTEFORMERR
;
6647 keep_trying
= ISC_TRUE
;
6650 * The server doesn't understand us. Since
6651 * all servers for a zone need similar
6652 * capabilities, we assume that we will get
6653 * FORMERR from all servers, and thus we
6654 * cannot make any more progress with this
6657 log_formerr(fctx
, "server sent FORMERR");
6658 result
= DNS_R_FORMERR
;
6660 } else if (message
->rcode
== dns_rcode_yxdomain
) {
6662 * DNAME mapping failed because the new name
6663 * was too long. There's no chance of success
6666 result
= DNS_R_YXDOMAIN
;
6667 } else if (message
->rcode
== dns_rcode_badvers
) {
6668 unsigned int flags
, mask
;
6669 unsigned int version
;
6672 version
= (opt
->ttl
>> 16) & 0xff;
6673 flags
= (version
<< DNS_FETCHOPT_EDNSVERSIONSHIFT
) |
6674 DNS_FETCHOPT_EDNSVERSIONSET
;
6675 mask
= DNS_FETCHOPT_EDNSVERSIONMASK
|
6676 DNS_FETCHOPT_EDNSVERSIONSET
;
6679 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
6683 broken_server
= DNS_R_BADVERS
;
6684 keep_trying
= ISC_TRUE
;
6691 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6692 INSIST(broken_server
!= ISC_R_SUCCESS
);
6693 keep_trying
= ISC_TRUE
;
6699 * Is the question the same as the one we asked?
6701 result
= same_question(fctx
);
6702 if (result
!= ISC_R_SUCCESS
) {
6704 if (result
== DNS_R_FORMERR
)
6705 keep_trying
= ISC_TRUE
;
6710 * Is the server lame?
6712 if (fctx
->res
->lame_ttl
!= 0 && !ISFORWARDER(query
->addrinfo
) &&
6714 inc_stats(fctx
->res
, dns_resstatscounter_lame
);
6715 log_lame(fctx
, query
->addrinfo
);
6716 result
= dns_adb_marklame(fctx
->adb
, query
->addrinfo
,
6717 &fctx
->name
, fctx
->type
,
6718 now
+ fctx
->res
->lame_ttl
);
6719 if (result
!= ISC_R_SUCCESS
)
6720 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6721 DNS_LOGMODULE_RESOLVER
, ISC_LOG_ERROR
,
6722 "could not mark server as lame: %s",
6723 isc_result_totext(result
));
6724 broken_server
= DNS_R_LAME
;
6725 keep_trying
= ISC_TRUE
;
6730 * Enforce delegations only zones like NET and COM.
6732 if (!ISFORWARDER(query
->addrinfo
) &&
6733 dns_view_isdelegationonly(fctx
->res
->view
, &fctx
->domain
) &&
6734 !dns_name_equal(&fctx
->domain
, &fctx
->name
) &&
6735 fix_mustbedelegationornxdomain(message
, fctx
)) {
6736 char namebuf
[DNS_NAME_FORMATSIZE
];
6737 char domainbuf
[DNS_NAME_FORMATSIZE
];
6738 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
6742 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
6743 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
6744 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
6745 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
,
6747 isc_sockaddr_format(&query
->addrinfo
->sockaddr
, addrbuf
,
6750 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DELEGATION_ONLY
,
6751 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
6752 "enforced delegation-only for '%s' (%s/%s/%s) "
6754 domainbuf
, namebuf
, typebuf
, classbuf
, addrbuf
);
6757 if ((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMES
) != 0)
6758 checknames(message
);
6763 fctx
->attributes
&= ~(FCTX_ATTR_WANTNCACHE
| FCTX_ATTR_WANTCACHE
);
6766 * Did we get any answers?
6768 if (message
->counts
[DNS_SECTION_ANSWER
] > 0 &&
6769 (message
->rcode
== dns_rcode_noerror
||
6770 message
->rcode
== dns_rcode_nxdomain
)) {
6773 * We've got answers. If it has an authoritative answer or an
6774 * answer from a forwarder, we're done.
6776 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0 ||
6777 ISFORWARDER(query
->addrinfo
))
6778 result
= answer_response(fctx
);
6779 else if (iscname(fctx
) &&
6780 fctx
->type
!= dns_rdatatype_any
&&
6781 fctx
->type
!= dns_rdatatype_cname
) {
6783 * A BIND8 server could return a non-authoritative
6784 * answer when a CNAME is followed. We should treat
6785 * it as a valid answer.
6787 result
= answer_response(fctx
);
6789 if (fctx
->type
== dns_rdatatype_ns
) {
6791 * A BIND 8 server could incorrectly return a
6792 * non-authoritative answer to an NS query
6793 * instead of a referral. Since this answer
6794 * lacks the SIGs necessary to do DNSSEC
6795 * validation, we must invoke the following
6796 * special kludge to treat it as a referral.
6798 result
= noanswer_response(fctx
, NULL
,
6799 LOOK_FOR_NS_IN_ANSWER
);
6802 * Some other servers may still somehow include
6803 * an answer when it should return a referral
6804 * with an empty answer. Check to see if we can
6805 * treat this as a referral by ignoring the
6806 * answer. Further more, there may be an
6807 * implementation that moves A/AAAA glue records
6808 * to the answer section for that type of
6809 * delegation when the query is for that glue
6810 * record. LOOK_FOR_GLUE_IN_ANSWER will handle
6811 * such a corner case.
6813 result
= noanswer_response(fctx
, NULL
,
6814 LOOK_FOR_GLUE_IN_ANSWER
);
6816 if (result
!= DNS_R_DELEGATION
) {
6818 * At this point, AA is not set, the response
6819 * is not a referral, and the server is not a
6820 * forwarder. It is technically lame and it's
6821 * easier to treat it as such than to figure out
6822 * some more elaborate course of action.
6824 broken_server
= DNS_R_LAME
;
6825 keep_trying
= ISC_TRUE
;
6828 goto force_referral
;
6830 if (result
!= ISC_R_SUCCESS
) {
6831 if (result
== DNS_R_FORMERR
)
6832 keep_trying
= ISC_TRUE
;
6835 } else if (message
->counts
[DNS_SECTION_AUTHORITY
] > 0 ||
6836 message
->rcode
== dns_rcode_noerror
||
6837 message
->rcode
== dns_rcode_nxdomain
) {
6839 * NXDOMAIN, NXRDATASET, or referral.
6841 result
= noanswer_response(fctx
, NULL
, 0);
6842 if (result
== DNS_R_CHASEDSSERVERS
) {
6843 } else if (result
== DNS_R_DELEGATION
) {
6846 * We don't have the answer, but we know a better
6849 get_nameservers
= ISC_TRUE
;
6850 keep_trying
= ISC_TRUE
;
6852 * We have a new set of name servers, and it
6853 * has not experienced any restarts yet.
6858 * Update local statistics counters collected for each
6862 fctx
->querysent
= 0;
6863 fctx
->lamecount
= 0;
6868 result
= ISC_R_SUCCESS
;
6869 } else if (result
!= ISC_R_SUCCESS
) {
6871 * Something has gone wrong.
6873 if (result
== DNS_R_FORMERR
)
6874 keep_trying
= ISC_TRUE
;
6879 * The server is insane.
6882 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6883 keep_trying
= ISC_TRUE
;
6888 * Follow additional section data chains.
6890 chase_additional(fctx
);
6893 * Cache the cacheable parts of the message. This may also cause
6894 * work to be queued to the DNSSEC validator.
6896 if (WANTCACHE(fctx
)) {
6897 result
= cache_message(fctx
, query
->addrinfo
, now
);
6898 if (result
!= ISC_R_SUCCESS
)
6903 * Ncache the negatively cacheable parts of the message. This may
6904 * also cause work to be queued to the DNSSEC validator.
6906 if (WANTNCACHE(fctx
)) {
6907 dns_rdatatype_t covers
;
6908 if (message
->rcode
== dns_rcode_nxdomain
)
6909 covers
= dns_rdatatype_any
;
6911 covers
= fctx
->type
;
6914 * Cache any negative cache entries in the message.
6916 result
= ncache_message(fctx
, query
->addrinfo
, covers
, now
);
6921 * Remember the query's addrinfo, in case we need to mark the
6924 addrinfo
= query
->addrinfo
;
6929 * XXXRTH Don't cancel the query if waiting for validation?
6931 fctx_cancelquery(&query
, &devent
, finish
, ISC_FALSE
);
6934 if (result
== DNS_R_FORMERR
)
6935 broken_server
= DNS_R_FORMERR
;
6936 if (broken_server
!= ISC_R_SUCCESS
) {
6938 * Add this server to the list of bad servers for
6941 add_bad(fctx
, addrinfo
, broken_server
, broken_type
);
6944 if (get_nameservers
) {
6946 dns_fixedname_init(&foundname
);
6947 fname
= dns_fixedname_name(&foundname
);
6948 if (result
!= ISC_R_SUCCESS
) {
6949 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6953 if (dns_rdatatype_atparent(fctx
->type
))
6954 findoptions
|= DNS_DBFIND_NOEXACT
;
6955 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0)
6958 name
= &fctx
->domain
;
6959 result
= dns_view_findzonecut(fctx
->res
->view
,
6965 if (result
!= ISC_R_SUCCESS
) {
6966 FCTXTRACE("couldn't find a zonecut");
6967 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6970 if (!dns_name_issubdomain(fname
, &fctx
->domain
)) {
6972 * The best nameservers are now above our
6975 FCTXTRACE("nameservers now above QDOMAIN");
6976 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6979 dns_name_free(&fctx
->domain
,
6980 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
);
6981 dns_name_init(&fctx
->domain
, NULL
);
6982 result
= dns_name_dup(fname
,
6983 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
6985 if (result
!= ISC_R_SUCCESS
) {
6986 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6989 fctx_cancelqueries(fctx
, ISC_TRUE
);
6990 fctx_cleanupfinds(fctx
);
6991 fctx_cleanupaltfinds(fctx
);
6992 fctx_cleanupforwaddrs(fctx
);
6993 fctx_cleanupaltaddrs(fctx
);
6998 fctx_try(fctx
, !get_nameservers
);
6999 } else if (resend
) {
7001 * Resend (probably with changed options).
7003 FCTXTRACE("resend");
7004 inc_stats(fctx
->res
, dns_resstatscounter_retry
);
7005 result
= fctx_query(fctx
, addrinfo
, options
);
7006 if (result
!= ISC_R_SUCCESS
)
7007 fctx_done(fctx
, result
, __LINE__
);
7008 } else if (result
== ISC_R_SUCCESS
&& !HAVE_ANSWER(fctx
)) {
7010 * All has gone well so far, but we are waiting for the
7011 * DNSSEC validator to validate the answer.
7013 FCTXTRACE("wait for validator");
7014 fctx_cancelqueries(fctx
, ISC_TRUE
);
7016 * We must not retransmit while the validator is working;
7017 * it has references to the current rmessage.
7019 result
= fctx_stopidletimer(fctx
);
7020 if (result
!= ISC_R_SUCCESS
)
7021 fctx_done(fctx
, result
, __LINE__
);
7022 } else if (result
== DNS_R_CHASEDSSERVERS
) {
7024 add_bad(fctx
, addrinfo
, result
, broken_type
);
7025 fctx_cancelqueries(fctx
, ISC_TRUE
);
7026 fctx_cleanupfinds(fctx
);
7027 fctx_cleanupforwaddrs(fctx
);
7029 n
= dns_name_countlabels(&fctx
->name
);
7030 dns_name_getlabelsequence(&fctx
->name
, 1, n
- 1, &fctx
->nsname
);
7032 FCTXTRACE("suspending DS lookup to find parent's NS records");
7034 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
7036 NULL
, NULL
, NULL
, 0, task
,
7037 resume_dslookup
, fctx
,
7038 &fctx
->nsrrset
, NULL
,
7040 if (result
!= ISC_R_SUCCESS
)
7041 fctx_done(fctx
, result
, __LINE__
);
7042 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
7044 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
7045 result
= fctx_stopidletimer(fctx
);
7046 if (result
!= ISC_R_SUCCESS
)
7047 fctx_done(fctx
, result
, __LINE__
);
7052 fctx_done(fctx
, result
, __LINE__
);
7058 *** Resolver Methods
7062 destroy(dns_resolver_t
*res
) {
7066 REQUIRE(res
->references
== 0);
7067 REQUIRE(!res
->priming
);
7068 REQUIRE(res
->primefetch
== NULL
);
7072 INSIST(res
->nfctx
== 0);
7074 DESTROYLOCK(&res
->primelock
);
7075 DESTROYLOCK(&res
->nlock
);
7076 DESTROYLOCK(&res
->lock
);
7077 for (i
= 0; i
< res
->nbuckets
; i
++) {
7078 INSIST(ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
));
7079 isc_task_shutdown(res
->buckets
[i
].task
);
7080 isc_task_detach(&res
->buckets
[i
].task
);
7081 DESTROYLOCK(&res
->buckets
[i
].lock
);
7082 isc_mem_detach(&res
->buckets
[i
].mctx
);
7084 isc_mem_put(res
->mctx
, res
->buckets
,
7085 res
->nbuckets
* sizeof(fctxbucket_t
));
7086 if (res
->dispatchv4
!= NULL
)
7087 dns_dispatch_detach(&res
->dispatchv4
);
7088 if (res
->dispatchv6
!= NULL
)
7089 dns_dispatch_detach(&res
->dispatchv6
);
7090 while ((a
= ISC_LIST_HEAD(res
->alternates
)) != NULL
) {
7091 ISC_LIST_UNLINK(res
->alternates
, a
, link
);
7093 dns_name_free(&a
->_u
._n
.name
, res
->mctx
);
7094 isc_mem_put(res
->mctx
, a
, sizeof(*a
));
7096 dns_resolver_reset_algorithms(res
);
7097 dns_resolver_resetmustbesecure(res
);
7099 isc_rwlock_destroy(&res
->alglock
);
7102 isc_rwlock_destroy(&res
->mbslock
);
7104 isc_timer_detach(&res
->spillattimer
);
7106 isc_mem_put(res
->mctx
, res
, sizeof(*res
));
7110 send_shutdown_events(dns_resolver_t
*res
) {
7111 isc_event_t
*event
, *next_event
;
7115 * Caller must be holding the resolver lock.
7118 for (event
= ISC_LIST_HEAD(res
->whenshutdown
);
7120 event
= next_event
) {
7121 next_event
= ISC_LIST_NEXT(event
, ev_link
);
7122 ISC_LIST_UNLINK(res
->whenshutdown
, event
, ev_link
);
7123 etask
= event
->ev_sender
;
7124 event
->ev_sender
= res
;
7125 isc_task_sendanddetach(&etask
, &event
);
7130 empty_bucket(dns_resolver_t
*res
) {
7131 RTRACE("empty_bucket");
7135 INSIST(res
->activebuckets
> 0);
7136 res
->activebuckets
--;
7137 if (res
->activebuckets
== 0)
7138 send_shutdown_events(res
);
7144 spillattimer_countdown(isc_task_t
*task
, isc_event_t
*event
) {
7145 dns_resolver_t
*res
= event
->ev_arg
;
7146 isc_result_t result
;
7148 isc_boolean_t logit
= ISC_FALSE
;
7150 REQUIRE(VALID_RESOLVER(res
));
7155 INSIST(!res
->exiting
);
7156 if (res
->spillat
> res
->spillatmin
) {
7160 if (res
->spillat
<= res
->spillatmin
) {
7161 result
= isc_timer_reset(res
->spillattimer
,
7162 isc_timertype_inactive
, NULL
,
7164 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
7166 count
= res
->spillat
;
7169 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
7170 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
7171 "clients-per-query decreased to %u", count
);
7173 isc_event_free(&event
);
7177 dns_resolver_create(dns_view_t
*view
,
7178 isc_taskmgr_t
*taskmgr
, unsigned int ntasks
,
7179 isc_socketmgr_t
*socketmgr
,
7180 isc_timermgr_t
*timermgr
,
7181 unsigned int options
,
7182 dns_dispatchmgr_t
*dispatchmgr
,
7183 dns_dispatch_t
*dispatchv4
,
7184 dns_dispatch_t
*dispatchv6
,
7185 dns_resolver_t
**resp
)
7187 dns_resolver_t
*res
;
7188 isc_result_t result
= ISC_R_SUCCESS
;
7189 unsigned int i
, buckets_created
= 0;
7190 isc_task_t
*task
= NULL
;
7195 * Create a resolver.
7198 REQUIRE(DNS_VIEW_VALID(view
));
7199 REQUIRE(ntasks
> 0);
7200 REQUIRE(resp
!= NULL
&& *resp
== NULL
);
7201 REQUIRE(dispatchmgr
!= NULL
);
7202 REQUIRE(dispatchv4
!= NULL
|| dispatchv6
!= NULL
);
7204 res
= isc_mem_get(view
->mctx
, sizeof(*res
));
7206 return (ISC_R_NOMEMORY
);
7208 res
->mctx
= view
->mctx
;
7209 res
->rdclass
= view
->rdclass
;
7210 res
->socketmgr
= socketmgr
;
7211 res
->timermgr
= timermgr
;
7212 res
->taskmgr
= taskmgr
;
7213 res
->dispatchmgr
= dispatchmgr
;
7215 res
->options
= options
;
7217 ISC_LIST_INIT(res
->alternates
);
7218 res
->udpsize
= RECV_BUFFER_SIZE
;
7219 res
->algorithms
= NULL
;
7220 res
->mustbesecure
= NULL
;
7221 res
->spillatmin
= res
->spillat
= 10;
7222 res
->spillatmax
= 100;
7223 res
->spillattimer
= NULL
;
7224 res
->zero_no_soa_ttl
= ISC_FALSE
;
7226 res
->nextdisp
= 0; /* meaningless at this point, but init it */
7227 res
->nbuckets
= ntasks
;
7228 res
->activebuckets
= ntasks
;
7229 res
->buckets
= isc_mem_get(view
->mctx
,
7230 ntasks
* sizeof(fctxbucket_t
));
7231 if (res
->buckets
== NULL
) {
7232 result
= ISC_R_NOMEMORY
;
7235 for (i
= 0; i
< ntasks
; i
++) {
7236 result
= isc_mutex_init(&res
->buckets
[i
].lock
);
7237 if (result
!= ISC_R_SUCCESS
)
7238 goto cleanup_buckets
;
7239 res
->buckets
[i
].task
= NULL
;
7240 result
= isc_task_create(taskmgr
, 0, &res
->buckets
[i
].task
);
7241 if (result
!= ISC_R_SUCCESS
) {
7242 DESTROYLOCK(&res
->buckets
[i
].lock
);
7243 goto cleanup_buckets
;
7245 res
->buckets
[i
].mctx
= NULL
;
7246 snprintf(name
, sizeof(name
), "res%u", i
);
7247 #ifdef ISC_PLATFORM_USETHREADS
7249 * Use a separate memory context for each bucket to reduce
7250 * contention among multiple threads. Do this only when
7251 * enabling threads because it will be require more memory.
7253 result
= isc_mem_create(0, 0, &res
->buckets
[i
].mctx
);
7254 if (result
!= ISC_R_SUCCESS
) {
7255 isc_task_detach(&res
->buckets
[i
].task
);
7256 DESTROYLOCK(&res
->buckets
[i
].lock
);
7257 goto cleanup_buckets
;
7259 isc_mem_setname(res
->buckets
[i
].mctx
, name
, NULL
);
7261 isc_mem_attach(view
->mctx
, &res
->buckets
[i
].mctx
);
7263 isc_task_setname(res
->buckets
[i
].task
, name
, res
);
7264 ISC_LIST_INIT(res
->buckets
[i
].fctxs
);
7265 res
->buckets
[i
].exiting
= ISC_FALSE
;
7269 res
->dispatchv4
= NULL
;
7270 if (dispatchv4
!= NULL
) {
7271 dns_dispatch_attach(dispatchv4
, &res
->dispatchv4
);
7272 dispattr
= dns_dispatch_getattributes(dispatchv4
);
7274 ISC_TF((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0);
7277 res
->dispatchv6
= NULL
;
7278 if (dispatchv6
!= NULL
) {
7279 dns_dispatch_attach(dispatchv6
, &res
->dispatchv6
);
7280 dispattr
= dns_dispatch_getattributes(dispatchv6
);
7282 ISC_TF((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0);
7285 res
->references
= 1;
7286 res
->exiting
= ISC_FALSE
;
7287 res
->frozen
= ISC_FALSE
;
7288 ISC_LIST_INIT(res
->whenshutdown
);
7289 res
->priming
= ISC_FALSE
;
7290 res
->primefetch
= NULL
;
7293 result
= isc_mutex_init(&res
->lock
);
7294 if (result
!= ISC_R_SUCCESS
)
7295 goto cleanup_dispatches
;
7297 result
= isc_mutex_init(&res
->nlock
);
7298 if (result
!= ISC_R_SUCCESS
)
7301 result
= isc_mutex_init(&res
->primelock
);
7302 if (result
!= ISC_R_SUCCESS
)
7306 result
= isc_task_create(taskmgr
, 0, &task
);
7307 if (result
!= ISC_R_SUCCESS
)
7308 goto cleanup_primelock
;
7310 result
= isc_timer_create(timermgr
, isc_timertype_inactive
, NULL
, NULL
,
7311 task
, spillattimer_countdown
, res
,
7312 &res
->spillattimer
);
7313 isc_task_detach(&task
);
7314 if (result
!= ISC_R_SUCCESS
)
7315 goto cleanup_primelock
;
7318 result
= isc_rwlock_init(&res
->alglock
, 0, 0);
7319 if (result
!= ISC_R_SUCCESS
)
7320 goto cleanup_spillattimer
;
7323 result
= isc_rwlock_init(&res
->mbslock
, 0, 0);
7324 if (result
!= ISC_R_SUCCESS
)
7325 goto cleanup_alglock
;
7328 res
->magic
= RES_MAGIC
;
7332 return (ISC_R_SUCCESS
);
7337 isc_rwlock_destroy(&res
->alglock
);
7340 #if USE_ALGLOCK || USE_MBSLOCK
7341 cleanup_spillattimer
:
7342 isc_timer_detach(&res
->spillattimer
);
7346 DESTROYLOCK(&res
->primelock
);
7349 DESTROYLOCK(&res
->nlock
);
7352 DESTROYLOCK(&res
->lock
);
7355 if (res
->dispatchv6
!= NULL
)
7356 dns_dispatch_detach(&res
->dispatchv6
);
7357 if (res
->dispatchv4
!= NULL
)
7358 dns_dispatch_detach(&res
->dispatchv4
);
7361 for (i
= 0; i
< buckets_created
; i
++) {
7362 isc_mem_detach(&res
->buckets
[i
].mctx
);
7363 DESTROYLOCK(&res
->buckets
[i
].lock
);
7364 isc_task_shutdown(res
->buckets
[i
].task
);
7365 isc_task_detach(&res
->buckets
[i
].task
);
7367 isc_mem_put(view
->mctx
, res
->buckets
,
7368 res
->nbuckets
* sizeof(fctxbucket_t
));
7371 isc_mem_put(view
->mctx
, res
, sizeof(*res
));
7378 prime_done(isc_task_t
*task
, isc_event_t
*event
) {
7379 dns_resolver_t
*res
;
7380 dns_fetchevent_t
*fevent
;
7382 dns_db_t
*db
= NULL
;
7384 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
7385 fevent
= (dns_fetchevent_t
*)event
;
7386 res
= event
->ev_arg
;
7387 REQUIRE(VALID_RESOLVER(res
));
7393 INSIST(res
->priming
);
7394 res
->priming
= ISC_FALSE
;
7395 LOCK(&res
->primelock
);
7396 fetch
= res
->primefetch
;
7397 res
->primefetch
= NULL
;
7398 UNLOCK(&res
->primelock
);
7402 if (fevent
->result
== ISC_R_SUCCESS
&&
7403 res
->view
->cache
!= NULL
&& res
->view
->hints
!= NULL
) {
7404 dns_cache_attachdb(res
->view
->cache
, &db
);
7405 dns_root_checkhints(res
->view
, res
->view
->hints
, db
);
7409 if (fevent
->node
!= NULL
)
7410 dns_db_detachnode(fevent
->db
, &fevent
->node
);
7411 if (fevent
->db
!= NULL
)
7412 dns_db_detach(&fevent
->db
);
7413 if (dns_rdataset_isassociated(fevent
->rdataset
))
7414 dns_rdataset_disassociate(fevent
->rdataset
);
7415 INSIST(fevent
->sigrdataset
== NULL
);
7417 isc_mem_put(res
->mctx
, fevent
->rdataset
, sizeof(*fevent
->rdataset
));
7419 isc_event_free(&event
);
7420 dns_resolver_destroyfetch(&fetch
);
7424 dns_resolver_prime(dns_resolver_t
*res
) {
7425 isc_boolean_t want_priming
= ISC_FALSE
;
7426 dns_rdataset_t
*rdataset
;
7427 isc_result_t result
;
7429 REQUIRE(VALID_RESOLVER(res
));
7430 REQUIRE(res
->frozen
);
7432 RTRACE("dns_resolver_prime");
7436 if (!res
->exiting
&& !res
->priming
) {
7437 INSIST(res
->primefetch
== NULL
);
7438 res
->priming
= ISC_TRUE
;
7439 want_priming
= ISC_TRUE
;
7446 * To avoid any possible recursive locking problems, we
7447 * start the priming fetch like any other fetch, and holding
7448 * no resolver locks. No one else will try to start it
7449 * because we're the ones who set res->priming to true.
7450 * Any other callers of dns_resolver_prime() while we're
7451 * running will see that res->priming is already true and
7455 rdataset
= isc_mem_get(res
->mctx
, sizeof(*rdataset
));
7456 if (rdataset
== NULL
) {
7458 INSIST(res
->priming
);
7459 INSIST(res
->primefetch
== NULL
);
7460 res
->priming
= ISC_FALSE
;
7464 dns_rdataset_init(rdataset
);
7465 LOCK(&res
->primelock
);
7466 result
= dns_resolver_createfetch(res
, dns_rootname
,
7468 NULL
, NULL
, NULL
, 0,
7469 res
->buckets
[0].task
,
7471 res
, rdataset
, NULL
,
7473 UNLOCK(&res
->primelock
);
7474 if (result
!= ISC_R_SUCCESS
) {
7476 INSIST(res
->priming
);
7477 res
->priming
= ISC_FALSE
;
7485 dns_resolver_freeze(dns_resolver_t
*res
) {
7491 REQUIRE(VALID_RESOLVER(res
));
7492 REQUIRE(!res
->frozen
);
7494 res
->frozen
= ISC_TRUE
;
7498 dns_resolver_attach(dns_resolver_t
*source
, dns_resolver_t
**targetp
) {
7499 REQUIRE(VALID_RESOLVER(source
));
7500 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
7502 RRTRACE(source
, "attach");
7503 LOCK(&source
->lock
);
7504 REQUIRE(!source
->exiting
);
7506 INSIST(source
->references
> 0);
7507 source
->references
++;
7508 INSIST(source
->references
!= 0);
7509 UNLOCK(&source
->lock
);
7515 dns_resolver_whenshutdown(dns_resolver_t
*res
, isc_task_t
*task
,
7516 isc_event_t
**eventp
)
7521 REQUIRE(VALID_RESOLVER(res
));
7522 REQUIRE(eventp
!= NULL
);
7529 if (res
->exiting
&& res
->activebuckets
== 0) {
7531 * We're already shutdown. Send the event.
7533 event
->ev_sender
= res
;
7534 isc_task_send(task
, &event
);
7537 isc_task_attach(task
, &clone
);
7538 event
->ev_sender
= clone
;
7539 ISC_LIST_APPEND(res
->whenshutdown
, event
, ev_link
);
7546 dns_resolver_shutdown(dns_resolver_t
*res
) {
7550 isc_result_t result
;
7552 REQUIRE(VALID_RESOLVER(res
));
7558 if (!res
->exiting
) {
7560 res
->exiting
= ISC_TRUE
;
7562 for (i
= 0; i
< res
->nbuckets
; i
++) {
7563 LOCK(&res
->buckets
[i
].lock
);
7564 for (fctx
= ISC_LIST_HEAD(res
->buckets
[i
].fctxs
);
7566 fctx
= ISC_LIST_NEXT(fctx
, link
))
7567 fctx_shutdown(fctx
);
7568 if (res
->dispatchv4
!= NULL
&& !res
->exclusivev4
) {
7569 sock
= dns_dispatch_getsocket(res
->dispatchv4
);
7570 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
7571 ISC_SOCKCANCEL_ALL
);
7573 if (res
->dispatchv6
!= NULL
&& !res
->exclusivev6
) {
7574 sock
= dns_dispatch_getsocket(res
->dispatchv6
);
7575 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
7576 ISC_SOCKCANCEL_ALL
);
7578 res
->buckets
[i
].exiting
= ISC_TRUE
;
7579 if (ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
)) {
7580 INSIST(res
->activebuckets
> 0);
7581 res
->activebuckets
--;
7583 UNLOCK(&res
->buckets
[i
].lock
);
7585 if (res
->activebuckets
== 0)
7586 send_shutdown_events(res
);
7587 result
= isc_timer_reset(res
->spillattimer
,
7588 isc_timertype_inactive
, NULL
,
7590 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
7597 dns_resolver_detach(dns_resolver_t
**resp
) {
7598 dns_resolver_t
*res
;
7599 isc_boolean_t need_destroy
= ISC_FALSE
;
7601 REQUIRE(resp
!= NULL
);
7603 REQUIRE(VALID_RESOLVER(res
));
7609 INSIST(res
->references
> 0);
7611 if (res
->references
== 0) {
7612 INSIST(res
->exiting
&& res
->activebuckets
== 0);
7613 need_destroy
= ISC_TRUE
;
7624 static inline isc_boolean_t
7625 fctx_match(fetchctx_t
*fctx
, dns_name_t
*name
, dns_rdatatype_t type
,
7626 unsigned int options
)
7628 if (fctx
->type
!= type
|| fctx
->options
!= options
)
7630 return (dns_name_equal(&fctx
->name
, name
));
7634 log_fetch(dns_name_t
*name
, dns_rdatatype_t type
) {
7635 char namebuf
[DNS_NAME_FORMATSIZE
];
7636 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
7637 int level
= ISC_LOG_DEBUG(1);
7639 if (! isc_log_wouldlog(dns_lctx
, level
))
7642 dns_name_format(name
, namebuf
, sizeof(namebuf
));
7643 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
7645 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
7646 DNS_LOGMODULE_RESOLVER
, level
,
7647 "createfetch: %s %s", namebuf
, typebuf
);
7651 dns_resolver_createfetch(dns_resolver_t
*res
, dns_name_t
*name
,
7652 dns_rdatatype_t type
,
7653 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
7654 dns_forwarders_t
*forwarders
,
7655 unsigned int options
, isc_task_t
*task
,
7656 isc_taskaction_t action
, void *arg
,
7657 dns_rdataset_t
*rdataset
,
7658 dns_rdataset_t
*sigrdataset
,
7659 dns_fetch_t
**fetchp
)
7661 return (dns_resolver_createfetch2(res
, name
, type
, domain
,
7662 nameservers
, forwarders
, NULL
, 0,
7663 options
, task
, action
, arg
,
7664 rdataset
, sigrdataset
, fetchp
));
7668 dns_resolver_createfetch2(dns_resolver_t
*res
, dns_name_t
*name
,
7669 dns_rdatatype_t type
,
7670 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
7671 dns_forwarders_t
*forwarders
,
7672 isc_sockaddr_t
*client
, dns_messageid_t id
,
7673 unsigned int options
, isc_task_t
*task
,
7674 isc_taskaction_t action
, void *arg
,
7675 dns_rdataset_t
*rdataset
,
7676 dns_rdataset_t
*sigrdataset
,
7677 dns_fetch_t
**fetchp
)
7680 fetchctx_t
*fctx
= NULL
;
7681 isc_result_t result
= ISC_R_SUCCESS
;
7682 unsigned int bucketnum
;
7683 isc_boolean_t new_fctx
= ISC_FALSE
;
7685 unsigned int count
= 0;
7686 unsigned int spillat
;
7687 unsigned int spillatmin
;
7691 REQUIRE(VALID_RESOLVER(res
));
7692 REQUIRE(res
->frozen
);
7693 /* XXXRTH Check for meta type */
7694 if (domain
!= NULL
) {
7695 REQUIRE(DNS_RDATASET_VALID(nameservers
));
7696 REQUIRE(nameservers
->type
== dns_rdatatype_ns
);
7698 REQUIRE(nameservers
== NULL
);
7699 REQUIRE(forwarders
== NULL
);
7700 REQUIRE(!dns_rdataset_isassociated(rdataset
));
7701 REQUIRE(sigrdataset
== NULL
||
7702 !dns_rdataset_isassociated(sigrdataset
));
7703 REQUIRE(fetchp
!= NULL
&& *fetchp
== NULL
);
7705 log_fetch(name
, type
);
7708 * XXXRTH use a mempool?
7710 fetch
= isc_mem_get(res
->mctx
, sizeof(*fetch
));
7712 return (ISC_R_NOMEMORY
);
7714 bucketnum
= dns_name_fullhash(name
, ISC_FALSE
) % res
->nbuckets
;
7717 spillat
= res
->spillat
;
7718 spillatmin
= res
->spillatmin
;
7720 LOCK(&res
->buckets
[bucketnum
].lock
);
7722 if (res
->buckets
[bucketnum
].exiting
) {
7723 result
= ISC_R_SHUTTINGDOWN
;
7727 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0) {
7728 for (fctx
= ISC_LIST_HEAD(res
->buckets
[bucketnum
].fctxs
);
7730 fctx
= ISC_LIST_NEXT(fctx
, link
)) {
7731 if (fctx_match(fctx
, name
, type
, options
))
7737 * Is this a duplicate?
7739 if (fctx
!= NULL
&& client
!= NULL
) {
7740 dns_fetchevent_t
*fevent
;
7741 for (fevent
= ISC_LIST_HEAD(fctx
->events
);
7743 fevent
= ISC_LIST_NEXT(fevent
, ev_link
)) {
7744 if (fevent
->client
!= NULL
&& fevent
->id
== id
&&
7745 isc_sockaddr_equal(fevent
->client
, client
)) {
7746 result
= DNS_R_DUPLICATE
;
7752 if (count
>= spillatmin
&& spillatmin
!= 0) {
7753 INSIST(fctx
!= NULL
);
7754 if (count
>= spillat
)
7755 fctx
->spilled
= ISC_TRUE
;
7756 if (fctx
->spilled
) {
7757 result
= DNS_R_DROP
;
7763 * If we didn't have a fetch, would attach to a done fetch, this
7764 * fetch has already cloned its results, or if the fetch has gone
7765 * "idle" (no one was interested in it), we need to start a new
7766 * fetch instead of joining with the existing one.
7769 fctx
->state
== fetchstate_done
||
7771 ISC_LIST_EMPTY(fctx
->events
)) {
7773 result
= fctx_create(res
, name
, type
, domain
, nameservers
,
7774 options
, bucketnum
, &fctx
);
7775 if (result
!= ISC_R_SUCCESS
)
7777 new_fctx
= ISC_TRUE
;
7780 result
= fctx_join(fctx
, task
, client
, id
, action
, arg
,
7781 rdataset
, sigrdataset
, fetch
);
7783 if (result
== ISC_R_SUCCESS
) {
7787 event
= &fctx
->control_event
;
7788 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
7789 DNS_EVENT_FETCHCONTROL
,
7790 fctx_start
, fctx
, NULL
,
7792 isc_task_send(res
->buckets
[bucketnum
].task
, &event
);
7795 * We don't care about the result of fctx_destroy()
7796 * since we know we're not exiting.
7798 (void)fctx_destroy(fctx
);
7803 UNLOCK(&res
->buckets
[bucketnum
].lock
);
7805 if (result
== ISC_R_SUCCESS
) {
7809 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
7815 dns_resolver_cancelfetch(dns_fetch_t
*fetch
) {
7817 dns_resolver_t
*res
;
7818 dns_fetchevent_t
*event
, *next_event
;
7821 REQUIRE(DNS_FETCH_VALID(fetch
));
7822 fctx
= fetch
->private;
7823 REQUIRE(VALID_FCTX(fctx
));
7826 FTRACE("cancelfetch");
7828 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7831 * Find the completion event for this fetch (as opposed
7832 * to those for other fetches that have joined the same
7833 * fctx) and send it with result = ISC_R_CANCELED.
7836 if (fctx
->state
!= fetchstate_done
) {
7837 for (event
= ISC_LIST_HEAD(fctx
->events
);
7839 event
= next_event
) {
7840 next_event
= ISC_LIST_NEXT(event
, ev_link
);
7841 if (event
->fetch
== fetch
) {
7842 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
7847 if (event
!= NULL
) {
7848 etask
= event
->ev_sender
;
7849 event
->ev_sender
= fctx
;
7850 event
->result
= ISC_R_CANCELED
;
7851 isc_task_sendanddetach(&etask
, ISC_EVENT_PTR(&event
));
7854 * The fctx continues running even if no fetches remain;
7855 * the answer is still cached.
7858 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7862 dns_resolver_destroyfetch(dns_fetch_t
**fetchp
) {
7864 dns_resolver_t
*res
;
7865 dns_fetchevent_t
*event
, *next_event
;
7867 unsigned int bucketnum
;
7868 isc_boolean_t bucket_empty
= ISC_FALSE
;
7870 REQUIRE(fetchp
!= NULL
);
7872 REQUIRE(DNS_FETCH_VALID(fetch
));
7873 fctx
= fetch
->private;
7874 REQUIRE(VALID_FCTX(fctx
));
7877 FTRACE("destroyfetch");
7879 bucketnum
= fctx
->bucketnum
;
7880 LOCK(&res
->buckets
[bucketnum
].lock
);
7883 * Sanity check: the caller should have gotten its event before
7884 * trying to destroy the fetch.
7887 if (fctx
->state
!= fetchstate_done
) {
7888 for (event
= ISC_LIST_HEAD(fctx
->events
);
7890 event
= next_event
) {
7891 next_event
= ISC_LIST_NEXT(event
, ev_link
);
7892 RUNTIME_CHECK(event
->fetch
!= fetch
);
7896 INSIST(fctx
->references
> 0);
7898 if (fctx
->references
== 0) {
7900 * No one cares about the result of this fetch anymore.
7902 if (fctx
->pending
== 0 && fctx
->nqueries
== 0 &&
7903 ISC_LIST_EMPTY(fctx
->validators
) &&
7904 SHUTTINGDOWN(fctx
)) {
7906 * This fctx is already shutdown; we were just
7907 * waiting for the last reference to go away.
7909 bucket_empty
= fctx_destroy(fctx
);
7912 * Initiate shutdown.
7914 fctx_shutdown(fctx
);
7918 UNLOCK(&res
->buckets
[bucketnum
].lock
);
7920 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
7928 dns_resolver_logfetch(dns_fetch_t
*fetch
, isc_log_t
*lctx
,
7929 isc_logcategory_t
*category
, isc_logmodule_t
*module
,
7930 int level
, isc_boolean_t duplicateok
)
7933 dns_resolver_t
*res
;
7934 char domainbuf
[DNS_NAME_FORMATSIZE
];
7936 REQUIRE(DNS_FETCH_VALID(fetch
));
7937 fctx
= fetch
->private;
7938 REQUIRE(VALID_FCTX(fctx
));
7941 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7943 INSIST(fctx
->exitline
>= 0);
7944 if (!fctx
->logged
|| duplicateok
) {
7945 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
7946 isc_log_write(lctx
, category
, module
, level
,
7947 "fetch completed at %s:%d for %s in "
7948 "%" ISC_PRINT_QUADFORMAT
"u."
7949 "%06" ISC_PRINT_QUADFORMAT
"u: %s/%s "
7950 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
7951 "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
7952 "adberr:%u,findfail:%u,valfail:%u]",
7953 __FILE__
, fctx
->exitline
, fctx
->info
,
7954 fctx
->duration
/ 1000000,
7955 fctx
->duration
% 1000000,
7956 isc_result_totext(fctx
->result
),
7957 isc_result_totext(fctx
->vresult
), domainbuf
,
7958 fctx
->referrals
, fctx
->restarts
,
7959 fctx
->querysent
, fctx
->timeouts
, fctx
->lamecount
,
7960 fctx
->neterr
, fctx
->badresp
, fctx
->adberr
,
7961 fctx
->findfail
, fctx
->valfail
);
7962 fctx
->logged
= ISC_TRUE
;
7965 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7969 dns_resolver_dispatchmgr(dns_resolver_t
*resolver
) {
7970 REQUIRE(VALID_RESOLVER(resolver
));
7971 return (resolver
->dispatchmgr
);
7975 dns_resolver_dispatchv4(dns_resolver_t
*resolver
) {
7976 REQUIRE(VALID_RESOLVER(resolver
));
7977 return (resolver
->dispatchv4
);
7981 dns_resolver_dispatchv6(dns_resolver_t
*resolver
) {
7982 REQUIRE(VALID_RESOLVER(resolver
));
7983 return (resolver
->dispatchv6
);
7987 dns_resolver_socketmgr(dns_resolver_t
*resolver
) {
7988 REQUIRE(VALID_RESOLVER(resolver
));
7989 return (resolver
->socketmgr
);
7993 dns_resolver_taskmgr(dns_resolver_t
*resolver
) {
7994 REQUIRE(VALID_RESOLVER(resolver
));
7995 return (resolver
->taskmgr
);
7999 dns_resolver_getlamettl(dns_resolver_t
*resolver
) {
8000 REQUIRE(VALID_RESOLVER(resolver
));
8001 return (resolver
->lame_ttl
);
8005 dns_resolver_setlamettl(dns_resolver_t
*resolver
, isc_uint32_t lame_ttl
) {
8006 REQUIRE(VALID_RESOLVER(resolver
));
8007 resolver
->lame_ttl
= lame_ttl
;
8011 dns_resolver_nrunning(dns_resolver_t
*resolver
) {
8013 LOCK(&resolver
->nlock
);
8014 n
= resolver
->nfctx
;
8015 UNLOCK(&resolver
->nlock
);
8020 dns_resolver_addalternate(dns_resolver_t
*resolver
, isc_sockaddr_t
*alt
,
8021 dns_name_t
*name
, in_port_t port
) {
8023 isc_result_t result
;
8025 REQUIRE(VALID_RESOLVER(resolver
));
8026 REQUIRE(!resolver
->frozen
);
8027 REQUIRE((alt
== NULL
) ^ (name
== NULL
));
8029 a
= isc_mem_get(resolver
->mctx
, sizeof(*a
));
8031 return (ISC_R_NOMEMORY
);
8033 a
->isaddress
= ISC_TRUE
;
8036 a
->isaddress
= ISC_FALSE
;
8037 a
->_u
._n
.port
= port
;
8038 dns_name_init(&a
->_u
._n
.name
, NULL
);
8039 result
= dns_name_dup(name
, resolver
->mctx
, &a
->_u
._n
.name
);
8040 if (result
!= ISC_R_SUCCESS
) {
8041 isc_mem_put(resolver
->mctx
, a
, sizeof(*a
));
8045 ISC_LINK_INIT(a
, link
);
8046 ISC_LIST_APPEND(resolver
->alternates
, a
, link
);
8048 return (ISC_R_SUCCESS
);
8052 dns_resolver_setudpsize(dns_resolver_t
*resolver
, isc_uint16_t udpsize
) {
8053 REQUIRE(VALID_RESOLVER(resolver
));
8054 resolver
->udpsize
= udpsize
;
8058 dns_resolver_getudpsize(dns_resolver_t
*resolver
) {
8059 REQUIRE(VALID_RESOLVER(resolver
));
8060 return (resolver
->udpsize
);
8064 free_algorithm(void *node
, void *arg
) {
8065 unsigned char *algorithms
= node
;
8066 isc_mem_t
*mctx
= arg
;
8068 isc_mem_put(mctx
, algorithms
, *algorithms
);
8072 dns_resolver_reset_algorithms(dns_resolver_t
*resolver
) {
8074 REQUIRE(VALID_RESOLVER(resolver
));
8077 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
8079 if (resolver
->algorithms
!= NULL
)
8080 dns_rbt_destroy(&resolver
->algorithms
);
8082 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
8087 dns_resolver_disable_algorithm(dns_resolver_t
*resolver
, dns_name_t
*name
,
8090 unsigned int len
, mask
;
8092 unsigned char *algorithms
;
8093 isc_result_t result
;
8094 dns_rbtnode_t
*node
= NULL
;
8096 REQUIRE(VALID_RESOLVER(resolver
));
8098 return (ISC_R_RANGE
);
8101 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
8103 if (resolver
->algorithms
== NULL
) {
8104 result
= dns_rbt_create(resolver
->mctx
, free_algorithm
,
8105 resolver
->mctx
, &resolver
->algorithms
);
8106 if (result
!= ISC_R_SUCCESS
)
8111 mask
= 1 << (alg
%8);
8113 result
= dns_rbt_addnode(resolver
->algorithms
, name
, &node
);
8115 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_EXISTS
) {
8116 algorithms
= node
->data
;
8117 if (algorithms
== NULL
|| len
> *algorithms
) {
8118 new = isc_mem_get(resolver
->mctx
, len
);
8120 result
= ISC_R_NOMEMORY
;
8123 memset(new, 0, len
);
8124 if (algorithms
!= NULL
)
8125 memcpy(new, algorithms
, *algorithms
);
8129 if (algorithms
!= NULL
)
8130 isc_mem_put(resolver
->mctx
, algorithms
,
8133 algorithms
[len
-1] |= mask
;
8135 result
= ISC_R_SUCCESS
;
8138 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
8144 dns_resolver_algorithm_supported(dns_resolver_t
*resolver
, dns_name_t
*name
,
8147 unsigned int len
, mask
;
8148 unsigned char *algorithms
;
8150 isc_result_t result
;
8151 isc_boolean_t found
= ISC_FALSE
;
8153 REQUIRE(VALID_RESOLVER(resolver
));
8156 RWLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
8158 if (resolver
->algorithms
== NULL
)
8160 result
= dns_rbt_findname(resolver
->algorithms
, name
, 0, NULL
, &data
);
8161 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
8163 mask
= 1 << (alg
%8);
8165 if (len
<= *algorithms
&& (algorithms
[len
-1] & mask
) != 0)
8170 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
8174 return (dst_algorithm_supported(alg
));
8178 dns_resolver_digest_supported(dns_resolver_t
*resolver
, unsigned int digest
) {
8181 return (dns_ds_digest_supported(digest
));
8185 dns_resolver_resetmustbesecure(dns_resolver_t
*resolver
) {
8187 REQUIRE(VALID_RESOLVER(resolver
));
8190 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
8192 if (resolver
->mustbesecure
!= NULL
)
8193 dns_rbt_destroy(&resolver
->mustbesecure
);
8195 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
8199 static isc_boolean_t yes
= ISC_TRUE
, no
= ISC_FALSE
;
8202 dns_resolver_setmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
,
8203 isc_boolean_t value
)
8205 isc_result_t result
;
8207 REQUIRE(VALID_RESOLVER(resolver
));
8210 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
8212 if (resolver
->mustbesecure
== NULL
) {
8213 result
= dns_rbt_create(resolver
->mctx
, NULL
, NULL
,
8214 &resolver
->mustbesecure
);
8215 if (result
!= ISC_R_SUCCESS
)
8218 result
= dns_rbt_addname(resolver
->mustbesecure
, name
,
8219 value
? &yes
: &no
);
8222 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
8228 dns_resolver_getmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
) {
8230 isc_boolean_t value
= ISC_FALSE
;
8231 isc_result_t result
;
8233 REQUIRE(VALID_RESOLVER(resolver
));
8236 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);
8238 if (resolver
->mustbesecure
== NULL
)
8240 result
= dns_rbt_findname(resolver
->mustbesecure
, name
, 0, NULL
, &data
);
8241 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
8242 value
= *(isc_boolean_t
*)data
;
8245 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);
8251 dns_resolver_getclientsperquery(dns_resolver_t
*resolver
, isc_uint32_t
*cur
,
8252 isc_uint32_t
*min
, isc_uint32_t
*max
)
8254 REQUIRE(VALID_RESOLVER(resolver
));
8256 LOCK(&resolver
->lock
);
8258 *cur
= resolver
->spillat
;
8260 *min
= resolver
->spillatmin
;
8262 *max
= resolver
->spillatmax
;
8263 UNLOCK(&resolver
->lock
);
8267 dns_resolver_setclientsperquery(dns_resolver_t
*resolver
, isc_uint32_t min
,
8270 REQUIRE(VALID_RESOLVER(resolver
));
8272 LOCK(&resolver
->lock
);
8273 resolver
->spillatmin
= resolver
->spillat
= min
;
8274 resolver
->spillatmax
= max
;
8275 UNLOCK(&resolver
->lock
);
8279 dns_resolver_getzeronosoattl(dns_resolver_t
*resolver
) {
8280 REQUIRE(VALID_RESOLVER(resolver
));
8282 return (resolver
->zero_no_soa_ttl
);
8286 dns_resolver_setzeronosoattl(dns_resolver_t
*resolver
, isc_boolean_t state
) {
8287 REQUIRE(VALID_RESOLVER(resolver
));
8289 resolver
->zero_no_soa_ttl
= state
;
8293 dns_resolver_getoptions(dns_resolver_t
*resolver
) {
8294 REQUIRE(VALID_RESOLVER(resolver
));
8296 return (resolver
->options
);