resolver.c revision 146057d7e755d646283adfe5d813f756b0538095
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Copyright (C) 1999-2003 Internet Software Consortium.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Permission to use, copy, modify, and/or distribute this software for any
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * purpose with or without fee is hereby granted, provided that the above
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * copyright notice and this permission notice appear in all copies.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * PERFORMANCE OF THIS SOFTWARE.
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer/* $Id: resolver.c,v 1.438 2011/11/02 23:42:33 marka Exp $ */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define RRTRACE(r, m) isc_log_write(dns_lctx, \
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer "res %p: %s", (r), (m))
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define FCTXTRACE(m) isc_log_write(dns_lctx, \
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer "fctx %p(%s): %s %s", \
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer "fetch %p (fctx %p(%s)): %s", \
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer "resquery %p (fctx %p(%s)): %s", \
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define DEFAULT_QUERY_TIMEOUT 10 /* The default time in seconds for the whole query to live. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Maximum EDNS0 input packet size.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * This defines the maximum number of timeouts we will permit before we
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * disable EDNS0 on the query.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyertypedef struct query {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Locked by task event serialization. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int magic;
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence unsigned int sends;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define RESQUERY_CANCELED(q) (((q)->attributes & \
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyertypedef enum {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer fetchstate_init = 0, /*%< Start event has not run yet. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer fetchstate_done /*%< FETCHDONE events posted. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyertypedef enum {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /*% Not locked. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned int magic;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*% Locked by appropriate bucket lock. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*% Locked by task event serialization. */
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer * The number of events we're waiting for.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * The number of times we've "restarted" the current
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * nameserver set. This acts as a failsafe to prevent
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * us from pounding constantly on a particular set of
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * servers that, for whatever reason, are not giving
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * us useful responses, but are responding in such a
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * way that they are not marked "bad".
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * The number of timeouts that have occurred since we
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * last successfully received a response packet. This
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * is used for EDNS0 black hole detection.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Look aside state for DS lookups.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Number of queries that reference this context.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * The reason to print when logging a successful
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * response to a query.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer const char * reason;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Random numbers to use for mixing up server addresses.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Fetch-local statistics for detailed logging.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_result_t vresult; /*%< validation result */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int neterr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int adberr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyertypedef struct {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int magic;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyertypedef struct fctxbucket {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyertypedef struct alternate {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /* Unlocked. */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer unsigned int magic;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer unsigned int ndisps;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /* Locked by lock. */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer unsigned int spillat; /* clients-per-query */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /* Bad cache. */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /* Locked by primelock. */
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer /* Locked by nlock. */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer unsigned int nfctx;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * which we also use as an addrinfo flag.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void empty_bucket(dns_resolver_t *res);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic isc_result_t resquery_send(resquery_t *query);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void resquery_response(isc_task_t *task, isc_event_t *event);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void resquery_connected(isc_task_t *task, isc_event_t *event);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic isc_boolean_t fctx_destroy(fetchctx_t *fctx);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic isc_result_t ncache_adderesult(dns_message_t *message,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void validated(isc_task_t *task, isc_event_t *event);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * Increment resolver-related statistics counters.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic inline void
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerinc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer isc_stats_increment(res->view->resstats, counter);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyervalcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer dns_rdatatype_t type, dns_rdataset_t *rdataset,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer dns_rdataset_t *sigrdataset, unsigned int valoptions,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer result = dns_validator_create(fctx->res->view, name, type, rdataset,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer inc_stats(fctx->res, dns_resstatscounter_val);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ISC_LIST_APPEND(fctx->validators, validator, link);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyerrrsig_fromchildzone(fetchctx_t *fctx, dns_rdataset_t *rdataset) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int labels;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer namereln = dns_name_fullcompare(&rrsig.signer, &fctx->domain,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerfix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * A DS RRset can appear anywhere in a zone, even for a delegation-only
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * zone. So a response to an explicit query for this type should be
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * excluded from delegation-only fixup.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * SOA, NS, and DNSKEY can only exist at a zone apex, so a postive
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * response to a query for these types can never violate the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * delegation-only assumption: if the query name is below a
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * zone cut, the response should normally be a referral, which should
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * be accepted; if the query name is below a zone cut but the server
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * happens to have authority for the zone of the query name, the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * response is a (non-referral) answer. But this does not violate
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * delegation-only because the query name must be in a different zone
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * due to the "apex-only" nature of these types. Note that if the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * remote server happens to have authority for a child zone of a
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * delegation-only zone, we may still incorrectly "fix" the response
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * with NXDOMAIN for queries for other types. Unfortunately it's
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * generally impossible to differentiate this case from violation of
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * the delegation-only assumption. Once the resolver learns the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * correct zone cut, possibly via a separate query for an "apex-only"
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * type, queries for other types will be resolved correctly.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * A query for type ANY will be accepted if it hits an exceptional
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * type above in the answer section as it should be from a child
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Also accept answers with RRSIG records from the child zone.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Direct queries for RRSIG records should not be answered from
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * the parent zone.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (message->counts[DNS_SECTION_ANSWER] != 0 &&
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer result = dns_message_firstname(message, DNS_SECTION_ANSWER);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer dns_message_currentname(message, DNS_SECTION_ANSWER,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * RRsig from child?
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Direct query for apex records or DS.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Indirect query for apex records or DS.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * A NODATA response to a DS query?
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Look for referral or indication of answer from child zone? */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (message->counts[DNS_SECTION_AUTHORITY] == 0)
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
f8fec75ee8f429821137aee090f56ab678404a56Michael Sawyer dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /* NS or SOA records. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * If a query for ANY causes a negative
d62f9221228219d3f0982e95fb805674b4b0f184Michael Sawyer * response, we can be sure that this is
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * an empty node. For other type of queries
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * we cannot differentiate an empty node
d12ed0876f4dc174b91cc6bb1ddcb4196c656462Michael Sawyer * from a node that just doesn't have that
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * type of record. We only accept the former
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (message->counts[DNS_SECTION_ANSWER] == 0 &&
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer } else if (dns_name_issubdomain(name, domain)) {
518c9fea58b4e35d050fc3a2f5195d36ac6c7f09Michael Sawyer /* Referral or answer from child zone. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Start the lifetime timer for fctx.
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence * This is also used for stopping the idle timer; in that
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * case we must purge events already posted to ensure that
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * no further idle events are delivered.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (isc_timer_reset(fctx->timer, isc_timertype_once,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic inline void
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * We don't return a result if resetting the timer to inactive fails
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * since there's nothing to be done about it. Resetting to inactive
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * should never fail anyway, since the code as currently written
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * cannot fail in that case.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer "isc_timer_reset(): %s",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerfctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence * Start the idle timer for fctx. The lifetime timer continues
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * to be in effect.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (isc_timer_reset(fctx->timer, isc_timertype_once,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * we use fctx_stopidletimer for readability in the code below.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic inline void
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer maybe_destroy(query->fctx); /* Locks bucket. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_put(query->mctx, query, sizeof(*query));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerfctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_time_t *finish, isc_boolean_t no_response)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int factor;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Should we update the RTT?
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * We have both the start and finish times for this
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * packet, so we can compute a real RTT.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer rtt = (unsigned int)isc_time_microdiff(finish,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * We don't have an RTT for this query. Maybe the
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * packet was lost, or maybe this server is very
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * slow. We don't know. Increase the RTT.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Replace the current RTT with our value.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /* Remember that the server has been tried. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer dns_adb_changeflags(fctx->adb, query->addrinfo,
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * Age RTTs of servers not tried.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * Check for any outstanding socket events. If they exist, cancel
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * them and let the event handlers finish the cleanup. The resolver
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * only needs to worry about managing the connect and send events;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * the dispatcher manages the recv events.
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * Cancel the connect.
db8b100cae62de849ecf4ba9ad3be811fb375b53Michael Sawyer socket = dns_dispatch_getentrysocket(query->dispentry);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Cancel the pending send.
unsigned int count = 0;
unsigned int old_spillat;
count++;
&i, ISC_TRUE);
if (logit)
* isc_socket_sendto/connect() was in progress.
case ISC_R_SUCCESS:
case ISC_R_HOSTUNREACH:
case ISC_R_NETUNREACH:
case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
case ISC_R_CONNREFUSED:
if (retry) {
static inline isc_result_t
return (result);
return (result);
return (result);
if (request_nsid) {
unsigned int seconds;
unsigned int us;
static isc_result_t
unsigned int options)
unsigned int srtt;
return (result);
sizeof(*query));
goto stop_idle_timer;
int pf;
if (!have_addr) {
switch (pf) {
case PF_INET:
result =
&addr);
case PF_INET6:
result =
&addr);
goto cleanup_query;
goto cleanup_query;
#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
goto cleanup_socket;
if (have_addr) {
case AF_INET:
case AF_INET6:
goto cleanup_query;
goto cleanup_query;
case PF_INET:
case PF_INET6:
goto cleanup_query;
goto cleanup_socket;
goto cleanup_dispatch;
return (ISC_R_SUCCESS);
return (result);
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
sizeof(*sa));
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
sizeof(*sa));
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
sizeof(*sa));
static isc_result_t
isc_region_t r;
unsigned int edns_fetchopt_flag;
goto cleanup_temps;
goto cleanup_temps;
task,
goto cleanup_temps;
if (secure_domain)
goto cleanup_message;
goto cleanup_message;
DNS_SECTION_QUESTION, 0);
goto cleanup_message;
now);
!useedns)
* * broken/misconfigured firewalls and NAT implementations
* * broken/misconfigured firewalls that don't handle responses
* * broken/misconfigured firewalls that don't handle EDNS, DO
unsigned int flags;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
query);
goto cleanup_message;
if (connecting) {
goto cleanup_message;
return (ISC_R_SUCCESS);
if (cleanup_cctx)
return (result);
unsigned int attrs;
case ISC_R_SUCCESS:
attrs = 0;
case ISC_R_NETUNREACH:
case ISC_R_HOSTUNREACH:
case ISC_R_CONNREFUSED:
case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
case ISC_R_CONNECTIONRESET:
if (retry) {
unsigned int bucketnum;
if (want_try)
else if (want_done)
else if (bucket_empty)
static inline isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
static inline isc_boolean_t
return (all_bad);
isc_buffer_t b;
switch (badtype) {
case badns_unreachable:
case badns_response:
case badns_validation:
sizeof(*sa));
if (port != 0)
port);
static isc_boolean_t
int order;
unsigned int nlabels;
static isc_result_t
unsigned int stdoptions = 0;
return (DNS_R_SERVFAIL);
unsigned int labels;
return (result);
goto out;
return (result);
if (need_alternate) {
int family;
alternate_t *a;
a != NULL;
if (!a->isaddress) {
&ai, 0);
publink);
out:
if (all_bad) {
if (badcache &&
return (result);
int match;
match > 0)
if (aborted) {
static inline dns_adbaddrinfo_t *
return (addrinfo);
return (addrinfo);
return (addrinfo);
else if (retrying)
static isc_boolean_t
unsigned int bucketnum;
return (ISC_TRUE);
return (ISC_FALSE);
&cevent);
unsigned int bucketnum;
if (bucket_empty)
unsigned int bucketnum;
if (!done) {
} else if (bucket_empty)
static inline isc_result_t
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
unsigned int findoptions = 0;
return (ISC_R_NOMEMORY);
goto cleanup_fetch;
goto cleanup_info;
unsigned int labels;
NULL);
goto cleanup_name;
goto cleanup_name;
goto cleanup_name;
goto cleanup_name;
goto cleanup_domain;
goto cleanup_qmessage;
goto cleanup_rmessage;
goto cleanup_rmessage;
return (ISC_R_SUCCESS);
return (result);
static inline isc_boolean_t
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
int order;
unsigned int labels;
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
static inline isc_result_t
return (DNS_R_FORMERR);
return (result);
return (DNS_R_FORMERR);
return (ISC_R_SUCCESS);
unsigned int bucketnum;
if (bucket_empty)
goto cleanup_event;
!negative &&
NULL,
NULL,
NULL);
0, NULL);
else if (sentresponse)
if (negative &&
if (negative) {
&node);
goto noanswer_response;
ttl = 0;
goto noanswer_response;
goto answer_response;
goto noanswer_response;
goto noanswer_response;
goto noanswer_response;
if (sentresponse) {
goto cleanup_event;
goto cleanup_event;
&name);
&nsnode);
sigrdataset, 0,
NULL);
== ISC_R_SUCCESS);
static inline isc_result_t
unsigned int options;
unsigned int valoptions = 0;
return (result);
!need_validation) {
return (result);
return (result);
sizeof(typebuf));
sizeof(classbuf));
if (fail) {
return (DNS_R_BADNAME);
* Cache this rdataset/sigrdataset pair as
0, addedrdataset);
if (!need_validation &&
eresult =
eresult =
sigrdataset, 0,
options = 0;
task);
return (result);
static inline isc_result_t
section++) {
&name);
return (result);
static isc_result_t
return (result);
static inline isc_result_t
unsigned int valoptions = 0;
return (result);
if (secure_domain) {
&tname);
return (result);
if (need_validation) {
return (result);
goto unlock;
goto unlock;
ttl = 0;
goto unlock;
return (result);
if (gluing) {
if (external)
static isc_result_t
return (ISC_R_SUCCESS);
gluing);
&rdataset);
gluing);
return (ISC_R_SUCCESS);
static isc_result_t
#ifndef CHECK_FOR_GLUE_IN_ANSWER
#define CHECK_FOR_GLUE_IN_ANSWER 0
static isc_result_t
&name);
fctx);
if (rescan)
goto again;
static inline isc_result_t
return (result);
return (result);
return (ISC_R_SUCCESS);
static inline isc_result_t
unsigned int nlabels;
int order;
return (result);
return (result);
return (DNS_R_FORMERR);
return (result);
static isc_boolean_t
int match;
return (ISC_TRUE);
return (ISC_TRUE);
sizeof(typebuf));
sizeof(classbuf));
return (ISC_FALSE);
return (ISC_TRUE);
static isc_boolean_t
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
sizeof(classbuf));
return (ISC_FALSE);
return (ISC_TRUE);
static isc_result_t
unsigned int look_in_options)
return (ISC_R_SUCCESS);
sizeof(tbuf));
sizeof(nbuf));
sizeof(qbuf));
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
if (aa)
return (result);
if (negative_response) {
if (aa)
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
if (aa)
return (result);
return (DNS_R_CHASEDSSERVERS);
return (ISC_R_SUCCESS);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
fctx);
return (result);
return (DNS_R_DELEGATION);
return (ISC_R_SUCCESS);
static isc_result_t
unsigned int aflag;
aflag = 0;
return (DNS_R_FORMERR);
rdataset)) {
return (DNS_R_SERVFAIL);
&& !found_cname) {
&& !found_type) {
return (DNS_R_FORMERR);
&tname);
return (result);
name,
&tname,
return (DNS_R_SERVFAIL);
&& !found_type) {
if (found) {
if (!chaining) {
if (aflag ==
if (aa)
} else if (external) {
(void)dns_rdataset_additionaldata(
fctx);
if (want_chaining) {
if (wanted_chaining)
aflag = 0;
return (DNS_R_FORMERR);
&dname);
return (result);
return (DNS_R_SERVFAIL);
if (found) {
if (!chaining) {
if (aflag ==
if (aa)
} else if (external) {
if (found_dname) {
NULL);
return (result);
&fqname);
if (wanted_chaining)
return (result);
if (!have_answer) {
return (DNS_R_FORMERR);
if (chaining) {
return (DNS_R_FORMERR);
if (!external) {
(void)dns_rdataset_additionaldata(
fctx);
return (result);
static isc_boolean_t
return (bucket_empty);
unsigned int bucketnum;
goto cleanup;
goto cleanup;
&nameservers);
if (!locked)
if (bucket_empty)
ISC_FALSE) ||
static isc_result_t
return (ISC_R_FAILURE);
return (ISC_R_FAILURE);
return (ISC_R_FAILURE);
return (ISC_R_NOSPACE);
p = buf;
for (i = 0; i < nsid_len; i++) {
nsid++;
sizeof(addrbuf));
return (ISC_R_SUCCESS);
0, &buffer);
buf);
static isc_boolean_t
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
unsigned int options;
unsigned int findoptions;
goto done;
goto done;
goto done;
goto done;
switch (result) {
case ISC_R_UNEXPECTEDEND:
goto done;
case DNS_R_FORMERR:
goto done;
goto done;
goto done;
sizeof(addrbuf));
if (truncated) {
goto done;
goto done;
case dns_rcode_nxdomain:
case dns_rcode_servfail:
case dns_rcode_formerr:
unsigned int version;
switch (version) {
goto done;
goto done;
goto done;
sizeof(classbuf));
sizeof(addrbuf));
goto done;
goto force_referral;
goto done;
goto done;
goto done;
goto done;
done:
if (keep_trying) {
if (get_nameservers) {
findoptions = 0;
NULL);
} else if (resend) {
alternate_t *a;
if (!a->isaddress)
#if USE_ALGLOCK
#if USE_MBSLOCK
unsigned int count;
if (logit)
unsigned int options,
unsigned int i, buckets_created = 0;
unsigned dispattr;
return (ISC_R_NOMEMORY);
goto cleanup_res;
for (i = 0; i < ntasks; i++) {
goto cleanup_buckets;
goto cleanup_buckets;
#ifdef ISC_PLATFORM_USETHREADS
goto cleanup_buckets;
goto cleanup_dispatches;
goto cleanup_lock;
goto cleanup_nlock;
goto cleanup_primelock;
goto cleanup_primelock;
#if USE_ALGLOCK
goto cleanup_spillattimer;
#if USE_MBSLOCK
goto cleanup_alglock;
return (ISC_R_SUCCESS);
#if USE_MBSLOCK
#if USE_ALGLOCK
for (i = 0; i < buckets_created; i++) {
return (result);
#ifdef BIND9
if (want_priming) {
if (need_destroy)
static inline isc_boolean_t
unsigned int options)
return (ISC_FALSE);
return (ISC_FALSE);
unsigned int bucketnum;
unsigned int count = 0;
unsigned int spillat;
unsigned int spillatmin;
return (ISC_R_NOMEMORY);
goto unlock;
goto unlock;
count++;
goto unlock;
goto unlock;
if (new_fctx) {
return (result);
unsigned int bucketnum;
if (bucket_empty)
alternate_t *a;
if (a == NULL)
return (ISC_R_NOMEMORY);
return (result);
return (ISC_R_SUCCESS);
goto unlock;
unsigned int newsize;
if (grow)
unsigned int i, hashval;
goto cleanup;
goto cleanup;
goto unlock;
return (answer);
isc_uint64_t t;
goto unlock;
sizeof(typebuf));
#if USE_ALGLOCK
#if USE_ALGLOCK
unsigned int alg)
unsigned char *new;
unsigned char *algorithms;
return (ISC_R_RANGE);
#if USE_ALGLOCK
goto cleanup;
goto cleanup;
*algorithms);
#if USE_ALGLOCK
return (result);
unsigned int alg)
unsigned char *algorithms;
#if USE_ALGLOCK
goto unlock;
#if USE_ALGLOCK
if (found)
return (ISC_FALSE);
#if USE_MBSLOCK
#if USE_MBSLOCK
#if USE_MBSLOCK
goto cleanup;
#if USE_MBSLOCK
return (result);
#if USE_MBSLOCK
goto unlock;
#if USE_MBSLOCK
return (value);
if (seconds == 0)