Convert Stream DNS to use isc_buffer API

Drop the whole isc_dnsbuffer API and use new improved isc_buffer API
that provides same functionality as the isc_dnsbuffer unit now.
This commit is contained in:
Ondřej Surý 2022-12-16 13:01:18 +01:00 committed by Artem Boldariev
parent 849d7292ad
commit 6cb6373b5a
6 changed files with 200 additions and 648 deletions

View file

@ -1521,7 +1521,6 @@ gcov:
- for SRC in dns isc; do for DST in dns isc ns; do cp -f "lib/${SRC}/include/${SRC}"/*.h "lib/${DST}/"; done; done
- find bin lib -maxdepth 1 -mindepth 1 -type d -exec cp -f lib/isc/include/isc/buffer.h "{}" \;
- cp -f lib/isc/include/isc/buffer.h lib/isc/netmgr/buffer.h
- cp -f lib/isc/include/isc/dnsbuffer.h lib/isc/netmgr/dnsbuffer.h
- cp -f lib/isc/include/isc/dnsstream.h lib/isc/netmgr/dnsstream.h
# Help gcovr find dlz_dbi.c file
- for DST in ldap mysql mysqldyn sqlite3 wildcard; do cp contrib/dlz/modules/common/dlz_dbi.c "contrib/dlz/modules/${DST}"; done

View file

@ -25,7 +25,6 @@ libisc_la_HEADERS = \
include/isc/crc64.h \
include/isc/deprecated.h \
include/isc/dir.h \
include/isc/dnsbuffer.h \
include/isc/dnsstream.h \
include/isc/endian.h \
include/isc/entropy.h \

View file

@ -1,446 +0,0 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/region.h>
#include <isc/util.h>
#define ISC_DNSBUFFER_STATIC_BUFFER_SIZE (512)
#define ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE (ISC_BUFFER_INCR * 2)
typedef struct isc_dnsbuffer {
isc_buffer_t *current; /* pointer to the currently used buffer */
isc_buffer_t stbuf; /* static memory buffer */
uint8_t buf[ISC_DNSBUFFER_STATIC_BUFFER_SIZE]; /* storage for the static
buffer */
isc_buffer_t *dynbuf; /* resizeable dynamic memory buffer */
isc_mem_t *mctx;
} isc_dnsbuffer_t;
/*
* The 'isc_dnsbuffer_t' object implementation is a thin wrapper on
* top of 'isc_buffer_t' which has the following characteristics:
*
* - provides interface specifically atuned for handling/generating
* DNS messages, especially in the format used for DNS messages over
* TCP;
*
* - avoids allocating dynamic memory when handling small DNS
* messages, while transparently switching to using dynamic memory
* when handling larger messages. This approach significantly
* reduces pressure on the memory allocator, as most of the DNS
* messages are small.
*/
static inline void
isc_dnsbuffer_init(isc_dnsbuffer_t *restrict dnsbuf, isc_mem_t *memctx);
/*!<
* \brief Initialise the 'isc_dnsbuffer_t' object, keep a reference to
* 'memctx' inside the object.
*
* Requires:
*\li 'dnsbuf' is not NULL;
*\li 'memctx' is not NULL.
*/
static inline void
isc_dnsbuffer_uninit(isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Un-initialise the 'isc_dnsbuffer_t' object, de-allocate any
*dynamically allocated memory, detach from an internal memory context
* reference.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline isc_dnsbuffer_t *
isc_dnsbuffer_new(isc_mem_t *memctx);
/*!<
* \brief Allocate and initialise a new 'isc_dnsbuffer_t' object, keep a
* reference to 'memctx' inside the object.
*
* Requires:
*\li 'dnsbuf' is not NULL;
*\li 'memctx' is not NULL.
*/
static inline void
isc_dnsbuffer_free(isc_dnsbuffer_t **restrict pdnsbuf);
/*!<
* \brief Un-initialise and de-allocate the given 'isc_dnsbuffer_t' object.
*
* Requires:
*\li 'pdnsbuf' is not NULL;
*\li 'pdnsbuf' does not point to NULL.
*/
static inline void
isc_dnsbuffer_clear(isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Clear the given 'isc_dnsbuffer_t' object (make it empty).
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline unsigned int
isc_dnsbuffer_length(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Return the total length of the internal memory buffer of
* the given 'isc_dnsbuffer_t' object.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline unsigned int
isc_dnsbuffer_usedlength(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Return the total number of used bytes from the internal
* memory buffer of the given 'isc_dnsbuffer_t' object.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline unsigned int
isc_dnsbuffer_remaininglength(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Return the total number of remaining (unprocessed data)
* bytes from the internal memory buffer of the given
* 'isc_dnsbuffer_t' object.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_remainingregion(const isc_dnsbuffer_t *restrict dnsbuf,
isc_region_t *region);
/*!<
* \brief Make the given 'isc_region_t' object reference remaining
* (unprocessed) data from the internal memory buffer of the given
* 'isc_dnsbuffer_t' object.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_compact(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Compact the internal used memory region of the internal
* memory buffer of the given 'isc_dnsbuffer_t' object so that it
* occurs at the start of the memory buffer. Then used region is
* shrunk by the size of the processed (consumed) region, and the
* consumed region is then made empty. This way the previously
* processed (consumed) amount of memory can be used again without
* resizing/reallocating the buffer.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline bool
isc_dnsbuffer_trycompact(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Compact the internal used memory region of the internal
* memory buffer of the given 'isc_dnsbuffer_t' object in the case
* when the processed (consumed) region is larger or equal in size to
* the unprocessed one.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_consume(isc_dnsbuffer_t *restrict dnsbuf, const unsigned int n);
/*!<
* \brief Consume the given number of bytes from the beginning of
* the unprocessed data region of the given 'isc_dnsbuffer_t' object.
* The call moves the 'current' unprocessed data region pointer by the
* given number of bytes.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_putmem(isc_dnsbuffer_t *restrict dnsbuf, void *buf,
const unsigned int buf_size);
/*!<
* \brief Copy 'buf_size' bytes from the location pointed to by
* 'buf' pointer to the end of the unprocessed data region of the
* given 'isc_dnsbuffer_t' object. Resize/reallocate the internal
* memory buffer if it is too small.
*
* Requires:
*\li 'dnsbuf' is not NULL;
*\li 'buf' is not NULL;
*\li 'buf_size' is greater than '0'.
*/
static inline uint8_t *
isc_dnsbuffer_current(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Return the pointer to the beginning of unprocessed data
* region of the given 'isc_dnsbuffer_t' object ("current pointer").
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline uint16_t
isc_dnsbuffer_peek_uint16be(const isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Lookup an unsigned short (16-bit) value in
* big-endian/network byte order at the beginning of unprocessed data
* region of the given 'isc_dnsbuffer_t' object.
*
* If there is not enough data available in the region, '0' will be
* returned.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline uint16_t
isc_dnsbuffer_consume_uint16be(isc_dnsbuffer_t *restrict dnsbuf);
/*!<
* \brief Read an unsigned short (16-bit) value in
* big-endian/network byte order at the beginning of unprocessed data
* region of the given 'isc_dnsbuffer_t' object.
*
* If there is not enough data available in the region, '0' will be
* returned.
*
* In the case, when the data has been read successfully, the start of
* the unprocessed data region is advanced by two bytes.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_putmem_uint16be(isc_dnsbuffer_t *restrict dnsbuf,
const uint16_t v);
/*!<
* \brief Append a given unsigned short (16-bit) value 'v' converted
* into big-endian/network byte order at the end of unprocessed data
* region of the given 'isc_dnsbuffer_t' object. Resize/reallocate the
* internal memory buffer if it is too small to hold the appended data.
*
* Requires:
*\li 'dnsbuf' is not NULL.
*/
static inline void
isc_dnsbuffer_init(isc_dnsbuffer_t *restrict dnsbuf, isc_mem_t *memctx) {
REQUIRE(dnsbuf != NULL);
REQUIRE(memctx != NULL);
*dnsbuf = (isc_dnsbuffer_t){ .current = &dnsbuf->stbuf };
isc_buffer_init(&dnsbuf->stbuf, &dnsbuf->buf[0], sizeof(dnsbuf->buf));
isc_mem_attach(memctx, &dnsbuf->mctx);
}
static inline void
isc_dnsbuffer_uninit(isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
isc_buffer_clear(&dnsbuf->stbuf);
if (dnsbuf->dynbuf != NULL) {
isc_buffer_free(&dnsbuf->dynbuf);
}
if (dnsbuf->mctx != NULL) {
isc_mem_detach(&dnsbuf->mctx);
}
}
static inline isc_dnsbuffer_t *
isc_dnsbuffer_new(isc_mem_t *memctx) {
isc_dnsbuffer_t *newbuf;
REQUIRE(memctx != NULL);
newbuf = isc_mem_get(memctx, sizeof(*newbuf));
isc_dnsbuffer_init(newbuf, memctx);
return (newbuf);
}
static inline void
isc_dnsbuffer_free(isc_dnsbuffer_t **restrict pdnsbuf) {
isc_dnsbuffer_t *restrict buf = NULL;
isc_mem_t *memctx = NULL;
REQUIRE(pdnsbuf != NULL && *pdnsbuf != NULL);
buf = *pdnsbuf;
isc_mem_attach(buf->mctx, &memctx);
isc_dnsbuffer_uninit(buf);
isc_mem_putanddetach(&memctx, buf, sizeof(*buf));
*pdnsbuf = NULL;
}
static inline void
isc_dnsbuffer_clear(isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
isc_buffer_clear(dnsbuf->current);
}
static inline unsigned int
isc_dnsbuffer_length(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
return (isc_buffer_length(dnsbuf->current));
}
static inline unsigned int
isc_dnsbuffer_usedlength(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
return (isc_buffer_usedlength(dnsbuf->current));
}
static inline unsigned int
isc_dnsbuffer_remaininglength(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
return (isc_buffer_remaininglength(dnsbuf->current));
}
static inline void
isc_dnsbuffer_remainingregion(const isc_dnsbuffer_t *restrict dnsbuf,
isc_region_t *region) {
REQUIRE(dnsbuf != NULL);
REQUIRE(region != NULL);
isc_buffer_remainingregion(dnsbuf->current, region);
}
static inline void
isc_dnsbuffer_compact(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
isc_buffer_compact(dnsbuf->current);
}
static inline bool
isc_dnsbuffer_trycompact(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
if (isc_buffer_consumedlength(dnsbuf->current) >=
isc_dnsbuffer_remaininglength(dnsbuf))
{
isc_dnsbuffer_compact(dnsbuf);
return (true);
}
return (false);
}
static inline void
isc_dnsbuffer_consume(isc_dnsbuffer_t *restrict dnsbuf, const unsigned int n) {
REQUIRE(dnsbuf != NULL);
isc_buffer_forward(dnsbuf->current, n);
}
static inline void
isc_dnsbuffer_putmem(isc_dnsbuffer_t *restrict dnsbuf, void *buf,
const unsigned int buf_size) {
REQUIRE(dnsbuf != NULL);
REQUIRE(buf != NULL);
REQUIRE(buf_size > 0);
if (!(dnsbuf->current == &dnsbuf->stbuf &&
isc_buffer_availablelength(dnsbuf->current) >= buf_size) &&
dnsbuf->dynbuf == NULL)
{
isc_region_t remaining = { 0 };
unsigned int total_size = 0;
isc_buffer_remainingregion(&dnsbuf->stbuf, &remaining);
total_size = remaining.length + buf_size;
if (total_size < ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE) {
total_size = ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE;
}
isc_buffer_allocate(dnsbuf->mctx, &dnsbuf->dynbuf, total_size);
isc_buffer_setautorealloc(dnsbuf->dynbuf, true);
if (remaining.length > 0) {
isc_buffer_putmem(dnsbuf->dynbuf, remaining.base,
remaining.length);
}
dnsbuf->current = dnsbuf->dynbuf;
}
isc_buffer_putmem(dnsbuf->current, buf, buf_size);
}
static inline uint8_t *
isc_dnsbuffer_current(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
return (isc_buffer_current(dnsbuf->current));
}
static inline uint16_t
isc__dnsbuffer_peek_uint16be(const isc_dnsbuffer_t *restrict dnsbuf) {
uint16_t v;
uint8_t *p = (uint8_t *)isc_dnsbuffer_current(dnsbuf);
v = p[0] << 8;
v |= p[1] & 0xFF;
return (v);
}
static inline uint16_t
isc_dnsbuffer_peek_uint16be(const isc_dnsbuffer_t *restrict dnsbuf) {
REQUIRE(dnsbuf != NULL);
if (isc_dnsbuffer_remaininglength(dnsbuf) < sizeof(uint16_t)) {
return (0);
}
return (isc__dnsbuffer_peek_uint16be(dnsbuf));
}
static inline uint16_t
isc_dnsbuffer_consume_uint16be(isc_dnsbuffer_t *restrict dnsbuf) {
uint16_t v;
REQUIRE(dnsbuf != NULL);
if (isc_dnsbuffer_remaininglength(dnsbuf) < sizeof(uint16_t)) {
return (0);
}
v = isc__dnsbuffer_peek_uint16be(dnsbuf);
isc_dnsbuffer_consume(dnsbuf, sizeof(uint16_t));
return (v);
}
static inline void
isc_dnsbuffer_putmem_uint16be(isc_dnsbuffer_t *restrict dnsbuf,
const uint16_t v) {
uint8_t b[2] = { 0 };
REQUIRE(dnsbuf != NULL);
b[0] = v >> 8;
b[1] = v & 0xFF;
isc_dnsbuffer_putmem(dnsbuf, b, sizeof(b));
}

View file

@ -12,12 +12,13 @@
*/
#pragma once
#include <isc/dnsbuffer.h>
#include <isc/buffer.h>
#include <isc/mem.h>
typedef struct isc_dnsstream_assembler isc_dnsstream_assembler_t;
/*!<
* \brief The 'isc_dnsstream_assembler_t' object is built on top of
* 'isc_dnsbuffer_t' and intended to encapsulate the state machine
* 'isc_buffer_t' and intended to encapsulate the state machine
* used for handling DNS messages received in the format used for
* messages transmitted over TCP.
*
@ -34,7 +35,7 @@ typedef struct isc_dnsstream_assembler isc_dnsstream_assembler_t;
* itself makes it trivial to write unit tests for it, leading to
* better verification of its correctness. Another important aspect
* of its functioning is directly related to the fact that it is built
* on top of 'isc_dnsbuffer_t', which tries to manage memory in a
* on top of 'isc_buffer_t', which tries to manage memory in a
* smart way. In particular:
*
*\li It tries to use a static buffer for smaller messages, reducing
@ -86,9 +87,12 @@ more;
message (i.e. someone attempts to send us junk data).
*/
#define ISC_DNSSTREAM_STATIC_BUFFER_SIZE (512)
struct isc_dnsstream_assembler {
isc_dnsbuffer_t dnsbuf; /*!< Internal buffer for assembling DNS
isc_buffer_t dnsbuf; /*!< Internal buffer for assembling DNS
messages. */
uint8_t buf[ISC_DNSSTREAM_STATIC_BUFFER_SIZE];
isc_dnsstream_assembler_cb_t onmsg_cb; /*!< Data processing callback. */
void *cbarg; /*!< Callback argument. */
bool calling_cb; /*<! Callback calling marker. Used to detect recursive
@ -226,7 +230,9 @@ isc_dnsstream_assembler_init(isc_dnsstream_assembler_t *restrict dnsasm,
*dnsasm = (isc_dnsstream_assembler_t){ .result = ISC_R_UNSET };
isc_dnsstream_assembler_setcb(dnsasm, cb, cbarg);
isc_mem_attach(memctx, &dnsasm->mctx);
isc_dnsbuffer_init(&dnsasm->dnsbuf, memctx);
isc_buffer_init(&dnsasm->dnsbuf, dnsasm->buf, sizeof(dnsasm->buf));
isc_buffer_setmctx(&dnsasm->dnsbuf, dnsasm->mctx);
}
static inline void
@ -237,7 +243,8 @@ isc_dnsstream_assembler_uninit(isc_dnsstream_assembler_t *restrict dnsasm) {
* make any sense.
*/
INSIST(dnsasm->calling_cb == false);
isc_dnsbuffer_uninit(&dnsasm->dnsbuf);
isc_buffer_clearmctx(&dnsasm->dnsbuf);
isc_buffer_invalidate(&dnsasm->dnsbuf);
if (dnsasm->mctx != NULL) {
isc_mem_detach(&dnsasm->mctx);
}
@ -286,40 +293,52 @@ isc__dnsstream_assembler_handle_message(
isc_dnsstream_assembler_t *restrict dnsasm, void *userarg) {
bool cont = false;
isc_region_t region = { 0 };
uint16_t dnslen = 0;
isc_result_t result;
uint16_t dnslen = isc_dnsbuffer_peek_uint16be(&dnsasm->dnsbuf);
INSIST(dnsasm->calling_cb == false);
if (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf) < sizeof(uint16_t)) {
result = ISC_R_NOMORE;
} else if (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf) >=
sizeof(uint16_t) &&
dnslen == 0)
{
/*
* Someone seems to send us binary junk or output from /dev/zero
*/
result = ISC_R_RANGE;
isc_dnsbuffer_clear(&dnsasm->dnsbuf);
} else if (dnslen <= (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf) -
result = isc_buffer_peekuint16(&dnsasm->dnsbuf, &dnslen);
switch (result) {
case ISC_R_SUCCESS:
if (dnslen == 0) {
/* This didn't make much sense to me: */
/* isc_buffer_remaininglength(&dnsasm->dnsbuf) >=
* sizeof(uint16_t) && */
/*
* Someone seems to send us binary junk or output from
* /dev/zero
*/
result = ISC_R_RANGE;
isc_buffer_clear(&dnsasm->dnsbuf);
break;
}
if (dnslen > (isc_buffer_remaininglength(&dnsasm->dnsbuf) -
sizeof(uint16_t)))
{
result = ISC_R_SUCCESS;
} else {
result = ISC_R_NOMORE;
{
result = ISC_R_NOMORE;
break;
}
break;
case ISC_R_NOMORE:
break;
default:
UNREACHABLE();
}
dnsasm->result = result;
dnsasm->calling_cb = true;
if (result == ISC_R_SUCCESS) {
(void)isc_dnsbuffer_consume_uint16be(&dnsasm->dnsbuf);
isc_dnsbuffer_remainingregion(&dnsasm->dnsbuf, &region);
(void)isc_buffer_getuint16(&dnsasm->dnsbuf);
isc_buffer_remainingregion(&dnsasm->dnsbuf, &region);
region.length = dnslen;
cont = dnsasm->onmsg_cb(dnsasm, ISC_R_SUCCESS, &region,
dnsasm->cbarg, userarg);
if (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf) >= dnslen) {
isc_dnsbuffer_consume(&dnsasm->dnsbuf, dnslen);
if (isc_buffer_remaininglength(&dnsasm->dnsbuf) >= dnslen) {
isc_buffer_forward(&dnsasm->dnsbuf, dnslen);
}
} else {
cont = false;
@ -342,15 +361,15 @@ isc_dnsstream_assembler_incoming(isc_dnsstream_assembler_t *restrict dnsasm,
INSIST(buf == NULL);
} else {
INSIST(buf != NULL);
isc_dnsbuffer_putmem(&dnsasm->dnsbuf, buf, buf_size);
isc_buffer_putmem(&dnsasm->dnsbuf, buf, buf_size);
}
while (isc__dnsstream_assembler_handle_message(dnsasm, userarg)) {
if (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf) == 0) {
if (isc_buffer_remaininglength(&dnsasm->dnsbuf) == 0) {
break;
}
}
isc_dnsbuffer_trycompact(&dnsasm->dnsbuf);
isc_buffer_trycompact(&dnsasm->dnsbuf);
}
static inline isc_result_t
@ -366,13 +385,13 @@ isc_dnsstream_assembler_remaininglength(
const isc_dnsstream_assembler_t *restrict dnsasm) {
REQUIRE(dnsasm != NULL);
return (isc_dnsbuffer_remaininglength(&dnsasm->dnsbuf));
return (isc_buffer_remaininglength(&dnsasm->dnsbuf));
}
static inline void
isc_dnsstream_assembler_clear(isc_dnsstream_assembler_t *restrict dnsasm) {
REQUIRE(dnsasm != NULL);
isc_dnsbuffer_clear(&dnsasm->dnsbuf);
isc_buffer_clear(&dnsasm->dnsbuf);
dnsasm->result = ISC_R_UNSET;
}

View file

@ -15,7 +15,6 @@
#include <unistd.h>
#include <isc/atomic.h>
#include <isc/dnsbuffer.h>
#include <isc/result.h>
#include <isc/thread.h>
@ -24,15 +23,14 @@
/*
* Stream DNS is a unified transport capable of serving both DNS over
* TCP and DNS over TLS. It is built on top of
* 'isc_dnsstream_assembler_t' and 'isc_dnsbuffer_t'. The first one
* is used for assembling DNS messages in the format used for DNS over
* TCP out of incoming data and is built on top of
* 'isc_dnsbuffer_t'. The 'isc_dnbuffer_t' is a thin wrapper on top of
* 'isc_buffer_t' and is optimised for small (>= 512 bytes) DNS
* messages. For small messages it uses a small static memory buffer,
* but it can automatically switch to a dynamically allocated memory
* buffer for larger ones. This way we avoid unnecessary memory
* allocation requests in most cases, as most DNS messages are small.
* 'isc_dnsstream_assembler_t' which is used for assembling DNS
* messages in the format used for DNS over TCP out of incoming data.
* It is built on top of 'isc_buffer_t' optimised for small (>= 512
* bytes) DNS messages. For small messages it uses a small static
* memory buffer, but it can automatically switch to a larger
* dynamically allocated memory buffer for larger ones. This way we
* avoid unnecessary memory allocation requests in most cases, as most
* DNS messages are small.
*
* The use of 'isc_dnsstream_assembler_t' allows decoupling DNS
* message assembling code from networking code itself, making it
@ -47,22 +45,12 @@
* The writing is done in a simpler manner due to the fact that we
* have full control over the data. For each write request we attempt
* to allocate a 'streamdns_send_req_t' structure, whose main purpose
* is to keep the data required for the send request processing. An
* 'isc_dnsbuffer_t' object is used as a data storage for the reasons
* described above.
* is to keep the data required for the send request processing.
*
* When processing write requests there is an important optimisation:
* we attempt to reuse 'streamdns_send_req_t' objects again, in order
* to avoid memory allocations when:
*
* a) requesting memory for the new 'streamdns_send_req_t' object;
*
* b) resizing the 'isc_dnsbuffer_t' to fit large messages, should it
* be required.
*
* The last characteristic is important as it allows gradually growing
* the reused send buffer in a lazy manner when transmitting multiple
* DNS messages (e.g. during zone transfers).
* to avoid memory allocations when requesting memory for the new
* 'streamdns_send_req_t' object.
*
* To understand how sending is done, start by looking at
* 'isc__nm_async_streamdnssend()'. Additionally also take a look at
@ -1147,7 +1135,7 @@ isc__nm_streamdns_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
return (sock->streamdns.tls_verify_error);
}
return (false);
return (NULL);
}
void

View file

@ -24,6 +24,7 @@
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/buffer.h>
#include <isc/dnsstream.h>
#include <isc/mem.h>
#include <isc/os.h>
@ -34,17 +35,20 @@
#include <tests/isc.h>
#define STATIC_BUFFER_SIZE (512)
#define DYNAMIC_BUFFER_SIZE (STATIC_BUFFER_SIZE + ISC_BUFFER_INCR)
static int
setup_test_dnsbuf(void **state) {
isc_dnsbuffer_t **pdnsbuf = (isc_dnsbuffer_t **)state;
*pdnsbuf = isc_dnsbuffer_new(mctx);
isc_buffer_t **pdnsbuf = (isc_buffer_t **)state;
isc_buffer_allocate(mctx, pdnsbuf, STATIC_BUFFER_SIZE);
return (0);
}
static int
teardown_test_dnsbuf(void **state) {
isc_dnsbuffer_free((isc_dnsbuffer_t **)state);
isc_buffer_free((isc_buffer_t **)state);
return (0);
}
@ -77,8 +81,8 @@ teardown_test_dnsasm(void **state) {
}
ISC_RUN_TEST_IMPL(dnsbuffer_generic_test) {
uint8_t buf[ISC_DNSBUFFER_STATIC_BUFFER_SIZE / 2] = { 0 };
isc_dnsbuffer_t *dnsbuf = (isc_dnsbuffer_t *)*state;
uint8_t buf[STATIC_BUFFER_SIZE / 2] = { 0 };
isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
isc_region_t reg = { 0 };
size_t n = 0;
@ -87,88 +91,74 @@ ISC_RUN_TEST_IMPL(dnsbuffer_generic_test) {
}
/* sanity checks */
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_STATIC_BUFFER_SIZE);
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == 0);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
assert_true(isc_buffer_usedlength(dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == sizeof(buf));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_dnsbuffer_current(dnsbuf) == dnsbuf->buf);
assert_true(dnsbuf->current == &dnsbuf->stbuf);
assert_true(isc_buffer_current(dnsbuf) == dnsbuf->base);
isc_dnsbuffer_clear(dnsbuf);
isc_buffer_clear(dnsbuf);
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_STATIC_BUFFER_SIZE);
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == 0);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
assert_true(isc_buffer_usedlength(dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
assert_true(dnsbuf->current == &dnsbuf->stbuf);
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == sizeof(buf));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_current(dnsbuf) == dnsbuf->base);
assert_true(isc_dnsbuffer_current(dnsbuf) == dnsbuf->buf);
assert_true(dnsbuf->current == &dnsbuf->stbuf);
for (size_t i = 0; i < sizeof(buf);
i++, isc_dnsbuffer_consume(dnsbuf, 1))
for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
{
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == i);
}
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf));
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_dnsbuffer_usedlength(dnsbuf) == sizeof(buf) * 2);
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
assert_true(isc_buffer_usedlength(dnsbuf) == sizeof(buf) * 2);
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_STATIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
assert_true(dnsbuf->current == &dnsbuf->stbuf);
for (size_t i = 0; i < sizeof(buf);
i++, isc_dnsbuffer_consume(dnsbuf, 1))
for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
{
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == i);
}
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
for (size_t i = 0; i < sizeof(buf);
i++, isc_dnsbuffer_consume(dnsbuf, 1))
for (size_t i = 0; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1))
{
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == i);
}
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_dnsbuffer_trycompact(dnsbuf));
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
isc_buffer_trycompact(dnsbuf);
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
isc_dnsbuffer_remainingregion(dnsbuf, &reg);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == reg.length);
isc_buffer_remainingregion(dnsbuf, &reg);
assert_true(isc_buffer_remaininglength(dnsbuf) == reg.length);
assert_true(reg.length == sizeof(buf));
for (size_t i = 0; i < reg.length; i++) {
@ -177,35 +167,33 @@ ISC_RUN_TEST_IMPL(dnsbuffer_generic_test) {
assert_true(d == i);
}
isc_dnsbuffer_consume(dnsbuf, reg.length);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
isc_buffer_forward(dnsbuf, reg.length);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(buf));
isc_dnsbuffer_clear(dnsbuf);
isc_buffer_clear(dnsbuf);
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) == DYNAMIC_BUFFER_SIZE);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
n = ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
n = DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
for (size_t i = 0; i < n; i++) {
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
}
assert_true(isc_dnsbuffer_length(dnsbuf) >
ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE);
assert_true(isc_dnsbuffer_length(dnsbuf) >= n * sizeof(buf));
assert_true(isc_buffer_length(dnsbuf) > DYNAMIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) >= n * sizeof(buf));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == n * sizeof(buf));
assert_true(isc_buffer_remaininglength(dnsbuf) == n * sizeof(buf));
for (size_t i = 0; i < n; i++) {
for (size_t k = 0; k < sizeof(buf);
k++, isc_dnsbuffer_consume(dnsbuf, 1))
k++, isc_buffer_forward(dnsbuf, 1))
{
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == k);
}
@ -213,64 +201,61 @@ ISC_RUN_TEST_IMPL(dnsbuffer_generic_test) {
}
ISC_RUN_TEST_IMPL(dnsbuffer_resize_alloc_test) {
uint8_t buf[ISC_DNSBUFFER_STATIC_BUFFER_SIZE / 2] = { 0 };
isc_dnsbuffer_t *dnsbuf = (isc_dnsbuffer_t *)*state;
uint8_t buf[STATIC_BUFFER_SIZE / 2] = { 0 };
isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
size_t i = 0, n = 0;
for (i = 0; i < sizeof(buf); i++) {
buf[i] = (uint8_t)i;
}
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
for (i = 0; i < (sizeof(buf) / 3) * 2;
i++, isc_dnsbuffer_consume(dnsbuf, 1))
i++, isc_buffer_forward(dnsbuf, 1))
{
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == i);
}
assert_true(isc_dnsbuffer_length(dnsbuf) ==
ISC_DNSBUFFER_STATIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) == STATIC_BUFFER_SIZE);
n = ISC_DNSBUFFER_INITIAL_DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
n = DYNAMIC_BUFFER_SIZE / sizeof(buf) + 1;
for (size_t k = 0; k < n; k++) {
isc_dnsbuffer_putmem(dnsbuf, buf, sizeof(buf));
isc_buffer_putmem(dnsbuf, buf, sizeof(buf));
}
assert_true(isc_dnsbuffer_length(dnsbuf) >=
ISC_DNSBUFFER_STATIC_BUFFER_SIZE);
assert_true(isc_buffer_length(dnsbuf) >= STATIC_BUFFER_SIZE);
for (; i < sizeof(buf); i++, isc_dnsbuffer_consume(dnsbuf, 1)) {
uint8_t *p = isc_dnsbuffer_current(dnsbuf);
for (; i < sizeof(buf); i++, isc_buffer_forward(dnsbuf, 1)) {
uint8_t *p = isc_buffer_current(dnsbuf);
assert_true(*p == i);
}
}
ISC_RUN_TEST_IMPL(dnsbuffer_be_test) {
isc_dnsbuffer_t *dnsbuf = (isc_dnsbuffer_t *)*state;
isc_buffer_t *dnsbuf = (isc_buffer_t *)*state;
const uint16_t u16 = 0xBEEF;
uint16_t *pu16;
uint16_t u16v;
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
assert_true(isc_dnsbuffer_peek_uint16be(dnsbuf) == 0);
assert_true(isc_dnsbuffer_consume_uint16be(dnsbuf) == 0);
isc_buffer_putuint16(dnsbuf, u16);
isc_dnsbuffer_putmem_uint16be(dnsbuf, u16);
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(u16));
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(u16));
pu16 = (uint16_t *)isc_dnsbuffer_current(dnsbuf);
pu16 = (uint16_t *)isc_buffer_current(dnsbuf);
assert_true(*pu16 == htons(u16));
assert_true(isc_dnsbuffer_peek_uint16be(dnsbuf) == u16);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == sizeof(u16));
assert_int_equal(isc_buffer_peekuint16(dnsbuf, &u16v), ISC_R_SUCCESS);
assert_int_equal(u16v, u16);
assert_true(isc_buffer_remaininglength(dnsbuf) == sizeof(u16));
assert_true(isc_dnsbuffer_consume_uint16be(dnsbuf) == u16);
assert_true(isc_dnsbuffer_remaininglength(dnsbuf) == 0);
assert_true(isc_buffer_getuint16(dnsbuf) == u16);
assert_true(isc_buffer_remaininglength(dnsbuf) == 0);
}
typedef struct verify_cbdata {
@ -392,17 +377,18 @@ ISC_RUN_TEST_IMPL(dnsasm_sequence_test) {
ISC_RUN_TEST_IMPL(dnsasm_multiple_messages_test) {
isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
isc_dnsbuffer_t dnsbuf;
isc_buffer_t dnsbuf;
verify_cbdata_t cbdata = { 0 };
size_t verified = 0;
isc_dnsbuffer_init(&dnsbuf, mctx);
isc_dnsbuffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_dnsbuffer_putmem(&dnsbuf, (void *)response, sizeof(response));
isc_dnsbuffer_putmem(&dnsbuf, (void *)request_large,
sizeof(request_large));
isc_dnsbuffer_putmem(&dnsbuf, (void *)response_large,
sizeof(response_large));
isc_buffer_init(&dnsbuf, NULL, 0);
isc_buffer_setmctx(&dnsbuf, mctx);
isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_buffer_putmem(&dnsbuf, (void *)response, sizeof(response));
isc_buffer_putmem(&dnsbuf, (void *)request_large,
sizeof(request_large));
isc_buffer_putmem(&dnsbuf, (void *)response_large,
sizeof(response_large));
cbdata.cont_on_success = false;
@ -411,11 +397,12 @@ ISC_RUN_TEST_IMPL(dnsasm_multiple_messages_test) {
*/
cbdata.verify_message = (uint8_t *)request;
isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
isc_dnsstream_assembler_incoming(
dnsasm, &verified, isc_dnsbuffer_current(&dnsbuf),
isc_dnsbuffer_remaininglength(&dnsbuf));
isc_dnsstream_assembler_incoming(dnsasm, &verified,
isc_buffer_current(&dnsbuf),
isc_buffer_remaininglength(&dnsbuf));
isc_dnsbuffer_uninit(&dnsbuf);
isc_buffer_clearmctx(&dnsbuf);
isc_buffer_invalidate(&dnsbuf);
assert_true(verified == 1);
assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
@ -473,26 +460,28 @@ ISC_RUN_TEST_IMPL(dnsasm_error_data_test) {
isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
verify_cbdata_t cbdata = { 0 };
size_t verified = 0;
isc_dnsbuffer_t dnsbuf;
isc_buffer_t dnsbuf;
uint16_t bad_data = 0;
isc_dnsbuffer_init(&dnsbuf, mctx);
isc_buffer_init(&dnsbuf, NULL, 0);
isc_buffer_setmctx(&dnsbuf, mctx);
isc_dnsbuffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_dnsbuffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
isc_dnsbuffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
isc_dnsbuffer_putmem(&dnsbuf, (void *)response_large,
sizeof(response_large));
isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_buffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
isc_buffer_putmem(&dnsbuf, (void *)&bad_data, sizeof(bad_data));
isc_buffer_putmem(&dnsbuf, (void *)response_large,
sizeof(response_large));
cbdata.cont_on_success = false;
cbdata.verify_message = (uint8_t *)request;
isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
isc_dnsstream_assembler_incoming(
dnsasm, &verified, isc_dnsbuffer_current(&dnsbuf),
isc_dnsbuffer_remaininglength(&dnsbuf));
isc_dnsstream_assembler_incoming(dnsasm, &verified,
isc_buffer_current(&dnsbuf),
isc_buffer_remaininglength(&dnsbuf));
isc_dnsbuffer_uninit(&dnsbuf);
isc_buffer_clearmctx(&dnsbuf);
isc_buffer_invalidate(&dnsbuf);
assert_true(verified == 1);
assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_SUCCESS);
@ -513,7 +502,7 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
verify_cbdata_t cbdata = { 0 };
verify_regions_cbdata_t cbdata_regions = { 0 };
isc_dnsbuffer_t dnsbuf;
isc_buffer_t dnsbuf;
size_t packetno;
isc_region_t packets[] = {
{ (void *)request, sizeof(request) },
@ -528,10 +517,11 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
};
const size_t npackets = sizeof(packets) / sizeof(packets[0]);
isc_dnsbuffer_init(&dnsbuf, mctx);
isc_buffer_init(&dnsbuf, NULL, 0);
isc_buffer_setmctx(&dnsbuf, mctx);
for (size_t i = 0; i < npackets; i++) {
isc_dnsbuffer_putmem(&dnsbuf, packets[i].base,
packets[i].length);
isc_buffer_putmem(&dnsbuf, packets[i].base, packets[i].length);
}
/* process packet by packet */
@ -540,9 +530,9 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
/* process random amount of data */
for (; isc_dnsbuffer_remaininglength(&dnsbuf) > 0;) {
for (; isc_buffer_remaininglength(&dnsbuf) > 0;) {
size_t sz = 1 + isc_random_uniform(
isc_dnsbuffer_remaininglength(&dnsbuf));
isc_buffer_remaininglength(&dnsbuf));
for (bool start = true; packetno < npackets; start = false) {
cbdata.verify_message =
@ -551,7 +541,7 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
if (start) {
isc_dnsstream_assembler_incoming(
dnsasm, &packetno,
isc_dnsbuffer_current(&dnsbuf), sz);
isc_buffer_current(&dnsbuf), sz);
} else {
isc_dnsstream_assembler_incoming(
dnsasm, &packetno, NULL, 0);
@ -564,16 +554,15 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
}
}
isc_dnsbuffer_consume(&dnsbuf, sz);
isc_buffer_forward(&dnsbuf, sz);
}
assert_true(packetno == npackets);
assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
assert_true(isc_dnsbuffer_remaininglength(&dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(&dnsbuf) == 0);
for (size_t i = 0; i < npackets; i++) {
isc_dnsbuffer_putmem(&dnsbuf, packets[i].base,
packets[i].length);
isc_buffer_putmem(&dnsbuf, packets[i].base, packets[i].length);
}
/* try to process multiple packets at once, when possible */
@ -585,44 +574,48 @@ ISC_RUN_TEST_IMPL(dnsasm_torn_randomly_test) {
(void *)&cbdata_regions);
/* process random amount of data */
for (; isc_dnsbuffer_remaininglength(&dnsbuf) > 0;) {
for (; isc_buffer_remaininglength(&dnsbuf) > 0;) {
size_t sz = 1 + isc_random_uniform(
isc_dnsbuffer_remaininglength(&dnsbuf));
isc_buffer_remaininglength(&dnsbuf));
isc_dnsstream_assembler_incoming(
dnsasm, &packetno, isc_dnsbuffer_current(&dnsbuf), sz);
dnsasm, &packetno, isc_buffer_current(&dnsbuf), sz);
isc_dnsbuffer_consume(&dnsbuf, sz);
isc_buffer_forward(&dnsbuf, sz);
}
assert_true(packetno == npackets);
assert_true(isc_dnsstream_assembler_remaininglength(dnsasm) == 0);
assert_true(isc_dnsbuffer_remaininglength(&dnsbuf) == 0);
assert_true(isc_buffer_remaininglength(&dnsbuf) == 0);
isc_dnsbuffer_uninit(&dnsbuf);
isc_buffer_clearmctx(&dnsbuf);
isc_buffer_invalidate(&dnsbuf);
dnsasm->cbarg = NULL; /* to make GCC happy about dangling pointers */
}
ISC_RUN_TEST_IMPL(dnsasm_clear_buffer_within_cb_test) {
isc_dnsstream_assembler_t *dnsasm = (isc_dnsstream_assembler_t *)*state;
verify_cbdata_t cbdata = { 0 };
size_t verified = 0;
isc_dnsbuffer_t dnsbuf;
isc_buffer_t dnsbuf;
isc_dnsbuffer_init(&dnsbuf, mctx);
isc_buffer_init(&dnsbuf, NULL, 0);
isc_buffer_setmctx(&dnsbuf, mctx);
isc_dnsbuffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_dnsbuffer_putmem(&dnsbuf, (void *)&response, sizeof(response));
isc_dnsbuffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
isc_buffer_putmem(&dnsbuf, (void *)&response, sizeof(response));
isc_buffer_putmem(&dnsbuf, (void *)request, sizeof(request));
cbdata.cont_on_success = true;
cbdata.clear_on_success = true;
cbdata.verify_message = (uint8_t *)request;
isc_dnsstream_assembler_setcb(dnsasm, verify_dnsmsg, (void *)&cbdata);
isc_dnsstream_assembler_incoming(
dnsasm, &verified, isc_dnsbuffer_current(&dnsbuf),
isc_dnsbuffer_remaininglength(&dnsbuf));
isc_dnsstream_assembler_incoming(dnsasm, &verified,
isc_buffer_current(&dnsbuf),
isc_buffer_remaininglength(&dnsbuf));
isc_dnsbuffer_uninit(&dnsbuf);
isc_buffer_clearmctx(&dnsbuf);
isc_buffer_invalidate(&dnsbuf);
assert_true(verified == 1);
assert_true(isc_dnsstream_assembler_result(dnsasm) == ISC_R_UNSET);