summaryrefslogtreecommitdiff
path: root/iterator/iter_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'iterator/iter_utils.c')
-rw-r--r--iterator/iter_utils.c50
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);