From: Wouter Wijngaards Date: Fri, 26 Aug 2011 09:00:43 +0000 (+0000) Subject: - Fix validation failures due to EDNS backoff retries, the retry X-Git-Tag: release-1.4.13rc1~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d56aef7b33d237aff707ad876124fd4fb92d4c71;p=thirdparty%2Funbound.git - Fix validation failures due to EDNS backoff retries, the retry for fetch of data has want_dnssec because the iter_indicate_dnssec function returns true when validation failure retry happens, and then the serviced query code does not fallback to noEDNS, even if the cache says it has this. This helps for DLV deployment when the DNSSEC status is not known for sure before the lookup concludes. git-svn-id: file:///svn/unbound/trunk@2483 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index dd6c1f38c..64fbcad26 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,5 +1,11 @@ 26 August 2011: Wouter - Fix num-threads 0 does not segfault, reported by Simon Deziel. + - Fix validation failures due to EDNS backoff retries, the retry + for fetch of data has want_dnssec because the iter_indicate_dnssec + function returns true when validation failure retry happens, and + then the serviced query code does not fallback to noEDNS, even if + the cache says it has this. This helps for DLV deployment when + the DNSSEC status is not known for sure before the lookup concludes. 24 August 2011: Wouter - Applied patch from Karel Slany that fixes a memory leak in the diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index dc1b3fe96..2bb216f1b 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -534,7 +534,7 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, - struct dns_msg* msg, uint16_t dclass) + struct dns_msg* msg, uint16_t dclass, struct module_qstate* qstate) { struct trust_anchor* a; /* information not available, !env->anchors can be common */ @@ -568,6 +568,15 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, regional_free_all(env->scratch); } } + /* on retries, we have to expect DNSSEC. + * just a blacklist of the cache is done for parentside lookups too, + * but blacklist of IPs is done for validation failures. */ + if(qstate && qstate->blacklist) { + struct sock_list* p; + for(p=qstate->blacklist; p; p=p->next) + if(p->len != 0) + return 1; + } return 0; } diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index deddac666..c7beeacc6 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -172,10 +172,12 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, * @param dp: delegation point. * @param msg: delegation message, with DS if a secure referral. * @param dclass: class of query. + * @param qstate: module query state for the query in question, for validation + * retry state. * @return 1 if dnssec is expected, 0 if not. */ int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, - struct dns_msg* msg, uint16_t dclass); + struct dns_msg* msg, uint16_t dclass, struct module_qstate* qstate); /** * See if a message contains DNSSEC. diff --git a/iterator/iterator.c b/iterator/iterator.c index 3924057ce..e4bfa8d5d 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -574,8 +574,8 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, } /* there should not be any target queries. */ subiq->num_target_queries = 0; - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, subq->qinfo.qclass); + subiq->dnssec_expected = iter_indicates_dnssec(qstate->env, + subiq->dp, NULL, subq->qinfo.qclass, subq); } /* this module stops, our submodule starts, and does the query. */ @@ -669,8 +669,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, * missing targets. */ subiq->num_target_queries = 0; subiq->wait_priming_stub = 1; - subiq->dnssec_expected = iter_indicates_dnssec( - qstate->env, subiq->dp, NULL, subq->qinfo.qclass); + subiq->dnssec_expected = iter_indicates_dnssec(qstate->env, + subiq->dp, NULL, subq->qinfo.qclass, subq); } /* this module stops, our submodule starts, and does the query. */ @@ -1191,7 +1191,7 @@ processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq, /* if the cache reply dp equals a validation anchor or msg has DS, * then DNSSEC RRSIGs are expected in the reply */ iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp, - iq->deleg_msg, iq->qchase.qclass); + iq->deleg_msg, iq->qchase.qclass, qstate); /* If the RD flag wasn't set, then we just finish with the * cached referral as the response. */ @@ -1254,7 +1254,7 @@ generate_parentside_target_query(struct module_qstate* qstate, subiq->dp = delegpt_copy(iq->dp, subq->region); subiq->dnssec_expected = iter_indicates_dnssec( qstate->env, subiq->dp, NULL, - subq->qinfo.qclass); + subq->qinfo.qclass, subq); subiq->refetch_glue = 1; } else { subiq->dp = dns_cache_find_delegation(qstate->env, @@ -1264,7 +1264,7 @@ generate_parentside_target_query(struct module_qstate* qstate, if(subiq->dp) { subiq->dnssec_expected = iter_indicates_dnssec( qstate->env, subiq->dp, NULL, - subq->qinfo.qclass); + subq->qinfo.qclass, subq); subiq->refetch_glue = 1; } } @@ -1897,7 +1897,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* see if the next dp is a trust anchor, or a DS was sent * along, indicating dnssec is expected for next zone */ iq->dnssec_expected = iter_indicates_dnssec(qstate->env, - iq->dp, iq->response, iq->qchase.qclass); + iq->dp, iq->response, iq->qchase.qclass, qstate); /* if dnssec, validating then also fetch the key for the DS */ if(iq->dnssec_expected && qstate->env->cfg->prefetch_key && !(qstate->query_flags&BIT_CD)) diff --git a/services/outside_network.c b/services/outside_network.c index 5397e8afb..59482c6ba 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1318,7 +1318,7 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff) /* even 700 msec may be too small */ rtt = 1000; sq->status = serviced_query_PROBE_EDNS; - } else if(vs != -1) { + } else if(vs != -1 || sq->want_dnssec) { sq->status = serviced_query_UDP_EDNS; } else { sq->status = serviced_query_UDP; @@ -1536,7 +1536,7 @@ serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff) if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, *sq->outnet->now_secs, &vs, &edns_lame_known, &rtt)) return 0; - if(vs != -1) + if(vs != -1 || sq->want_dnssec) sq->status = serviced_query_TCP_EDNS; else sq->status = serviced_query_TCP; serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);