resolver.c revision eeb8892daa70f57ec4d8a85dca8a2ad769653ee4
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews * Copyright (C) 1999-2003 Internet Software Consortium.
/* $Id: resolver.c,v 1.366 2008/04/03 23:14:52 jinmei Exp $ */
#include <config.h>
#define DNS_RESOLVER_TRACE
#ifdef DNS_RESOLVER_TRACE
#define RTRACE(m)
#define RRTRACE(r, m)
#define FCTXTRACE(m)
#define FTRACE(m)
#define QTRACE(m)
typedef struct query {
unsigned int magic;
unsigned int options;
unsigned int attributes;
unsigned int sends;
unsigned int connects;
} resquery_t;
RESQUERY_ATTR_CANCELED) != 0)
} fetchstate;
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;
} dns_valarg_t;
struct dns_fetch {
unsigned int magic;
typedef struct fctxbucket {
} fctxbucket_t;
typedef struct alternate {
} _n;
} _u;
} alternate_t;
#ifdef ISC_RWLOCK_USEATOMIC
#define DNS_RESOLVER_USERWLOCK 0
struct dns_resolver {
unsigned int magic;
unsigned int options;
unsigned int ndisps;
unsigned int nbuckets;
#if USE_ALGLOCK
#if USE_MBSLOCK
unsigned int spillatmax;
unsigned int spillatmin;
#ifdef LRU_DEBUG
unsigned int references;
unsigned int activebuckets;
unsigned int nextdisp;
unsigned int nfctx;
#ifdef LRU_DEBUG
unsigned int extqueries;
unsigned int extqueries_ns;
unsigned int extqueries_soa;
unsigned int extqueries_a;
unsigned int extqueries_aaaa;
FCTX_ADDRINFO_FORWARDER) != 0)
#ifdef LRU_DEBUG
static isc_result_t
sizeof(*valarg));
return (ISC_R_NOMEMORY);
&validator);
return (result);
static isc_boolean_t
return (ISC_FALSE);
&name);
return (ISC_FALSE);
goto munge;
goto munge;
return (ISC_FALSE);
if (!keep_auth)
return (ISC_TRUE);
static inline isc_result_t
static inline isc_result_t
ISC_FALSE));
unsigned int rtt;
unsigned int factor;
0, factor);
0, factor);
0, factor);
0, factor);
unsigned int count = 0;
unsigned int old_spillat;
count++;
&i, ISC_TRUE);
if (logit)
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)
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;
int did = 0;
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_result_t
isc_region_t r;
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)
unsigned int flags;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
goto cleanup_message;
#ifdef LRU_DEBUG
case dns_rdatatype_ns:
case dns_rdatatype_soa:
case dns_rdatatype_a:
case dns_rdatatype_aaaa:
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 &&
} else 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 &&
if (!need_validation)
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
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)
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;
&& !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) ||
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);
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;
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;
#ifdef LRU_DEBUG
if (!a->isaddress)
#ifdef LRU_DEBUG
#if USE_ALGLOCK
#if USE_MBSLOCK
unsigned int count;
if (logit)
unsigned int options,
unsigned int i, buckets_created = 0;
return (ISC_R_NOMEMORY);
#ifdef LRU_DEBUG
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_poollock;
#ifdef LRU_DEBUG
&interval) ==
goto cleanup_poollock;
#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;
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);
#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);
unsigned int nxt;
attrs_base = 0;
attrmask = 0;
&addr4);
&addr6);
&disp4);
&disp6);
unsigned int tick)
attrs_base = 0;
attrmask = 0;
sizeof(dns_dispatch_t *) *
ndisps);
return (ISC_R_NOMEMORY);
for (i = 0; i < ndisps; i++)
sizeof(dns_dispatch_t *) *
ndisps);
return (ISC_R_NOMEMORY);
for (i = 0; i < ndisps; i++)
for (i = 0; i < ndisps; i++) {
&disp);
goto cleanup;
&disp);
goto cleanup;
if (tick != 0) {
goto cleanup;
goto cleanup;
return (result);
for (i = 0; i < ndisps; i++)
for (i = 0; i < ndisps; i++)
return (result);
#ifdef LRU_DEBUG