diff --git a/CHANGES b/CHANGES
index 00bf399789..15c48589d4 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 10afa9a609..b0223242a6 100644
--- a/bin/named/include/named/globals.h
+++ b/bin/named/include/named/globals.h
@@ -184,6 +184,8 @@ EXTERN dns_geoip_databases_t *ns_g_geoip INIT(NULL);
EXTERN const char * ns_g_fuzz_named_addr INIT(NULL);
EXTERN ns_fuzz_t ns_g_fuzz_type INIT(ns_fuzz_none);
+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 be283ed23f..7f427ffe3a 100644
--- a/bin/named/main.c
+++ b/bin/named/main.c
@@ -1171,6 +1171,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 ffcc62a331..a2ecdb0bff 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -3007,6 +3007,28 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
}
#endif /* HAVE_DNSTAP */
+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'.
@@ -3472,6 +3494,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
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 21605fdb78..8534835179 100644
--- a/bin/tests/system/dns64/ns1/example.db
+++ b/bin/tests/system/dns64/ns1/example.db
@@ -28,6 +28,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 4e6e31c5eb..6c8f2d0da5 100644
--- a/bin/tests/system/dns64/ns2/named.conf
+++ b/bin/tests/system/dns64/ns2/named.conf
@@ -41,6 +41,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 815d4cbd43..7cfbab55bc 100644
--- a/bin/tests/system/dns64/tests.sh
+++ b/bin/tests/system/dns64/tests.sh
@@ -76,6 +76,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 a3a0d8fdce..5cb6a0ba2a 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -5513,7 +5513,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 f19a98d2f1..7bf6b089dc 100644
--- a/lib/isc/unix/include/isc/net.h
+++ b/lib/isc/unix/include/isc/net.h
@@ -38,7 +38,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.
@@ -115,6 +115,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 aac43e4c13..2b56a0d2a6 100644
--- a/lib/isc/win32/include/isc/ipv6.h
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -44,6 +44,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;