resolver.c revision a473029e76dfc68db00505f40065607b4ea1e0f5
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2003 Internet Software Consortium.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Permission to use, copy, modify, and distribute this software for any
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff/* $Id: resolver.c,v 1.336 2006/10/18 04:18:54 marka Exp $ */
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff#define RRTRACE(r, m) isc_log_write(dns_lctx, \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews "res %p: %s", (r), (m))
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff "fctx %p(%s): %s %s", \
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson "fetch %p (fctx %p(%s)): %s", \
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews "resquery %p (fctx %p(%s)): %s", \
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson * Maximum EDNS0 input packet size.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * This defines the maximum number of timeouts we will permit before we
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * disable EDNS0 on the query.
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrewstypedef struct query {
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews /* Locked by task event serialization. */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int magic;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int options;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int sends;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews unsigned int connects;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews#define RESQUERY_CANCELED(q) (((q)->attributes & \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewstypedef enum {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews fetchstate_init = 0, /*%< Start event has not run yet. */
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff fetchstate_done /*%< FETCHDONE events posted. */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*% Not locked. */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int magic;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int options;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*% Locked by appropriate bucket lock. */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews /*% Locked by task event serialization. */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * The number of events we're waiting for.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int pending;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * The number of times we've "restarted" the current
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * nameserver set. This acts as a failsafe to prevent
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * us from pounding constantly on a particular set of
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * servers that, for whatever reason, are not giving
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * us useful responses, but are responding in such a
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * way that they are not marked "bad".
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int restarts;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * The number of timeouts that have occurred since we
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * last successfully received a response packet. This
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * is used for EDNS0 black hole detection.
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * Look aside state for DS lookups.
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington#define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewstypedef struct {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int magic;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrewstypedef struct fctxbucket {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewstypedef struct alternate {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews /* Unlocked. */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews unsigned int magic;
8b61d2012063306528286680bd9f086fa868d86eMark Andrews unsigned int options;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int nbuckets;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* Locked by lock. */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int spillat;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /* Locked by primelock. */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* Locked by nlock. */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int nfctx;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * which we also use as an addrinfo flag.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsstatic isc_result_t resquery_send(resquery_t *query);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsstatic void resquery_response(isc_task_t *task, isc_event_t *event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void resquery_connected(isc_task_t *task, isc_event_t *event);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsstatic isc_boolean_t fctx_destroy(fetchctx_t *fctx);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic isc_result_t ncache_adderesult(dns_message_t *message,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void validated(isc_task_t *task, isc_event_t *event);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvalcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_rdatatype_t type, dns_rdataset_t *rdataset,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_rdataset_t *sigrdataset, unsigned int valoptions,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews result = dns_validator_create(fctx->res->view, name, type, rdataset,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_APPEND(fctx->validators, validator, link);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsfix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Look for BIND 8 style delegations.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Also look for answers to ANY queries where the duplicate NS RRset
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * may have been stripped from the authority section.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if (message->counts[DNS_SECTION_ANSWER] != 0 &&
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews result = dns_message_firstname(message, DNS_SECTION_ANSWER);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews dns_message_currentname(message, DNS_SECTION_ANSWER,
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews /* Look for referral. */
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews if (message->counts[DNS_SECTION_AUTHORITY] == 0)
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington rdataset = ISC_LIST_NEXT(rdataset, link)) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson message->counts[DNS_SECTION_AUTHORITY] = 0;
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson message->counts[DNS_SECTION_ADDITIONAL] = 0;
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * Start the lifetime timer for fctx.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * This is also used for stopping the idle timer; in that
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * case we must purge events already posted to ensure that
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * no further idle events are delivered.
97f26b88f62b10a9c26a91ebe8387d2e498c2d00Andreas Gustafsson return (isc_timer_reset(fctx->timer, isc_timertype_once,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsstatic inline void
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * We don't return a result if resetting the timer to inactive fails
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * since there's nothing to be done about it. Resetting to inactive
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * should never fail anyway, since the code as currently written
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * cannot fail in that case.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews "isc_timer_reset(): %s",
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Start the idle timer for fctx. The lifetime timer continues
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * to be in effect.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (isc_timer_reset(fctx->timer, isc_timertype_once,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * we use fctx_stopidletimer for readability in the code below.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsstatic inline void
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews isc_mem_put(query->mctx, query, sizeof(*query));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsfctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int rtt;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int factor;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Should we update the RTT?
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * We have both the start and finish times for this
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * packet, so we can compute a real RTT.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * We don't have an RTT for this query. Maybe the
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * packet was lost, or maybe this server is very
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * slow. We don't know. Increase the RTT.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Replace the current RTT with our value.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Age RTTs of servers not tried.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_dispatch_removeresponse(&query->dispentry, deventp);
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * Check for any outstanding socket events. If they exist, cancel
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * them and let the event handlers finish the cleanup. The resolver
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * only needs to worry about managing the connect and send events;
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * the dispatcher manages the recv events.
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * Cancel the connect.
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * Cancel the pending send.
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * It's safe to destroy the query now.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsfctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews fctx_cancelquery(&query, NULL, NULL, no_response);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews ISC_LIST_UNLINK(fctx->altfinds, find, publink);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsstatic inline void
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsfctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsstatic inline void
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsfctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews unsigned int count = 0;
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Caller must be holding the appropriate bucket lock.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington if (count == fctx->res->spillat && !fctx->res->exiting) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (fctx->res->spillat > fctx->res->spillatmax &&
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews result = isc_timer_reset(fctx->res->spillattimer,
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews "clients-per-query increased to %u",
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellingtonfctx_done(fetchctx_t *fctx, isc_result_t result) {
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrewsresquery_senddone(isc_task_t *task, isc_event_t *event) {
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * Currently we don't wait for the senddone event before retrying
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * a query. This means that if we get really behind, we may end
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * up doing extra work!
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * This query was canceled while the
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * isc_socket_sendto() was in progress.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * No route to remote.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Behave as if the idle timer has expired. For TCP
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * this may not actually reflect the latest timer.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsfctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington result = dns_message_gettemprdatalist(message, &rdatalist);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = dns_message_gettemprdata(message, &rdata);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = dns_message_gettemprdataset(message, &rdataset);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Set Maximum UDP buffer size.
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * Set EXTENDED-RCODE and Z to 0, DO to 1.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * No EDNS options.
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (dns_message_setopt(message, rdataset));
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtonstatic inline void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsfctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int seconds;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int us;
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * We retry every .5 seconds the first two times through the address
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * list, and then we do exponential back-off.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Double the round-trip time.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Always wait for at least the doubled round-trip time.
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * But don't ever wait for more than 10 seconds.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_interval_set(&fctx->interval, seconds, us * 1000);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsfctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int options)
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews query->mctx = res->buckets[fctx->bucketnum].mctx;
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington * Note that the caller MUST guarantee that 'addrinfo' will remain
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington * valid until this query is canceled.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * If this is a TCP query, then we need to make a socket and
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington * a dispatch for it here. Otherwise we use the resolver's
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * shared dispatch.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff result = dns_peerlist_peerbyaddr(res->view->peers,
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff result = dns_peer_getquerysource(peer, &addr);
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington if ((query->options & DNS_FETCHOPT_TCP) != 0) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = isc_socket_bind(query->tcpsocket, &addr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * A dispatch will be created once the connect succeeds.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson result = dns_dispatch_getudp(res->dispatchmgr,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * We should always have a valid dispatcher here. If we
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * don't support a protocol family, then its dispatcher
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * will be NULL, but we shouldn't be finding addresses for
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * protocol types we don't support, so the dispatcher
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * we found should never be NULL.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if ((query->options & DNS_FETCHOPT_TCP) != 0) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * Connect to the remote server.
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * XXXRTH Should we attach to the socket?
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = isc_socket_connect(query->tcpsocket,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews isc_mem_put(res->buckets[fctx->bucketnum].mctx,
9cb39bbe40998ee14df86609da806441b9e144ceAndreas Gustafsson RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssontriededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsadd_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
f53848e17123569387b279578f0100dca5407da5Mark Andrewstriededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsadd_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
f53848e17123569387b279578f0100dca5407da5Mark Andrews sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if ((query->options & DNS_FETCHOPT_TCP) != 0) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Reserve space for the TCP message length.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff isc_buffer_init(&query->buffer, query->data + 2,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews result = dns_message_gettempname(fctx->qmessage, &qname);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Get a query id from the dispatch.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_dispatch_addresponse(query->dispatch,
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff * Set up question.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews * Set RD if the client has requested that we do a recursive query,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * or if we're sending to a forwarder.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * Set CD if the client says don't validate or the question is
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff * under a secure entry point.
897f762e3caf052688d4ec7b725746cfef09b058Andreas Gustafsson if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
897f762e3caf052688d4ec7b725746cfef09b058Andreas Gustafsson fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
897f762e3caf052688d4ec7b725746cfef09b058Andreas Gustafsson } else if (res->view->enablevalidation) {
897f762e3caf052688d4ec7b725746cfef09b058Andreas Gustafsson result = dns_keytable_issecuredomain(res->view->secroots,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * We don't have to set opcode because it defaults to query.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * Convert the question to wire format.
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews result = dns_compress_init(&cctx, -1, fctx->res->mctx);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff result = dns_message_renderbegin(fctx->qmessage, &cctx,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = dns_message_rendersection(fctx->qmessage,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * The ADB does not know about servers with "edns no". Check this,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * and then inform the ADB for future use.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * Use EDNS0, unless the caller doesn't want it, or we know that
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * the remote server doesn't like it.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
8068ceb2a9cc56d18016c3cd94a09e4bb0bc7b0dAndreas Gustafsson (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
8068ceb2a9cc56d18016c3cd94a09e4bb0bc7b0dAndreas Gustafsson FCTXTRACE("too many timeouts, disabling EDNS0");
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
390b2077fc751105e40174ceaa1ce34ef06e7dd4Mark Andrews FCTXTRACE("too many timeouts, setting EDNS size to 512");
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews unsigned int version = 0; /* Default version. */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews unsigned int flags;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews result = fctx_addopt(fctx->qmessage, version, udpsize);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * We couldn't add the OPT, but we'll press on.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * We're not using EDNS0, so set the NOEDNS0
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * We know this server doesn't like EDNS0, so we
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * won't use it. Set the NOEDNS0 bit since we're
8b61d2012063306528286680bd9f086fa868d86eMark Andrews * not using EDNS0.
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
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;
sizeof(*sa));
if (port != 0)
port);
static isc_result_t
unsigned int stdoptions;
return (DNS_R_SERVFAIL);
unsigned int labels;
&forwarders);
goto out;
return (result);
if (need_alternate) {
int family;
alternate_t *a;
a != NULL;
if (!a->isaddress) {
&ai, 0);
publink);
out:
if (all_bad) {
return (result);
int match;
match > 0)
if (aborted) {
static inline dns_adbaddrinfo_t *
return (addrinfo);
return (addrinfo);
return (addrinfo);
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 &&
if (sentresponse)
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
if (!need_validation)
if (!need_validation)
sigrdataset, 0,
options = 0;
eresult =
eresult =
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
NULL);
gluing);
&rdataset);
gluing);
return (ISC_R_SUCCESS);
&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_result_t
return (ISC_R_SUCCESS);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
return (DNS_R_FORMERR);
if (aa)
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;
&& !found_cname) {
&& !found_type) {
return (DNS_R_FORMERR);
&tname);
return (result);
&& !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);
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);
unsigned int bucketnum;
goto cleanup;
goto cleanup;
&nameservers);
if (!locked)
if (bucket_empty)
ISC_FALSE) ||
0, &buffer);
buf);
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;
if (truncated) {
goto done;
goto done;
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;
return (ISC_R_NOMEMORY);
goto cleanup_res;
for (i = 0; i < ntasks; i++) {
goto cleanup_buckets;
goto cleanup_buckets;
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);
if (want_priming) {
if (need_destroy)
static inline isc_boolean_t
unsigned int options)
return (ISC_FALSE);
unsigned int bucketnum;
unsigned int count = 0;
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);
#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);