diff options
Diffstat (limited to 'usr.sbin/unbound/dns64/dns64.c')
-rw-r--r-- | usr.sbin/unbound/dns64/dns64.c | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/usr.sbin/unbound/dns64/dns64.c b/usr.sbin/unbound/dns64/dns64.c index 1e31f51e831..83fb027790e 100644 --- a/usr.sbin/unbound/dns64/dns64.c +++ b/usr.sbin/unbound/dns64/dns64.c @@ -573,28 +573,29 @@ static enum module_ext_state handle_event_pass(struct module_qstate* qstate, int id) { struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id]; - if (iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR - && qstate->qinfo.qname_len == 74 - && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) - /* Handle PTR queries for IPv6 addresses. */ - return handle_ipv6_ptr(qstate, id); - - if (qstate->env->cfg->dns64_synthall && - iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) - return generate_type_A_query(qstate, id); + int synth_all_cfg = qstate->env->cfg->dns64_synthall; + int synth_qname = 0; + + if(iq && iq->state == DNS64_NEW_QUERY + && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR + && qstate->qinfo.qname_len == 74 + && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) { + /* Handle PTR queries for IPv6 addresses. */ + return handle_ipv6_ptr(qstate, id); + } - if(dns64_always_synth_for_qname(qstate, id) && - iq && iq->state == DNS64_NEW_QUERY - && !(qstate->query_flags & BIT_CD) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); + if(iq && iq->state == DNS64_NEW_QUERY && + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA && + (synth_all_cfg || + (synth_qname=(dns64_always_synth_for_qname(qstate, id) + && !(qstate->query_flags & BIT_CD))))) { + if(synth_qname) + verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); return generate_type_A_query(qstate, id); } /* We are finished when our sub-query is finished. */ - if (iq && iq->state == DNS64_SUBQUERY_FINISHED) + if(iq && iq->state == DNS64_SUBQUERY_FINISHED) return module_finished; /* Otherwise, pass request to next module. */ @@ -627,32 +628,37 @@ handle_event_moddone(struct module_qstate* qstate, int id) * synthesize in (sec 5.1.2 of RFC6147). * - A successful AAAA query with an answer. */ - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && !(qstate->return_msg && - qstate->return_msg->rep && - reply_find_answer_rrset(&qstate->qinfo, - qstate->return_msg->rep))) - /* not internal, type AAAA, not CD, and no answer RRset, - * So, this is a AAAA noerror/nodata answer */ - return generate_type_A_query(qstate, id); - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && dns64_always_synth_for_qname(qstate, id)) { - /* if it is not internal, AAAA, not CD and listed domain, - * generate from A record and ignore AAAA */ - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); + /* When an AAAA query completes check if we want to perform DNS64 + * synthesis. We skip queries with DNSSEC enabled (!CD) and + * ones generated by us to retrive the A/PTR record to use for + * synth. */ + int could_synth = + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA && + (!iq || iq->state != DNS64_INTERNAL_QUERY) && + !(qstate->query_flags & BIT_CD); + int has_data = /* whether query returned non-empty rrset */ + qstate->return_msg && + qstate->return_msg->rep && + reply_find_answer_rrset(&qstate->qinfo, qstate->return_msg->rep); + int synth_qname = 0; + + if(could_synth && + (!has_data || + (synth_qname=dns64_always_synth_for_qname(qstate, id)))) { + if(synth_qname) + verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); return generate_type_A_query(qstate, id); } /* Store the response in cache. */ - if ( (!iq || !iq->started_no_cache_store) && - qstate->return_msg && qstate->return_msg->rep && - !dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep, - 0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime)) + if( (!iq || !iq->started_no_cache_store) && + qstate->return_msg && + qstate->return_msg->rep && + !dns_cache_store( + qstate->env, &qstate->qinfo, qstate->return_msg->rep, + 0, 0, 0, NULL, + qstate->query_flags, qstate->qstarttime)) log_err("out of memory"); /* do nothing */ @@ -969,10 +975,19 @@ dns64_inform_super(struct module_qstate* qstate, int id, } super_dq->state = DNS64_SUBQUERY_FINISHED; - /* If there is no successful answer, we're done. */ - if (qstate->return_rcode != LDNS_RCODE_NOERROR - || !qstate->return_msg - || !qstate->return_msg->rep) { + /* If there is no successful answer, we're done. + * Guarantee that we have at least a NOERROR reply further on. */ + if(qstate->return_rcode != LDNS_RCODE_NOERROR + || !qstate->return_msg + || !qstate->return_msg->rep) { + return; + } + + /* When no A record is found for synthesis fall back to AAAA again. */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_A && + !reply_find_answer_rrset(&qstate->qinfo, + qstate->return_msg->rep)) { + super_dq->state = DNS64_INTERNAL_QUERY; return; } |