From: Yorgos Thessalonikefs Date: Sat, 1 Nov 2025 14:10:27 +0000 (+0100) Subject: - Fix #1366: Infra cache does not work correctly for NAT64, by X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=024c921dbface1e7373ccea5a7b8cca86a087317;p=thirdparty%2Funbound.git - Fix #1366: Infra cache does not work correctly for NAT64, by moving the NAT64 synthesis from the iterator when selecting a target address, to the delegation point itself when adding target addresses. --- diff --git a/doc/Changelog b/doc/Changelog index 3a8506e61..9829c8feb 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +1 November 2025: Yorgos + - Fix #1366: Infra cache does not work correctly for NAT64, by + moving the NAT64 synthesis from the iterator when selecting a target + address, to the delegation point itself when adding target + addresses. + 27 October 2025: Yorgos - Merge #1331 from Jitka Plesníková: Replace deprecated $function by new $action, for SWIG. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 1da21896c..fb419f9ab 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -253,7 +253,9 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) return 1; } -/** filter out unsuitable targets +/** filter out unsuitable targets. + * Applies NAT64 if needed as well by replacing the IPv4 with the synthesized + * IPv6 address. * @param iter_env: iterator environment with ipv6-support flag. * @param env: module environment with infra cache. * @param name: zone name @@ -317,6 +319,20 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, !addr_is_ip6(&a->addr, a->addrlen)) { return -1; /* there is no ip4 available */ } + if(iter_env->nat64.use_nat64 && !addr_is_ip6(&a->addr, a->addrlen)) { + struct sockaddr_storage real_addr; + socklen_t real_addrlen; + addr_to_nat64(&a->addr, &iter_env->nat64.nat64_prefix_addr, + iter_env->nat64.nat64_prefix_addrlen, + iter_env->nat64.nat64_prefix_net, + &real_addr, &real_addrlen); + log_name_addr(VERB_QUERY, "NAT64 apply: from: ", + name, &a->addr, a->addrlen); + log_name_addr(VERB_QUERY, "NAT64 apply: to: ", + name, &real_addr, real_addrlen); + a->addr = real_addr; + a->addrlen = real_addrlen; + } /* check lameness - need zone , class info */ if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, name, namelen, qtype, &lame, &dnsseclame, &reclame, diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index b17b091e6..f7f374742 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -84,6 +84,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg); /** * Select a valid, nice target to send query to. * Sorting and removing unsuitable targets is combined. + * Adds records to the infra cache if not already there. * * @param iter_env: iterator module global state, with ip6 enabled and * do-not-query-addresses. diff --git a/iterator/iterator.c b/iterator/iterator.c index 071dd0827..836cb36e0 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -2436,8 +2436,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, int tf_policy; struct delegpt_addr* target; struct outbound_entry* outq; - struct sockaddr_storage real_addr; - socklen_t real_addrlen; int auth_fallback = 0; uint8_t* qout_orig = NULL; size_t qout_orig_len = 0; @@ -3060,17 +3058,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->dnssec_lame_query?" but lame_query anyway": ""); } - real_addr = target->addr; - real_addrlen = target->addrlen; - - if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) { - addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr, - ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net, - &real_addr, &real_addrlen); - log_name_addr(VERB_QUERY, "applied NAT64:", - iq->dp->name, &real_addr, real_addrlen); - } - fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query)); outq = (*qstate->env->send_query)(&iq->qinfo_out, iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), @@ -3082,7 +3069,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, !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( - ie, iq), sq_check_ratelimit, &real_addr, real_addrlen, + ie, iq), sq_check_ratelimit, &target->addr, target->addrlen, iq->dp->name, iq->dp->namelen, (iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream), (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), @@ -3099,7 +3086,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); } log_addr(VERB_QUERY, "error sending query to auth server", - &real_addr, real_addrlen); + &target->addr, target->addrlen); if(qstate->env->cfg->qname_minimisation) iq->minimisation_state = SKIP_MINIMISE_STATE; return next_state(iq, QUERYTARGETS_STATE); diff --git a/util/net_help.c b/util/net_help.c index 426ace934..9ad9a3bb8 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -783,7 +783,7 @@ sockaddr_cmp_scopeid(struct sockaddr_storage* addr1, socklen_t len1, } int -addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) +addr_is_ip6(const struct sockaddr_storage* addr, socklen_t len) { if(len == (socklen_t)sizeof(struct sockaddr_in6) && ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) diff --git a/util/net_help.h b/util/net_help.h index 7b8a20642..1f31a89c3 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -307,7 +307,7 @@ int sockaddr_cmp_scopeid(struct sockaddr_storage* addr1, socklen_t len1, * @param len: the length of addr. * @return: true if sockaddr is ip6. */ -int addr_is_ip6(struct sockaddr_storage* addr, socklen_t len); +int addr_is_ip6(const struct sockaddr_storage* addr, socklen_t len); /** * Make sure the sockaddr ends in zeroes. For tree insertion and subsequent