2 * Copyright (C) 2004-2008 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.284.18.66.8.4 2008/07/24 05:00:48 jinmei Exp $ */
24 #include <isc/print.h>
25 #include <isc/string.h>
27 #include <isc/timer.h>
32 #include <dns/cache.h>
34 #include <dns/dispatch.h>
36 #include <dns/events.h>
37 #include <dns/forward.h>
38 #include <dns/keytable.h>
40 #include <dns/message.h>
41 #include <dns/ncache.h>
42 #include <dns/opcode.h>
45 #include <dns/rcode.h>
46 #include <dns/rdata.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdatalist.h>
49 #include <dns/rdataset.h>
50 #include <dns/rdatastruct.h>
51 #include <dns/rdatatype.h>
52 #include <dns/resolver.h>
53 #include <dns/result.h>
54 #include <dns/rootns.h>
56 #include <dns/validator.h>
58 #define DNS_RESOLVER_TRACE
59 #ifdef DNS_RESOLVER_TRACE
60 #define RTRACE(m) isc_log_write(dns_lctx, \
61 DNS_LOGCATEGORY_RESOLVER, \
62 DNS_LOGMODULE_RESOLVER, \
64 "res %p: %s", res, (m))
65 #define RRTRACE(r, m) isc_log_write(dns_lctx, \
66 DNS_LOGCATEGORY_RESOLVER, \
67 DNS_LOGMODULE_RESOLVER, \
69 "res %p: %s", (r), (m))
70 #define FCTXTRACE(m) isc_log_write(dns_lctx, \
71 DNS_LOGCATEGORY_RESOLVER, \
72 DNS_LOGMODULE_RESOLVER, \
74 "fctx %p(%s'): %s", fctx, fctx->info, (m))
75 #define FCTXTRACE2(m1, m2) \
76 isc_log_write(dns_lctx, \
77 DNS_LOGCATEGORY_RESOLVER, \
78 DNS_LOGMODULE_RESOLVER, \
80 "fctx %p(%s): %s %s", \
81 fctx, fctx->info, (m1), (m2))
82 #define FTRACE(m) isc_log_write(dns_lctx, \
83 DNS_LOGCATEGORY_RESOLVER, \
84 DNS_LOGMODULE_RESOLVER, \
86 "fetch %p (fctx %p(%s)): %s", \
87 fetch, fetch->private, \
88 fetch->private->info, (m))
89 #define QTRACE(m) isc_log_write(dns_lctx, \
90 DNS_LOGCATEGORY_RESOLVER, \
91 DNS_LOGMODULE_RESOLVER, \
93 "resquery %p (fctx %p(%s)): %s", \
95 query->fctx->info, (m))
105 * Maximum EDNS0 input packet size.
107 #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
110 * This defines the maximum number of timeouts we will permit before we
111 * disable EDNS0 on the query.
113 #define MAX_EDNS0_TIMEOUTS 3
115 typedef struct fetchctx fetchctx_t;
117 typedef struct query {
118 /* Locked by task event serialization. */
122 dns_dispatchmgr_t * dispatchmgr;
123 dns_dispatch_t * dispatch;
124 dns_adbaddrinfo_t * addrinfo;
125 isc_socket_t * tcpsocket;
128 dns_dispentry_t * dispentry;
129 ISC_LINK(struct query) link;
132 dns_tsigkey_t *tsigkey;
133 unsigned int options;
134 unsigned int attributes;
136 unsigned int connects;
137 unsigned char data[512];
140 #define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
141 #define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
143 #define RESQUERY_ATTR_CANCELED 0x02
145 #define RESQUERY_CONNECTING(q) ((q)->connects > 0)
146 #define RESQUERY_CANCELED(q) (((q)->attributes & \
147 RESQUERY_ATTR_CANCELED) != 0)
148 #define RESQUERY_SENDING(q) ((q)->sends > 0)
151 fetchstate_init = 0, /*%< Start event has not run yet. */
153 fetchstate_done /*%< FETCHDONE events posted. */
159 dns_resolver_t * res;
161 dns_rdatatype_t type;
162 unsigned int options;
163 unsigned int bucketnum;
165 /*% Locked by appropriate bucket lock. */
167 isc_boolean_t want_shutdown;
168 isc_boolean_t cloned;
169 isc_boolean_t spilled;
170 unsigned int references;
171 isc_event_t control_event;
172 ISC_LINK(struct fetchctx) link;
173 ISC_LIST(dns_fetchevent_t) events;
174 /*% Locked by task event serialization. */
176 dns_rdataset_t nameservers;
177 unsigned int attributes;
180 isc_interval_t interval;
181 dns_message_t * qmessage;
182 dns_message_t * rmessage;
183 ISC_LIST(resquery_t) queries;
184 dns_adbfindlist_t finds;
185 dns_adbfind_t * find;
186 dns_adbfindlist_t altfinds;
187 dns_adbfind_t * altfind;
188 dns_adbaddrinfolist_t forwaddrs;
189 dns_adbaddrinfolist_t altaddrs;
190 isc_sockaddrlist_t forwarders;
191 dns_fwdpolicy_t fwdpolicy;
192 isc_sockaddrlist_t bad;
193 isc_sockaddrlist_t edns;
194 isc_sockaddrlist_t edns512;
195 dns_validator_t *validator;
196 ISC_LIST(dns_validator_t) validators;
201 * The number of events we're waiting for.
203 unsigned int pending;
206 * The number of times we've "restarted" the current
207 * nameserver set. This acts as a failsafe to prevent
208 * us from pounding constantly on a particular set of
209 * servers that, for whatever reason, are not giving
210 * us useful responses, but are responding in such a
211 * way that they are not marked "bad".
213 unsigned int restarts;
216 * The number of timeouts that have occurred since we
217 * last successfully received a response packet. This
218 * is used for EDNS0 black hole detection.
220 unsigned int timeouts;
222 * Look aside state for DS lookups.
225 dns_fetch_t * nsfetch;
226 dns_rdataset_t nsrrset;
229 * Number of queries that reference this context.
231 unsigned int nqueries;
234 #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
235 #define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
237 #define FCTX_ATTR_HAVEANSWER 0x0001
238 #define FCTX_ATTR_GLUING 0x0002
239 #define FCTX_ATTR_ADDRWAIT 0x0004
240 #define FCTX_ATTR_SHUTTINGDOWN 0x0008
241 #define FCTX_ATTR_WANTCACHE 0x0010
242 #define FCTX_ATTR_WANTNCACHE 0x0020
243 #define FCTX_ATTR_NEEDEDNS0 0x0040
244 #define FCTX_ATTR_TRIEDFIND 0x0080
245 #define FCTX_ATTR_TRIEDALT 0x0100
247 #define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
249 #define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
251 #define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
253 #define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
255 #define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
256 #define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
257 #define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
258 #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
259 #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
262 dns_adbaddrinfo_t * addrinfo;
268 fetchctx_t * private;
271 #define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
272 #define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
274 typedef struct fctxbucket {
277 ISC_LIST(fetchctx_t) fctxs;
278 isc_boolean_t exiting;
282 typedef struct alternate {
283 isc_boolean_t isaddress;
291 ISC_LINK(struct alternate) link;
294 struct dns_resolver {
300 isc_mutex_t primelock;
301 dns_rdataclass_t rdclass;
302 isc_socketmgr_t * socketmgr;
303 isc_timermgr_t * timermgr;
304 isc_taskmgr_t * taskmgr;
306 isc_boolean_t frozen;
307 unsigned int options;
308 dns_dispatchmgr_t * dispatchmgr;
309 dns_dispatch_t * dispatchv4;
310 dns_dispatch_t * dispatchv6;
311 unsigned int nbuckets;
312 fctxbucket_t * buckets;
313 isc_uint32_t lame_ttl;
314 ISC_LIST(alternate_t) alternates;
315 isc_uint16_t udpsize;
317 isc_rwlock_t alglock;
319 dns_rbt_t * algorithms;
321 isc_rwlock_t mbslock;
323 dns_rbt_t * mustbesecure;
324 unsigned int spillatmax;
325 unsigned int spillatmin;
326 isc_timer_t * spillattimer;
327 isc_boolean_t zero_no_soa_ttl;
328 /* Locked by lock. */
329 unsigned int references;
330 isc_boolean_t exiting;
331 isc_eventlist_t whenshutdown;
332 unsigned int activebuckets;
333 isc_boolean_t priming;
334 unsigned int spillat;
335 /* Locked by primelock. */
336 dns_fetch_t * primefetch;
337 /* Locked by nlock. */
341 #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
342 #define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
345 * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
346 * which we also use as an addrinfo flag.
348 #define FCTX_ADDRINFO_MARK 0x0001
349 #define FCTX_ADDRINFO_FORWARDER 0x1000
350 #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
352 #define ISFORWARDER(a) (((a)->flags & \
353 FCTX_ADDRINFO_FORWARDER) != 0)
355 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
357 #define dns_db_transfernode(a,b,c) do { (*c) = (*b); (*b) = NULL; } while (0)
359 static void destroy(dns_resolver_t *res);
360 static void empty_bucket(dns_resolver_t *res);
361 static isc_result_t resquery_send(resquery_t *query);
362 static void resquery_response(isc_task_t *task, isc_event_t *event);
363 static void resquery_connected(isc_task_t *task, isc_event_t *event);
364 static void fctx_try(fetchctx_t *fctx);
365 static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
366 static isc_result_t ncache_adderesult(dns_message_t *message,
367 dns_db_t *cache, dns_dbnode_t *node,
368 dns_rdatatype_t covers,
369 isc_stdtime_t now, dns_ttl_t maxttl,
370 dns_rdataset_t *ardataset,
371 isc_result_t *eresultp);
372 static void validated(isc_task_t *task, isc_event_t *event);
373 static void maybe_destroy(fetchctx_t *fctx);
376 valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
377 dns_rdatatype_t type, dns_rdataset_t *rdataset,
378 dns_rdataset_t *sigrdataset, unsigned int valoptions,
381 dns_validator_t *validator = NULL;
382 dns_valarg_t *valarg;
385 valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
388 return (ISC_R_NOMEMORY);
391 valarg->addrinfo = addrinfo;
393 if (!ISC_LIST_EMPTY(fctx->validators))
394 INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
396 result = dns_validator_create(fctx->res->view, name, type, rdataset,
397 sigrdataset, fctx->rmessage,
398 valoptions, task, validated, valarg,
400 if (result == ISC_R_SUCCESS) {
401 if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
402 INSIST(fctx->validator == NULL);
403 fctx->validator = validator;
405 ISC_LIST_APPEND(fctx->validators, validator, link);
407 isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
408 valarg, sizeof(*valarg));
413 fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
415 dns_name_t *domain = &fctx->domain;
416 dns_rdataset_t *rdataset;
417 dns_rdatatype_t type;
419 isc_boolean_t keep_auth = ISC_FALSE;
421 if (message->rcode == dns_rcode_nxdomain)
425 * Look for BIND 8 style delegations.
426 * Also look for answers to ANY queries where the duplicate NS RRset
427 * may have been stripped from the authority section.
429 if (message->counts[DNS_SECTION_ANSWER] != 0 &&
430 (fctx->type == dns_rdatatype_ns ||
431 fctx->type == dns_rdatatype_any)) {
432 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
433 while (result == ISC_R_SUCCESS) {
435 dns_message_currentname(message, DNS_SECTION_ANSWER,
437 for (rdataset = ISC_LIST_HEAD(name->list);
439 rdataset = ISC_LIST_NEXT(rdataset, link)) {
440 type = rdataset->type;
441 if (type != dns_rdatatype_ns)
443 if (dns_name_issubdomain(name, domain))
446 result = dns_message_nextname(message,
451 /* Look for referral. */
452 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
455 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
456 while (result == ISC_R_SUCCESS) {
458 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
459 for (rdataset = ISC_LIST_HEAD(name->list);
461 rdataset = ISC_LIST_NEXT(rdataset, link)) {
462 type = rdataset->type;
463 if (type == dns_rdatatype_soa &&
464 dns_name_equal(name, domain))
465 keep_auth = ISC_TRUE;
466 if (type != dns_rdatatype_ns &&
467 type != dns_rdatatype_soa)
469 if (dns_name_equal(name, domain))
471 if (dns_name_issubdomain(name, domain))
474 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
478 message->rcode = dns_rcode_nxdomain;
479 message->counts[DNS_SECTION_ANSWER] = 0;
481 message->counts[DNS_SECTION_AUTHORITY] = 0;
482 message->counts[DNS_SECTION_ADDITIONAL] = 0;
486 static inline isc_result_t
487 fctx_starttimer(fetchctx_t *fctx) {
489 * Start the lifetime timer for fctx.
491 * This is also used for stopping the idle timer; in that
492 * case we must purge events already posted to ensure that
493 * no further idle events are delivered.
495 return (isc_timer_reset(fctx->timer, isc_timertype_once,
496 &fctx->expires, NULL, ISC_TRUE));
500 fctx_stoptimer(fetchctx_t *fctx) {
504 * We don't return a result if resetting the timer to inactive fails
505 * since there's nothing to be done about it. Resetting to inactive
506 * should never fail anyway, since the code as currently written
507 * cannot fail in that case.
509 result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
510 NULL, NULL, ISC_TRUE);
511 if (result != ISC_R_SUCCESS) {
512 UNEXPECTED_ERROR(__FILE__, __LINE__,
513 "isc_timer_reset(): %s",
514 isc_result_totext(result));
519 static inline isc_result_t
520 fctx_startidletimer(fetchctx_t *fctx) {
522 * Start the idle timer for fctx. The lifetime timer continues
525 return (isc_timer_reset(fctx->timer, isc_timertype_once,
526 &fctx->expires, &fctx->interval,
531 * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
532 * we use fctx_stopidletimer for readability in the code below.
534 #define fctx_stopidletimer fctx_starttimer
538 resquery_destroy(resquery_t **queryp) {
541 REQUIRE(queryp != NULL);
543 REQUIRE(!ISC_LINK_LINKED(query, link));
545 INSIST(query->tcpsocket == NULL);
547 query->fctx->nqueries--;
548 if (SHUTTINGDOWN(query->fctx))
549 maybe_destroy(query->fctx); /* Locks bucket. */
551 isc_mem_put(query->mctx, query, sizeof(*query));
556 fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
557 isc_time_t *finish, isc_boolean_t no_response)
564 dns_adbaddrinfo_t *addrinfo;
569 FCTXTRACE("cancelquery");
571 REQUIRE(!RESQUERY_CANCELED(query));
573 query->attributes |= RESQUERY_ATTR_CANCELED;
576 * Should we update the RTT?
578 if (finish != NULL || no_response) {
579 if (finish != NULL) {
581 * We have both the start and finish times for this
582 * packet, so we can compute a real RTT.
584 rtt = (unsigned int)isc_time_microdiff(finish,
586 factor = DNS_ADB_RTTADJDEFAULT;
589 * We don't have an RTT for this query. Maybe the
590 * packet was lost, or maybe this server is very
591 * slow. We don't know. Increase the RTT.
594 rtt = query->addrinfo->srtt + 200000;
598 * Replace the current RTT with our value.
600 factor = DNS_ADB_RTTADJREPLACE;
602 dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
606 * Age RTTs of servers not tried.
608 factor = DNS_ADB_RTTADJAGE;
610 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
612 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
613 if (UNMARKED(addrinfo))
614 dns_adb_adjustsrtt(fctx->adb, addrinfo,
617 if (finish != NULL && TRIEDFIND(fctx))
618 for (find = ISC_LIST_HEAD(fctx->finds);
620 find = ISC_LIST_NEXT(find, publink))
621 for (addrinfo = ISC_LIST_HEAD(find->list);
623 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
624 if (UNMARKED(addrinfo))
625 dns_adb_adjustsrtt(fctx->adb, addrinfo,
628 if (finish != NULL && TRIEDALT(fctx)) {
629 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
631 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
632 if (UNMARKED(addrinfo))
633 dns_adb_adjustsrtt(fctx->adb, addrinfo,
635 for (find = ISC_LIST_HEAD(fctx->altfinds);
637 find = ISC_LIST_NEXT(find, publink))
638 for (addrinfo = ISC_LIST_HEAD(find->list);
640 addrinfo = ISC_LIST_NEXT(addrinfo, publink))
641 if (UNMARKED(addrinfo))
642 dns_adb_adjustsrtt(fctx->adb, addrinfo,
646 if (query->dispentry != NULL)
647 dns_dispatch_removeresponse(&query->dispentry, deventp);
649 ISC_LIST_UNLINK(fctx->queries, query, link);
651 if (query->tsig != NULL)
652 isc_buffer_free(&query->tsig);
654 if (query->tsigkey != NULL)
655 dns_tsigkey_detach(&query->tsigkey);
658 * Check for any outstanding socket events. If they exist, cancel
659 * them and let the event handlers finish the cleanup. The resolver
660 * only needs to worry about managing the connect and send events;
661 * the dispatcher manages the recv events.
663 if (RESQUERY_CONNECTING(query))
665 * Cancel the connect.
667 isc_socket_cancel(query->tcpsocket, NULL,
668 ISC_SOCKCANCEL_CONNECT);
669 else if (RESQUERY_SENDING(query))
671 * Cancel the pending send.
673 isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
674 NULL, ISC_SOCKCANCEL_SEND);
676 if (query->dispatch != NULL)
677 dns_dispatch_detach(&query->dispatch);
679 if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
681 * It's safe to destroy the query now.
683 resquery_destroy(&query);
687 fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
688 resquery_t *query, *next_query;
690 FCTXTRACE("cancelqueries");
692 for (query = ISC_LIST_HEAD(fctx->queries);
694 query = next_query) {
695 next_query = ISC_LIST_NEXT(query, link);
696 fctx_cancelquery(&query, NULL, NULL, no_response);
701 fctx_cleanupfinds(fetchctx_t *fctx) {
702 dns_adbfind_t *find, *next_find;
704 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
706 for (find = ISC_LIST_HEAD(fctx->finds);
709 next_find = ISC_LIST_NEXT(find, publink);
710 ISC_LIST_UNLINK(fctx->finds, find, publink);
711 dns_adb_destroyfind(&find);
717 fctx_cleanupaltfinds(fetchctx_t *fctx) {
718 dns_adbfind_t *find, *next_find;
720 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
722 for (find = ISC_LIST_HEAD(fctx->altfinds);
725 next_find = ISC_LIST_NEXT(find, publink);
726 ISC_LIST_UNLINK(fctx->altfinds, find, publink);
727 dns_adb_destroyfind(&find);
729 fctx->altfind = NULL;
733 fctx_cleanupforwaddrs(fetchctx_t *fctx) {
734 dns_adbaddrinfo_t *addr, *next_addr;
736 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
738 for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
741 next_addr = ISC_LIST_NEXT(addr, publink);
742 ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
743 dns_adb_freeaddrinfo(fctx->adb, &addr);
748 fctx_cleanupaltaddrs(fetchctx_t *fctx) {
749 dns_adbaddrinfo_t *addr, *next_addr;
751 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
753 for (addr = ISC_LIST_HEAD(fctx->altaddrs);
756 next_addr = ISC_LIST_NEXT(addr, publink);
757 ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
758 dns_adb_freeaddrinfo(fctx->adb, &addr);
763 fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
764 FCTXTRACE("stopeverything");
765 fctx_cancelqueries(fctx, no_response);
766 fctx_cleanupfinds(fctx);
767 fctx_cleanupaltfinds(fctx);
768 fctx_cleanupforwaddrs(fctx);
769 fctx_cleanupaltaddrs(fctx);
770 fctx_stoptimer(fctx);
774 fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
775 dns_fetchevent_t *event, *next_event;
777 unsigned int count = 0;
779 isc_boolean_t logit = ISC_FALSE;
782 * Caller must be holding the appropriate bucket lock.
784 REQUIRE(fctx->state == fetchstate_done);
786 FCTXTRACE("sendevents");
788 for (event = ISC_LIST_HEAD(fctx->events);
790 event = next_event) {
791 next_event = ISC_LIST_NEXT(event, ev_link);
792 ISC_LIST_UNLINK(fctx->events, event, ev_link);
793 task = event->ev_sender;
794 event->ev_sender = fctx;
795 if (!HAVE_ANSWER(fctx))
796 event->result = result;
798 INSIST(result != ISC_R_SUCCESS ||
799 dns_rdataset_isassociated(event->rdataset) ||
800 fctx->type == dns_rdatatype_any ||
801 fctx->type == dns_rdatatype_rrsig ||
802 fctx->type == dns_rdatatype_sig);
805 * Negative results must be indicated in event->result.
807 if (dns_rdataset_isassociated(event->rdataset) &&
808 event->rdataset->type == dns_rdatatype_none) {
809 INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
810 event->result == DNS_R_NCACHENXRRSET);
813 isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
817 if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
819 (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
820 LOCK(&fctx->res->lock);
821 if (count == fctx->res->spillat && !fctx->res->exiting) {
822 fctx->res->spillat += 5;
823 if (fctx->res->spillat > fctx->res->spillatmax &&
824 fctx->res->spillatmax != 0)
825 fctx->res->spillat = fctx->res->spillatmax;
827 isc_interval_set(&i, 20 * 60, 0);
828 result = isc_timer_reset(fctx->res->spillattimer,
829 isc_timertype_ticker, NULL,
831 RUNTIME_CHECK(result == ISC_R_SUCCESS);
833 UNLOCK(&fctx->res->lock);
835 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
836 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
837 "clients-per-query increased to %u",
843 fctx_done(fetchctx_t *fctx, isc_result_t result) {
845 isc_boolean_t no_response;
851 if (result == ISC_R_SUCCESS)
852 no_response = ISC_TRUE;
854 no_response = ISC_FALSE;
855 fctx_stopeverything(fctx, no_response);
857 LOCK(&res->buckets[fctx->bucketnum].lock);
859 fctx->state = fetchstate_done;
860 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
861 fctx_sendevents(fctx, result);
863 UNLOCK(&res->buckets[fctx->bucketnum].lock);
867 resquery_senddone(isc_task_t *task, isc_event_t *event) {
868 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
869 resquery_t *query = event->ev_arg;
870 isc_boolean_t retry = ISC_FALSE;
874 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
881 * Currently we don't wait for the senddone event before retrying
882 * a query. This means that if we get really behind, we may end
883 * up doing extra work!
888 INSIST(RESQUERY_SENDING(query));
893 if (RESQUERY_CANCELED(query)) {
894 if (query->sends == 0) {
896 * This query was canceled while the
897 * isc_socket_sendto() was in progress.
899 if (query->tcpsocket != NULL)
900 isc_socket_detach(&query->tcpsocket);
901 resquery_destroy(&query);
904 switch (sevent->result) {
908 case ISC_R_HOSTUNREACH:
909 case ISC_R_NETUNREACH:
911 case ISC_R_ADDRNOTAVAIL:
912 case ISC_R_CONNREFUSED:
915 * No route to remote.
917 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
922 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
926 isc_event_free(&event);
930 * Behave as if the idle timer has expired. For TCP
931 * this may not actually reflect the latest timer.
933 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
934 result = fctx_stopidletimer(fctx);
935 if (result != ISC_R_SUCCESS)
936 fctx_done(fctx, result);
942 static inline isc_result_t
943 fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
945 dns_rdataset_t *rdataset;
946 dns_rdatalist_t *rdatalist;
951 result = dns_message_gettemprdatalist(message, &rdatalist);
952 if (result != ISC_R_SUCCESS)
955 result = dns_message_gettemprdata(message, &rdata);
956 if (result != ISC_R_SUCCESS)
959 result = dns_message_gettemprdataset(message, &rdataset);
960 if (result != ISC_R_SUCCESS)
962 dns_rdataset_init(rdataset);
964 rdatalist->type = dns_rdatatype_opt;
965 rdatalist->covers = 0;
968 * Set Maximum UDP buffer size.
970 rdatalist->rdclass = udpsize;
973 * Set EXTENDED-RCODE and Z to 0, DO to 1.
975 rdatalist->ttl = (version << 16);
976 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
983 rdata->rdclass = rdatalist->rdclass;
984 rdata->type = rdatalist->type;
987 ISC_LIST_INIT(rdatalist->rdata);
988 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
989 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
991 return (dns_message_setopt(message, rdataset));
995 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
996 unsigned int seconds;
1000 * We retry every .5 seconds the first two times through the address
1001 * list, and then we do exponential back-off.
1003 if (fctx->restarts < 3)
1006 us = (500000 << (fctx->restarts - 2));
1009 * Double the round-trip time.
1014 * Always wait for at least the doubled round-trip time.
1020 * But don't ever wait for more than 10 seconds.
1025 seconds = us / 1000000;
1026 us -= seconds * 1000000;
1027 isc_interval_set(&fctx->interval, seconds, us * 1000);
1031 fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
1032 unsigned int options)
1034 dns_resolver_t *res;
1036 isc_result_t result;
1038 isc_sockaddr_t addr;
1039 isc_boolean_t have_addr = ISC_FALSE;
1044 task = res->buckets[fctx->bucketnum].task;
1046 fctx_setretryinterval(fctx, addrinfo->srtt);
1047 result = fctx_startidletimer(fctx);
1048 if (result != ISC_R_SUCCESS)
1051 INSIST(ISC_LIST_EMPTY(fctx->validators));
1053 dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
1055 query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,
1057 if (query == NULL) {
1058 result = ISC_R_NOMEMORY;
1059 goto stop_idle_timer;
1061 query->mctx = res->buckets[fctx->bucketnum].mctx;
1062 query->options = options;
1063 query->attributes = 0;
1065 query->connects = 0;
1067 * Note that the caller MUST guarantee that 'addrinfo' will remain
1068 * valid until this query is canceled.
1070 query->addrinfo = addrinfo;
1071 TIME_NOW(&query->start);
1074 * If this is a TCP query, then we need to make a socket and
1075 * a dispatch for it here. Otherwise we use the resolver's
1078 query->dispatchmgr = res->dispatchmgr;
1079 query->dispatch = NULL;
1080 query->tcpsocket = NULL;
1081 if (res->view->peers != NULL) {
1082 dns_peer_t *peer = NULL;
1083 isc_netaddr_t dstip;
1084 isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
1085 result = dns_peerlist_peerbyaddr(res->view->peers,
1087 if (result == ISC_R_SUCCESS) {
1088 result = dns_peer_getquerysource(peer, &addr);
1089 if (result == ISC_R_SUCCESS)
1090 have_addr = ISC_TRUE;
1094 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1097 pf = isc_sockaddr_pf(&addrinfo->sockaddr);
1102 dns_dispatch_getlocaladdress(res->dispatchv4,
1107 dns_dispatch_getlocaladdress(res->dispatchv6,
1111 result = ISC_R_NOTIMPLEMENTED;
1114 if (result != ISC_R_SUCCESS)
1117 isc_sockaddr_setport(&addr, 0);
1119 result = isc_socket_create(res->socketmgr, pf,
1122 if (result != ISC_R_SUCCESS)
1125 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
1126 result = isc_socket_bind(query->tcpsocket, &addr, 0);
1127 if (result != ISC_R_SUCCESS)
1128 goto cleanup_socket;
1132 * A dispatch will be created once the connect succeeds.
1136 unsigned int attrs, attrmask;
1137 attrs = DNS_DISPATCHATTR_UDP;
1138 switch (isc_sockaddr_pf(&addr)) {
1140 attrs |= DNS_DISPATCHATTR_IPV4;
1143 attrs |= DNS_DISPATCHATTR_IPV6;
1146 result = ISC_R_NOTIMPLEMENTED;
1149 attrmask = DNS_DISPATCHATTR_UDP;
1150 attrmask |= DNS_DISPATCHATTR_TCP;
1151 attrmask |= DNS_DISPATCHATTR_IPV4;
1152 attrmask |= DNS_DISPATCHATTR_IPV6;
1153 result = dns_dispatch_getudp(res->dispatchmgr,
1155 res->taskmgr, &addr,
1156 4096, 1000, 32768, 16411,
1157 16433, attrs, attrmask,
1159 if (result != ISC_R_SUCCESS)
1162 isc_sockaddr_t localaddr;
1163 unsigned int attrs, attrmask;
1164 dns_dispatch_t *disp_base;
1167 attrs |= DNS_DISPATCHATTR_UDP;
1168 attrs |= DNS_DISPATCHATTR_RANDOMPORT;
1171 attrmask |= DNS_DISPATCHATTR_UDP;
1172 attrmask |= DNS_DISPATCHATTR_TCP;
1173 attrmask |= DNS_DISPATCHATTR_IPV4;
1174 attrmask |= DNS_DISPATCHATTR_IPV6;
1176 switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
1178 disp_base = res->dispatchv4;
1179 attrs |= DNS_DISPATCHATTR_IPV4;
1182 disp_base = res->dispatchv6;
1183 attrs |= DNS_DISPATCHATTR_IPV6;
1186 result = ISC_R_NOTIMPLEMENTED;
1190 result = dns_dispatch_getlocaladdress(disp_base,
1192 if (result != ISC_R_SUCCESS)
1194 if (isc_sockaddr_getport(&localaddr) == 0) {
1195 result = dns_dispatch_getudp(res->dispatchmgr,
1203 if (result != ISC_R_SUCCESS)
1206 dns_dispatch_attach(disp_base,
1211 * We should always have a valid dispatcher here. If we
1212 * don't support a protocol family, then its dispatcher
1213 * will be NULL, but we shouldn't be finding addresses for
1214 * protocol types we don't support, so the dispatcher
1215 * we found should never be NULL.
1217 INSIST(query->dispatch != NULL);
1220 query->dispentry = NULL;
1223 query->tsigkey = NULL;
1224 ISC_LINK_INIT(query, link);
1225 query->magic = QUERY_MAGIC;
1227 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1229 * Connect to the remote server.
1231 * XXXRTH Should we attach to the socket?
1233 result = isc_socket_connect(query->tcpsocket,
1234 &addrinfo->sockaddr, task,
1235 resquery_connected, query);
1236 if (result != ISC_R_SUCCESS)
1237 goto cleanup_socket;
1239 QTRACE("connecting via TCP");
1241 result = resquery_send(query);
1242 if (result != ISC_R_SUCCESS)
1243 goto cleanup_dispatch;
1246 ISC_LIST_APPEND(fctx->queries, query, link);
1247 query->fctx->nqueries++;
1249 return (ISC_R_SUCCESS);
1252 isc_socket_detach(&query->tcpsocket);
1255 if (query->dispatch != NULL)
1256 dns_dispatch_detach(&query->dispatch);
1260 isc_mem_put(res->buckets[fctx->bucketnum].mctx,
1261 query, sizeof(*query));
1264 RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
1269 static isc_boolean_t
1270 triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1273 for (sa = ISC_LIST_HEAD(fctx->edns);
1275 sa = ISC_LIST_NEXT(sa, link)) {
1276 if (isc_sockaddr_equal(sa, address))
1284 add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
1287 if (triededns(fctx, address))
1290 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
1296 ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
1299 static isc_boolean_t
1300 triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1303 for (sa = ISC_LIST_HEAD(fctx->edns512);
1305 sa = ISC_LIST_NEXT(sa, link)) {
1306 if (isc_sockaddr_equal(sa, address))
1314 add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
1317 if (triededns512(fctx, address))
1320 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
1326 ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
1330 resquery_send(resquery_t *query) {
1332 isc_result_t result;
1333 dns_name_t *qname = NULL;
1334 dns_rdataset_t *qrdataset = NULL;
1336 dns_resolver_t *res;
1338 isc_socket_t *socket;
1339 isc_buffer_t tcpbuffer;
1340 isc_sockaddr_t *address;
1341 isc_buffer_t *buffer;
1342 isc_netaddr_t ipaddr;
1343 dns_tsigkey_t *tsigkey = NULL;
1344 dns_peer_t *peer = NULL;
1345 isc_boolean_t useedns;
1346 dns_compress_t cctx;
1347 isc_boolean_t cleanup_cctx = ISC_FALSE;
1348 isc_boolean_t secure_domain;
1354 task = res->buckets[fctx->bucketnum].task;
1357 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1359 * Reserve space for the TCP message length.
1361 isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
1362 isc_buffer_init(&query->buffer, query->data + 2,
1363 sizeof(query->data) - 2);
1364 buffer = &tcpbuffer;
1366 isc_buffer_init(&query->buffer, query->data,
1367 sizeof(query->data));
1368 buffer = &query->buffer;
1371 result = dns_message_gettempname(fctx->qmessage, &qname);
1372 if (result != ISC_R_SUCCESS)
1374 result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
1375 if (result != ISC_R_SUCCESS)
1379 * Get a query id from the dispatch.
1381 result = dns_dispatch_addresponse(query->dispatch,
1382 &query->addrinfo->sockaddr,
1388 if (result != ISC_R_SUCCESS)
1391 fctx->qmessage->opcode = dns_opcode_query;
1396 dns_name_init(qname, NULL);
1397 dns_name_clone(&fctx->name, qname);
1398 dns_rdataset_init(qrdataset);
1399 dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
1400 ISC_LIST_APPEND(qname->list, qrdataset, link);
1401 dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
1406 * Set RD if the client has requested that we do a recursive query,
1407 * or if we're sending to a forwarder.
1409 if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
1410 ISFORWARDER(query->addrinfo))
1411 fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
1414 * Set CD if the client says don't validate or the question is
1415 * under a secure entry point.
1417 if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
1418 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1419 } else if (res->view->enablevalidation) {
1420 result = dns_keytable_issecuredomain(res->view->secroots,
1423 if (result != ISC_R_SUCCESS)
1424 secure_domain = ISC_FALSE;
1425 if (res->view->dlv != NULL)
1426 secure_domain = ISC_TRUE;
1428 fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
1432 * We don't have to set opcode because it defaults to query.
1434 fctx->qmessage->id = query->id;
1437 * Convert the question to wire format.
1439 result = dns_compress_init(&cctx, -1, fctx->res->mctx);
1440 if (result != ISC_R_SUCCESS)
1441 goto cleanup_message;
1442 cleanup_cctx = ISC_TRUE;
1444 result = dns_message_renderbegin(fctx->qmessage, &cctx,
1446 if (result != ISC_R_SUCCESS)
1447 goto cleanup_message;
1449 result = dns_message_rendersection(fctx->qmessage,
1450 DNS_SECTION_QUESTION, 0);
1451 if (result != ISC_R_SUCCESS)
1452 goto cleanup_message;
1455 isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
1456 (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
1459 * The ADB does not know about servers with "edns no". Check this,
1460 * and then inform the ADB for future use.
1462 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
1464 dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
1467 query->options |= DNS_FETCHOPT_NOEDNS0;
1468 dns_adb_changeflags(fctx->adb,
1470 DNS_FETCHOPT_NOEDNS0,
1471 DNS_FETCHOPT_NOEDNS0);
1475 * Use EDNS0, unless the caller doesn't want it, or we know that
1476 * the remote server doesn't like it.
1479 if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
1480 fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
1481 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1482 query->options |= DNS_FETCHOPT_NOEDNS0;
1483 FCTXTRACE("too many timeouts, disabling EDNS0");
1484 } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
1485 fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
1486 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1487 query->options |= DNS_FETCHOPT_EDNS512;
1488 FCTXTRACE("too many timeouts, setting EDNS size to 512");
1491 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
1492 if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
1493 unsigned int version = 0; /* Default version. */
1495 isc_uint16_t udpsize = res->udpsize;
1497 flags = query->addrinfo->flags;
1498 if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
1499 version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
1500 version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
1502 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1504 else if (peer != NULL)
1505 (void)dns_peer_getudpsize(peer, &udpsize);
1506 result = fctx_addopt(fctx->qmessage, version, udpsize);
1507 if (result != ISC_R_SUCCESS) {
1509 * We couldn't add the OPT, but we'll press on.
1510 * We're not using EDNS0, so set the NOEDNS0
1513 query->options |= DNS_FETCHOPT_NOEDNS0;
1517 * We know this server doesn't like EDNS0, so we
1518 * won't use it. Set the NOEDNS0 bit since we're
1521 query->options |= DNS_FETCHOPT_NOEDNS0;
1526 * If we need EDNS0 to do this query and aren't using it, we lose.
1528 if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
1529 result = DNS_R_SERVFAIL;
1530 goto cleanup_message;
1533 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
1534 add_triededns(fctx, &query->addrinfo->sockaddr);
1536 if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
1537 add_triededns512(fctx, &query->addrinfo->sockaddr);
1540 * Clear CD if EDNS is not in use.
1542 if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
1543 fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
1546 * Add TSIG record tailored to the current recipient.
1548 result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
1549 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1550 goto cleanup_message;
1552 if (tsigkey != NULL) {
1553 result = dns_message_settsigkey(fctx->qmessage, tsigkey);
1554 dns_tsigkey_detach(&tsigkey);
1555 if (result != ISC_R_SUCCESS)
1556 goto cleanup_message;
1559 result = dns_message_rendersection(fctx->qmessage,
1560 DNS_SECTION_ADDITIONAL, 0);
1561 if (result != ISC_R_SUCCESS)
1562 goto cleanup_message;
1564 result = dns_message_renderend(fctx->qmessage);
1565 if (result != ISC_R_SUCCESS)
1566 goto cleanup_message;
1568 dns_compress_invalidate(&cctx);
1569 cleanup_cctx = ISC_FALSE;
1571 if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
1572 dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
1574 result = dns_message_getquerytsig(fctx->qmessage,
1577 if (result != ISC_R_SUCCESS)
1578 goto cleanup_message;
1582 * If using TCP, write the length of the message at the beginning
1585 if ((query->options & DNS_FETCHOPT_TCP) != 0) {
1586 isc_buffer_usedregion(&query->buffer, &r);
1587 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
1588 isc_buffer_add(&tcpbuffer, r.length);
1592 * We're now done with the query message.
1594 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1596 socket = dns_dispatch_getsocket(query->dispatch);
1600 if ((query->options & DNS_FETCHOPT_TCP) == 0)
1601 address = &query->addrinfo->sockaddr;
1602 isc_buffer_usedregion(buffer, &r);
1605 * XXXRTH Make sure we don't send to ourselves! We should probably
1606 * prune out these addresses when we get them from the ADB.
1608 result = isc_socket_sendto(socket, &r, task, resquery_senddone,
1609 query, address, NULL);
1610 if (result != ISC_R_SUCCESS)
1611 goto cleanup_message;
1615 return (ISC_R_SUCCESS);
1619 dns_compress_invalidate(&cctx);
1621 dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
1624 * Stop the dispatcher from listening.
1626 dns_dispatch_removeresponse(&query->dispentry, NULL);
1630 dns_message_puttempname(fctx->qmessage, &qname);
1631 if (qrdataset != NULL)
1632 dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
1638 resquery_connected(isc_task_t *task, isc_event_t *event) {
1639 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1640 resquery_t *query = event->ev_arg;
1641 isc_boolean_t retry = ISC_FALSE;
1642 isc_result_t result;
1646 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1647 REQUIRE(VALID_QUERY(query));
1649 QTRACE("connected");
1656 * Currently we don't wait for the connect event before retrying
1657 * a query. This means that if we get really behind, we may end
1658 * up doing extra work!
1664 if (RESQUERY_CANCELED(query)) {
1666 * This query was canceled while the connect() was in
1669 isc_socket_detach(&query->tcpsocket);
1670 resquery_destroy(&query);
1672 switch (sevent->result) {
1675 * We are connected. Create a dispatcher and
1679 attrs |= DNS_DISPATCHATTR_TCP;
1680 attrs |= DNS_DISPATCHATTR_PRIVATE;
1681 attrs |= DNS_DISPATCHATTR_CONNECTED;
1682 if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
1684 attrs |= DNS_DISPATCHATTR_IPV4;
1686 attrs |= DNS_DISPATCHATTR_IPV6;
1687 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
1689 result = dns_dispatch_createtcp(query->dispatchmgr,
1691 query->fctx->res->taskmgr,
1692 4096, 2, 1, 1, 3, attrs,
1696 * Regardless of whether dns_dispatch_create()
1697 * succeeded or not, we don't need our reference
1698 * to the socket anymore.
1700 isc_socket_detach(&query->tcpsocket);
1702 if (result == ISC_R_SUCCESS)
1703 result = resquery_send(query);
1705 if (result != ISC_R_SUCCESS) {
1706 fctx_cancelquery(&query, NULL, NULL,
1708 fctx_done(fctx, result);
1712 case ISC_R_NETUNREACH:
1713 case ISC_R_HOSTUNREACH:
1714 case ISC_R_CONNREFUSED:
1716 case ISC_R_ADDRNOTAVAIL:
1717 case ISC_R_CONNECTIONRESET:
1719 * No route to remote.
1721 isc_socket_detach(&query->tcpsocket);
1722 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
1727 isc_socket_detach(&query->tcpsocket);
1728 fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
1733 isc_event_free(&event);
1737 * Behave as if the idle timer has expired. For TCP
1738 * connections this may not actually reflect the latest timer.
1740 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1741 result = fctx_stopidletimer(fctx);
1742 if (result != ISC_R_SUCCESS)
1743 fctx_done(fctx, result);
1750 fctx_finddone(isc_task_t *task, isc_event_t *event) {
1752 dns_adbfind_t *find;
1753 dns_resolver_t *res;
1754 isc_boolean_t want_try = ISC_FALSE;
1755 isc_boolean_t want_done = ISC_FALSE;
1756 isc_boolean_t bucket_empty = ISC_FALSE;
1757 unsigned int bucketnum;
1759 find = event->ev_sender;
1760 fctx = event->ev_arg;
1761 REQUIRE(VALID_FCTX(fctx));
1766 FCTXTRACE("finddone");
1768 INSIST(fctx->pending > 0);
1771 if (ADDRWAIT(fctx)) {
1773 * The fetch is waiting for a name to be found.
1775 INSIST(!SHUTTINGDOWN(fctx));
1776 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
1777 if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
1778 want_try = ISC_TRUE;
1779 else if (fctx->pending == 0) {
1781 * We've got nothing else to wait for and don't
1782 * know the answer. There's nothing to do but
1785 want_done = ISC_TRUE;
1787 } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
1788 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
1789 bucketnum = fctx->bucketnum;
1790 LOCK(&res->buckets[bucketnum].lock);
1792 * Note that we had to wait until we had the lock before
1793 * looking at fctx->references.
1795 if (fctx->references == 0)
1796 bucket_empty = fctx_destroy(fctx);
1797 UNLOCK(&res->buckets[bucketnum].lock);
1800 isc_event_free(&event);
1801 dns_adb_destroyfind(&find);
1806 fctx_done(fctx, ISC_R_FAILURE);
1807 else if (bucket_empty)
1812 static inline isc_boolean_t
1813 bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
1816 for (sa = ISC_LIST_HEAD(fctx->bad);
1818 sa = ISC_LIST_NEXT(sa, link)) {
1819 if (isc_sockaddr_equal(sa, address))
1826 static inline isc_boolean_t
1827 mark_bad(fetchctx_t *fctx) {
1828 dns_adbfind_t *curr;
1829 dns_adbaddrinfo_t *addrinfo;
1830 isc_boolean_t all_bad = ISC_TRUE;
1833 * Mark all known bad servers, so we don't try to talk to them
1838 * Mark any bad nameservers.
1840 for (curr = ISC_LIST_HEAD(fctx->finds);
1842 curr = ISC_LIST_NEXT(curr, publink)) {
1843 for (addrinfo = ISC_LIST_HEAD(curr->list);
1845 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1846 if (bad_server(fctx, &addrinfo->sockaddr))
1847 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1849 all_bad = ISC_FALSE;
1854 * Mark any bad forwarders.
1856 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
1858 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1859 if (bad_server(fctx, &addrinfo->sockaddr))
1860 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1862 all_bad = ISC_FALSE;
1866 * Mark any bad alternates.
1868 for (curr = ISC_LIST_HEAD(fctx->altfinds);
1870 curr = ISC_LIST_NEXT(curr, publink)) {
1871 for (addrinfo = ISC_LIST_HEAD(curr->list);
1873 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1874 if (bad_server(fctx, &addrinfo->sockaddr))
1875 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1877 all_bad = ISC_FALSE;
1881 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
1883 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
1884 if (bad_server(fctx, &addrinfo->sockaddr))
1885 addrinfo->flags |= FCTX_ADDRINFO_MARK;
1887 all_bad = ISC_FALSE;
1894 add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
1895 char namebuf[DNS_NAME_FORMATSIZE];
1896 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
1902 const char *sep1, *sep2;
1903 isc_sockaddr_t *address = &addrinfo->sockaddr;
1905 if (bad_server(fctx, address)) {
1907 * We already know this server is bad.
1912 FCTXTRACE("add_bad");
1914 sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
1919 ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
1921 if (reason == DNS_R_LAME) /* already logged */
1924 if (reason == DNS_R_UNEXPECTEDRCODE &&
1925 fctx->rmessage->opcode == dns_rcode_servfail &&
1926 ISFORWARDER(addrinfo))
1929 if (reason == DNS_R_UNEXPECTEDRCODE) {
1930 isc_buffer_init(&b, code, sizeof(code) - 1);
1931 dns_rcode_totext(fctx->rmessage->rcode, &b);
1932 code[isc_buffer_usedlength(&b)] = '\0';
1935 } else if (reason == DNS_R_UNEXPECTEDOPCODE) {
1936 isc_buffer_init(&b, code, sizeof(code) - 1);
1937 dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
1938 code[isc_buffer_usedlength(&b)] = '\0';
1946 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
1947 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
1948 dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
1949 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
1950 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
1951 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
1952 "%s %s%s%sresolving '%s/%s/%s': %s",
1953 dns_result_totext(reason), sep1, code, sep2,
1954 namebuf, typebuf, classbuf, addrbuf);
1958 sort_adbfind(dns_adbfind_t *find) {
1959 dns_adbaddrinfo_t *best, *curr;
1960 dns_adbaddrinfolist_t sorted;
1963 * Lame N^2 bubble sort.
1966 ISC_LIST_INIT(sorted);
1967 while (!ISC_LIST_EMPTY(find->list)) {
1968 best = ISC_LIST_HEAD(find->list);
1969 curr = ISC_LIST_NEXT(best, publink);
1970 while (curr != NULL) {
1971 if (curr->srtt < best->srtt)
1973 curr = ISC_LIST_NEXT(curr, publink);
1975 ISC_LIST_UNLINK(find->list, best, publink);
1976 ISC_LIST_APPEND(sorted, best, publink);
1978 find->list = sorted;
1982 sort_finds(fetchctx_t *fctx) {
1983 dns_adbfind_t *best, *curr;
1984 dns_adbfindlist_t sorted;
1985 dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
1988 * Lame N^2 bubble sort.
1991 ISC_LIST_INIT(sorted);
1992 while (!ISC_LIST_EMPTY(fctx->finds)) {
1993 best = ISC_LIST_HEAD(fctx->finds);
1994 bestaddrinfo = ISC_LIST_HEAD(best->list);
1995 INSIST(bestaddrinfo != NULL);
1996 curr = ISC_LIST_NEXT(best, publink);
1997 while (curr != NULL) {
1998 addrinfo = ISC_LIST_HEAD(curr->list);
1999 INSIST(addrinfo != NULL);
2000 if (addrinfo->srtt < bestaddrinfo->srtt) {
2002 bestaddrinfo = addrinfo;
2004 curr = ISC_LIST_NEXT(curr, publink);
2006 ISC_LIST_UNLINK(fctx->finds, best, publink);
2007 ISC_LIST_APPEND(sorted, best, publink);
2009 fctx->finds = sorted;
2011 ISC_LIST_INIT(sorted);
2012 while (!ISC_LIST_EMPTY(fctx->altfinds)) {
2013 best = ISC_LIST_HEAD(fctx->altfinds);
2014 bestaddrinfo = ISC_LIST_HEAD(best->list);
2015 INSIST(bestaddrinfo != NULL);
2016 curr = ISC_LIST_NEXT(best, publink);
2017 while (curr != NULL) {
2018 addrinfo = ISC_LIST_HEAD(curr->list);
2019 INSIST(addrinfo != NULL);
2020 if (addrinfo->srtt < bestaddrinfo->srtt) {
2022 bestaddrinfo = addrinfo;
2024 curr = ISC_LIST_NEXT(curr, publink);
2026 ISC_LIST_UNLINK(fctx->altfinds, best, publink);
2027 ISC_LIST_APPEND(sorted, best, publink);
2029 fctx->altfinds = sorted;
2033 findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
2034 unsigned int options, unsigned int flags, isc_stdtime_t now,
2035 isc_boolean_t *need_alternate)
2037 dns_adbaddrinfo_t *ai;
2038 dns_adbfind_t *find;
2039 dns_resolver_t *res;
2040 isc_boolean_t unshared;
2041 isc_result_t result;
2044 unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
2046 * If this name is a subdomain of the query domain, tell
2047 * the ADB to start looking using zone/hint data. This keeps us
2048 * from getting stuck if the nameserver is beneath the zone cut
2049 * and we don't know its address (e.g. because the A record has
2052 if (dns_name_issubdomain(name, &fctx->domain))
2053 options |= DNS_ADBFIND_STARTATZONE;
2054 options |= DNS_ADBFIND_GLUEOK;
2055 options |= DNS_ADBFIND_HINTOK;
2058 * See what we know about this address.
2061 result = dns_adb_createfind(fctx->adb,
2062 res->buckets[fctx->bucketnum].task,
2063 fctx_finddone, fctx, name,
2064 &fctx->name, fctx->type,
2066 res->view->dstport, &find);
2067 if (result != ISC_R_SUCCESS) {
2068 if (result == DNS_R_ALIAS) {
2070 * XXXRTH Follow the CNAME/DNAME chain?
2072 dns_adb_destroyfind(&find);
2074 } else if (!ISC_LIST_EMPTY(find->list)) {
2076 * We have at least some of the addresses for the
2079 INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
2081 if (flags != 0 || port != 0) {
2082 for (ai = ISC_LIST_HEAD(find->list);
2084 ai = ISC_LIST_NEXT(ai, publink)) {
2087 isc_sockaddr_setport(&ai->sockaddr,
2091 if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
2092 ISC_LIST_APPEND(fctx->altfinds, find, publink);
2094 ISC_LIST_APPEND(fctx->finds, find, publink);
2097 * We don't know any of the addresses for this
2100 if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
2102 * We're looking for them and will get an
2103 * event about it later.
2109 if (need_alternate != NULL &&
2110 !*need_alternate && unshared &&
2111 ((res->dispatchv4 == NULL &&
2112 find->result_v6 != DNS_R_NXDOMAIN) ||
2113 (res->dispatchv6 == NULL &&
2114 find->result_v4 != DNS_R_NXDOMAIN)))
2115 *need_alternate = ISC_TRUE;
2118 * If we know there are no addresses for
2119 * the family we are using then try to add
2120 * an alternative server.
2122 if (need_alternate != NULL && !*need_alternate &&
2123 ((res->dispatchv4 == NULL &&
2124 find->result_v6 == DNS_R_NXRRSET) ||
2125 (res->dispatchv6 == NULL &&
2126 find->result_v4 == DNS_R_NXRRSET)))
2127 *need_alternate = ISC_TRUE;
2128 dns_adb_destroyfind(&find);
2134 fctx_getaddresses(fetchctx_t *fctx) {
2135 dns_rdata_t rdata = DNS_RDATA_INIT;
2136 isc_result_t result;
2137 dns_resolver_t *res;
2139 unsigned int stdoptions;
2141 dns_adbaddrinfo_t *ai;
2142 isc_boolean_t all_bad;
2144 isc_boolean_t need_alternate = ISC_FALSE;
2146 FCTXTRACE("getaddresses");
2149 * Don't pound on remote servers. (Failsafe!)
2152 if (fctx->restarts > 10) {
2153 FCTXTRACE("too many restarts");
2154 return (DNS_R_SERVFAIL);
2158 stdoptions = 0; /* Keep compiler happy. */
2164 INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
2165 INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
2168 * If this fctx has forwarders, use them; otherwise use any
2169 * selective forwarders specified in the view; otherwise use the
2170 * resolver's forwarders (if any).
2172 sa = ISC_LIST_HEAD(fctx->forwarders);
2174 dns_forwarders_t *forwarders = NULL;
2175 dns_name_t *name = &fctx->name;
2177 unsigned int labels;
2180 * DS records are found in the parent server.
2181 * Strip label to get the correct forwarder (if any).
2183 if (fctx->type == dns_rdatatype_ds &&
2184 dns_name_countlabels(name) > 1) {
2185 dns_name_init(&suffix, NULL);
2186 labels = dns_name_countlabels(name);
2187 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
2190 result = dns_fwdtable_find(fctx->res->view->fwdtable, name,
2192 if (result == ISC_R_SUCCESS) {
2193 sa = ISC_LIST_HEAD(forwarders->addrs);
2194 fctx->fwdpolicy = forwarders->fwdpolicy;
2198 while (sa != NULL) {
2200 result = dns_adb_findaddrinfo(fctx->adb,
2201 sa, &ai, 0); /* XXXMLG */
2202 if (result == ISC_R_SUCCESS) {
2203 dns_adbaddrinfo_t *cur;
2204 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2205 cur = ISC_LIST_HEAD(fctx->forwaddrs);
2206 while (cur != NULL && cur->srtt < ai->srtt)
2207 cur = ISC_LIST_NEXT(cur, publink);
2209 ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
2212 ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
2214 sa = ISC_LIST_NEXT(sa, link);
2218 * If the forwarding policy is "only", we don't need the addresses
2219 * of the nameservers.
2221 if (fctx->fwdpolicy == dns_fwdpolicy_only)
2225 * Normal nameservers.
2228 stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
2229 if (fctx->restarts == 1) {
2231 * To avoid sending out a flood of queries likely to
2232 * result in NXRRSET, we suppress fetches for address
2233 * families we don't have the first time through,
2234 * provided that we have addresses in some family we
2237 * We don't want to set this option all the time, since
2238 * if fctx->restarts > 1, we've clearly been having trouble
2239 * with the addresses we had, so getting more could help.
2241 stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
2243 if (res->dispatchv4 != NULL)
2244 stdoptions |= DNS_ADBFIND_INET;
2245 if (res->dispatchv6 != NULL)
2246 stdoptions |= DNS_ADBFIND_INET6;
2247 isc_stdtime_get(&now);
2249 INSIST(ISC_LIST_EMPTY(fctx->finds));
2250 INSIST(ISC_LIST_EMPTY(fctx->altfinds));
2252 for (result = dns_rdataset_first(&fctx->nameservers);
2253 result == ISC_R_SUCCESS;
2254 result = dns_rdataset_next(&fctx->nameservers))
2256 dns_rdataset_current(&fctx->nameservers, &rdata);
2258 * Extract the name from the NS record.
2260 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2261 if (result != ISC_R_SUCCESS)
2264 findname(fctx, &ns.name, 0, stdoptions, 0, now,
2266 dns_rdata_reset(&rdata);
2267 dns_rdata_freestruct(&ns);
2269 if (result != ISC_R_NOMORE)
2273 * Do we need to use 6 to 4?
2275 if (need_alternate) {
2278 family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
2279 for (a = ISC_LIST_HEAD(fctx->res->alternates);
2281 a = ISC_LIST_NEXT(a, link)) {
2282 if (!a->isaddress) {
2283 findname(fctx, &a->_u._n.name, a->_u._n.port,
2284 stdoptions, FCTX_ADDRINFO_FORWARDER,
2288 if (isc_sockaddr_pf(&a->_u.addr) != family)
2291 result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
2293 if (result == ISC_R_SUCCESS) {
2294 dns_adbaddrinfo_t *cur;
2295 ai->flags |= FCTX_ADDRINFO_FORWARDER;
2296 cur = ISC_LIST_HEAD(fctx->altaddrs);
2297 while (cur != NULL && cur->srtt < ai->srtt)
2298 cur = ISC_LIST_NEXT(cur, publink);
2300 ISC_LIST_INSERTBEFORE(fctx->altaddrs,
2303 ISC_LIST_APPEND(fctx->altaddrs, ai,
2311 * Mark all known bad servers.
2313 all_bad = mark_bad(fctx);
2320 * We've got no addresses.
2322 if (fctx->pending > 0) {
2324 * We're fetching the addresses, but don't have any
2325 * yet. Tell the caller to wait for an answer.
2327 result = DNS_R_WAIT;
2330 * We've lost completely. We don't know any
2331 * addresses, and the ADB has told us it can't get
2334 FCTXTRACE("no addresses");
2335 result = ISC_R_FAILURE;
2339 * We've found some addresses. We might still be looking
2340 * for more addresses.
2343 result = ISC_R_SUCCESS;
2350 possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
2353 char buf[ISC_NETADDR_FORMATSIZE];
2355 isc_boolean_t aborted = ISC_FALSE;
2356 isc_boolean_t bogus;
2357 dns_acl_t *blackhole;
2358 isc_netaddr_t ipaddr;
2359 dns_peer_t *peer = NULL;
2360 dns_resolver_t *res;
2361 const char *msg = NULL;
2363 sa = &addr->sockaddr;
2366 isc_netaddr_fromsockaddr(&ipaddr, sa);
2367 blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
2368 (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
2370 if (blackhole != NULL) {
2373 if (dns_acl_match(&ipaddr, NULL, blackhole,
2375 &match, NULL) == ISC_R_SUCCESS &&
2381 dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
2386 addr->flags |= FCTX_ADDRINFO_MARK;
2387 msg = "ignoring blackholed / bogus server: ";
2388 } else if (isc_sockaddr_ismulticast(sa)) {
2389 addr->flags |= FCTX_ADDRINFO_MARK;
2390 msg = "ignoring multicast address: ";
2391 } else if (isc_sockaddr_isexperimental(sa)) {
2392 addr->flags |= FCTX_ADDRINFO_MARK;
2393 msg = "ignoring experimental address: ";
2394 } else if (sa->type.sa.sa_family != AF_INET6) {
2396 } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
2397 addr->flags |= FCTX_ADDRINFO_MARK;
2398 msg = "ignoring IPv6 mapped IPV4 address: ";
2399 } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
2400 addr->flags |= FCTX_ADDRINFO_MARK;
2401 msg = "ignoring IPv6 compatibility IPV4 address: ";
2405 if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
2408 isc_netaddr_fromsockaddr(&na, sa);
2409 isc_netaddr_format(&na, buf, sizeof(buf));
2410 FCTXTRACE2(msg, buf);
2413 static inline dns_adbaddrinfo_t *
2414 fctx_nextaddress(fetchctx_t *fctx) {
2415 dns_adbfind_t *find, *start;
2416 dns_adbaddrinfo_t *addrinfo;
2417 dns_adbaddrinfo_t *faddrinfo;
2420 * Return the next untried address, if any.
2424 * Find the first unmarked forwarder (if any).
2426 for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
2428 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2429 if (!UNMARKED(addrinfo))
2431 possibly_mark(fctx, addrinfo);
2432 if (UNMARKED(addrinfo)) {
2433 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2440 * No forwarders. Move to the next find.
2443 fctx->attributes |= FCTX_ATTR_TRIEDFIND;
2447 find = ISC_LIST_HEAD(fctx->finds);
2449 find = ISC_LIST_NEXT(find, publink);
2451 find = ISC_LIST_HEAD(fctx->finds);
2455 * Find the first unmarked addrinfo.
2461 for (addrinfo = ISC_LIST_HEAD(find->list);
2463 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2464 if (!UNMARKED(addrinfo))
2466 possibly_mark(fctx, addrinfo);
2467 if (UNMARKED(addrinfo)) {
2468 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2472 if (addrinfo != NULL)
2474 find = ISC_LIST_NEXT(find, publink);
2476 find = ISC_LIST_HEAD(fctx->finds);
2477 } while (find != start);
2481 if (addrinfo != NULL)
2485 * No nameservers left. Try alternates.
2488 fctx->attributes |= FCTX_ATTR_TRIEDALT;
2490 find = fctx->altfind;
2492 find = ISC_LIST_HEAD(fctx->altfinds);
2494 find = ISC_LIST_NEXT(find, publink);
2496 find = ISC_LIST_HEAD(fctx->altfinds);
2500 * Find the first unmarked addrinfo.
2506 for (addrinfo = ISC_LIST_HEAD(find->list);
2508 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2509 if (!UNMARKED(addrinfo))
2511 possibly_mark(fctx, addrinfo);
2512 if (UNMARKED(addrinfo)) {
2513 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2517 if (addrinfo != NULL)
2519 find = ISC_LIST_NEXT(find, publink);
2521 find = ISC_LIST_HEAD(fctx->altfinds);
2522 } while (find != start);
2525 faddrinfo = addrinfo;
2528 * See if we have a better alternate server by address.
2531 for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
2533 addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
2534 if (!UNMARKED(addrinfo))
2536 possibly_mark(fctx, addrinfo);
2537 if (UNMARKED(addrinfo) &&
2538 (faddrinfo == NULL ||
2539 addrinfo->srtt < faddrinfo->srtt)) {
2540 if (faddrinfo != NULL)
2541 faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
2542 addrinfo->flags |= FCTX_ADDRINFO_MARK;
2547 if (addrinfo == NULL) {
2548 addrinfo = faddrinfo;
2549 fctx->altfind = find;
2556 fctx_try(fetchctx_t *fctx) {
2557 isc_result_t result;
2558 dns_adbaddrinfo_t *addrinfo;
2562 REQUIRE(!ADDRWAIT(fctx));
2564 addrinfo = fctx_nextaddress(fctx);
2565 if (addrinfo == NULL) {
2567 * We have no more addresses. Start over.
2569 fctx_cancelqueries(fctx, ISC_TRUE);
2570 fctx_cleanupfinds(fctx);
2571 fctx_cleanupaltfinds(fctx);
2572 fctx_cleanupforwaddrs(fctx);
2573 fctx_cleanupaltaddrs(fctx);
2574 result = fctx_getaddresses(fctx);
2575 if (result == DNS_R_WAIT) {
2577 * Sleep waiting for addresses.
2579 FCTXTRACE("addrwait");
2580 fctx->attributes |= FCTX_ATTR_ADDRWAIT;
2582 } else if (result != ISC_R_SUCCESS) {
2584 * Something bad happened.
2586 fctx_done(fctx, result);
2590 addrinfo = fctx_nextaddress(fctx);
2592 * While we may have addresses from the ADB, they
2593 * might be bad ones. In this case, return SERVFAIL.
2595 if (addrinfo == NULL) {
2596 fctx_done(fctx, DNS_R_SERVFAIL);
2601 result = fctx_query(fctx, addrinfo, fctx->options);
2602 if (result != ISC_R_SUCCESS)
2603 fctx_done(fctx, result);
2606 static isc_boolean_t
2607 fctx_destroy(fetchctx_t *fctx) {
2608 dns_resolver_t *res;
2609 unsigned int bucketnum;
2610 isc_sockaddr_t *sa, *next_sa;
2613 * Caller must be holding the bucket lock.
2616 REQUIRE(VALID_FCTX(fctx));
2617 REQUIRE(fctx->state == fetchstate_done ||
2618 fctx->state == fetchstate_init);
2619 REQUIRE(ISC_LIST_EMPTY(fctx->events));
2620 REQUIRE(ISC_LIST_EMPTY(fctx->queries));
2621 REQUIRE(ISC_LIST_EMPTY(fctx->finds));
2622 REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
2623 REQUIRE(fctx->pending == 0);
2624 REQUIRE(fctx->references == 0);
2625 REQUIRE(ISC_LIST_EMPTY(fctx->validators));
2627 FCTXTRACE("destroy");
2630 bucketnum = fctx->bucketnum;
2632 ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
2637 for (sa = ISC_LIST_HEAD(fctx->bad);
2640 next_sa = ISC_LIST_NEXT(sa, link);
2641 ISC_LIST_UNLINK(fctx->bad, sa, link);
2642 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
2645 for (sa = ISC_LIST_HEAD(fctx->edns);
2648 next_sa = ISC_LIST_NEXT(sa, link);
2649 ISC_LIST_UNLINK(fctx->edns, sa, link);
2650 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
2653 for (sa = ISC_LIST_HEAD(fctx->edns512);
2656 next_sa = ISC_LIST_NEXT(sa, link);
2657 ISC_LIST_UNLINK(fctx->edns512, sa, link);
2658 isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
2661 isc_timer_detach(&fctx->timer);
2662 dns_message_destroy(&fctx->rmessage);
2663 dns_message_destroy(&fctx->qmessage);
2664 if (dns_name_countlabels(&fctx->domain) > 0)
2665 dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
2666 if (dns_rdataset_isassociated(&fctx->nameservers))
2667 dns_rdataset_disassociate(&fctx->nameservers);
2668 dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
2669 dns_db_detach(&fctx->cache);
2670 dns_adb_detach(&fctx->adb);
2671 isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
2672 isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
2676 UNLOCK(&res->nlock);
2678 if (res->buckets[bucketnum].exiting &&
2679 ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
2686 * Fetch event handlers.
2690 fctx_timeout(isc_task_t *task, isc_event_t *event) {
2691 fetchctx_t *fctx = event->ev_arg;
2692 isc_timerevent_t *tevent = (isc_timerevent_t *)event;
2695 REQUIRE(VALID_FCTX(fctx));
2699 FCTXTRACE("timeout");
2701 if (event->ev_type == ISC_TIMEREVENT_LIFE) {
2702 fctx_done(fctx, ISC_R_TIMEDOUT);
2704 isc_result_t result;
2708 * We could cancel the running queries here, or we could let
2709 * them keep going. Since we normally use separate sockets for
2710 * different queries, we adopt the former approach to reduce
2711 * the number of open sockets: cancel the oldest query if it
2712 * expired after the query had started (this is usually the
2713 * case but is not always so, depending on the task schedule
2716 query = ISC_LIST_HEAD(fctx->queries);
2717 if (query != NULL &&
2718 isc_time_compare(&tevent->due, &query->start) >= 0) {
2719 fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
2721 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2723 * Our timer has triggered. Reestablish the fctx lifetime
2726 result = fctx_starttimer(fctx);
2727 if (result != ISC_R_SUCCESS)
2728 fctx_done(fctx, result);
2736 isc_event_free(&event);
2740 fctx_shutdown(fetchctx_t *fctx) {
2741 isc_event_t *cevent;
2744 * Start the shutdown process for fctx, if it isn't already underway.
2747 FCTXTRACE("shutdown");
2750 * The caller must be holding the appropriate bucket lock.
2753 if (fctx->want_shutdown)
2756 fctx->want_shutdown = ISC_TRUE;
2759 * Unless we're still initializing (in which case the
2760 * control event is still outstanding), we need to post
2761 * the control event to tell the fetch we want it to
2764 if (fctx->state != fetchstate_init) {
2765 cevent = &fctx->control_event;
2766 isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
2772 fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
2773 fetchctx_t *fctx = event->ev_arg;
2774 isc_boolean_t bucket_empty = ISC_FALSE;
2775 dns_resolver_t *res;
2776 unsigned int bucketnum;
2777 dns_validator_t *validator;
2779 REQUIRE(VALID_FCTX(fctx));
2784 bucketnum = fctx->bucketnum;
2786 FCTXTRACE("doshutdown");
2789 * An fctx that is shutting down is no longer in ADDRWAIT mode.
2791 fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
2794 * Cancel all pending validators. Note that this must be done
2795 * without the bucket lock held, since that could cause deadlock.
2797 validator = ISC_LIST_HEAD(fctx->validators);
2798 while (validator != NULL) {
2799 dns_validator_cancel(validator);
2800 validator = ISC_LIST_NEXT(validator, link);
2803 if (fctx->nsfetch != NULL)
2804 dns_resolver_cancelfetch(fctx->nsfetch);
2807 * Shut down anything that is still running on behalf of this
2808 * fetch. To avoid deadlock with the ADB, we must do this
2809 * before we lock the bucket lock.
2811 fctx_stopeverything(fctx, ISC_FALSE);
2813 LOCK(&res->buckets[bucketnum].lock);
2815 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2817 INSIST(fctx->state == fetchstate_active ||
2818 fctx->state == fetchstate_done);
2819 INSIST(fctx->want_shutdown);
2821 if (fctx->state != fetchstate_done) {
2822 fctx->state = fetchstate_done;
2823 fctx_sendevents(fctx, ISC_R_CANCELED);
2826 if (fctx->references == 0 && fctx->pending == 0 &&
2827 fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators))
2828 bucket_empty = fctx_destroy(fctx);
2830 UNLOCK(&res->buckets[bucketnum].lock);
2837 fctx_start(isc_task_t *task, isc_event_t *event) {
2838 fetchctx_t *fctx = event->ev_arg;
2839 isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
2840 dns_resolver_t *res;
2841 unsigned int bucketnum;
2843 REQUIRE(VALID_FCTX(fctx));
2848 bucketnum = fctx->bucketnum;
2852 LOCK(&res->buckets[bucketnum].lock);
2854 INSIST(fctx->state == fetchstate_init);
2855 if (fctx->want_shutdown) {
2857 * We haven't started this fctx yet, and we've been requested
2860 fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
2861 fctx->state = fetchstate_done;
2862 fctx_sendevents(fctx, ISC_R_CANCELED);
2864 * Since we haven't started, we INSIST that we have no
2865 * pending ADB finds and no pending validations.
2867 INSIST(fctx->pending == 0);
2868 INSIST(fctx->nqueries == 0);
2869 INSIST(ISC_LIST_EMPTY(fctx->validators));
2870 if (fctx->references == 0) {
2872 * It's now safe to destroy this fctx.
2874 bucket_empty = fctx_destroy(fctx);
2879 * Normal fctx startup.
2881 fctx->state = fetchstate_active;
2883 * Reset the control event for later use in shutting down
2886 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
2887 DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
2891 UNLOCK(&res->buckets[bucketnum].lock);
2894 isc_result_t result;
2897 * All is well. Start working on the fetch.
2899 result = fctx_starttimer(fctx);
2900 if (result != ISC_R_SUCCESS)
2901 fctx_done(fctx, result);
2904 } else if (bucket_empty)
2909 * Fetch Creation, Joining, and Cancelation.
2912 static inline isc_result_t
2913 fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
2914 dns_messageid_t id, isc_taskaction_t action, void *arg,
2915 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
2919 dns_fetchevent_t *event;
2924 * We store the task we're going to send this event to in the
2925 * sender field. We'll make the fetch the sender when we actually
2929 isc_task_attach(task, &clone);
2930 event = (dns_fetchevent_t *)
2931 isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
2932 action, arg, sizeof(*event));
2933 if (event == NULL) {
2934 isc_task_detach(&clone);
2935 return (ISC_R_NOMEMORY);
2937 event->result = DNS_R_SERVFAIL;
2938 event->qtype = fctx->type;
2941 event->rdataset = rdataset;
2942 event->sigrdataset = sigrdataset;
2943 event->fetch = fetch;
2944 event->client = client;
2946 dns_fixedname_init(&event->foundname);
2949 * Make sure that we can store the sigrdataset in the
2950 * first event if it is needed by any of the events.
2952 if (event->sigrdataset != NULL)
2953 ISC_LIST_PREPEND(fctx->events, event, ev_link);
2955 ISC_LIST_APPEND(fctx->events, event, ev_link);
2958 fetch->magic = DNS_FETCH_MAGIC;
2959 fetch->private = fctx;
2961 return (ISC_R_SUCCESS);
2965 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
2966 dns_name_t *domain, dns_rdataset_t *nameservers,
2967 unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
2970 isc_result_t result;
2971 isc_result_t iresult;
2972 isc_interval_t interval;
2973 dns_fixedname_t fixed;
2974 unsigned int findoptions = 0;
2975 char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
2976 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2980 * Caller must be holding the lock for bucket number 'bucketnum'.
2982 REQUIRE(fctxp != NULL && *fctxp == NULL);
2984 fctx = isc_mem_get(res->buckets[bucketnum].mctx, sizeof(*fctx));
2986 return (ISC_R_NOMEMORY);
2987 dns_name_format(name, buf, sizeof(buf));
2988 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2989 strcat(buf, "/"); /* checked */
2990 strcat(buf, typebuf); /* checked */
2991 fctx->info = isc_mem_strdup(res->buckets[bucketnum].mctx, buf);
2992 if (fctx->info == NULL) {
2993 result = ISC_R_NOMEMORY;
2996 FCTXTRACE("create");
2997 dns_name_init(&fctx->name, NULL);
2998 result = dns_name_dup(name, res->buckets[bucketnum].mctx, &fctx->name);
2999 if (result != ISC_R_SUCCESS)
3001 dns_name_init(&fctx->domain, NULL);
3002 dns_rdataset_init(&fctx->nameservers);
3005 fctx->options = options;
3007 * Note! We do not attach to the task. We are relying on the
3008 * resolver to ensure that this task doesn't go away while we are
3012 fctx->references = 0;
3013 fctx->bucketnum = bucketnum;
3014 fctx->state = fetchstate_init;
3015 fctx->want_shutdown = ISC_FALSE;
3016 fctx->cloned = ISC_FALSE;
3017 ISC_LIST_INIT(fctx->queries);
3018 ISC_LIST_INIT(fctx->finds);
3019 ISC_LIST_INIT(fctx->altfinds);
3020 ISC_LIST_INIT(fctx->forwaddrs);
3021 ISC_LIST_INIT(fctx->altaddrs);
3022 ISC_LIST_INIT(fctx->forwarders);
3023 fctx->fwdpolicy = dns_fwdpolicy_none;
3024 ISC_LIST_INIT(fctx->bad);
3025 ISC_LIST_INIT(fctx->edns);
3026 ISC_LIST_INIT(fctx->edns512);
3027 ISC_LIST_INIT(fctx->validators);
3028 fctx->validator = NULL;
3030 fctx->altfind = NULL;
3034 fctx->attributes = 0;
3035 fctx->spilled = ISC_FALSE;
3038 dns_name_init(&fctx->nsname, NULL);
3039 fctx->nsfetch = NULL;
3040 dns_rdataset_init(&fctx->nsrrset);
3042 if (domain == NULL) {
3043 dns_forwarders_t *forwarders = NULL;
3044 unsigned int labels;
3047 * DS records are found in the parent server.
3048 * Strip label to get the correct forwarder (if any).
3050 if (fctx->type == dns_rdatatype_ds &&
3051 dns_name_countlabels(name) > 1) {
3052 dns_name_init(&suffix, NULL);
3053 labels = dns_name_countlabels(name);
3054 dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
3057 dns_fixedname_init(&fixed);
3058 domain = dns_fixedname_name(&fixed);
3059 result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
3060 domain, &forwarders);
3061 if (result == ISC_R_SUCCESS)
3062 fctx->fwdpolicy = forwarders->fwdpolicy;
3064 if (fctx->fwdpolicy != dns_fwdpolicy_only) {
3066 * The caller didn't supply a query domain and
3067 * nameservers, and we're not in forward-only mode,
3068 * so find the best nameservers to use.
3070 if (dns_rdatatype_atparent(type))
3071 findoptions |= DNS_DBFIND_NOEXACT;
3072 result = dns_view_findzonecut(res->view, name, domain,
3073 0, findoptions, ISC_TRUE,
3076 if (result != ISC_R_SUCCESS)
3078 result = dns_name_dup(domain,
3079 res->buckets[bucketnum].mctx,
3081 if (result != ISC_R_SUCCESS) {
3082 dns_rdataset_disassociate(&fctx->nameservers);
3087 * We're in forward-only mode. Set the query domain.
3089 result = dns_name_dup(domain,
3090 res->buckets[bucketnum].mctx,
3092 if (result != ISC_R_SUCCESS)
3096 result = dns_name_dup(domain,
3097 res->buckets[bucketnum].mctx,
3099 if (result != ISC_R_SUCCESS)
3101 dns_rdataset_clone(nameservers, &fctx->nameservers);
3104 INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
3106 fctx->qmessage = NULL;
3107 result = dns_message_create(res->buckets[bucketnum].mctx,
3108 DNS_MESSAGE_INTENTRENDER,
3111 if (result != ISC_R_SUCCESS)
3112 goto cleanup_domain;
3114 fctx->rmessage = NULL;
3115 result = dns_message_create(res->buckets[bucketnum].mctx,
3116 DNS_MESSAGE_INTENTPARSE,
3119 if (result != ISC_R_SUCCESS)
3120 goto cleanup_qmessage;
3123 * Compute an expiration time for the entire fetch.
3125 isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
3126 iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
3127 if (iresult != ISC_R_SUCCESS) {
3128 UNEXPECTED_ERROR(__FILE__, __LINE__,
3129 "isc_time_nowplusinterval: %s",
3130 isc_result_totext(iresult));
3131 result = ISC_R_UNEXPECTED;
3132 goto cleanup_rmessage;
3136 * Default retry interval initialization. We set the interval now
3137 * mostly so it won't be uninitialized. It will be set to the
3138 * correct value before a query is issued.
3140 isc_interval_set(&fctx->interval, 2, 0);
3143 * Create an inactive timer. It will be made active when the fetch
3144 * is actually started.
3147 iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
3149 res->buckets[bucketnum].task, fctx_timeout,
3150 fctx, &fctx->timer);
3151 if (iresult != ISC_R_SUCCESS) {
3152 UNEXPECTED_ERROR(__FILE__, __LINE__,
3153 "isc_timer_create: %s",
3154 isc_result_totext(iresult));
3155 result = ISC_R_UNEXPECTED;
3156 goto cleanup_rmessage;
3160 * Attach to the view's cache and adb.
3163 dns_db_attach(res->view->cachedb, &fctx->cache);
3165 dns_adb_attach(res->view->adb, &fctx->adb);
3167 ISC_LIST_INIT(fctx->events);
3168 ISC_LINK_INIT(fctx, link);
3169 fctx->magic = FCTX_MAGIC;
3171 ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
3175 UNLOCK(&res->nlock);
3179 return (ISC_R_SUCCESS);
3182 dns_message_destroy(&fctx->rmessage);
3185 dns_message_destroy(&fctx->qmessage);
3188 if (dns_name_countlabels(&fctx->domain) > 0)
3189 dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
3190 if (dns_rdataset_isassociated(&fctx->nameservers))
3191 dns_rdataset_disassociate(&fctx->nameservers);
3194 dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
3197 isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
3200 isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
3208 static inline isc_boolean_t
3209 is_lame(fetchctx_t *fctx) {
3210 dns_message_t *message = fctx->rmessage;
3212 dns_rdataset_t *rdataset;
3213 isc_result_t result;
3215 if (message->rcode != dns_rcode_noerror &&
3216 message->rcode != dns_rcode_nxdomain)
3219 if (message->counts[DNS_SECTION_ANSWER] != 0)
3222 if (message->counts[DNS_SECTION_AUTHORITY] == 0)
3225 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
3226 while (result == ISC_R_SUCCESS) {
3228 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
3229 for (rdataset = ISC_LIST_HEAD(name->list);
3231 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3232 dns_namereln_t namereln;
3234 unsigned int labels;
3235 if (rdataset->type != dns_rdatatype_ns)
3237 namereln = dns_name_fullcompare(name, &fctx->domain,
3239 if (namereln == dns_namereln_equal &&
3240 (message->flags & DNS_MESSAGEFLAG_AA) != 0)
3242 if (namereln == dns_namereln_subdomain)
3246 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
3253 log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
3254 char namebuf[DNS_NAME_FORMATSIZE];
3255 char domainbuf[DNS_NAME_FORMATSIZE];
3256 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3258 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
3259 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
3260 isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
3261 isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
3262 DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
3263 "lame server resolving '%s' (in '%s'?): %s",
3264 namebuf, domainbuf, addrbuf);
3267 static inline isc_result_t
3268 same_question(fetchctx_t *fctx) {
3269 isc_result_t result;
3270 dns_message_t *message = fctx->rmessage;
3272 dns_rdataset_t *rdataset;
3275 * Caller must be holding the fctx lock.
3279 * XXXRTH Currently we support only one question.
3281 if (message->counts[DNS_SECTION_QUESTION] != 1)
3282 return (DNS_R_FORMERR);
3284 result = dns_message_firstname(message, DNS_SECTION_QUESTION);
3285 if (result != ISC_R_SUCCESS)
3288 dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
3289 rdataset = ISC_LIST_HEAD(name->list);
3290 INSIST(rdataset != NULL);
3291 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
3292 if (fctx->type != rdataset->type ||
3293 fctx->res->rdclass != rdataset->rdclass ||
3294 !dns_name_equal(&fctx->name, name))
3295 return (DNS_R_FORMERR);
3297 return (ISC_R_SUCCESS);
3301 clone_results(fetchctx_t *fctx) {
3302 dns_fetchevent_t *event, *hevent;
3303 isc_result_t result;
3304 dns_name_t *name, *hname;
3306 FCTXTRACE("clone_results");
3309 * Set up any other events to have the same data as the first
3312 * Caller must be holding the appropriate lock.
3315 fctx->cloned = ISC_TRUE;
3316 hevent = ISC_LIST_HEAD(fctx->events);
3319 hname = dns_fixedname_name(&hevent->foundname);
3320 for (event = ISC_LIST_NEXT(hevent, ev_link);
3322 event = ISC_LIST_NEXT(event, ev_link)) {
3323 name = dns_fixedname_name(&event->foundname);
3324 result = dns_name_copy(hname, name, NULL);
3325 if (result != ISC_R_SUCCESS)
3326 event->result = result;
3328 event->result = hevent->result;
3329 dns_db_attach(hevent->db, &event->db);
3330 dns_db_attachnode(hevent->db, hevent->node, &event->node);
3331 INSIST(hevent->rdataset != NULL);
3332 INSIST(event->rdataset != NULL);
3333 if (dns_rdataset_isassociated(hevent->rdataset))
3334 dns_rdataset_clone(hevent->rdataset, event->rdataset);
3335 INSIST(! (hevent->sigrdataset == NULL &&
3336 event->sigrdataset != NULL));
3337 if (hevent->sigrdataset != NULL &&
3338 dns_rdataset_isassociated(hevent->sigrdataset) &&
3339 event->sigrdataset != NULL)
3340 dns_rdataset_clone(hevent->sigrdataset,
3341 event->sigrdataset);
3345 #define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
3346 #define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
3347 #define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
3348 #define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
3349 #define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
3350 #define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
3351 #define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
3355 * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
3356 * no references and is no longer waiting for any events). If this
3357 * was the last fctx in the resolver, destroy the resolver.
3360 * '*fctx' is shutting down.
3363 maybe_destroy(fetchctx_t *fctx) {
3364 unsigned int bucketnum;
3365 isc_boolean_t bucket_empty = ISC_FALSE;
3366 dns_resolver_t *res = fctx->res;
3367 dns_validator_t *validator, *next_validator;
3369 REQUIRE(SHUTTINGDOWN(fctx));
3371 if (fctx->pending != 0 || fctx->nqueries != 0)
3374 for (validator = ISC_LIST_HEAD(fctx->validators);
3375 validator != NULL; validator = next_validator) {
3376 next_validator = ISC_LIST_NEXT(validator, link);
3377 dns_validator_cancel(validator);
3379 * If this is a active validator wait for the cancel
3380 * to complete before calling dns_validator_destroy().
3382 if (validator == fctx->validator)
3384 ISC_LIST_UNLINK(fctx->validators, validator, link);
3385 dns_validator_destroy(&validator);
3388 bucketnum = fctx->bucketnum;
3389 LOCK(&res->buckets[bucketnum].lock);
3390 if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators))
3391 bucket_empty = fctx_destroy(fctx);
3392 UNLOCK(&res->buckets[bucketnum].lock);
3399 * The validator has finished.
3402 validated(isc_task_t *task, isc_event_t *event) {
3403 isc_result_t result = ISC_R_SUCCESS;
3404 isc_result_t eresult = ISC_R_SUCCESS;
3407 dns_validatorevent_t *vevent;
3408 dns_fetchevent_t *hevent;
3409 dns_rdataset_t *ardataset = NULL;
3410 dns_rdataset_t *asigrdataset = NULL;
3411 dns_dbnode_t *node = NULL;
3412 isc_boolean_t negative;
3413 isc_boolean_t chaining;
3414 isc_boolean_t sentresponse;
3416 dns_dbnode_t *nsnode = NULL;
3418 dns_rdataset_t *rdataset;
3419 dns_rdataset_t *sigrdataset;
3420 dns_valarg_t *valarg;
3421 dns_adbaddrinfo_t *addrinfo;
3423 UNUSED(task); /* for now */
3425 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
3426 valarg = event->ev_arg;
3427 fctx = valarg->fctx;
3428 addrinfo = valarg->addrinfo;
3429 REQUIRE(VALID_FCTX(fctx));
3430 REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
3432 vevent = (dns_validatorevent_t *)event;
3434 FCTXTRACE("received validation completion event");
3436 ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
3437 fctx->validator = NULL;
3440 * Destroy the validator early so that we can
3441 * destroy the fctx if necessary.
3443 dns_validator_destroy(&vevent->validator);
3444 isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
3445 valarg, sizeof(*valarg));
3447 negative = ISC_TF(vevent->rdataset == NULL);
3449 sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
3452 * If shutting down, ignore the results. Check to see if we're
3453 * done waiting for validator completions and ADB pending events; if
3454 * so, destroy the fctx.
3456 if (SHUTTINGDOWN(fctx) && !sentresponse) {
3457 maybe_destroy(fctx); /* Locks bucket. */
3461 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3464 * If chaining, we need to make sure that the right result code is
3465 * returned, and that the rdatasets are bound.
3467 if (vevent->result == ISC_R_SUCCESS &&
3469 vevent->rdataset != NULL &&
3470 CHAINING(vevent->rdataset))
3472 if (vevent->rdataset->type == dns_rdatatype_cname)
3473 eresult = DNS_R_CNAME;
3475 INSIST(vevent->rdataset->type == dns_rdatatype_dname);
3476 eresult = DNS_R_DNAME;
3478 chaining = ISC_TRUE;
3480 chaining = ISC_FALSE;
3483 * Either we're not shutting down, or we are shutting down but want
3484 * to cache the result anyway (if this was a validation started by
3485 * a query with cd set)
3488 hevent = ISC_LIST_HEAD(fctx->events);
3489 if (hevent != NULL) {
3490 if (!negative && !chaining &&
3491 (fctx->type == dns_rdatatype_any ||
3492 fctx->type == dns_rdatatype_rrsig ||
3493 fctx->type == dns_rdatatype_sig)) {
3495 * Don't bind rdatasets; the caller
3496 * will iterate the node.
3499 ardataset = hevent->rdataset;
3500 asigrdataset = hevent->sigrdataset;
3504 if (vevent->result != ISC_R_SUCCESS) {
3505 FCTXTRACE("validation failed");
3506 result = ISC_R_NOTFOUND;
3507 if (vevent->rdataset != NULL)
3508 result = dns_db_findnode(fctx->cache, vevent->name,
3510 if (result == ISC_R_SUCCESS)
3511 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
3513 if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
3514 (void)dns_db_deleterdataset(fctx->cache, node, NULL,
3515 dns_rdatatype_rrsig,
3517 if (result == ISC_R_SUCCESS)
3518 dns_db_detachnode(fctx->cache, &node);
3519 result = vevent->result;
3520 add_bad(fctx, addrinfo, result);
3521 isc_event_free(&event);
3522 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3523 INSIST(fctx->validator == NULL);
3524 fctx->validator = ISC_LIST_HEAD(fctx->validators);
3525 if (fctx->validator != NULL) {
3526 dns_validator_send(fctx->validator);
3527 } else if (sentresponse)
3528 fctx_done(fctx, result); /* Locks bucket. */
3530 fctx_try(fctx); /* Locks bucket. */
3534 isc_stdtime_get(&now);
3537 dns_rdatatype_t covers;
3538 FCTXTRACE("nonexistence validation OK");
3540 if (fctx->rmessage->rcode == dns_rcode_nxdomain)
3541 covers = dns_rdatatype_any;
3543 covers = fctx->type;
3545 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
3547 if (result != ISC_R_SUCCESS)
3548 goto noanswer_response;
3551 * If we are asking for a SOA record set the cache time
3552 * to zero to facilitate locating the containing zone of
3555 ttl = fctx->res->view->maxncachettl;
3556 if (fctx->type == dns_rdatatype_soa &&
3557 covers == dns_rdatatype_any &&
3558 fctx->res->zero_no_soa_ttl)
3561 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
3563 ardataset, &eresult);
3564 if (result != ISC_R_SUCCESS)
3565 goto noanswer_response;
3566 goto answer_response;
3569 FCTXTRACE("validation OK");
3571 if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
3573 result = dns_rdataset_addnoqname(vevent->rdataset,
3574 vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
3575 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3576 INSIST(vevent->sigrdataset != NULL);
3577 vevent->sigrdataset->ttl = vevent->rdataset->ttl;
3581 * The data was already cached as pending data.
3582 * Re-cache it as secure and bind the cached
3583 * rdatasets to the first event on the fetch
3586 result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
3587 if (result != ISC_R_SUCCESS)
3588 goto noanswer_response;
3590 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
3591 vevent->rdataset, 0, ardataset);
3592 if (result != ISC_R_SUCCESS &&
3593 result != DNS_R_UNCHANGED)
3594 goto noanswer_response;
3595 if (ardataset != NULL && ardataset->type == 0) {
3596 if (NXDOMAIN(ardataset))
3597 eresult = DNS_R_NCACHENXDOMAIN;
3599 eresult = DNS_R_NCACHENXRRSET;
3600 } else if (vevent->sigrdataset != NULL) {
3601 result = dns_db_addrdataset(fctx->cache, node, NULL, now,
3602 vevent->sigrdataset, 0,
3604 if (result != ISC_R_SUCCESS &&
3605 result != DNS_R_UNCHANGED)
3606 goto noanswer_response;
3611 * If we only deferred the destroy because we wanted to cache
3612 * the data, destroy now.
3614 dns_db_detachnode(fctx->cache, &node);
3615 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3616 if (SHUTTINGDOWN(fctx))
3617 maybe_destroy(fctx); /* Locks bucket. */
3621 if (!ISC_LIST_EMPTY(fctx->validators)) {
3623 INSIST(fctx->type == dns_rdatatype_any ||
3624 fctx->type == dns_rdatatype_rrsig ||
3625 fctx->type == dns_rdatatype_sig);
3627 * Don't send a response yet - we have
3628 * more rdatasets that still need to
3631 dns_db_detachnode(fctx->cache, &node);
3632 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3633 dns_validator_send(ISC_LIST_HEAD(fctx->validators));
3639 * Cache any NS/NSEC records that happened to be validated.
3641 result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
3642 while (result == ISC_R_SUCCESS) {
3644 dns_message_currentname(fctx->rmessage, DNS_SECTION_AUTHORITY,
3646 for (rdataset = ISC_LIST_HEAD(name->list);
3648 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3649 if ((rdataset->type != dns_rdatatype_ns &&
3650 rdataset->type != dns_rdatatype_nsec) ||
3651 rdataset->trust != dns_trust_secure)
3653 for (sigrdataset = ISC_LIST_HEAD(name->list);
3654 sigrdataset != NULL;
3655 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
3656 if (sigrdataset->type != dns_rdatatype_rrsig ||
3657 sigrdataset->covers != rdataset->type)
3661 if (sigrdataset == NULL ||
3662 sigrdataset->trust != dns_trust_secure)
3664 result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
3666 if (result != ISC_R_SUCCESS)
3669 result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
3670 now, rdataset, 0, NULL);
3671 if (result == ISC_R_SUCCESS)
3672 result = dns_db_addrdataset(fctx->cache, nsnode,
3676 dns_db_detachnode(fctx->cache, &nsnode);
3678 result = dns_message_nextname(fctx->rmessage,
3679 DNS_SECTION_AUTHORITY);
3682 result = ISC_R_SUCCESS;
3685 * Respond with an answer, positive or negative,
3686 * as opposed to an error. 'node' must be non-NULL.
3689 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
3691 if (hevent != NULL) {
3692 hevent->result = eresult;
3693 RUNTIME_CHECK(dns_name_copy(vevent->name,
3694 dns_fixedname_name(&hevent->foundname), NULL)
3696 dns_db_attach(fctx->cache, &hevent->db);
3697 dns_db_transfernode(fctx->cache, &node, &hevent->node);
3698 clone_results(fctx);
3703 dns_db_detachnode(fctx->cache, &node);
3705 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
3707 fctx_done(fctx, result); /* Locks bucket. */
3710 INSIST(node == NULL);
3711 isc_event_free(&event);
3714 static inline isc_result_t
3715 cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
3718 dns_rdataset_t *rdataset, *sigrdataset;
3719 dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
3720 dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
3721 dns_dbnode_t *node, **anodep;
3724 dns_resolver_t *res;
3725 isc_boolean_t need_validation, secure_domain, have_answer;
3726 isc_result_t result, eresult;
3727 dns_fetchevent_t *event;
3728 unsigned int options;
3731 unsigned int valoptions = 0;
3734 * The appropriate bucket lock must be held.
3738 need_validation = ISC_FALSE;
3739 secure_domain = ISC_FALSE;
3740 have_answer = ISC_FALSE;
3741 eresult = ISC_R_SUCCESS;
3742 task = res->buckets[fctx->bucketnum].task;
3745 * Is DNSSEC validation required for this name?
3747 if (res->view->enablevalidation) {
3748 result = dns_keytable_issecuredomain(res->view->secroots, name,
3750 if (result != ISC_R_SUCCESS)
3753 if (!secure_domain && res->view->dlv != NULL) {
3754 valoptions = DNS_VALIDATOR_DLV;
3755 secure_domain = ISC_TRUE;
3759 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
3760 need_validation = ISC_FALSE;
3762 need_validation = secure_domain;
3768 asigrdataset = NULL;
3770 if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
3772 have_answer = ISC_TRUE;
3773 event = ISC_LIST_HEAD(fctx->events);
3774 if (event != NULL) {
3776 aname = dns_fixedname_name(&event->foundname);
3777 result = dns_name_copy(name, aname, NULL);
3778 if (result != ISC_R_SUCCESS)
3780 anodep = &event->node;
3782 * If this is an ANY, SIG or RRSIG query, we're not
3783 * going to return any rdatasets, unless we encountered
3784 * a CNAME or DNAME as "the answer". In this case,
3785 * we're going to return DNS_R_CNAME or DNS_R_DNAME
3786 * and we must set up the rdatasets.
3788 if ((fctx->type != dns_rdatatype_any &&
3789 fctx->type != dns_rdatatype_rrsig &&
3790 fctx->type != dns_rdatatype_sig) ||
3791 (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
3792 ardataset = event->rdataset;
3793 asigrdataset = event->sigrdataset;
3799 * Find or create the cache node.
3802 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
3803 if (result != ISC_R_SUCCESS)
3807 * Cache or validate each cacheable rdataset.
3809 fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
3810 for (rdataset = ISC_LIST_HEAD(name->list);
3812 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3813 if (!CACHE(rdataset))
3815 if (CHECKNAMES(rdataset)) {
3816 char namebuf[DNS_NAME_FORMATSIZE];
3817 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3818 char classbuf[DNS_RDATATYPE_FORMATSIZE];
3820 dns_name_format(name, namebuf, sizeof(namebuf));
3821 dns_rdatatype_format(rdataset->type, typebuf,
3823 dns_rdataclass_format(rdataset->rdclass, classbuf,
3825 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
3826 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
3827 "check-names %s %s/%s/%s",
3828 fail ? "failure" : "warning",
3829 namebuf, typebuf, classbuf);
3831 if (ANSWER(rdataset)) {
3832 dns_db_detachnode(fctx->cache, &node);
3833 return (DNS_R_BADNAME);
3840 * Enforce the configure maximum cache TTL.
3842 if (rdataset->ttl > res->view->maxcachettl)
3843 rdataset->ttl = res->view->maxcachettl;
3846 * If this rrset is in a secure domain, do DNSSEC validation
3847 * for it, unless it is glue.
3849 if (secure_domain && rdataset->trust != dns_trust_glue) {
3851 * RRSIGs are validated as part of validating the
3854 if (rdataset->type == dns_rdatatype_rrsig)
3857 * Find the SIG for this rdataset, if we have it.
3859 for (sigrdataset = ISC_LIST_HEAD(name->list);
3860 sigrdataset != NULL;
3861 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
3862 if (sigrdataset->type == dns_rdatatype_rrsig &&
3863 sigrdataset->covers == rdataset->type)
3866 if (sigrdataset == NULL) {
3867 if (!ANSWER(rdataset) && need_validation) {
3869 * Ignore non-answer rdatasets that
3870 * are missing signatures.
3877 * Normalize the rdataset and sigrdataset TTLs.
3879 if (sigrdataset != NULL) {
3880 rdataset->ttl = ISC_MIN(rdataset->ttl,
3882 sigrdataset->ttl = rdataset->ttl;
3886 * Cache this rdataset/sigrdataset pair as
3889 rdataset->trust = dns_trust_pending;
3890 if (sigrdataset != NULL)
3891 sigrdataset->trust = dns_trust_pending;
3892 if (!need_validation)
3893 addedrdataset = ardataset;
3895 addedrdataset = NULL;
3896 result = dns_db_addrdataset(fctx->cache, node, NULL,
3899 if (result == DNS_R_UNCHANGED) {
3900 result = ISC_R_SUCCESS;
3901 if (!need_validation &&
3902 ardataset != NULL &&
3903 ardataset->type == 0) {
3905 * The answer in the cache is better
3906 * than the answer we found, and is
3907 * a negative cache entry, so we
3908 * must set eresult appropriately.
3910 if (NXDOMAIN(ardataset))
3911 eresult = DNS_R_NCACHENXDOMAIN;
3913 eresult = DNS_R_NCACHENXRRSET;
3915 * We have a negative response from
3916 * the cache so don't attempt to
3917 * add the RRSIG rrset.
3922 if (result != ISC_R_SUCCESS)
3924 if (sigrdataset != NULL) {
3925 if (!need_validation)
3926 addedrdataset = asigrdataset;
3928 addedrdataset = NULL;
3929 result = dns_db_addrdataset(fctx->cache,
3933 if (result == DNS_R_UNCHANGED)
3934 result = ISC_R_SUCCESS;
3935 if (result != ISC_R_SUCCESS)
3937 } else if (!ANSWER(rdataset))
3940 if (ANSWER(rdataset) && need_validation) {
3941 if (fctx->type != dns_rdatatype_any &&
3942 fctx->type != dns_rdatatype_rrsig &&
3943 fctx->type != dns_rdatatype_sig) {
3945 * This is The Answer. We will
3946 * validate it, but first we cache
3947 * the rest of the response - it may
3948 * contain useful keys.
3950 INSIST(valrdataset == NULL &&
3951 valsigrdataset == NULL);
3952 valrdataset = rdataset;
3953 valsigrdataset = sigrdataset;
3956 * This is one of (potentially)
3957 * multiple answers to an ANY
3958 * or SIG query. To keep things
3959 * simple, we just start the
3960 * validator right away rather
3961 * than caching first and
3962 * having to remember which
3963 * rdatasets needed validation.
3965 result = valcreate(fctx, addrinfo,
3966 name, rdataset->type,
3971 * Defer any further validations.
3972 * This prevents multiple validators
3973 * from manipulating fctx->rmessage
3976 valoptions |= DNS_VALIDATOR_DEFER;
3978 } else if (CHAINING(rdataset)) {
3979 if (rdataset->type == dns_rdatatype_cname)
3980 eresult = DNS_R_CNAME;
3982 INSIST(rdataset->type ==
3983 dns_rdatatype_dname);
3984 eresult = DNS_R_DNAME;
3987 } else if (!EXTERNAL(rdataset)) {
3989 * It's OK to cache this rdataset now.
3991 if (ANSWER(rdataset))
3992 addedrdataset = ardataset;
3993 else if (ANSWERSIG(rdataset))
3994 addedrdataset = asigrdataset;
3996 addedrdataset = NULL;
3997 if (CHAINING(rdataset)) {
3998 if (rdataset->type == dns_rdatatype_cname)
3999 eresult = DNS_R_CNAME;
4001 INSIST(rdataset->type ==
4002 dns_rdatatype_dname);
4003 eresult = DNS_R_DNAME;
4006 if (rdataset->trust == dns_trust_glue &&
4007 (rdataset->type == dns_rdatatype_ns ||
4008 (rdataset->type == dns_rdatatype_rrsig &&
4009 rdataset->covers == dns_rdatatype_ns))) {
4011 * If the trust level is 'dns_trust_glue'
4012 * then we are adding data from a referral
4013 * we got while executing the search algorithm.
4014 * New referral data always takes precedence
4015 * over the existing cache contents.
4017 options = DNS_DBADD_FORCE;
4021 * Now we can add the rdataset.
4023 result = dns_db_addrdataset(fctx->cache,
4028 if (result == DNS_R_UNCHANGED) {
4029 if (ANSWER(rdataset) &&
4030 ardataset != NULL &&
4031 ardataset->type == 0) {
4033 * The answer in the cache is better
4034 * than the answer we found, and is
4035 * a negative cache entry, so we
4036 * must set eresult appropriately.
4038 if (NXDOMAIN(ardataset))
4039 eresult = DNS_R_NCACHENXDOMAIN;
4041 eresult = DNS_R_NCACHENXRRSET;
4043 result = ISC_R_SUCCESS;
4044 } else if (result != ISC_R_SUCCESS)
4049 if (valrdataset != NULL)
4050 result = valcreate(fctx, addrinfo, name, fctx->type,
4051 valrdataset, valsigrdataset, valoptions,
4054 if (result == ISC_R_SUCCESS && have_answer) {
4055 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4056 if (event != NULL) {
4058 * Negative results must be indicated in event->result.
4060 if (dns_rdataset_isassociated(event->rdataset) &&
4061 event->rdataset->type == dns_rdatatype_none) {
4062 INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
4063 eresult == DNS_R_NCACHENXRRSET);
4065 event->result = eresult;
4066 dns_db_attach(fctx->cache, adbp);
4067 dns_db_transfernode(fctx->cache, &node, anodep);
4068 clone_results(fctx);
4073 dns_db_detachnode(fctx->cache, &node);
4078 static inline isc_result_t
4079 cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
4081 isc_result_t result;
4082 dns_section_t section;
4085 FCTXTRACE("cache_message");
4087 fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
4089 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4091 for (section = DNS_SECTION_ANSWER;
4092 section <= DNS_SECTION_ADDITIONAL;
4094 result = dns_message_firstname(fctx->rmessage, section);
4095 while (result == ISC_R_SUCCESS) {
4097 dns_message_currentname(fctx->rmessage, section,
4099 if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
4100 result = cache_name(fctx, name, addrinfo, now);
4101 if (result != ISC_R_SUCCESS)
4104 result = dns_message_nextname(fctx->rmessage, section);
4106 if (result != ISC_R_NOMORE)
4109 if (result == ISC_R_NOMORE)
4110 result = ISC_R_SUCCESS;
4112 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
4118 * Do what dns_ncache_add() does, and then compute an appropriate eresult.
4121 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
4122 dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
4123 dns_rdataset_t *ardataset,
4124 isc_result_t *eresultp)
4126 isc_result_t result;
4127 dns_rdataset_t rdataset;
4129 if (ardataset == NULL) {
4130 dns_rdataset_init(&rdataset);
4131 ardataset = &rdataset;
4133 result = dns_ncache_add(message, cache, node, covers, now,
4135 if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
4137 * If the cache now contains a negative entry and we
4138 * care about whether it is DNS_R_NCACHENXDOMAIN or
4139 * DNS_R_NCACHENXRRSET then extract it.
4141 if (ardataset->type == 0) {
4143 * The cache data is a negative cache entry.
4145 if (NXDOMAIN(ardataset))
4146 *eresultp = DNS_R_NCACHENXDOMAIN;
4148 *eresultp = DNS_R_NCACHENXRRSET;
4151 * Either we don't care about the nature of the
4152 * cache rdataset (because no fetch is interested
4153 * in the outcome), or the cache rdataset is not
4154 * a negative cache entry. Whichever case it is,
4155 * we can return success.
4157 * XXXRTH There's a CNAME/DNAME problem here.
4159 *eresultp = ISC_R_SUCCESS;
4161 result = ISC_R_SUCCESS;
4163 if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
4164 dns_rdataset_disassociate(ardataset);
4169 static inline isc_result_t
4170 ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
4171 dns_rdatatype_t covers, isc_stdtime_t now)
4173 isc_result_t result, eresult;
4175 dns_resolver_t *res;
4177 dns_dbnode_t *node, **anodep;
4178 dns_rdataset_t *ardataset;
4179 isc_boolean_t need_validation, secure_domain;
4181 dns_fetchevent_t *event;
4183 unsigned int valoptions = 0;
4185 FCTXTRACE("ncache_message");
4187 fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
4190 need_validation = ISC_FALSE;
4191 secure_domain = ISC_FALSE;
4192 eresult = ISC_R_SUCCESS;
4197 * XXXMPA remove when we follow cnames and adjust the setting
4198 * of FCTX_ATTR_WANTNCACHE in noanswer_response().
4200 INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
4203 * Is DNSSEC validation required for this name?
4205 if (fctx->res->view->enablevalidation) {
4206 result = dns_keytable_issecuredomain(res->view->secroots, name,
4208 if (result != ISC_R_SUCCESS)
4211 if (!secure_domain && res->view->dlv != NULL) {
4212 valoptions = DNS_VALIDATOR_DLV;
4213 secure_domain = ISC_TRUE;
4217 if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
4218 need_validation = ISC_FALSE;
4220 need_validation = secure_domain;
4222 if (secure_domain) {
4224 * Mark all rdatasets as pending.
4226 dns_rdataset_t *trdataset;
4229 result = dns_message_firstname(fctx->rmessage,
4230 DNS_SECTION_AUTHORITY);
4231 while (result == ISC_R_SUCCESS) {
4233 dns_message_currentname(fctx->rmessage,
4234 DNS_SECTION_AUTHORITY,
4236 for (trdataset = ISC_LIST_HEAD(tname->list);
4238 trdataset = ISC_LIST_NEXT(trdataset, link))
4239 trdataset->trust = dns_trust_pending;
4240 result = dns_message_nextname(fctx->rmessage,
4241 DNS_SECTION_AUTHORITY);
4243 if (result != ISC_R_NOMORE)
4248 if (need_validation) {
4250 * Do negative response validation.
4252 result = valcreate(fctx, addrinfo, name, fctx->type,
4253 NULL, NULL, valoptions,
4254 res->buckets[fctx->bucketnum].task);
4256 * If validation is necessary, return now. Otherwise continue
4257 * to process the message, letting the validation complete
4258 * in its own good time.
4263 LOCK(&res->buckets[fctx->bucketnum].lock);
4269 if (!HAVE_ANSWER(fctx)) {
4270 event = ISC_LIST_HEAD(fctx->events);
4271 if (event != NULL) {
4273 aname = dns_fixedname_name(&event->foundname);
4274 result = dns_name_copy(name, aname, NULL);
4275 if (result != ISC_R_SUCCESS)
4277 anodep = &event->node;
4278 ardataset = event->rdataset;
4283 result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
4284 if (result != ISC_R_SUCCESS)
4288 * If we are asking for a SOA record set the cache time
4289 * to zero to facilitate locating the containing zone of
4292 ttl = fctx->res->view->maxncachettl;
4293 if (fctx->type == dns_rdatatype_soa &&
4294 covers == dns_rdatatype_any)
4297 result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
4298 covers, now, ttl, ardataset, &eresult);
4299 if (result != ISC_R_SUCCESS)
4302 if (!HAVE_ANSWER(fctx)) {
4303 fctx->attributes |= FCTX_ATTR_HAVEANSWER;
4304 if (event != NULL) {
4305 event->result = eresult;
4306 dns_db_attach(fctx->cache, adbp);
4307 dns_db_transfernode(fctx->cache, &node, anodep);
4308 clone_results(fctx);
4313 UNLOCK(&res->buckets[fctx->bucketnum].lock);
4316 dns_db_detachnode(fctx->cache, &node);
4322 mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
4323 isc_boolean_t external, isc_boolean_t gluing)
4325 name->attributes |= DNS_NAMEATTR_CACHE;
4327 rdataset->trust = dns_trust_glue;
4329 * Glue with 0 TTL causes problems. We force the TTL to
4330 * 1 second to prevent this.
4332 if (rdataset->ttl == 0)
4335 rdataset->trust = dns_trust_additional;
4337 * Avoid infinite loops by only marking new rdatasets.
4339 if (!CACHE(rdataset)) {
4340 name->attributes |= DNS_NAMEATTR_CHASE;
4341 rdataset->attributes |= DNS_RDATASETATTR_CHASE;
4343 rdataset->attributes |= DNS_RDATASETATTR_CACHE;
4345 rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
4349 check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
4350 fetchctx_t *fctx = arg;
4351 isc_result_t result;
4353 dns_rdataset_t *rdataset;
4354 isc_boolean_t external;
4355 dns_rdatatype_t rtype;
4356 isc_boolean_t gluing;
4358 REQUIRE(VALID_FCTX(fctx));
4366 result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
4367 addname, dns_rdatatype_any, 0, &name,
4369 if (result == ISC_R_SUCCESS) {
4370 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4371 if (type == dns_rdatatype_a) {
4372 for (rdataset = ISC_LIST_HEAD(name->list);
4374 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4375 if (rdataset->type == dns_rdatatype_rrsig)
4376 rtype = rdataset->covers;
4378 rtype = rdataset->type;
4379 if (rtype == dns_rdatatype_a ||
4380 rtype == dns_rdatatype_aaaa)
4381 mark_related(name, rdataset, external,
4385 result = dns_message_findtype(name, type, 0,
4387 if (result == ISC_R_SUCCESS) {
4388 mark_related(name, rdataset, external, gluing);
4390 * Do we have its SIG too?
4393 result = dns_message_findtype(name,
4394 dns_rdatatype_rrsig,
4396 if (result == ISC_R_SUCCESS)
4397 mark_related(name, rdataset, external,
4403 return (ISC_R_SUCCESS);
4407 chase_additional(fetchctx_t *fctx) {
4408 isc_boolean_t rescan;
4409 dns_section_t section = DNS_SECTION_ADDITIONAL;
4410 isc_result_t result;
4415 for (result = dns_message_firstname(fctx->rmessage, section);
4416 result == ISC_R_SUCCESS;
4417 result = dns_message_nextname(fctx->rmessage, section)) {
4418 dns_name_t *name = NULL;
4419 dns_rdataset_t *rdataset;
4420 dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
4422 if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
4424 name->attributes &= ~DNS_NAMEATTR_CHASE;
4425 for (rdataset = ISC_LIST_HEAD(name->list);
4427 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4428 if (CHASE(rdataset)) {
4429 rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
4430 (void)dns_rdataset_additionaldata(rdataset,
4441 static inline isc_result_t
4442 cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
4443 isc_result_t result;
4444 dns_rdata_t rdata = DNS_RDATA_INIT;
4445 dns_rdata_cname_t cname;
4447 result = dns_rdataset_first(rdataset);
4448 if (result != ISC_R_SUCCESS)
4450 dns_rdataset_current(rdataset, &rdata);
4451 result = dns_rdata_tostruct(&rdata, &cname, NULL);
4452 if (result != ISC_R_SUCCESS)
4454 dns_name_init(tname, NULL);
4455 dns_name_clone(&cname.cname, tname);
4456 dns_rdata_freestruct(&cname);
4458 return (ISC_R_SUCCESS);
4461 static inline isc_result_t
4462 dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
4463 dns_fixedname_t *fixeddname)
4465 isc_result_t result;
4466 dns_rdata_t rdata = DNS_RDATA_INIT;
4467 unsigned int nlabels;
4469 dns_namereln_t namereln;
4470 dns_rdata_dname_t dname;
4471 dns_fixedname_t prefix;
4474 * Get the target name of the DNAME.
4477 result = dns_rdataset_first(rdataset);
4478 if (result != ISC_R_SUCCESS)
4480 dns_rdataset_current(rdataset, &rdata);
4481 result = dns_rdata_tostruct(&rdata, &dname, NULL);
4482 if (result != ISC_R_SUCCESS)
4486 * Get the prefix of qname.
4488 namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
4489 if (namereln != dns_namereln_subdomain) {
4490 dns_rdata_freestruct(&dname);
4491 return (DNS_R_FORMERR);
4493 dns_fixedname_init(&prefix);
4494 dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
4495 dns_fixedname_init(fixeddname);
4496 result = dns_name_concatenate(dns_fixedname_name(&prefix),
4498 dns_fixedname_name(fixeddname), NULL);
4499 dns_rdata_freestruct(&dname);
4504 * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
4505 * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
4506 * response to an NS query that should be treated as a referral
4507 * even though the NS records occur in the answer section
4508 * rather than the authority section.
4511 noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
4512 isc_boolean_t bind8_ns_resp)
4514 isc_result_t result;
4515 dns_message_t *message;
4516 dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
4517 dns_rdataset_t *rdataset, *ns_rdataset;
4518 isc_boolean_t aa, negative_response;
4519 dns_rdatatype_t type;
4520 dns_section_t section =
4521 bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
4523 FCTXTRACE("noanswer_response");
4525 message = fctx->rmessage;
4530 if (oqname == NULL) {
4532 * We have a normal, non-chained negative response or
4535 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
4539 qname = &fctx->name;
4542 * We're being invoked by answer_response() after it has
4543 * followed a CNAME/DNAME chain.
4548 * If the current qname is not a subdomain of the query
4549 * domain, there's no point in looking at the authority
4550 * section without doing DNSSEC validation.
4552 * Until we do that validation, we'll just return success
4555 if (!dns_name_issubdomain(qname, &fctx->domain))
4556 return (ISC_R_SUCCESS);
4560 * We have to figure out if this is a negative response, or a
4565 * Sometimes we can tell if its a negative response by looking at
4566 * the message header.
4568 negative_response = ISC_FALSE;
4569 if (message->rcode == dns_rcode_nxdomain ||
4570 (message->counts[DNS_SECTION_ANSWER] == 0 &&
4571 message->counts[DNS_SECTION_AUTHORITY] == 0))
4572 negative_response = ISC_TRUE;
4575 * Process the authority section.
4581 result = dns_message_firstname(message, section);
4582 while (result == ISC_R_SUCCESS) {
4584 dns_message_currentname(message, section, &name);
4585 if (dns_name_issubdomain(name, &fctx->domain)) {
4587 * Look for NS/SOA RRsets first.
4589 for (rdataset = ISC_LIST_HEAD(name->list);
4591 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4592 type = rdataset->type;
4593 if (type == dns_rdatatype_rrsig)
4594 type = rdataset->covers;
4595 if (((type == dns_rdatatype_ns ||
4596 type == dns_rdatatype_soa) &&
4597 !dns_name_issubdomain(qname, name)))
4598 return (DNS_R_FORMERR);
4599 if (type == dns_rdatatype_ns) {
4603 * Only one set of NS RRs is allowed.
4605 if (rdataset->type ==
4607 if (ns_name != NULL &&
4609 return (DNS_R_FORMERR);
4611 ns_rdataset = rdataset;
4615 rdataset->attributes |=
4616 DNS_RDATASETATTR_CACHE;
4617 rdataset->trust = dns_trust_glue;
4619 if (type == dns_rdatatype_soa) {
4621 * SOA, or RRSIG SOA.
4623 * Only one SOA is allowed.
4625 if (rdataset->type ==
4626 dns_rdatatype_soa) {
4627 if (soa_name != NULL &&
4629 return (DNS_R_FORMERR);
4633 DNS_NAMEATTR_NCACHE;
4634 rdataset->attributes |=
4635 DNS_RDATASETATTR_NCACHE;
4638 dns_trust_authauthority;
4641 dns_trust_additional;
4645 result = dns_message_nextname(message, section);
4646 if (result == ISC_R_NOMORE)
4648 else if (result != ISC_R_SUCCESS)
4653 * A negative response has a SOA record (Type 2)
4654 * and a optional NS RRset (Type 1) or it has neither
4655 * a SOA or a NS RRset (Type 3, handled above) or
4656 * rcode is NXDOMAIN (handled above) in which case
4657 * the NS RRset is allowed (Type 4).
4659 if (soa_name != NULL)
4660 negative_response = ISC_TRUE;
4662 result = dns_message_firstname(message, section);
4663 while (result == ISC_R_SUCCESS) {
4665 dns_message_currentname(message, section, &name);
4666 if (dns_name_issubdomain(name, &fctx->domain)) {
4667 for (rdataset = ISC_LIST_HEAD(name->list);
4669 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4670 type = rdataset->type;
4671 if (type == dns_rdatatype_rrsig)
4672 type = rdataset->covers;
4673 if (type == dns_rdatatype_nsec) {
4675 * NSEC or RRSIG NSEC.
4677 if (negative_response) {
4679 DNS_NAMEATTR_NCACHE;
4680 rdataset->attributes |=
4681 DNS_RDATASETATTR_NCACHE;
4685 rdataset->attributes |=
4686 DNS_RDATASETATTR_CACHE;
4690 dns_trust_authauthority;
4693 dns_trust_additional;
4695 * No additional data needs to be
4698 } else if (type == dns_rdatatype_ds) {
4702 * These should only be here if
4703 * this is a referral, and there
4704 * should only be one DS.
4706 if (ns_name == NULL)
4707 return (DNS_R_FORMERR);
4708 if (rdataset->type ==
4710 if (ds_name != NULL &&
4712 return (DNS_R_FORMERR);
4717 rdataset->attributes |=
4718 DNS_RDATASETATTR_CACHE;
4721 dns_trust_authauthority;
4724 dns_trust_additional;
4728 result = dns_message_nextname(message, section);
4729 if (result == ISC_R_NOMORE)
4731 else if (result != ISC_R_SUCCESS)
4736 * Trigger lookups for DNS nameservers.
4738 if (negative_response && message->rcode == dns_rcode_noerror &&
4739 fctx->type == dns_rdatatype_ds && soa_name != NULL &&
4740 dns_name_equal(soa_name, qname) &&
4741 !dns_name_equal(qname, dns_rootname))
4742 return (DNS_R_CHASEDSSERVERS);
4745 * Did we find anything?
4747 if (!negative_response && ns_name == NULL) {
4751 if (oqname != NULL) {
4753 * We've already got a partial CNAME/DNAME chain,
4754 * and haven't found else anything useful here, but
4755 * no error has occurred since we have an answer.
4757 return (ISC_R_SUCCESS);
4760 * The responder is insane.
4762 return (DNS_R_FORMERR);
4767 * If we found both NS and SOA, they should be the same name.
4769 if (ns_name != NULL && soa_name != NULL && ns_name != soa_name)
4770 return (DNS_R_FORMERR);
4773 * Do we have a referral? (We only want to follow a referral if
4774 * we're not following a chain.)
4776 if (!negative_response && ns_name != NULL && oqname == NULL) {
4778 * We already know ns_name is a subdomain of fctx->domain.
4779 * If ns_name is equal to fctx->domain, we're not making
4780 * progress. We return DNS_R_FORMERR so that we'll keep
4781 * trying other servers.
4783 if (dns_name_equal(ns_name, &fctx->domain))
4784 return (DNS_R_FORMERR);
4787 * If the referral name is not a parent of the query
4788 * name, consider the responder insane.
4790 if (! dns_name_issubdomain(&fctx->name, ns_name)) {
4791 FCTXTRACE("referral to non-parent");
4792 return (DNS_R_FORMERR);
4796 * Mark any additional data related to this rdataset.
4797 * It's important that we do this before we change the
4800 INSIST(ns_rdataset != NULL);
4801 fctx->attributes |= FCTX_ATTR_GLUING;
4802 (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
4804 fctx->attributes &= ~FCTX_ATTR_GLUING;
4806 * NS rdatasets with 0 TTL cause problems.
4807 * dns_view_findzonecut() will not find them when we
4808 * try to follow the referral, and we'll SERVFAIL
4809 * because the best nameservers are now above QDOMAIN.
4810 * We force the TTL to 1 second to prevent this.
4812 if (ns_rdataset->ttl == 0)
4813 ns_rdataset->ttl = 1;
4815 * Set the current query domain to the referral name.
4817 * XXXRTH We should check if we're in forward-only mode, and
4818 * if so we should bail out.
4820 INSIST(dns_name_countlabels(&fctx->domain) > 0);
4821 dns_name_free(&fctx->domain,
4822 fctx->res->buckets[fctx->bucketnum].mctx);
4823 if (dns_rdataset_isassociated(&fctx->nameservers))
4824 dns_rdataset_disassociate(&fctx->nameservers);
4825 dns_name_init(&fctx->domain, NULL);
4826 result = dns_name_dup(ns_name,
4827 fctx->res->buckets[fctx->bucketnum].mctx,
4829 if (result != ISC_R_SUCCESS)
4831 fctx->attributes |= FCTX_ATTR_WANTCACHE;
4832 return (DNS_R_DELEGATION);
4836 * Since we're not doing a referral, we don't want to cache any
4837 * NS RRs we may have found.
4839 if (ns_name != NULL)
4840 ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
4842 if (negative_response && oqname == NULL)
4843 fctx->attributes |= FCTX_ATTR_WANTNCACHE;
4845 return (ISC_R_SUCCESS);
4849 answer_response(fetchctx_t *fctx) {
4850 isc_result_t result;
4851 dns_message_t *message;
4852 dns_name_t *name, *qname, tname;
4853 dns_rdataset_t *rdataset;
4854 isc_boolean_t done, external, chaining, aa, found, want_chaining;
4855 isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
4857 dns_rdatatype_t type;
4858 dns_fixedname_t dname, fqname;
4860 FCTXTRACE("answer_response");
4862 message = fctx->rmessage;
4865 * Examine the answer section, marking those rdatasets which are
4866 * part of the answer and should be cached.
4870 found_cname = ISC_FALSE;
4871 found_type = ISC_FALSE;
4872 chaining = ISC_FALSE;
4873 have_answer = ISC_FALSE;
4874 want_chaining = ISC_FALSE;
4875 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
4879 qname = &fctx->name;
4881 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
4882 while (!done && result == ISC_R_SUCCESS) {
4884 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
4885 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
4886 if (dns_name_equal(name, qname)) {
4887 wanted_chaining = ISC_FALSE;
4888 for (rdataset = ISC_LIST_HEAD(name->list);
4890 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4892 want_chaining = ISC_FALSE;
4894 if (rdataset->type == type && !found_cname) {
4896 * We've found an ordinary answer.
4899 found_type = ISC_TRUE;
4901 aflag = DNS_RDATASETATTR_ANSWER;
4902 } else if (type == dns_rdatatype_any) {
4904 * We've found an answer matching
4905 * an ANY query. There may be
4909 aflag = DNS_RDATASETATTR_ANSWER;
4910 } else if (rdataset->type == dns_rdatatype_rrsig
4911 && rdataset->covers == type
4914 * We've found a signature that
4915 * covers the type we're looking for.
4918 found_type = ISC_TRUE;
4919 aflag = DNS_RDATASETATTR_ANSWERSIG;
4920 } else if (rdataset->type ==
4924 * We're looking for something else,
4925 * but we found a CNAME.
4927 * Getting a CNAME response for some
4928 * query types is an error.
4930 if (type == dns_rdatatype_rrsig ||
4931 type == dns_rdatatype_dnskey ||
4932 type == dns_rdatatype_nsec)
4933 return (DNS_R_FORMERR);
4935 found_cname = ISC_TRUE;
4936 want_chaining = ISC_TRUE;
4937 aflag = DNS_RDATASETATTR_ANSWER;
4938 result = cname_target(rdataset,
4940 if (result != ISC_R_SUCCESS)
4942 } else if (rdataset->type == dns_rdatatype_rrsig
4943 && rdataset->covers ==
4947 * We're looking for something else,
4948 * but we found a SIG CNAME.
4951 found_cname = ISC_TRUE;
4952 aflag = DNS_RDATASETATTR_ANSWERSIG;
4957 * We've found an answer to our
4962 rdataset->attributes |=
4963 DNS_RDATASETATTR_CACHE;
4964 rdataset->trust = dns_trust_answer;
4967 * This data is "the" answer
4968 * to our question only if
4969 * we're not chaining (i.e.
4970 * if we haven't followed
4971 * a CNAME or DNAME).
4975 DNS_RDATASETATTR_ANSWER)
4976 have_answer = ISC_TRUE;
4978 DNS_NAMEATTR_ANSWER;
4979 rdataset->attributes |= aflag;
4982 dns_trust_authanswer;
4983 } else if (external) {
4985 * This data is outside of
4986 * our query domain, and
4987 * may only be cached if it
4988 * comes from a secure zone
4991 rdataset->attributes |=
4992 DNS_RDATASETATTR_EXTERNAL;
4996 * Mark any additional data related
4999 (void)dns_rdataset_additionaldata(
5007 if (want_chaining) {
5008 wanted_chaining = ISC_TRUE;
5010 DNS_NAMEATTR_CHAINING;
5011 rdataset->attributes |=
5012 DNS_RDATASETATTR_CHAINING;
5017 * We could add an "else" clause here and
5018 * log that we're ignoring this rdataset.
5022 * If wanted_chaining is true, we've done
5023 * some chaining as the result of processing
5024 * this node, and thus we need to set
5027 * We don't set chaining inside of the
5028 * rdataset loop because doing that would
5029 * cause us to ignore the signatures of
5032 if (wanted_chaining)
5033 chaining = ISC_TRUE;
5036 * Look for a DNAME (or its SIG). Anything else is
5039 wanted_chaining = ISC_FALSE;
5040 for (rdataset = ISC_LIST_HEAD(name->list);
5042 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5043 isc_boolean_t found_dname = ISC_FALSE;
5046 if (rdataset->type == dns_rdatatype_dname) {
5048 * We're looking for something else,
5049 * but we found a DNAME.
5051 * If we're not chaining, then the
5052 * DNAME should not be external.
5054 if (!chaining && external)
5055 return (DNS_R_FORMERR);
5057 want_chaining = ISC_TRUE;
5058 aflag = DNS_RDATASETATTR_ANSWER;
5059 result = dname_target(rdataset,
5062 if (result == ISC_R_NOSPACE) {
5064 * We can't construct the
5065 * DNAME target. Do not
5068 want_chaining = ISC_FALSE;
5069 } else if (result != ISC_R_SUCCESS)
5072 found_dname = ISC_TRUE;
5073 } else if (rdataset->type == dns_rdatatype_rrsig
5074 && rdataset->covers ==
5075 dns_rdatatype_dname) {
5077 * We've found a signature that
5081 aflag = DNS_RDATASETATTR_ANSWERSIG;
5086 * We've found an answer to our
5091 rdataset->attributes |=
5092 DNS_RDATASETATTR_CACHE;
5093 rdataset->trust = dns_trust_answer;
5096 * This data is "the" answer
5097 * to our question only if
5098 * we're not chaining.
5102 DNS_RDATASETATTR_ANSWER)
5103 have_answer = ISC_TRUE;
5105 DNS_NAMEATTR_ANSWER;
5106 rdataset->attributes |= aflag;
5109 dns_trust_authanswer;
5110 } else if (external) {
5111 rdataset->attributes |=
5112 DNS_RDATASETATTR_EXTERNAL;
5120 * Copy the the dname into the
5123 * Although we check for
5124 * failure of the copy
5125 * operation, in practice it
5126 * should never fail since
5127 * we already know that the
5128 * result fits in a fixedname.
5130 dns_fixedname_init(&fqname);
5131 result = dns_name_copy(
5132 dns_fixedname_name(&dname),
5133 dns_fixedname_name(&fqname),
5135 if (result != ISC_R_SUCCESS)
5137 wanted_chaining = ISC_TRUE;
5139 DNS_NAMEATTR_CHAINING;
5140 rdataset->attributes |=
5141 DNS_RDATASETATTR_CHAINING;
5142 qname = dns_fixedname_name(
5147 if (wanted_chaining)
5148 chaining = ISC_TRUE;
5150 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
5152 if (result == ISC_R_NOMORE)
5153 result = ISC_R_SUCCESS;
5154 if (result != ISC_R_SUCCESS)
5158 * We should have found an answer.
5161 return (DNS_R_FORMERR);
5164 * This response is now potentially cacheable.
5166 fctx->attributes |= FCTX_ATTR_WANTCACHE;
5169 * Did chaining end before we got the final answer?
5173 * Yes. This may be a negative reply, so hand off
5174 * authority section processing to the noanswer code.
5175 * If it isn't a noanswer response, no harm will be
5178 return (noanswer_response(fctx, qname, ISC_FALSE));
5182 * We didn't end with an incomplete chain, so the rcode should be
5185 if (message->rcode != dns_rcode_noerror)
5186 return (DNS_R_FORMERR);
5189 * Examine the authority section (if there is one).
5191 * We expect there to be only one owner name for all the rdatasets
5192 * in this section, and we expect that it is not external.
5195 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
5196 while (!done && result == ISC_R_SUCCESS) {
5198 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
5199 external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
5202 * We expect to find NS or SIG NS rdatasets, and
5205 for (rdataset = ISC_LIST_HEAD(name->list);
5207 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5208 if (rdataset->type == dns_rdatatype_ns ||
5209 (rdataset->type == dns_rdatatype_rrsig &&
5210 rdataset->covers == dns_rdatatype_ns)) {
5213 rdataset->attributes |=
5214 DNS_RDATASETATTR_CACHE;
5215 if (aa && !chaining)
5217 dns_trust_authauthority;
5220 dns_trust_additional;
5223 * Mark any additional data related
5226 (void)dns_rdataset_additionaldata(
5234 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
5236 if (result == ISC_R_NOMORE)
5237 result = ISC_R_SUCCESS;
5243 resume_dslookup(isc_task_t *task, isc_event_t *event) {
5244 dns_fetchevent_t *fevent;
5245 dns_resolver_t *res;
5247 isc_result_t result;
5248 isc_boolean_t bucket_empty = ISC_FALSE;
5249 isc_boolean_t locked = ISC_FALSE;
5250 unsigned int bucketnum;
5251 dns_rdataset_t nameservers;
5252 dns_fixedname_t fixed;
5255 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
5256 fevent = (dns_fetchevent_t *)event;
5257 fctx = event->ev_arg;
5258 REQUIRE(VALID_FCTX(fctx));
5262 FCTXTRACE("resume_dslookup");
5264 if (fevent->node != NULL)
5265 dns_db_detachnode(fevent->db, &fevent->node);
5266 if (fevent->db != NULL)
5267 dns_db_detach(&fevent->db);
5269 dns_rdataset_init(&nameservers);
5271 bucketnum = fctx->bucketnum;
5272 if (fevent->result == ISC_R_CANCELED) {
5273 dns_resolver_destroyfetch(&fctx->nsfetch);
5274 fctx_done(fctx, ISC_R_CANCELED);
5275 } else if (fevent->result == ISC_R_SUCCESS) {
5277 FCTXTRACE("resuming DS lookup");
5279 dns_resolver_destroyfetch(&fctx->nsfetch);
5280 if (dns_rdataset_isassociated(&fctx->nameservers))
5281 dns_rdataset_disassociate(&fctx->nameservers);
5282 dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
5283 dns_name_free(&fctx->domain,
5284 fctx->res->buckets[bucketnum].mctx);
5285 dns_name_init(&fctx->domain, NULL);
5286 result = dns_name_dup(&fctx->nsname,
5287 fctx->res->buckets[bucketnum].mctx,
5289 if (result != ISC_R_SUCCESS) {
5290 fctx_done(fctx, DNS_R_SERVFAIL);
5299 dns_rdataset_t *nsrdataset = NULL;
5302 * Retrieve state from fctx->nsfetch before we destroy it.
5304 dns_fixedname_init(&fixed);
5305 domain = dns_fixedname_name(&fixed);
5306 dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
5307 if (dns_name_equal(&fctx->nsname, domain)) {
5308 fctx_done(fctx, DNS_R_SERVFAIL);
5309 dns_resolver_destroyfetch(&fctx->nsfetch);
5312 if (dns_rdataset_isassociated(
5313 &fctx->nsfetch->private->nameservers)) {
5315 &fctx->nsfetch->private->nameservers,
5317 nsrdataset = &nameservers;
5320 dns_resolver_destroyfetch(&fctx->nsfetch);
5321 n = dns_name_countlabels(&fctx->nsname);
5322 dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
5325 if (dns_rdataset_isassociated(fevent->rdataset))
5326 dns_rdataset_disassociate(fevent->rdataset);
5327 FCTXTRACE("continuing to look for parent's NS records");
5328 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
5329 dns_rdatatype_ns, domain,
5330 nsrdataset, NULL, 0, task,
5331 resume_dslookup, fctx,
5332 &fctx->nsrrset, NULL,
5334 if (result != ISC_R_SUCCESS)
5335 fctx_done(fctx, result);
5337 LOCK(&res->buckets[bucketnum].lock);
5344 if (dns_rdataset_isassociated(&nameservers))
5345 dns_rdataset_disassociate(&nameservers);
5346 if (dns_rdataset_isassociated(fevent->rdataset))
5347 dns_rdataset_disassociate(fevent->rdataset);
5348 INSIST(fevent->sigrdataset == NULL);
5349 isc_event_free(&event);
5351 LOCK(&res->buckets[bucketnum].lock);
5353 if (fctx->references == 0)
5354 bucket_empty = fctx_destroy(fctx);
5355 UNLOCK(&res->buckets[bucketnum].lock);
5361 checknamessection(dns_message_t *message, dns_section_t section) {
5362 isc_result_t result;
5364 dns_rdata_t rdata = DNS_RDATA_INIT;
5365 dns_rdataset_t *rdataset;
5367 for (result = dns_message_firstname(message, section);
5368 result == ISC_R_SUCCESS;
5369 result = dns_message_nextname(message, section))
5372 dns_message_currentname(message, section, &name);
5373 for (rdataset = ISC_LIST_HEAD(name->list);
5375 rdataset = ISC_LIST_NEXT(rdataset, link)) {
5376 for (result = dns_rdataset_first(rdataset);
5377 result == ISC_R_SUCCESS;
5378 result = dns_rdataset_next(rdataset)) {
5379 dns_rdataset_current(rdataset, &rdata);
5380 if (!dns_rdata_checkowner(name, rdata.rdclass,
5383 !dns_rdata_checknames(&rdata, name, NULL))
5385 rdataset->attributes |=
5386 DNS_RDATASETATTR_CHECKNAMES;
5388 dns_rdata_reset(&rdata);
5395 checknames(dns_message_t *message) {
5397 checknamessection(message, DNS_SECTION_ANSWER);
5398 checknamessection(message, DNS_SECTION_AUTHORITY);
5399 checknamessection(message, DNS_SECTION_ADDITIONAL);
5403 log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
5404 isc_buffer_t buffer;
5407 isc_result_t result;
5409 if (! isc_log_wouldlog(dns_lctx, level))
5413 * Note that these are multiline debug messages. We want a newline
5414 * to appear in the log after each message.
5418 buf = isc_mem_get(mctx, len);
5421 isc_buffer_init(&buffer, buf, len);
5422 result = dns_message_totext(message, &dns_master_style_debug,
5424 if (result == ISC_R_NOSPACE) {
5425 isc_mem_put(mctx, buf, len);
5427 } else if (result == ISC_R_SUCCESS)
5428 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5429 DNS_LOGMODULE_RESOLVER, level,
5430 "received packet:\n%.*s",
5431 (int)isc_buffer_usedlength(&buffer),
5433 } while (result == ISC_R_NOSPACE);
5436 isc_mem_put(mctx, buf, len);
5440 resquery_response(isc_task_t *task, isc_event_t *event) {
5441 isc_result_t result = ISC_R_SUCCESS;
5442 resquery_t *query = event->ev_arg;
5443 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
5444 isc_boolean_t keep_trying, get_nameservers, resend;
5445 isc_boolean_t truncated;
5446 dns_message_t *message;
5449 dns_fixedname_t foundname;
5451 isc_time_t tnow, *finish;
5452 dns_adbaddrinfo_t *addrinfo;
5453 unsigned int options;
5454 unsigned int findoptions;
5455 isc_result_t broken_server;
5457 REQUIRE(VALID_QUERY(query));
5459 options = query->options;
5460 REQUIRE(VALID_FCTX(fctx));
5461 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
5465 (void)isc_timer_touch(fctx->timer);
5467 keep_trying = ISC_FALSE;
5468 broken_server = ISC_R_SUCCESS;
5469 get_nameservers = ISC_FALSE;
5471 truncated = ISC_FALSE;
5474 if (fctx->res->exiting) {
5475 result = ISC_R_SHUTTINGDOWN;
5482 * XXXRTH We should really get the current time just once. We
5483 * need a routine to convert from an isc_time_t to an
5488 isc_stdtime_get(&now);
5491 * Did the dispatcher have a problem?
5493 if (devent->result != ISC_R_SUCCESS) {
5494 if (devent->result == ISC_R_EOF &&
5495 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5497 * The problem might be that they
5498 * don't understand EDNS0. Turn it
5499 * off and try again.
5501 options |= DNS_FETCHOPT_NOEDNS0;
5504 * Remember that they don't like EDNS0.
5506 dns_adb_changeflags(fctx->adb,
5508 DNS_FETCHOPT_NOEDNS0,
5509 DNS_FETCHOPT_NOEDNS0);
5512 * There's no hope for this query.
5514 keep_trying = ISC_TRUE;
5519 message = fctx->rmessage;
5521 if (query->tsig != NULL) {
5522 result = dns_message_setquerytsig(message, query->tsig);
5523 if (result != ISC_R_SUCCESS)
5527 if (query->tsigkey) {
5528 result = dns_message_settsigkey(message, query->tsigkey);
5529 if (result != ISC_R_SUCCESS)
5533 result = dns_message_parse(message, &devent->buffer, 0);
5534 if (result != ISC_R_SUCCESS) {
5536 case ISC_R_UNEXPECTEDEND:
5537 if (!message->question_ok ||
5538 (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
5539 (options & DNS_FETCHOPT_TCP) != 0) {
5541 * Either the message ended prematurely,
5542 * and/or wasn't marked as being truncated,
5543 * and/or this is a response to a query we
5544 * sent over TCP. In all of these cases,
5545 * something is wrong with the remote
5546 * server and we don't want to retry using
5549 if ((query->options & DNS_FETCHOPT_NOEDNS0)
5552 * The problem might be that they
5553 * don't understand EDNS0. Turn it
5554 * off and try again.
5556 options |= DNS_FETCHOPT_NOEDNS0;
5559 * Remember that they don't like EDNS0.
5561 dns_adb_changeflags(
5564 DNS_FETCHOPT_NOEDNS0,
5565 DNS_FETCHOPT_NOEDNS0);
5567 broken_server = result;
5568 keep_trying = ISC_TRUE;
5573 * We defer retrying via TCP for a bit so we can
5574 * check out this message further.
5576 truncated = ISC_TRUE;
5579 if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5581 * The problem might be that they
5582 * don't understand EDNS0. Turn it
5583 * off and try again.
5585 options |= DNS_FETCHOPT_NOEDNS0;
5588 * Remember that they don't like EDNS0.
5590 dns_adb_changeflags(fctx->adb,
5592 DNS_FETCHOPT_NOEDNS0,
5593 DNS_FETCHOPT_NOEDNS0);
5595 broken_server = DNS_R_UNEXPECTEDRCODE;
5596 keep_trying = ISC_TRUE;
5601 * Something bad has happened.
5608 * Log the incoming packet.
5610 log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
5613 * If the message is signed, check the signature. If not, this
5614 * returns success anyway.
5616 result = dns_message_checksig(message, fctx->res->view);
5617 if (result != ISC_R_SUCCESS)
5621 * The dispatcher should ensure we only get responses with QR set.
5623 INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
5625 * INSIST() that the message comes from the place we sent it to,
5626 * since the dispatch code should ensure this.
5628 * INSIST() that the message id is correct (this should also be
5629 * ensured by the dispatch code).
5634 * Deal with truncated responses by retrying using TCP.
5636 if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
5637 truncated = ISC_TRUE;
5640 if ((options & DNS_FETCHOPT_TCP) != 0) {
5641 broken_server = DNS_R_TRUNCATEDTCP;
5642 keep_trying = ISC_TRUE;
5644 options |= DNS_FETCHOPT_TCP;
5651 * Is it a query response?
5653 if (message->opcode != dns_opcode_query) {
5655 broken_server = DNS_R_UNEXPECTEDOPCODE;
5656 keep_trying = ISC_TRUE;
5661 * Is the remote server broken, or does it dislike us?
5663 if (message->rcode != dns_rcode_noerror &&
5664 message->rcode != dns_rcode_nxdomain) {
5665 if ((message->rcode == dns_rcode_formerr ||
5666 message->rcode == dns_rcode_notimp ||
5667 message->rcode == dns_rcode_servfail) &&
5668 (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
5670 * It's very likely they don't like EDNS0.
5672 * XXXRTH We should check if the question
5673 * we're asking requires EDNS0, and
5674 * if so, we should bail out.
5676 options |= DNS_FETCHOPT_NOEDNS0;
5679 * Remember that they don't like EDNS0.
5681 if (message->rcode != dns_rcode_servfail)
5682 dns_adb_changeflags(fctx->adb, query->addrinfo,
5683 DNS_FETCHOPT_NOEDNS0,
5684 DNS_FETCHOPT_NOEDNS0);
5685 } else if (message->rcode == dns_rcode_formerr) {
5686 if (ISFORWARDER(query->addrinfo)) {
5688 * This forwarder doesn't understand us,
5689 * but other forwarders might. Keep trying.
5691 broken_server = DNS_R_REMOTEFORMERR;
5692 keep_trying = ISC_TRUE;
5695 * The server doesn't understand us. Since
5696 * all servers for a zone need similar
5697 * capabilities, we assume that we will get
5698 * FORMERR from all servers, and thus we
5699 * cannot make any more progress with this
5702 result = DNS_R_FORMERR;
5704 } else if (message->rcode == dns_rcode_yxdomain) {
5706 * DNAME mapping failed because the new name
5707 * was too long. There's no chance of success
5710 result = DNS_R_YXDOMAIN;
5711 } else if (message->rcode == dns_rcode_badvers) {
5712 dns_rdataset_t *opt;
5713 unsigned int flags, mask;
5714 unsigned int version;
5717 opt = dns_message_getopt(message);
5718 version = (opt->ttl >> 16) & 0xff;
5719 flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
5720 DNS_FETCHOPT_EDNSVERSIONSET;
5721 mask = DNS_FETCHOPT_EDNSVERSIONMASK |
5722 DNS_FETCHOPT_EDNSVERSIONSET;
5725 dns_adb_changeflags(fctx->adb, query->addrinfo,
5729 broken_server = DNS_R_BADVERS;
5730 keep_trying = ISC_TRUE;
5737 broken_server = DNS_R_UNEXPECTEDRCODE;
5738 INSIST(broken_server != ISC_R_SUCCESS);
5739 keep_trying = ISC_TRUE;
5745 * Is the question the same as the one we asked?
5747 result = same_question(fctx);
5748 if (result != ISC_R_SUCCESS) {
5750 if (result == DNS_R_FORMERR)
5751 keep_trying = ISC_TRUE;
5756 * Is the server lame?
5758 if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
5760 log_lame(fctx, query->addrinfo);
5761 result = dns_adb_marklame(fctx->adb, query->addrinfo,
5762 &fctx->name, fctx->type,
5763 now + fctx->res->lame_ttl);
5764 if (result != ISC_R_SUCCESS)
5765 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
5766 DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
5767 "could not mark server as lame: %s",
5768 isc_result_totext(result));
5769 broken_server = DNS_R_LAME;
5770 keep_trying = ISC_TRUE;
5775 * Enforce delegations only zones like NET and COM.
5777 if (!ISFORWARDER(query->addrinfo) &&
5778 dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
5779 !dns_name_equal(&fctx->domain, &fctx->name) &&
5780 fix_mustbedelegationornxdomain(message, fctx)) {
5781 char namebuf[DNS_NAME_FORMATSIZE];
5782 char domainbuf[DNS_NAME_FORMATSIZE];
5783 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
5787 dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
5788 dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
5789 dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
5790 dns_rdataclass_format(fctx->res->rdclass, classbuf,
5792 isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
5795 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
5796 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
5797 "enforced delegation-only for '%s' (%s/%s/%s) "
5799 domainbuf, namebuf, typebuf, classbuf, addrbuf);
5802 if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
5803 checknames(message);
5808 fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
5811 * Did we get any answers?
5813 if (message->counts[DNS_SECTION_ANSWER] > 0 &&
5814 (message->rcode == dns_rcode_noerror ||
5815 message->rcode == dns_rcode_nxdomain)) {
5817 * We've got answers. However, if we sent
5818 * a BIND 8 server an NS query, it may have
5819 * incorrectly responded with a non-authoritative
5820 * answer instead of a referral. Since this
5821 * answer lacks the SIGs necessary to do DNSSEC
5822 * validation, we must invoke the following special
5823 * kludge to treat it as a referral.
5825 if (fctx->type == dns_rdatatype_ns &&
5826 (message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
5827 !ISFORWARDER(query->addrinfo))
5829 result = noanswer_response(fctx, NULL, ISC_TRUE);
5830 if (result != DNS_R_DELEGATION) {
5832 * The answer section must have contained
5833 * something other than the NS records
5834 * we asked for. Since AA is not set
5835 * and the server is not a forwarder,
5836 * it is technically lame and it's easier
5837 * to treat it as such than to figure out
5838 * some more elaborate course of action.
5840 broken_server = DNS_R_LAME;
5841 keep_trying = ISC_TRUE;
5844 goto force_referral;
5846 result = answer_response(fctx);
5847 if (result != ISC_R_SUCCESS) {
5848 if (result == DNS_R_FORMERR)
5849 keep_trying = ISC_TRUE;
5852 } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
5853 message->rcode == dns_rcode_noerror ||
5854 message->rcode == dns_rcode_nxdomain) {
5856 * NXDOMAIN, NXRDATASET, or referral.
5858 result = noanswer_response(fctx, NULL, ISC_FALSE);
5859 if (result == DNS_R_CHASEDSSERVERS) {
5860 } else if (result == DNS_R_DELEGATION) {
5863 * We don't have the answer, but we know a better
5866 get_nameservers = ISC_TRUE;
5867 keep_trying = ISC_TRUE;
5869 * We have a new set of name servers, and it
5870 * has not experienced any restarts yet.
5873 result = ISC_R_SUCCESS;
5874 } else if (result != ISC_R_SUCCESS) {
5876 * Something has gone wrong.
5878 if (result == DNS_R_FORMERR)
5879 keep_trying = ISC_TRUE;
5884 * The server is insane.
5887 broken_server = DNS_R_UNEXPECTEDRCODE;
5888 keep_trying = ISC_TRUE;
5893 * Follow additional section data chains.
5895 chase_additional(fctx);
5898 * Cache the cacheable parts of the message. This may also cause
5899 * work to be queued to the DNSSEC validator.
5901 if (WANTCACHE(fctx)) {
5902 result = cache_message(fctx, query->addrinfo, now);
5903 if (result != ISC_R_SUCCESS)
5908 * Ncache the negatively cacheable parts of the message. This may
5909 * also cause work to be queued to the DNSSEC validator.
5911 if (WANTNCACHE(fctx)) {
5912 dns_rdatatype_t covers;
5913 if (message->rcode == dns_rcode_nxdomain)
5914 covers = dns_rdatatype_any;
5916 covers = fctx->type;
5919 * Cache any negative cache entries in the message.
5921 result = ncache_message(fctx, query->addrinfo, covers, now);
5926 * Remember the query's addrinfo, in case we need to mark the
5929 addrinfo = query->addrinfo;
5934 * XXXRTH Don't cancel the query if waiting for validation?
5936 fctx_cancelquery(&query, &devent, finish, ISC_FALSE);
5939 if (result == DNS_R_FORMERR)
5940 broken_server = DNS_R_FORMERR;
5941 if (broken_server != ISC_R_SUCCESS) {
5943 * Add this server to the list of bad servers for
5946 add_bad(fctx, addrinfo, broken_server);
5949 if (get_nameservers) {
5951 dns_fixedname_init(&foundname);
5952 fname = dns_fixedname_name(&foundname);
5953 if (result != ISC_R_SUCCESS) {
5954 fctx_done(fctx, DNS_R_SERVFAIL);
5958 if (dns_rdatatype_atparent(fctx->type))
5959 findoptions |= DNS_DBFIND_NOEXACT;
5960 if ((options & DNS_FETCHOPT_UNSHARED) == 0)
5963 name = &fctx->domain;
5964 result = dns_view_findzonecut(fctx->res->view,
5970 if (result != ISC_R_SUCCESS) {
5971 FCTXTRACE("couldn't find a zonecut");
5972 fctx_done(fctx, DNS_R_SERVFAIL);
5975 if (!dns_name_issubdomain(fname, &fctx->domain)) {
5977 * The best nameservers are now above our
5980 FCTXTRACE("nameservers now above QDOMAIN");
5981 fctx_done(fctx, DNS_R_SERVFAIL);
5984 dns_name_free(&fctx->domain,
5985 fctx->res->buckets[fctx->bucketnum].mctx);
5986 dns_name_init(&fctx->domain, NULL);
5987 result = dns_name_dup(fname,
5988 fctx->res->buckets[fctx->bucketnum].mctx,
5990 if (result != ISC_R_SUCCESS) {
5991 fctx_done(fctx, DNS_R_SERVFAIL);
5994 fctx_cancelqueries(fctx, ISC_TRUE);
5995 fctx_cleanupfinds(fctx);
5996 fctx_cleanupaltfinds(fctx);
5997 fctx_cleanupforwaddrs(fctx);
5998 fctx_cleanupaltaddrs(fctx);
6004 } else if (resend) {
6006 * Resend (probably with changed options).
6008 FCTXTRACE("resend");
6009 result = fctx_query(fctx, addrinfo, options);
6010 if (result != ISC_R_SUCCESS)
6011 fctx_done(fctx, result);
6012 } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
6014 * All has gone well so far, but we are waiting for the
6015 * DNSSEC validator to validate the answer.
6017 FCTXTRACE("wait for validator");
6018 fctx_cancelqueries(fctx, ISC_TRUE);
6020 * We must not retransmit while the validator is working;
6021 * it has references to the current rmessage.
6023 result = fctx_stopidletimer(fctx);
6024 if (result != ISC_R_SUCCESS)
6025 fctx_done(fctx, result);
6026 } else if (result == DNS_R_CHASEDSSERVERS) {
6028 add_bad(fctx, addrinfo, result);
6029 fctx_cancelqueries(fctx, ISC_TRUE);
6030 fctx_cleanupfinds(fctx);
6031 fctx_cleanupforwaddrs(fctx);
6033 n = dns_name_countlabels(&fctx->name);
6034 dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
6036 FCTXTRACE("suspending DS lookup to find parent's NS records");
6038 result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
6040 NULL, NULL, NULL, 0, task,
6041 resume_dslookup, fctx,
6042 &fctx->nsrrset, NULL,
6044 if (result != ISC_R_SUCCESS)
6045 fctx_done(fctx, result);
6046 LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
6048 UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
6049 result = fctx_stopidletimer(fctx);
6050 if (result != ISC_R_SUCCESS)
6051 fctx_done(fctx, result);
6056 fctx_done(fctx, result);
6062 *** Resolver Methods
6066 destroy(dns_resolver_t *res) {
6070 REQUIRE(res->references == 0);
6071 REQUIRE(!res->priming);
6072 REQUIRE(res->primefetch == NULL);
6076 INSIST(res->nfctx == 0);
6078 DESTROYLOCK(&res->primelock);
6079 DESTROYLOCK(&res->nlock);
6080 DESTROYLOCK(&res->lock);
6081 for (i = 0; i < res->nbuckets; i++) {
6082 INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
6083 isc_task_shutdown(res->buckets[i].task);
6084 isc_task_detach(&res->buckets[i].task);
6085 DESTROYLOCK(&res->buckets[i].lock);
6086 isc_mem_detach(&res->buckets[i].mctx);
6088 isc_mem_put(res->mctx, res->buckets,
6089 res->nbuckets * sizeof(fctxbucket_t));
6090 if (res->dispatchv4 != NULL)
6091 dns_dispatch_detach(&res->dispatchv4);
6092 if (res->dispatchv6 != NULL)
6093 dns_dispatch_detach(&res->dispatchv6);
6094 while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
6095 ISC_LIST_UNLINK(res->alternates, a, link);
6097 dns_name_free(&a->_u._n.name, res->mctx);
6098 isc_mem_put(res->mctx, a, sizeof(*a));
6100 dns_resolver_reset_algorithms(res);
6101 dns_resolver_resetmustbesecure(res);
6103 isc_rwlock_destroy(&res->alglock);
6106 isc_rwlock_destroy(&res->mbslock);
6108 isc_timer_detach(&res->spillattimer);
6110 isc_mem_put(res->mctx, res, sizeof(*res));
6114 send_shutdown_events(dns_resolver_t *res) {
6115 isc_event_t *event, *next_event;
6119 * Caller must be holding the resolver lock.
6122 for (event = ISC_LIST_HEAD(res->whenshutdown);
6124 event = next_event) {
6125 next_event = ISC_LIST_NEXT(event, ev_link);
6126 ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
6127 etask = event->ev_sender;
6128 event->ev_sender = res;
6129 isc_task_sendanddetach(&etask, &event);
6134 empty_bucket(dns_resolver_t *res) {
6135 RTRACE("empty_bucket");
6139 INSIST(res->activebuckets > 0);
6140 res->activebuckets--;
6141 if (res->activebuckets == 0)
6142 send_shutdown_events(res);
6148 spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
6149 dns_resolver_t *res = event->ev_arg;
6150 isc_result_t result;
6152 isc_boolean_t logit = ISC_FALSE;
6154 REQUIRE(VALID_RESOLVER(res));
6159 INSIST(!res->exiting);
6160 if (res->spillat > res->spillatmin) {
6164 if (res->spillat <= res->spillatmin) {
6165 result = isc_timer_reset(res->spillattimer,
6166 isc_timertype_inactive, NULL,
6168 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6170 count = res->spillat;
6173 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6174 DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
6175 "clients-per-query decreased to %u", count);
6177 isc_event_free(&event);
6181 dns_resolver_create(dns_view_t *view,
6182 isc_taskmgr_t *taskmgr, unsigned int ntasks,
6183 isc_socketmgr_t *socketmgr,
6184 isc_timermgr_t *timermgr,
6185 unsigned int options,
6186 dns_dispatchmgr_t *dispatchmgr,
6187 dns_dispatch_t *dispatchv4,
6188 dns_dispatch_t *dispatchv6,
6189 dns_resolver_t **resp)
6191 dns_resolver_t *res;
6192 isc_result_t result = ISC_R_SUCCESS;
6193 unsigned int i, buckets_created = 0;
6194 isc_task_t *task = NULL;
6198 * Create a resolver.
6201 REQUIRE(DNS_VIEW_VALID(view));
6202 REQUIRE(ntasks > 0);
6203 REQUIRE(resp != NULL && *resp == NULL);
6204 REQUIRE(dispatchmgr != NULL);
6205 REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
6207 res = isc_mem_get(view->mctx, sizeof(*res));
6209 return (ISC_R_NOMEMORY);
6211 res->mctx = view->mctx;
6212 res->rdclass = view->rdclass;
6213 res->socketmgr = socketmgr;
6214 res->timermgr = timermgr;
6215 res->taskmgr = taskmgr;
6216 res->dispatchmgr = dispatchmgr;
6218 res->options = options;
6220 ISC_LIST_INIT(res->alternates);
6221 res->udpsize = RECV_BUFFER_SIZE;
6222 res->algorithms = NULL;
6223 res->mustbesecure = NULL;
6224 res->spillatmin = res->spillat = 10;
6225 res->spillatmax = 100;
6226 res->spillattimer = NULL;
6227 res->zero_no_soa_ttl = ISC_FALSE;
6229 res->nbuckets = ntasks;
6230 res->activebuckets = ntasks;
6231 res->buckets = isc_mem_get(view->mctx,
6232 ntasks * sizeof(fctxbucket_t));
6233 if (res->buckets == NULL) {
6234 result = ISC_R_NOMEMORY;
6237 for (i = 0; i < ntasks; i++) {
6238 result = isc_mutex_init(&res->buckets[i].lock);
6239 if (result != ISC_R_SUCCESS)
6240 goto cleanup_buckets;
6241 res->buckets[i].task = NULL;
6242 result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
6243 if (result != ISC_R_SUCCESS) {
6244 DESTROYLOCK(&res->buckets[i].lock);
6245 goto cleanup_buckets;
6247 res->buckets[i].mctx = NULL;
6248 result = isc_mem_create(0, 0, &res->buckets[i].mctx);
6249 if (result != ISC_R_SUCCESS) {
6250 isc_task_detach(&res->buckets[i].task);
6251 DESTROYLOCK(&res->buckets[i].lock);
6252 goto cleanup_buckets;
6254 snprintf(name, sizeof(name), "res%u", i);
6255 isc_task_setname(res->buckets[i].task, name, res);
6256 ISC_LIST_INIT(res->buckets[i].fctxs);
6257 res->buckets[i].exiting = ISC_FALSE;
6261 res->dispatchv4 = NULL;
6262 if (dispatchv4 != NULL)
6263 dns_dispatch_attach(dispatchv4, &res->dispatchv4);
6264 res->dispatchv6 = NULL;
6265 if (dispatchv6 != NULL)
6266 dns_dispatch_attach(dispatchv6, &res->dispatchv6);
6268 res->references = 1;
6269 res->exiting = ISC_FALSE;
6270 res->frozen = ISC_FALSE;
6271 ISC_LIST_INIT(res->whenshutdown);
6272 res->priming = ISC_FALSE;
6273 res->primefetch = NULL;
6276 result = isc_mutex_init(&res->lock);
6277 if (result != ISC_R_SUCCESS)
6278 goto cleanup_dispatches;
6280 result = isc_mutex_init(&res->nlock);
6281 if (result != ISC_R_SUCCESS)
6284 result = isc_mutex_init(&res->primelock);
6285 if (result != ISC_R_SUCCESS)
6289 result = isc_task_create(taskmgr, 0, &task);
6290 if (result != ISC_R_SUCCESS)
6291 goto cleanup_primelock;
6293 result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
6294 task, spillattimer_countdown, res,
6295 &res->spillattimer);
6296 isc_task_detach(&task);
6297 if (result != ISC_R_SUCCESS)
6298 goto cleanup_primelock;
6301 result = isc_rwlock_init(&res->alglock, 0, 0);
6302 if (result != ISC_R_SUCCESS)
6303 goto cleanup_spillattimer;
6306 result = isc_rwlock_init(&res->mbslock, 0, 0);
6307 if (result != ISC_R_SUCCESS)
6308 goto cleanup_alglock;
6311 res->magic = RES_MAGIC;
6315 return (ISC_R_SUCCESS);
6320 isc_rwlock_destroy(&res->alglock);
6323 #if USE_ALGLOCK || USE_MBSLOCK
6324 cleanup_spillattimer:
6325 isc_timer_detach(&res->spillattimer);
6329 DESTROYLOCK(&res->primelock);
6332 DESTROYLOCK(&res->nlock);
6335 DESTROYLOCK(&res->lock);
6338 if (res->dispatchv6 != NULL)
6339 dns_dispatch_detach(&res->dispatchv6);
6340 if (res->dispatchv4 != NULL)
6341 dns_dispatch_detach(&res->dispatchv4);
6344 for (i = 0; i < buckets_created; i++) {
6345 isc_mem_detach(&res->buckets[i].mctx);
6346 DESTROYLOCK(&res->buckets[i].lock);
6347 isc_task_shutdown(res->buckets[i].task);
6348 isc_task_detach(&res->buckets[i].task);
6350 isc_mem_put(view->mctx, res->buckets,
6351 res->nbuckets * sizeof(fctxbucket_t));
6354 isc_mem_put(view->mctx, res, sizeof(*res));
6360 prime_done(isc_task_t *task, isc_event_t *event) {
6361 dns_resolver_t *res;
6362 dns_fetchevent_t *fevent;
6364 dns_db_t *db = NULL;
6366 REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
6367 fevent = (dns_fetchevent_t *)event;
6368 res = event->ev_arg;
6369 REQUIRE(VALID_RESOLVER(res));
6375 INSIST(res->priming);
6376 res->priming = ISC_FALSE;
6377 LOCK(&res->primelock);
6378 fetch = res->primefetch;
6379 res->primefetch = NULL;
6380 UNLOCK(&res->primelock);
6384 if (fevent->result == ISC_R_SUCCESS &&
6385 res->view->cache != NULL && res->view->hints != NULL) {
6386 dns_cache_attachdb(res->view->cache, &db);
6387 dns_root_checkhints(res->view, res->view->hints, db);
6391 if (fevent->node != NULL)
6392 dns_db_detachnode(fevent->db, &fevent->node);
6393 if (fevent->db != NULL)
6394 dns_db_detach(&fevent->db);
6395 if (dns_rdataset_isassociated(fevent->rdataset))
6396 dns_rdataset_disassociate(fevent->rdataset);
6397 INSIST(fevent->sigrdataset == NULL);
6399 isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
6401 isc_event_free(&event);
6402 dns_resolver_destroyfetch(&fetch);
6406 dns_resolver_prime(dns_resolver_t *res) {
6407 isc_boolean_t want_priming = ISC_FALSE;
6408 dns_rdataset_t *rdataset;
6409 isc_result_t result;
6411 REQUIRE(VALID_RESOLVER(res));
6412 REQUIRE(res->frozen);
6414 RTRACE("dns_resolver_prime");
6418 if (!res->exiting && !res->priming) {
6419 INSIST(res->primefetch == NULL);
6420 res->priming = ISC_TRUE;
6421 want_priming = ISC_TRUE;
6428 * To avoid any possible recursive locking problems, we
6429 * start the priming fetch like any other fetch, and holding
6430 * no resolver locks. No one else will try to start it
6431 * because we're the ones who set res->priming to true.
6432 * Any other callers of dns_resolver_prime() while we're
6433 * running will see that res->priming is already true and
6437 rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
6438 if (rdataset == NULL) {
6440 INSIST(res->priming);
6441 INSIST(res->primefetch == NULL);
6442 res->priming = ISC_FALSE;
6446 dns_rdataset_init(rdataset);
6447 LOCK(&res->primelock);
6448 result = dns_resolver_createfetch(res, dns_rootname,
6450 NULL, NULL, NULL, 0,
6451 res->buckets[0].task,
6453 res, rdataset, NULL,
6455 UNLOCK(&res->primelock);
6456 if (result != ISC_R_SUCCESS) {
6458 INSIST(res->priming);
6459 res->priming = ISC_FALSE;
6466 dns_resolver_freeze(dns_resolver_t *res) {
6472 REQUIRE(VALID_RESOLVER(res));
6473 REQUIRE(!res->frozen);
6475 res->frozen = ISC_TRUE;
6479 dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
6480 REQUIRE(VALID_RESOLVER(source));
6481 REQUIRE(targetp != NULL && *targetp == NULL);
6483 RRTRACE(source, "attach");
6484 LOCK(&source->lock);
6485 REQUIRE(!source->exiting);
6487 INSIST(source->references > 0);
6488 source->references++;
6489 INSIST(source->references != 0);
6490 UNLOCK(&source->lock);
6496 dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
6497 isc_event_t **eventp)
6502 REQUIRE(VALID_RESOLVER(res));
6503 REQUIRE(eventp != NULL);
6510 if (res->exiting && res->activebuckets == 0) {
6512 * We're already shutdown. Send the event.
6514 event->ev_sender = res;
6515 isc_task_send(task, &event);
6518 isc_task_attach(task, &clone);
6519 event->ev_sender = clone;
6520 ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
6527 dns_resolver_shutdown(dns_resolver_t *res) {
6531 isc_result_t result;
6533 REQUIRE(VALID_RESOLVER(res));
6539 if (!res->exiting) {
6541 res->exiting = ISC_TRUE;
6543 for (i = 0; i < res->nbuckets; i++) {
6544 LOCK(&res->buckets[i].lock);
6545 for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
6547 fctx = ISC_LIST_NEXT(fctx, link))
6548 fctx_shutdown(fctx);
6549 if (res->dispatchv4 != NULL) {
6550 sock = dns_dispatch_getsocket(res->dispatchv4);
6551 isc_socket_cancel(sock, res->buckets[i].task,
6552 ISC_SOCKCANCEL_ALL);
6554 if (res->dispatchv6 != NULL) {
6555 sock = dns_dispatch_getsocket(res->dispatchv6);
6556 isc_socket_cancel(sock, res->buckets[i].task,
6557 ISC_SOCKCANCEL_ALL);
6559 res->buckets[i].exiting = ISC_TRUE;
6560 if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
6561 INSIST(res->activebuckets > 0);
6562 res->activebuckets--;
6564 UNLOCK(&res->buckets[i].lock);
6566 if (res->activebuckets == 0)
6567 send_shutdown_events(res);
6568 result = isc_timer_reset(res->spillattimer,
6569 isc_timertype_inactive, NULL,
6571 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6578 dns_resolver_detach(dns_resolver_t **resp) {
6579 dns_resolver_t *res;
6580 isc_boolean_t need_destroy = ISC_FALSE;
6582 REQUIRE(resp != NULL);
6584 REQUIRE(VALID_RESOLVER(res));
6590 INSIST(res->references > 0);
6592 if (res->references == 0) {
6593 INSIST(res->exiting && res->activebuckets == 0);
6594 need_destroy = ISC_TRUE;
6605 static inline isc_boolean_t
6606 fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
6607 unsigned int options)
6609 if (fctx->type != type || fctx->options != options)
6611 return (dns_name_equal(&fctx->name, name));
6615 log_fetch(dns_name_t *name, dns_rdatatype_t type) {
6616 char namebuf[DNS_NAME_FORMATSIZE];
6617 char typebuf[DNS_RDATATYPE_FORMATSIZE];
6618 int level = ISC_LOG_DEBUG(1);
6620 if (! isc_log_wouldlog(dns_lctx, level))
6623 dns_name_format(name, namebuf, sizeof(namebuf));
6624 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
6626 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
6627 DNS_LOGMODULE_RESOLVER, level,
6628 "createfetch: %s %s", namebuf, typebuf);
6632 dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
6633 dns_rdatatype_t type,
6634 dns_name_t *domain, dns_rdataset_t *nameservers,
6635 dns_forwarders_t *forwarders,
6636 unsigned int options, isc_task_t *task,
6637 isc_taskaction_t action, void *arg,
6638 dns_rdataset_t *rdataset,
6639 dns_rdataset_t *sigrdataset,
6640 dns_fetch_t **fetchp)
6642 return (dns_resolver_createfetch2(res, name, type, domain,
6643 nameservers, forwarders, NULL, 0,
6644 options, task, action, arg,
6645 rdataset, sigrdataset, fetchp));
6649 dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
6650 dns_rdatatype_t type,
6651 dns_name_t *domain, dns_rdataset_t *nameservers,
6652 dns_forwarders_t *forwarders,
6653 isc_sockaddr_t *client, dns_messageid_t id,
6654 unsigned int options, isc_task_t *task,
6655 isc_taskaction_t action, void *arg,
6656 dns_rdataset_t *rdataset,
6657 dns_rdataset_t *sigrdataset,
6658 dns_fetch_t **fetchp)
6661 fetchctx_t *fctx = NULL;
6662 isc_result_t result = ISC_R_SUCCESS;
6663 unsigned int bucketnum;
6664 isc_boolean_t new_fctx = ISC_FALSE;
6666 unsigned int count = 0;
6667 unsigned int spillat;
6671 REQUIRE(VALID_RESOLVER(res));
6672 REQUIRE(res->frozen);
6673 /* XXXRTH Check for meta type */
6674 if (domain != NULL) {
6675 REQUIRE(DNS_RDATASET_VALID(nameservers));
6676 REQUIRE(nameservers->type == dns_rdatatype_ns);
6678 REQUIRE(nameservers == NULL);
6679 REQUIRE(forwarders == NULL);
6680 REQUIRE(!dns_rdataset_isassociated(rdataset));
6681 REQUIRE(sigrdataset == NULL ||
6682 !dns_rdataset_isassociated(sigrdataset));
6683 REQUIRE(fetchp != NULL && *fetchp == NULL);
6685 log_fetch(name, type);
6688 * XXXRTH use a mempool?
6690 fetch = isc_mem_get(res->mctx, sizeof(*fetch));
6692 return (ISC_R_NOMEMORY);
6694 bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
6697 spillat = res->spillat;
6699 LOCK(&res->buckets[bucketnum].lock);
6701 if (res->buckets[bucketnum].exiting) {
6702 result = ISC_R_SHUTTINGDOWN;
6706 if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
6707 for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
6709 fctx = ISC_LIST_NEXT(fctx, link)) {
6710 if (fctx_match(fctx, name, type, options))
6716 * Is this a duplicate?
6718 if (fctx != NULL && client != NULL) {
6719 dns_fetchevent_t *fevent;
6720 for (fevent = ISC_LIST_HEAD(fctx->events);
6722 fevent = ISC_LIST_NEXT(fevent, ev_link)) {
6723 if (fevent->client != NULL && fevent->id == id &&
6724 isc_sockaddr_equal(fevent->client, client)) {
6725 result = DNS_R_DUPLICATE;
6731 if (count >= res->spillatmin && res->spillatmin != 0) {
6732 if (count >= spillat)
6733 fctx->spilled = ISC_TRUE;
6734 if (fctx->spilled) {
6735 result = DNS_R_DROP;
6741 * If we didn't have a fetch, would attach to a done fetch, this
6742 * fetch has already cloned its results, or if the fetch has gone
6743 * "idle" (no one was interested in it), we need to start a new
6744 * fetch instead of joining with the existing one.
6747 fctx->state == fetchstate_done ||
6749 ISC_LIST_EMPTY(fctx->events)) {
6751 result = fctx_create(res, name, type, domain, nameservers,
6752 options, bucketnum, &fctx);
6753 if (result != ISC_R_SUCCESS)
6755 new_fctx = ISC_TRUE;
6758 result = fctx_join(fctx, task, client, id, action, arg,
6759 rdataset, sigrdataset, fetch);
6761 if (result == ISC_R_SUCCESS) {
6765 event = &fctx->control_event;
6766 ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
6767 DNS_EVENT_FETCHCONTROL,
6768 fctx_start, fctx, NULL,
6770 isc_task_send(res->buckets[bucketnum].task, &event);
6773 * We don't care about the result of fctx_destroy()
6774 * since we know we're not exiting.
6776 (void)fctx_destroy(fctx);
6781 UNLOCK(&res->buckets[bucketnum].lock);
6783 if (result == ISC_R_SUCCESS) {
6787 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
6793 dns_resolver_cancelfetch(dns_fetch_t *fetch) {
6795 dns_resolver_t *res;
6796 dns_fetchevent_t *event, *next_event;
6799 REQUIRE(DNS_FETCH_VALID(fetch));
6800 fctx = fetch->private;
6801 REQUIRE(VALID_FCTX(fctx));
6804 FTRACE("cancelfetch");
6806 LOCK(&res->buckets[fctx->bucketnum].lock);
6809 * Find the completion event for this fetch (as opposed
6810 * to those for other fetches that have joined the same
6811 * fctx) and send it with result = ISC_R_CANCELED.
6814 if (fctx->state != fetchstate_done) {
6815 for (event = ISC_LIST_HEAD(fctx->events);
6817 event = next_event) {
6818 next_event = ISC_LIST_NEXT(event, ev_link);
6819 if (event->fetch == fetch) {
6820 ISC_LIST_UNLINK(fctx->events, event, ev_link);
6825 if (event != NULL) {
6826 etask = event->ev_sender;
6827 event->ev_sender = fctx;
6828 event->result = ISC_R_CANCELED;
6829 isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
6832 * The fctx continues running even if no fetches remain;
6833 * the answer is still cached.
6836 UNLOCK(&res->buckets[fctx->bucketnum].lock);
6840 dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
6842 dns_resolver_t *res;
6843 dns_fetchevent_t *event, *next_event;
6845 unsigned int bucketnum;
6846 isc_boolean_t bucket_empty = ISC_FALSE;
6848 REQUIRE(fetchp != NULL);
6850 REQUIRE(DNS_FETCH_VALID(fetch));
6851 fctx = fetch->private;
6852 REQUIRE(VALID_FCTX(fctx));
6855 FTRACE("destroyfetch");
6857 bucketnum = fctx->bucketnum;
6858 LOCK(&res->buckets[bucketnum].lock);
6861 * Sanity check: the caller should have gotten its event before
6862 * trying to destroy the fetch.
6865 if (fctx->state != fetchstate_done) {
6866 for (event = ISC_LIST_HEAD(fctx->events);
6868 event = next_event) {
6869 next_event = ISC_LIST_NEXT(event, ev_link);
6870 RUNTIME_CHECK(event->fetch != fetch);
6874 INSIST(fctx->references > 0);
6876 if (fctx->references == 0) {
6878 * No one cares about the result of this fetch anymore.
6880 if (fctx->pending == 0 && fctx->nqueries == 0 &&
6881 ISC_LIST_EMPTY(fctx->validators) &&
6882 SHUTTINGDOWN(fctx)) {
6884 * This fctx is already shutdown; we were just
6885 * waiting for the last reference to go away.
6887 bucket_empty = fctx_destroy(fctx);
6890 * Initiate shutdown.
6892 fctx_shutdown(fctx);
6896 UNLOCK(&res->buckets[bucketnum].lock);
6898 isc_mem_put(res->mctx, fetch, sizeof(*fetch));
6906 dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
6907 REQUIRE(VALID_RESOLVER(resolver));
6908 return (resolver->dispatchmgr);
6912 dns_resolver_dispatchv4(dns_resolver_t *resolver) {
6913 REQUIRE(VALID_RESOLVER(resolver));
6914 return (resolver->dispatchv4);
6918 dns_resolver_dispatchv6(dns_resolver_t *resolver) {
6919 REQUIRE(VALID_RESOLVER(resolver));
6920 return (resolver->dispatchv6);
6924 dns_resolver_socketmgr(dns_resolver_t *resolver) {
6925 REQUIRE(VALID_RESOLVER(resolver));
6926 return (resolver->socketmgr);
6930 dns_resolver_taskmgr(dns_resolver_t *resolver) {
6931 REQUIRE(VALID_RESOLVER(resolver));
6932 return (resolver->taskmgr);
6936 dns_resolver_getlamettl(dns_resolver_t *resolver) {
6937 REQUIRE(VALID_RESOLVER(resolver));
6938 return (resolver->lame_ttl);
6942 dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
6943 REQUIRE(VALID_RESOLVER(resolver));
6944 resolver->lame_ttl = lame_ttl;
6948 dns_resolver_nrunning(dns_resolver_t *resolver) {
6950 LOCK(&resolver->nlock);
6951 n = resolver->nfctx;
6952 UNLOCK(&resolver->nlock);
6957 dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
6958 dns_name_t *name, in_port_t port) {
6960 isc_result_t result;
6962 REQUIRE(VALID_RESOLVER(resolver));
6963 REQUIRE(!resolver->frozen);
6964 REQUIRE((alt == NULL) ^ (name == NULL));
6966 a = isc_mem_get(resolver->mctx, sizeof(*a));
6968 return (ISC_R_NOMEMORY);
6970 a->isaddress = ISC_TRUE;
6973 a->isaddress = ISC_FALSE;
6974 a->_u._n.port = port;
6975 dns_name_init(&a->_u._n.name, NULL);
6976 result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
6977 if (result != ISC_R_SUCCESS) {
6978 isc_mem_put(resolver->mctx, a, sizeof(*a));
6982 ISC_LINK_INIT(a, link);
6983 ISC_LIST_APPEND(resolver->alternates, a, link);
6985 return (ISC_R_SUCCESS);
6989 dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
6990 REQUIRE(VALID_RESOLVER(resolver));
6991 resolver->udpsize = udpsize;
6995 dns_resolver_getudpsize(dns_resolver_t *resolver) {
6996 REQUIRE(VALID_RESOLVER(resolver));
6997 return (resolver->udpsize);
7001 free_algorithm(void *node, void *arg) {
7002 unsigned char *algorithms = node;
7003 isc_mem_t *mctx = arg;
7005 isc_mem_put(mctx, algorithms, *algorithms);
7009 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
7011 REQUIRE(VALID_RESOLVER(resolver));
7014 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
7016 if (resolver->algorithms != NULL)
7017 dns_rbt_destroy(&resolver->algorithms);
7019 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
7024 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
7027 unsigned int len, mask;
7029 unsigned char *algorithms;
7030 isc_result_t result;
7031 dns_rbtnode_t *node = NULL;
7033 REQUIRE(VALID_RESOLVER(resolver));
7035 return (ISC_R_RANGE);
7038 RWLOCK(&resolver->alglock, isc_rwlocktype_write);
7040 if (resolver->algorithms == NULL) {
7041 result = dns_rbt_create(resolver->mctx, free_algorithm,
7042 resolver->mctx, &resolver->algorithms);
7043 if (result != ISC_R_SUCCESS)
7048 mask = 1 << (alg%8);
7050 result = dns_rbt_addnode(resolver->algorithms, name, &node);
7052 if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
7053 algorithms = node->data;
7054 if (algorithms == NULL || len > *algorithms) {
7055 new = isc_mem_get(resolver->mctx, len);
7057 result = ISC_R_NOMEMORY;
7060 memset(new, 0, len);
7061 if (algorithms != NULL)
7062 memcpy(new, algorithms, *algorithms);
7066 if (algorithms != NULL)
7067 isc_mem_put(resolver->mctx, algorithms,
7070 algorithms[len-1] |= mask;
7072 result = ISC_R_SUCCESS;
7075 RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
7081 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
7084 unsigned int len, mask;
7085 unsigned char *algorithms;
7087 isc_result_t result;
7088 isc_boolean_t found = ISC_FALSE;
7090 REQUIRE(VALID_RESOLVER(resolver));
7093 RWLOCK(&resolver->alglock, isc_rwlocktype_read);
7095 if (resolver->algorithms == NULL)
7097 result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
7098 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
7100 mask = 1 << (alg%8);
7102 if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
7107 RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
7111 return (dst_algorithm_supported(alg));
7115 dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
7118 return (dns_ds_digest_supported(digest));
7122 dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
7124 REQUIRE(VALID_RESOLVER(resolver));
7127 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
7129 if (resolver->mustbesecure != NULL)
7130 dns_rbt_destroy(&resolver->mustbesecure);
7132 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
7136 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
7139 dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
7140 isc_boolean_t value)
7142 isc_result_t result;
7144 REQUIRE(VALID_RESOLVER(resolver));
7147 RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
7149 if (resolver->mustbesecure == NULL) {
7150 result = dns_rbt_create(resolver->mctx, NULL, NULL,
7151 &resolver->mustbesecure);
7152 if (result != ISC_R_SUCCESS)
7155 result = dns_rbt_addname(resolver->mustbesecure, name,
7156 value ? &yes : &no);
7159 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
7165 dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
7167 isc_boolean_t value = ISC_FALSE;
7168 isc_result_t result;
7170 REQUIRE(VALID_RESOLVER(resolver));
7173 RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
7175 if (resolver->mustbesecure == NULL)
7177 result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
7178 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
7179 value = *(isc_boolean_t*)data;
7182 RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
7188 dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
7189 isc_uint32_t *min, isc_uint32_t *max)
7191 REQUIRE(VALID_RESOLVER(resolver));
7193 LOCK(&resolver->lock);
7195 *cur = resolver->spillat;
7197 *min = resolver->spillatmin;
7199 *max = resolver->spillatmax;
7200 UNLOCK(&resolver->lock);
7204 dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
7207 REQUIRE(VALID_RESOLVER(resolver));
7209 LOCK(&resolver->lock);
7210 resolver->spillatmin = resolver->spillat = min;
7211 resolver->spillatmax = max;
7212 UNLOCK(&resolver->lock);
7216 dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
7217 REQUIRE(VALID_RESOLVER(resolver));
7219 return (resolver->zero_no_soa_ttl);
7223 dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
7224 REQUIRE(VALID_RESOLVER(resolver));
7226 resolver->zero_no_soa_ttl = state;