summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/dns64
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2019-12-18 11:04:15 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2019-12-18 11:04:15 +0000
commit4dc56a39845e9269df10b13964307d93622681ea (patch)
tree97ce227ce1c02e3a8a86cef13cb8420dc7947401 /usr.sbin/unbound/dns64
parent80feb8b533ce2d5a9c0115cf2b292e4d5c844f5b (diff)
merge Unbound 1.9.6
Diffstat (limited to 'usr.sbin/unbound/dns64')
-rw-r--r--usr.sbin/unbound/dns64/dns64.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/usr.sbin/unbound/dns64/dns64.c b/usr.sbin/unbound/dns64/dns64.c
index f2834da2bfc..1a569059aff 100644
--- a/usr.sbin/unbound/dns64/dns64.c
+++ b/usr.sbin/unbound/dns64/dns64.c
@@ -191,16 +191,19 @@ uitoa(unsigned n, char* s)
*
* \param ipv6 IPv6 address represented as a 128-bit array in big-endian
* order.
+ * \param ipv6_len length of the ipv6 byte array.
* \param offset Index of the MSB of the IPv4 address embedded in the IPv6
* address.
*/
static uint32_t
-extract_ipv4(const uint8_t ipv6[16], const int offset)
+extract_ipv4(const uint8_t ipv6[], size_t ipv6_len, const int offset)
{
- uint32_t ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8))
- | (uint32_t)ipv6[offset/8+1] << (16 + (offset%8))
- | (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8))
- | (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8));
+ uint32_t ipv4;
+ log_assert(ipv6_len == 16); (void)ipv6_len;
+ ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8))
+ | (uint32_t)ipv6[offset/8+1] << (16 + (offset%8))
+ | (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8))
+ | (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8));
if (offset/8+4 < 16)
ipv4 |= (uint32_t)ipv6[offset/8+4] >> (8 - offset%8);
return ipv4;
@@ -214,22 +217,26 @@ extract_ipv4(const uint8_t ipv6[16], const int offset)
* \param ipv4 IPv4 address represented as an unsigned 32-bit number.
* \param ptr The result will be written here. Must be large enough, be
* careful!
+ * \param nm_len length of the ptr buffer.
*
* \return The number of characters written.
*/
static size_t
-ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4])
+ipv4_to_ptr(uint32_t ipv4, char ptr[], size_t nm_len)
{
static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa";
int i;
char* c = ptr;
+ log_assert(nm_len == MAX_PTR_QNAME_IPV4);
for (i = 0; i < 4; ++i) {
*c = uitoa((unsigned int)(ipv4 % 256), c + 1);
c += *c + 1;
+ log_assert(c < ptr+nm_len);
ipv4 /= 256;
}
+ log_assert(c + sizeof(IPV4_PTR_SUFFIX) <= ptr+nm_len);
memmove(c, IPV4_PTR_SUFFIX, sizeof(IPV4_PTR_SUFFIX));
return c + sizeof(IPV4_PTR_SUFFIX) - ptr;
@@ -241,13 +248,15 @@ ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4])
*
* \param ptr The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa")
* \param ipv6 The result will be written here, in network byte order.
+ * \param ipv6_len length of the ipv6 byte array.
*
* \return 1 on success, 0 on failure.
*/
static int
-ptr_to_ipv6(const char* ptr, uint8_t ipv6[16])
+ptr_to_ipv6(const char* ptr, uint8_t ipv6[], size_t ipv6_len)
{
int i;
+ log_assert(ipv6_len == 16); (void)ipv6_len;
for (i = 0; i < 64; i++) {
int x;
@@ -275,14 +284,20 @@ ptr_to_ipv6(const char* ptr, uint8_t ipv6[16])
* Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix.
*
* \param prefix_addr DNS64 prefix address.
+ * \param prefix_addr_len length of the prefix_addr buffer.
* \param prefix_net CIDR length of the DNS64 prefix. Must be between 0 and 96.
* \param a IPv4 address.
+ * \param a_len length of the a buffer.
* \param aaaa IPv6 address. The result will be written here.
+ * \param aaaa_len length of the aaaa buffer.
*/
static void
-synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
- const uint8_t a[4], uint8_t aaaa[16])
+synthesize_aaaa(const uint8_t prefix_addr[], size_t prefix_addr_len,
+ int prefix_net, const uint8_t a[], size_t a_len, uint8_t aaaa[],
+ size_t aaaa_len)
{
+ log_assert(prefix_addr_len == 16 && a_len == 4 && aaaa_len == 16);
+ (void)prefix_addr_len; (void)a_len; (void)aaaa_len;
memcpy(aaaa, prefix_addr, 16);
aaaa[prefix_net/8+0] |= a[0] >> (0+prefix_net%8);
aaaa[prefix_net/8+1] |= a[0] << (8-prefix_net%8);
@@ -447,7 +462,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
/* Convert the PTR query string to an IPv6 address. */
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
- if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr))
+ if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr,
+ sizeof(sin6.sin6_addr.s6_addr)))
return module_wait_module; /* Let other module handle this. */
/*
@@ -470,7 +486,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4)))
return module_error;
qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr,
- dns64_env->prefix_net), (char*)qinfo.qname);
+ sizeof(sin6.sin6_addr.s6_addr), dns64_env->prefix_net),
+ (char*)qinfo.qname, MAX_PTR_QNAME_IPV4);
/* Create the new sub-query. */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
@@ -740,8 +757,10 @@ dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk,
dd->rr_data[i][1] = 16;
synthesize_aaaa(
((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr,
+ sizeof(((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr),
dns64_env->prefix_net, &fd->rr_data[i][2],
- &dd->rr_data[i][2] );
+ fd->rr_len[i]-2, &dd->rr_data[i][2],
+ dd->rr_len[i]-2);
dd->rr_ttl[i] = fd->rr_ttl[i];
}
@@ -928,6 +947,12 @@ dns64_inform_super(struct module_qstate* qstate, int id,
if(!super_dq) {
super_dq = (struct dns64_qstate*)regional_alloc(super->region,
sizeof(*super_dq));
+ if(!super_dq) {
+ log_err("out of memory");
+ super->return_rcode = LDNS_RCODE_SERVFAIL;
+ super->return_msg = NULL;
+ return;
+ }
super->minfo[id] = super_dq;
memset(super_dq, 0, sizeof(*super_dq));
super_dq->started_no_cache_store = super->no_cache_store;