Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / dns64.c
blob156d4e31bc8657a9a42f49b5dd0d12dc9390507d
1 /* $NetBSD: dns64.c,v 1.6 2014/12/10 04:37:58 christos Exp $ */
3 /*
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 */
21 #include <config.h>
23 #include <isc/list.h>
24 #include <isc/mem.h>
25 #include <isc/netaddr.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
29 #include <dns/acl.h>
30 #include <dns/dns64.h>
31 #include <dns/rdata.h>
32 #include <dns/rdataset.h>
33 #include <dns/result.h>
35 struct dns_dns64 {
36 unsigned char bits[16]; /*
37 * Prefix + suffix bits.
39 dns_acl_t * clients; /*
40 * Which clients get mapped
41 * addresses.
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.
53 unsigned int flags;
54 isc_mem_t * mctx;
55 ISC_LINK(dns_dns64_t) link;
58 isc_result_t
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)
64 dns_dns64_t *new;
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);
74 if (suffix != 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)
80 nbytes++;
81 REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0);
84 new = isc_mem_get(mctx, sizeof(dns_dns64_t));
85 if (new == NULL)
86 return (ISC_R_NOMEMORY);
87 memset(new->bits, 0, sizeof(new->bits));
88 memmove(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
89 if (suffix != NULL)
90 memmove(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
91 16 - nbytes);
92 new->clients = NULL;
93 if (clients != NULL)
94 dns_acl_attach(clients, &new->clients);
95 new->mapped = NULL;
96 if (mapped != NULL)
97 dns_acl_attach(mapped, &new->mapped);
98 new->excluded = NULL;
99 if (excluded != NULL)
100 dns_acl_attach(excluded, &new->excluded);
101 new->prefixlen = prefixlen;
102 new->flags = flags;
103 ISC_LINK_INIT(new, link);
104 new->mctx = NULL;
105 isc_mem_attach(mctx, &new->mctx);
106 *dns64 = new;
107 return (ISC_R_SUCCESS);
110 void
111 dns_dns64_destroy(dns_dns64_t **dns64p) {
112 dns_dns64_t *dns64;
114 REQUIRE(dns64p != NULL && *dns64p != NULL);
116 dns64 = *dns64p;
117 *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));
130 isc_result_t
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;
136 isc_result_t result;
137 int match;
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,
149 &match, NULL);
150 if (result != ISC_R_SUCCESS)
151 return (result);
152 if (match <= 0)
153 return (DNS_R_DISALLOWED);
156 if (dns64->mapped != NULL) {
157 struct in_addr ina;
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,
163 &match, NULL);
164 if (result != ISC_R_SUCCESS)
165 return (result);
166 if (match <= 0)
167 return (DNS_R_DISALLOWED);
170 nbytes = dns64->prefixlen / 8;
171 INSIST(nbytes <= 12);
172 /* Copy prefix. */
173 memmove(aaaa, dns64->bits, nbytes);
174 /* Bits 64-71 are zeros. rfc6052.txt */
175 if (nbytes == 8)
176 aaaa[nbytes++] = 0;
177 /* Copy mapped address. */
178 for (i = 0; i < 4U; i++) {
179 aaaa[nbytes++] = a[i];
180 /* Bits 64-71 are zeros. rfc6052.txt */
181 if (nbytes == 8)
182 aaaa[nbytes++] = 0;
184 /* Copy suffix. */
185 memmove(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
186 return (ISC_R_SUCCESS);
189 dns_dns64_t *
190 dns_dns64_next(dns_dns64_t *dns64) {
191 dns64 = ISC_LIST_NEXT(dns64, link);
192 return (dns64);
195 void
196 dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64) {
197 ISC_LIST_APPEND(*list, dns64, link);
200 void
201 dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64) {
202 ISC_LIST_UNLINK(*list, dns64, link);
205 isc_boolean_t
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)
211 struct in6_addr in6;
212 isc_netaddr_t netaddr;
213 isc_result_t result;
214 int match;
215 isc_boolean_t answer = ISC_FALSE;
216 isc_boolean_t found = ISC_FALSE;
217 unsigned int i, ok;
219 REQUIRE(rdataset != NULL);
220 REQUIRE(rdataset->type == dns_rdatatype_aaaa);
221 REQUIRE(rdataset->rdclass == dns_rdataclass_in);
222 if (aaaaok != NULL)
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)
228 continue;
230 if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
231 (flags & DNS_DNS64_DNSSEC) != 0)
232 continue;
234 * Work out if this dns64 structure applies to this client.
236 if (dns64->clients != NULL) {
237 result = dns_acl_match(reqaddr, reqsigner,
238 dns64->clients, env,
239 &match, NULL);
240 if (result != ISC_R_SUCCESS)
241 continue;
242 if (match <= 0)
243 continue;
246 if (!found && aaaaok != NULL) {
247 for (i = 0; i < aaaaoklen; i++)
248 aaaaok[i] = ISC_FALSE;
250 found = ISC_TRUE;
253 * If we are not excluding any addresses then any AAAA
254 * will do.
256 if (dns64->excluded == NULL) {
257 answer = ISC_TRUE;
258 if (aaaaok == NULL)
259 goto done;
260 for (i = 0; i < aaaaoklen; i++)
261 aaaaok[i] = ISC_TRUE;
262 goto done;
265 i = 0; ok = 0;
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,
277 dns64->excluded,
278 env, &match, NULL);
279 if (result == ISC_R_SUCCESS && match <= 0) {
280 answer = ISC_TRUE;
281 if (aaaaok == NULL)
282 goto done;
283 aaaaok[i] = ISC_TRUE;
284 ok++;
286 } else
287 ok++;
288 i++;
291 * Are all addresses ok?
293 if (aaaaok != NULL && ok == aaaaoklen)
294 goto done;
297 done:
298 if (!found && aaaaok != NULL) {
299 for (i = 0; i < aaaaoklen; i++)
300 aaaaok[i] = ISC_TRUE;
302 return (found ? answer : ISC_TRUE);