diff --git a/src/context.c b/src/context.c index 37f056bf..5b9de124 100644 --- a/src/context.c +++ b/src/context.c @@ -1323,6 +1323,9 @@ getdns_context_create_with_extended_memory_functions( result->return_both_v4_and_v6 = 0; result->return_call_reporting = 0; (void) memset(result->dns64_prefix, 0, 16); + result->dns64_prefix[1] = 0x64; + result->dns64_prefix[2] = 0xff; + result->dns64_prefix[3] = 0x9b; result->specify_class = GETDNS_RRCLASS_IN; /* state data used to detect changes to the system config files diff --git a/src/request-internal.c b/src/request-internal.c index 66e14656..e75c9b4f 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -721,10 +721,13 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, getdns_dns_req *result = NULL; uint32_t klass = context->specify_class; getdns_bindata *dns64_prefix = NULL; - int a_aaaa_query = is_extension_set(extensions, - "return_both_v4_and_v6", context->return_both_v4_and_v6) && - ( request_type == GETDNS_RRTYPE_A || - request_type == GETDNS_RRTYPE_AAAA ); + int dns64 = is_extension_set(extensions, "dns64", context->dns64); + int a_aaaa_query = (dns64 && request_type == GETDNS_RRTYPE_AAAA) || + ( is_extension_set( extensions, "return_both_v4_and_v6" + , context->return_both_v4_and_v6) + && ( request_type == GETDNS_RRTYPE_A + || request_type == GETDNS_RRTYPE_AAAA )); + /* Reserve for the buffer at least one more byte * (to test for udp overflow) (hence the + 1), * And align on the 8 byte boundry (hence the (x + 7) / 8 * 8) @@ -910,7 +913,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->add_warning_for_bad_dns = is_extension_set(extensions, "add_warning_for_bad_dns", context->add_warning_for_bad_dns); - result->dns64 = is_extension_set(extensions, "dns64", context->dns64); + result->dns64 = dns64; if (!getdns_dict_get_bindata(extensions, "dns64_prefix", &dns64_prefix) && dns64_prefix->size == 16) (void) memcpy(result->dns64_prefix, dns64_prefix->data, 16); diff --git a/src/util-internal.c b/src/util-internal.c index 1b154b3a..0bcf9d23 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -563,6 +563,12 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, getdns_list *bad_dns = NULL; _getdns_rrset_spc answer_spc; _getdns_rrset *answer; + uint8_t dns64_address[16]; + + int dns64_translate = req->owner->dns64 && + req->owner->netreqs[1] && + req->request_type == GETDNS_RRTYPE_A && + just_addrs && !just_addrs->numinuse; if (!result) goto error; @@ -667,7 +673,15 @@ _getdns_create_reply_dict(getdns_context *context, getdns_network_req *req, continue; bin_size = rdf_iter->nxt - rdf_iter->pos; - bin_data = rdf_iter->pos; + if (dns64_translate && rr_type == GETDNS_RRTYPE_A) { + (void) memcpy(dns64_address, req->owner->dns64_prefix, 12); + (void) memcpy(dns64_address + 12, rdf_iter->pos, 4); + rr_type = GETDNS_RRTYPE_AAAA; + bin_size = 16; + bin_data = dns64_address; + } + else + bin_data = rdf_iter->pos; if (!set_dict(&rr_dict, getdns_dict_create_with_context(context)) || getdns_dict_util_set_string(rr_dict, "address_type", @@ -1125,6 +1139,13 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) if (! netreq->response_len) continue; + /* Skip dns64 translation if we had IPv6 answers alread */ + if (completed_request->dns64 && + completed_request->netreqs[1] && + netreq->request_type == GETDNS_RRTYPE_A && + just_addrs && just_addrs->numinuse) + continue; + if (netreq->tsig_status == GETDNS_DNSSEC_INSECURE) _getdns_network_validate_tsig(netreq); @@ -1138,7 +1159,6 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request) netreq->dnssec_status == GETDNS_DNSSEC_BOGUS) nbogus++; - if (! completed_request->dnssec_return_all_statuses && ! completed_request->dnssec_return_validation_chain) { if (dnssec_return_status &&