summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/iterator/iterator.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/unbound/iterator/iterator.c')
-rw-r--r--usr.sbin/unbound/iterator/iterator.c74
1 files changed, 69 insertions, 5 deletions
diff --git a/usr.sbin/unbound/iterator/iterator.c b/usr.sbin/unbound/iterator/iterator.c
index 1548dfcaee6..6ff811a27d0 100644
--- a/usr.sbin/unbound/iterator/iterator.c
+++ b/usr.sbin/unbound/iterator/iterator.c
@@ -1449,6 +1449,39 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
iq->qchase.qname = sname;
iq->qchase.qname_len = slen;
+ if(qstate->env->auth_zones) {
+ /* apply rpz qname triggers after cname */
+ struct dns_msg* forged_response =
+ rpz_callback_from_iterator_cname(qstate, iq);
+ while(forged_response && reply_find_rrset_section_an(
+ forged_response->rep, iq->qchase.qname,
+ iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
+ iq->qchase.qclass)) {
+ /* another cname to follow */
+ if(!handle_cname_response(qstate, iq, forged_response,
+ &sname, &slen)) {
+ errinf(qstate, "malloc failure, CNAME info");
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ iq->qchase.qname = sname;
+ iq->qchase.qname_len = slen;
+ forged_response =
+ rpz_callback_from_iterator_cname(qstate, iq);
+ }
+ if(forged_response != NULL) {
+ qstate->ext_state[id] = module_finished;
+ qstate->return_rcode = LDNS_RCODE_NOERROR;
+ qstate->return_msg = forged_response;
+ iq->response = forged_response;
+ next_state(iq, FINISHED_STATE);
+ if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
+ log_err("rpz: after cached cname, prepend rrsets: out of memory");
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ qstate->return_msg->qinfo = qstate->qinfo;
+ return 0;
+ }
+ }
/* This *is* a query restart, even if it is a cheap
* one. */
iq->dp = NULL;
@@ -2875,7 +2908,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* unset CD if to forwarder(RD set) and not dnssec retry
* (blacklist nonempty) and no trust-anchors are configured
* above the qname or on the first attempt when dnssec is on */
- EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
+ (qstate->env->cfg->disable_edns_do?0:EDNS_DO)|
+ ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
@@ -2940,7 +2974,7 @@ static int
processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id)
{
- int dnsseclame = 0, origtypecname = 0;
+ int dnsseclame = 0, origtypecname = 0, orig_empty_nodata_found;
enum response_type type;
iq->num_current_queries--;
@@ -2960,12 +2994,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
return next_state(iq, QUERYTARGETS_STATE);
}
iq->timeout_count = 0;
+ orig_empty_nodata_found = iq->empty_nodata_found;
type = response_type_from_server(
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
- iq->response, &iq->qinfo_out, iq->dp);
+ iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
iq->chase_to_rd = 0;
/* remove TC flag, if this is erroneously set by TCP upstream */
iq->response->rep->flags &= ~BIT_TC;
+ if(orig_empty_nodata_found != iq->empty_nodata_found &&
+ iq->empty_nodata_found < EMPTY_NODATA_RETRY_COUNT) {
+ /* try to search at another server */
+ if(qstate->reply) {
+ struct delegpt_addr* a = delegpt_find_addr(
+ iq->dp, &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen);
+ /* make selection disprefer it */
+ if(a) a->lame = 1;
+ }
+ return next_state(iq, QUERYTARGETS_STATE);
+ }
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
!iq->auth_zone_response) {
/* When forwarding (RD bit is set), we handle referrals
@@ -3501,7 +3548,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */
type = response_type_from_server(
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
- iq->response, &iq->qchase, iq->dp);
+ iq->response, &iq->qchase, iq->dp, NULL);
if(type == RESPONSE_TYPE_ANSWER) {
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
@@ -3874,6 +3921,23 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
/* explicitly set the EDE string to NULL */
iq->response->rep->reason_bogus_str = NULL;
+ if((qstate->env->cfg->val_log_level >= 2 ||
+ qstate->env->cfg->log_servfail) && qstate->errinf &&
+ !qstate->env->cfg->val_log_squelch) {
+ char* err_str = errinf_to_str_misc(qstate);
+ if(err_str) {
+ size_t err_str_len = strlen(err_str);
+ verbose(VERB_ALGO, "iterator EDE: %s", err_str);
+ /* allocate space and store the error
+ * string */
+ iq->response->rep->reason_bogus_str = regional_alloc(
+ qstate->region,
+ sizeof(char) * (err_str_len+1));
+ memcpy(iq->response->rep->reason_bogus_str,
+ err_str, err_str_len+1);
+ }
+ free(err_str);
+ }
/* we have finished processing this query */
qstate->ext_state[id] = module_finished;
@@ -4098,7 +4162,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
/* normalize and sanitize: easy to delete items from linked lists */
if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name,
- qstate->env->scratch, qstate->env, ie)) {
+ qstate->env->scratch, qstate->env, qstate, ie)) {
/* if 0x20 enabled, start fallback, but we have no message */
if(event == module_event_capsfail && !iq->caps_fallback) {
iq->caps_fallback = 1;