summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/dns64/dns64.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/unbound/dns64/dns64.c')
-rw-r--r--usr.sbin/unbound/dns64/dns64.c99
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;
}