2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: resolver.c,v 1.355.12.44.2.2 2010/01/07 17:19:22 each Exp $ */
24 #include <isc/platform.h>
25 #include <isc/print.h>
26 #include <isc/string.h>
27 #include <isc/random.h>
29 #include <isc/stats.h>
30 #include <isc/timer.h>
35 #include <dns/cache.h>
37 #include <dns/dispatch.h>
39 #include <dns/events.h>
40 #include <dns/forward.h>
41 #include <dns/keytable.h>
43 #include <dns/message.h>
44 #include <dns/ncache.h>
45 #include <dns/opcode.h>
48 #include <dns/rcode.h>
49 #include <dns/rdata.h>
50 #include <dns/rdataclass.h>
51 #include <dns/rdatalist.h>
52 #include <dns/rdataset.h>
53 #include <dns/rdatastruct.h>
54 #include <dns/rdatatype.h>
55 #include <dns/resolver.h>
56 #include <dns/result.h>
57 #include <dns/rootns.h>
58 #include <dns/stats.h>
60 #include <dns/validator.h>
62 #define DNS_RESOLVER_TRACE
63 #ifdef DNS_RESOLVER_TRACE
64 #define RTRACE(m) isc_log_write(dns_lctx, \
65 DNS_LOGCATEGORY_RESOLVER, \
66 DNS_LOGMODULE_RESOLVER, \
68 "res %p: %s", res, (m))
69 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
70 DNS_LOGCATEGORY_RESOLVER, \
71 DNS_LOGMODULE_RESOLVER, \
73 "res %p: %s", (r), (m))
74 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
75 DNS_LOGCATEGORY_RESOLVER, \
76 DNS_LOGMODULE_RESOLVER, \
78 "fctx %p(%s'): %s", fctx, fctx->info, (m))
79 #define FCTXTRACE2(m1, m2) \
80 isc_log_write(dns_lctx, \
81 DNS_LOGCATEGORY_RESOLVER, \
82 DNS_LOGMODULE_RESOLVER, \
84 "fctx %p(%s): %s %s", \
85 fctx, fctx->info, (m1), (m2))
86 #define FTRACE(m) isc_log_write(dns_lctx, \
87 DNS_LOGCATEGORY_RESOLVER, \
88 DNS_LOGMODULE_RESOLVER, \
90 "fetch %p (fctx %p(%s)): %s", \
91 fetch, fetch->private, \
92 fetch->private->info, (m))
93 #define QTRACE(m) isc_log_write(dns_lctx, \
94 DNS_LOGCATEGORY_RESOLVER, \
95 DNS_LOGMODULE_RESOLVER, \
97 "resquery %p (fctx %p(%s)): %s", \
99 query->fctx->info, (m))
102 #define RRTRACE(r, m)
109 * Maximum EDNS0 input packet size.
111 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
114 * This defines the maximum number of timeouts we will permit before we
115 * disable EDNS0 on the query.
117 #define MAX_EDNS0_TIMEOUTS 3
119 typedef struct fetchctx fetchctx_t
;
121 typedef struct query
{
122 /* Locked by task event serialization. */
126 dns_dispatchmgr_t
* dispatchmgr
;
127 dns_dispatch_t
* dispatch
;
128 isc_boolean_t exclusivesocket
;
129 dns_adbaddrinfo_t
* addrinfo
;
130 isc_socket_t
* tcpsocket
;
133 dns_dispentry_t
* dispentry
;
134 ISC_LINK(struct query
) link
;
137 dns_tsigkey_t
*tsigkey
;
138 unsigned int options
;
139 unsigned int attributes
;
141 unsigned int connects
;
142 unsigned char data
[512];
145 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
146 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
148 #define RESQUERY_ATTR_CANCELED 0x02
150 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
151 #define RESQUERY_CANCELED(q) (((q)->attributes & \
152 RESQUERY_ATTR_CANCELED) != 0)
153 #define RESQUERY_SENDING(q) ((q)->sends > 0)
156 fetchstate_init
= 0, /*%< Start event has not run yet. */
158 fetchstate_done
/*%< FETCHDONE events posted. */
162 badns_unreachable
= 0,
170 dns_resolver_t
* res
;
172 dns_rdatatype_t type
;
173 unsigned int options
;
174 unsigned int bucketnum
;
176 /*% Locked by appropriate bucket lock. */
178 isc_boolean_t want_shutdown
;
179 isc_boolean_t cloned
;
180 isc_boolean_t spilled
;
181 unsigned int references
;
182 isc_event_t control_event
;
183 ISC_LINK(struct fetchctx
) link
;
184 ISC_LIST(dns_fetchevent_t
) events
;
185 /*% Locked by task event serialization. */
187 dns_rdataset_t nameservers
;
188 unsigned int attributes
;
191 isc_interval_t interval
;
192 dns_message_t
* qmessage
;
193 dns_message_t
* rmessage
;
194 ISC_LIST(resquery_t
) queries
;
195 dns_adbfindlist_t finds
;
196 dns_adbfind_t
* find
;
197 dns_adbfindlist_t altfinds
;
198 dns_adbfind_t
* altfind
;
199 dns_adbaddrinfolist_t forwaddrs
;
200 dns_adbaddrinfolist_t altaddrs
;
201 isc_sockaddrlist_t forwarders
;
202 dns_fwdpolicy_t fwdpolicy
;
203 isc_sockaddrlist_t bad
;
204 isc_sockaddrlist_t edns
;
205 isc_sockaddrlist_t edns512
;
206 dns_validator_t
*validator
;
207 ISC_LIST(dns_validator_t
) validators
;
212 * The number of events we're waiting for.
214 unsigned int pending
;
217 * The number of times we've "restarted" the current
218 * nameserver set. This acts as a failsafe to prevent
219 * us from pounding constantly on a particular set of
220 * servers that, for whatever reason, are not giving
221 * us useful responses, but are responding in such a
222 * way that they are not marked "bad".
224 unsigned int restarts
;
227 * The number of timeouts that have occurred since we
228 * last successfully received a response packet. This
229 * is used for EDNS0 black hole detection.
231 unsigned int timeouts
;
234 * Look aside state for DS lookups.
237 dns_fetch_t
* nsfetch
;
238 dns_rdataset_t nsrrset
;
241 * Number of queries that reference this context.
243 unsigned int nqueries
;
246 * The reason to print when logging a successful
247 * response to a query.
252 * Fetch-local statistics for detailed logging.
254 isc_result_t result
; /*%< fetch result */
255 isc_result_t vresult
; /*%< validation result */
258 isc_uint64_t duration
;
259 isc_boolean_t logged
;
260 unsigned int querysent
;
261 unsigned int referrals
;
262 unsigned int lamecount
;
264 unsigned int badresp
;
266 unsigned int findfail
;
267 unsigned int valfail
;
268 isc_boolean_t timeout
;
271 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
272 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
274 #define FCTX_ATTR_HAVEANSWER 0x0001
275 #define FCTX_ATTR_GLUING 0x0002
276 #define FCTX_ATTR_ADDRWAIT 0x0004
277 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
278 #define FCTX_ATTR_WANTCACHE 0x0010
279 #define FCTX_ATTR_WANTNCACHE 0x0020
280 #define FCTX_ATTR_NEEDEDNS0 0x0040
281 #define FCTX_ATTR_TRIEDFIND 0x0080
282 #define FCTX_ATTR_TRIEDALT 0x0100
284 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
286 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
288 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
290 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
292 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
293 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
294 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
295 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
296 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
299 dns_adbaddrinfo_t
* addrinfo
;
305 fetchctx_t
* private;
308 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
309 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
311 typedef struct fctxbucket
{
314 ISC_LIST(fetchctx_t
) fctxs
;
315 isc_boolean_t exiting
;
319 typedef struct alternate
{
320 isc_boolean_t isaddress
;
328 ISC_LINK(struct alternate
) link
;
331 struct dns_resolver
{
337 isc_mutex_t primelock
;
338 dns_rdataclass_t rdclass
;
339 isc_socketmgr_t
* socketmgr
;
340 isc_timermgr_t
* timermgr
;
341 isc_taskmgr_t
* taskmgr
;
343 isc_boolean_t frozen
;
344 unsigned int options
;
345 dns_dispatchmgr_t
* dispatchmgr
;
346 dns_dispatch_t
* dispatchv4
;
347 isc_boolean_t exclusivev4
;
348 dns_dispatch_t
* dispatchv6
;
349 isc_boolean_t exclusivev6
;
351 unsigned int nbuckets
;
352 fctxbucket_t
* buckets
;
353 isc_uint32_t lame_ttl
;
354 ISC_LIST(alternate_t
) alternates
;
355 isc_uint16_t udpsize
;
357 isc_rwlock_t alglock
;
359 dns_rbt_t
* algorithms
;
361 isc_rwlock_t mbslock
;
363 dns_rbt_t
* mustbesecure
;
364 unsigned int spillatmax
;
365 unsigned int spillatmin
;
366 isc_timer_t
* spillattimer
;
367 isc_boolean_t zero_no_soa_ttl
;
369 /* Locked by lock. */
370 unsigned int references
;
371 isc_boolean_t exiting
;
372 isc_eventlist_t whenshutdown
;
373 unsigned int activebuckets
;
374 isc_boolean_t priming
;
375 unsigned int spillat
; /* clients-per-query */
376 unsigned int nextdisp
;
377 /* Locked by primelock. */
378 dns_fetch_t
* primefetch
;
379 /* Locked by nlock. */
383 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
384 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
387 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
388 * which we also use as an addrinfo flag.
390 #define FCTX_ADDRINFO_MARK 0x0001
391 #define FCTX_ADDRINFO_FORWARDER 0x1000
392 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
394 #define ISFORWARDER(a) (((a)->flags & \
395 FCTX_ADDRINFO_FORWARDER) != 0)
397 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
399 static void destroy(dns_resolver_t
*res
);
400 static void empty_bucket(dns_resolver_t
*res
);
401 static isc_result_t
resquery_send(resquery_t
*query
);
402 static void resquery_response(isc_task_t
*task
, isc_event_t
*event
);
403 static void resquery_connected(isc_task_t
*task
, isc_event_t
*event
);
404 static void fctx_try(fetchctx_t
*fctx
, isc_boolean_t retrying
);
405 static isc_boolean_t
fctx_destroy(fetchctx_t
*fctx
);
406 static isc_result_t
ncache_adderesult(dns_message_t
*message
,
407 dns_db_t
*cache
, dns_dbnode_t
*node
,
408 dns_rdatatype_t covers
,
409 isc_stdtime_t now
, dns_ttl_t maxttl
,
410 dns_rdataset_t
*ardataset
,
411 isc_result_t
*eresultp
);
412 static void validated(isc_task_t
*task
, isc_event_t
*event
);
413 static void maybe_destroy(fetchctx_t
*fctx
);
414 static void add_bad(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
415 isc_result_t reason
, badnstype_t badtype
);
418 * Increment resolver-related statistics counters.
421 inc_stats(dns_resolver_t
*res
, isc_statscounter_t counter
) {
422 if (res
->view
->resstats
!= NULL
)
423 isc_stats_increment(res
->view
->resstats
, counter
);
427 valcreate(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, dns_name_t
*name
,
428 dns_rdatatype_t type
, dns_rdataset_t
*rdataset
,
429 dns_rdataset_t
*sigrdataset
, unsigned int valoptions
,
432 dns_validator_t
*validator
= NULL
;
433 dns_valarg_t
*valarg
;
436 valarg
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
439 return (ISC_R_NOMEMORY
);
442 valarg
->addrinfo
= addrinfo
;
444 if (!ISC_LIST_EMPTY(fctx
->validators
))
445 INSIST((valoptions
& DNS_VALIDATOR_DEFER
) != 0);
447 result
= dns_validator_create(fctx
->res
->view
, name
, type
, rdataset
,
448 sigrdataset
, fctx
->rmessage
,
449 valoptions
, task
, validated
, valarg
,
451 if (result
== ISC_R_SUCCESS
) {
452 inc_stats(fctx
->res
, dns_resstatscounter_val
);
453 if ((valoptions
& DNS_VALIDATOR_DEFER
) == 0) {
454 INSIST(fctx
->validator
== NULL
);
455 fctx
->validator
= validator
;
457 ISC_LIST_APPEND(fctx
->validators
, validator
, link
);
459 isc_mem_put(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
460 valarg
, sizeof(*valarg
));
465 rrsig_fromchildzone(fetchctx_t
*fctx
, dns_rdataset_t
*rdataset
) {
466 dns_namereln_t namereln
;
467 dns_rdata_rrsig_t rrsig
;
468 dns_rdata_t rdata
= DNS_RDATA_INIT
;
473 for (result
= dns_rdataset_first(rdataset
);
474 result
== ISC_R_SUCCESS
;
475 result
= dns_rdataset_next(rdataset
)) {
476 dns_rdataset_current(rdataset
, &rdata
);
477 result
= dns_rdata_tostruct(&rdata
, &rrsig
, NULL
);
478 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
479 namereln
= dns_name_fullcompare(&rrsig
.signer
, &fctx
->domain
,
481 if (namereln
== dns_namereln_subdomain
)
483 dns_rdata_reset(&rdata
);
489 fix_mustbedelegationornxdomain(dns_message_t
*message
, fetchctx_t
*fctx
) {
491 dns_name_t
*domain
= &fctx
->domain
;
492 dns_rdataset_t
*rdataset
;
493 dns_rdatatype_t type
;
495 isc_boolean_t keep_auth
= ISC_FALSE
;
497 if (message
->rcode
== dns_rcode_nxdomain
)
501 * A DS RRset can appear anywhere in a zone, even for a delegation-only
502 * zone. So a response to an explicit query for this type should be
503 * excluded from delegation-only fixup.
505 * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
506 * response to a query for these types can never violate the
507 * delegation-only assumption: if the query name is below a
508 * zone cut, the response should normally be a referral, which should
509 * be accepted; if the query name is below a zone cut but the server
510 * happens to have authority for the zone of the query name, the
511 * response is a (non-referral) answer. But this does not violate
512 * delegation-only because the query name must be in a different zone
513 * due to the "apex-only" nature of these types. Note that if the
514 * remote server happens to have authority for a child zone of a
515 * delegation-only zone, we may still incorrectly "fix" the response
516 * with NXDOMAIN for queries for other types. Unfortunately it's
517 * generally impossible to differentiate this case from violation of
518 * the delegation-only assumption. Once the resolver learns the
519 * correct zone cut, possibly via a separate query for an "apex-only"
520 * type, queries for other types will be resolved correctly.
522 * A query for type ANY will be accepted if it hits an exceptional
523 * type above in the answer section as it should be from a child
526 * Also accept answers with RRSIG records from the child zone.
527 * Direct queries for RRSIG records should not be answered from
531 if (message
->counts
[DNS_SECTION_ANSWER
] != 0 &&
532 (fctx
->type
== dns_rdatatype_ns
||
533 fctx
->type
== dns_rdatatype_ds
||
534 fctx
->type
== dns_rdatatype_soa
||
535 fctx
->type
== dns_rdatatype_any
||
536 fctx
->type
== dns_rdatatype_rrsig
||
537 fctx
->type
== dns_rdatatype_dnskey
)) {
538 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
539 while (result
== ISC_R_SUCCESS
) {
541 dns_message_currentname(message
, DNS_SECTION_ANSWER
,
543 for (rdataset
= ISC_LIST_HEAD(name
->list
);
545 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
546 if (!dns_name_equal(name
, &fctx
->name
))
548 type
= rdataset
->type
;
552 if (type
== dns_rdatatype_rrsig
&&
553 rrsig_fromchildzone(fctx
, rdataset
))
556 * Direct query for apex records or DS.
558 if (fctx
->type
== type
&&
559 (type
== dns_rdatatype_ds
||
560 type
== dns_rdatatype_ns
||
561 type
== dns_rdatatype_soa
||
562 type
== dns_rdatatype_dnskey
))
565 * Indirect query for apex records or DS.
567 if (fctx
->type
== dns_rdatatype_any
&&
568 (type
== dns_rdatatype_ns
||
569 type
== dns_rdatatype_ds
||
570 type
== dns_rdatatype_soa
||
571 type
== dns_rdatatype_dnskey
))
574 result
= dns_message_nextname(message
,
580 * A NODATA response to a DS query?
582 if (fctx
->type
== dns_rdatatype_ds
&&
583 message
->counts
[DNS_SECTION_ANSWER
] == 0)
586 /* Look for referral or indication of answer from child zone? */
587 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
590 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
591 while (result
== ISC_R_SUCCESS
) {
593 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
594 for (rdataset
= ISC_LIST_HEAD(name
->list
);
596 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
597 type
= rdataset
->type
;
598 if (type
== dns_rdatatype_soa
&&
599 dns_name_equal(name
, domain
))
600 keep_auth
= ISC_TRUE
;
602 if (type
!= dns_rdatatype_ns
&&
603 type
!= dns_rdatatype_soa
&&
604 type
!= dns_rdatatype_rrsig
)
607 if (type
== dns_rdatatype_rrsig
) {
608 if (rrsig_fromchildzone(fctx
, rdataset
))
614 /* NS or SOA records. */
615 if (dns_name_equal(name
, domain
)) {
617 * If a query for ANY causes a negative
618 * response, we can be sure that this is
619 * an empty node. For other type of queries
620 * we cannot differentiate an empty node
621 * from a node that just doesn't have that
622 * type of record. We only accept the former
625 if (message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
626 fctx
->type
== dns_rdatatype_any
)
628 } else if (dns_name_issubdomain(name
, domain
)) {
629 /* Referral or answer from child zone. */
633 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
637 message
->rcode
= dns_rcode_nxdomain
;
638 message
->counts
[DNS_SECTION_ANSWER
] = 0;
640 message
->counts
[DNS_SECTION_AUTHORITY
] = 0;
641 message
->counts
[DNS_SECTION_ADDITIONAL
] = 0;
645 static inline isc_result_t
646 fctx_starttimer(fetchctx_t
*fctx
) {
648 * Start the lifetime timer for fctx.
650 * This is also used for stopping the idle timer; in that
651 * case we must purge events already posted to ensure that
652 * no further idle events are delivered.
654 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
655 &fctx
->expires
, NULL
, ISC_TRUE
));
659 fctx_stoptimer(fetchctx_t
*fctx
) {
663 * We don't return a result if resetting the timer to inactive fails
664 * since there's nothing to be done about it. Resetting to inactive
665 * should never fail anyway, since the code as currently written
666 * cannot fail in that case.
668 result
= isc_timer_reset(fctx
->timer
, isc_timertype_inactive
,
669 NULL
, NULL
, ISC_TRUE
);
670 if (result
!= ISC_R_SUCCESS
) {
671 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
672 "isc_timer_reset(): %s",
673 isc_result_totext(result
));
678 static inline isc_result_t
679 fctx_startidletimer(fetchctx_t
*fctx
, isc_interval_t
*interval
) {
681 * Start the idle timer for fctx. The lifetime timer continues
684 return (isc_timer_reset(fctx
->timer
, isc_timertype_once
,
685 &fctx
->expires
, interval
, ISC_FALSE
));
689 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
690 * we use fctx_stopidletimer for readability in the code below.
692 #define fctx_stopidletimer fctx_starttimer
696 resquery_destroy(resquery_t
**queryp
) {
699 REQUIRE(queryp
!= NULL
);
701 REQUIRE(!ISC_LINK_LINKED(query
, link
));
703 INSIST(query
->tcpsocket
== NULL
);
705 query
->fctx
->nqueries
--;
706 if (SHUTTINGDOWN(query
->fctx
))
707 maybe_destroy(query
->fctx
); /* Locks bucket. */
709 isc_mem_put(query
->mctx
, query
, sizeof(*query
));
714 fctx_cancelquery(resquery_t
**queryp
, dns_dispatchevent_t
**deventp
,
715 isc_time_t
*finish
, isc_boolean_t no_response
)
719 unsigned int rtt
, rttms
;
722 dns_adbaddrinfo_t
*addrinfo
;
723 isc_socket_t
*socket
;
728 FCTXTRACE("cancelquery");
730 REQUIRE(!RESQUERY_CANCELED(query
));
732 query
->attributes
|= RESQUERY_ATTR_CANCELED
;
735 * Should we update the RTT?
737 if (finish
!= NULL
|| no_response
) {
738 if (finish
!= NULL
) {
740 * We have both the start and finish times for this
741 * packet, so we can compute a real RTT.
743 rtt
= (unsigned int)isc_time_microdiff(finish
,
745 factor
= DNS_ADB_RTTADJDEFAULT
;
748 if (rttms
< DNS_RESOLVER_QRYRTTCLASS0
) {
750 dns_resstatscounter_queryrtt0
);
751 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS1
) {
753 dns_resstatscounter_queryrtt1
);
754 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS2
) {
756 dns_resstatscounter_queryrtt2
);
757 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS3
) {
759 dns_resstatscounter_queryrtt3
);
760 } else if (rttms
< DNS_RESOLVER_QRYRTTCLASS4
) {
762 dns_resstatscounter_queryrtt4
);
765 dns_resstatscounter_queryrtt5
);
769 * We don't have an RTT for this query. Maybe the
770 * packet was lost, or maybe this server is very
771 * slow. We don't know. Increase the RTT.
774 rtt
= query
->addrinfo
->srtt
+ 200000;
778 * Replace the current RTT with our value.
780 factor
= DNS_ADB_RTTADJREPLACE
;
782 dns_adb_adjustsrtt(fctx
->adb
, query
->addrinfo
, rtt
, factor
);
786 * Age RTTs of servers not tried.
788 factor
= DNS_ADB_RTTADJAGE
;
790 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
792 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
793 if (UNMARKED(addrinfo
))
794 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
797 if (finish
!= NULL
&& TRIEDFIND(fctx
))
798 for (find
= ISC_LIST_HEAD(fctx
->finds
);
800 find
= ISC_LIST_NEXT(find
, publink
))
801 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
803 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
804 if (UNMARKED(addrinfo
))
805 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
808 if (finish
!= NULL
&& TRIEDALT(fctx
)) {
809 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
811 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
812 if (UNMARKED(addrinfo
))
813 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
815 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
817 find
= ISC_LIST_NEXT(find
, publink
))
818 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
820 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
))
821 if (UNMARKED(addrinfo
))
822 dns_adb_adjustsrtt(fctx
->adb
, addrinfo
,
827 * Check for any outstanding socket events. If they exist, cancel
828 * them and let the event handlers finish the cleanup. The resolver
829 * only needs to worry about managing the connect and send events;
830 * the dispatcher manages the recv events.
832 if (RESQUERY_CONNECTING(query
)) {
834 * Cancel the connect.
836 if (query
->tcpsocket
!= NULL
) {
837 isc_socket_cancel(query
->tcpsocket
, NULL
,
838 ISC_SOCKCANCEL_CONNECT
);
839 } else if (query
->dispentry
!= NULL
) {
840 INSIST(query
->exclusivesocket
);
841 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
843 isc_socket_cancel(socket
, NULL
,
844 ISC_SOCKCANCEL_CONNECT
);
846 } else if (RESQUERY_SENDING(query
)) {
848 * Cancel the pending send.
850 if (query
->exclusivesocket
&& query
->dispentry
!= NULL
)
851 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
853 socket
= dns_dispatch_getsocket(query
->dispatch
);
855 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_SEND
);
858 if (query
->dispentry
!= NULL
)
859 dns_dispatch_removeresponse(&query
->dispentry
, deventp
);
861 ISC_LIST_UNLINK(fctx
->queries
, query
, link
);
863 if (query
->tsig
!= NULL
)
864 isc_buffer_free(&query
->tsig
);
866 if (query
->tsigkey
!= NULL
)
867 dns_tsigkey_detach(&query
->tsigkey
);
869 if (query
->dispatch
!= NULL
)
870 dns_dispatch_detach(&query
->dispatch
);
872 if (! (RESQUERY_CONNECTING(query
) || RESQUERY_SENDING(query
)))
874 * It's safe to destroy the query now.
876 resquery_destroy(&query
);
880 fctx_cancelqueries(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
881 resquery_t
*query
, *next_query
;
883 FCTXTRACE("cancelqueries");
885 for (query
= ISC_LIST_HEAD(fctx
->queries
);
887 query
= next_query
) {
888 next_query
= ISC_LIST_NEXT(query
, link
);
889 fctx_cancelquery(&query
, NULL
, NULL
, no_response
);
894 fctx_cleanupfinds(fetchctx_t
*fctx
) {
895 dns_adbfind_t
*find
, *next_find
;
897 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
899 for (find
= ISC_LIST_HEAD(fctx
->finds
);
902 next_find
= ISC_LIST_NEXT(find
, publink
);
903 ISC_LIST_UNLINK(fctx
->finds
, find
, publink
);
904 dns_adb_destroyfind(&find
);
910 fctx_cleanupaltfinds(fetchctx_t
*fctx
) {
911 dns_adbfind_t
*find
, *next_find
;
913 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
915 for (find
= ISC_LIST_HEAD(fctx
->altfinds
);
918 next_find
= ISC_LIST_NEXT(find
, publink
);
919 ISC_LIST_UNLINK(fctx
->altfinds
, find
, publink
);
920 dns_adb_destroyfind(&find
);
922 fctx
->altfind
= NULL
;
926 fctx_cleanupforwaddrs(fetchctx_t
*fctx
) {
927 dns_adbaddrinfo_t
*addr
, *next_addr
;
929 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
931 for (addr
= ISC_LIST_HEAD(fctx
->forwaddrs
);
934 next_addr
= ISC_LIST_NEXT(addr
, publink
);
935 ISC_LIST_UNLINK(fctx
->forwaddrs
, addr
, publink
);
936 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
941 fctx_cleanupaltaddrs(fetchctx_t
*fctx
) {
942 dns_adbaddrinfo_t
*addr
, *next_addr
;
944 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
946 for (addr
= ISC_LIST_HEAD(fctx
->altaddrs
);
949 next_addr
= ISC_LIST_NEXT(addr
, publink
);
950 ISC_LIST_UNLINK(fctx
->altaddrs
, addr
, publink
);
951 dns_adb_freeaddrinfo(fctx
->adb
, &addr
);
956 fctx_stopeverything(fetchctx_t
*fctx
, isc_boolean_t no_response
) {
957 FCTXTRACE("stopeverything");
958 fctx_cancelqueries(fctx
, no_response
);
959 fctx_cleanupfinds(fctx
);
960 fctx_cleanupaltfinds(fctx
);
961 fctx_cleanupforwaddrs(fctx
);
962 fctx_cleanupaltaddrs(fctx
);
963 fctx_stoptimer(fctx
);
967 fctx_sendevents(fetchctx_t
*fctx
, isc_result_t result
, int line
) {
968 dns_fetchevent_t
*event
, *next_event
;
970 unsigned int count
= 0;
972 isc_boolean_t logit
= ISC_FALSE
;
974 unsigned int old_spillat
;
975 unsigned int new_spillat
= 0; /* initialized to silence
979 * Caller must be holding the appropriate bucket lock.
981 REQUIRE(fctx
->state
== fetchstate_done
);
983 FCTXTRACE("sendevents");
986 * Keep some record of fetch result for logging later (if required).
988 fctx
->result
= result
;
989 fctx
->exitline
= line
;
991 fctx
->duration
= isc_time_microdiff(&now
, &fctx
->start
);
993 for (event
= ISC_LIST_HEAD(fctx
->events
);
995 event
= next_event
) {
996 next_event
= ISC_LIST_NEXT(event
, ev_link
);
997 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
998 task
= event
->ev_sender
;
999 event
->ev_sender
= fctx
;
1000 if (!HAVE_ANSWER(fctx
))
1001 event
->result
= result
;
1003 INSIST(result
!= ISC_R_SUCCESS
||
1004 dns_rdataset_isassociated(event
->rdataset
) ||
1005 fctx
->type
== dns_rdatatype_any
||
1006 fctx
->type
== dns_rdatatype_rrsig
||
1007 fctx
->type
== dns_rdatatype_sig
);
1010 * Negative results must be indicated in event->result.
1012 if (dns_rdataset_isassociated(event
->rdataset
) &&
1013 event
->rdataset
->type
== dns_rdatatype_none
) {
1014 INSIST(event
->result
== DNS_R_NCACHENXDOMAIN
||
1015 event
->result
== DNS_R_NCACHENXRRSET
);
1018 isc_task_sendanddetach(&task
, ISC_EVENT_PTR(&event
));
1022 if ((fctx
->attributes
& FCTX_ATTR_HAVEANSWER
) != 0 &&
1024 (count
< fctx
->res
->spillatmax
|| fctx
->res
->spillatmax
== 0)) {
1025 LOCK(&fctx
->res
->lock
);
1026 if (count
== fctx
->res
->spillat
&& !fctx
->res
->exiting
) {
1027 old_spillat
= fctx
->res
->spillat
;
1028 fctx
->res
->spillat
+= 5;
1029 if (fctx
->res
->spillat
> fctx
->res
->spillatmax
&&
1030 fctx
->res
->spillatmax
!= 0)
1031 fctx
->res
->spillat
= fctx
->res
->spillatmax
;
1032 new_spillat
= fctx
->res
->spillat
;
1033 if (new_spillat
!= old_spillat
) {
1036 isc_interval_set(&i
, 20 * 60, 0);
1037 result
= isc_timer_reset(fctx
->res
->spillattimer
,
1038 isc_timertype_ticker
, NULL
,
1040 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1042 UNLOCK(&fctx
->res
->lock
);
1044 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
1045 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
1046 "clients-per-query increased to %u",
1052 log_edns(fetchctx_t
*fctx
) {
1053 char domainbuf
[DNS_NAME_FORMATSIZE
];
1055 if (fctx
->reason
== NULL
)
1058 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
1059 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_EDNS_DISABLED
,
1060 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
1061 "too many timeouts resolving '%s' (in '%s'?): %s",
1062 fctx
->info
, domainbuf
, fctx
->reason
);
1064 fctx
->reason
= NULL
;
1068 fctx_done(fetchctx_t
*fctx
, isc_result_t result
, int line
) {
1069 dns_resolver_t
*res
;
1070 isc_boolean_t no_response
;
1078 if (result
== ISC_R_SUCCESS
) {
1080 * Log any deferred EDNS timeout messages.
1083 no_response
= ISC_TRUE
;
1085 no_response
= ISC_FALSE
;
1087 fctx
->reason
= NULL
;
1088 fctx_stopeverything(fctx
, no_response
);
1090 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
1092 fctx
->state
= fetchstate_done
;
1093 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1094 fctx_sendevents(fctx
, result
, line
);
1096 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
1100 process_sendevent(resquery_t
*query
, isc_event_t
*event
) {
1101 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1102 isc_boolean_t retry
= ISC_FALSE
;
1103 isc_result_t result
;
1108 if (RESQUERY_CANCELED(query
)) {
1109 if (query
->sends
== 0 && query
->connects
== 0) {
1111 * This query was canceled while the
1112 * isc_socket_sendto/connect() was in progress.
1114 if (query
->tcpsocket
!= NULL
)
1115 isc_socket_detach(&query
->tcpsocket
);
1116 resquery_destroy(&query
);
1119 switch (sevent
->result
) {
1123 case ISC_R_HOSTUNREACH
:
1124 case ISC_R_NETUNREACH
:
1126 case ISC_R_ADDRNOTAVAIL
:
1127 case ISC_R_CONNREFUSED
:
1130 * No route to remote.
1132 add_bad(fctx
, query
->addrinfo
, sevent
->result
,
1134 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
1139 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
1144 isc_event_free(&event
);
1148 * Behave as if the idle timer has expired. For TCP
1149 * this may not actually reflect the latest timer.
1151 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
1152 result
= fctx_stopidletimer(fctx
);
1153 if (result
!= ISC_R_SUCCESS
)
1154 fctx_done(fctx
, result
, __LINE__
);
1156 fctx_try(fctx
, ISC_TRUE
);
1161 resquery_udpconnected(isc_task_t
*task
, isc_event_t
*event
) {
1162 resquery_t
*query
= event
->ev_arg
;
1164 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1166 QTRACE("udpconnected");
1170 INSIST(RESQUERY_CONNECTING(query
));
1174 process_sendevent(query
, event
);
1178 resquery_senddone(isc_task_t
*task
, isc_event_t
*event
) {
1179 resquery_t
*query
= event
->ev_arg
;
1181 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1188 * Currently we don't wait for the senddone event before retrying
1189 * a query. This means that if we get really behind, we may end
1190 * up doing extra work!
1195 INSIST(RESQUERY_SENDING(query
));
1199 process_sendevent(query
, event
);
1202 static inline isc_result_t
1203 fctx_addopt(dns_message_t
*message
, unsigned int version
,
1204 isc_uint16_t udpsize
, isc_boolean_t request_nsid
)
1206 dns_rdataset_t
*rdataset
;
1207 dns_rdatalist_t
*rdatalist
;
1209 isc_result_t result
;
1212 result
= dns_message_gettemprdatalist(message
, &rdatalist
);
1213 if (result
!= ISC_R_SUCCESS
)
1216 result
= dns_message_gettemprdata(message
, &rdata
);
1217 if (result
!= ISC_R_SUCCESS
)
1220 result
= dns_message_gettemprdataset(message
, &rdataset
);
1221 if (result
!= ISC_R_SUCCESS
)
1223 dns_rdataset_init(rdataset
);
1225 rdatalist
->type
= dns_rdatatype_opt
;
1226 rdatalist
->covers
= 0;
1229 * Set Maximum UDP buffer size.
1231 rdatalist
->rdclass
= udpsize
;
1234 * Set EXTENDED-RCODE and Z to 0, DO to 1.
1236 rdatalist
->ttl
= (version
<< 16);
1237 rdatalist
->ttl
|= DNS_MESSAGEEXTFLAG_DO
;
1240 * Set EDNS options if applicable
1243 /* Send empty NSID option (RFC5001) */
1244 unsigned char data
[4];
1247 isc_buffer_init(&buf
, data
, sizeof(data
));
1248 isc_buffer_putuint16(&buf
, DNS_OPT_NSID
);
1249 isc_buffer_putuint16(&buf
, 0);
1251 rdata
->length
= sizeof(data
);
1257 rdata
->rdclass
= rdatalist
->rdclass
;
1258 rdata
->type
= rdatalist
->type
;
1261 ISC_LIST_INIT(rdatalist
->rdata
);
1262 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1263 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
) == ISC_R_SUCCESS
);
1265 return (dns_message_setopt(message
, rdataset
));
1269 fctx_setretryinterval(fetchctx_t
*fctx
, unsigned int rtt
) {
1270 unsigned int seconds
;
1274 * We retry every .8 seconds the first two times through the address
1275 * list, and then we do exponential back-off.
1277 if (fctx
->restarts
< 3)
1280 us
= (800000 << (fctx
->restarts
- 2));
1283 * Double the round-trip time.
1288 * Always wait for at least the doubled round-trip time.
1294 * But don't ever wait for more than 10 seconds.
1299 seconds
= us
/ 1000000;
1300 us
-= seconds
* 1000000;
1301 isc_interval_set(&fctx
->interval
, seconds
, us
* 1000);
1305 fctx_query(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
1306 unsigned int options
)
1308 dns_resolver_t
*res
;
1310 isc_result_t result
;
1312 isc_sockaddr_t addr
;
1313 isc_boolean_t have_addr
= ISC_FALSE
;
1318 task
= res
->buckets
[fctx
->bucketnum
].task
;
1320 fctx_setretryinterval(fctx
, addrinfo
->srtt
);
1321 result
= fctx_startidletimer(fctx
, &fctx
->interval
);
1322 if (result
!= ISC_R_SUCCESS
)
1325 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
1327 dns_message_reset(fctx
->rmessage
, DNS_MESSAGE_INTENTPARSE
);
1329 query
= isc_mem_get(res
->buckets
[fctx
->bucketnum
].mctx
,
1331 if (query
== NULL
) {
1332 result
= ISC_R_NOMEMORY
;
1333 goto stop_idle_timer
;
1335 query
->mctx
= res
->buckets
[fctx
->bucketnum
].mctx
;
1336 query
->options
= options
;
1337 query
->attributes
= 0;
1339 query
->connects
= 0;
1341 * Note that the caller MUST guarantee that 'addrinfo' will remain
1342 * valid until this query is canceled.
1344 query
->addrinfo
= addrinfo
;
1345 TIME_NOW(&query
->start
);
1348 * If this is a TCP query, then we need to make a socket and
1349 * a dispatch for it here. Otherwise we use the resolver's
1352 query
->dispatchmgr
= res
->dispatchmgr
;
1353 query
->dispatch
= NULL
;
1354 query
->exclusivesocket
= ISC_FALSE
;
1355 query
->tcpsocket
= NULL
;
1356 if (res
->view
->peers
!= NULL
) {
1357 dns_peer_t
*peer
= NULL
;
1358 isc_netaddr_t dstip
;
1359 isc_netaddr_fromsockaddr(&dstip
, &addrinfo
->sockaddr
);
1360 result
= dns_peerlist_peerbyaddr(res
->view
->peers
,
1362 if (result
== ISC_R_SUCCESS
) {
1363 result
= dns_peer_getquerysource(peer
, &addr
);
1364 if (result
== ISC_R_SUCCESS
)
1365 have_addr
= ISC_TRUE
;
1369 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1372 pf
= isc_sockaddr_pf(&addrinfo
->sockaddr
);
1377 dns_dispatch_getlocaladdress(res
->dispatchv4
,
1382 dns_dispatch_getlocaladdress(res
->dispatchv6
,
1386 result
= ISC_R_NOTIMPLEMENTED
;
1389 if (result
!= ISC_R_SUCCESS
)
1392 isc_sockaddr_setport(&addr
, 0);
1394 result
= isc_socket_create(res
->socketmgr
, pf
,
1397 if (result
!= ISC_R_SUCCESS
)
1400 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1401 result
= isc_socket_bind(query
->tcpsocket
, &addr
, 0);
1402 if (result
!= ISC_R_SUCCESS
)
1403 goto cleanup_socket
;
1407 * A dispatch will be created once the connect succeeds.
1411 unsigned int attrs
, attrmask
;
1412 attrs
= DNS_DISPATCHATTR_UDP
;
1413 switch (isc_sockaddr_pf(&addr
)) {
1415 attrs
|= DNS_DISPATCHATTR_IPV4
;
1418 attrs
|= DNS_DISPATCHATTR_IPV6
;
1421 result
= ISC_R_NOTIMPLEMENTED
;
1424 attrmask
= DNS_DISPATCHATTR_UDP
;
1425 attrmask
|= DNS_DISPATCHATTR_TCP
;
1426 attrmask
|= DNS_DISPATCHATTR_IPV4
;
1427 attrmask
|= DNS_DISPATCHATTR_IPV6
;
1428 result
= dns_dispatch_getudp(res
->dispatchmgr
,
1430 res
->taskmgr
, &addr
,
1431 4096, 1000, 32768, 16411,
1432 16433, attrs
, attrmask
,
1434 if (result
!= ISC_R_SUCCESS
)
1437 switch (isc_sockaddr_pf(&addrinfo
->sockaddr
)) {
1439 dns_dispatch_attach(res
->dispatchv4
,
1441 query
->exclusivesocket
= res
->exclusivev4
;
1444 dns_dispatch_attach(res
->dispatchv6
,
1446 query
->exclusivesocket
= res
->exclusivev6
;
1449 result
= ISC_R_NOTIMPLEMENTED
;
1454 * We should always have a valid dispatcher here. If we
1455 * don't support a protocol family, then its dispatcher
1456 * will be NULL, but we shouldn't be finding addresses for
1457 * protocol types we don't support, so the dispatcher
1458 * we found should never be NULL.
1460 INSIST(query
->dispatch
!= NULL
);
1463 query
->dispentry
= NULL
;
1466 query
->tsigkey
= NULL
;
1467 ISC_LINK_INIT(query
, link
);
1468 query
->magic
= QUERY_MAGIC
;
1470 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1472 * Connect to the remote server.
1474 * XXXRTH Should we attach to the socket?
1476 result
= isc_socket_connect(query
->tcpsocket
,
1477 &addrinfo
->sockaddr
, task
,
1478 resquery_connected
, query
);
1479 if (result
!= ISC_R_SUCCESS
)
1480 goto cleanup_socket
;
1482 QTRACE("connecting via TCP");
1484 result
= resquery_send(query
);
1485 if (result
!= ISC_R_SUCCESS
)
1486 goto cleanup_dispatch
;
1490 ISC_LIST_APPEND(fctx
->queries
, query
, link
);
1491 query
->fctx
->nqueries
++;
1492 if (isc_sockaddr_pf(&addrinfo
->sockaddr
) == PF_INET
)
1493 inc_stats(res
, dns_resstatscounter_queryv4
);
1495 inc_stats(res
, dns_resstatscounter_queryv6
);
1496 if (res
->view
->resquerystats
!= NULL
)
1497 dns_rdatatypestats_increment(res
->view
->resquerystats
,
1500 return (ISC_R_SUCCESS
);
1503 isc_socket_detach(&query
->tcpsocket
);
1506 if (query
->dispatch
!= NULL
)
1507 dns_dispatch_detach(&query
->dispatch
);
1511 isc_mem_put(res
->buckets
[fctx
->bucketnum
].mctx
,
1512 query
, sizeof(*query
));
1515 RUNTIME_CHECK(fctx_stopidletimer(fctx
) == ISC_R_SUCCESS
);
1520 static isc_boolean_t
1521 triededns(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1524 for (sa
= ISC_LIST_HEAD(fctx
->edns
);
1526 sa
= ISC_LIST_NEXT(sa
, link
)) {
1527 if (isc_sockaddr_equal(sa
, address
))
1535 add_triededns(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1538 if (triededns(fctx
, address
))
1541 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
1547 ISC_LIST_INITANDAPPEND(fctx
->edns
, sa
, link
);
1550 static isc_boolean_t
1551 triededns512(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1554 for (sa
= ISC_LIST_HEAD(fctx
->edns512
);
1556 sa
= ISC_LIST_NEXT(sa
, link
)) {
1557 if (isc_sockaddr_equal(sa
, address
))
1565 add_triededns512(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
1568 if (triededns512(fctx
, address
))
1571 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
1577 ISC_LIST_INITANDAPPEND(fctx
->edns512
, sa
, link
);
1581 resquery_send(resquery_t
*query
) {
1583 isc_result_t result
;
1584 dns_name_t
*qname
= NULL
;
1585 dns_rdataset_t
*qrdataset
= NULL
;
1587 dns_resolver_t
*res
;
1589 isc_socket_t
*socket
;
1590 isc_buffer_t tcpbuffer
;
1591 isc_sockaddr_t
*address
;
1592 isc_buffer_t
*buffer
;
1593 isc_netaddr_t ipaddr
;
1594 dns_tsigkey_t
*tsigkey
= NULL
;
1595 dns_peer_t
*peer
= NULL
;
1596 isc_boolean_t useedns
;
1597 dns_compress_t cctx
;
1598 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
1599 isc_boolean_t secure_domain
;
1605 task
= res
->buckets
[fctx
->bucketnum
].task
;
1608 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1610 * Reserve space for the TCP message length.
1612 isc_buffer_init(&tcpbuffer
, query
->data
, sizeof(query
->data
));
1613 isc_buffer_init(&query
->buffer
, query
->data
+ 2,
1614 sizeof(query
->data
) - 2);
1615 buffer
= &tcpbuffer
;
1617 isc_buffer_init(&query
->buffer
, query
->data
,
1618 sizeof(query
->data
));
1619 buffer
= &query
->buffer
;
1622 result
= dns_message_gettempname(fctx
->qmessage
, &qname
);
1623 if (result
!= ISC_R_SUCCESS
)
1625 result
= dns_message_gettemprdataset(fctx
->qmessage
, &qrdataset
);
1626 if (result
!= ISC_R_SUCCESS
)
1630 * Get a query id from the dispatch.
1632 result
= dns_dispatch_addresponse2(query
->dispatch
,
1633 &query
->addrinfo
->sockaddr
,
1640 if (result
!= ISC_R_SUCCESS
)
1643 fctx
->qmessage
->opcode
= dns_opcode_query
;
1648 dns_name_init(qname
, NULL
);
1649 dns_name_clone(&fctx
->name
, qname
);
1650 dns_rdataset_init(qrdataset
);
1651 dns_rdataset_makequestion(qrdataset
, res
->rdclass
, fctx
->type
);
1652 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
1653 dns_message_addname(fctx
->qmessage
, qname
, DNS_SECTION_QUESTION
);
1658 * Set RD if the client has requested that we do a recursive query,
1659 * or if we're sending to a forwarder.
1661 if ((query
->options
& DNS_FETCHOPT_RECURSIVE
) != 0 ||
1662 ISFORWARDER(query
->addrinfo
))
1663 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_RD
;
1666 * Set CD if the client says don't validate or the question is
1667 * under a secure entry point.
1669 if ((query
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0) {
1670 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1671 } else if (res
->view
->enablevalidation
) {
1672 result
= dns_keytable_issecuredomain(res
->view
->secroots
,
1675 if (result
!= ISC_R_SUCCESS
)
1676 secure_domain
= ISC_FALSE
;
1677 if (res
->view
->dlv
!= NULL
)
1678 secure_domain
= ISC_TRUE
;
1680 fctx
->qmessage
->flags
|= DNS_MESSAGEFLAG_CD
;
1684 * We don't have to set opcode because it defaults to query.
1686 fctx
->qmessage
->id
= query
->id
;
1689 * Convert the question to wire format.
1691 result
= dns_compress_init(&cctx
, -1, fctx
->res
->mctx
);
1692 if (result
!= ISC_R_SUCCESS
)
1693 goto cleanup_message
;
1694 cleanup_cctx
= ISC_TRUE
;
1696 result
= dns_message_renderbegin(fctx
->qmessage
, &cctx
,
1698 if (result
!= ISC_R_SUCCESS
)
1699 goto cleanup_message
;
1701 result
= dns_message_rendersection(fctx
->qmessage
,
1702 DNS_SECTION_QUESTION
, 0);
1703 if (result
!= ISC_R_SUCCESS
)
1704 goto cleanup_message
;
1707 isc_netaddr_fromsockaddr(&ipaddr
, &query
->addrinfo
->sockaddr
);
1708 (void) dns_peerlist_peerbyaddr(fctx
->res
->view
->peers
, &ipaddr
, &peer
);
1711 * The ADB does not know about servers with "edns no". Check this,
1712 * and then inform the ADB for future use.
1714 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0 &&
1716 dns_peer_getsupportedns(peer
, &useedns
) == ISC_R_SUCCESS
&&
1719 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1720 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
1721 DNS_FETCHOPT_NOEDNS0
,
1722 DNS_FETCHOPT_NOEDNS0
);
1725 /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
1726 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) != 0)
1727 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1730 * Handle timeouts by reducing the UDP response size to 512 bytes
1731 * then if that doesn't work disabling EDNS (includes DO) and CD.
1733 * These timeout can be due to:
1734 * * broken nameservers that don't respond to EDNS queries.
1735 * * broken/misconfigured firewalls and NAT implementations
1736 * that don't handle IP fragmentation.
1737 * * broken/misconfigured firewalls that don't handle responses
1738 * greater than 512 bytes.
1739 * * broken/misconfigured firewalls that don't handle EDNS, DO
1741 * * packet loss / link outage.
1743 if (fctx
->timeout
) {
1744 if ((triededns512(fctx
, &query
->addrinfo
->sockaddr
) ||
1745 fctx
->timeouts
>= (MAX_EDNS0_TIMEOUTS
* 2)) &&
1746 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1747 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1748 fctx
->reason
= "disabling EDNS";
1749 } else if ((triededns(fctx
, &query
->addrinfo
->sockaddr
) ||
1750 fctx
->timeouts
>= MAX_EDNS0_TIMEOUTS
) &&
1751 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1752 query
->options
|= DNS_FETCHOPT_EDNS512
;
1753 fctx
->reason
= "reducing the advertised EDNS UDP "
1754 "packet size to 512 octets";
1756 fctx
->timeout
= ISC_FALSE
;
1760 * Use EDNS0, unless the caller doesn't want it, or we know that
1761 * the remote server doesn't like it.
1763 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1764 if ((query
->addrinfo
->flags
& DNS_FETCHOPT_NOEDNS0
) == 0) {
1765 unsigned int version
= 0; /* Default version. */
1767 isc_uint16_t udpsize
= res
->udpsize
;
1768 isc_boolean_t reqnsid
= res
->view
->requestnsid
;
1770 flags
= query
->addrinfo
->flags
;
1771 if ((flags
& DNS_FETCHOPT_EDNSVERSIONSET
) != 0) {
1772 version
= flags
& DNS_FETCHOPT_EDNSVERSIONMASK
;
1773 version
>>= DNS_FETCHOPT_EDNSVERSIONSHIFT
;
1775 if ((query
->options
& DNS_FETCHOPT_EDNS512
) != 0)
1777 else if (peer
!= NULL
)
1778 (void)dns_peer_getudpsize(peer
, &udpsize
);
1780 /* request NSID for current view or peer? */
1782 (void) dns_peer_getrequestnsid(peer
, &reqnsid
);
1783 result
= fctx_addopt(fctx
->qmessage
, version
,
1785 if (reqnsid
&& result
== ISC_R_SUCCESS
) {
1786 query
->options
|= DNS_FETCHOPT_WANTNSID
;
1787 } else if (result
!= ISC_R_SUCCESS
) {
1789 * We couldn't add the OPT, but we'll press on.
1790 * We're not using EDNS0, so set the NOEDNS0
1793 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1797 * We know this server doesn't like EDNS0, so we
1798 * won't use it. Set the NOEDNS0 bit since we're
1801 query
->options
|= DNS_FETCHOPT_NOEDNS0
;
1806 * If we need EDNS0 to do this query and aren't using it, we lose.
1808 if (NEEDEDNS0(fctx
) && (query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0) {
1809 result
= DNS_R_SERVFAIL
;
1810 goto cleanup_message
;
1813 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0)
1814 add_triededns(fctx
, &query
->addrinfo
->sockaddr
);
1816 if ((query
->options
& DNS_FETCHOPT_EDNS512
) != 0)
1817 add_triededns512(fctx
, &query
->addrinfo
->sockaddr
);
1820 * Clear CD if EDNS is not in use.
1822 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) != 0)
1823 fctx
->qmessage
->flags
&= ~DNS_MESSAGEFLAG_CD
;
1826 * Add TSIG record tailored to the current recipient.
1828 result
= dns_view_getpeertsig(fctx
->res
->view
, &ipaddr
, &tsigkey
);
1829 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
1830 goto cleanup_message
;
1832 if (tsigkey
!= NULL
) {
1833 result
= dns_message_settsigkey(fctx
->qmessage
, tsigkey
);
1834 dns_tsigkey_detach(&tsigkey
);
1835 if (result
!= ISC_R_SUCCESS
)
1836 goto cleanup_message
;
1839 result
= dns_message_rendersection(fctx
->qmessage
,
1840 DNS_SECTION_ADDITIONAL
, 0);
1841 if (result
!= ISC_R_SUCCESS
)
1842 goto cleanup_message
;
1844 result
= dns_message_renderend(fctx
->qmessage
);
1845 if (result
!= ISC_R_SUCCESS
)
1846 goto cleanup_message
;
1848 dns_compress_invalidate(&cctx
);
1849 cleanup_cctx
= ISC_FALSE
;
1851 if (dns_message_gettsigkey(fctx
->qmessage
) != NULL
) {
1852 dns_tsigkey_attach(dns_message_gettsigkey(fctx
->qmessage
),
1854 result
= dns_message_getquerytsig(fctx
->qmessage
,
1857 if (result
!= ISC_R_SUCCESS
)
1858 goto cleanup_message
;
1862 * If using TCP, write the length of the message at the beginning
1865 if ((query
->options
& DNS_FETCHOPT_TCP
) != 0) {
1866 isc_buffer_usedregion(&query
->buffer
, &r
);
1867 isc_buffer_putuint16(&tcpbuffer
, (isc_uint16_t
)r
.length
);
1868 isc_buffer_add(&tcpbuffer
, r
.length
);
1872 * We're now done with the query message.
1874 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1876 if (query
->exclusivesocket
)
1877 socket
= dns_dispatch_getentrysocket(query
->dispentry
);
1879 socket
= dns_dispatch_getsocket(query
->dispatch
);
1883 if ((query
->options
& DNS_FETCHOPT_TCP
) == 0) {
1884 address
= &query
->addrinfo
->sockaddr
;
1885 if (query
->exclusivesocket
) {
1886 result
= isc_socket_connect(socket
, address
, task
,
1887 resquery_udpconnected
,
1889 if (result
!= ISC_R_SUCCESS
)
1890 goto cleanup_message
;
1894 isc_buffer_usedregion(buffer
, &r
);
1897 * XXXRTH Make sure we don't send to ourselves! We should probably
1898 * prune out these addresses when we get them from the ADB.
1900 result
= isc_socket_sendto(socket
, &r
, task
, resquery_senddone
,
1901 query
, address
, NULL
);
1902 if (result
!= ISC_R_SUCCESS
)
1903 goto cleanup_message
;
1909 return (ISC_R_SUCCESS
);
1913 dns_compress_invalidate(&cctx
);
1915 dns_message_reset(fctx
->qmessage
, DNS_MESSAGE_INTENTRENDER
);
1918 * Stop the dispatcher from listening.
1920 dns_dispatch_removeresponse(&query
->dispentry
, NULL
);
1924 dns_message_puttempname(fctx
->qmessage
, &qname
);
1925 if (qrdataset
!= NULL
)
1926 dns_message_puttemprdataset(fctx
->qmessage
, &qrdataset
);
1932 resquery_connected(isc_task_t
*task
, isc_event_t
*event
) {
1933 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1934 resquery_t
*query
= event
->ev_arg
;
1935 isc_boolean_t retry
= ISC_FALSE
;
1936 isc_interval_t interval
;
1937 isc_result_t result
;
1941 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1942 REQUIRE(VALID_QUERY(query
));
1944 QTRACE("connected");
1951 * Currently we don't wait for the connect event before retrying
1952 * a query. This means that if we get really behind, we may end
1953 * up doing extra work!
1959 if (RESQUERY_CANCELED(query
)) {
1961 * This query was canceled while the connect() was in
1964 isc_socket_detach(&query
->tcpsocket
);
1965 resquery_destroy(&query
);
1967 switch (sevent
->result
) {
1971 * Extend the idle timer for TCP. 20 seconds
1972 * should be long enough for a TCP connection to be
1973 * established, a single DNS request to be sent,
1974 * and the response received.
1976 isc_interval_set(&interval
, 20, 0);
1977 result
= fctx_startidletimer(query
->fctx
, &interval
);
1978 if (result
!= ISC_R_SUCCESS
) {
1979 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
1980 fctx_done(fctx
, result
, __LINE__
);
1984 * We are connected. Create a dispatcher and
1988 attrs
|= DNS_DISPATCHATTR_TCP
;
1989 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
1990 attrs
|= DNS_DISPATCHATTR_CONNECTED
;
1991 if (isc_sockaddr_pf(&query
->addrinfo
->sockaddr
) ==
1993 attrs
|= DNS_DISPATCHATTR_IPV4
;
1995 attrs
|= DNS_DISPATCHATTR_IPV6
;
1996 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
1998 result
= dns_dispatch_createtcp(query
->dispatchmgr
,
2000 query
->fctx
->res
->taskmgr
,
2001 4096, 2, 1, 1, 3, attrs
,
2005 * Regardless of whether dns_dispatch_create()
2006 * succeeded or not, we don't need our reference
2007 * to the socket anymore.
2009 isc_socket_detach(&query
->tcpsocket
);
2011 if (result
== ISC_R_SUCCESS
)
2012 result
= resquery_send(query
);
2014 if (result
!= ISC_R_SUCCESS
) {
2015 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
2016 fctx_done(fctx
, result
, __LINE__
);
2020 case ISC_R_NETUNREACH
:
2021 case ISC_R_HOSTUNREACH
:
2022 case ISC_R_CONNREFUSED
:
2024 case ISC_R_ADDRNOTAVAIL
:
2025 case ISC_R_CONNECTIONRESET
:
2027 * No route to remote.
2029 isc_socket_detach(&query
->tcpsocket
);
2030 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
2035 isc_socket_detach(&query
->tcpsocket
);
2036 fctx_cancelquery(&query
, NULL
, NULL
, ISC_FALSE
);
2041 isc_event_free(&event
);
2045 * Behave as if the idle timer has expired. For TCP
2046 * connections this may not actually reflect the latest timer.
2048 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2049 result
= fctx_stopidletimer(fctx
);
2050 if (result
!= ISC_R_SUCCESS
)
2051 fctx_done(fctx
, result
, __LINE__
);
2053 fctx_try(fctx
, ISC_TRUE
);
2058 fctx_finddone(isc_task_t
*task
, isc_event_t
*event
) {
2060 dns_adbfind_t
*find
;
2061 dns_resolver_t
*res
;
2062 isc_boolean_t want_try
= ISC_FALSE
;
2063 isc_boolean_t want_done
= ISC_FALSE
;
2064 isc_boolean_t bucket_empty
= ISC_FALSE
;
2065 unsigned int bucketnum
;
2067 find
= event
->ev_sender
;
2068 fctx
= event
->ev_arg
;
2069 REQUIRE(VALID_FCTX(fctx
));
2074 FCTXTRACE("finddone");
2076 INSIST(fctx
->pending
> 0);
2079 if (ADDRWAIT(fctx
)) {
2081 * The fetch is waiting for a name to be found.
2083 INSIST(!SHUTTINGDOWN(fctx
));
2084 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
2085 if (event
->ev_type
== DNS_EVENT_ADBMOREADDRESSES
)
2086 want_try
= ISC_TRUE
;
2089 if (fctx
->pending
== 0) {
2091 * We've got nothing else to wait for and don't
2092 * know the answer. There's nothing to do but
2095 want_done
= ISC_TRUE
;
2098 } else if (SHUTTINGDOWN(fctx
) && fctx
->pending
== 0 &&
2099 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
)) {
2100 bucketnum
= fctx
->bucketnum
;
2101 LOCK(&res
->buckets
[bucketnum
].lock
);
2103 * Note that we had to wait until we had the lock before
2104 * looking at fctx->references.
2106 if (fctx
->references
== 0)
2107 bucket_empty
= fctx_destroy(fctx
);
2108 UNLOCK(&res
->buckets
[bucketnum
].lock
);
2111 isc_event_free(&event
);
2112 dns_adb_destroyfind(&find
);
2115 fctx_try(fctx
, ISC_TRUE
);
2117 fctx_done(fctx
, ISC_R_FAILURE
, __LINE__
);
2118 else if (bucket_empty
)
2123 static inline isc_boolean_t
2124 bad_server(fetchctx_t
*fctx
, isc_sockaddr_t
*address
) {
2127 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
2129 sa
= ISC_LIST_NEXT(sa
, link
)) {
2130 if (isc_sockaddr_equal(sa
, address
))
2137 static inline isc_boolean_t
2138 mark_bad(fetchctx_t
*fctx
) {
2139 dns_adbfind_t
*curr
;
2140 dns_adbaddrinfo_t
*addrinfo
;
2141 isc_boolean_t all_bad
= ISC_TRUE
;
2144 * Mark all known bad servers, so we don't try to talk to them
2149 * Mark any bad nameservers.
2151 for (curr
= ISC_LIST_HEAD(fctx
->finds
);
2153 curr
= ISC_LIST_NEXT(curr
, publink
)) {
2154 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
2156 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2157 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2158 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2160 all_bad
= ISC_FALSE
;
2165 * Mark any bad forwarders.
2167 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2169 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2170 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2171 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2173 all_bad
= ISC_FALSE
;
2177 * Mark any bad alternates.
2179 for (curr
= ISC_LIST_HEAD(fctx
->altfinds
);
2181 curr
= ISC_LIST_NEXT(curr
, publink
)) {
2182 for (addrinfo
= ISC_LIST_HEAD(curr
->list
);
2184 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2185 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2186 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2188 all_bad
= ISC_FALSE
;
2192 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
2194 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2195 if (bad_server(fctx
, &addrinfo
->sockaddr
))
2196 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2198 all_bad
= ISC_FALSE
;
2205 add_bad(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, isc_result_t reason
,
2206 badnstype_t badtype
)
2208 char namebuf
[DNS_NAME_FORMATSIZE
];
2209 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2215 const char *sep1
, *sep2
;
2216 isc_sockaddr_t
*address
= &addrinfo
->sockaddr
;
2218 if (reason
== DNS_R_LAME
)
2222 case badns_unreachable
:
2225 case badns_response
:
2228 case badns_validation
:
2229 break; /* counted as 'valfail' */
2233 if (bad_server(fctx
, address
)) {
2235 * We already know this server is bad.
2240 FCTXTRACE("add_bad");
2242 sa
= isc_mem_get(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
2247 ISC_LIST_INITANDAPPEND(fctx
->bad
, sa
, link
);
2249 if (reason
== DNS_R_LAME
) /* already logged */
2252 if (reason
== DNS_R_UNEXPECTEDRCODE
&&
2253 fctx
->rmessage
->rcode
== dns_rcode_servfail
&&
2254 ISFORWARDER(addrinfo
))
2257 if (reason
== DNS_R_UNEXPECTEDRCODE
) {
2258 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
2259 dns_rcode_totext(fctx
->rmessage
->rcode
, &b
);
2260 code
[isc_buffer_usedlength(&b
)] = '\0';
2263 } else if (reason
== DNS_R_UNEXPECTEDOPCODE
) {
2264 isc_buffer_init(&b
, code
, sizeof(code
) - 1);
2265 dns_opcode_totext((dns_opcode_t
)fctx
->rmessage
->opcode
, &b
);
2266 code
[isc_buffer_usedlength(&b
)] = '\0';
2274 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
2275 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
2276 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
, sizeof(classbuf
));
2277 isc_sockaddr_format(address
, addrbuf
, sizeof(addrbuf
));
2278 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
2279 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
2280 "%s %s%s%sresolving '%s/%s/%s': %s",
2281 dns_result_totext(reason
), sep1
, code
, sep2
,
2282 namebuf
, typebuf
, classbuf
, addrbuf
);
2286 sort_adbfind(dns_adbfind_t
*find
) {
2287 dns_adbaddrinfo_t
*best
, *curr
;
2288 dns_adbaddrinfolist_t sorted
;
2291 * Lame N^2 bubble sort.
2294 ISC_LIST_INIT(sorted
);
2295 while (!ISC_LIST_EMPTY(find
->list
)) {
2296 best
= ISC_LIST_HEAD(find
->list
);
2297 curr
= ISC_LIST_NEXT(best
, publink
);
2298 while (curr
!= NULL
) {
2299 if (curr
->srtt
< best
->srtt
)
2301 curr
= ISC_LIST_NEXT(curr
, publink
);
2303 ISC_LIST_UNLINK(find
->list
, best
, publink
);
2304 ISC_LIST_APPEND(sorted
, best
, publink
);
2306 find
->list
= sorted
;
2310 sort_finds(fetchctx_t
*fctx
) {
2311 dns_adbfind_t
*best
, *curr
;
2312 dns_adbfindlist_t sorted
;
2313 dns_adbaddrinfo_t
*addrinfo
, *bestaddrinfo
;
2316 * Lame N^2 bubble sort.
2319 ISC_LIST_INIT(sorted
);
2320 while (!ISC_LIST_EMPTY(fctx
->finds
)) {
2321 best
= ISC_LIST_HEAD(fctx
->finds
);
2322 bestaddrinfo
= ISC_LIST_HEAD(best
->list
);
2323 INSIST(bestaddrinfo
!= NULL
);
2324 curr
= ISC_LIST_NEXT(best
, publink
);
2325 while (curr
!= NULL
) {
2326 addrinfo
= ISC_LIST_HEAD(curr
->list
);
2327 INSIST(addrinfo
!= NULL
);
2328 if (addrinfo
->srtt
< bestaddrinfo
->srtt
) {
2330 bestaddrinfo
= addrinfo
;
2332 curr
= ISC_LIST_NEXT(curr
, publink
);
2334 ISC_LIST_UNLINK(fctx
->finds
, best
, publink
);
2335 ISC_LIST_APPEND(sorted
, best
, publink
);
2337 fctx
->finds
= sorted
;
2339 ISC_LIST_INIT(sorted
);
2340 while (!ISC_LIST_EMPTY(fctx
->altfinds
)) {
2341 best
= ISC_LIST_HEAD(fctx
->altfinds
);
2342 bestaddrinfo
= ISC_LIST_HEAD(best
->list
);
2343 INSIST(bestaddrinfo
!= NULL
);
2344 curr
= ISC_LIST_NEXT(best
, publink
);
2345 while (curr
!= NULL
) {
2346 addrinfo
= ISC_LIST_HEAD(curr
->list
);
2347 INSIST(addrinfo
!= NULL
);
2348 if (addrinfo
->srtt
< bestaddrinfo
->srtt
) {
2350 bestaddrinfo
= addrinfo
;
2352 curr
= ISC_LIST_NEXT(curr
, publink
);
2354 ISC_LIST_UNLINK(fctx
->altfinds
, best
, publink
);
2355 ISC_LIST_APPEND(sorted
, best
, publink
);
2357 fctx
->altfinds
= sorted
;
2361 findname(fetchctx_t
*fctx
, dns_name_t
*name
, in_port_t port
,
2362 unsigned int options
, unsigned int flags
, isc_stdtime_t now
,
2363 isc_boolean_t
*need_alternate
)
2365 dns_adbaddrinfo_t
*ai
;
2366 dns_adbfind_t
*find
;
2367 dns_resolver_t
*res
;
2368 isc_boolean_t unshared
;
2369 isc_result_t result
;
2372 unshared
= ISC_TF((fctx
->options
| DNS_FETCHOPT_UNSHARED
) != 0);
2374 * If this name is a subdomain of the query domain, tell
2375 * the ADB to start looking using zone/hint data. This keeps us
2376 * from getting stuck if the nameserver is beneath the zone cut
2377 * and we don't know its address (e.g. because the A record has
2380 if (dns_name_issubdomain(name
, &fctx
->domain
))
2381 options
|= DNS_ADBFIND_STARTATZONE
;
2382 options
|= DNS_ADBFIND_GLUEOK
;
2383 options
|= DNS_ADBFIND_HINTOK
;
2386 * See what we know about this address.
2389 result
= dns_adb_createfind(fctx
->adb
,
2390 res
->buckets
[fctx
->bucketnum
].task
,
2391 fctx_finddone
, fctx
, name
,
2392 &fctx
->name
, fctx
->type
,
2394 res
->view
->dstport
, &find
);
2395 if (result
!= ISC_R_SUCCESS
) {
2396 if (result
== DNS_R_ALIAS
) {
2398 * XXXRTH Follow the CNAME/DNAME chain?
2400 dns_adb_destroyfind(&find
);
2403 } else if (!ISC_LIST_EMPTY(find
->list
)) {
2405 * We have at least some of the addresses for the
2408 INSIST((find
->options
& DNS_ADBFIND_WANTEVENT
) == 0);
2410 if (flags
!= 0 || port
!= 0) {
2411 for (ai
= ISC_LIST_HEAD(find
->list
);
2413 ai
= ISC_LIST_NEXT(ai
, publink
)) {
2416 isc_sockaddr_setport(&ai
->sockaddr
,
2420 if ((flags
& FCTX_ADDRINFO_FORWARDER
) != 0)
2421 ISC_LIST_APPEND(fctx
->altfinds
, find
, publink
);
2423 ISC_LIST_APPEND(fctx
->finds
, find
, publink
);
2426 * We don't know any of the addresses for this
2429 if ((find
->options
& DNS_ADBFIND_WANTEVENT
) != 0) {
2431 * We're looking for them and will get an
2432 * event about it later.
2438 if (need_alternate
!= NULL
&&
2439 !*need_alternate
&& unshared
&&
2440 ((res
->dispatchv4
== NULL
&&
2441 find
->result_v6
!= DNS_R_NXDOMAIN
) ||
2442 (res
->dispatchv6
== NULL
&&
2443 find
->result_v4
!= DNS_R_NXDOMAIN
)))
2444 *need_alternate
= ISC_TRUE
;
2446 if ((find
->options
& DNS_ADBFIND_LAMEPRUNED
) != 0)
2447 fctx
->lamecount
++; /* cached lame server */
2449 fctx
->adberr
++; /* unreachable server, etc. */
2452 * If we know there are no addresses for
2453 * the family we are using then try to add
2454 * an alternative server.
2456 if (need_alternate
!= NULL
&& !*need_alternate
&&
2457 ((res
->dispatchv4
== NULL
&&
2458 find
->result_v6
== DNS_R_NXRRSET
) ||
2459 (res
->dispatchv6
== NULL
&&
2460 find
->result_v4
== DNS_R_NXRRSET
)))
2461 *need_alternate
= ISC_TRUE
;
2462 dns_adb_destroyfind(&find
);
2467 static isc_boolean_t
2468 isstrictsubdomain(dns_name_t
*name1
, dns_name_t
*name2
) {
2470 unsigned int nlabels
;
2471 dns_namereln_t namereln
;
2473 namereln
= dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
2474 return (ISC_TF(namereln
== dns_namereln_subdomain
));
2478 fctx_getaddresses(fetchctx_t
*fctx
) {
2479 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2480 isc_result_t result
;
2481 dns_resolver_t
*res
;
2483 unsigned int stdoptions
;
2485 dns_adbaddrinfo_t
*ai
;
2486 isc_boolean_t all_bad
;
2488 isc_boolean_t need_alternate
= ISC_FALSE
;
2490 FCTXTRACE("getaddresses");
2493 * Don't pound on remote servers. (Failsafe!)
2496 if (fctx
->restarts
> 10) {
2497 FCTXTRACE("too many restarts");
2498 return (DNS_R_SERVFAIL
);
2502 stdoptions
= 0; /* Keep compiler happy. */
2508 INSIST(ISC_LIST_EMPTY(fctx
->forwaddrs
));
2509 INSIST(ISC_LIST_EMPTY(fctx
->altaddrs
));
2512 * If this fctx has forwarders, use them; otherwise use any
2513 * selective forwarders specified in the view; otherwise use the
2514 * resolver's forwarders (if any).
2516 sa
= ISC_LIST_HEAD(fctx
->forwarders
);
2518 dns_forwarders_t
*forwarders
= NULL
;
2519 dns_name_t
*name
= &fctx
->name
;
2521 unsigned int labels
;
2522 dns_fixedname_t fixed
;
2526 * DS records are found in the parent server.
2527 * Strip label to get the correct forwarder (if any).
2529 if (dns_rdatatype_atparent(fctx
->type
) &&
2530 dns_name_countlabels(name
) > 1) {
2531 dns_name_init(&suffix
, NULL
);
2532 labels
= dns_name_countlabels(name
);
2533 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
2537 dns_fixedname_init(&fixed
);
2538 domain
= dns_fixedname_name(&fixed
);
2539 result
= dns_fwdtable_find2(fctx
->res
->view
->fwdtable
, name
,
2540 domain
, &forwarders
);
2541 if (result
== ISC_R_SUCCESS
) {
2542 sa
= ISC_LIST_HEAD(forwarders
->addrs
);
2543 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
2544 if (fctx
->fwdpolicy
== dns_fwdpolicy_only
&&
2545 isstrictsubdomain(domain
, &fctx
->domain
)) {
2548 mctx
= res
->buckets
[fctx
->bucketnum
].mctx
;
2549 dns_name_free(&fctx
->domain
, mctx
);
2550 dns_name_init(&fctx
->domain
, NULL
);
2551 result
= dns_name_dup(domain
, mctx
,
2553 if (result
!= ISC_R_SUCCESS
)
2559 while (sa
!= NULL
) {
2560 if ((isc_sockaddr_pf(sa
) == AF_INET
&&
2561 fctx
->res
->dispatchv4
== NULL
) ||
2562 (isc_sockaddr_pf(sa
) == AF_INET6
&&
2563 fctx
->res
->dispatchv6
== NULL
)) {
2564 sa
= ISC_LIST_NEXT(sa
, link
);
2568 result
= dns_adb_findaddrinfo(fctx
->adb
,
2569 sa
, &ai
, 0); /* XXXMLG */
2570 if (result
== ISC_R_SUCCESS
) {
2571 dns_adbaddrinfo_t
*cur
;
2572 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
2573 cur
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2574 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
2575 cur
= ISC_LIST_NEXT(cur
, publink
);
2577 ISC_LIST_INSERTBEFORE(fctx
->forwaddrs
, cur
,
2580 ISC_LIST_APPEND(fctx
->forwaddrs
, ai
, publink
);
2582 sa
= ISC_LIST_NEXT(sa
, link
);
2586 * If the forwarding policy is "only", we don't need the addresses
2587 * of the nameservers.
2589 if (fctx
->fwdpolicy
== dns_fwdpolicy_only
)
2593 * Normal nameservers.
2596 stdoptions
= DNS_ADBFIND_WANTEVENT
| DNS_ADBFIND_EMPTYEVENT
;
2597 if (fctx
->restarts
== 1) {
2599 * To avoid sending out a flood of queries likely to
2600 * result in NXRRSET, we suppress fetches for address
2601 * families we don't have the first time through,
2602 * provided that we have addresses in some family we
2605 * We don't want to set this option all the time, since
2606 * if fctx->restarts > 1, we've clearly been having trouble
2607 * with the addresses we had, so getting more could help.
2609 stdoptions
|= DNS_ADBFIND_AVOIDFETCHES
;
2611 if (res
->dispatchv4
!= NULL
)
2612 stdoptions
|= DNS_ADBFIND_INET
;
2613 if (res
->dispatchv6
!= NULL
)
2614 stdoptions
|= DNS_ADBFIND_INET6
;
2615 isc_stdtime_get(&now
);
2617 INSIST(ISC_LIST_EMPTY(fctx
->finds
));
2618 INSIST(ISC_LIST_EMPTY(fctx
->altfinds
));
2620 for (result
= dns_rdataset_first(&fctx
->nameservers
);
2621 result
== ISC_R_SUCCESS
;
2622 result
= dns_rdataset_next(&fctx
->nameservers
))
2624 dns_rdataset_current(&fctx
->nameservers
, &rdata
);
2626 * Extract the name from the NS record.
2628 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
2629 if (result
!= ISC_R_SUCCESS
)
2632 findname(fctx
, &ns
.name
, 0, stdoptions
, 0, now
,
2634 dns_rdata_reset(&rdata
);
2635 dns_rdata_freestruct(&ns
);
2637 if (result
!= ISC_R_NOMORE
)
2641 * Do we need to use 6 to 4?
2643 if (need_alternate
) {
2646 family
= (res
->dispatchv6
!= NULL
) ? AF_INET6
: AF_INET
;
2647 for (a
= ISC_LIST_HEAD(fctx
->res
->alternates
);
2649 a
= ISC_LIST_NEXT(a
, link
)) {
2650 if (!a
->isaddress
) {
2651 findname(fctx
, &a
->_u
._n
.name
, a
->_u
._n
.port
,
2652 stdoptions
, FCTX_ADDRINFO_FORWARDER
,
2656 if (isc_sockaddr_pf(&a
->_u
.addr
) != family
)
2659 result
= dns_adb_findaddrinfo(fctx
->adb
, &a
->_u
.addr
,
2661 if (result
== ISC_R_SUCCESS
) {
2662 dns_adbaddrinfo_t
*cur
;
2663 ai
->flags
|= FCTX_ADDRINFO_FORWARDER
;
2664 cur
= ISC_LIST_HEAD(fctx
->altaddrs
);
2665 while (cur
!= NULL
&& cur
->srtt
< ai
->srtt
)
2666 cur
= ISC_LIST_NEXT(cur
, publink
);
2668 ISC_LIST_INSERTBEFORE(fctx
->altaddrs
,
2671 ISC_LIST_APPEND(fctx
->altaddrs
, ai
,
2679 * Mark all known bad servers.
2681 all_bad
= mark_bad(fctx
);
2688 * We've got no addresses.
2690 if (fctx
->pending
> 0) {
2692 * We're fetching the addresses, but don't have any
2693 * yet. Tell the caller to wait for an answer.
2695 result
= DNS_R_WAIT
;
2698 * We've lost completely. We don't know any
2699 * addresses, and the ADB has told us it can't get
2702 FCTXTRACE("no addresses");
2703 result
= ISC_R_FAILURE
;
2707 * We've found some addresses. We might still be looking
2708 * for more addresses.
2711 result
= ISC_R_SUCCESS
;
2718 possibly_mark(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addr
)
2721 char buf
[ISC_NETADDR_FORMATSIZE
];
2723 isc_boolean_t aborted
= ISC_FALSE
;
2724 isc_boolean_t bogus
;
2725 dns_acl_t
*blackhole
;
2726 isc_netaddr_t ipaddr
;
2727 dns_peer_t
*peer
= NULL
;
2728 dns_resolver_t
*res
;
2729 const char *msg
= NULL
;
2731 sa
= &addr
->sockaddr
;
2734 isc_netaddr_fromsockaddr(&ipaddr
, sa
);
2735 blackhole
= dns_dispatchmgr_getblackhole(res
->dispatchmgr
);
2736 (void) dns_peerlist_peerbyaddr(res
->view
->peers
, &ipaddr
, &peer
);
2738 if (blackhole
!= NULL
) {
2741 if (dns_acl_match(&ipaddr
, NULL
, blackhole
,
2743 &match
, NULL
) == ISC_R_SUCCESS
&&
2749 dns_peer_getbogus(peer
, &bogus
) == ISC_R_SUCCESS
&&
2754 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2755 msg
= "ignoring blackholed / bogus server: ";
2756 } else if (isc_sockaddr_ismulticast(sa
)) {
2757 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2758 msg
= "ignoring multicast address: ";
2759 } else if (isc_sockaddr_isexperimental(sa
)) {
2760 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2761 msg
= "ignoring experimental address: ";
2762 } else if (sa
->type
.sa
.sa_family
!= AF_INET6
) {
2764 } else if (IN6_IS_ADDR_V4MAPPED(&sa
->type
.sin6
.sin6_addr
)) {
2765 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2766 msg
= "ignoring IPv6 mapped IPV4 address: ";
2767 } else if (IN6_IS_ADDR_V4COMPAT(&sa
->type
.sin6
.sin6_addr
)) {
2768 addr
->flags
|= FCTX_ADDRINFO_MARK
;
2769 msg
= "ignoring IPv6 compatibility IPV4 address: ";
2773 if (!isc_log_wouldlog(dns_lctx
, ISC_LOG_DEBUG(3)))
2776 isc_netaddr_fromsockaddr(&na
, sa
);
2777 isc_netaddr_format(&na
, buf
, sizeof(buf
));
2778 FCTXTRACE2(msg
, buf
);
2781 static inline dns_adbaddrinfo_t
*
2782 fctx_nextaddress(fetchctx_t
*fctx
) {
2783 dns_adbfind_t
*find
, *start
;
2784 dns_adbaddrinfo_t
*addrinfo
;
2785 dns_adbaddrinfo_t
*faddrinfo
;
2788 * Return the next untried address, if any.
2792 * Find the first unmarked forwarder (if any).
2794 for (addrinfo
= ISC_LIST_HEAD(fctx
->forwaddrs
);
2796 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2797 if (!UNMARKED(addrinfo
))
2799 possibly_mark(fctx
, addrinfo
);
2800 if (UNMARKED(addrinfo
)) {
2801 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2808 * No forwarders. Move to the next find.
2811 fctx
->attributes
|= FCTX_ATTR_TRIEDFIND
;
2815 find
= ISC_LIST_HEAD(fctx
->finds
);
2817 find
= ISC_LIST_NEXT(find
, publink
);
2819 find
= ISC_LIST_HEAD(fctx
->finds
);
2823 * Find the first unmarked addrinfo.
2829 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2831 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2832 if (!UNMARKED(addrinfo
))
2834 possibly_mark(fctx
, addrinfo
);
2835 if (UNMARKED(addrinfo
)) {
2836 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2840 if (addrinfo
!= NULL
)
2842 find
= ISC_LIST_NEXT(find
, publink
);
2844 find
= ISC_LIST_HEAD(fctx
->finds
);
2845 } while (find
!= start
);
2849 if (addrinfo
!= NULL
)
2853 * No nameservers left. Try alternates.
2856 fctx
->attributes
|= FCTX_ATTR_TRIEDALT
;
2858 find
= fctx
->altfind
;
2860 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2862 find
= ISC_LIST_NEXT(find
, publink
);
2864 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2868 * Find the first unmarked addrinfo.
2874 for (addrinfo
= ISC_LIST_HEAD(find
->list
);
2876 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2877 if (!UNMARKED(addrinfo
))
2879 possibly_mark(fctx
, addrinfo
);
2880 if (UNMARKED(addrinfo
)) {
2881 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2885 if (addrinfo
!= NULL
)
2887 find
= ISC_LIST_NEXT(find
, publink
);
2889 find
= ISC_LIST_HEAD(fctx
->altfinds
);
2890 } while (find
!= start
);
2893 faddrinfo
= addrinfo
;
2896 * See if we have a better alternate server by address.
2899 for (addrinfo
= ISC_LIST_HEAD(fctx
->altaddrs
);
2901 addrinfo
= ISC_LIST_NEXT(addrinfo
, publink
)) {
2902 if (!UNMARKED(addrinfo
))
2904 possibly_mark(fctx
, addrinfo
);
2905 if (UNMARKED(addrinfo
) &&
2906 (faddrinfo
== NULL
||
2907 addrinfo
->srtt
< faddrinfo
->srtt
)) {
2908 if (faddrinfo
!= NULL
)
2909 faddrinfo
->flags
&= ~FCTX_ADDRINFO_MARK
;
2910 addrinfo
->flags
|= FCTX_ADDRINFO_MARK
;
2915 if (addrinfo
== NULL
) {
2916 addrinfo
= faddrinfo
;
2917 fctx
->altfind
= find
;
2924 fctx_try(fetchctx_t
*fctx
, isc_boolean_t retrying
) {
2925 isc_result_t result
;
2926 dns_adbaddrinfo_t
*addrinfo
;
2930 REQUIRE(!ADDRWAIT(fctx
));
2932 addrinfo
= fctx_nextaddress(fctx
);
2933 if (addrinfo
== NULL
) {
2935 * We have no more addresses. Start over.
2937 fctx_cancelqueries(fctx
, ISC_TRUE
);
2938 fctx_cleanupfinds(fctx
);
2939 fctx_cleanupaltfinds(fctx
);
2940 fctx_cleanupforwaddrs(fctx
);
2941 fctx_cleanupaltaddrs(fctx
);
2942 result
= fctx_getaddresses(fctx
);
2943 if (result
== DNS_R_WAIT
) {
2945 * Sleep waiting for addresses.
2947 FCTXTRACE("addrwait");
2948 fctx
->attributes
|= FCTX_ATTR_ADDRWAIT
;
2950 } else if (result
!= ISC_R_SUCCESS
) {
2952 * Something bad happened.
2954 fctx_done(fctx
, result
, __LINE__
);
2958 addrinfo
= fctx_nextaddress(fctx
);
2960 * While we may have addresses from the ADB, they
2961 * might be bad ones. In this case, return SERVFAIL.
2963 if (addrinfo
== NULL
) {
2964 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
2969 result
= fctx_query(fctx
, addrinfo
, fctx
->options
);
2970 if (result
!= ISC_R_SUCCESS
)
2971 fctx_done(fctx
, result
, __LINE__
);
2973 inc_stats(fctx
->res
, dns_resstatscounter_retry
);
2976 static isc_boolean_t
2977 fctx_destroy(fetchctx_t
*fctx
) {
2978 dns_resolver_t
*res
;
2979 unsigned int bucketnum
;
2980 isc_sockaddr_t
*sa
, *next_sa
;
2983 * Caller must be holding the bucket lock.
2986 REQUIRE(VALID_FCTX(fctx
));
2987 REQUIRE(fctx
->state
== fetchstate_done
||
2988 fctx
->state
== fetchstate_init
);
2989 REQUIRE(ISC_LIST_EMPTY(fctx
->events
));
2990 REQUIRE(ISC_LIST_EMPTY(fctx
->queries
));
2991 REQUIRE(ISC_LIST_EMPTY(fctx
->finds
));
2992 REQUIRE(ISC_LIST_EMPTY(fctx
->altfinds
));
2993 REQUIRE(fctx
->pending
== 0);
2994 REQUIRE(fctx
->references
== 0);
2995 REQUIRE(ISC_LIST_EMPTY(fctx
->validators
));
2997 FCTXTRACE("destroy");
3000 bucketnum
= fctx
->bucketnum
;
3002 ISC_LIST_UNLINK(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
3007 for (sa
= ISC_LIST_HEAD(fctx
->bad
);
3010 next_sa
= ISC_LIST_NEXT(sa
, link
);
3011 ISC_LIST_UNLINK(fctx
->bad
, sa
, link
);
3012 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3015 for (sa
= ISC_LIST_HEAD(fctx
->edns
);
3018 next_sa
= ISC_LIST_NEXT(sa
, link
);
3019 ISC_LIST_UNLINK(fctx
->edns
, sa
, link
);
3020 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3023 for (sa
= ISC_LIST_HEAD(fctx
->edns512
);
3026 next_sa
= ISC_LIST_NEXT(sa
, link
);
3027 ISC_LIST_UNLINK(fctx
->edns512
, sa
, link
);
3028 isc_mem_put(res
->buckets
[bucketnum
].mctx
, sa
, sizeof(*sa
));
3031 isc_timer_detach(&fctx
->timer
);
3032 dns_message_destroy(&fctx
->rmessage
);
3033 dns_message_destroy(&fctx
->qmessage
);
3034 if (dns_name_countlabels(&fctx
->domain
) > 0)
3035 dns_name_free(&fctx
->domain
, res
->buckets
[bucketnum
].mctx
);
3036 if (dns_rdataset_isassociated(&fctx
->nameservers
))
3037 dns_rdataset_disassociate(&fctx
->nameservers
);
3038 dns_name_free(&fctx
->name
, res
->buckets
[bucketnum
].mctx
);
3039 dns_db_detach(&fctx
->cache
);
3040 dns_adb_detach(&fctx
->adb
);
3041 isc_mem_free(res
->buckets
[bucketnum
].mctx
, fctx
->info
);
3042 isc_mem_put(res
->buckets
[bucketnum
].mctx
, fctx
, sizeof(*fctx
));
3046 UNLOCK(&res
->nlock
);
3048 if (res
->buckets
[bucketnum
].exiting
&&
3049 ISC_LIST_EMPTY(res
->buckets
[bucketnum
].fctxs
))
3056 * Fetch event handlers.
3060 fctx_timeout(isc_task_t
*task
, isc_event_t
*event
) {
3061 fetchctx_t
*fctx
= event
->ev_arg
;
3062 isc_timerevent_t
*tevent
= (isc_timerevent_t
*)event
;
3065 REQUIRE(VALID_FCTX(fctx
));
3069 FCTXTRACE("timeout");
3071 inc_stats(fctx
->res
, dns_resstatscounter_querytimeout
);
3073 if (event
->ev_type
== ISC_TIMEREVENT_LIFE
) {
3074 fctx
->reason
= NULL
;
3075 fctx_done(fctx
, ISC_R_TIMEDOUT
, __LINE__
);
3077 isc_result_t result
;
3080 fctx
->timeout
= ISC_TRUE
;
3082 * We could cancel the running queries here, or we could let
3083 * them keep going. Since we normally use separate sockets for
3084 * different queries, we adopt the former approach to reduce
3085 * the number of open sockets: cancel the oldest query if it
3086 * expired after the query had started (this is usually the
3087 * case but is not always so, depending on the task schedule
3090 query
= ISC_LIST_HEAD(fctx
->queries
);
3091 if (query
!= NULL
&&
3092 isc_time_compare(&tevent
->due
, &query
->start
) >= 0) {
3093 fctx_cancelquery(&query
, NULL
, NULL
, ISC_TRUE
);
3095 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
3097 * Our timer has triggered. Reestablish the fctx lifetime
3100 result
= fctx_starttimer(fctx
);
3101 if (result
!= ISC_R_SUCCESS
)
3102 fctx_done(fctx
, result
, __LINE__
);
3107 fctx_try(fctx
, ISC_TRUE
);
3110 isc_event_free(&event
);
3114 fctx_shutdown(fetchctx_t
*fctx
) {
3115 isc_event_t
*cevent
;
3118 * Start the shutdown process for fctx, if it isn't already underway.
3121 FCTXTRACE("shutdown");
3124 * The caller must be holding the appropriate bucket lock.
3127 if (fctx
->want_shutdown
)
3130 fctx
->want_shutdown
= ISC_TRUE
;
3133 * Unless we're still initializing (in which case the
3134 * control event is still outstanding), we need to post
3135 * the control event to tell the fetch we want it to
3138 if (fctx
->state
!= fetchstate_init
) {
3139 cevent
= &fctx
->control_event
;
3140 isc_task_send(fctx
->res
->buckets
[fctx
->bucketnum
].task
,
3146 fctx_doshutdown(isc_task_t
*task
, isc_event_t
*event
) {
3147 fetchctx_t
*fctx
= event
->ev_arg
;
3148 isc_boolean_t bucket_empty
= ISC_FALSE
;
3149 dns_resolver_t
*res
;
3150 unsigned int bucketnum
;
3151 dns_validator_t
*validator
;
3153 REQUIRE(VALID_FCTX(fctx
));
3158 bucketnum
= fctx
->bucketnum
;
3160 FCTXTRACE("doshutdown");
3163 * An fctx that is shutting down is no longer in ADDRWAIT mode.
3165 fctx
->attributes
&= ~FCTX_ATTR_ADDRWAIT
;
3168 * Cancel all pending validators. Note that this must be done
3169 * without the bucket lock held, since that could cause deadlock.
3171 validator
= ISC_LIST_HEAD(fctx
->validators
);
3172 while (validator
!= NULL
) {
3173 dns_validator_cancel(validator
);
3174 validator
= ISC_LIST_NEXT(validator
, link
);
3177 if (fctx
->nsfetch
!= NULL
)
3178 dns_resolver_cancelfetch(fctx
->nsfetch
);
3181 * Shut down anything that is still running on behalf of this
3182 * fetch. To avoid deadlock with the ADB, we must do this
3183 * before we lock the bucket lock.
3185 fctx_stopeverything(fctx
, ISC_FALSE
);
3187 LOCK(&res
->buckets
[bucketnum
].lock
);
3189 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
3191 INSIST(fctx
->state
== fetchstate_active
||
3192 fctx
->state
== fetchstate_done
);
3193 INSIST(fctx
->want_shutdown
);
3195 if (fctx
->state
!= fetchstate_done
) {
3196 fctx
->state
= fetchstate_done
;
3197 fctx_sendevents(fctx
, ISC_R_CANCELED
, __LINE__
);
3200 if (fctx
->references
== 0 && fctx
->pending
== 0 &&
3201 fctx
->nqueries
== 0 && ISC_LIST_EMPTY(fctx
->validators
))
3202 bucket_empty
= fctx_destroy(fctx
);
3204 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3211 fctx_start(isc_task_t
*task
, isc_event_t
*event
) {
3212 fetchctx_t
*fctx
= event
->ev_arg
;
3213 isc_boolean_t done
= ISC_FALSE
, bucket_empty
= ISC_FALSE
;
3214 dns_resolver_t
*res
;
3215 unsigned int bucketnum
;
3217 REQUIRE(VALID_FCTX(fctx
));
3222 bucketnum
= fctx
->bucketnum
;
3226 LOCK(&res
->buckets
[bucketnum
].lock
);
3228 INSIST(fctx
->state
== fetchstate_init
);
3229 if (fctx
->want_shutdown
) {
3231 * We haven't started this fctx yet, and we've been requested
3234 fctx
->attributes
|= FCTX_ATTR_SHUTTINGDOWN
;
3235 fctx
->state
= fetchstate_done
;
3236 fctx_sendevents(fctx
, ISC_R_CANCELED
, __LINE__
);
3238 * Since we haven't started, we INSIST that we have no
3239 * pending ADB finds and no pending validations.
3241 INSIST(fctx
->pending
== 0);
3242 INSIST(fctx
->nqueries
== 0);
3243 INSIST(ISC_LIST_EMPTY(fctx
->validators
));
3244 if (fctx
->references
== 0) {
3246 * It's now safe to destroy this fctx.
3248 bucket_empty
= fctx_destroy(fctx
);
3253 * Normal fctx startup.
3255 fctx
->state
= fetchstate_active
;
3257 * Reset the control event for later use in shutting down
3260 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
3261 DNS_EVENT_FETCHCONTROL
, fctx_doshutdown
, fctx
,
3265 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3268 isc_result_t result
;
3271 * All is well. Start working on the fetch.
3273 result
= fctx_starttimer(fctx
);
3274 if (result
!= ISC_R_SUCCESS
)
3275 fctx_done(fctx
, result
, __LINE__
);
3277 fctx_try(fctx
, ISC_FALSE
);
3278 } else if (bucket_empty
)
3283 * Fetch Creation, Joining, and Cancelation.
3286 static inline isc_result_t
3287 fctx_join(fetchctx_t
*fctx
, isc_task_t
*task
, isc_sockaddr_t
*client
,
3288 dns_messageid_t id
, isc_taskaction_t action
, void *arg
,
3289 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
3293 dns_fetchevent_t
*event
;
3298 * We store the task we're going to send this event to in the
3299 * sender field. We'll make the fetch the sender when we actually
3303 isc_task_attach(task
, &clone
);
3304 event
= (dns_fetchevent_t
*)
3305 isc_event_allocate(fctx
->res
->mctx
, clone
, DNS_EVENT_FETCHDONE
,
3306 action
, arg
, sizeof(*event
));
3307 if (event
== NULL
) {
3308 isc_task_detach(&clone
);
3309 return (ISC_R_NOMEMORY
);
3311 event
->result
= DNS_R_SERVFAIL
;
3312 event
->qtype
= fctx
->type
;
3315 event
->rdataset
= rdataset
;
3316 event
->sigrdataset
= sigrdataset
;
3317 event
->fetch
= fetch
;
3318 event
->client
= client
;
3320 dns_fixedname_init(&event
->foundname
);
3323 * Make sure that we can store the sigrdataset in the
3324 * first event if it is needed by any of the events.
3326 if (event
->sigrdataset
!= NULL
)
3327 ISC_LIST_PREPEND(fctx
->events
, event
, ev_link
);
3329 ISC_LIST_APPEND(fctx
->events
, event
, ev_link
);
3332 fetch
->magic
= DNS_FETCH_MAGIC
;
3333 fetch
->private = fctx
;
3335 return (ISC_R_SUCCESS
);
3339 fctx_create(dns_resolver_t
*res
, dns_name_t
*name
, dns_rdatatype_t type
,
3340 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
3341 unsigned int options
, unsigned int bucketnum
, fetchctx_t
**fctxp
)
3344 isc_result_t result
;
3345 isc_result_t iresult
;
3346 isc_interval_t interval
;
3347 dns_fixedname_t fixed
;
3348 unsigned int findoptions
= 0;
3349 char buf
[DNS_NAME_FORMATSIZE
+ DNS_RDATATYPE_FORMATSIZE
];
3350 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3354 * Caller must be holding the lock for bucket number 'bucketnum'.
3356 REQUIRE(fctxp
!= NULL
&& *fctxp
== NULL
);
3358 fctx
= isc_mem_get(res
->buckets
[bucketnum
].mctx
, sizeof(*fctx
));
3360 return (ISC_R_NOMEMORY
);
3361 dns_name_format(name
, buf
, sizeof(buf
));
3362 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
3363 strcat(buf
, "/"); /* checked */
3364 strcat(buf
, typebuf
); /* checked */
3365 fctx
->info
= isc_mem_strdup(res
->buckets
[bucketnum
].mctx
, buf
);
3366 if (fctx
->info
== NULL
) {
3367 result
= ISC_R_NOMEMORY
;
3370 FCTXTRACE("create");
3371 dns_name_init(&fctx
->name
, NULL
);
3372 result
= dns_name_dup(name
, res
->buckets
[bucketnum
].mctx
, &fctx
->name
);
3373 if (result
!= ISC_R_SUCCESS
)
3375 dns_name_init(&fctx
->domain
, NULL
);
3376 dns_rdataset_init(&fctx
->nameservers
);
3379 fctx
->options
= options
;
3381 * Note! We do not attach to the task. We are relying on the
3382 * resolver to ensure that this task doesn't go away while we are
3386 fctx
->references
= 0;
3387 fctx
->bucketnum
= bucketnum
;
3388 fctx
->state
= fetchstate_init
;
3389 fctx
->want_shutdown
= ISC_FALSE
;
3390 fctx
->cloned
= ISC_FALSE
;
3391 ISC_LIST_INIT(fctx
->queries
);
3392 ISC_LIST_INIT(fctx
->finds
);
3393 ISC_LIST_INIT(fctx
->altfinds
);
3394 ISC_LIST_INIT(fctx
->forwaddrs
);
3395 ISC_LIST_INIT(fctx
->altaddrs
);
3396 ISC_LIST_INIT(fctx
->forwarders
);
3397 fctx
->fwdpolicy
= dns_fwdpolicy_none
;
3398 ISC_LIST_INIT(fctx
->bad
);
3399 ISC_LIST_INIT(fctx
->edns
);
3400 ISC_LIST_INIT(fctx
->edns512
);
3401 ISC_LIST_INIT(fctx
->validators
);
3402 fctx
->validator
= NULL
;
3404 fctx
->altfind
= NULL
;
3407 fctx
->querysent
= 0;
3408 fctx
->referrals
= 0;
3409 TIME_NOW(&fctx
->start
);
3411 fctx
->lamecount
= 0;
3417 fctx
->result
= ISC_R_FAILURE
;
3418 fctx
->vresult
= ISC_R_SUCCESS
;
3419 fctx
->exitline
= -1; /* sentinel */
3420 fctx
->logged
= ISC_FALSE
;
3421 fctx
->attributes
= 0;
3422 fctx
->spilled
= ISC_FALSE
;
3424 fctx
->reason
= NULL
;
3425 fctx
->timeout
= ISC_FALSE
;
3427 dns_name_init(&fctx
->nsname
, NULL
);
3428 fctx
->nsfetch
= NULL
;
3429 dns_rdataset_init(&fctx
->nsrrset
);
3431 if (domain
== NULL
) {
3432 dns_forwarders_t
*forwarders
= NULL
;
3433 unsigned int labels
;
3434 dns_name_t
*fwdname
= name
;
3437 * DS records are found in the parent server.
3438 * Strip label to get the correct forwarder (if any).
3440 if (dns_rdatatype_atparent(fctx
->type
) &&
3441 dns_name_countlabels(name
) > 1) {
3442 dns_name_init(&suffix
, NULL
);
3443 labels
= dns_name_countlabels(name
);
3444 dns_name_getlabelsequence(name
, 1, labels
- 1, &suffix
);
3447 dns_fixedname_init(&fixed
);
3448 domain
= dns_fixedname_name(&fixed
);
3449 result
= dns_fwdtable_find2(fctx
->res
->view
->fwdtable
, fwdname
,
3450 domain
, &forwarders
);
3451 if (result
== ISC_R_SUCCESS
)
3452 fctx
->fwdpolicy
= forwarders
->fwdpolicy
;
3454 if (fctx
->fwdpolicy
!= dns_fwdpolicy_only
) {
3456 * The caller didn't supply a query domain and
3457 * nameservers, and we're not in forward-only mode,
3458 * so find the best nameservers to use.
3460 if (dns_rdatatype_atparent(fctx
->type
))
3461 findoptions
|= DNS_DBFIND_NOEXACT
;
3462 result
= dns_view_findzonecut(res
->view
, name
, domain
,
3463 0, findoptions
, ISC_TRUE
,
3466 if (result
!= ISC_R_SUCCESS
)
3468 result
= dns_name_dup(domain
,
3469 res
->buckets
[bucketnum
].mctx
,
3471 if (result
!= ISC_R_SUCCESS
) {
3472 dns_rdataset_disassociate(&fctx
->nameservers
);
3477 * We're in forward-only mode. Set the query domain.
3479 result
= dns_name_dup(domain
,
3480 res
->buckets
[bucketnum
].mctx
,
3482 if (result
!= ISC_R_SUCCESS
)
3486 result
= dns_name_dup(domain
,
3487 res
->buckets
[bucketnum
].mctx
,
3489 if (result
!= ISC_R_SUCCESS
)
3491 dns_rdataset_clone(nameservers
, &fctx
->nameservers
);
3494 INSIST(dns_name_issubdomain(&fctx
->name
, &fctx
->domain
));
3496 fctx
->qmessage
= NULL
;
3497 result
= dns_message_create(res
->buckets
[bucketnum
].mctx
,
3498 DNS_MESSAGE_INTENTRENDER
,
3501 if (result
!= ISC_R_SUCCESS
)
3502 goto cleanup_domain
;
3504 fctx
->rmessage
= NULL
;
3505 result
= dns_message_create(res
->buckets
[bucketnum
].mctx
,
3506 DNS_MESSAGE_INTENTPARSE
,
3509 if (result
!= ISC_R_SUCCESS
)
3510 goto cleanup_qmessage
;
3513 * Compute an expiration time for the entire fetch.
3515 isc_interval_set(&interval
, 30, 0); /* XXXRTH constant */
3516 iresult
= isc_time_nowplusinterval(&fctx
->expires
, &interval
);
3517 if (iresult
!= ISC_R_SUCCESS
) {
3518 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
3519 "isc_time_nowplusinterval: %s",
3520 isc_result_totext(iresult
));
3521 result
= ISC_R_UNEXPECTED
;
3522 goto cleanup_rmessage
;
3526 * Default retry interval initialization. We set the interval now
3527 * mostly so it won't be uninitialized. It will be set to the
3528 * correct value before a query is issued.
3530 isc_interval_set(&fctx
->interval
, 2, 0);
3533 * Create an inactive timer. It will be made active when the fetch
3534 * is actually started.
3537 iresult
= isc_timer_create(res
->timermgr
, isc_timertype_inactive
,
3539 res
->buckets
[bucketnum
].task
, fctx_timeout
,
3540 fctx
, &fctx
->timer
);
3541 if (iresult
!= ISC_R_SUCCESS
) {
3542 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
3543 "isc_timer_create: %s",
3544 isc_result_totext(iresult
));
3545 result
= ISC_R_UNEXPECTED
;
3546 goto cleanup_rmessage
;
3550 * Attach to the view's cache and adb.
3553 dns_db_attach(res
->view
->cachedb
, &fctx
->cache
);
3555 dns_adb_attach(res
->view
->adb
, &fctx
->adb
);
3557 ISC_LIST_INIT(fctx
->events
);
3558 ISC_LINK_INIT(fctx
, link
);
3559 fctx
->magic
= FCTX_MAGIC
;
3561 ISC_LIST_APPEND(res
->buckets
[bucketnum
].fctxs
, fctx
, link
);
3565 UNLOCK(&res
->nlock
);
3569 return (ISC_R_SUCCESS
);
3572 dns_message_destroy(&fctx
->rmessage
);
3575 dns_message_destroy(&fctx
->qmessage
);
3578 if (dns_name_countlabels(&fctx
->domain
) > 0)
3579 dns_name_free(&fctx
->domain
, res
->buckets
[bucketnum
].mctx
);
3580 if (dns_rdataset_isassociated(&fctx
->nameservers
))
3581 dns_rdataset_disassociate(&fctx
->nameservers
);
3584 dns_name_free(&fctx
->name
, res
->buckets
[bucketnum
].mctx
);
3587 isc_mem_free(res
->buckets
[bucketnum
].mctx
, fctx
->info
);
3590 isc_mem_put(res
->buckets
[bucketnum
].mctx
, fctx
, sizeof(*fctx
));
3598 static inline isc_boolean_t
3599 is_lame(fetchctx_t
*fctx
) {
3600 dns_message_t
*message
= fctx
->rmessage
;
3602 dns_rdataset_t
*rdataset
;
3603 isc_result_t result
;
3605 if (message
->rcode
!= dns_rcode_noerror
&&
3606 message
->rcode
!= dns_rcode_nxdomain
)
3609 if (message
->counts
[DNS_SECTION_ANSWER
] != 0)
3612 if (message
->counts
[DNS_SECTION_AUTHORITY
] == 0)
3615 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
3616 while (result
== ISC_R_SUCCESS
) {
3618 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
3619 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3621 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3622 dns_namereln_t namereln
;
3624 unsigned int labels
;
3625 if (rdataset
->type
!= dns_rdatatype_ns
)
3627 namereln
= dns_name_fullcompare(name
, &fctx
->domain
,
3629 if (namereln
== dns_namereln_equal
&&
3630 (message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3632 if (namereln
== dns_namereln_subdomain
)
3636 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
3643 log_lame(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
) {
3644 char namebuf
[DNS_NAME_FORMATSIZE
];
3645 char domainbuf
[DNS_NAME_FORMATSIZE
];
3646 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
3648 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
3649 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
3650 isc_sockaddr_format(&addrinfo
->sockaddr
, addrbuf
, sizeof(addrbuf
));
3651 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_LAME_SERVERS
,
3652 DNS_LOGMODULE_RESOLVER
, ISC_LOG_INFO
,
3653 "lame server resolving '%s' (in '%s'?): %s",
3654 namebuf
, domainbuf
, addrbuf
);
3657 static inline isc_result_t
3658 same_question(fetchctx_t
*fctx
) {
3659 isc_result_t result
;
3660 dns_message_t
*message
= fctx
->rmessage
;
3662 dns_rdataset_t
*rdataset
;
3665 * Caller must be holding the fctx lock.
3669 * XXXRTH Currently we support only one question.
3671 if (message
->counts
[DNS_SECTION_QUESTION
] != 1)
3672 return (DNS_R_FORMERR
);
3674 result
= dns_message_firstname(message
, DNS_SECTION_QUESTION
);
3675 if (result
!= ISC_R_SUCCESS
)
3678 dns_message_currentname(message
, DNS_SECTION_QUESTION
, &name
);
3679 rdataset
= ISC_LIST_HEAD(name
->list
);
3680 INSIST(rdataset
!= NULL
);
3681 INSIST(ISC_LIST_NEXT(rdataset
, link
) == NULL
);
3682 if (fctx
->type
!= rdataset
->type
||
3683 fctx
->res
->rdclass
!= rdataset
->rdclass
||
3684 !dns_name_equal(&fctx
->name
, name
))
3685 return (DNS_R_FORMERR
);
3687 return (ISC_R_SUCCESS
);
3691 clone_results(fetchctx_t
*fctx
) {
3692 dns_fetchevent_t
*event
, *hevent
;
3693 isc_result_t result
;
3694 dns_name_t
*name
, *hname
;
3696 FCTXTRACE("clone_results");
3699 * Set up any other events to have the same data as the first
3702 * Caller must be holding the appropriate lock.
3705 fctx
->cloned
= ISC_TRUE
;
3706 hevent
= ISC_LIST_HEAD(fctx
->events
);
3709 hname
= dns_fixedname_name(&hevent
->foundname
);
3710 for (event
= ISC_LIST_NEXT(hevent
, ev_link
);
3712 event
= ISC_LIST_NEXT(event
, ev_link
)) {
3713 name
= dns_fixedname_name(&event
->foundname
);
3714 result
= dns_name_copy(hname
, name
, NULL
);
3715 if (result
!= ISC_R_SUCCESS
)
3716 event
->result
= result
;
3718 event
->result
= hevent
->result
;
3719 dns_db_attach(hevent
->db
, &event
->db
);
3720 dns_db_attachnode(hevent
->db
, hevent
->node
, &event
->node
);
3721 INSIST(hevent
->rdataset
!= NULL
);
3722 INSIST(event
->rdataset
!= NULL
);
3723 if (dns_rdataset_isassociated(hevent
->rdataset
))
3724 dns_rdataset_clone(hevent
->rdataset
, event
->rdataset
);
3725 INSIST(! (hevent
->sigrdataset
== NULL
&&
3726 event
->sigrdataset
!= NULL
));
3727 if (hevent
->sigrdataset
!= NULL
&&
3728 dns_rdataset_isassociated(hevent
->sigrdataset
) &&
3729 event
->sigrdataset
!= NULL
)
3730 dns_rdataset_clone(hevent
->sigrdataset
,
3731 event
->sigrdataset
);
3735 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3736 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3737 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3738 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3739 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3740 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3741 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3745 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3746 * no references and is no longer waiting for any events). If this
3747 * was the last fctx in the resolver, destroy the resolver.
3750 * '*fctx' is shutting down.
3753 maybe_destroy(fetchctx_t
*fctx
) {
3754 unsigned int bucketnum
;
3755 isc_boolean_t bucket_empty
= ISC_FALSE
;
3756 dns_resolver_t
*res
= fctx
->res
;
3757 dns_validator_t
*validator
, *next_validator
;
3759 REQUIRE(SHUTTINGDOWN(fctx
));
3761 if (fctx
->pending
!= 0 || fctx
->nqueries
!= 0)
3764 for (validator
= ISC_LIST_HEAD(fctx
->validators
);
3765 validator
!= NULL
; validator
= next_validator
) {
3766 next_validator
= ISC_LIST_NEXT(validator
, link
);
3767 dns_validator_cancel(validator
);
3769 * If this is a active validator wait for the cancel
3770 * to complete before calling dns_validator_destroy().
3772 if (validator
== fctx
->validator
)
3774 ISC_LIST_UNLINK(fctx
->validators
, validator
, link
);
3775 dns_validator_destroy(&validator
);
3778 bucketnum
= fctx
->bucketnum
;
3779 LOCK(&res
->buckets
[bucketnum
].lock
);
3780 if (fctx
->references
== 0 && ISC_LIST_EMPTY(fctx
->validators
))
3781 bucket_empty
= fctx_destroy(fctx
);
3782 UNLOCK(&res
->buckets
[bucketnum
].lock
);
3789 * The validator has finished.
3792 validated(isc_task_t
*task
, isc_event_t
*event
) {
3793 isc_result_t result
= ISC_R_SUCCESS
;
3794 isc_result_t eresult
= ISC_R_SUCCESS
;
3797 dns_validatorevent_t
*vevent
;
3798 dns_fetchevent_t
*hevent
;
3799 dns_rdataset_t
*ardataset
= NULL
;
3800 dns_rdataset_t
*asigrdataset
= NULL
;
3801 dns_dbnode_t
*node
= NULL
;
3802 isc_boolean_t negative
;
3803 isc_boolean_t chaining
;
3804 isc_boolean_t sentresponse
;
3806 dns_dbnode_t
*nsnode
= NULL
;
3808 dns_rdataset_t
*rdataset
;
3809 dns_rdataset_t
*sigrdataset
;
3810 dns_valarg_t
*valarg
;
3811 dns_adbaddrinfo_t
*addrinfo
;
3813 UNUSED(task
); /* for now */
3815 REQUIRE(event
->ev_type
== DNS_EVENT_VALIDATORDONE
);
3816 valarg
= event
->ev_arg
;
3817 fctx
= valarg
->fctx
;
3818 addrinfo
= valarg
->addrinfo
;
3819 REQUIRE(VALID_FCTX(fctx
));
3820 REQUIRE(!ISC_LIST_EMPTY(fctx
->validators
));
3822 vevent
= (dns_validatorevent_t
*)event
;
3824 FCTXTRACE("received validation completion event");
3826 ISC_LIST_UNLINK(fctx
->validators
, vevent
->validator
, link
);
3827 fctx
->validator
= NULL
;
3830 * Destroy the validator early so that we can
3831 * destroy the fctx if necessary.
3833 dns_validator_destroy(&vevent
->validator
);
3834 isc_mem_put(fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
3835 valarg
, sizeof(*valarg
));
3837 negative
= ISC_TF(vevent
->rdataset
== NULL
);
3839 sentresponse
= ISC_TF((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0);
3842 * If shutting down, ignore the results. Check to see if we're
3843 * done waiting for validator completions and ADB pending events; if
3844 * so, destroy the fctx.
3846 if (SHUTTINGDOWN(fctx
) && !sentresponse
) {
3847 maybe_destroy(fctx
); /* Locks bucket. */
3851 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3854 * If chaining, we need to make sure that the right result code is
3855 * returned, and that the rdatasets are bound.
3857 if (vevent
->result
== ISC_R_SUCCESS
&&
3859 vevent
->rdataset
!= NULL
&&
3860 CHAINING(vevent
->rdataset
))
3862 if (vevent
->rdataset
->type
== dns_rdatatype_cname
)
3863 eresult
= DNS_R_CNAME
;
3865 INSIST(vevent
->rdataset
->type
== dns_rdatatype_dname
);
3866 eresult
= DNS_R_DNAME
;
3868 chaining
= ISC_TRUE
;
3870 chaining
= ISC_FALSE
;
3873 * Either we're not shutting down, or we are shutting down but want
3874 * to cache the result anyway (if this was a validation started by
3875 * a query with cd set)
3878 hevent
= ISC_LIST_HEAD(fctx
->events
);
3879 if (hevent
!= NULL
) {
3880 if (!negative
&& !chaining
&&
3881 (fctx
->type
== dns_rdatatype_any
||
3882 fctx
->type
== dns_rdatatype_rrsig
||
3883 fctx
->type
== dns_rdatatype_sig
)) {
3885 * Don't bind rdatasets; the caller
3886 * will iterate the node.
3889 ardataset
= hevent
->rdataset
;
3890 asigrdataset
= hevent
->sigrdataset
;
3894 if (vevent
->result
!= ISC_R_SUCCESS
) {
3895 FCTXTRACE("validation failed");
3896 inc_stats(fctx
->res
, dns_resstatscounter_valfail
);
3898 fctx
->vresult
= vevent
->result
;
3899 result
= ISC_R_NOTFOUND
;
3900 if (vevent
->rdataset
!= NULL
)
3901 result
= dns_db_findnode(fctx
->cache
, vevent
->name
,
3903 if (result
== ISC_R_SUCCESS
)
3904 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
3906 if (result
== ISC_R_SUCCESS
&& vevent
->sigrdataset
!= NULL
)
3907 (void)dns_db_deleterdataset(fctx
->cache
, node
, NULL
,
3908 dns_rdatatype_rrsig
,
3910 if (result
== ISC_R_SUCCESS
)
3911 dns_db_detachnode(fctx
->cache
, &node
);
3912 result
= vevent
->result
;
3913 add_bad(fctx
, addrinfo
, result
, badns_validation
);
3914 isc_event_free(&event
);
3915 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
3916 INSIST(fctx
->validator
== NULL
);
3917 fctx
->validator
= ISC_LIST_HEAD(fctx
->validators
);
3918 if (fctx
->validator
!= NULL
) {
3919 dns_validator_send(fctx
->validator
);
3920 } else if (sentresponse
)
3921 fctx_done(fctx
, result
, __LINE__
); /* Locks bucket. */
3923 fctx_try(fctx
, ISC_TRUE
); /* Locks bucket. */
3927 isc_stdtime_get(&now
);
3930 dns_rdatatype_t covers
;
3931 FCTXTRACE("nonexistence validation OK");
3933 inc_stats(fctx
->res
, dns_resstatscounter_valnegsuccess
);
3935 if (fctx
->rmessage
->rcode
== dns_rcode_nxdomain
)
3936 covers
= dns_rdatatype_any
;
3938 covers
= fctx
->type
;
3940 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
,
3942 if (result
!= ISC_R_SUCCESS
)
3943 goto noanswer_response
;
3946 * If we are asking for a SOA record set the cache time
3947 * to zero to facilitate locating the containing zone of
3950 ttl
= fctx
->res
->view
->maxncachettl
;
3951 if (fctx
->type
== dns_rdatatype_soa
&&
3952 covers
== dns_rdatatype_any
&&
3953 fctx
->res
->zero_no_soa_ttl
)
3956 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
3958 ardataset
, &eresult
);
3959 if (result
!= ISC_R_SUCCESS
)
3960 goto noanswer_response
;
3961 goto answer_response
;
3963 inc_stats(fctx
->res
, dns_resstatscounter_valsuccess
);
3965 FCTXTRACE("validation OK");
3967 if (vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
] != NULL
) {
3969 result
= dns_rdataset_addnoqname(vevent
->rdataset
,
3970 vevent
->proofs
[DNS_VALIDATOR_NOQNAMEPROOF
]);
3971 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3972 INSIST(vevent
->sigrdataset
!= NULL
);
3973 vevent
->sigrdataset
->ttl
= vevent
->rdataset
->ttl
;
3977 * The data was already cached as pending data.
3978 * Re-cache it as secure and bind the cached
3979 * rdatasets to the first event on the fetch
3982 result
= dns_db_findnode(fctx
->cache
, vevent
->name
, ISC_TRUE
, &node
);
3983 if (result
!= ISC_R_SUCCESS
)
3984 goto noanswer_response
;
3986 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
3987 vevent
->rdataset
, 0, ardataset
);
3988 if (result
!= ISC_R_SUCCESS
&&
3989 result
!= DNS_R_UNCHANGED
)
3990 goto noanswer_response
;
3991 if (ardataset
!= NULL
&& ardataset
->type
== 0) {
3992 if (NXDOMAIN(ardataset
))
3993 eresult
= DNS_R_NCACHENXDOMAIN
;
3995 eresult
= DNS_R_NCACHENXRRSET
;
3996 } else if (vevent
->sigrdataset
!= NULL
) {
3997 result
= dns_db_addrdataset(fctx
->cache
, node
, NULL
, now
,
3998 vevent
->sigrdataset
, 0,
4000 if (result
!= ISC_R_SUCCESS
&&
4001 result
!= DNS_R_UNCHANGED
)
4002 goto noanswer_response
;
4007 * If we only deferred the destroy because we wanted to cache
4008 * the data, destroy now.
4010 dns_db_detachnode(fctx
->cache
, &node
);
4011 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4012 if (SHUTTINGDOWN(fctx
))
4013 maybe_destroy(fctx
); /* Locks bucket. */
4017 if (!ISC_LIST_EMPTY(fctx
->validators
)) {
4019 INSIST(fctx
->type
== dns_rdatatype_any
||
4020 fctx
->type
== dns_rdatatype_rrsig
||
4021 fctx
->type
== dns_rdatatype_sig
);
4023 * Don't send a response yet - we have
4024 * more rdatasets that still need to
4027 dns_db_detachnode(fctx
->cache
, &node
);
4028 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4029 dns_validator_send(ISC_LIST_HEAD(fctx
->validators
));
4035 * Cache any NS/NSEC records that happened to be validated.
4037 result
= dns_message_firstname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
);
4038 while (result
== ISC_R_SUCCESS
) {
4040 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_AUTHORITY
,
4042 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4044 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4045 if ((rdataset
->type
!= dns_rdatatype_ns
&&
4046 rdataset
->type
!= dns_rdatatype_nsec
) ||
4047 rdataset
->trust
!= dns_trust_secure
)
4049 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
4050 sigrdataset
!= NULL
;
4051 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
4052 if (sigrdataset
->type
!= dns_rdatatype_rrsig
||
4053 sigrdataset
->covers
!= rdataset
->type
)
4057 if (sigrdataset
== NULL
||
4058 sigrdataset
->trust
!= dns_trust_secure
)
4060 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
,
4062 if (result
!= ISC_R_SUCCESS
)
4065 result
= dns_db_addrdataset(fctx
->cache
, nsnode
, NULL
,
4066 now
, rdataset
, 0, NULL
);
4067 if (result
== ISC_R_SUCCESS
)
4068 result
= dns_db_addrdataset(fctx
->cache
, nsnode
,
4072 dns_db_detachnode(fctx
->cache
, &nsnode
);
4074 result
= dns_message_nextname(fctx
->rmessage
,
4075 DNS_SECTION_AUTHORITY
);
4078 result
= ISC_R_SUCCESS
;
4081 * Respond with an answer, positive or negative,
4082 * as opposed to an error. 'node' must be non-NULL.
4085 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4087 if (hevent
!= NULL
) {
4088 hevent
->result
= eresult
;
4089 RUNTIME_CHECK(dns_name_copy(vevent
->name
,
4090 dns_fixedname_name(&hevent
->foundname
), NULL
)
4092 dns_db_attach(fctx
->cache
, &hevent
->db
);
4093 dns_db_transfernode(fctx
->cache
, &node
, &hevent
->node
);
4094 clone_results(fctx
);
4099 dns_db_detachnode(fctx
->cache
, &node
);
4101 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4103 fctx_done(fctx
, result
, __LINE__
); /* Locks bucket. */
4106 INSIST(node
== NULL
);
4107 isc_event_free(&event
);
4110 static inline isc_result_t
4111 cache_name(fetchctx_t
*fctx
, dns_name_t
*name
, dns_adbaddrinfo_t
*addrinfo
,
4114 dns_rdataset_t
*rdataset
, *sigrdataset
;
4115 dns_rdataset_t
*addedrdataset
, *ardataset
, *asigrdataset
;
4116 dns_rdataset_t
*valrdataset
= NULL
, *valsigrdataset
= NULL
;
4117 dns_dbnode_t
*node
, **anodep
;
4120 dns_resolver_t
*res
;
4121 isc_boolean_t need_validation
, secure_domain
, have_answer
;
4122 isc_result_t result
, eresult
;
4123 dns_fetchevent_t
*event
;
4124 unsigned int options
;
4127 unsigned int valoptions
= 0;
4130 * The appropriate bucket lock must be held.
4134 need_validation
= ISC_FALSE
;
4135 secure_domain
= ISC_FALSE
;
4136 have_answer
= ISC_FALSE
;
4137 eresult
= ISC_R_SUCCESS
;
4138 task
= res
->buckets
[fctx
->bucketnum
].task
;
4141 * Is DNSSEC validation required for this name?
4143 if (res
->view
->enablevalidation
) {
4144 result
= dns_keytable_issecuredomain(res
->view
->secroots
, name
,
4146 if (result
!= ISC_R_SUCCESS
)
4149 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
4150 valoptions
= DNS_VALIDATOR_DLV
;
4151 secure_domain
= ISC_TRUE
;
4155 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
4156 need_validation
= ISC_FALSE
;
4158 need_validation
= secure_domain
;
4164 asigrdataset
= NULL
;
4166 if ((name
->attributes
& DNS_NAMEATTR_ANSWER
) != 0 &&
4168 have_answer
= ISC_TRUE
;
4169 event
= ISC_LIST_HEAD(fctx
->events
);
4170 if (event
!= NULL
) {
4172 aname
= dns_fixedname_name(&event
->foundname
);
4173 result
= dns_name_copy(name
, aname
, NULL
);
4174 if (result
!= ISC_R_SUCCESS
)
4176 anodep
= &event
->node
;
4178 * If this is an ANY, SIG or RRSIG query, we're not
4179 * going to return any rdatasets, unless we encountered
4180 * a CNAME or DNAME as "the answer". In this case,
4181 * we're going to return DNS_R_CNAME or DNS_R_DNAME
4182 * and we must set up the rdatasets.
4184 if ((fctx
->type
!= dns_rdatatype_any
&&
4185 fctx
->type
!= dns_rdatatype_rrsig
&&
4186 fctx
->type
!= dns_rdatatype_sig
) ||
4187 (name
->attributes
& DNS_NAMEATTR_CHAINING
) != 0) {
4188 ardataset
= event
->rdataset
;
4189 asigrdataset
= event
->sigrdataset
;
4195 * Find or create the cache node.
4198 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
4199 if (result
!= ISC_R_SUCCESS
)
4203 * Cache or validate each cacheable rdataset.
4205 fail
= ISC_TF((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMESFAIL
) != 0);
4206 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4208 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4209 if (!CACHE(rdataset
))
4211 if (CHECKNAMES(rdataset
)) {
4212 char namebuf
[DNS_NAME_FORMATSIZE
];
4213 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
4214 char classbuf
[DNS_RDATATYPE_FORMATSIZE
];
4216 dns_name_format(name
, namebuf
, sizeof(namebuf
));
4217 dns_rdatatype_format(rdataset
->type
, typebuf
,
4219 dns_rdataclass_format(rdataset
->rdclass
, classbuf
,
4221 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
4222 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
4223 "check-names %s %s/%s/%s",
4224 fail
? "failure" : "warning",
4225 namebuf
, typebuf
, classbuf
);
4227 if (ANSWER(rdataset
)) {
4228 dns_db_detachnode(fctx
->cache
, &node
);
4229 return (DNS_R_BADNAME
);
4236 * Enforce the configure maximum cache TTL.
4238 if (rdataset
->ttl
> res
->view
->maxcachettl
)
4239 rdataset
->ttl
= res
->view
->maxcachettl
;
4242 * If this RRset is in a secure domain, is in bailiwick,
4243 * and is not glue, attempt DNSSEC validation. (We do not
4244 * attempt to validate glue or out-of-bailiwick data--even
4245 * though there might be some performance benefit to doing
4246 * so--because it makes it simpler and safer to ensure that
4247 * records from a secure domain are only cached if validated
4248 * within the context of a query to the domain that owns
4251 if (secure_domain
&& rdataset
->trust
!= dns_trust_glue
&&
4252 !EXTERNAL(rdataset
)) {
4256 * RRSIGs are validated as part of validating the
4259 if (rdataset
->type
== dns_rdatatype_rrsig
)
4262 * Find the SIG for this rdataset, if we have it.
4264 for (sigrdataset
= ISC_LIST_HEAD(name
->list
);
4265 sigrdataset
!= NULL
;
4266 sigrdataset
= ISC_LIST_NEXT(sigrdataset
, link
)) {
4267 if (sigrdataset
->type
== dns_rdatatype_rrsig
&&
4268 sigrdataset
->covers
== rdataset
->type
)
4271 if (sigrdataset
== NULL
) {
4272 if (!ANSWER(rdataset
) && need_validation
) {
4274 * Ignore non-answer rdatasets that
4275 * are missing signatures.
4282 * Normalize the rdataset and sigrdataset TTLs.
4284 if (sigrdataset
!= NULL
) {
4285 rdataset
->ttl
= ISC_MIN(rdataset
->ttl
,
4287 sigrdataset
->ttl
= rdataset
->ttl
;
4291 * Cache this rdataset/sigrdataset pair as
4292 * pending data. Track whether it was additional
4295 if (rdataset
->trust
== dns_trust_additional
)
4296 trust
= dns_trust_pending_additional
;
4298 trust
= dns_trust_pending_answer
;
4300 rdataset
->trust
= trust
;
4301 if (sigrdataset
!= NULL
)
4302 sigrdataset
->trust
= trust
;
4303 if (!need_validation
|| !ANSWER(rdataset
)) {
4304 addedrdataset
= ardataset
;
4305 result
= dns_db_addrdataset(fctx
->cache
, node
,
4306 NULL
, now
, rdataset
,
4308 if (result
== DNS_R_UNCHANGED
) {
4309 result
= ISC_R_SUCCESS
;
4310 if (!need_validation
&&
4311 ardataset
!= NULL
&&
4312 ardataset
->type
== 0) {
4314 * The answer in the cache is
4315 * better than the answer we
4316 * found, and is a negative
4317 * cache entry, so we must set
4318 * eresult appropriately.
4320 if (NXDOMAIN(ardataset
))
4322 DNS_R_NCACHENXDOMAIN
;
4325 DNS_R_NCACHENXRRSET
;
4327 * We have a negative response
4328 * from the cache so don't
4329 * attempt to add the RRSIG
4335 if (result
!= ISC_R_SUCCESS
)
4337 if (sigrdataset
!= NULL
) {
4338 addedrdataset
= asigrdataset
;
4339 result
= dns_db_addrdataset(fctx
->cache
,
4343 if (result
== DNS_R_UNCHANGED
)
4344 result
= ISC_R_SUCCESS
;
4345 if (result
!= ISC_R_SUCCESS
)
4347 } else if (!ANSWER(rdataset
))
4351 if (ANSWER(rdataset
) && need_validation
) {
4352 if (fctx
->type
!= dns_rdatatype_any
&&
4353 fctx
->type
!= dns_rdatatype_rrsig
&&
4354 fctx
->type
!= dns_rdatatype_sig
) {
4356 * This is The Answer. We will
4357 * validate it, but first we cache
4358 * the rest of the response - it may
4359 * contain useful keys.
4361 INSIST(valrdataset
== NULL
&&
4362 valsigrdataset
== NULL
);
4363 valrdataset
= rdataset
;
4364 valsigrdataset
= sigrdataset
;
4367 * This is one of (potentially)
4368 * multiple answers to an ANY
4369 * or SIG query. To keep things
4370 * simple, we just start the
4371 * validator right away rather
4372 * than caching first and
4373 * having to remember which
4374 * rdatasets needed validation.
4376 result
= valcreate(fctx
, addrinfo
,
4377 name
, rdataset
->type
,
4382 * Defer any further validations.
4383 * This prevents multiple validators
4384 * from manipulating fctx->rmessage
4387 valoptions
|= DNS_VALIDATOR_DEFER
;
4389 } else if (CHAINING(rdataset
)) {
4390 if (rdataset
->type
== dns_rdatatype_cname
)
4391 eresult
= DNS_R_CNAME
;
4393 INSIST(rdataset
->type
==
4394 dns_rdatatype_dname
);
4395 eresult
= DNS_R_DNAME
;
4398 } else if (!EXTERNAL(rdataset
)) {
4400 * It's OK to cache this rdataset now.
4402 if (ANSWER(rdataset
))
4403 addedrdataset
= ardataset
;
4404 else if (ANSWERSIG(rdataset
))
4405 addedrdataset
= asigrdataset
;
4407 addedrdataset
= NULL
;
4408 if (CHAINING(rdataset
)) {
4409 if (rdataset
->type
== dns_rdatatype_cname
)
4410 eresult
= DNS_R_CNAME
;
4412 INSIST(rdataset
->type
==
4413 dns_rdatatype_dname
);
4414 eresult
= DNS_R_DNAME
;
4417 if (rdataset
->trust
== dns_trust_glue
&&
4418 (rdataset
->type
== dns_rdatatype_ns
||
4419 (rdataset
->type
== dns_rdatatype_rrsig
&&
4420 rdataset
->covers
== dns_rdatatype_ns
))) {
4422 * If the trust level is 'dns_trust_glue'
4423 * then we are adding data from a referral
4424 * we got while executing the search algorithm.
4425 * New referral data always takes precedence
4426 * over the existing cache contents.
4428 options
= DNS_DBADD_FORCE
;
4432 * Now we can add the rdataset.
4434 result
= dns_db_addrdataset(fctx
->cache
,
4439 if (result
== DNS_R_UNCHANGED
) {
4440 if (ANSWER(rdataset
) &&
4441 ardataset
!= NULL
&&
4442 ardataset
->type
== 0) {
4444 * The answer in the cache is better
4445 * than the answer we found, and is
4446 * a negative cache entry, so we
4447 * must set eresult appropriately.
4449 if (NXDOMAIN(ardataset
))
4450 eresult
= DNS_R_NCACHENXDOMAIN
;
4452 eresult
= DNS_R_NCACHENXRRSET
;
4454 result
= ISC_R_SUCCESS
;
4455 } else if (result
!= ISC_R_SUCCESS
)
4460 if (valrdataset
!= NULL
)
4461 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
4462 valrdataset
, valsigrdataset
, valoptions
,
4465 if (result
== ISC_R_SUCCESS
&& have_answer
) {
4466 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4467 if (event
!= NULL
) {
4469 * Negative results must be indicated in event->result.
4471 if (dns_rdataset_isassociated(event
->rdataset
) &&
4472 event
->rdataset
->type
== dns_rdatatype_none
) {
4473 INSIST(eresult
== DNS_R_NCACHENXDOMAIN
||
4474 eresult
== DNS_R_NCACHENXRRSET
);
4476 event
->result
= eresult
;
4477 dns_db_attach(fctx
->cache
, adbp
);
4478 dns_db_transfernode(fctx
->cache
, &node
, anodep
);
4479 clone_results(fctx
);
4484 dns_db_detachnode(fctx
->cache
, &node
);
4489 static inline isc_result_t
4490 cache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
, isc_stdtime_t now
)
4492 isc_result_t result
;
4493 dns_section_t section
;
4496 FCTXTRACE("cache_message");
4498 fctx
->attributes
&= ~FCTX_ATTR_WANTCACHE
;
4500 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4502 for (section
= DNS_SECTION_ANSWER
;
4503 section
<= DNS_SECTION_ADDITIONAL
;
4505 result
= dns_message_firstname(fctx
->rmessage
, section
);
4506 while (result
== ISC_R_SUCCESS
) {
4508 dns_message_currentname(fctx
->rmessage
, section
,
4510 if ((name
->attributes
& DNS_NAMEATTR_CACHE
) != 0) {
4511 result
= cache_name(fctx
, name
, addrinfo
, now
);
4512 if (result
!= ISC_R_SUCCESS
)
4515 result
= dns_message_nextname(fctx
->rmessage
, section
);
4517 if (result
!= ISC_R_NOMORE
)
4520 if (result
== ISC_R_NOMORE
)
4521 result
= ISC_R_SUCCESS
;
4523 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
4529 * Do what dns_ncache_add() does, and then compute an appropriate eresult.
4532 ncache_adderesult(dns_message_t
*message
, dns_db_t
*cache
, dns_dbnode_t
*node
,
4533 dns_rdatatype_t covers
, isc_stdtime_t now
, dns_ttl_t maxttl
,
4534 dns_rdataset_t
*ardataset
,
4535 isc_result_t
*eresultp
)
4537 isc_result_t result
;
4538 dns_rdataset_t rdataset
;
4540 if (ardataset
== NULL
) {
4541 dns_rdataset_init(&rdataset
);
4542 ardataset
= &rdataset
;
4544 result
= dns_ncache_add(message
, cache
, node
, covers
, now
,
4546 if (result
== DNS_R_UNCHANGED
|| result
== ISC_R_SUCCESS
) {
4548 * If the cache now contains a negative entry and we
4549 * care about whether it is DNS_R_NCACHENXDOMAIN or
4550 * DNS_R_NCACHENXRRSET then extract it.
4552 if (ardataset
->type
== 0) {
4554 * The cache data is a negative cache entry.
4556 if (NXDOMAIN(ardataset
))
4557 *eresultp
= DNS_R_NCACHENXDOMAIN
;
4559 *eresultp
= DNS_R_NCACHENXRRSET
;
4562 * Either we don't care about the nature of the
4563 * cache rdataset (because no fetch is interested
4564 * in the outcome), or the cache rdataset is not
4565 * a negative cache entry. Whichever case it is,
4566 * we can return success.
4568 * XXXRTH There's a CNAME/DNAME problem here.
4570 *eresultp
= ISC_R_SUCCESS
;
4572 result
= ISC_R_SUCCESS
;
4574 if (ardataset
== &rdataset
&& dns_rdataset_isassociated(ardataset
))
4575 dns_rdataset_disassociate(ardataset
);
4580 static inline isc_result_t
4581 ncache_message(fetchctx_t
*fctx
, dns_adbaddrinfo_t
*addrinfo
,
4582 dns_rdatatype_t covers
, isc_stdtime_t now
)
4584 isc_result_t result
, eresult
;
4586 dns_resolver_t
*res
;
4588 dns_dbnode_t
*node
, **anodep
;
4589 dns_rdataset_t
*ardataset
;
4590 isc_boolean_t need_validation
, secure_domain
;
4592 dns_fetchevent_t
*event
;
4594 unsigned int valoptions
= 0;
4596 FCTXTRACE("ncache_message");
4598 fctx
->attributes
&= ~FCTX_ATTR_WANTNCACHE
;
4601 need_validation
= ISC_FALSE
;
4602 secure_domain
= ISC_FALSE
;
4603 eresult
= ISC_R_SUCCESS
;
4608 * XXXMPA remove when we follow cnames and adjust the setting
4609 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4611 INSIST(fctx
->rmessage
->counts
[DNS_SECTION_ANSWER
] == 0);
4614 * Is DNSSEC validation required for this name?
4616 if (fctx
->res
->view
->enablevalidation
) {
4617 result
= dns_keytable_issecuredomain(res
->view
->secroots
, name
,
4619 if (result
!= ISC_R_SUCCESS
)
4622 if (!secure_domain
&& res
->view
->dlv
!= NULL
) {
4623 valoptions
= DNS_VALIDATOR_DLV
;
4624 secure_domain
= ISC_TRUE
;
4628 if ((fctx
->options
& DNS_FETCHOPT_NOVALIDATE
) != 0)
4629 need_validation
= ISC_FALSE
;
4631 need_validation
= secure_domain
;
4633 if (secure_domain
) {
4635 * Mark all rdatasets as pending.
4637 dns_rdataset_t
*trdataset
;
4640 result
= dns_message_firstname(fctx
->rmessage
,
4641 DNS_SECTION_AUTHORITY
);
4642 while (result
== ISC_R_SUCCESS
) {
4644 dns_message_currentname(fctx
->rmessage
,
4645 DNS_SECTION_AUTHORITY
,
4647 for (trdataset
= ISC_LIST_HEAD(tname
->list
);
4649 trdataset
= ISC_LIST_NEXT(trdataset
, link
))
4650 trdataset
->trust
= dns_trust_pending_answer
;
4651 result
= dns_message_nextname(fctx
->rmessage
,
4652 DNS_SECTION_AUTHORITY
);
4654 if (result
!= ISC_R_NOMORE
)
4659 if (need_validation
) {
4661 * Do negative response validation.
4663 result
= valcreate(fctx
, addrinfo
, name
, fctx
->type
,
4664 NULL
, NULL
, valoptions
,
4665 res
->buckets
[fctx
->bucketnum
].task
);
4667 * If validation is necessary, return now. Otherwise continue
4668 * to process the message, letting the validation complete
4669 * in its own good time.
4674 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
4680 if (!HAVE_ANSWER(fctx
)) {
4681 event
= ISC_LIST_HEAD(fctx
->events
);
4682 if (event
!= NULL
) {
4684 aname
= dns_fixedname_name(&event
->foundname
);
4685 result
= dns_name_copy(name
, aname
, NULL
);
4686 if (result
!= ISC_R_SUCCESS
)
4688 anodep
= &event
->node
;
4689 ardataset
= event
->rdataset
;
4694 result
= dns_db_findnode(fctx
->cache
, name
, ISC_TRUE
, &node
);
4695 if (result
!= ISC_R_SUCCESS
)
4699 * If we are asking for a SOA record set the cache time
4700 * to zero to facilitate locating the containing zone of
4703 ttl
= fctx
->res
->view
->maxncachettl
;
4704 if (fctx
->type
== dns_rdatatype_soa
&&
4705 covers
== dns_rdatatype_any
&&
4706 fctx
->res
->zero_no_soa_ttl
)
4709 result
= ncache_adderesult(fctx
->rmessage
, fctx
->cache
, node
,
4710 covers
, now
, ttl
, ardataset
, &eresult
);
4711 if (result
!= ISC_R_SUCCESS
)
4714 if (!HAVE_ANSWER(fctx
)) {
4715 fctx
->attributes
|= FCTX_ATTR_HAVEANSWER
;
4716 if (event
!= NULL
) {
4717 event
->result
= eresult
;
4718 dns_db_attach(fctx
->cache
, adbp
);
4719 dns_db_transfernode(fctx
->cache
, &node
, anodep
);
4720 clone_results(fctx
);
4725 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
4728 dns_db_detachnode(fctx
->cache
, &node
);
4734 mark_related(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4735 isc_boolean_t external
, isc_boolean_t gluing
)
4737 name
->attributes
|= DNS_NAMEATTR_CACHE
;
4739 rdataset
->trust
= dns_trust_glue
;
4741 * Glue with 0 TTL causes problems. We force the TTL to
4742 * 1 second to prevent this.
4744 if (rdataset
->ttl
== 0)
4747 rdataset
->trust
= dns_trust_additional
;
4749 * Avoid infinite loops by only marking new rdatasets.
4751 if (!CACHE(rdataset
)) {
4752 name
->attributes
|= DNS_NAMEATTR_CHASE
;
4753 rdataset
->attributes
|= DNS_RDATASETATTR_CHASE
;
4755 rdataset
->attributes
|= DNS_RDATASETATTR_CACHE
;
4757 rdataset
->attributes
|= DNS_RDATASETATTR_EXTERNAL
;
4761 check_related(void *arg
, dns_name_t
*addname
, dns_rdatatype_t type
) {
4762 fetchctx_t
*fctx
= arg
;
4763 isc_result_t result
;
4765 dns_rdataset_t
*rdataset
;
4766 isc_boolean_t external
;
4767 dns_rdatatype_t rtype
;
4768 isc_boolean_t gluing
;
4770 REQUIRE(VALID_FCTX(fctx
));
4778 result
= dns_message_findname(fctx
->rmessage
, DNS_SECTION_ADDITIONAL
,
4779 addname
, dns_rdatatype_any
, 0, &name
,
4781 if (result
== ISC_R_SUCCESS
) {
4782 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
4783 if (type
== dns_rdatatype_a
) {
4784 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4786 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4787 if (rdataset
->type
== dns_rdatatype_rrsig
)
4788 rtype
= rdataset
->covers
;
4790 rtype
= rdataset
->type
;
4791 if (rtype
== dns_rdatatype_a
||
4792 rtype
== dns_rdatatype_aaaa
)
4793 mark_related(name
, rdataset
, external
,
4797 result
= dns_message_findtype(name
, type
, 0,
4799 if (result
== ISC_R_SUCCESS
) {
4800 mark_related(name
, rdataset
, external
, gluing
);
4802 * Do we have its SIG too?
4805 result
= dns_message_findtype(name
,
4806 dns_rdatatype_rrsig
,
4808 if (result
== ISC_R_SUCCESS
)
4809 mark_related(name
, rdataset
, external
,
4815 return (ISC_R_SUCCESS
);
4819 chase_additional(fetchctx_t
*fctx
) {
4820 isc_boolean_t rescan
;
4821 dns_section_t section
= DNS_SECTION_ADDITIONAL
;
4822 isc_result_t result
;
4827 for (result
= dns_message_firstname(fctx
->rmessage
, section
);
4828 result
== ISC_R_SUCCESS
;
4829 result
= dns_message_nextname(fctx
->rmessage
, section
)) {
4830 dns_name_t
*name
= NULL
;
4831 dns_rdataset_t
*rdataset
;
4832 dns_message_currentname(fctx
->rmessage
, DNS_SECTION_ADDITIONAL
,
4834 if ((name
->attributes
& DNS_NAMEATTR_CHASE
) == 0)
4836 name
->attributes
&= ~DNS_NAMEATTR_CHASE
;
4837 for (rdataset
= ISC_LIST_HEAD(name
->list
);
4839 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4840 if (CHASE(rdataset
)) {
4841 rdataset
->attributes
&= ~DNS_RDATASETATTR_CHASE
;
4842 (void)dns_rdataset_additionaldata(rdataset
,
4853 static inline isc_result_t
4854 cname_target(dns_rdataset_t
*rdataset
, dns_name_t
*tname
) {
4855 isc_result_t result
;
4856 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4857 dns_rdata_cname_t cname
;
4859 result
= dns_rdataset_first(rdataset
);
4860 if (result
!= ISC_R_SUCCESS
)
4862 dns_rdataset_current(rdataset
, &rdata
);
4863 result
= dns_rdata_tostruct(&rdata
, &cname
, NULL
);
4864 if (result
!= ISC_R_SUCCESS
)
4866 dns_name_init(tname
, NULL
);
4867 dns_name_clone(&cname
.cname
, tname
);
4868 dns_rdata_freestruct(&cname
);
4870 return (ISC_R_SUCCESS
);
4873 static inline isc_result_t
4874 dname_target(dns_rdataset_t
*rdataset
, dns_name_t
*qname
, dns_name_t
*oname
,
4875 dns_fixedname_t
*fixeddname
)
4877 isc_result_t result
;
4878 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4879 unsigned int nlabels
;
4881 dns_namereln_t namereln
;
4882 dns_rdata_dname_t dname
;
4883 dns_fixedname_t prefix
;
4886 * Get the target name of the DNAME.
4889 result
= dns_rdataset_first(rdataset
);
4890 if (result
!= ISC_R_SUCCESS
)
4892 dns_rdataset_current(rdataset
, &rdata
);
4893 result
= dns_rdata_tostruct(&rdata
, &dname
, NULL
);
4894 if (result
!= ISC_R_SUCCESS
)
4898 * Get the prefix of qname.
4900 namereln
= dns_name_fullcompare(qname
, oname
, &order
, &nlabels
);
4901 if (namereln
!= dns_namereln_subdomain
) {
4902 dns_rdata_freestruct(&dname
);
4903 return (DNS_R_FORMERR
);
4905 dns_fixedname_init(&prefix
);
4906 dns_name_split(qname
, nlabels
, dns_fixedname_name(&prefix
), NULL
);
4907 dns_fixedname_init(fixeddname
);
4908 result
= dns_name_concatenate(dns_fixedname_name(&prefix
),
4910 dns_fixedname_name(fixeddname
), NULL
);
4911 dns_rdata_freestruct(&dname
);
4916 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
4917 * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
4918 * response to an NS query that should be treated as a referral
4919 * even though the NS records occur in the answer section
4920 * rather than the authority section.
4923 noanswer_response(fetchctx_t
*fctx
, dns_name_t
*oqname
,
4924 isc_boolean_t bind8_ns_resp
)
4926 isc_result_t result
;
4927 dns_message_t
*message
;
4928 dns_name_t
*name
, *qname
, *ns_name
, *soa_name
, *ds_name
;
4929 dns_rdataset_t
*rdataset
, *ns_rdataset
;
4930 isc_boolean_t aa
, negative_response
;
4931 dns_rdatatype_t type
;
4932 dns_section_t section
=
4933 bind8_ns_resp
? DNS_SECTION_ANSWER
: DNS_SECTION_AUTHORITY
;
4935 FCTXTRACE("noanswer_response");
4937 message
= fctx
->rmessage
;
4942 if (oqname
== NULL
) {
4944 * We have a normal, non-chained negative response or
4947 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
4951 qname
= &fctx
->name
;
4954 * We're being invoked by answer_response() after it has
4955 * followed a CNAME/DNAME chain.
4960 * If the current qname is not a subdomain of the query
4961 * domain, there's no point in looking at the authority
4962 * section without doing DNSSEC validation.
4964 * Until we do that validation, we'll just return success
4967 if (!dns_name_issubdomain(qname
, &fctx
->domain
))
4968 return (ISC_R_SUCCESS
);
4972 * We have to figure out if this is a negative response, or a
4977 * Sometimes we can tell if its a negative response by looking at
4978 * the message header.
4980 negative_response
= ISC_FALSE
;
4981 if (message
->rcode
== dns_rcode_nxdomain
||
4982 (message
->counts
[DNS_SECTION_ANSWER
] == 0 &&
4983 message
->counts
[DNS_SECTION_AUTHORITY
] == 0))
4984 negative_response
= ISC_TRUE
;
4987 * Process the authority section.
4993 result
= dns_message_firstname(message
, section
);
4994 while (result
== ISC_R_SUCCESS
) {
4996 dns_message_currentname(message
, section
, &name
);
4997 if (dns_name_issubdomain(name
, &fctx
->domain
)) {
4999 * Look for NS/SOA RRsets first.
5001 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5003 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5004 type
= rdataset
->type
;
5005 if (type
== dns_rdatatype_rrsig
)
5006 type
= rdataset
->covers
;
5007 if (((type
== dns_rdatatype_ns
||
5008 type
== dns_rdatatype_soa
) &&
5009 !dns_name_issubdomain(qname
, name
)))
5010 return (DNS_R_FORMERR
);
5011 if (type
== dns_rdatatype_ns
) {
5015 * Only one set of NS RRs is allowed.
5017 if (rdataset
->type
==
5019 if (ns_name
!= NULL
&&
5021 return (DNS_R_FORMERR
);
5023 ns_rdataset
= rdataset
;
5027 rdataset
->attributes
|=
5028 DNS_RDATASETATTR_CACHE
;
5029 rdataset
->trust
= dns_trust_glue
;
5031 if (type
== dns_rdatatype_soa
) {
5033 * SOA, or RRSIG SOA.
5035 * Only one SOA is allowed.
5037 if (rdataset
->type
==
5038 dns_rdatatype_soa
) {
5039 if (soa_name
!= NULL
&&
5041 return (DNS_R_FORMERR
);
5045 DNS_NAMEATTR_NCACHE
;
5046 rdataset
->attributes
|=
5047 DNS_RDATASETATTR_NCACHE
;
5050 dns_trust_authauthority
;
5053 dns_trust_additional
;
5057 result
= dns_message_nextname(message
, section
);
5058 if (result
== ISC_R_NOMORE
)
5060 else if (result
!= ISC_R_SUCCESS
)
5065 * A negative response has a SOA record (Type 2)
5066 * and a optional NS RRset (Type 1) or it has neither
5067 * a SOA or a NS RRset (Type 3, handled above) or
5068 * rcode is NXDOMAIN (handled above) in which case
5069 * the NS RRset is allowed (Type 4).
5071 if (soa_name
!= NULL
)
5072 negative_response
= ISC_TRUE
;
5074 result
= dns_message_firstname(message
, section
);
5075 while (result
== ISC_R_SUCCESS
) {
5077 dns_message_currentname(message
, section
, &name
);
5078 if (dns_name_issubdomain(name
, &fctx
->domain
)) {
5079 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5081 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5082 type
= rdataset
->type
;
5083 if (type
== dns_rdatatype_rrsig
)
5084 type
= rdataset
->covers
;
5085 if (type
== dns_rdatatype_nsec
) {
5087 * NSEC or RRSIG NSEC.
5089 if (negative_response
) {
5091 DNS_NAMEATTR_NCACHE
;
5092 rdataset
->attributes
|=
5093 DNS_RDATASETATTR_NCACHE
;
5097 rdataset
->attributes
|=
5098 DNS_RDATASETATTR_CACHE
;
5102 dns_trust_authauthority
;
5105 dns_trust_additional
;
5107 * No additional data needs to be
5110 } else if (type
== dns_rdatatype_ds
) {
5114 * These should only be here if
5115 * this is a referral, and there
5116 * should only be one DS.
5118 if (ns_name
== NULL
)
5119 return (DNS_R_FORMERR
);
5120 if (rdataset
->type
==
5122 if (ds_name
!= NULL
&&
5124 return (DNS_R_FORMERR
);
5129 rdataset
->attributes
|=
5130 DNS_RDATASETATTR_CACHE
;
5133 dns_trust_authauthority
;
5136 dns_trust_additional
;
5140 result
= dns_message_nextname(message
, section
);
5141 if (result
== ISC_R_NOMORE
)
5143 else if (result
!= ISC_R_SUCCESS
)
5148 * Trigger lookups for DNS nameservers.
5150 if (negative_response
&& message
->rcode
== dns_rcode_noerror
&&
5151 fctx
->type
== dns_rdatatype_ds
&& soa_name
!= NULL
&&
5152 dns_name_equal(soa_name
, qname
) &&
5153 !dns_name_equal(qname
, dns_rootname
))
5154 return (DNS_R_CHASEDSSERVERS
);
5157 * Did we find anything?
5159 if (!negative_response
&& ns_name
== NULL
) {
5163 if (oqname
!= NULL
) {
5165 * We've already got a partial CNAME/DNAME chain,
5166 * and haven't found else anything useful here, but
5167 * no error has occurred since we have an answer.
5169 return (ISC_R_SUCCESS
);
5172 * The responder is insane.
5174 return (DNS_R_FORMERR
);
5179 * If we found both NS and SOA, they should be the same name.
5181 if (ns_name
!= NULL
&& soa_name
!= NULL
&& ns_name
!= soa_name
)
5182 return (DNS_R_FORMERR
);
5185 * Do we have a referral? (We only want to follow a referral if
5186 * we're not following a chain.)
5188 if (!negative_response
&& ns_name
!= NULL
&& oqname
== NULL
) {
5190 * We already know ns_name is a subdomain of fctx->domain.
5191 * If ns_name is equal to fctx->domain, we're not making
5192 * progress. We return DNS_R_FORMERR so that we'll keep
5193 * trying other servers.
5195 if (dns_name_equal(ns_name
, &fctx
->domain
))
5196 return (DNS_R_FORMERR
);
5199 * If the referral name is not a parent of the query
5200 * name, consider the responder insane.
5202 if (! dns_name_issubdomain(&fctx
->name
, ns_name
)) {
5203 FCTXTRACE("referral to non-parent");
5204 return (DNS_R_FORMERR
);
5208 * Mark any additional data related to this rdataset.
5209 * It's important that we do this before we change the
5212 INSIST(ns_rdataset
!= NULL
);
5213 fctx
->attributes
|= FCTX_ATTR_GLUING
;
5214 (void)dns_rdataset_additionaldata(ns_rdataset
, check_related
,
5216 fctx
->attributes
&= ~FCTX_ATTR_GLUING
;
5218 * NS rdatasets with 0 TTL cause problems.
5219 * dns_view_findzonecut() will not find them when we
5220 * try to follow the referral, and we'll SERVFAIL
5221 * because the best nameservers are now above QDOMAIN.
5222 * We force the TTL to 1 second to prevent this.
5224 if (ns_rdataset
->ttl
== 0)
5225 ns_rdataset
->ttl
= 1;
5227 * Set the current query domain to the referral name.
5229 * XXXRTH We should check if we're in forward-only mode, and
5230 * if so we should bail out.
5232 INSIST(dns_name_countlabels(&fctx
->domain
) > 0);
5233 dns_name_free(&fctx
->domain
,
5234 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
);
5235 if (dns_rdataset_isassociated(&fctx
->nameservers
))
5236 dns_rdataset_disassociate(&fctx
->nameservers
);
5237 dns_name_init(&fctx
->domain
, NULL
);
5238 result
= dns_name_dup(ns_name
,
5239 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
5241 if (result
!= ISC_R_SUCCESS
)
5243 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
5244 return (DNS_R_DELEGATION
);
5248 * Since we're not doing a referral, we don't want to cache any
5249 * NS RRs we may have found.
5251 if (ns_name
!= NULL
)
5252 ns_name
->attributes
&= ~DNS_NAMEATTR_CACHE
;
5254 if (negative_response
&& oqname
== NULL
)
5255 fctx
->attributes
|= FCTX_ATTR_WANTNCACHE
;
5257 return (ISC_R_SUCCESS
);
5261 answer_response(fetchctx_t
*fctx
) {
5262 isc_result_t result
;
5263 dns_message_t
*message
;
5264 dns_name_t
*name
, *qname
, tname
;
5265 dns_rdataset_t
*rdataset
;
5266 isc_boolean_t done
, external
, chaining
, aa
, found
, want_chaining
;
5267 isc_boolean_t have_answer
, found_cname
, found_type
, wanted_chaining
;
5269 dns_rdatatype_t type
;
5270 dns_fixedname_t dname
, fqname
;
5272 FCTXTRACE("answer_response");
5274 message
= fctx
->rmessage
;
5277 * Examine the answer section, marking those rdatasets which are
5278 * part of the answer and should be cached.
5282 found_cname
= ISC_FALSE
;
5283 found_type
= ISC_FALSE
;
5284 chaining
= ISC_FALSE
;
5285 have_answer
= ISC_FALSE
;
5286 want_chaining
= ISC_FALSE
;
5287 if ((message
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
5291 qname
= &fctx
->name
;
5293 result
= dns_message_firstname(message
, DNS_SECTION_ANSWER
);
5294 while (!done
&& result
== ISC_R_SUCCESS
) {
5296 dns_message_currentname(message
, DNS_SECTION_ANSWER
, &name
);
5297 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
5298 if (dns_name_equal(name
, qname
)) {
5299 wanted_chaining
= ISC_FALSE
;
5300 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5302 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5304 want_chaining
= ISC_FALSE
;
5306 if (rdataset
->type
== type
&& !found_cname
) {
5308 * We've found an ordinary answer.
5311 found_type
= ISC_TRUE
;
5313 aflag
= DNS_RDATASETATTR_ANSWER
;
5314 } else if (type
== dns_rdatatype_any
) {
5316 * We've found an answer matching
5317 * an ANY query. There may be
5321 aflag
= DNS_RDATASETATTR_ANSWER
;
5322 } else if (rdataset
->type
== dns_rdatatype_rrsig
5323 && rdataset
->covers
== type
5326 * We've found a signature that
5327 * covers the type we're looking for.
5330 found_type
= ISC_TRUE
;
5331 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5332 } else if (rdataset
->type
==
5336 * We're looking for something else,
5337 * but we found a CNAME.
5339 * Getting a CNAME response for some
5340 * query types is an error.
5342 if (type
== dns_rdatatype_rrsig
||
5343 type
== dns_rdatatype_dnskey
||
5344 type
== dns_rdatatype_nsec
)
5345 return (DNS_R_FORMERR
);
5347 found_cname
= ISC_TRUE
;
5348 want_chaining
= ISC_TRUE
;
5349 aflag
= DNS_RDATASETATTR_ANSWER
;
5350 result
= cname_target(rdataset
,
5352 if (result
!= ISC_R_SUCCESS
)
5354 } else if (rdataset
->type
== dns_rdatatype_rrsig
5355 && rdataset
->covers
==
5359 * We're looking for something else,
5360 * but we found a SIG CNAME.
5363 found_cname
= ISC_TRUE
;
5364 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5369 * We've found an answer to our
5374 rdataset
->attributes
|=
5375 DNS_RDATASETATTR_CACHE
;
5376 rdataset
->trust
= dns_trust_answer
;
5379 * This data is "the" answer
5380 * to our question only if
5381 * we're not chaining (i.e.
5382 * if we haven't followed
5383 * a CNAME or DNAME).
5387 DNS_RDATASETATTR_ANSWER
)
5388 have_answer
= ISC_TRUE
;
5390 DNS_NAMEATTR_ANSWER
;
5391 rdataset
->attributes
|= aflag
;
5394 dns_trust_authanswer
;
5395 } else if (external
) {
5397 * This data is outside of
5398 * our query domain, and
5399 * may not be cached.
5401 rdataset
->attributes
|=
5402 DNS_RDATASETATTR_EXTERNAL
;
5406 * Mark any additional data related
5409 (void)dns_rdataset_additionaldata(
5417 if (want_chaining
) {
5418 wanted_chaining
= ISC_TRUE
;
5420 DNS_NAMEATTR_CHAINING
;
5421 rdataset
->attributes
|=
5422 DNS_RDATASETATTR_CHAINING
;
5427 * We could add an "else" clause here and
5428 * log that we're ignoring this rdataset.
5432 * If wanted_chaining is true, we've done
5433 * some chaining as the result of processing
5434 * this node, and thus we need to set
5437 * We don't set chaining inside of the
5438 * rdataset loop because doing that would
5439 * cause us to ignore the signatures of
5442 if (wanted_chaining
)
5443 chaining
= ISC_TRUE
;
5446 * Look for a DNAME (or its SIG). Anything else is
5449 wanted_chaining
= ISC_FALSE
;
5450 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5452 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5453 isc_boolean_t found_dname
= ISC_FALSE
;
5456 if (rdataset
->type
== dns_rdatatype_dname
) {
5458 * We're looking for something else,
5459 * but we found a DNAME.
5461 * If we're not chaining, then the
5462 * DNAME should not be external.
5464 if (!chaining
&& external
)
5465 return (DNS_R_FORMERR
);
5467 want_chaining
= ISC_TRUE
;
5468 aflag
= DNS_RDATASETATTR_ANSWER
;
5469 result
= dname_target(rdataset
,
5472 if (result
== ISC_R_NOSPACE
) {
5474 * We can't construct the
5475 * DNAME target. Do not
5478 want_chaining
= ISC_FALSE
;
5479 } else if (result
!= ISC_R_SUCCESS
)
5482 found_dname
= ISC_TRUE
;
5483 } else if (rdataset
->type
== dns_rdatatype_rrsig
5484 && rdataset
->covers
==
5485 dns_rdatatype_dname
) {
5487 * We've found a signature that
5491 aflag
= DNS_RDATASETATTR_ANSWERSIG
;
5496 * We've found an answer to our
5501 rdataset
->attributes
|=
5502 DNS_RDATASETATTR_CACHE
;
5503 rdataset
->trust
= dns_trust_answer
;
5506 * This data is "the" answer
5507 * to our question only if
5508 * we're not chaining.
5512 DNS_RDATASETATTR_ANSWER
)
5513 have_answer
= ISC_TRUE
;
5515 DNS_NAMEATTR_ANSWER
;
5516 rdataset
->attributes
|= aflag
;
5519 dns_trust_authanswer
;
5520 } else if (external
) {
5521 rdataset
->attributes
|=
5522 DNS_RDATASETATTR_EXTERNAL
;
5530 * Copy the dname into the
5533 * Although we check for
5534 * failure of the copy
5535 * operation, in practice it
5536 * should never fail since
5537 * we already know that the
5538 * result fits in a fixedname.
5540 dns_fixedname_init(&fqname
);
5541 result
= dns_name_copy(
5542 dns_fixedname_name(&dname
),
5543 dns_fixedname_name(&fqname
),
5545 if (result
!= ISC_R_SUCCESS
)
5547 wanted_chaining
= ISC_TRUE
;
5549 DNS_NAMEATTR_CHAINING
;
5550 rdataset
->attributes
|=
5551 DNS_RDATASETATTR_CHAINING
;
5552 qname
= dns_fixedname_name(
5557 if (wanted_chaining
)
5558 chaining
= ISC_TRUE
;
5560 result
= dns_message_nextname(message
, DNS_SECTION_ANSWER
);
5562 if (result
== ISC_R_NOMORE
)
5563 result
= ISC_R_SUCCESS
;
5564 if (result
!= ISC_R_SUCCESS
)
5568 * We should have found an answer.
5571 return (DNS_R_FORMERR
);
5574 * This response is now potentially cacheable.
5576 fctx
->attributes
|= FCTX_ATTR_WANTCACHE
;
5579 * Did chaining end before we got the final answer?
5583 * Yes. This may be a negative reply, so hand off
5584 * authority section processing to the noanswer code.
5585 * If it isn't a noanswer response, no harm will be
5588 return (noanswer_response(fctx
, qname
, ISC_FALSE
));
5592 * We didn't end with an incomplete chain, so the rcode should be
5595 if (message
->rcode
!= dns_rcode_noerror
)
5596 return (DNS_R_FORMERR
);
5599 * Examine the authority section (if there is one).
5601 * We expect there to be only one owner name for all the rdatasets
5602 * in this section, and we expect that it is not external.
5605 result
= dns_message_firstname(message
, DNS_SECTION_AUTHORITY
);
5606 while (!done
&& result
== ISC_R_SUCCESS
) {
5608 dns_message_currentname(message
, DNS_SECTION_AUTHORITY
, &name
);
5609 external
= ISC_TF(!dns_name_issubdomain(name
, &fctx
->domain
));
5612 * We expect to find NS or SIG NS rdatasets, and
5615 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5617 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5618 if (rdataset
->type
== dns_rdatatype_ns
||
5619 (rdataset
->type
== dns_rdatatype_rrsig
&&
5620 rdataset
->covers
== dns_rdatatype_ns
)) {
5623 rdataset
->attributes
|=
5624 DNS_RDATASETATTR_CACHE
;
5625 if (aa
&& !chaining
)
5627 dns_trust_authauthority
;
5630 dns_trust_additional
;
5633 * Mark any additional data related
5636 (void)dns_rdataset_additionaldata(
5644 result
= dns_message_nextname(message
, DNS_SECTION_AUTHORITY
);
5646 if (result
== ISC_R_NOMORE
)
5647 result
= ISC_R_SUCCESS
;
5653 resume_dslookup(isc_task_t
*task
, isc_event_t
*event
) {
5654 dns_fetchevent_t
*fevent
;
5655 dns_resolver_t
*res
;
5657 isc_result_t result
;
5658 isc_boolean_t bucket_empty
= ISC_FALSE
;
5659 isc_boolean_t locked
= ISC_FALSE
;
5660 unsigned int bucketnum
;
5661 dns_rdataset_t nameservers
;
5662 dns_fixedname_t fixed
;
5665 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
5666 fevent
= (dns_fetchevent_t
*)event
;
5667 fctx
= event
->ev_arg
;
5668 REQUIRE(VALID_FCTX(fctx
));
5672 FCTXTRACE("resume_dslookup");
5674 if (fevent
->node
!= NULL
)
5675 dns_db_detachnode(fevent
->db
, &fevent
->node
);
5676 if (fevent
->db
!= NULL
)
5677 dns_db_detach(&fevent
->db
);
5679 dns_rdataset_init(&nameservers
);
5681 bucketnum
= fctx
->bucketnum
;
5682 if (fevent
->result
== ISC_R_CANCELED
) {
5683 dns_resolver_destroyfetch(&fctx
->nsfetch
);
5684 fctx_done(fctx
, ISC_R_CANCELED
, __LINE__
);
5685 } else if (fevent
->result
== ISC_R_SUCCESS
) {
5687 FCTXTRACE("resuming DS lookup");
5689 dns_resolver_destroyfetch(&fctx
->nsfetch
);
5690 if (dns_rdataset_isassociated(&fctx
->nameservers
))
5691 dns_rdataset_disassociate(&fctx
->nameservers
);
5692 dns_rdataset_clone(fevent
->rdataset
, &fctx
->nameservers
);
5693 dns_name_free(&fctx
->domain
,
5694 fctx
->res
->buckets
[bucketnum
].mctx
);
5695 dns_name_init(&fctx
->domain
, NULL
);
5696 result
= dns_name_dup(&fctx
->nsname
,
5697 fctx
->res
->buckets
[bucketnum
].mctx
,
5699 if (result
!= ISC_R_SUCCESS
) {
5700 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
5706 fctx_try(fctx
, ISC_TRUE
);
5709 dns_rdataset_t
*nsrdataset
= NULL
;
5712 * Retrieve state from fctx->nsfetch before we destroy it.
5714 dns_fixedname_init(&fixed
);
5715 domain
= dns_fixedname_name(&fixed
);
5716 dns_name_copy(&fctx
->nsfetch
->private->domain
, domain
, NULL
);
5717 if (dns_name_equal(&fctx
->nsname
, domain
)) {
5718 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
5719 dns_resolver_destroyfetch(&fctx
->nsfetch
);
5722 if (dns_rdataset_isassociated(
5723 &fctx
->nsfetch
->private->nameservers
)) {
5725 &fctx
->nsfetch
->private->nameservers
,
5727 nsrdataset
= &nameservers
;
5730 dns_resolver_destroyfetch(&fctx
->nsfetch
);
5731 n
= dns_name_countlabels(&fctx
->nsname
);
5732 dns_name_getlabelsequence(&fctx
->nsname
, 1, n
- 1,
5735 if (dns_rdataset_isassociated(fevent
->rdataset
))
5736 dns_rdataset_disassociate(fevent
->rdataset
);
5737 FCTXTRACE("continuing to look for parent's NS records");
5738 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
5739 dns_rdatatype_ns
, domain
,
5740 nsrdataset
, NULL
, 0, task
,
5741 resume_dslookup
, fctx
,
5742 &fctx
->nsrrset
, NULL
,
5744 if (result
!= ISC_R_SUCCESS
)
5745 fctx_done(fctx
, result
, __LINE__
);
5747 LOCK(&res
->buckets
[bucketnum
].lock
);
5754 if (dns_rdataset_isassociated(&nameservers
))
5755 dns_rdataset_disassociate(&nameservers
);
5756 if (dns_rdataset_isassociated(fevent
->rdataset
))
5757 dns_rdataset_disassociate(fevent
->rdataset
);
5758 INSIST(fevent
->sigrdataset
== NULL
);
5759 isc_event_free(&event
);
5761 LOCK(&res
->buckets
[bucketnum
].lock
);
5763 if (fctx
->references
== 0)
5764 bucket_empty
= fctx_destroy(fctx
);
5765 UNLOCK(&res
->buckets
[bucketnum
].lock
);
5771 checknamessection(dns_message_t
*message
, dns_section_t section
) {
5772 isc_result_t result
;
5774 dns_rdata_t rdata
= DNS_RDATA_INIT
;
5775 dns_rdataset_t
*rdataset
;
5777 for (result
= dns_message_firstname(message
, section
);
5778 result
== ISC_R_SUCCESS
;
5779 result
= dns_message_nextname(message
, section
))
5782 dns_message_currentname(message
, section
, &name
);
5783 for (rdataset
= ISC_LIST_HEAD(name
->list
);
5785 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
5786 for (result
= dns_rdataset_first(rdataset
);
5787 result
== ISC_R_SUCCESS
;
5788 result
= dns_rdataset_next(rdataset
)) {
5789 dns_rdataset_current(rdataset
, &rdata
);
5790 if (!dns_rdata_checkowner(name
, rdata
.rdclass
,
5793 !dns_rdata_checknames(&rdata
, name
, NULL
))
5795 rdataset
->attributes
|=
5796 DNS_RDATASETATTR_CHECKNAMES
;
5798 dns_rdata_reset(&rdata
);
5805 checknames(dns_message_t
*message
) {
5807 checknamessection(message
, DNS_SECTION_ANSWER
);
5808 checknamessection(message
, DNS_SECTION_AUTHORITY
);
5809 checknamessection(message
, DNS_SECTION_ADDITIONAL
);
5813 * Log server NSID at log level 'level'
5816 log_nsid(dns_rdataset_t
*opt
, resquery_t
*query
, int level
, isc_mem_t
*mctx
)
5818 static const char hex
[17] = "0123456789abcdef";
5819 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
5820 isc_uint16_t optcode
, nsid_len
, buflen
, i
;
5821 isc_result_t result
;
5822 isc_buffer_t nsidbuf
;
5824 unsigned char *p
, *buf
, *nsid
;
5826 /* Extract rdata from OPT rdataset */
5827 result
= dns_rdataset_first(opt
);
5828 if (result
!= ISC_R_SUCCESS
)
5829 return (ISC_R_FAILURE
);
5831 dns_rdata_init(&rdata
);
5832 dns_rdataset_current(opt
, &rdata
);
5833 if (rdata
.length
< 4)
5834 return (ISC_R_FAILURE
);
5836 /* Check for NSID */
5837 isc_buffer_init(&nsidbuf
, rdata
.data
, rdata
.length
);
5838 isc_buffer_add(&nsidbuf
, rdata
.length
);
5839 optcode
= isc_buffer_getuint16(&nsidbuf
);
5840 nsid_len
= isc_buffer_getuint16(&nsidbuf
);
5841 if (optcode
!= DNS_OPT_NSID
|| nsid_len
== 0)
5842 return (ISC_R_FAILURE
);
5844 /* Allocate buffer for storing hex version of the NSID */
5845 buflen
= nsid_len
* 2 + 1;
5846 buf
= isc_mem_get(mctx
, buflen
);
5848 return (ISC_R_NOSPACE
);
5850 /* Convert to hex */
5852 nsid
= rdata
.data
+ 4;
5853 for (i
= 0; i
< nsid_len
; i
++) {
5854 *p
++ = hex
[(nsid
[0] >> 4) & 0xf];
5855 *p
++ = hex
[nsid
[0] & 0xf];
5860 isc_sockaddr_format(&query
->addrinfo
->sockaddr
, addrbuf
,
5862 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5863 DNS_LOGMODULE_RESOLVER
, level
,
5864 "received NSID '%s' from %s", buf
, addrbuf
);
5867 isc_mem_put(mctx
, buf
, buflen
);
5868 return (ISC_R_SUCCESS
);
5872 log_packet(dns_message_t
*message
, int level
, isc_mem_t
*mctx
) {
5873 isc_buffer_t buffer
;
5876 isc_result_t result
;
5878 if (! isc_log_wouldlog(dns_lctx
, level
))
5882 * Note that these are multiline debug messages. We want a newline
5883 * to appear in the log after each message.
5887 buf
= isc_mem_get(mctx
, len
);
5890 isc_buffer_init(&buffer
, buf
, len
);
5891 result
= dns_message_totext(message
, &dns_master_style_debug
,
5893 if (result
== ISC_R_NOSPACE
) {
5894 isc_mem_put(mctx
, buf
, len
);
5896 } else if (result
== ISC_R_SUCCESS
)
5897 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
5898 DNS_LOGMODULE_RESOLVER
, level
,
5899 "received packet:\n%.*s",
5900 (int)isc_buffer_usedlength(&buffer
),
5902 } while (result
== ISC_R_NOSPACE
);
5905 isc_mem_put(mctx
, buf
, len
);
5909 resquery_response(isc_task_t
*task
, isc_event_t
*event
) {
5910 isc_result_t result
= ISC_R_SUCCESS
;
5911 resquery_t
*query
= event
->ev_arg
;
5912 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
5913 isc_boolean_t keep_trying
, get_nameservers
, resend
;
5914 isc_boolean_t truncated
;
5915 dns_message_t
*message
;
5916 dns_rdataset_t
*opt
;
5919 dns_fixedname_t foundname
;
5921 isc_time_t tnow
, *finish
;
5922 dns_adbaddrinfo_t
*addrinfo
;
5923 unsigned int options
;
5924 unsigned int findoptions
;
5925 isc_result_t broken_server
;
5926 badnstype_t broken_type
= badns_response
;
5928 REQUIRE(VALID_QUERY(query
));
5930 options
= query
->options
;
5931 REQUIRE(VALID_FCTX(fctx
));
5932 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
5936 if (isc_sockaddr_pf(&query
->addrinfo
->sockaddr
) == PF_INET
)
5937 inc_stats(fctx
->res
, dns_resstatscounter_responsev4
);
5939 inc_stats(fctx
->res
, dns_resstatscounter_responsev6
);
5941 (void)isc_timer_touch(fctx
->timer
);
5943 keep_trying
= ISC_FALSE
;
5944 broken_server
= ISC_R_SUCCESS
;
5945 get_nameservers
= ISC_FALSE
;
5947 truncated
= ISC_FALSE
;
5950 if (fctx
->res
->exiting
) {
5951 result
= ISC_R_SHUTTINGDOWN
;
5956 fctx
->timeout
= ISC_FALSE
;
5959 * XXXRTH We should really get the current time just once. We
5960 * need a routine to convert from an isc_time_t to an
5965 isc_stdtime_get(&now
);
5968 * Did the dispatcher have a problem?
5970 if (devent
->result
!= ISC_R_SUCCESS
) {
5971 if (devent
->result
== ISC_R_EOF
&&
5972 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
5974 * The problem might be that they
5975 * don't understand EDNS0. Turn it
5976 * off and try again.
5978 options
|= DNS_FETCHOPT_NOEDNS0
;
5981 * Remember that they don't like EDNS0.
5983 dns_adb_changeflags(fctx
->adb
,
5985 DNS_FETCHOPT_NOEDNS0
,
5986 DNS_FETCHOPT_NOEDNS0
);
5989 * There's no hope for this query.
5991 keep_trying
= ISC_TRUE
;
5994 * If this is a network error on an exclusive query
5995 * socket, mark the server as bad so that we won't try
5996 * it for this fetch again.
5998 if (query
->exclusivesocket
&&
5999 (devent
->result
== ISC_R_HOSTUNREACH
||
6000 devent
->result
== ISC_R_NETUNREACH
||
6001 devent
->result
== ISC_R_CONNREFUSED
||
6002 devent
->result
== ISC_R_CANCELED
)) {
6003 broken_server
= devent
->result
;
6004 broken_type
= badns_unreachable
;
6010 message
= fctx
->rmessage
;
6012 if (query
->tsig
!= NULL
) {
6013 result
= dns_message_setquerytsig(message
, query
->tsig
);
6014 if (result
!= ISC_R_SUCCESS
)
6018 if (query
->tsigkey
) {
6019 result
= dns_message_settsigkey(message
, query
->tsigkey
);
6020 if (result
!= ISC_R_SUCCESS
)
6024 result
= dns_message_parse(message
, &devent
->buffer
, 0);
6025 if (result
!= ISC_R_SUCCESS
) {
6027 case ISC_R_UNEXPECTEDEND
:
6028 if (!message
->question_ok
||
6029 (message
->flags
& DNS_MESSAGEFLAG_TC
) == 0 ||
6030 (options
& DNS_FETCHOPT_TCP
) != 0) {
6032 * Either the message ended prematurely,
6033 * and/or wasn't marked as being truncated,
6034 * and/or this is a response to a query we
6035 * sent over TCP. In all of these cases,
6036 * something is wrong with the remote
6037 * server and we don't want to retry using
6040 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
)
6043 * The problem might be that they
6044 * don't understand EDNS0. Turn it
6045 * off and try again.
6047 options
|= DNS_FETCHOPT_NOEDNS0
;
6050 * Remember that they don't like EDNS0.
6052 dns_adb_changeflags(
6055 DNS_FETCHOPT_NOEDNS0
,
6056 DNS_FETCHOPT_NOEDNS0
);
6057 inc_stats(fctx
->res
,
6058 dns_resstatscounter_edns0fail
);
6060 broken_server
= result
;
6061 keep_trying
= ISC_TRUE
;
6066 * We defer retrying via TCP for a bit so we can
6067 * check out this message further.
6069 truncated
= ISC_TRUE
;
6072 if ((query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
6074 * The problem might be that they
6075 * don't understand EDNS0. Turn it
6076 * off and try again.
6078 options
|= DNS_FETCHOPT_NOEDNS0
;
6081 * Remember that they don't like EDNS0.
6083 dns_adb_changeflags(fctx
->adb
,
6085 DNS_FETCHOPT_NOEDNS0
,
6086 DNS_FETCHOPT_NOEDNS0
);
6087 inc_stats(fctx
->res
,
6088 dns_resstatscounter_edns0fail
);
6090 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6091 keep_trying
= ISC_TRUE
;
6096 * Something bad has happened.
6104 * Log the incoming packet.
6106 log_packet(message
, ISC_LOG_DEBUG(10), fctx
->res
->mctx
);
6109 * Did we request NSID? If so, and if the response contains
6110 * NSID data, log it at INFO level.
6112 opt
= dns_message_getopt(message
);
6113 if (opt
!= NULL
&& (query
->options
& DNS_FETCHOPT_WANTNSID
) != 0)
6114 log_nsid(opt
, query
, ISC_LOG_INFO
, fctx
->res
->mctx
);
6117 * If the message is signed, check the signature. If not, this
6118 * returns success anyway.
6120 result
= dns_message_checksig(message
, fctx
->res
->view
);
6121 if (result
!= ISC_R_SUCCESS
)
6125 * The dispatcher should ensure we only get responses with QR set.
6127 INSIST((message
->flags
& DNS_MESSAGEFLAG_QR
) != 0);
6129 * INSIST() that the message comes from the place we sent it to,
6130 * since the dispatch code should ensure this.
6132 * INSIST() that the message id is correct (this should also be
6133 * ensured by the dispatch code).
6138 * Deal with truncated responses by retrying using TCP.
6140 if ((message
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
6141 truncated
= ISC_TRUE
;
6144 inc_stats(fctx
->res
, dns_resstatscounter_truncated
);
6145 if ((options
& DNS_FETCHOPT_TCP
) != 0) {
6146 broken_server
= DNS_R_TRUNCATEDTCP
;
6147 keep_trying
= ISC_TRUE
;
6149 options
|= DNS_FETCHOPT_TCP
;
6156 * Is it a query response?
6158 if (message
->opcode
!= dns_opcode_query
) {
6160 broken_server
= DNS_R_UNEXPECTEDOPCODE
;
6161 keep_trying
= ISC_TRUE
;
6166 * Update statistics about erroneous responses.
6168 if (message
->rcode
!= dns_rcode_noerror
) {
6169 switch (message
->rcode
) {
6170 case dns_rcode_nxdomain
:
6171 inc_stats(fctx
->res
, dns_resstatscounter_nxdomain
);
6173 case dns_rcode_servfail
:
6174 inc_stats(fctx
->res
, dns_resstatscounter_servfail
);
6176 case dns_rcode_formerr
:
6177 inc_stats(fctx
->res
, dns_resstatscounter_formerr
);
6180 inc_stats(fctx
->res
, dns_resstatscounter_othererror
);
6186 * Is the remote server broken, or does it dislike us?
6188 if (message
->rcode
!= dns_rcode_noerror
&&
6189 message
->rcode
!= dns_rcode_nxdomain
) {
6190 if (((message
->rcode
== dns_rcode_formerr
||
6191 message
->rcode
== dns_rcode_notimp
) ||
6192 (message
->rcode
== dns_rcode_servfail
&&
6193 dns_message_getopt(message
) == NULL
)) &&
6194 (query
->options
& DNS_FETCHOPT_NOEDNS0
) == 0) {
6196 * It's very likely they don't like EDNS0.
6197 * If the response code is SERVFAIL, also check if the
6198 * response contains an OPT RR and don't cache the
6199 * failure since it can be returned for various other
6202 * XXXRTH We should check if the question
6203 * we're asking requires EDNS0, and
6204 * if so, we should bail out.
6206 options
|= DNS_FETCHOPT_NOEDNS0
;
6209 * Remember that they don't like EDNS0.
6211 if (message
->rcode
!= dns_rcode_servfail
)
6212 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
6213 DNS_FETCHOPT_NOEDNS0
,
6214 DNS_FETCHOPT_NOEDNS0
);
6215 inc_stats(fctx
->res
, dns_resstatscounter_edns0fail
);
6216 } else if (message
->rcode
== dns_rcode_formerr
) {
6217 if (ISFORWARDER(query
->addrinfo
)) {
6219 * This forwarder doesn't understand us,
6220 * but other forwarders might. Keep trying.
6222 broken_server
= DNS_R_REMOTEFORMERR
;
6223 keep_trying
= ISC_TRUE
;
6226 * The server doesn't understand us. Since
6227 * all servers for a zone need similar
6228 * capabilities, we assume that we will get
6229 * FORMERR from all servers, and thus we
6230 * cannot make any more progress with this
6233 result
= DNS_R_FORMERR
;
6235 } else if (message
->rcode
== dns_rcode_yxdomain
) {
6237 * DNAME mapping failed because the new name
6238 * was too long. There's no chance of success
6241 result
= DNS_R_YXDOMAIN
;
6242 } else if (message
->rcode
== dns_rcode_badvers
) {
6243 unsigned int flags
, mask
;
6244 unsigned int version
;
6247 version
= (opt
->ttl
>> 16) & 0xff;
6248 flags
= (version
<< DNS_FETCHOPT_EDNSVERSIONSHIFT
) |
6249 DNS_FETCHOPT_EDNSVERSIONSET
;
6250 mask
= DNS_FETCHOPT_EDNSVERSIONMASK
|
6251 DNS_FETCHOPT_EDNSVERSIONSET
;
6254 dns_adb_changeflags(fctx
->adb
, query
->addrinfo
,
6258 broken_server
= DNS_R_BADVERS
;
6259 keep_trying
= ISC_TRUE
;
6266 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6267 INSIST(broken_server
!= ISC_R_SUCCESS
);
6268 keep_trying
= ISC_TRUE
;
6274 * Is the question the same as the one we asked?
6276 result
= same_question(fctx
);
6277 if (result
!= ISC_R_SUCCESS
) {
6279 if (result
== DNS_R_FORMERR
)
6280 keep_trying
= ISC_TRUE
;
6285 * Is the server lame?
6287 if (fctx
->res
->lame_ttl
!= 0 && !ISFORWARDER(query
->addrinfo
) &&
6289 inc_stats(fctx
->res
, dns_resstatscounter_lame
);
6290 log_lame(fctx
, query
->addrinfo
);
6291 result
= dns_adb_marklame(fctx
->adb
, query
->addrinfo
,
6292 &fctx
->name
, fctx
->type
,
6293 now
+ fctx
->res
->lame_ttl
);
6294 if (result
!= ISC_R_SUCCESS
)
6295 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6296 DNS_LOGMODULE_RESOLVER
, ISC_LOG_ERROR
,
6297 "could not mark server as lame: %s",
6298 isc_result_totext(result
));
6299 broken_server
= DNS_R_LAME
;
6300 keep_trying
= ISC_TRUE
;
6305 * Enforce delegations only zones like NET and COM.
6307 if (!ISFORWARDER(query
->addrinfo
) &&
6308 dns_view_isdelegationonly(fctx
->res
->view
, &fctx
->domain
) &&
6309 !dns_name_equal(&fctx
->domain
, &fctx
->name
) &&
6310 fix_mustbedelegationornxdomain(message
, fctx
)) {
6311 char namebuf
[DNS_NAME_FORMATSIZE
];
6312 char domainbuf
[DNS_NAME_FORMATSIZE
];
6313 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
6317 dns_name_format(&fctx
->name
, namebuf
, sizeof(namebuf
));
6318 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
6319 dns_rdatatype_format(fctx
->type
, typebuf
, sizeof(typebuf
));
6320 dns_rdataclass_format(fctx
->res
->rdclass
, classbuf
,
6322 isc_sockaddr_format(&query
->addrinfo
->sockaddr
, addrbuf
,
6325 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DELEGATION_ONLY
,
6326 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
6327 "enforced delegation-only for '%s' (%s/%s/%s) "
6329 domainbuf
, namebuf
, typebuf
, classbuf
, addrbuf
);
6332 if ((fctx
->res
->options
& DNS_RESOLVER_CHECKNAMES
) != 0)
6333 checknames(message
);
6338 fctx
->attributes
&= ~(FCTX_ATTR_WANTNCACHE
| FCTX_ATTR_WANTCACHE
);
6341 * Did we get any answers?
6343 if (message
->counts
[DNS_SECTION_ANSWER
] > 0 &&
6344 (message
->rcode
== dns_rcode_noerror
||
6345 message
->rcode
== dns_rcode_nxdomain
)) {
6347 * We've got answers. However, if we sent
6348 * a BIND 8 server an NS query, it may have
6349 * incorrectly responded with a non-authoritative
6350 * answer instead of a referral. Since this
6351 * answer lacks the SIGs necessary to do DNSSEC
6352 * validation, we must invoke the following special
6353 * kludge to treat it as a referral.
6355 if (fctx
->type
== dns_rdatatype_ns
&&
6356 (message
->flags
& DNS_MESSAGEFLAG_AA
) == 0 &&
6357 !ISFORWARDER(query
->addrinfo
))
6359 result
= noanswer_response(fctx
, NULL
, ISC_TRUE
);
6360 if (result
!= DNS_R_DELEGATION
) {
6362 * The answer section must have contained
6363 * something other than the NS records
6364 * we asked for. Since AA is not set
6365 * and the server is not a forwarder,
6366 * it is technically lame and it's easier
6367 * to treat it as such than to figure out
6368 * some more elaborate course of action.
6370 broken_server
= DNS_R_LAME
;
6371 keep_trying
= ISC_TRUE
;
6374 goto force_referral
;
6376 result
= answer_response(fctx
);
6377 if (result
!= ISC_R_SUCCESS
) {
6378 if (result
== DNS_R_FORMERR
)
6379 keep_trying
= ISC_TRUE
;
6382 } else if (message
->counts
[DNS_SECTION_AUTHORITY
] > 0 ||
6383 message
->rcode
== dns_rcode_noerror
||
6384 message
->rcode
== dns_rcode_nxdomain
) {
6386 * NXDOMAIN, NXRDATASET, or referral.
6388 result
= noanswer_response(fctx
, NULL
, ISC_FALSE
);
6389 if (result
== DNS_R_CHASEDSSERVERS
) {
6390 } else if (result
== DNS_R_DELEGATION
) {
6393 * We don't have the answer, but we know a better
6396 get_nameservers
= ISC_TRUE
;
6397 keep_trying
= ISC_TRUE
;
6399 * We have a new set of name servers, and it
6400 * has not experienced any restarts yet.
6405 * Update local statistics counters collected for each
6409 fctx
->querysent
= 0;
6410 fctx
->lamecount
= 0;
6415 result
= ISC_R_SUCCESS
;
6416 } else if (result
!= ISC_R_SUCCESS
) {
6418 * Something has gone wrong.
6420 if (result
== DNS_R_FORMERR
)
6421 keep_trying
= ISC_TRUE
;
6426 * The server is insane.
6429 broken_server
= DNS_R_UNEXPECTEDRCODE
;
6430 keep_trying
= ISC_TRUE
;
6435 * Follow additional section data chains.
6437 chase_additional(fctx
);
6440 * Cache the cacheable parts of the message. This may also cause
6441 * work to be queued to the DNSSEC validator.
6443 if (WANTCACHE(fctx
)) {
6444 result
= cache_message(fctx
, query
->addrinfo
, now
);
6445 if (result
!= ISC_R_SUCCESS
)
6450 * Ncache the negatively cacheable parts of the message. This may
6451 * also cause work to be queued to the DNSSEC validator.
6453 if (WANTNCACHE(fctx
)) {
6454 dns_rdatatype_t covers
;
6455 if (message
->rcode
== dns_rcode_nxdomain
)
6456 covers
= dns_rdatatype_any
;
6458 covers
= fctx
->type
;
6461 * Cache any negative cache entries in the message.
6463 result
= ncache_message(fctx
, query
->addrinfo
, covers
, now
);
6468 * Remember the query's addrinfo, in case we need to mark the
6471 addrinfo
= query
->addrinfo
;
6476 * XXXRTH Don't cancel the query if waiting for validation?
6478 fctx_cancelquery(&query
, &devent
, finish
, ISC_FALSE
);
6481 if (result
== DNS_R_FORMERR
)
6482 broken_server
= DNS_R_FORMERR
;
6483 if (broken_server
!= ISC_R_SUCCESS
) {
6485 * Add this server to the list of bad servers for
6488 add_bad(fctx
, addrinfo
, broken_server
, broken_type
);
6491 if (get_nameservers
) {
6493 dns_fixedname_init(&foundname
);
6494 fname
= dns_fixedname_name(&foundname
);
6495 if (result
!= ISC_R_SUCCESS
) {
6496 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6500 if (dns_rdatatype_atparent(fctx
->type
))
6501 findoptions
|= DNS_DBFIND_NOEXACT
;
6502 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0)
6505 name
= &fctx
->domain
;
6506 result
= dns_view_findzonecut(fctx
->res
->view
,
6512 if (result
!= ISC_R_SUCCESS
) {
6513 FCTXTRACE("couldn't find a zonecut");
6514 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6517 if (!dns_name_issubdomain(fname
, &fctx
->domain
)) {
6519 * The best nameservers are now above our
6522 FCTXTRACE("nameservers now above QDOMAIN");
6523 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6526 dns_name_free(&fctx
->domain
,
6527 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
);
6528 dns_name_init(&fctx
->domain
, NULL
);
6529 result
= dns_name_dup(fname
,
6530 fctx
->res
->buckets
[fctx
->bucketnum
].mctx
,
6532 if (result
!= ISC_R_SUCCESS
) {
6533 fctx_done(fctx
, DNS_R_SERVFAIL
, __LINE__
);
6536 fctx_cancelqueries(fctx
, ISC_TRUE
);
6537 fctx_cleanupfinds(fctx
);
6538 fctx_cleanupaltfinds(fctx
);
6539 fctx_cleanupforwaddrs(fctx
);
6540 fctx_cleanupaltaddrs(fctx
);
6545 fctx_try(fctx
, !get_nameservers
);
6546 } else if (resend
) {
6548 * Resend (probably with changed options).
6550 FCTXTRACE("resend");
6551 inc_stats(fctx
->res
, dns_resstatscounter_retry
);
6552 result
= fctx_query(fctx
, addrinfo
, options
);
6553 if (result
!= ISC_R_SUCCESS
)
6554 fctx_done(fctx
, result
, __LINE__
);
6555 } else if (result
== ISC_R_SUCCESS
&& !HAVE_ANSWER(fctx
)) {
6557 * All has gone well so far, but we are waiting for the
6558 * DNSSEC validator to validate the answer.
6560 FCTXTRACE("wait for validator");
6561 fctx_cancelqueries(fctx
, ISC_TRUE
);
6563 * We must not retransmit while the validator is working;
6564 * it has references to the current rmessage.
6566 result
= fctx_stopidletimer(fctx
);
6567 if (result
!= ISC_R_SUCCESS
)
6568 fctx_done(fctx
, result
, __LINE__
);
6569 } else if (result
== DNS_R_CHASEDSSERVERS
) {
6571 add_bad(fctx
, addrinfo
, result
, broken_type
);
6572 fctx_cancelqueries(fctx
, ISC_TRUE
);
6573 fctx_cleanupfinds(fctx
);
6574 fctx_cleanupforwaddrs(fctx
);
6576 n
= dns_name_countlabels(&fctx
->name
);
6577 dns_name_getlabelsequence(&fctx
->name
, 1, n
- 1, &fctx
->nsname
);
6579 FCTXTRACE("suspending DS lookup to find parent's NS records");
6581 result
= dns_resolver_createfetch(fctx
->res
, &fctx
->nsname
,
6583 NULL
, NULL
, NULL
, 0, task
,
6584 resume_dslookup
, fctx
,
6585 &fctx
->nsrrset
, NULL
,
6587 if (result
!= ISC_R_SUCCESS
)
6588 fctx_done(fctx
, result
, __LINE__
);
6589 LOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
6591 UNLOCK(&fctx
->res
->buckets
[fctx
->bucketnum
].lock
);
6592 result
= fctx_stopidletimer(fctx
);
6593 if (result
!= ISC_R_SUCCESS
)
6594 fctx_done(fctx
, result
, __LINE__
);
6599 fctx_done(fctx
, result
, __LINE__
);
6605 *** Resolver Methods
6609 destroy(dns_resolver_t
*res
) {
6613 REQUIRE(res
->references
== 0);
6614 REQUIRE(!res
->priming
);
6615 REQUIRE(res
->primefetch
== NULL
);
6619 INSIST(res
->nfctx
== 0);
6621 DESTROYLOCK(&res
->primelock
);
6622 DESTROYLOCK(&res
->nlock
);
6623 DESTROYLOCK(&res
->lock
);
6624 for (i
= 0; i
< res
->nbuckets
; i
++) {
6625 INSIST(ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
));
6626 isc_task_shutdown(res
->buckets
[i
].task
);
6627 isc_task_detach(&res
->buckets
[i
].task
);
6628 DESTROYLOCK(&res
->buckets
[i
].lock
);
6629 isc_mem_detach(&res
->buckets
[i
].mctx
);
6631 isc_mem_put(res
->mctx
, res
->buckets
,
6632 res
->nbuckets
* sizeof(fctxbucket_t
));
6633 if (res
->dispatchv4
!= NULL
)
6634 dns_dispatch_detach(&res
->dispatchv4
);
6635 if (res
->dispatchv6
!= NULL
)
6636 dns_dispatch_detach(&res
->dispatchv6
);
6637 while ((a
= ISC_LIST_HEAD(res
->alternates
)) != NULL
) {
6638 ISC_LIST_UNLINK(res
->alternates
, a
, link
);
6640 dns_name_free(&a
->_u
._n
.name
, res
->mctx
);
6641 isc_mem_put(res
->mctx
, a
, sizeof(*a
));
6643 dns_resolver_reset_algorithms(res
);
6644 dns_resolver_resetmustbesecure(res
);
6646 isc_rwlock_destroy(&res
->alglock
);
6649 isc_rwlock_destroy(&res
->mbslock
);
6651 isc_timer_detach(&res
->spillattimer
);
6653 isc_mem_put(res
->mctx
, res
, sizeof(*res
));
6657 send_shutdown_events(dns_resolver_t
*res
) {
6658 isc_event_t
*event
, *next_event
;
6662 * Caller must be holding the resolver lock.
6665 for (event
= ISC_LIST_HEAD(res
->whenshutdown
);
6667 event
= next_event
) {
6668 next_event
= ISC_LIST_NEXT(event
, ev_link
);
6669 ISC_LIST_UNLINK(res
->whenshutdown
, event
, ev_link
);
6670 etask
= event
->ev_sender
;
6671 event
->ev_sender
= res
;
6672 isc_task_sendanddetach(&etask
, &event
);
6677 empty_bucket(dns_resolver_t
*res
) {
6678 RTRACE("empty_bucket");
6682 INSIST(res
->activebuckets
> 0);
6683 res
->activebuckets
--;
6684 if (res
->activebuckets
== 0)
6685 send_shutdown_events(res
);
6691 spillattimer_countdown(isc_task_t
*task
, isc_event_t
*event
) {
6692 dns_resolver_t
*res
= event
->ev_arg
;
6693 isc_result_t result
;
6695 isc_boolean_t logit
= ISC_FALSE
;
6697 REQUIRE(VALID_RESOLVER(res
));
6702 INSIST(!res
->exiting
);
6703 if (res
->spillat
> res
->spillatmin
) {
6707 if (res
->spillat
<= res
->spillatmin
) {
6708 result
= isc_timer_reset(res
->spillattimer
,
6709 isc_timertype_inactive
, NULL
,
6711 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
6713 count
= res
->spillat
;
6716 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
6717 DNS_LOGMODULE_RESOLVER
, ISC_LOG_NOTICE
,
6718 "clients-per-query decreased to %u", count
);
6720 isc_event_free(&event
);
6724 dns_resolver_create(dns_view_t
*view
,
6725 isc_taskmgr_t
*taskmgr
, unsigned int ntasks
,
6726 isc_socketmgr_t
*socketmgr
,
6727 isc_timermgr_t
*timermgr
,
6728 unsigned int options
,
6729 dns_dispatchmgr_t
*dispatchmgr
,
6730 dns_dispatch_t
*dispatchv4
,
6731 dns_dispatch_t
*dispatchv6
,
6732 dns_resolver_t
**resp
)
6734 dns_resolver_t
*res
;
6735 isc_result_t result
= ISC_R_SUCCESS
;
6736 unsigned int i
, buckets_created
= 0;
6737 isc_task_t
*task
= NULL
;
6742 * Create a resolver.
6745 REQUIRE(DNS_VIEW_VALID(view
));
6746 REQUIRE(ntasks
> 0);
6747 REQUIRE(resp
!= NULL
&& *resp
== NULL
);
6748 REQUIRE(dispatchmgr
!= NULL
);
6749 REQUIRE(dispatchv4
!= NULL
|| dispatchv6
!= NULL
);
6751 res
= isc_mem_get(view
->mctx
, sizeof(*res
));
6753 return (ISC_R_NOMEMORY
);
6755 res
->mctx
= view
->mctx
;
6756 res
->rdclass
= view
->rdclass
;
6757 res
->socketmgr
= socketmgr
;
6758 res
->timermgr
= timermgr
;
6759 res
->taskmgr
= taskmgr
;
6760 res
->dispatchmgr
= dispatchmgr
;
6762 res
->options
= options
;
6764 ISC_LIST_INIT(res
->alternates
);
6765 res
->udpsize
= RECV_BUFFER_SIZE
;
6766 res
->algorithms
= NULL
;
6767 res
->mustbesecure
= NULL
;
6768 res
->spillatmin
= res
->spillat
= 10;
6769 res
->spillatmax
= 100;
6770 res
->spillattimer
= NULL
;
6771 res
->zero_no_soa_ttl
= ISC_FALSE
;
6773 res
->nextdisp
= 0; /* meaningless at this point, but init it */
6774 res
->nbuckets
= ntasks
;
6775 res
->activebuckets
= ntasks
;
6776 res
->buckets
= isc_mem_get(view
->mctx
,
6777 ntasks
* sizeof(fctxbucket_t
));
6778 if (res
->buckets
== NULL
) {
6779 result
= ISC_R_NOMEMORY
;
6782 for (i
= 0; i
< ntasks
; i
++) {
6783 result
= isc_mutex_init(&res
->buckets
[i
].lock
);
6784 if (result
!= ISC_R_SUCCESS
)
6785 goto cleanup_buckets
;
6786 res
->buckets
[i
].task
= NULL
;
6787 result
= isc_task_create(taskmgr
, 0, &res
->buckets
[i
].task
);
6788 if (result
!= ISC_R_SUCCESS
) {
6789 DESTROYLOCK(&res
->buckets
[i
].lock
);
6790 goto cleanup_buckets
;
6792 res
->buckets
[i
].mctx
= NULL
;
6793 snprintf(name
, sizeof(name
), "res%u", i
);
6794 #ifdef ISC_PLATFORM_USETHREADS
6796 * Use a separate memory context for each bucket to reduce
6797 * contention among multiple threads. Do this only when
6798 * enabling threads because it will be require more memory.
6800 result
= isc_mem_create(0, 0, &res
->buckets
[i
].mctx
);
6801 if (result
!= ISC_R_SUCCESS
) {
6802 isc_task_detach(&res
->buckets
[i
].task
);
6803 DESTROYLOCK(&res
->buckets
[i
].lock
);
6804 goto cleanup_buckets
;
6806 isc_mem_setname(res
->buckets
[i
].mctx
, name
, NULL
);
6808 isc_mem_attach(view
->mctx
, &res
->buckets
[i
].mctx
);
6810 isc_task_setname(res
->buckets
[i
].task
, name
, res
);
6811 ISC_LIST_INIT(res
->buckets
[i
].fctxs
);
6812 res
->buckets
[i
].exiting
= ISC_FALSE
;
6816 res
->dispatchv4
= NULL
;
6817 if (dispatchv4
!= NULL
) {
6818 dns_dispatch_attach(dispatchv4
, &res
->dispatchv4
);
6819 dispattr
= dns_dispatch_getattributes(dispatchv4
);
6821 ISC_TF((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0);
6824 res
->dispatchv6
= NULL
;
6825 if (dispatchv6
!= NULL
) {
6826 dns_dispatch_attach(dispatchv6
, &res
->dispatchv6
);
6827 dispattr
= dns_dispatch_getattributes(dispatchv6
);
6829 ISC_TF((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0);
6832 res
->references
= 1;
6833 res
->exiting
= ISC_FALSE
;
6834 res
->frozen
= ISC_FALSE
;
6835 ISC_LIST_INIT(res
->whenshutdown
);
6836 res
->priming
= ISC_FALSE
;
6837 res
->primefetch
= NULL
;
6840 result
= isc_mutex_init(&res
->lock
);
6841 if (result
!= ISC_R_SUCCESS
)
6842 goto cleanup_dispatches
;
6844 result
= isc_mutex_init(&res
->nlock
);
6845 if (result
!= ISC_R_SUCCESS
)
6848 result
= isc_mutex_init(&res
->primelock
);
6849 if (result
!= ISC_R_SUCCESS
)
6853 result
= isc_task_create(taskmgr
, 0, &task
);
6854 if (result
!= ISC_R_SUCCESS
)
6855 goto cleanup_primelock
;
6857 result
= isc_timer_create(timermgr
, isc_timertype_inactive
, NULL
, NULL
,
6858 task
, spillattimer_countdown
, res
,
6859 &res
->spillattimer
);
6860 isc_task_detach(&task
);
6861 if (result
!= ISC_R_SUCCESS
)
6862 goto cleanup_primelock
;
6865 result
= isc_rwlock_init(&res
->alglock
, 0, 0);
6866 if (result
!= ISC_R_SUCCESS
)
6867 goto cleanup_spillattimer
;
6870 result
= isc_rwlock_init(&res
->mbslock
, 0, 0);
6871 if (result
!= ISC_R_SUCCESS
)
6872 goto cleanup_alglock
;
6875 res
->magic
= RES_MAGIC
;
6879 return (ISC_R_SUCCESS
);
6884 isc_rwlock_destroy(&res
->alglock
);
6887 #if USE_ALGLOCK || USE_MBSLOCK
6888 cleanup_spillattimer
:
6889 isc_timer_detach(&res
->spillattimer
);
6893 DESTROYLOCK(&res
->primelock
);
6896 DESTROYLOCK(&res
->nlock
);
6899 DESTROYLOCK(&res
->lock
);
6902 if (res
->dispatchv6
!= NULL
)
6903 dns_dispatch_detach(&res
->dispatchv6
);
6904 if (res
->dispatchv4
!= NULL
)
6905 dns_dispatch_detach(&res
->dispatchv4
);
6908 for (i
= 0; i
< buckets_created
; i
++) {
6909 isc_mem_detach(&res
->buckets
[i
].mctx
);
6910 DESTROYLOCK(&res
->buckets
[i
].lock
);
6911 isc_task_shutdown(res
->buckets
[i
].task
);
6912 isc_task_detach(&res
->buckets
[i
].task
);
6914 isc_mem_put(view
->mctx
, res
->buckets
,
6915 res
->nbuckets
* sizeof(fctxbucket_t
));
6918 isc_mem_put(view
->mctx
, res
, sizeof(*res
));
6924 prime_done(isc_task_t
*task
, isc_event_t
*event
) {
6925 dns_resolver_t
*res
;
6926 dns_fetchevent_t
*fevent
;
6928 dns_db_t
*db
= NULL
;
6930 REQUIRE(event
->ev_type
== DNS_EVENT_FETCHDONE
);
6931 fevent
= (dns_fetchevent_t
*)event
;
6932 res
= event
->ev_arg
;
6933 REQUIRE(VALID_RESOLVER(res
));
6939 INSIST(res
->priming
);
6940 res
->priming
= ISC_FALSE
;
6941 LOCK(&res
->primelock
);
6942 fetch
= res
->primefetch
;
6943 res
->primefetch
= NULL
;
6944 UNLOCK(&res
->primelock
);
6948 if (fevent
->result
== ISC_R_SUCCESS
&&
6949 res
->view
->cache
!= NULL
&& res
->view
->hints
!= NULL
) {
6950 dns_cache_attachdb(res
->view
->cache
, &db
);
6951 dns_root_checkhints(res
->view
, res
->view
->hints
, db
);
6955 if (fevent
->node
!= NULL
)
6956 dns_db_detachnode(fevent
->db
, &fevent
->node
);
6957 if (fevent
->db
!= NULL
)
6958 dns_db_detach(&fevent
->db
);
6959 if (dns_rdataset_isassociated(fevent
->rdataset
))
6960 dns_rdataset_disassociate(fevent
->rdataset
);
6961 INSIST(fevent
->sigrdataset
== NULL
);
6963 isc_mem_put(res
->mctx
, fevent
->rdataset
, sizeof(*fevent
->rdataset
));
6965 isc_event_free(&event
);
6966 dns_resolver_destroyfetch(&fetch
);
6970 dns_resolver_prime(dns_resolver_t
*res
) {
6971 isc_boolean_t want_priming
= ISC_FALSE
;
6972 dns_rdataset_t
*rdataset
;
6973 isc_result_t result
;
6975 REQUIRE(VALID_RESOLVER(res
));
6976 REQUIRE(res
->frozen
);
6978 RTRACE("dns_resolver_prime");
6982 if (!res
->exiting
&& !res
->priming
) {
6983 INSIST(res
->primefetch
== NULL
);
6984 res
->priming
= ISC_TRUE
;
6985 want_priming
= ISC_TRUE
;
6992 * To avoid any possible recursive locking problems, we
6993 * start the priming fetch like any other fetch, and holding
6994 * no resolver locks. No one else will try to start it
6995 * because we're the ones who set res->priming to true.
6996 * Any other callers of dns_resolver_prime() while we're
6997 * running will see that res->priming is already true and
7001 rdataset
= isc_mem_get(res
->mctx
, sizeof(*rdataset
));
7002 if (rdataset
== NULL
) {
7004 INSIST(res
->priming
);
7005 INSIST(res
->primefetch
== NULL
);
7006 res
->priming
= ISC_FALSE
;
7010 dns_rdataset_init(rdataset
);
7011 LOCK(&res
->primelock
);
7012 result
= dns_resolver_createfetch(res
, dns_rootname
,
7014 NULL
, NULL
, NULL
, 0,
7015 res
->buckets
[0].task
,
7017 res
, rdataset
, NULL
,
7019 UNLOCK(&res
->primelock
);
7020 if (result
!= ISC_R_SUCCESS
) {
7022 INSIST(res
->priming
);
7023 res
->priming
= ISC_FALSE
;
7030 dns_resolver_freeze(dns_resolver_t
*res
) {
7036 REQUIRE(VALID_RESOLVER(res
));
7037 REQUIRE(!res
->frozen
);
7039 res
->frozen
= ISC_TRUE
;
7043 dns_resolver_attach(dns_resolver_t
*source
, dns_resolver_t
**targetp
) {
7044 REQUIRE(VALID_RESOLVER(source
));
7045 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
7047 RRTRACE(source
, "attach");
7048 LOCK(&source
->lock
);
7049 REQUIRE(!source
->exiting
);
7051 INSIST(source
->references
> 0);
7052 source
->references
++;
7053 INSIST(source
->references
!= 0);
7054 UNLOCK(&source
->lock
);
7060 dns_resolver_whenshutdown(dns_resolver_t
*res
, isc_task_t
*task
,
7061 isc_event_t
**eventp
)
7066 REQUIRE(VALID_RESOLVER(res
));
7067 REQUIRE(eventp
!= NULL
);
7074 if (res
->exiting
&& res
->activebuckets
== 0) {
7076 * We're already shutdown. Send the event.
7078 event
->ev_sender
= res
;
7079 isc_task_send(task
, &event
);
7082 isc_task_attach(task
, &clone
);
7083 event
->ev_sender
= clone
;
7084 ISC_LIST_APPEND(res
->whenshutdown
, event
, ev_link
);
7091 dns_resolver_shutdown(dns_resolver_t
*res
) {
7095 isc_result_t result
;
7097 REQUIRE(VALID_RESOLVER(res
));
7103 if (!res
->exiting
) {
7105 res
->exiting
= ISC_TRUE
;
7107 for (i
= 0; i
< res
->nbuckets
; i
++) {
7108 LOCK(&res
->buckets
[i
].lock
);
7109 for (fctx
= ISC_LIST_HEAD(res
->buckets
[i
].fctxs
);
7111 fctx
= ISC_LIST_NEXT(fctx
, link
))
7112 fctx_shutdown(fctx
);
7113 if (res
->dispatchv4
!= NULL
&& !res
->exclusivev4
) {
7114 sock
= dns_dispatch_getsocket(res
->dispatchv4
);
7115 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
7116 ISC_SOCKCANCEL_ALL
);
7118 if (res
->dispatchv6
!= NULL
&& !res
->exclusivev6
) {
7119 sock
= dns_dispatch_getsocket(res
->dispatchv6
);
7120 isc_socket_cancel(sock
, res
->buckets
[i
].task
,
7121 ISC_SOCKCANCEL_ALL
);
7123 res
->buckets
[i
].exiting
= ISC_TRUE
;
7124 if (ISC_LIST_EMPTY(res
->buckets
[i
].fctxs
)) {
7125 INSIST(res
->activebuckets
> 0);
7126 res
->activebuckets
--;
7128 UNLOCK(&res
->buckets
[i
].lock
);
7130 if (res
->activebuckets
== 0)
7131 send_shutdown_events(res
);
7132 result
= isc_timer_reset(res
->spillattimer
,
7133 isc_timertype_inactive
, NULL
,
7135 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
7142 dns_resolver_detach(dns_resolver_t
**resp
) {
7143 dns_resolver_t
*res
;
7144 isc_boolean_t need_destroy
= ISC_FALSE
;
7146 REQUIRE(resp
!= NULL
);
7148 REQUIRE(VALID_RESOLVER(res
));
7154 INSIST(res
->references
> 0);
7156 if (res
->references
== 0) {
7157 INSIST(res
->exiting
&& res
->activebuckets
== 0);
7158 need_destroy
= ISC_TRUE
;
7169 static inline isc_boolean_t
7170 fctx_match(fetchctx_t
*fctx
, dns_name_t
*name
, dns_rdatatype_t type
,
7171 unsigned int options
)
7173 if (fctx
->type
!= type
|| fctx
->options
!= options
)
7175 return (dns_name_equal(&fctx
->name
, name
));
7179 log_fetch(dns_name_t
*name
, dns_rdatatype_t type
) {
7180 char namebuf
[DNS_NAME_FORMATSIZE
];
7181 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
7182 int level
= ISC_LOG_DEBUG(1);
7184 if (! isc_log_wouldlog(dns_lctx
, level
))
7187 dns_name_format(name
, namebuf
, sizeof(namebuf
));
7188 dns_rdatatype_format(type
, typebuf
, sizeof(typebuf
));
7190 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_RESOLVER
,
7191 DNS_LOGMODULE_RESOLVER
, level
,
7192 "createfetch: %s %s", namebuf
, typebuf
);
7196 dns_resolver_createfetch(dns_resolver_t
*res
, dns_name_t
*name
,
7197 dns_rdatatype_t type
,
7198 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
7199 dns_forwarders_t
*forwarders
,
7200 unsigned int options
, isc_task_t
*task
,
7201 isc_taskaction_t action
, void *arg
,
7202 dns_rdataset_t
*rdataset
,
7203 dns_rdataset_t
*sigrdataset
,
7204 dns_fetch_t
**fetchp
)
7206 return (dns_resolver_createfetch2(res
, name
, type
, domain
,
7207 nameservers
, forwarders
, NULL
, 0,
7208 options
, task
, action
, arg
,
7209 rdataset
, sigrdataset
, fetchp
));
7213 dns_resolver_createfetch2(dns_resolver_t
*res
, dns_name_t
*name
,
7214 dns_rdatatype_t type
,
7215 dns_name_t
*domain
, dns_rdataset_t
*nameservers
,
7216 dns_forwarders_t
*forwarders
,
7217 isc_sockaddr_t
*client
, dns_messageid_t id
,
7218 unsigned int options
, isc_task_t
*task
,
7219 isc_taskaction_t action
, void *arg
,
7220 dns_rdataset_t
*rdataset
,
7221 dns_rdataset_t
*sigrdataset
,
7222 dns_fetch_t
**fetchp
)
7225 fetchctx_t
*fctx
= NULL
;
7226 isc_result_t result
= ISC_R_SUCCESS
;
7227 unsigned int bucketnum
;
7228 isc_boolean_t new_fctx
= ISC_FALSE
;
7230 unsigned int count
= 0;
7231 unsigned int spillat
;
7232 unsigned int spillatmin
;
7236 REQUIRE(VALID_RESOLVER(res
));
7237 REQUIRE(res
->frozen
);
7238 /* XXXRTH Check for meta type */
7239 if (domain
!= NULL
) {
7240 REQUIRE(DNS_RDATASET_VALID(nameservers
));
7241 REQUIRE(nameservers
->type
== dns_rdatatype_ns
);
7243 REQUIRE(nameservers
== NULL
);
7244 REQUIRE(forwarders
== NULL
);
7245 REQUIRE(!dns_rdataset_isassociated(rdataset
));
7246 REQUIRE(sigrdataset
== NULL
||
7247 !dns_rdataset_isassociated(sigrdataset
));
7248 REQUIRE(fetchp
!= NULL
&& *fetchp
== NULL
);
7250 log_fetch(name
, type
);
7253 * XXXRTH use a mempool?
7255 fetch
= isc_mem_get(res
->mctx
, sizeof(*fetch
));
7257 return (ISC_R_NOMEMORY
);
7259 bucketnum
= dns_name_fullhash(name
, ISC_FALSE
) % res
->nbuckets
;
7262 spillat
= res
->spillat
;
7263 spillatmin
= res
->spillatmin
;
7265 LOCK(&res
->buckets
[bucketnum
].lock
);
7267 if (res
->buckets
[bucketnum
].exiting
) {
7268 result
= ISC_R_SHUTTINGDOWN
;
7272 if ((options
& DNS_FETCHOPT_UNSHARED
) == 0) {
7273 for (fctx
= ISC_LIST_HEAD(res
->buckets
[bucketnum
].fctxs
);
7275 fctx
= ISC_LIST_NEXT(fctx
, link
)) {
7276 if (fctx_match(fctx
, name
, type
, options
))
7282 * Is this a duplicate?
7284 if (fctx
!= NULL
&& client
!= NULL
) {
7285 dns_fetchevent_t
*fevent
;
7286 for (fevent
= ISC_LIST_HEAD(fctx
->events
);
7288 fevent
= ISC_LIST_NEXT(fevent
, ev_link
)) {
7289 if (fevent
->client
!= NULL
&& fevent
->id
== id
&&
7290 isc_sockaddr_equal(fevent
->client
, client
)) {
7291 result
= DNS_R_DUPLICATE
;
7297 if (count
>= spillatmin
&& spillatmin
!= 0) {
7298 INSIST(fctx
!= NULL
);
7299 if (count
>= spillat
)
7300 fctx
->spilled
= ISC_TRUE
;
7301 if (fctx
->spilled
) {
7302 result
= DNS_R_DROP
;
7308 * If we didn't have a fetch, would attach to a done fetch, this
7309 * fetch has already cloned its results, or if the fetch has gone
7310 * "idle" (no one was interested in it), we need to start a new
7311 * fetch instead of joining with the existing one.
7314 fctx
->state
== fetchstate_done
||
7316 ISC_LIST_EMPTY(fctx
->events
)) {
7318 result
= fctx_create(res
, name
, type
, domain
, nameservers
,
7319 options
, bucketnum
, &fctx
);
7320 if (result
!= ISC_R_SUCCESS
)
7322 new_fctx
= ISC_TRUE
;
7325 result
= fctx_join(fctx
, task
, client
, id
, action
, arg
,
7326 rdataset
, sigrdataset
, fetch
);
7328 if (result
== ISC_R_SUCCESS
) {
7332 event
= &fctx
->control_event
;
7333 ISC_EVENT_INIT(event
, sizeof(*event
), 0, NULL
,
7334 DNS_EVENT_FETCHCONTROL
,
7335 fctx_start
, fctx
, NULL
,
7337 isc_task_send(res
->buckets
[bucketnum
].task
, &event
);
7340 * We don't care about the result of fctx_destroy()
7341 * since we know we're not exiting.
7343 (void)fctx_destroy(fctx
);
7348 UNLOCK(&res
->buckets
[bucketnum
].lock
);
7350 if (result
== ISC_R_SUCCESS
) {
7354 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
7360 dns_resolver_cancelfetch(dns_fetch_t
*fetch
) {
7362 dns_resolver_t
*res
;
7363 dns_fetchevent_t
*event
, *next_event
;
7366 REQUIRE(DNS_FETCH_VALID(fetch
));
7367 fctx
= fetch
->private;
7368 REQUIRE(VALID_FCTX(fctx
));
7371 FTRACE("cancelfetch");
7373 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7376 * Find the completion event for this fetch (as opposed
7377 * to those for other fetches that have joined the same
7378 * fctx) and send it with result = ISC_R_CANCELED.
7381 if (fctx
->state
!= fetchstate_done
) {
7382 for (event
= ISC_LIST_HEAD(fctx
->events
);
7384 event
= next_event
) {
7385 next_event
= ISC_LIST_NEXT(event
, ev_link
);
7386 if (event
->fetch
== fetch
) {
7387 ISC_LIST_UNLINK(fctx
->events
, event
, ev_link
);
7392 if (event
!= NULL
) {
7393 etask
= event
->ev_sender
;
7394 event
->ev_sender
= fctx
;
7395 event
->result
= ISC_R_CANCELED
;
7396 isc_task_sendanddetach(&etask
, ISC_EVENT_PTR(&event
));
7399 * The fctx continues running even if no fetches remain;
7400 * the answer is still cached.
7403 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7407 dns_resolver_destroyfetch(dns_fetch_t
**fetchp
) {
7409 dns_resolver_t
*res
;
7410 dns_fetchevent_t
*event
, *next_event
;
7412 unsigned int bucketnum
;
7413 isc_boolean_t bucket_empty
= ISC_FALSE
;
7415 REQUIRE(fetchp
!= NULL
);
7417 REQUIRE(DNS_FETCH_VALID(fetch
));
7418 fctx
= fetch
->private;
7419 REQUIRE(VALID_FCTX(fctx
));
7422 FTRACE("destroyfetch");
7424 bucketnum
= fctx
->bucketnum
;
7425 LOCK(&res
->buckets
[bucketnum
].lock
);
7428 * Sanity check: the caller should have gotten its event before
7429 * trying to destroy the fetch.
7432 if (fctx
->state
!= fetchstate_done
) {
7433 for (event
= ISC_LIST_HEAD(fctx
->events
);
7435 event
= next_event
) {
7436 next_event
= ISC_LIST_NEXT(event
, ev_link
);
7437 RUNTIME_CHECK(event
->fetch
!= fetch
);
7441 INSIST(fctx
->references
> 0);
7443 if (fctx
->references
== 0) {
7445 * No one cares about the result of this fetch anymore.
7447 if (fctx
->pending
== 0 && fctx
->nqueries
== 0 &&
7448 ISC_LIST_EMPTY(fctx
->validators
) &&
7449 SHUTTINGDOWN(fctx
)) {
7451 * This fctx is already shutdown; we were just
7452 * waiting for the last reference to go away.
7454 bucket_empty
= fctx_destroy(fctx
);
7457 * Initiate shutdown.
7459 fctx_shutdown(fctx
);
7463 UNLOCK(&res
->buckets
[bucketnum
].lock
);
7465 isc_mem_put(res
->mctx
, fetch
, sizeof(*fetch
));
7473 dns_resolver_logfetch(dns_fetch_t
*fetch
, isc_log_t
*lctx
,
7474 isc_logcategory_t
*category
, isc_logmodule_t
*module
,
7475 int level
, isc_boolean_t duplicateok
)
7478 dns_resolver_t
*res
;
7479 char domainbuf
[DNS_NAME_FORMATSIZE
];
7481 REQUIRE(DNS_FETCH_VALID(fetch
));
7482 fctx
= fetch
->private;
7483 REQUIRE(VALID_FCTX(fctx
));
7486 LOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7488 INSIST(fctx
->exitline
>= 0);
7489 if (!fctx
->logged
|| duplicateok
) {
7490 dns_name_format(&fctx
->domain
, domainbuf
, sizeof(domainbuf
));
7491 isc_log_write(lctx
, category
, module
, level
,
7492 "fetch completed at %s:%d for %s in "
7493 "%" ISC_PRINT_QUADFORMAT
"u."
7494 "%06" ISC_PRINT_QUADFORMAT
"u: %s/%s "
7495 "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
7496 "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
7497 "adberr:%u,findfail:%u,valfail:%u]",
7498 __FILE__
, fctx
->exitline
, fctx
->info
,
7499 fctx
->duration
/ 1000000,
7500 fctx
->duration
% 1000000,
7501 isc_result_totext(fctx
->result
),
7502 isc_result_totext(fctx
->vresult
), domainbuf
,
7503 fctx
->referrals
, fctx
->restarts
,
7504 fctx
->querysent
, fctx
->timeouts
, fctx
->lamecount
,
7505 fctx
->neterr
, fctx
->badresp
, fctx
->adberr
,
7506 fctx
->findfail
, fctx
->valfail
);
7507 fctx
->logged
= ISC_TRUE
;
7510 UNLOCK(&res
->buckets
[fctx
->bucketnum
].lock
);
7514 dns_resolver_dispatchmgr(dns_resolver_t
*resolver
) {
7515 REQUIRE(VALID_RESOLVER(resolver
));
7516 return (resolver
->dispatchmgr
);
7520 dns_resolver_dispatchv4(dns_resolver_t
*resolver
) {
7521 REQUIRE(VALID_RESOLVER(resolver
));
7522 return (resolver
->dispatchv4
);
7526 dns_resolver_dispatchv6(dns_resolver_t
*resolver
) {
7527 REQUIRE(VALID_RESOLVER(resolver
));
7528 return (resolver
->dispatchv6
);
7532 dns_resolver_socketmgr(dns_resolver_t
*resolver
) {
7533 REQUIRE(VALID_RESOLVER(resolver
));
7534 return (resolver
->socketmgr
);
7538 dns_resolver_taskmgr(dns_resolver_t
*resolver
) {
7539 REQUIRE(VALID_RESOLVER(resolver
));
7540 return (resolver
->taskmgr
);
7544 dns_resolver_getlamettl(dns_resolver_t
*resolver
) {
7545 REQUIRE(VALID_RESOLVER(resolver
));
7546 return (resolver
->lame_ttl
);
7550 dns_resolver_setlamettl(dns_resolver_t
*resolver
, isc_uint32_t lame_ttl
) {
7551 REQUIRE(VALID_RESOLVER(resolver
));
7552 resolver
->lame_ttl
= lame_ttl
;
7556 dns_resolver_nrunning(dns_resolver_t
*resolver
) {
7558 LOCK(&resolver
->nlock
);
7559 n
= resolver
->nfctx
;
7560 UNLOCK(&resolver
->nlock
);
7565 dns_resolver_addalternate(dns_resolver_t
*resolver
, isc_sockaddr_t
*alt
,
7566 dns_name_t
*name
, in_port_t port
) {
7568 isc_result_t result
;
7570 REQUIRE(VALID_RESOLVER(resolver
));
7571 REQUIRE(!resolver
->frozen
);
7572 REQUIRE((alt
== NULL
) ^ (name
== NULL
));
7574 a
= isc_mem_get(resolver
->mctx
, sizeof(*a
));
7576 return (ISC_R_NOMEMORY
);
7578 a
->isaddress
= ISC_TRUE
;
7581 a
->isaddress
= ISC_FALSE
;
7582 a
->_u
._n
.port
= port
;
7583 dns_name_init(&a
->_u
._n
.name
, NULL
);
7584 result
= dns_name_dup(name
, resolver
->mctx
, &a
->_u
._n
.name
);
7585 if (result
!= ISC_R_SUCCESS
) {
7586 isc_mem_put(resolver
->mctx
, a
, sizeof(*a
));
7590 ISC_LINK_INIT(a
, link
);
7591 ISC_LIST_APPEND(resolver
->alternates
, a
, link
);
7593 return (ISC_R_SUCCESS
);
7597 dns_resolver_setudpsize(dns_resolver_t
*resolver
, isc_uint16_t udpsize
) {
7598 REQUIRE(VALID_RESOLVER(resolver
));
7599 resolver
->udpsize
= udpsize
;
7603 dns_resolver_getudpsize(dns_resolver_t
*resolver
) {
7604 REQUIRE(VALID_RESOLVER(resolver
));
7605 return (resolver
->udpsize
);
7609 free_algorithm(void *node
, void *arg
) {
7610 unsigned char *algorithms
= node
;
7611 isc_mem_t
*mctx
= arg
;
7613 isc_mem_put(mctx
, algorithms
, *algorithms
);
7617 dns_resolver_reset_algorithms(dns_resolver_t
*resolver
) {
7619 REQUIRE(VALID_RESOLVER(resolver
));
7622 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
7624 if (resolver
->algorithms
!= NULL
)
7625 dns_rbt_destroy(&resolver
->algorithms
);
7627 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
7632 dns_resolver_disable_algorithm(dns_resolver_t
*resolver
, dns_name_t
*name
,
7635 unsigned int len
, mask
;
7637 unsigned char *algorithms
;
7638 isc_result_t result
;
7639 dns_rbtnode_t
*node
= NULL
;
7641 REQUIRE(VALID_RESOLVER(resolver
));
7643 return (ISC_R_RANGE
);
7646 RWLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
7648 if (resolver
->algorithms
== NULL
) {
7649 result
= dns_rbt_create(resolver
->mctx
, free_algorithm
,
7650 resolver
->mctx
, &resolver
->algorithms
);
7651 if (result
!= ISC_R_SUCCESS
)
7656 mask
= 1 << (alg
%8);
7658 result
= dns_rbt_addnode(resolver
->algorithms
, name
, &node
);
7660 if (result
== ISC_R_SUCCESS
|| result
== ISC_R_EXISTS
) {
7661 algorithms
= node
->data
;
7662 if (algorithms
== NULL
|| len
> *algorithms
) {
7663 new = isc_mem_get(resolver
->mctx
, len
);
7665 result
= ISC_R_NOMEMORY
;
7668 memset(new, 0, len
);
7669 if (algorithms
!= NULL
)
7670 memcpy(new, algorithms
, *algorithms
);
7674 if (algorithms
!= NULL
)
7675 isc_mem_put(resolver
->mctx
, algorithms
,
7678 algorithms
[len
-1] |= mask
;
7680 result
= ISC_R_SUCCESS
;
7683 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_write
);
7689 dns_resolver_algorithm_supported(dns_resolver_t
*resolver
, dns_name_t
*name
,
7692 unsigned int len
, mask
;
7693 unsigned char *algorithms
;
7695 isc_result_t result
;
7696 isc_boolean_t found
= ISC_FALSE
;
7698 REQUIRE(VALID_RESOLVER(resolver
));
7701 RWLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
7703 if (resolver
->algorithms
== NULL
)
7705 result
= dns_rbt_findname(resolver
->algorithms
, name
, 0, NULL
, &data
);
7706 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
7708 mask
= 1 << (alg
%8);
7710 if (len
<= *algorithms
&& (algorithms
[len
-1] & mask
) != 0)
7715 RWUNLOCK(&resolver
->alglock
, isc_rwlocktype_read
);
7719 return (dst_algorithm_supported(alg
));
7723 dns_resolver_digest_supported(dns_resolver_t
*resolver
, unsigned int digest
) {
7726 return (dns_ds_digest_supported(digest
));
7730 dns_resolver_resetmustbesecure(dns_resolver_t
*resolver
) {
7732 REQUIRE(VALID_RESOLVER(resolver
));
7735 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
7737 if (resolver
->mustbesecure
!= NULL
)
7738 dns_rbt_destroy(&resolver
->mustbesecure
);
7740 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
7744 static isc_boolean_t yes
= ISC_TRUE
, no
= ISC_FALSE
;
7747 dns_resolver_setmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
,
7748 isc_boolean_t value
)
7750 isc_result_t result
;
7752 REQUIRE(VALID_RESOLVER(resolver
));
7755 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
7757 if (resolver
->mustbesecure
== NULL
) {
7758 result
= dns_rbt_create(resolver
->mctx
, NULL
, NULL
,
7759 &resolver
->mustbesecure
);
7760 if (result
!= ISC_R_SUCCESS
)
7763 result
= dns_rbt_addname(resolver
->mustbesecure
, name
,
7764 value
? &yes
: &no
);
7767 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_write
);
7773 dns_resolver_getmustbesecure(dns_resolver_t
*resolver
, dns_name_t
*name
) {
7775 isc_boolean_t value
= ISC_FALSE
;
7776 isc_result_t result
;
7778 REQUIRE(VALID_RESOLVER(resolver
));
7781 RWLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);
7783 if (resolver
->mustbesecure
== NULL
)
7785 result
= dns_rbt_findname(resolver
->mustbesecure
, name
, 0, NULL
, &data
);
7786 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
7787 value
= *(isc_boolean_t
*)data
;
7790 RWUNLOCK(&resolver
->mbslock
, isc_rwlocktype_read
);
7796 dns_resolver_getclientsperquery(dns_resolver_t
*resolver
, isc_uint32_t
*cur
,
7797 isc_uint32_t
*min
, isc_uint32_t
*max
)
7799 REQUIRE(VALID_RESOLVER(resolver
));
7801 LOCK(&resolver
->lock
);
7803 *cur
= resolver
->spillat
;
7805 *min
= resolver
->spillatmin
;
7807 *max
= resolver
->spillatmax
;
7808 UNLOCK(&resolver
->lock
);
7812 dns_resolver_setclientsperquery(dns_resolver_t
*resolver
, isc_uint32_t min
,
7815 REQUIRE(VALID_RESOLVER(resolver
));
7817 LOCK(&resolver
->lock
);
7818 resolver
->spillatmin
= resolver
->spillat
= min
;
7819 resolver
->spillatmax
= max
;
7820 UNLOCK(&resolver
->lock
);
7824 dns_resolver_getzeronosoattl(dns_resolver_t
*resolver
) {
7825 REQUIRE(VALID_RESOLVER(resolver
));
7827 return (resolver
->zero_no_soa_ttl
);
7831 dns_resolver_setzeronosoattl(dns_resolver_t
*resolver
, isc_boolean_t state
) {
7832 REQUIRE(VALID_RESOLVER(resolver
));
7834 resolver
->zero_no_soa_ttl
= state
;
7838 dns_resolver_getoptions(dns_resolver_t
*resolver
) {
7839 REQUIRE(VALID_RESOLVER(resolver
));
7841 return (resolver
->options
);