1 /* $NetBSD: dns64.c,v 1.6 2014/12/10 04:37:58 christos Exp $ */
4 * Copyright (C) 2010, 2011, 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: dns64.c,v 1.8 2011/03/12 04:59:47 tbox Exp */
25 #include <isc/netaddr.h>
26 #include <isc/string.h>
30 #include <dns/dns64.h>
31 #include <dns/rdata.h>
32 #include <dns/rdataset.h>
33 #include <dns/result.h>
36 unsigned char bits
[16]; /*
37 * Prefix + suffix bits.
39 dns_acl_t
* clients
; /*
40 * Which clients get mapped
43 dns_acl_t
* mapped
; /*
44 * IPv4 addresses to be mapped.
46 dns_acl_t
* excluded
; /*
47 * IPv6 addresses that are
48 * treated as not existing.
50 unsigned int prefixlen
; /*
51 * Start of mapped address.
55 ISC_LINK(dns_dns64_t
) link
;
59 dns_dns64_create(isc_mem_t
*mctx
, isc_netaddr_t
*prefix
,
60 unsigned int prefixlen
, isc_netaddr_t
*suffix
,
61 dns_acl_t
*clients
, dns_acl_t
*mapped
, dns_acl_t
*excluded
,
62 unsigned int flags
, dns_dns64_t
**dns64
)
65 unsigned int nbytes
= 16;
67 REQUIRE(prefix
!= NULL
&& prefix
->family
== AF_INET6
);
68 /* Legal prefix lengths from rfc6052.txt. */
69 REQUIRE(prefixlen
== 32 || prefixlen
== 40 || prefixlen
== 48 ||
70 prefixlen
== 56 || prefixlen
== 64 || prefixlen
== 96);
71 REQUIRE(isc_netaddr_prefixok(prefix
, prefixlen
) == ISC_R_SUCCESS
);
72 REQUIRE(dns64
!= NULL
&& *dns64
== NULL
);
75 static const unsigned char zeros
[16];
76 REQUIRE(prefix
->family
== AF_INET6
);
77 nbytes
= prefixlen
/ 8 + 4;
78 /* Bits 64-71 are zeros. rfc6052.txt */
79 if (prefixlen
>= 32 && prefixlen
<= 64)
81 REQUIRE(memcmp(suffix
->type
.in6
.s6_addr
, zeros
, nbytes
) == 0);
84 new = isc_mem_get(mctx
, sizeof(dns_dns64_t
));
86 return (ISC_R_NOMEMORY
);
87 memset(new->bits
, 0, sizeof(new->bits
));
88 memmove(new->bits
, prefix
->type
.in6
.s6_addr
, prefixlen
/ 8);
90 memmove(new->bits
+ nbytes
, suffix
->type
.in6
.s6_addr
+ nbytes
,
94 dns_acl_attach(clients
, &new->clients
);
97 dns_acl_attach(mapped
, &new->mapped
);
100 dns_acl_attach(excluded
, &new->excluded
);
101 new->prefixlen
= prefixlen
;
103 ISC_LINK_INIT(new, link
);
105 isc_mem_attach(mctx
, &new->mctx
);
107 return (ISC_R_SUCCESS
);
111 dns_dns64_destroy(dns_dns64_t
**dns64p
) {
114 REQUIRE(dns64p
!= NULL
&& *dns64p
!= NULL
);
119 REQUIRE(!ISC_LINK_LINKED(dns64
, link
));
121 if (dns64
->clients
!= NULL
)
122 dns_acl_detach(&dns64
->clients
);
123 if (dns64
->mapped
!= NULL
)
124 dns_acl_detach(&dns64
->mapped
);
125 if (dns64
->excluded
!= NULL
)
126 dns_acl_detach(&dns64
->excluded
);
127 isc_mem_putanddetach(&dns64
->mctx
, dns64
, sizeof(*dns64
));
131 dns_dns64_aaaafroma(const dns_dns64_t
*dns64
, const isc_netaddr_t
*reqaddr
,
132 const dns_name_t
*reqsigner
, const dns_aclenv_t
*env
,
133 unsigned int flags
, unsigned char *a
, unsigned char *aaaa
)
135 unsigned int nbytes
, i
;
139 if ((dns64
->flags
& DNS_DNS64_RECURSIVE_ONLY
) != 0 &&
140 (flags
& DNS_DNS64_RECURSIVE
) == 0)
141 return (DNS_R_DISALLOWED
);
143 if ((dns64
->flags
& DNS_DNS64_BREAK_DNSSEC
) == 0 &&
144 (flags
& DNS_DNS64_DNSSEC
) != 0)
145 return (DNS_R_DISALLOWED
);
147 if (dns64
->clients
!= NULL
) {
148 result
= dns_acl_match(reqaddr
, reqsigner
, dns64
->clients
, env
,
150 if (result
!= ISC_R_SUCCESS
)
153 return (DNS_R_DISALLOWED
);
156 if (dns64
->mapped
!= NULL
) {
158 isc_netaddr_t netaddr
;
160 memmove(&ina
.s_addr
, a
, 4);
161 isc_netaddr_fromin(&netaddr
, &ina
);
162 result
= dns_acl_match(&netaddr
, NULL
, dns64
->mapped
, env
,
164 if (result
!= ISC_R_SUCCESS
)
167 return (DNS_R_DISALLOWED
);
170 nbytes
= dns64
->prefixlen
/ 8;
171 INSIST(nbytes
<= 12);
173 memmove(aaaa
, dns64
->bits
, nbytes
);
174 /* Bits 64-71 are zeros. rfc6052.txt */
177 /* Copy mapped address. */
178 for (i
= 0; i
< 4U; i
++) {
179 aaaa
[nbytes
++] = a
[i
];
180 /* Bits 64-71 are zeros. rfc6052.txt */
185 memmove(aaaa
+ nbytes
, dns64
->bits
+ nbytes
, 16 - nbytes
);
186 return (ISC_R_SUCCESS
);
190 dns_dns64_next(dns_dns64_t
*dns64
) {
191 dns64
= ISC_LIST_NEXT(dns64
, link
);
196 dns_dns64_append(dns_dns64list_t
*list
, dns_dns64_t
*dns64
) {
197 ISC_LIST_APPEND(*list
, dns64
, link
);
201 dns_dns64_unlink(dns_dns64list_t
*list
, dns_dns64_t
*dns64
) {
202 ISC_LIST_UNLINK(*list
, dns64
, link
);
206 dns_dns64_aaaaok(const dns_dns64_t
*dns64
, const isc_netaddr_t
*reqaddr
,
207 const dns_name_t
*reqsigner
, const dns_aclenv_t
*env
,
208 unsigned int flags
, dns_rdataset_t
*rdataset
,
209 isc_boolean_t
*aaaaok
, size_t aaaaoklen
)
212 isc_netaddr_t netaddr
;
215 isc_boolean_t answer
= ISC_FALSE
;
216 isc_boolean_t found
= ISC_FALSE
;
219 REQUIRE(rdataset
!= NULL
);
220 REQUIRE(rdataset
->type
== dns_rdatatype_aaaa
);
221 REQUIRE(rdataset
->rdclass
== dns_rdataclass_in
);
223 REQUIRE(aaaaoklen
== dns_rdataset_count(rdataset
));
225 for (;dns64
!= NULL
; dns64
= ISC_LIST_NEXT(dns64
, link
)) {
226 if ((dns64
->flags
& DNS_DNS64_RECURSIVE_ONLY
) != 0 &&
227 (flags
& DNS_DNS64_RECURSIVE
) == 0)
230 if ((dns64
->flags
& DNS_DNS64_BREAK_DNSSEC
) == 0 &&
231 (flags
& DNS_DNS64_DNSSEC
) != 0)
234 * Work out if this dns64 structure applies to this client.
236 if (dns64
->clients
!= NULL
) {
237 result
= dns_acl_match(reqaddr
, reqsigner
,
240 if (result
!= ISC_R_SUCCESS
)
246 if (!found
&& aaaaok
!= NULL
) {
247 for (i
= 0; i
< aaaaoklen
; i
++)
248 aaaaok
[i
] = ISC_FALSE
;
253 * If we are not excluding any addresses then any AAAA
256 if (dns64
->excluded
== NULL
) {
260 for (i
= 0; i
< aaaaoklen
; i
++)
261 aaaaok
[i
] = ISC_TRUE
;
266 for (result
= dns_rdataset_first(rdataset
);
267 result
== ISC_R_SUCCESS
;
268 result
= dns_rdataset_next(rdataset
)) {
269 dns_rdata_t rdata
= DNS_RDATA_INIT
;
270 if (aaaaok
== NULL
|| !aaaaok
[i
]) {
272 dns_rdataset_current(rdataset
, &rdata
);
273 memmove(&in6
.s6_addr
, rdata
.data
, 16);
274 isc_netaddr_fromin6(&netaddr
, &in6
);
276 result
= dns_acl_match(&netaddr
, NULL
,
279 if (result
== ISC_R_SUCCESS
&& match
<= 0) {
283 aaaaok
[i
] = ISC_TRUE
;
291 * Are all addresses ok?
293 if (aaaaok
!= NULL
&& ok
== aaaaoklen
)
298 if (!found
&& aaaaok
!= NULL
) {
299 for (i
= 0; i
< aaaaoklen
; i
++)
300 aaaaok
[i
] = ISC_TRUE
;
302 return (found
? answer
: ISC_TRUE
);