resolver.c revision 8d56a8531dc71a58a65ddd5080b9292dcf1b5d7b
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * Copyright (C) 1999-2003 Internet Software Consortium.
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * Permission to use, copy, modify, and/or distribute this software for any
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
68a8db1efb0cd13e0e3d59362ab9db1a4a8bc496Andreas Gustafsson * PERFORMANCE OF THIS SOFTWARE.
#ifdef AES_SIT
#define DNS_RESOLVER_TRACE
#ifdef DNS_RESOLVER_TRACE
#define RTRACE(m)
#define RRTRACE(r, m)
#define FCTXTRACE(m)
#define FTRACE(m)
#define QTRACE(m)
#ifndef DEFAULT_QUERY_TIMEOUT
#ifndef MAXIMUM_QUERY_TIMEOUT
typedef struct query {
unsigned int magic;
unsigned int options;
unsigned int attributes;
unsigned int sends;
unsigned int connects;
unsigned int udpsize;
} resquery_t;
struct tried {
unsigned int count;
RESQUERY_ATTR_CANCELED) != 0)
} fetchstate;
badns_unreachable = 0,
} badnstype_t;
struct fetchctx {
unsigned int magic;
unsigned int options;
unsigned int bucketnum;
char * info;
unsigned int references;
unsigned int attributes;
unsigned int pending;
unsigned int restarts;
unsigned int timeouts;
unsigned int nqueries;
const char * reason;
int exitline;
unsigned int querysent;
unsigned int referrals;
unsigned int lamecount;
unsigned int neterr;
unsigned int badresp;
unsigned int adberr;
unsigned int findfail;
unsigned int valfail;
} dns_valarg_t;
struct dns_fetch {
unsigned int magic;
typedef struct fctxbucket {
} fctxbucket_t;
typedef struct alternate {
} _n;
} _u;
} alternate_t;
struct dns_badcache {
unsigned int hashval;
struct dns_resolver {
unsigned int magic;
unsigned int options;
unsigned int nbuckets;
#if USE_ALGLOCK
#if USE_MBSLOCK
unsigned int spillatmax;
unsigned int spillatmin;
unsigned int query_timeout;
unsigned int references;
unsigned int activebuckets;
unsigned int badcount;
unsigned int badhash;
unsigned int badsweep;
unsigned int nfctx;
FCTX_ADDRINFO_FORWARDER) != 0)
FCTX_ADDRINFO_TRIED) != 0)
FCTX_ADDRINFO_NOSIT) != 0)
static isc_result_t
return (ISC_R_NOMEMORY);
&validator);
return (result);
static isc_boolean_t
int order;
unsigned int labels;
return (ISC_TRUE);
return (ISC_FALSE);
static isc_boolean_t
return (ISC_FALSE);
&name);
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
goto munge;
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
if (!keep_auth)
return (ISC_TRUE);
static inline isc_result_t
static inline isc_result_t
unsigned int factor;
now);
now);
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);
unsigned int seconds;
unsigned int us;
static isc_result_t
unsigned int options)
unsigned int srtt;
return (result);
goto stop_idle_timer;
int pf;
if (!have_addr) {
switch (pf) {
case PF_INET:
&addr);
case PF_INET6:
&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);
static struct tried *
return (tried);
return (NULL);
static struct tried *
return (tried);
return (NULL);
#ifdef ISC_PLATFORM_USESIT
#ifdef AES_SIT
case AF_INET:
case AF_INET6:
#ifdef HMAC_SHA1_SIT
case AF_INET:
case AF_INET6:
#ifdef HMAC_SHA256_SIT
case AF_INET:
case AF_INET6:
static isc_result_t
isc_region_t r;
unsigned ednsopt = 0;
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;
!useedns)
#ifdef ISC_PLATFORM_USESIT
if (hint != 0U)
if (udpsize == 0U)
#ifdef ISC_PLATFORM_USESIT
#ifdef ISC_PLATFORM_USESIT
if (reqnsid) {
ednsopt++;
#ifdef ISC_PLATFORM_USESIT
if (reqsit) {
ednsopt++;
udpsize = 0;
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 (destroy) {
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:
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 (destroy) {
if (bucket_empty)
unsigned int bucketnum;
if (!done) {
} else if (destroy) {
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);
static isc_boolean_t
unsigned int bucketnum;
if (!locked)
goto unlock;
if (!locked)
if (destroy)
return (bucket_empty);
unsigned options;
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;
noqname);
goto noanswer_response;
options = 0;
goto noanswer_response;
goto noanswer_response;
if (sentresponse) {
if (bucket_empty)
goto cleanup_event;
goto cleanup_event;
&name);
&nsnode);
sigrdataset, 0,
NULL);
== ISC_R_SUCCESS);
static inline isc_result_t
unsigned int labels;
return (ISC_R_NOTFOUND);
return (ISC_R_NOTFOUND);
return (result);
fctx)))
if (!exists) {
return (result);
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
options = 0;
&noqname);
tresult =
if (!need_validation &&
eresult =
eresult =
options = 0;
task);
return (result);
static inline isc_result_t
section++) {
&name);
return (result);
static isc_result_t
if (secure)
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);
sizeof(tbuf));
sizeof(dbuf));
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) ||
unsigned char *p, *nsid;
goto cleanup;
goto cleanup;
p = buf;
for (i = 0; i < nsid_len; i++) {
p = pbuf;
for (i = 0; i < nsid_len; i++) {
*p++ = nsid[i];
sizeof(addrbuf));
static isc_boolean_t
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
#ifdef ISC_PLATFORM_USESIT
unsigned char *sit;
switch (optcode) {
case DNS_OPT_NSID:
#ifdef ISC_PLATFORM_USESIT
case DNS_OPT_SIT:
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;
#ifdef notyet
#ifdef ISC_PLATFORM_USESIT
goto done;
goto done;
addrbuf);
addrbuf);
if (truncated) {
goto done;
goto done;
case dns_rcode_nxdomain:
case dns_rcode_servfail:
case dns_rcode_formerr:
case dns_rcode_refused:
case dns_rcode_badvers:
#ifdef ISC_PLATFORM_USESIT
unsigned int version;
#ifdef ISC_PLATFORM_USESIT
switch (version) {
goto done;
goto done;
goto done;
sizeof(classbuf));
sizeof(addrbuf));
goto done;
goto force_referral;
goto done;
switch (result) {
case ISC_R_SUCCESS:
case DNS_R_CHASEDSSERVERS:
case DNS_R_DELEGATION:
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);
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) {
if (destroy)
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;
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_ALGLOCK
#if USE_ALGLOCK
unsigned int digest_type)
unsigned char *new;
unsigned char *digests;
return (ISC_R_RANGE);
#if USE_ALGLOCK
goto cleanup;
goto cleanup;
*digests);
#if USE_ALGLOCK
return (result);
unsigned int digest_type)
unsigned char *digests;
#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)