diff --git a/CHANGES b/CHANGES
index bcc45fda18..9754f4d334 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4409. [bug] DNS64 should exlude mapped addresses by default when
+ a exclude acl is not defined. [RT #42810]
+
4406. [bug] getrrsetbyname with a non absolute name could
trigger a infinite recursion bug in lwresd
and named with lwres configured if when combined
diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h
index b215408000..3d16299bed 100644
--- a/bin/named/include/named/globals.h
+++ b/bin/named/include/named/globals.h
@@ -167,6 +167,8 @@ EXTERN isc_boolean_t ns_g_disable6 INIT(ISC_FALSE);
EXTERN isc_boolean_t ns_g_disable4 INIT(ISC_FALSE);
+EXTERN dns_acl_t * ns_g_mapped INIT(NULL);
+
#undef EXTERN
#undef INIT
diff --git a/bin/named/main.c b/bin/named/main.c
index 539366d8b6..0dcda4e354 100644
--- a/bin/named/main.c
+++ b/bin/named/main.c
@@ -1031,6 +1031,9 @@ static void
cleanup(void) {
destroy_managers();
+ if (ns_g_mapped != NULL)
+ dns_acl_detach(&ns_g_mapped);
+
ns_server_destroy(&ns_g_server);
isc_entropy_detach(&ns_g_entropy);
diff --git a/bin/named/server.c b/bin/named/server.c
index 9872855f9f..21867bd582 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -2073,6 +2073,28 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
return (result);
}
+static isc_result_t
+create_mapped_acl(void) {
+ isc_result_t result;
+ dns_acl_t *acl = NULL;
+ isc_netaddr_t addr = {
+ .family = AF_INET6,
+ .type.in6 = IN6ADDR_V4MAPPED_INIT,
+ .zone = 0
+ };
+
+ result = dns_acl_create(ns_g_mctx, 1, &acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_iptable_addprefix2(acl->iptable, &addr, 96,
+ ISC_TRUE, ISC_FALSE);
+ if (result == ISC_R_SUCCESS)
+ dns_acl_attach(acl, &ns_g_mapped);
+ dns_acl_detach(&acl);
+ return (result);
+}
+
/*
* Configure 'view' according to 'vconfig', taking defaults from 'config'
* where values are missing in 'vconfig'.
@@ -2511,6 +2533,13 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
mctx, 0, &excluded);
if (result != ISC_R_SUCCESS)
goto cleanup;
+ } else {
+ if (ns_g_mapped == NULL) {
+ result = create_mapped_acl();
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ dns_acl_attach(ns_g_mapped, &excluded);
}
obj = NULL;
diff --git a/bin/tests/system/dns64/ns1/example.db b/bin/tests/system/dns64/ns1/example.db
index f3af12605d..7ec0ea5f21 100644
--- a/bin/tests/system/dns64/ns1/example.db
+++ b/bin/tests/system/dns64/ns1/example.db
@@ -36,6 +36,8 @@ a-and-aaaa AAAA 2001::1
A 1.2.3.6
aaaa-only AAAA 2001::2
a-not-mapped A 10.0.0.2
+a-and-mapped AAAA ::ffff:1.2.3.4
+ A 1.2.3.5
mx-only MX 10 ns.example.
cname-excluded-good-a CNAME excluded-good-a
cname-excluded-bad-a CNAME excluded-bad-a
diff --git a/bin/tests/system/dns64/ns2/named.conf b/bin/tests/system/dns64/ns2/named.conf
index afd28dfa1b..6ab28fb957 100644
--- a/bin/tests/system/dns64/ns2/named.conf
+++ b/bin/tests/system/dns64/ns2/named.conf
@@ -49,6 +49,12 @@ options {
suffix ::;
};
+ dns64 2001:bbbb::/96 {
+ clients { 10.53.0.4; };
+ mapped { !rfc1918; any; };
+ suffix ::;
+ };
+
dns64-server "dns64.example.net.";
dns64-contact "hostmaster.example.net.";
dns64 2001:32::/32 { clients { 10.53.0.6; }; };
diff --git a/bin/tests/system/dns64/tests.sh b/bin/tests/system/dns64/tests.sh
index 153f1f815b..07985090d6 100644
--- a/bin/tests/system/dns64/tests.sh
+++ b/bin/tests/system/dns64/tests.sh
@@ -84,6 +84,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I: checking default exclude acl works (::ffff:0.0.0.0/96) ($n)"
+ret=0
+$DIG $DIGOPTS a-and-mapped.example. @10.53.0.2 -b 10.53.0.4 aaaa > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+grep "2001:bbbb::1.2.3.5" dig.out.ns2.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I: checking partially excluded only AAAA lookup works ($n)"
ret=0
$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa > dig.out.ns2.test$n || ret=1
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index fff8e8ff61..a5e2c42196 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -5137,7 +5137,7 @@ options {
if they appear in a domain name's AAAA records, and
DNS64 will be applied to any A records the domain
name owns. If not defined, exclude
- defaults to none.
+ defaults to ::ffff:0.0.0.0/96.
A optional suffix can also
diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h
index e3058a024b..a8b7bffdfb 100644
--- a/lib/isc/unix/include/isc/net.h
+++ b/lib/isc/unix/include/isc/net.h
@@ -47,7 +47,7 @@
* It declares inet_aton(), inet_ntop(), and inet_pton().
*
* It ensures that #INADDR_LOOPBACK, #INADDR_ANY, #IN6ADDR_ANY_INIT,
- * in6addr_any, and in6addr_loopback are available.
+ * IN6ADDR_V4MAPPED_INIT, in6addr_any, and in6addr_loopback are available.
*
* It ensures that IN_MULTICAST() is available to check for multicast
* addresses.
@@ -124,6 +124,15 @@
#endif
#endif
+#ifndef IN6ADDR_V4MAPPED_INIT
+#ifdef s6_addr
+/*% IPv6 v4mapped prefix init */
+#define IN6ADDR_V4MAPPED_INIT { { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 } } }
+#else
+#define IN6ADDR_V4MAPPED_INIT { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 } }
+#endif
+#endif
+
#ifndef IN6_IS_ADDR_V4MAPPED
/*% Is IPv6 address V4 mapped? */
#define IN6_IS_ADDR_V4MAPPED(x) \
diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h
index 8f085c1f13..7eef166020 100644
--- a/lib/isc/win32/include/isc/ipv6.h
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -53,6 +53,9 @@
#ifndef IN6ADDR_LOOPBACK_INIT
#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
#endif
+#ifndef IN6ADDR_V4MAPPED_INIT
+#define IN6ADDR_V4MAPPED_INIT {{ 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 }}
+#endif
LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_any;
LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback;