diff options
author | Doug Barton <dougb@FreeBSD.org> | 2005-12-29 04:22:58 +0000 |
---|---|---|
committer | Doug Barton <dougb@FreeBSD.org> | 2005-12-29 04:22:58 +0000 |
commit | a00aca3467ce973cd6d2414c81fd5e39559374b3 (patch) | |
tree | 570b6e4f35462e81147786cc2f272d28fac7f470 /contrib/bind9/lib/dns/resolver.c | |
parent | adaaaab975815edcabdc20da6c7f0ad57ca75402 (diff) | |
download | src-a00aca3467ce973cd6d2414c81fd5e39559374b3.tar.gz src-a00aca3467ce973cd6d2414c81fd5e39559374b3.zip |
Vendor import of BIND 9.3.2
Notes
Notes:
svn path=/vendor/bind9/dist/; revision=153816
Diffstat (limited to 'contrib/bind9/lib/dns/resolver.c')
-rw-r--r-- | contrib/bind9/lib/dns/resolver.c | 224 |
1 files changed, 142 insertions, 82 deletions
diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index 790a2f41686f..6f803eb192f4 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.218.2.18.4.51 2005/02/08 23:59:44 marka Exp $ */ +/* $Id: resolver.c,v 1.218.2.18.4.56 2005/10/14 01:38:48 marka Exp $ */ #include <config.h> @@ -244,6 +244,11 @@ struct fetchctx { #define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0) #define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0) +typedef struct { + dns_adbaddrinfo_t * addrinfo; + fetchctx_t * fctx; +} dns_valarg_t; + struct dns_fetch { unsigned int magic; fetchctx_t * private; @@ -342,6 +347,35 @@ static isc_result_t ncache_adderesult(dns_message_t *message, isc_stdtime_t now, dns_ttl_t maxttl, dns_rdataset_t *ardataset, isc_result_t *eresultp); +static void validated(isc_task_t *task, isc_event_t *event); + +static isc_result_t +valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, + dns_rdatatype_t type, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, unsigned int valoptions, + isc_task_t *task) +{ + dns_validator_t *validator = NULL; + dns_valarg_t *valarg; + isc_result_t result; + + valarg = isc_mem_get(fctx->res->mctx, sizeof(*valarg)); + if (valarg == NULL) + return (ISC_R_NOMEMORY); + + valarg->fctx = fctx; + valarg->addrinfo = addrinfo; + + result = dns_validator_create(fctx->res->view, name, type, rdataset, + sigrdataset, fctx->rmessage, + valoptions, task, validated, valarg, + &validator); + if (result == ISC_R_SUCCESS) + ISC_LIST_APPEND(fctx->validators, validator, link); + else + isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg)); + return (result); +} static isc_boolean_t fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) { @@ -1424,6 +1458,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { case ISC_R_CONNREFUSED: case ISC_R_NOPERM: case ISC_R_ADDRNOTAVAIL: + case ISC_R_CONNECTIONRESET: /* * No route to remote. */ @@ -1855,7 +1890,6 @@ fctx_getaddresses(fetchctx_t *fctx) { isc_boolean_t pruned, all_bad; dns_rdata_ns_t ns; isc_boolean_t need_alternate = ISC_FALSE; - isc_boolean_t unshared; FCTXTRACE("getaddresses"); @@ -1871,7 +1905,6 @@ fctx_getaddresses(fetchctx_t *fctx) { res = fctx->res; pruned = ISC_FALSE; stdoptions = 0; /* Keep compiler happy. */ - unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0); /* * Forwarders. @@ -2668,7 +2701,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, isc_result_t result; isc_result_t iresult; isc_interval_t interval; - dns_fixedname_t qdomain; + dns_fixedname_t fixed; unsigned int findoptions = 0; char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; @@ -2747,8 +2780,10 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, dns_name_getlabelsequence(name, 1, labels - 1, &suffix); name = &suffix; } - result = dns_fwdtable_find(fctx->res->view->fwdtable, name, - &forwarders); + dns_fixedname_init(&fixed); + domain = dns_fixedname_name(&fixed); + result = dns_fwdtable_find2(fctx->res->view->fwdtable, name, + domain, &forwarders); if (result == ISC_R_SUCCESS) fctx->fwdpolicy = forwarders->fwdpolicy; @@ -2760,27 +2795,22 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, */ if (dns_rdatatype_atparent(type)) findoptions |= DNS_DBFIND_NOEXACT; - dns_fixedname_init(&qdomain); - result = dns_view_findzonecut(res->view, name, - dns_fixedname_name(&qdomain), 0, - findoptions, ISC_TRUE, + result = dns_view_findzonecut(res->view, name, domain, + 0, findoptions, ISC_TRUE, &fctx->nameservers, NULL); if (result != ISC_R_SUCCESS) goto cleanup_name; - result = dns_name_dup(dns_fixedname_name(&qdomain), - res->mctx, &fctx->domain); + result = dns_name_dup(domain, res->mctx, &fctx->domain); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&fctx->nameservers); goto cleanup_name; } } else { /* - * We're in forward-only mode. Set the query domain - * to ".". + * We're in forward-only mode. Set the query domain. */ - result = dns_name_dup(dns_rootname, res->mctx, - &fctx->domain); + result = dns_name_dup(domain, res->mctx, &fctx->domain); if (result != ISC_R_SUCCESS) goto cleanup_name; } @@ -3090,11 +3120,15 @@ validated(isc_task_t *task, isc_event_t *event) { dns_name_t *name; dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; + dns_valarg_t *valarg; + dns_adbaddrinfo_t *addrinfo; UNUSED(task); /* for now */ REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE); - fctx = event->ev_arg; + valarg = event->ev_arg; + fctx = valarg->fctx; + addrinfo = valarg->addrinfo; REQUIRE(VALID_FCTX(fctx)); REQUIRE(!ISC_LIST_EMPTY(fctx->validators)); @@ -3109,6 +3143,7 @@ validated(isc_task_t *task, isc_event_t *event) { * destroy the fctx if necessary. */ dns_validator_destroy(&vevent->validator); + isc_mem_put(fctx->res->mctx, valarg, sizeof(*valarg)); negative = ISC_TF(vevent->rdataset == NULL); @@ -3166,21 +3201,27 @@ validated(isc_task_t *task, isc_event_t *event) { if (vevent->result != ISC_R_SUCCESS) { FCTXTRACE("validation failed"); - if (vevent->rdataset != NULL) { + result = ISC_R_NOTFOUND; + if (vevent->rdataset != NULL) result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node); - if (result != ISC_R_SUCCESS) - goto noanswer_response; + if (result == ISC_R_SUCCESS) (void)dns_db_deleterdataset(fctx->cache, node, NULL, vevent->type, 0); - if (vevent->sigrdataset != NULL) - (void)dns_db_deleterdataset(fctx->cache, - node, NULL, - dns_rdatatype_rrsig, - vevent->type); - } + if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL) + (void)dns_db_deleterdataset(fctx->cache, node, NULL, + dns_rdatatype_rrsig, + vevent->type); + if (result == ISC_R_SUCCESS) + dns_db_detachnode(fctx->cache, &node); result = vevent->result; - goto noanswer_response; + add_bad(fctx, &addrinfo->sockaddr, result); + isc_event_free(&event); + if (sentresponse) + fctx_done(fctx, result); + else + fctx_try(fctx); + return; } isc_stdtime_get(&now); @@ -3350,7 +3391,8 @@ validated(isc_task_t *task, isc_event_t *event) { } static inline isc_result_t -cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { +cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, + isc_stdtime_t now) { dns_rdataset_t *rdataset, *sigrdataset; dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset; dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL; @@ -3363,8 +3405,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { dns_fetchevent_t *event; unsigned int options; isc_task_t *task; - dns_validator_t *validator; isc_boolean_t fail; + unsigned int valoptions = 0; /* * The appropriate bucket lock must be held. @@ -3385,8 +3427,10 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { if (result != ISC_R_SUCCESS) return (result); - if (res->view->dlv != NULL) + if (!secure_domain && res->view->dlv != NULL) { + valoptions = DNS_VALIDATOR_DLV; secure_domain = ISC_TRUE; + } if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) need_validation = ISC_FALSE; @@ -3437,7 +3481,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { /* * Cache or validate each cacheable rdataset. */ - fail = (fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0; + fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { @@ -3569,23 +3613,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { * having to remember which * rdatasets needed validation. */ - validator = NULL; - result = dns_validator_create( - res->view, - name, - rdataset->type, - rdataset, - sigrdataset, - fctx->rmessage, - 0, - task, - validated, - fctx, - &validator); - if (result == ISC_R_SUCCESS) - ISC_LIST_APPEND( - fctx->validators, - validator, link); + result = valcreate(fctx, addrinfo, + name, rdataset->type, + rdataset, + sigrdataset, + valoptions, task); } } else if (CHAINING(rdataset)) { if (rdataset->type == dns_rdatatype_cname) @@ -3660,22 +3692,10 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { } } - if (valrdataset != NULL) { - validator = NULL; - result = dns_validator_create(res->view, - name, - fctx->type, - valrdataset, - valsigrdataset, - fctx->rmessage, - 0, - task, - validated, - fctx, - &validator); - if (result == ISC_R_SUCCESS) - ISC_LIST_APPEND(fctx->validators, validator, link); - } + if (valrdataset != NULL) + result = valcreate(fctx, addrinfo, name, fctx->type, + valrdataset, valsigrdataset, valoptions, + task); if (result == ISC_R_SUCCESS && have_answer) { fctx->attributes |= FCTX_ATTR_HAVEANSWER; @@ -3695,7 +3715,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) { } static inline isc_result_t -cache_message(fetchctx_t *fctx, isc_stdtime_t now) { +cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now) +{ isc_result_t result; dns_section_t section; dns_name_t *name; @@ -3715,7 +3736,7 @@ cache_message(fetchctx_t *fctx, isc_stdtime_t now) { dns_message_currentname(fctx->rmessage, section, &name); if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) { - result = cache_name(fctx, name, now); + result = cache_name(fctx, name, addrinfo, now); if (result != ISC_R_SUCCESS) break; } @@ -3783,7 +3804,9 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, } static inline isc_result_t -ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { +ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, + dns_rdatatype_t covers, isc_stdtime_t now) +{ isc_result_t result, eresult; dns_name_t *name; dns_resolver_t *res; @@ -3794,6 +3817,7 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { dns_name_t *aname; dns_fetchevent_t *event; isc_uint32_t ttl; + unsigned int valoptions = 0; FCTXTRACE("ncache_message"); @@ -3820,8 +3844,10 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { if (result != ISC_R_SUCCESS) return (result); - if (res->view->dlv != NULL) + if (!secure_domain && res->view->dlv != NULL) { + valoptions = DNS_VALIDATOR_DLV; secure_domain = ISC_TRUE; + } if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) need_validation = ISC_FALSE; @@ -3858,23 +3884,15 @@ ncache_message(fetchctx_t *fctx, dns_rdatatype_t covers, isc_stdtime_t now) { /* * Do negative response validation. */ - dns_validator_t *validator = NULL; - isc_task_t *task = res->buckets[fctx->bucketnum].task; - - result = dns_validator_create(res->view, name, fctx->type, - NULL, NULL, - fctx->rmessage, 0, task, - validated, fctx, - &validator); - if (result != ISC_R_SUCCESS) - return (result); - ISC_LIST_APPEND(fctx->validators, validator, link); + result = valcreate(fctx, addrinfo, name, fctx->type, + NULL, NULL, valoptions, + res->buckets[fctx->bucketnum].task); /* * If validation is necessary, return now. Otherwise continue * to process the message, letting the validation complete * in its own good time. */ - return (ISC_R_SUCCESS); + return (result); } LOCK(&res->buckets[fctx->bucketnum].lock); @@ -4992,6 +5010,43 @@ checknames(dns_message_t *message) { } static void +log_packet(dns_message_t *message, int level, isc_mem_t *mctx) { + isc_buffer_t buffer; + char *buf = NULL; + int len = 1024; + isc_result_t result; + + if (! isc_log_wouldlog(dns_lctx, level)) + return; + + /* + * Note that these are multiline debug messages. We want a newline + * to appear in the log after each message. + */ + + do { + buf = isc_mem_get(mctx, len); + if (buf == NULL) + break; + isc_buffer_init(&buffer, buf, len); + result = dns_message_totext(message, &dns_master_style_debug, + 0, &buffer); + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, buf, len); + len += 1024; + } else if (result == ISC_R_SUCCESS) + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, level, + "received packet:\n%.*s", + (int)isc_buffer_usedlength(&buffer), + buf); + } while (result == ISC_R_NOSPACE); + + if (buf != NULL) + isc_mem_put(mctx, buf, len); +} + +static void resquery_response(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; resquery_t *query = event->ev_arg; @@ -5160,6 +5215,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } /* + * Log the incoming packet. + */ + log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); + + /* * If the message is signed, check the signature. If not, this * returns success anyway. */ @@ -5427,7 +5487,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * work to be queued to the DNSSEC validator. */ if (WANTCACHE(fctx)) { - result = cache_message(fctx, now); + result = cache_message(fctx, query->addrinfo, now); if (result != ISC_R_SUCCESS) goto done; } @@ -5446,7 +5506,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { /* * Cache any negative cache entries in the message. */ - result = ncache_message(fctx, covers, now); + result = ncache_message(fctx, query->addrinfo, covers, now); } done: |