version 1.1.1.2, 2019/01/09 16:48:20 |
version 1.1.1.3, 2020/05/24 19:36:41 |
|
|
* information regarding copyright ownership. |
* information regarding copyright ownership. |
*/ |
*/ |
|
|
#include <config.h> |
|
|
|
#include <stdbool.h> |
#include <stdbool.h> |
|
#include <string.h> |
|
|
#include <isc/list.h> |
#include <isc/list.h> |
#include <isc/mem.h> |
#include <isc/mem.h> |
|
|
#include <dns/rdata.h> |
#include <dns/rdata.h> |
#include <dns/rdataset.h> |
#include <dns/rdataset.h> |
#include <dns/result.h> |
#include <dns/result.h> |
#include <string.h> |
|
|
|
struct dns_dns64 { |
struct dns_dns64 { |
unsigned char bits[16]; /* |
unsigned char bits[16]; /* |
* Prefix + suffix bits. |
* Prefix + suffix bits. |
*/ |
*/ |
dns_acl_t * clients; /* |
dns_acl_t *clients; /* |
* Which clients get mapped |
* Which clients get mapped |
* addresses. |
* addresses. |
*/ |
*/ |
dns_acl_t * mapped; /* |
dns_acl_t *mapped; /* |
* IPv4 addresses to be mapped. |
* IPv4 addresses to be mapped. |
*/ |
*/ |
dns_acl_t * excluded; /* |
dns_acl_t *excluded; /* |
* IPv6 addresses that are |
* IPv6 addresses that are |
* treated as not existing. |
* treated as not existing. |
*/ |
*/ |
unsigned int prefixlen; /* |
unsigned int prefixlen; /* |
* Start of mapped address. |
* Start of mapped address. |
*/ |
*/ |
unsigned int flags; |
unsigned int flags; |
isc_mem_t * mctx; |
isc_mem_t *mctx; |
ISC_LINK(dns_dns64_t) link; |
ISC_LINK(dns_dns64_t) link; |
}; |
}; |
|
|
isc_result_t |
isc_result_t |
dns_dns64_create(isc_mem_t *mctx, const isc_netaddr_t *prefix, |
dns_dns64_create(isc_mem_t *mctx, const isc_netaddr_t *prefix, |
unsigned int prefixlen, const isc_netaddr_t *suffix, |
unsigned int prefixlen, const isc_netaddr_t *suffix, |
dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded, |
dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded, |
unsigned int flags, dns_dns64_t **dns64p) |
unsigned int flags, dns_dns64_t **dns64p) { |
{ |
|
dns_dns64_t *dns64; |
dns_dns64_t *dns64; |
unsigned int nbytes = 16; |
unsigned int nbytes = 16; |
|
|
Line 72 dns_dns64_create(isc_mem_t *mctx, const |
|
Line 69 dns_dns64_create(isc_mem_t *mctx, const |
|
REQUIRE(prefix->family == AF_INET6); |
REQUIRE(prefix->family == AF_INET6); |
nbytes = prefixlen / 8 + 4; |
nbytes = prefixlen / 8 + 4; |
/* Bits 64-71 are zeros. rfc6052.txt */ |
/* Bits 64-71 are zeros. rfc6052.txt */ |
if (prefixlen >= 32 && prefixlen <= 64) |
if (prefixlen >= 32 && prefixlen <= 64) { |
nbytes++; |
nbytes++; |
|
} |
REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0); |
REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0); |
} |
} |
|
|
dns64 = isc_mem_get(mctx, sizeof(dns_dns64_t)); |
dns64 = isc_mem_get(mctx, sizeof(dns_dns64_t)); |
if (dns64 == NULL) |
|
return (ISC_R_NOMEMORY); |
|
memset(dns64->bits, 0, sizeof(dns64->bits)); |
memset(dns64->bits, 0, sizeof(dns64->bits)); |
memmove(dns64->bits, prefix->type.in6.s6_addr, prefixlen / 8); |
memmove(dns64->bits, prefix->type.in6.s6_addr, prefixlen / 8); |
if (suffix != NULL) |
if (suffix != NULL) { |
memmove(dns64->bits + nbytes, suffix->type.in6.s6_addr + nbytes, |
memmove(dns64->bits + nbytes, suffix->type.in6.s6_addr + nbytes, |
16 - nbytes); |
16 - nbytes); |
|
} |
dns64->clients = NULL; |
dns64->clients = NULL; |
if (clients != NULL) |
if (clients != NULL) { |
dns_acl_attach(clients, &dns64->clients); |
dns_acl_attach(clients, &dns64->clients); |
|
} |
dns64->mapped = NULL; |
dns64->mapped = NULL; |
if (mapped != NULL) |
if (mapped != NULL) { |
dns_acl_attach(mapped, &dns64->mapped); |
dns_acl_attach(mapped, &dns64->mapped); |
|
} |
dns64->excluded = NULL; |
dns64->excluded = NULL; |
if (excluded != NULL) |
if (excluded != NULL) { |
dns_acl_attach(excluded, &dns64->excluded); |
dns_acl_attach(excluded, &dns64->excluded); |
|
} |
dns64->prefixlen = prefixlen; |
dns64->prefixlen = prefixlen; |
dns64->flags = flags; |
dns64->flags = flags; |
ISC_LINK_INIT(dns64, link); |
ISC_LINK_INIT(dns64, link); |
Line 114 dns_dns64_destroy(dns_dns64_t **dns64p) |
|
Line 114 dns_dns64_destroy(dns_dns64_t **dns64p) |
|
|
|
REQUIRE(!ISC_LINK_LINKED(dns64, link)); |
REQUIRE(!ISC_LINK_LINKED(dns64, link)); |
|
|
if (dns64->clients != NULL) |
if (dns64->clients != NULL) { |
dns_acl_detach(&dns64->clients); |
dns_acl_detach(&dns64->clients); |
if (dns64->mapped != NULL) |
} |
|
if (dns64->mapped != NULL) { |
dns_acl_detach(&dns64->mapped); |
dns_acl_detach(&dns64->mapped); |
if (dns64->excluded != NULL) |
} |
|
if (dns64->excluded != NULL) { |
dns_acl_detach(&dns64->excluded); |
dns_acl_detach(&dns64->excluded); |
|
} |
isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64)); |
isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64)); |
} |
} |
|
|
isc_result_t |
isc_result_t |
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, |
dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, |
const dns_name_t *reqsigner, const dns_aclenv_t *env, |
const dns_name_t *reqsigner, const dns_aclenv_t *env, |
unsigned int flags, unsigned char *a, unsigned char *aaaa) |
unsigned int flags, unsigned char *a, unsigned char *aaaa) { |
{ |
|
unsigned int nbytes, i; |
unsigned int nbytes, i; |
isc_result_t result; |
isc_result_t result; |
int match; |
int match; |
|
|
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && |
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && |
(flags & DNS_DNS64_RECURSIVE) == 0) |
(flags & DNS_DNS64_RECURSIVE) == 0) |
|
{ |
return (DNS_R_DISALLOWED); |
return (DNS_R_DISALLOWED); |
|
} |
|
|
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && |
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && |
(flags & DNS_DNS64_DNSSEC) != 0) |
(flags & DNS_DNS64_DNSSEC) != 0) |
|
{ |
return (DNS_R_DISALLOWED); |
return (DNS_R_DISALLOWED); |
|
} |
|
|
if (dns64->clients != NULL) { |
if (dns64->clients != NULL) { |
result = dns_acl_match(reqaddr, reqsigner, dns64->clients, |
result = dns_acl_match(reqaddr, reqsigner, dns64->clients, env, |
env, &match, NULL); |
&match, NULL); |
if (result != ISC_R_SUCCESS) |
if (result != ISC_R_SUCCESS) { |
return (result); |
return (result); |
if (match <= 0) |
} |
|
if (match <= 0) { |
return (DNS_R_DISALLOWED); |
return (DNS_R_DISALLOWED); |
|
} |
} |
} |
|
|
if (dns64->mapped != NULL) { |
if (dns64->mapped != NULL) { |
Line 155 dns_dns64_aaaafroma(const dns_dns64_t *d |
|
Line 163 dns_dns64_aaaafroma(const dns_dns64_t *d |
|
|
|
memmove(&ina.s_addr, a, 4); |
memmove(&ina.s_addr, a, 4); |
isc_netaddr_fromin(&netaddr, &ina); |
isc_netaddr_fromin(&netaddr, &ina); |
result = dns_acl_match(&netaddr, NULL, dns64->mapped, |
result = dns_acl_match(&netaddr, NULL, dns64->mapped, env, |
env, &match, NULL); |
&match, NULL); |
if (result != ISC_R_SUCCESS) |
if (result != ISC_R_SUCCESS) { |
return (result); |
return (result); |
if (match <= 0) |
} |
|
if (match <= 0) { |
return (DNS_R_DISALLOWED); |
return (DNS_R_DISALLOWED); |
|
} |
} |
} |
|
|
nbytes = dns64->prefixlen / 8; |
nbytes = dns64->prefixlen / 8; |
Line 168 dns_dns64_aaaafroma(const dns_dns64_t *d |
|
Line 178 dns_dns64_aaaafroma(const dns_dns64_t *d |
|
/* Copy prefix. */ |
/* Copy prefix. */ |
memmove(aaaa, dns64->bits, nbytes); |
memmove(aaaa, dns64->bits, nbytes); |
/* Bits 64-71 are zeros. rfc6052.txt */ |
/* Bits 64-71 are zeros. rfc6052.txt */ |
if (nbytes == 8) |
if (nbytes == 8) { |
aaaa[nbytes++] = 0; |
aaaa[nbytes++] = 0; |
|
} |
/* Copy mapped address. */ |
/* Copy mapped address. */ |
for (i = 0; i < 4U; i++) { |
for (i = 0; i < 4U; i++) { |
aaaa[nbytes++] = a[i]; |
aaaa[nbytes++] = a[i]; |
/* Bits 64-71 are zeros. rfc6052.txt */ |
/* Bits 64-71 are zeros. rfc6052.txt */ |
if (nbytes == 8) |
if (nbytes == 8) { |
aaaa[nbytes++] = 0; |
aaaa[nbytes++] = 0; |
|
} |
} |
} |
/* Copy suffix. */ |
/* Copy suffix. */ |
memmove(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes); |
memmove(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes); |
Line 201 dns_dns64_unlink(dns_dns64list_t *list, |
|
Line 213 dns_dns64_unlink(dns_dns64list_t *list, |
|
bool |
bool |
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, |
dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, |
const dns_name_t *reqsigner, const dns_aclenv_t *env, |
const dns_name_t *reqsigner, const dns_aclenv_t *env, |
unsigned int flags, dns_rdataset_t *rdataset, |
unsigned int flags, dns_rdataset_t *rdataset, bool *aaaaok, |
bool *aaaaok, size_t aaaaoklen) |
size_t aaaaoklen) { |
{ |
|
struct in6_addr in6; |
struct in6_addr in6; |
isc_netaddr_t netaddr; |
isc_netaddr_t netaddr; |
isc_result_t result; |
isc_result_t result; |
Line 215 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
Line 226 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
REQUIRE(rdataset != NULL); |
REQUIRE(rdataset != NULL); |
REQUIRE(rdataset->type == dns_rdatatype_aaaa); |
REQUIRE(rdataset->type == dns_rdatatype_aaaa); |
REQUIRE(rdataset->rdclass == dns_rdataclass_in); |
REQUIRE(rdataset->rdclass == dns_rdataclass_in); |
if (aaaaok != NULL) |
if (aaaaok != NULL) { |
REQUIRE(aaaaoklen == dns_rdataset_count(rdataset)); |
REQUIRE(aaaaoklen == dns_rdataset_count(rdataset)); |
|
} |
|
|
for (;dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) { |
for (; dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) { |
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && |
if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 && |
(flags & DNS_DNS64_RECURSIVE) == 0) |
(flags & DNS_DNS64_RECURSIVE) == 0) |
|
{ |
continue; |
continue; |
|
} |
|
|
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && |
if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 && |
(flags & DNS_DNS64_DNSSEC) != 0) |
(flags & DNS_DNS64_DNSSEC) != 0) |
|
{ |
continue; |
continue; |
|
} |
/* |
/* |
* Work out if this dns64 structure applies to this client. |
* Work out if this dns64 structure applies to this client. |
*/ |
*/ |
if (dns64->clients != NULL) { |
if (dns64->clients != NULL) { |
result = dns_acl_match(reqaddr, reqsigner, |
result = dns_acl_match(reqaddr, reqsigner, |
dns64->clients, env, |
dns64->clients, env, &match, |
&match, NULL); |
NULL); |
if (result != ISC_R_SUCCESS) |
if (result != ISC_R_SUCCESS) { |
continue; |
continue; |
if (match <= 0) |
} |
|
if (match <= 0) { |
continue; |
continue; |
|
} |
} |
} |
|
|
if (!found && aaaaok != NULL) { |
if (!found && aaaaok != NULL) { |
for (i = 0; i < aaaaoklen; i++) |
for (i = 0; i < aaaaoklen; i++) { |
aaaaok[i] = false; |
aaaaok[i] = false; |
|
} |
} |
} |
found = true; |
found = true; |
|
|
Line 251 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
Line 270 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
*/ |
*/ |
if (dns64->excluded == NULL) { |
if (dns64->excluded == NULL) { |
answer = true; |
answer = true; |
if (aaaaok == NULL) |
if (aaaaok == NULL) { |
goto done; |
goto done; |
for (i = 0; i < aaaaoklen; i++) |
} |
|
for (i = 0; i < aaaaoklen; i++) { |
aaaaok[i] = true; |
aaaaok[i] = true; |
|
} |
goto done; |
goto done; |
} |
} |
|
|
i = 0; ok = 0; |
i = 0; |
|
ok = 0; |
for (result = dns_rdataset_first(rdataset); |
for (result = dns_rdataset_first(rdataset); |
result == ISC_R_SUCCESS; |
result == ISC_R_SUCCESS; |
result = dns_rdataset_next(rdataset)) { |
result = dns_rdataset_next(rdataset)) |
|
{ |
dns_rdata_t rdata = DNS_RDATA_INIT; |
dns_rdata_t rdata = DNS_RDATA_INIT; |
if (aaaaok == NULL || !aaaaok[i]) { |
if (aaaaok == NULL || !aaaaok[i]) { |
|
|
dns_rdataset_current(rdataset, &rdata); |
dns_rdataset_current(rdataset, &rdata); |
memmove(&in6.s6_addr, rdata.data, 16); |
memmove(&in6.s6_addr, rdata.data, 16); |
isc_netaddr_fromin6(&netaddr, &in6); |
isc_netaddr_fromin6(&netaddr, &in6); |
Line 274 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
Line 296 dns_dns64_aaaaok(const dns_dns64_t *dns6 |
|
&match, NULL); |
&match, NULL); |
if (result == ISC_R_SUCCESS && match <= 0) { |
if (result == ISC_R_SUCCESS && match <= 0) { |
answer = true; |
answer = true; |
if (aaaaok == NULL) |
if (aaaaok == NULL) { |
goto done; |
goto done; |
|
} |
aaaaok[i] = true; |
aaaaok[i] = true; |
ok++; |
ok++; |
} |
} |
} else |
} else { |
ok++; |
ok++; |
|
} |
i++; |
i++; |
} |
} |
/* |
/* |
* Are all addresses ok? |
* Are all addresses ok? |
*/ |
*/ |
if (aaaaok != NULL && ok == aaaaoklen) |
if (aaaaok != NULL && ok == aaaaoklen) { |
goto done; |
goto done; |
|
} |
} |
} |
|
|
done: |
done: |
if (!found && aaaaok != NULL) { |
if (!found && aaaaok != NULL) { |
for (i = 0; i < aaaaoklen; i++) |
for (i = 0; i < aaaaoklen; i++) { |
aaaaok[i] = true; |
aaaaok[i] = true; |
|
} |
} |
} |
return (found ? answer : true); |
return (found ? answer : true); |
} |
} |