diff options
Diffstat (limited to 'iterator/iter_utils.c')
| -rw-r--r-- | iterator/iter_utils.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 1da21896cb20..cc09fa52461e 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 @@ -306,9 +308,30 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, if(a->bogus) return -1; /* address of server is bogus */ if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) { - log_addr(VERB_ALGO, "skip addr on the donotquery list", - &a->addr, a->addrlen); - return -1; /* server is on the donotquery list */ + if(iter_env->nat64.use_nat64 && + addr_is_ip6(&a->addr, a->addrlen) && + a->addrlen == iter_env->nat64.nat64_prefix_addrlen && + addr_in_common(&a->addr, 128, + &iter_env->nat64.nat64_prefix_addr, + iter_env->nat64.nat64_prefix_net, + iter_env->nat64.nat64_prefix_addrlen) == + iter_env->nat64.nat64_prefix_net) { + /* The NAT64 is enabled, and address is IPv6, it is + * in the NAT64 prefix. It is allowed. + * So that in an IPv6-only cluster without internet + * access, that makes the NAT64 translation continue + * to work. The NAT64 prefix is allowed. */ + /* Otherwise, after a timeout, the already NAT64 + * translated address would be treated differently, + * and that causes confusion. */ + log_addr(VERB_ALGO, "the addr is on the donotquery " + "list, but allowed because it is NAT64", + &a->addr, a->addrlen); + } else { + log_addr(VERB_ALGO, "skip addr on the donotquery list", + &a->addr, a->addrlen); + return -1; /* server is on the donotquery list */ + } } if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) { return -1; /* there is no ip6 available */ @@ -317,6 +340,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, @@ -1511,6 +1548,11 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf, struct delegpt *dp; int nolock = 1; + log_assert((retdpname && retdpnamelen + && dpname_storage && dpname_storage_len > 0) || + (retdpname == NULL && retdpnamelen == NULL + && dpname_storage == NULL && dpname_storage_len == 0)); + /* Check for stub. */ /* Lock both forwards and hints for atomic read. */ lock_rw_rdlock(&qstate->env->fwds->lock); |
