Compare commits

...
Author SHA1 Message Date
Tony FinchandTony Finch 82a5d96407 Cache decompressed names 2022-12-09 21:35:34 +00:00
Tony FinchandTony Finch 180885fb46 Add a dns_name_append() function
This is maybe redundant wrt dns_name_concatenate() but neither the
documentation nor the code are straightforward enough for me to be
sure.
2022-12-09 21:35:34 +00:00
Tony FinchandTony Finch 8de253181e Avoid mystery numbers when manipulating labels in names
Use some more descriptive macros instead.
2022-12-09 21:35:15 +00:00
Tony FinchandTony Finch 0fc505df97 Embiggen decompression contexts
This partly reverts commit 1d807d84f1 "Shrink decompression contexts",
and while I am adjusting nearly all the calls to dns_name_fromwire()
it seems like a good time to remove all the unused `options`
arguments, to reduce the amount of cleanup churn.

I reworked the code that calls dns_decompress_setpermitted() at least
twice before I understood that it's a no-op. Good grief!

Before this year's changes, the decompression modes were ANY (which
became ALWAYS), NONE (became NEVER), and STRICT, which meant "strictly
follow RFC 3579" wrt whether or not a name is allowed to be compressed
in RDATA. (STRICT became DEFAULT, which in retrospect was a misnomer.)
STRICT was the only mode in which dns_decompress_setmethods() had any
effect, but decompression contexts were not initialized to STRICT and
later toggled (except in the tests), so all this machinery was not
actually used in production.

In practice, we either expect no names to be compressed, or permit any
name to be compressed. This is not entirely Postel's law: there were
compatibility issues around the time RFC 3579 was written, so RRtypes
allocated between RFC 1035 and RFC 3579 might legitimately have compressed
RDATA even though that is formally discouraged.

So after another round of refactoring, "ALWAYS" is now indicated by
the presence of a decompression context, and "NEVER" is indicated by a
NULL dctx pointer, and the mutable mode only remains in a vesigial
place-holder form.
2022-12-09 18:48:06 +00:00
Tony FinchandTony Finch da2abb8840 Parse large messages a little bit faster
dns_message_gettempname() allocates a dns_fixedname_t, which
includes a buffer and an offsets vector, so it is not necessary to
separately allocate a scratch buffer or a fresh offsets vector.

When parsing a message, owner names are deduplicated to collect
records into RRsets. This can require a lot of name comparisons.
Add a place to keep a hash value inside a dns_fixedname_t, and use
it to avoid comparisons.

Together these speed up a large zone transfer by about 2.5%
2022-12-09 12:50:57 +00:00
101 changed files with 1140 additions and 755 deletions
+4
View File
@@ -1,3 +1,7 @@
6044. [performance] Speed up message parsing by avoiding unnecessary
allocations, and by hashing names to reduce the need
to compare them in full. [GL !7197]
6043. [bug] The key file IO locks objects would never get
deleted from the hashtable due to off-by-one error.
[GL #3727]
+1 -2
View File
@@ -297,8 +297,7 @@ print_yaml(dns_dtdata_t *dt) {
isc_buffer_init(&b, m->query_zone.data, m->query_zone.len);
isc_buffer_add(&b, m->query_zone.len);
result = dns_name_fromwire(name, &b, DNS_DECOMPRESS_NEVER, 0,
NULL);
result = dns_name_fromwire(name, &b, NULL, NULL);
if (result == ISC_R_SUCCESS) {
printf(" query_zone: ");
dns_name_print(name, stdout);
+3 -6
View File
@@ -196,22 +196,20 @@ security area and must be paranoid about its input.
fromwire_typename(dns_rdataclass_t class,
dns_rdatatype_t type,
isc_buffer_t *source,
dns_decompress_t dctx,
bool downcase,
dns_decompress_t *dctx,
isc_buffer_t *target);
static dns_result_t
fromwire_classname_typename(dns_rdataclass_t class,
dns_rdatatype_t type,
isc_buffer_t *source,
dns_decompress_t dctx,
bool downcase,
dns_decompress_t *dctx,
isc_buffer_t *target);
`fromwire_classname_typename()` is required to set whether
name compression is allowed, according to RFC 3597.
dctx = dns_decompress_setpermitted(dctx, true); /* or false */
dns_decompress_setpermitted(dctx, true); /* or false */
|Parameter|Description |
|---------|-----------------------|
@@ -219,7 +217,6 @@ name compression is allowed, according to RFC 3597.
|`type`|This should be tested with a `REQUIRE(type == <value>)` statement at the beginning of the function.|
|`source`|This is a `BINARY` buffer with the `active` region containing a resource record in wire format.|
|`dctx`|This is the decompression context and is passed to `dns_name_fromwire()`, along with `downcase`, to enable a compressed domain name to be extracted from the source.|
|`downcase`|This is passed to `dns_name_fromwire()` to say whether the extracted domain name should be downcased during the extraction.|
|`target`|This is a `BINARY` buffer into which the decompressed and checked resource record is written.|
`fromwire_typename()` is a security sensitive routine
+9 -3
View File
@@ -44,9 +44,10 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
dns_name_t *old_name = dns_fixedname_initname(&old_fixed);
uint8_t *new_offsets;
uint8_t *old_offsets;
dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
isc_buffer_t new_buf;
isc_buffer_t old_buf;
dns_decompress_t new_dctx;
dns_decompress_t old_dctx;
/*
* Output buffers may be partially used or undersized.
@@ -72,13 +73,15 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
isc_buffer_add(&new_buf, size);
isc_buffer_setactive(&new_buf, size);
isc_buffer_forward(&new_buf, size / 2);
new_result = dns_name_fromwire(new_name, &new_buf, dctx, 0, NULL);
dns_decompress_init(&new_dctx, &new_buf);
new_result = dns_name_fromwire(new_name, &new_buf, &new_dctx, NULL);
isc_buffer_constinit(&old_buf, data, size);
isc_buffer_add(&old_buf, size);
isc_buffer_setactive(&old_buf, size);
isc_buffer_forward(&old_buf, size / 2);
old_result = old_name_fromwire(old_name, &old_buf, dctx, 0, NULL);
dns_decompress_init(&old_dctx, &old_buf);
old_result = old_name_fromwire(old_name, &old_buf, &old_dctx, NULL);
REQUIRE(new_result == old_result);
REQUIRE(dns_name_equal(new_name, old_name));
@@ -100,5 +103,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
REQUIRE(new_buf.used == old_buf.used);
REQUIRE(new_buf.length == old_buf.length);
dns_decompress_invalidate(&new_dctx);
dns_decompress_invalidate(&old_dctx);
return (0);
}
+2 -2
View File
@@ -144,8 +144,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
* Reject invalid rdata. (Disallow decompression as we are
* reading a packet)
*/
CHECK(dns_rdata_fromwire(&rdata1, rdclass, rdtype, &source,
DNS_DECOMPRESS_NEVER, 0, &target));
CHECK(dns_rdata_fromwire(&rdata1, rdclass, rdtype, &source, NULL,
&target));
assert(rdata1.length == size);
/*
+3 -3
View File
@@ -51,8 +51,8 @@ typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state;
#define BINDABLE(name) (!name->attributes.readonly && !name->attributes.dynamic)
isc_result_t
old_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
unsigned int options, isc_buffer_t *target) {
old_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_buffer_t *target) {
unsigned char *cdata, *ndata;
unsigned int cused; /* Bytes of compressed name data used */
unsigned int nused, labels, n, nmax;
@@ -75,7 +75,7 @@ old_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
downcase = ((options & DNS_NAME_DOWNCASE) != 0);
downcase = false; /* ((options & DNS_NAME_DOWNCASE) != 0) */
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
+2 -2
View File
@@ -17,5 +17,5 @@
* For verifying no functional change in the rewrite of dns_name_fromwire()
*/
isc_result_t
old_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
unsigned int options, isc_buffer_t *target);
old_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_buffer_t *target);
+1 -2
View File
@@ -1128,8 +1128,7 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
dns_rdata_init(&rdata);
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, databuf,
DNS_DECOMPRESS_NEVER, 0, &b));
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, databuf, NULL, &b));
if (rdtype == dns_rdatatype_ds) {
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
+406 -9
View File
@@ -24,6 +24,7 @@
#include <isc/util.h>
#include <dns/compress.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#define HASH_INIT_DJB2 5381
@@ -31,6 +32,11 @@
#define CCTX_MAGIC ISC_MAGIC('C', 'C', 'T', 'X')
#define CCTX_VALID(x) ISC_MAGIC_VALID(x, CCTX_MAGIC)
#define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X')
#define DCTX_VALID(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
#define DCTX_VALID_SOURCE(dctx, source) \
(ISC_MAGIC_VALID(dctx, DCTX_MAGIC) && dctx->source == source)
void
dns_compress_init(dns_compress_t *cctx, isc_mem_t *mctx,
dns_compress_flags_t flags) {
@@ -41,13 +47,13 @@ dns_compress_init(dns_compress_t *cctx, isc_mem_t *mctx,
REQUIRE(mctx != NULL);
if ((flags & DNS_COMPRESS_LARGE) != 0) {
size_t count = (1 << DNS_COMPRESS_LARGEBITS);
size_t size = count * sizeof(*set);
mask = count - 1;
set = isc_mem_allocatex(mctx, size, ISC_MEM_ZERO);
size_t size = (1 << DNS_COMPRESS_LARGEBITS);
size_t bytes = size * sizeof(*set);
set = isc_mem_allocatex(mctx, bytes, ISC_MEM_ZERO);
mask = size - 1;
} else {
mask = ARRAY_SIZE(cctx->smallset) - 1;
set = cctx->smallset;
mask = ARRAY_SIZE(cctx->smallset) - 1;
}
/*
@@ -69,7 +75,9 @@ dns_compress_invalidate(dns_compress_t *cctx) {
if (cctx->set != cctx->smallset) {
isc_mem_free(cctx->mctx, cctx->set);
}
*cctx = (dns_compress_t){ 0 };
cctx->magic = 0;
cctx->mctx = NULL;
cctx->set = NULL;
}
void
@@ -159,12 +167,13 @@ match_wirename(uint8_t *a, uint8_t *b, unsigned int len, bool sensitive) {
static bool
match_suffix(isc_buffer_t *buffer, unsigned int new_coff, uint8_t *sptr,
unsigned int slen, unsigned int old_coff, bool sensitive) {
uint8_t pptr[] = { 0xC0 | (old_coff >> 8), old_coff & 0xff };
uint16_t ptr = old_coff | DNS_NAME_PTRBITS;
uint8_t pptr[] = { ptr >> 8, ptr & 0xff };
uint8_t *bptr = isc_buffer_base(buffer);
unsigned int blen = isc_buffer_usedlength(buffer);
unsigned int llen = sptr[0] + 1;
INSIST(llen <= 64 && llen < slen);
INSIST(DNS_LABEL_ISNORMAL(llen) && llen < slen);
if (blen < new_coff + llen) {
return (false);
@@ -229,7 +238,7 @@ insert_label(dns_compress_t *cctx, isc_buffer_t *buffer, const dns_name_t *name,
*/
unsigned int prefix_len = name->offsets[label];
unsigned int coff = isc_buffer_usedlength(buffer) + prefix_len;
if (coff >= 0x4000 || cctx->count > cctx->mask * 3 / 4) {
if (coff > DNS_NAME_MAXPTR || cctx->count > cctx->mask * 3 / 4) {
return false;
}
for (;;) {
@@ -365,3 +374,391 @@ dns_compress_rollback(dns_compress_t *cctx, unsigned int coff) {
cctx->count--;
}
}
/**********************************************************************/
/*
* *** WARNING ***
*
* The dns_decompress routines deal with raw network data. An error in
* these routines could result in the failure or hijacking of the
* server. (It is more risky than dns_name_fromwire() because here we
* have to handle compression pointers.)
*
* The description of name compression in RFC 1035 section 4.1.4 is
* subtle wrt certain edge cases. The first important sentence is:
*
* > In this scheme, an entire domain name or a list of labels at the
* > end of a domain name is replaced with a pointer to a prior
* > occurance of the same name.
*
* The key word is "prior". This says that compression pointers must
* point strictly earlier in the message (before our "marker" variable),
* which is enough to prevent DoS attacks due to compression loops.
*
* It is possible that we might not have parsed a prior occurance of a
* name as a name, for instance, if it was in the RDATA of a record
* with an unknown RRtype. This makes it difficult to detect dirty
* tricks with pointers and cut parsing short with a FORMERR.
*
* The next important sentence is:
*
* > If a domain name is contained in a part of the message subject to a
* > length field (such as the RDATA section of an RR), and compression
* > is used, the length of the compressed name is used in the length
* > calculation, rather than the length of the expanded name.
*
* When decompressing, this means that the amount of the source buffer
* that we consumed (which is checked wrt the container's length field)
* is the length of the compressed name. A compressed name is defined as
* a sequence of labels ending with the root label or a compression
* pointer, that is, the segment of the name that dns_name_fromwire()
* examines first.
*
* This matters when handling names that play dirty tricks, like:
*
* +---+---+---+---+---+---+
* | 4 | 1 |'a'|192| 0 | 0 |
* +---+---+---+---+---+---+
*
* We start at octet 1. There is an ordinary single character label "a",
* followed by a compression pointer that refers back to octet zero.
* Here there is a label of length 4, which weirdly re-uses the octets
* we already examined as the data for the label. It is followed by the
* root label,
*
* The specification says that the compressed name ends after the first
* zero octet (after the compression pointer) not the second zero octet,
* even though the second octet is later in the message. This shows the
* correct way to set our "consumed" variable.
*/
void
dns_decompress_init(dns_decompress_t *dctx, isc_buffer_t *source) {
REQUIRE(dctx != NULL);
REQUIRE(source != NULL);
*dctx = (dns_decompress_t){
.magic = CCTX_MAGIC,
.source = source,
};
}
void
dns_decompress_findowner(dns_decompress_t *dctx) {
REQUIRE(DCTX_VALID(dctx));
dctx->mode = DNS_DECOMPRESS_FINDOWNER;
}
dns_name_t *
dns_decompress_getowner(dns_decompress_t *dctx) {
REQUIRE(DCTX_VALID(dctx));
REQUIRE(dctx->mode == DNS_DECOMPRESS_EXISTS);
REQUIRE(dctx->cache[dctx->found].name_is_owner);
uint8_t *name_data = dctx->cache[dctx->found].name_data;
uint8_t *offset_name = name_data - offsetof(dns_fixedname_t, data);
dns_name_t *name = (dns_name_t *)offset_name;
INSIST(name->magic == DNS_NAME_MAGIC);
INSIST(name->ndata == name_data);
dctx->mode = DNS_DECOMPRESS_DEFAULT;
return (name);
}
/*
* Restore the message buffer to its state before we marked its
* pointer targets, between:
*
* - max_offset, always the end of the message;
*
* - min_offset, determined by the functions below
*/
static void
decompress_rollback(dns_decompress_t *dctx, uint32_t min_offset) {
isc_buffer_t *source = dctx->source;
uint8_t *base = isc_buffer_base(source);
uint32_t max_offset = isc_buffer_usedlength(source);
uint32_t slot = dctx->count;
while (slot-- > 0) {
uint32_t message_offset = dctx->cache[slot].message_offset;
INSIST(message_offset < max_offset);
if (message_offset < min_offset) {
break;
}
base[message_offset] = dctx->cache[slot].saved_label_length;
dctx->cache[slot] = (dns_decompress_slot_t){};
dctx->count = slot;
}
}
/*
* When dns_rdata_fromwire() fails, it rolls back the consumed part of
* the source buffer, and calls dns_decompress_rollback() to clean up
* the unconsumed rdata.
*
* If it failed because there was not enough space in the rdata target
* buffer, dns_message_parse() will reallocate the buffer and retry,
* so we need to have cleaned up after the first attempt so the second
* attempt does not encounter our mess.
*/
void
dns_decompress_rollback(dns_decompress_t *dctx, isc_buffer_t *source) {
REQUIRE(DCTX_VALID_SOURCE(dctx, source));
decompress_rollback(dctx, isc_buffer_consumedlength(source));
}
/*
* At the end of dns_message_parse() the decompression context is
* invalidated, and we clean up the whole message.
*/
void
dns_decompress_invalidate(dns_decompress_t *dctx) {
REQUIRE(DCTX_VALID(dctx));
decompress_rollback(dctx, 0);
INSIST(dctx->count == 0);
dctx->magic = 0;
dctx->source = NULL;
}
/*
* Add a name to the decompression cache after it has been parsed.
*
* It's mildly annoying that we have to loop over the labels a second
* time, but it's necessary because we don't know the name length
* until the end of the first loop. And it makes error cleanup easier,
* so I guess it isn't too bad.
*/
static void
decompress_add(dns_decompress_t *dctx, dns_name_t *name) {
uint32_t message_offset = isc_buffer_consumedlength(dctx->source);
uint8_t *name_data = isc_buffer_current(dctx->source);
uint8_t name_length = name->length;
uint8_t label_count = name->labels;
bool name_is_owner = dctx->mode == DNS_DECOMPRESS_FINDOWNER;
while (message_offset <= DNS_NAME_MAXPTR &&
dctx->count < ARRAY_SIZE(dctx->cache))
{
uint8_t label_len = *name_data;
if (DNS_LABEL_ISROOT(label_len) || DNS_LABEL_ISPTR(label_len)) {
break;
}
*name_data = dctx->count;
dctx->cache[dctx->count++] = (dns_decompress_slot_t){
.saved_label_length = label_len,
.message_offset = message_offset,
.name_is_owner = name_is_owner,
.label_count = label_count,
.name_length = name_length,
.name_data = name_data,
};
message_offset += label_len + 1;
name_data += label_len + 1;
name_length -= label_len + 1;
label_count -= 1;
name_is_owner = false;
}
}
/*
* dns_name_fromwire() parsed up to a root label
*/
void
dns_decompress_add(dns_decompress_t *dctx, isc_buffer_t *source,
dns_name_t *name) {
REQUIRE(DCTX_VALID_SOURCE(dctx, source));
REQUIRE(isc_buffer_remaininglength(source) >= name->length);
decompress_add(dctx, name);
isc_buffer_forward(source, name->length);
/* we did not find an instant match */
dctx->mode = DNS_DECOMPRESS_DEFAULT;
}
#define CHECK(condition, result) \
if (!(condition)) { \
dctx->mode == DNS_DECOMPRESS_DEFAULT; \
dns_name_reset(name); \
return (result); \
} else
/*
* dns_name_fromwire() parsed up to a compression pointer
*/
isc_result_t
dns_decompress_pointer(dns_decompress_t *dctx, isc_buffer_t *source,
dns_name_t *name, isc_buffer_t *target) {
REQUIRE(DCTX_VALID_SOURCE(dctx, source));
REQUIRE(name != NULL && name->magic == DNS_NAME_MAGIC);
REQUIRE(!dns_name_isabsolute(name));
uint32_t source_remaining = isc_buffer_remaininglength(source);
uint32_t name_len = name->length;
CHECK(name_len + 2 <= source_remaining, ISC_R_UNEXPECTEDEND);
uint8_t *name_src = isc_buffer_current(source);
uint8_t hi = name_src[name_len + 0];
uint8_t lo = name_src[name_len + 1];
uint16_t pointer = DNS_NAME_PTRTARGET(hi, lo);
CHECK(pointer < isc_buffer_consumedlength(source), DNS_R_BADPOINTER);
uint8_t *src_base = isc_buffer_base(source);
uint8_t slot_number = src_base[pointer];
dns_decompress_slot_t *slot = &dctx->cache[slot_number];
/* here we should decompress the hard way instead of giving up */
CHECK(slot->message_offset == pointer, ISC_R_NOTIMPLEMENTED);
/* instant match: our name is just a pointer to another owner name */
if (dctx->mode == DNS_DECOMPRESS_FINDOWNER && slot->name_is_owner &&
name_len == 0)
{
dctx->mode = DNS_DECOMPRESS_EXISTS;
dctx->found = slot_number;
return (ISC_R_EXISTS);
}
dns_name_t suffix = DNS_NAME_INITEMPTY;
suffix.attributes.absolute = true;
suffix.length = slot->name_length;
suffix.labels = slot->label_count;
suffix.ndata = slot->name_data;
isc_result_t result = dns_name_append(name, &suffix, target);
if (result == ISC_R_SUCCESS) {
decompress_add(dctx, name);
isc_buffer_forward(source, name_len + 2); /* and pointer */
}
dctx->mode = DNS_DECOMPRESS_DEFAULT;
return (result);
}
#if 0
static isc_result_t
decompress_unmatched(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_buffer_t *target) {
REQUIRE(DCTX_VALID(dctx));
REQUIRE(dctx->source == source);
REQUIRE(name != NULL && name->magic == DNS_NAME_MAGIC);
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(target);
}
/* in case of failure */
name->ndata = NULL;
name->length = 0;
name->labels = 0;
name->attributes.absolute = false;
uint8_t *const name_buf = isc_buffer_used(target);
const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
isc_buffer_availablelength(target));
dns_offsets_t odata;
uint8_t *offsets = name->offsets != NULL ? name->offsets : odata;
uint32_t name_len = 0;
uint32_t labels = 0;
/*
* After chasing a compression pointer, these variables refer to the
* source buffer as follows:
*
* sb --- mr --- cr --- st --- cd --- sm
*
* sb = source_buf (const)
* mr = marker
* cr = cursor
* st = start (const)
* cd = consumed
* sm = source_max (const)
*
* The marker jumps left for each pointer.
* The cursor steps right for each label.
* The amount of the source we consumed is set once.
*/
const uint8_t *const source_buf = isc_buffer_base(source);
const uint8_t *const source_max = isc_buffer_used(source);
const uint8_t *const start = isc_buffer_current(source);
const uint8_t *marker = start;
const uint8_t *cursor = start;
const uint8_t *consumed = NULL;
/*
* One iteration per label.
*/
while (cursor < source_max) {
const uint8_t label_len = *cursor++;
if (DNS_LABEL_ISNORMAL(label_len)) {
/*
* Normal label: record its offset, and check bounds on
* the name length, which also ensures we don't overrun
* the offsets array. Don't touch any source bytes yet!
* The source bounds check will happen when we loop.
*/
offsets[labels++] = name_len;
/* and then a step to the ri-i-i-i-i-ight */
cursor += label_len;
name_len += label_len + 1;
if (name_len > name_max) {
return (name_max == DNS_NAME_MAXWIRE
? DNS_R_NAMETOOLONG
: ISC_R_NOSPACE);
} else if (DNS_LABEL_ISROOT(label_len)) {
goto root_label;
}
} else if (DNS_LABEL_INVALID(label_len)) {
return (DNS_R_BADLABELTYPE);
} else if (cursor < source_max) {
/*
* Compression pointer. Ensure it does not loop.
*
* Copy multiple labels in one go, to make the most of
* memmove() performance. Start at the marker and finish
* just before the pointer's hi+lo bytes, before the
* cursor. Bounds were already checked.
*/
const uint8_t *pointer = source_buf;
pointer += DNS_NAME_PTRTARGET(label_len, *cursor++);
if (pointer >= marker) {
return (DNS_R_BADPOINTER);
}
const uint32_t copy_len = (cursor - 2) - marker;
uint8_t *const dest = name_buf + name_len - copy_len;
memmove(dest, marker, copy_len);
consumed = consumed != NULL ? consumed : cursor;
/* it's just a jump to the left */
cursor = marker = pointer;
}
}
return (ISC_R_UNEXPECTEDEND);
root_label:;
/*
* Copy labels almost like we do for compression pointers,
* from the marker up to and including the root label.
*/
const uint32_t copy_len = cursor - marker;
memmove(name_buf + name_len - copy_len, marker, copy_len);
consumed = consumed != NULL ? consumed : cursor;
isc_buffer_forward(source, consumed - start);
name->attributes.absolute = true;
name->ndata = name_buf;
name->labels = labels;
name->length = name_len;
isc_buffer_add(target, name_len);
return (ISC_R_SUCCESS);
}
#endif
+12
View File
@@ -20,6 +20,7 @@ dns_fixedname_init(dns_fixedname_t *fixed) {
dns_name_init(&fixed->name, fixed->offsets);
isc_buffer_init(&fixed->buffer, fixed->data, DNS_NAME_MAXWIRE);
dns_name_setbuffer(&fixed->name, &fixed->buffer);
fixed->hash = 0;
}
void
@@ -37,3 +38,14 @@ dns_fixedname_initname(dns_fixedname_t *fixed) {
dns_fixedname_init(fixed);
return (dns_fixedname_name(fixed));
}
void
dns_fixedname_hash(dns_fixedname_t *fixed) {
fixed->hash = dns_name_hash(&fixed->name, false);
}
bool
dns_fixedname_equal(dns_fixedname_t *fixed1, dns_fixedname_t *fixed2) {
return (fixed1->hash == fixed2->hash &&
dns_name_equal(&fixed1->name, &fixed2->name));
}
+1 -1
View File
@@ -51,7 +51,7 @@
#define TOTEXTTYPE "rdata->type"
#define TOTEXTDEF "use_default = true"
#define FROMWIREARGS "rdclass, type, source, dctx, options, target"
#define FROMWIREARGS "rdclass, type, source, dctx, target"
#define FROMWIRECLASS "rdclass"
#define FROMWIRETYPE "type"
#define FROMWIREDEF "use_default = true"
+151 -30
View File
@@ -24,9 +24,7 @@
ISC_LANG_BEGINDECLS
/*! \file dns/compress.h
* Direct manipulation of the structures is strongly discouraged.
*
/*
* A name compression context handles compression of multiple DNS names in
* relation to a single DNS message. The context can be used to selectively
* turn on/off compression for specific names (depending on the RR type,
@@ -100,15 +98,105 @@ struct dns_compress {
};
/*
* Deompression context
* *** WARNING ***
*
* THe dns_decompress routines deal with raw network data. An error in these
* routines could result in the failure or hijacking of the server.
*
* A decompression context handles compression of multiple DNS names in
* relation to a single DNS message.
*
* Depending on the caller's requirements, we either expect all names to be
* uncompressed already, or we allow any name to need decompression
* regardless of whether that is strictly allowed by RFC 3579. Decompression
* is disabled by a NULL decompression context pointer, and allowed by an
* initialized decompression context.
*
* The decompression context has two jobs. It allows us to avoid chasing
* pointers multiple times by keeping a cache of compression pointer targets;
* when we get a cache hit we can re-use a previous name, or part of a name,
* without re-parsing. And it helps dns_message_parse() to match owner names
* when collecting records into an rdataset.
*
* This does not entirely eliminate pointer chasing. We normally encounter
* and cache names before they are used as pointer targets, but it is
* possible for a pointer to refer to the RDATA of a record with an unknown
* RRtype, which we will not have parsed. (Thanks to Peter "habbie" van Dijk
* for pointing out this example.) This means that we can't defend against
* malicious messages that force decompression cache misses.
*/
enum dns_decompress {
/*
* The decompression cache needs to be very fast, ideally faster than
* chasing pointers, or at least negligibly slower than chasing one
* pointer. It also needs to avoid using lots of memory. It is
* difficult to satisfy both of these requirements using a data
* structure that is indexed with the compression pointer's value.
*
* Instead we use a dirty and dangerous trick. This is probably unwise.
*
* After we have parsed a name, we add the possible compression
* pointer targets (the start of each label) to the cache. The label
* length octet in the message is OVERWRITTEN by the cache slot
* number. The cache slot contains the label length that we overwrote,
* and its offset in the message, i.e. its pointer target value.
*
* To look up a compression pointer in the cache, we get the octet in
* the message at the pointer's target, and use that as a cache slot
* number. We cross-check by verifying that the slot's message offset
* matches the pointer target.
*
* When parsing a message, there are two contexts for names.
*
* Inside rdata, the dns_name_t objects passed to dns_name_fromwire()
* are ephemeral; the decompressed name is only retained in the
* dns_rdata_fromwire() target buffer. This means the decompression
* cache must contain enough information about the name without using
* a dns_name_t pointer. All we need is a pointer into the target
* buffer and the length of the name. These will describe a suffix of
* the name when the compression pointer target is not the first label.
*
* Owner names are special because dns_message_parse() needs to match
* them in order to collect records into RRsets. We know that they are
* allocated as dns_fixedname_t objects, so with some offsetof()
* tricks we can find the fixedname's address using its name_data
* pointer. We only need to do this for the first label in a name,
* because we only need to find exact matches.
*/
struct dns_decompress_slot {
uint16_t message_offset : 14;
uint16_t name_is_owner : 1;
uint8_t saved_label_length;
uint8_t label_count;
uint8_t name_length;
uint8_t *name_data;
} __attribute__((__packed__));
/*
* A decompression context contains a little extra state to help with
* matching owner names.
*
* dns_message_parse() calls dns_decompress_findowner() to tell us we
* should check for exact matches on the next call; if we find one, it
* gets stashed in the `found` member so it can be retrieved.
*/
enum {
DNS_DECOMPRESS_DEFAULT,
DNS_DECOMPRESS_PERMITTED,
DNS_DECOMPRESS_NEVER,
DNS_DECOMPRESS_ALWAYS,
DNS_DECOMPRESS_FINDOWNER,
DNS_DECOMPRESS_EXISTS,
};
struct dns_decompress {
unsigned int magic;
unsigned int mode; /*%< findowner state */
unsigned int found; /*%< matching owner */
unsigned int count; /*%< of cache entries */
isc_buffer_t *source; /*%< for safety */
dns_decompress_slot_t cache[256];
};
/**********************************************************************/
void
dns_compress_init(dns_compress_t *cctx, isc_mem_t *mctx,
dns_compress_flags_t flags);
@@ -133,7 +221,6 @@ dns_compress_init(dns_compress_t *cctx, isc_mem_t *mctx,
void
dns_compress_invalidate(dns_compress_t *cctx);
/*%<
* Invalidate the compression structure pointed to by
* 'cctx', freeing any memory that has been allocated.
@@ -144,7 +231,6 @@ dns_compress_invalidate(dns_compress_t *cctx);
void
dns_compress_setpermitted(dns_compress_t *cctx, bool permitted);
/*%<
* Sets whether compression is allowed, according to RFC 3597.
* This can vary depending on the rdata type.
@@ -155,7 +241,6 @@ dns_compress_setpermitted(dns_compress_t *cctx, bool permitted);
bool
dns_compress_getpermitted(dns_compress_t *cctx);
/*%<
* Find out whether compression is allowed, according to RFC 3597.
*
@@ -206,27 +291,63 @@ dns_compress_rollback(dns_compress_t *cctx, unsigned int offset);
*\li 'cctx' is initialized.
*/
/*%
* Set whether decompression is allowed, according to RFC 3597
*/
static inline dns_decompress_t /* inline to suppress code generation */
dns_decompress_setpermitted(dns_decompress_t dctx, bool permitted) {
if (dctx == DNS_DECOMPRESS_NEVER || dctx == DNS_DECOMPRESS_ALWAYS) {
return (dctx);
} else if (permitted) {
return (DNS_DECOMPRESS_PERMITTED);
} else {
return (DNS_DECOMPRESS_DEFAULT);
}
}
/**********************************************************************/
/*%
* Returns whether decompression is allowed here
* The various per-rdatatype fromwire() functions call setpermitted(dctx)
* according to whether RFC 3579 says name compression is allowed inside that
* particular type's RDATA. But (apart from the tests) decompression contexts
* were never initialized in a way that allowed these fromwire setpermitted()
* calls to make any changes. So this function has become a no-op.
*
* The dns_decompress_setpermitted() calls remain as documentation of whether
* an rdatatype allows compression or not, according to RFC 3579, and for
* symmetry with the compression contexts in the towire() functions.
*/
static inline bool /* inline to suppress code generation */
dns_decompress_getpermitted(dns_decompress_t dctx) {
return (dctx == DNS_DECOMPRESS_ALWAYS ||
dctx == DNS_DECOMPRESS_PERMITTED);
}
#define dns_decompress_setpermitted(dctx, permitted) /* no-op */
/*%
* Returns whether decompression is allowed here
*/
#define dns_decompress_getpermitted(dctx) (dctx != NULL)
void
dns_decompress_init(dns_decompress_t *dctx, isc_buffer_t *message);
/*%<
* Initializes 'dctx'.
*
* A pointer to the message buffer is stored in the decompression
* context so that we can ensure that later calls are consistent.
*
* Requires:
*
* \li 'dctx' is not NULL.
*
* \li 'message' is a buffer containing the message.
*/
void
dns_decompress_invalidate(dns_decompress_t *dctx);
/*%<
* Invalidates 'dctx'.
*
* Requires:
*
* \li 'dctx' is a valid decompression context.
*/
void
dns_decompress_rollback(dns_decompress_t *dctx, isc_buffer_t *source);
void
dns_decompress_findowner(dns_decompress_t *dctx);
dns_name_t *
dns_decompress_getowner(dns_decompress_t *dctx);
void
dns_decompress_add(dns_decompress_t *dctx, isc_buffer_t *source,
dns_name_t *name);
isc_result_t
dns_decompress_pointer(dns_decompress_t *dctx, isc_buffer_t *source,
dns_name_t *name, isc_buffer_t *target);
ISC_LANG_ENDDECLS
+7
View File
@@ -62,6 +62,7 @@ struct dns_fixedname {
dns_name_t name;
dns_offsets_t offsets;
isc_buffer_t buffer;
unsigned int hash;
unsigned char data[DNS_NAME_MAXWIRE];
};
@@ -79,4 +80,10 @@ dns_fixedname_name(dns_fixedname_t *fixed);
dns_name_t *
dns_fixedname_initname(dns_fixedname_t *fixed);
void
dns_fixedname_hash(dns_fixedname_t *fixed);
bool
dns_fixedname_equal(dns_fixedname_t *fixed1, dns_fixedname_t *fixed2);
ISC_LANG_ENDDECLS
+4 -6
View File
@@ -307,18 +307,16 @@ struct dns_message {
ISC_LIST(dns_rdata_t) freerdata;
ISC_LIST(dns_rdatalist_t) freerdatalist;
dns_rcode_t tsigstatus;
dns_rcode_t querytsigstatus;
dns_name_t *tsigname; /* Owner name of TSIG, if any
* */
dns_rcode_t tsigstatus;
dns_rcode_t querytsigstatus;
dns_name_t *tsigname; /* Owner of TSIG, if any */
dns_rdataset_t *querytsig;
dns_tsigkey_t *tsigkey;
dst_context_t *tsigctx;
int sigstart;
int timeadjust;
dns_name_t *sig0name; /* Owner name of SIG0, if any
* */
dns_name_t *sig0name; /* Owner of SIG0, if any */
dst_key_t *sig0key;
dns_rcode_t sig0status;
isc_region_t query;
+65 -16
View File
@@ -185,6 +185,38 @@ extern const dns_name_t *dns_wildcardname;
* Standard size of a wire format name
*/
#define DNS_NAME_MAXWIRE 255
/*%
* To get the maximum number of labels, remove the root label, allow 2
* bytes (length and contents) for each label, and reattach the root.
*/
#define DNS_NAME_MAXLABELS (((DNS_NAME_MAXWIRE - 1) / 2) + 1)
/*%
* Maximum length of a normal label
*/
#define DNS_LABEL_MAXLEN 63
/*
* Tests for label length/type bytes. Note the root is also normal.
*/
#define DNS_LABEL_ISROOT(byte) ((byte) == 0)
#define DNS_LABEL_ISNORMAL(byte) ((byte) <= DNS_LABEL_MAXLEN)
#define DNS_LABEL_ISPTR(byte) ((byte) >= 192)
#define DNS_LABEL_INVALID(byte) \
(!DNS_LABEL_ISNORMAL(byte) && !DNS_LABEL_ISPTR(byte))
/*%
* Set these bits to turn a compression offset into a pointer on the wire
* (like DNS_LABEL_ISPTR)
*/
#define DNS_NAME_PTRBITS (192 << 8)
/*%
* Calculate a compression offset from a pointer's bytes on the wire
*/
#define DNS_NAME_PTRTARGET(hi, lo) (256 * (hi) + (lo) & ~DNS_NAME_PTRBITS)
/*%
* Maximum value of a name compression offset
*/
#define DNS_NAME_MAXPTR DNS_NAME_PTRTARGET(0xFF, 0xFF)
/*
* Text output filter procedure.
@@ -680,22 +712,14 @@ dns_name_toregion(const dns_name_t *name, isc_region_t *r);
*/
isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
unsigned int options, isc_buffer_t *target);
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_buffer_t *target);
/*%<
* Copy the possibly-compressed name at source (active region) into target,
* decompressing it.
*
* Notes:
* \li Decompression policy is controlled by 'dctx'.
*
* Security:
*
* \li *** WARNING ***
*
* \li This routine will often be used when 'source' contains raw network
* data. A programming error in this routine could result in a denial
* of service, or in the hijacking of the server.
* \li Decompression is enabled or disabled by 'dctx'.
*
* Requires:
*
@@ -707,9 +731,8 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
* \li 'target' is a valid buffer or 'target' is NULL and 'name' has
* a dedicated buffer.
*
* \li 'dctx' is a valid decompression context.
*
* \li DNS_NAME_DOWNCASE is not set.
* \li 'dctx' is a valid decompression context, or NULL to indicate
* that names must not be compressed.
*
* Ensures:
*
@@ -722,9 +745,8 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
* Result:
* \li Success
* \li Bad Form: Label Length
* \li Bad Form: Unknown Label Type
* \li Bad Form: Name Length
* \li Bad Form: Compression type not allowed
* \li Bad Form: Bad Label Type
* \li Bad Form: Bad compression pointer
* \li Bad Form: Input too short
* \li Resource Limit: Not enough space in buffer
@@ -937,6 +959,33 @@ dns_name_downcase(const dns_name_t *source, dns_name_t *name,
* Note: if source == name, then the result will always be ISC_R_SUCCESS.
*/
isc_result_t
dns_name_append(dns_name_t *name, const dns_name_t *suffix,
isc_buffer_t *target);
/*%<
* Appends 'suffix' onto 'name'
*
* Requires:
*
*\li 'name' is a valid name.
*
*\li 'suffix' is a valid name.
*
*\li 'target' is a valid buffer or 'target' is NULL and 'name' has
* a dedicated buffer.
*
*\li If 'name' is absolute, 'suffix' must be empty.
*
* Ensures:
*
*\li On success, the used space in target is updated.
*
* Returns:
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOSPACE
*\li #DNS_R_NAMETOOLONG
*/
isc_result_t
dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
dns_name_t *name, isc_buffer_t *target);
+1 -2
View File
@@ -281,8 +281,7 @@ dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r);
isc_result_t
dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
dns_rdatatype_t type, isc_buffer_t *source,
dns_decompress_t dctx, unsigned int options,
isc_buffer_t *target);
dns_decompress_t *dctx, isc_buffer_t *target);
/*%<
* Copy the possibly-compressed rdata at source into the target region.
*
-1
View File
@@ -166,7 +166,6 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t;
#define DNS_QMIN_MAXLABELS 7
#define DNS_QMIN_MAX_NO_DELEGATION 3
#define DNS_MAX_LABELS 127
isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
+2 -1
View File
@@ -67,7 +67,8 @@ typedef struct dns_dlzdb dns_dlzdb_t;
typedef ISC_LIST(dns_dlzdb_t) dns_dlzdblist_t;
typedef struct dns_dyndbctx dns_dyndbctx_t;
typedef struct dns_sdlzimplementation dns_sdlzimplementation_t;
typedef enum dns_decompress dns_decompress_t;
typedef struct dns_decompress dns_decompress_t;
typedef struct dns_decompress_slot dns_decompress_slot_t;
typedef struct dns_dispatch dns_dispatch_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchset dns_dispatchset_t;
+2 -4
View File
@@ -354,7 +354,6 @@ struct dns_journal {
uint32_t current_serial; /*%< Current SOA serial */
isc_buffer_t source; /*%< Data from disk */
isc_buffer_t target; /*%< Data from _fromwire check */
dns_decompress_t dctx; /*%< Dummy decompression ctx */
dns_name_t name; /*%< Current domain name */
dns_rdata_t rdata; /*%< Current rdata */
uint32_t ttl; /*%< Current TTL */
@@ -737,7 +736,6 @@ journal_open(isc_mem_t *mctx, const char *filename, bool writable, bool create,
*/
isc_buffer_init(&j->it.source, NULL, 0);
isc_buffer_init(&j->it.target, NULL, 0);
j->it.dctx = DNS_DECOMPRESS_NEVER;
j->state = writable ? JOURNAL_STATE_WRITE : JOURNAL_STATE_READ;
@@ -2034,7 +2032,7 @@ read_one_rr(dns_journal_t *j) {
*/
isc_buffer_setactive(&j->it.source,
j->it.source.used - j->it.source.current);
CHECK(dns_name_fromwire(&j->it.name, &j->it.source, j->it.dctx, 0,
CHECK(dns_name_fromwire(&j->it.name, &j->it.source, NULL,
&j->it.target));
/*
@@ -2066,7 +2064,7 @@ read_one_rr(dns_journal_t *j) {
isc_buffer_setactive(&j->it.source, rdlen);
dns_rdata_reset(&j->it.rdata);
CHECK(dns_rdata_fromwire(&j->it.rdata, rdclass, rdtype, &j->it.source,
j->it.dctx, 0, &j->it.target));
NULL, &j->it.target));
j->it.ttl = ttl;
j->it.xpos += sizeof(journal_rawrrhdr_t) + rrhdr.size;
+2 -4
View File
@@ -2336,10 +2336,8 @@ load_raw(dns_loadctx_t *lctx) {
int target_size = TSIZ;
isc_buffer_t target, buf;
unsigned char *target_mem = NULL;
dns_decompress_t dctx;
callbacks = lctx->callbacks;
dctx = DNS_DECOMPRESS_NEVER;
if (lctx->first) {
result = load_header(lctx);
@@ -2469,7 +2467,7 @@ load_raw(dns_loadctx_t *lctx) {
}
isc_buffer_setactive(&target, (unsigned int)namelen);
result = dns_name_fromwire(name, &target, dctx, 0, NULL);
result = dns_name_fromwire(name, &target, NULL, NULL);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
@@ -2560,7 +2558,7 @@ load_raw(dns_loadctx_t *lctx) {
(unsigned int)rdlen);
result = dns_rdata_fromwire(
&rdata[i], rdatalist.rdclass, rdatalist.type,
&target, dctx, 0, &buf);
&target, NULL, &buf);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
+175 -220
View File
@@ -255,19 +255,18 @@ msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block,
}
/*
* Allocate a new dynamic buffer, and attach it to this message as the
* "current" buffer. (which is always the last on the list, for our
* uses)
* Allocate a new dynamic buffer, attach it to this message as the
* "current" buffer (which is always the last on the list, for our
* uses), and return it.
*/
static isc_result_t
static isc_buffer_t *
newbuffer(dns_message_t *msg, unsigned int size) {
isc_buffer_t *dynbuf;
dynbuf = NULL;
isc_buffer_allocate(msg->mctx, &dynbuf, size);
ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
return (ISC_R_SUCCESS);
return (dynbuf);
}
static isc_buffer_t *
@@ -340,24 +339,6 @@ out:
return (rdatalist);
}
static dns_offsets_t *
newoffsets(dns_message_t *msg) {
dns_msgblock_t *msgblock;
dns_offsets_t *offsets;
msgblock = ISC_LIST_TAIL(msg->offsets);
offsets = msgblock_get(msgblock, dns_offsets_t);
if (offsets == NULL) {
msgblock = msgblock_allocate(msg->mctx, sizeof(dns_offsets_t),
OFFSET_COUNT);
ISC_LIST_APPEND(msg->offsets, msgblock, link);
offsets = msgblock_get(msgblock, dns_offsets_t);
}
return (offsets);
}
static void
msginitheader(dns_message_t *m) {
m->id = 0;
@@ -793,23 +774,26 @@ dns_message_detach(dns_message_t **messagep) {
}
}
static isc_result_t
findname(dns_name_t **foundname, const dns_name_t *target,
dns_namelist_t *section) {
dns_name_t *curr;
static dns_name_t *
findowner(const dns_name_t *ntarget, dns_namelist_t *section) {
/*
* We know that owner names used by dns_message_parse() are
* really fixednames, so INSIST that they look plausible.
*/
dns_fixedname_t *target = (dns_fixedname_t *)ntarget;
INSIST(ntarget->ndata == target->data);
dns_fixedname_hash(target);
for (curr = ISC_LIST_TAIL(*section); curr != NULL;
curr = ISC_LIST_PREV(curr, link))
for (dns_name_t *ncurr = ISC_LIST_TAIL(*section); ncurr != NULL;
ncurr = ISC_LIST_PREV(ncurr, link))
{
if (dns_name_equal(curr, target)) {
if (foundname != NULL) {
*foundname = curr;
}
return (ISC_R_SUCCESS);
dns_fixedname_t *curr = (dns_fixedname_t *)ncurr;
INSIST(ncurr->ndata == curr->data);
if (dns_fixedname_equal(curr, target)) {
return (ncurr);
}
}
return (ISC_R_NOTFOUND);
return (NULL);
}
isc_result_t
@@ -859,52 +843,12 @@ dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type,
return (ISC_R_NOTFOUND);
}
/*
* Read a name from buffer "source".
*/
static isc_result_t
getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
dns_decompress_t dctx) {
isc_buffer_t *scratch;
isc_result_t result;
unsigned int tries;
scratch = currentbuffer(msg);
/*
* First try: use current buffer.
* Second try: allocate a new buffer and use that.
*/
tries = 0;
while (tries < 2) {
result = dns_name_fromwire(name, source, dctx, 0, scratch);
if (result == ISC_R_NOSPACE) {
tries++;
result = newbuffer(msg, SCRATCHPAD_SIZE);
if (result != ISC_R_SUCCESS) {
return (result);
}
scratch = currentbuffer(msg);
dns_name_reset(name);
} else {
return (result);
}
}
UNREACHABLE();
}
static isc_result_t
getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
unsigned int rdatalen, dns_rdata_t *rdata) {
isc_buffer_t *scratch;
isc_result_t result;
unsigned int tries;
unsigned int trysize;
scratch = currentbuffer(msg);
@@ -916,39 +860,20 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
* max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
* (the data will fit if it was not more than 50% compressed)
* Subsequent tries: double buffer size on each try.
* dns_rdata_fromwire() will stop the loop if it gets too large.
*/
tries = 0;
trysize = 0;
/* XXX possibly change this to a while (tries < 2) loop */
for (;;) {
result = dns_rdata_fromwire(rdata, rdclass, rdtype, source, dctx,
scratch);
for (unsigned int size = ISC_MAX(SCRATCHPAD_SIZE, 2 * rdatalen);
result == ISC_R_NOSPACE; size *= 2)
{
scratch = newbuffer(msg, size);
result = dns_rdata_fromwire(rdata, rdclass, rdtype, source,
dctx, 0, scratch);
if (result == ISC_R_NOSPACE) {
if (tries == 0) {
trysize = 2 * rdatalen;
if (trysize < SCRATCHPAD_SIZE) {
trysize = SCRATCHPAD_SIZE;
}
} else {
INSIST(trysize != 0);
if (trysize >= 65535) {
return (ISC_R_NOSPACE);
}
/* XXX DNS_R_RRTOOLONG? */
trysize *= 2;
}
tries++;
result = newbuffer(msg, trysize);
if (result != ISC_R_SUCCESS) {
return (result);
}
scratch = currentbuffer(msg);
} else {
return (result);
}
dctx, scratch);
}
return (result);
}
#define DO_ERROR(r) \
@@ -962,10 +887,9 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
} while (0)
static isc_result_t
getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
unsigned int options) {
isc_region_t r;
unsigned int count;
unsigned int count, remaining;
dns_name_t *name = NULL;
dns_name_t *name2 = NULL;
dns_rdataset_t *rdataset = NULL;
@@ -981,55 +905,57 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
name = NULL;
dns_message_gettempname(msg, &name);
name->offsets = (unsigned char *)newoffsets(msg);
free_name = true;
/*
* Parse the name out of this packet.
* Parse the owner name, looking for matches. (Unlikely for the
* question, but matching does not harm the common case.)
*/
isc_buffer_remainingregion(source, &r);
isc_buffer_setactive(source, r.length);
result = getname(name, source, msg, dctx);
if (result != ISC_R_SUCCESS) {
remaining = isc_buffer_remaininglength(source);
isc_buffer_setactive(source, remaining);
dns_decompress_findowner(dctx);
result = dns_name_fromwire(name, source, dctx, NULL);
if (result == ISC_R_EXISTS) {
/*
* We found an instant match for the name.
*/
name2 = dns_decompress_getowner(dctx);
} else if (result == ISC_R_SUCCESS) {
/*
* Scan the section for matching names.
*/
name2 = findowner(name, section);
} else {
goto cleanup;
}
/*
* Run through the section, looking to see if this name
* is already there. If it is found, put back the allocated
* name since we no longer need it, and set our name pointer
* to point to the name we found.
*/
result = findname(&name2, name, section);
/*
* If it is the first name in the section, accept it.
*
* If it is not, but is not the same as the name already
* in the question section, append to the section. Note that
* here in the question section this is illegal, so return
* FORMERR. In the future, check the opcode to see if
* this should be legal or not. In either case we no longer
* need this name pointer.
*/
if (result != ISC_R_SUCCESS) {
if (!ISC_LIST_EMPTY(*section)) {
DO_ERROR(DNS_R_FORMERR);
}
if (name2 != NULL) {
/*
* Drop the new name and re-use its older match.
*/
dns_message_puttempname(msg, &name);
free_name = false;
name = name2;
name2 = NULL;
} else if (ISC_LIST_EMPTY(*section)) {
/*
* Keep the first name in the section.
*/
ISC_LIST_APPEND(*section, name, link);
free_name = false;
} else {
dns_message_puttempname(msg, &name);
name = name2;
name2 = NULL;
free_name = false;
/*
* Multiple different names in the question section are
* not allowed, so return FORMERR. In the future, check
* the opcode to see if this should be legal or not.
*/
DO_ERROR(DNS_R_FORMERR);
}
/*
* Get type and class.
*/
isc_buffer_remainingregion(source, &r);
if (r.length < 4) {
if (isc_buffer_remaininglength(source) < 2 + 2) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
@@ -1174,10 +1100,9 @@ auth_signed(dns_namelist_t *section) {
}
static isc_result_t
getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
dns_section_t sectionid, unsigned int options) {
isc_region_t r;
unsigned int count, rdatalen;
unsigned int count, rdatalen, remaining;
dns_name_t *name = NULL;
dns_name_t *name2 = NULL;
dns_rdataset_t *rdataset = NULL;
@@ -1194,7 +1119,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
bool isedns, issigzero, istsig;
for (count = 0; count < msg->counts[sectionid]; count++) {
int recstart = source->current;
int recstart = isc_buffer_consumedlength(source);
bool skip_name_search, skip_type_search;
skip_name_search = false;
@@ -1206,16 +1131,30 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
name = NULL;
dns_message_gettempname(msg, &name);
name->offsets = (unsigned char *)newoffsets(msg);
free_name = true;
/*
* Parse the name out of this packet.
* Parse the owner name, looking for matches.
*
* If we find an instant match, then the name will remain empty
* until later. We need to examine more of the record before we
* know that we need to search for matching names, or that we
* want to keep multiple copies of matching names. This means
* the following code needs to take care when checking the
* name, using dns_name_isabsolute() to verify it is not empty.
*/
isc_buffer_remainingregion(source, &r);
isc_buffer_setactive(source, r.length);
result = getname(name, source, msg, dctx);
if (result != ISC_R_SUCCESS) {
remaining = isc_buffer_remaininglength(source);
isc_buffer_setactive(source, remaining);
dns_decompress_findowner(dctx);
result = dns_name_fromwire(name, source, dctx, NULL);
if (result == ISC_R_EXISTS) {
/*
* We found an instant match for the name.
*/
name2 = dns_decompress_getowner(dctx);
} else if (result == ISC_R_SUCCESS) {
name2 = NULL;
} else {
goto cleanup;
}
@@ -1224,8 +1163,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
* rdatalen bytes remain. (Some of this is deferred to
* later.)
*/
isc_buffer_remainingregion(source, &r);
if (r.length < 2 + 2 + 4 + 2) {
if (isc_buffer_remaininglength(source) < 2 + 2 + 4 + 2) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
@@ -1297,7 +1235,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
* must be in the additional data section, and
* it must be the first OPT we've seen.
*/
if (!dns_name_equal(dns_rootname, name) ||
if (!dns_name_isabsolute(name) ||
!dns_name_equal(dns_rootname, name) ||
sectionid != DNS_SECTION_ADDITIONAL ||
msg->opt != NULL)
{
@@ -1334,8 +1273,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
*/
ttl = isc_buffer_getuint32(source);
rdatalen = isc_buffer_getuint16(source);
r.length -= (2 + 2 + 4 + 2);
if (r.length < rdatalen) {
if (isc_buffer_remaininglength(source) < rdatalen) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
@@ -1397,6 +1335,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
if (covers == 0) {
if (sectionid != DNS_SECTION_ADDITIONAL ||
count != msg->counts[sectionid] - 1 ||
!dns_name_isabsolute(name) ||
!dns_name_equal(name, dns_rootname))
{
DO_ERROR(DNS_R_BADSIG0);
@@ -1416,6 +1355,52 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
covers = 0;
}
/*
* If we are doing a dynamic update or this is a
* meta-type, don't bother searching for a name, just
* append this one to the end of the message.
*/
if (preserve_order || msg->opcode == dns_opcode_update ||
skip_name_search)
{
if (name2 != NULL) {
/*
* We found a quick match, so we need to make a
* copy that can be added to the list.
*/
dns_name_copy(name2, name);
name2 = NULL;
}
if (!isedns && !istsig && !issigzero) {
ISC_LIST_APPEND(*section, name, link);
free_name = false;
}
} else {
/*
* If we did not find a quick match, scan the section
* for a matching owner name.
*/
if (name2 == NULL) {
name2 = findowner(name, section);
}
if (name2 == NULL) {
/*
* Keep the new name.
*/
ISC_LIST_APPEND(*section, name, link);
free_name = false;
} else {
/*
* Drop the new name and re-use its older match.
*/
dns_message_puttempname(msg, &name);
free_name = false;
name = name2;
name2 = NULL;
}
}
INSIST(name2 == NULL);
/*
* Check the ownername of NSEC3 records
*/
@@ -1426,39 +1411,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
goto cleanup;
}
/*
* If we are doing a dynamic update or this is a meta-type,
* don't bother searching for a name, just append this one
* to the end of the message.
*/
if (preserve_order || msg->opcode == dns_opcode_update ||
skip_name_search)
{
if (!isedns && !istsig && !issigzero) {
ISC_LIST_APPEND(*section, name, link);
free_name = false;
}
} else {
/*
* Run through the section, looking to see if this name
* is already there. If it is found, put back the
* allocated name since we no longer need it, and set
* our name pointer to point to the name we found.
*/
result = findname(&name2, name, section);
/*
* If it is a new name, append to the section.
*/
if (result == ISC_R_SUCCESS) {
dns_message_puttempname(msg, &name);
name = name2;
} else {
ISC_LIST_APPEND(*section, name, link);
}
free_name = false;
}
/*
* Search name for the particular type and class.
* Skip this stage if in update mode or this is a meta-type.
@@ -1635,7 +1587,6 @@ cleanup:
isc_result_t
dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
unsigned int options) {
isc_region_t r;
dns_decompress_t dctx;
isc_result_t ret;
uint16_t tmpflags;
@@ -1665,8 +1616,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
msg->free_saved = 1;
}
isc_buffer_remainingregion(source, &r);
if (r.length < DNS_MESSAGE_HEADERLEN) {
if (isc_buffer_remaininglength(source) < DNS_MESSAGE_HEADERLEN) {
return (ISC_R_UNEXPECTEDEND);
}
@@ -1684,74 +1634,74 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
msg->header_ok = 1;
msg->state = DNS_SECTION_QUESTION;
dctx = DNS_DECOMPRESS_ALWAYS;
dns_decompress_init(&dctx, source);
ret = getquestions(source, msg, dctx, options);
ret = getquestions(source, msg, &dctx, options);
if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
goto truncated;
goto cleanup;
}
if (ret == DNS_R_RECOVERABLE) {
seen_problem = true;
ret = ISC_R_SUCCESS;
}
if (ret != ISC_R_SUCCESS) {
return (ret);
goto cleanup;
}
msg->question_ok = 1;
ret = getsection(source, msg, dctx, DNS_SECTION_ANSWER, options);
ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
goto truncated;
goto cleanup;
}
if (ret == DNS_R_RECOVERABLE) {
seen_problem = true;
ret = ISC_R_SUCCESS;
}
if (ret != ISC_R_SUCCESS) {
return (ret);
goto cleanup;
}
ret = getsection(source, msg, dctx, DNS_SECTION_AUTHORITY, options);
ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
goto truncated;
goto cleanup;
}
if (ret == DNS_R_RECOVERABLE) {
seen_problem = true;
ret = ISC_R_SUCCESS;
}
if (ret != ISC_R_SUCCESS) {
return (ret);
goto cleanup;
}
ret = getsection(source, msg, dctx, DNS_SECTION_ADDITIONAL, options);
ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
goto truncated;
goto cleanup;
}
if (ret == DNS_R_RECOVERABLE) {
seen_problem = true;
ret = ISC_R_SUCCESS;
}
if (ret != ISC_R_SUCCESS) {
return (ret);
goto cleanup;
}
isc_buffer_remainingregion(source, &r);
if (r.length != 0) {
if (isc_buffer_remaininglength(source) != 0) {
isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
"message has %u byte(s) of trailing garbage",
r.length);
isc_buffer_remaininglength(source));
}
truncated:
cleanup:
dns_decompress_invalidate(&dctx);
if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
return (DNS_R_RECOVERABLE);
}
if (seen_problem) {
if (ret == ISC_R_SUCCESS && seen_problem) {
return (DNS_R_RECOVERABLE);
}
return (ISC_R_SUCCESS);
return (ret);
}
isc_result_t
@@ -2436,7 +2386,7 @@ dns_message_findname(dns_message_t *msg, dns_section_t section,
const dns_name_t *target, dns_rdatatype_t type,
dns_rdatatype_t covers, dns_name_t **name,
dns_rdataset_t **rdataset) {
dns_name_t *foundname;
dns_name_t *foundname = NULL;
isc_result_t result;
/*
@@ -2456,12 +2406,17 @@ dns_message_findname(dns_message_t *msg, dns_section_t section,
REQUIRE(rdataset == NULL || *rdataset == NULL);
}
result = findname(&foundname, target, &msg->sections[section]);
for (dns_name_t *curr = ISC_LIST_TAIL(msg->sections[section]);
curr != NULL; curr = ISC_LIST_PREV(curr, link))
{
if (dns_name_equal(curr, target)) {
foundname = curr;
break;
}
}
if (result == ISC_R_NOTFOUND) {
if (foundname == NULL) {
return (DNS_R_NXDOMAIN);
} else if (result != ISC_R_SUCCESS) {
return (result);
}
if (name != NULL) {
+115 -159
View File
@@ -162,7 +162,7 @@ dns_name_isvalid(const dns_name_t *name) {
while (offset != length) {
count = *ndata;
if (count > 63U) {
if (!DNS_LABEL_ISNORMAL(count)) {
return (false);
}
if (offsets != NULL && offsets[nlabels] != offset) {
@@ -176,7 +176,7 @@ dns_name_isvalid(const dns_name_t *name) {
return (false);
}
if (count == 0) {
if (DNS_LABEL_ISROOT(count)) {
break;
}
}
@@ -254,7 +254,7 @@ dns_name_ismailbox(const dns_name_t *name) {
ndata = name->ndata;
n = *ndata++;
INSIST(n <= 63);
INSIST(DNS_LABEL_ISNORMAL(n));
while (n--) {
ch = *ndata++;
if (!domainchar(ch)) {
@@ -271,7 +271,7 @@ dns_name_ismailbox(const dns_name_t *name) {
*/
while (ndata < (name->ndata + name->length)) {
n = *ndata++;
INSIST(n <= 63);
INSIST(DNS_LABEL_ISNORMAL(n));
first = true;
while (n--) {
ch = *ndata++;
@@ -320,7 +320,7 @@ dns_name_ishostname(const dns_name_t *name, bool wildcard) {
*/
while (ndata < (name->ndata + name->length)) {
n = *ndata++;
INSIST(n <= 63);
INSIST(DNS_LABEL_ISNORMAL(n));
first = true;
while (n--) {
ch = *ndata++;
@@ -378,7 +378,7 @@ dns_name_internalwildcard(const dns_name_t *name) {
*/
ndata = name->ndata;
count = *ndata++;
INSIST(count <= 63);
INSIST(DNS_LABEL_ISNORMAL(count));
ndata += count;
label = 1;
/*
@@ -386,7 +386,7 @@ dns_name_internalwildcard(const dns_name_t *name) {
*/
while (label + 1 < name->labels) {
count = *ndata++;
INSIST(count <= 63);
INSIST(DNS_LABEL_ISNORMAL(count));
if (count == 1 && *ndata == '*') {
return (true);
}
@@ -991,7 +991,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
} else if (c == '\\') {
state = ft_escape;
} else {
if (count >= 63) {
if (count >= DNS_LABEL_MAXLEN) {
return (DNS_R_LABELTOOLONG);
}
count++;
@@ -1016,7 +1016,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
FALLTHROUGH;
case ft_escape:
if (!isdigit((unsigned char)c)) {
if (count >= 63) {
if (count >= DNS_LABEL_MAXLEN) {
return (DNS_R_LABELTOOLONG);
}
count++;
@@ -1043,7 +1043,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
if (value > 255) {
return (DNS_R_BADESCAPE);
}
if (count >= 63) {
if (count >= DNS_LABEL_MAXLEN) {
return (DNS_R_LABELTOOLONG);
}
count++;
@@ -1088,7 +1088,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
POST(nrem);
while (n1 > 0) {
n2 = *label++;
INSIST(n2 <= 63); /* no bitstring support */
INSIST(DNS_LABEL_ISNORMAL(n2));
*ndata++ = n2;
n1 -= n2 + 1;
nused += n2 + 1;
@@ -1217,11 +1217,11 @@ dns_name_totext2(const dns_name_t *name, unsigned int options,
labels--;
count = *ndata++;
nlen--;
if (count == 0) {
if (DNS_LABEL_ISROOT(count)) {
saw_root = true;
break;
}
if (count < 64) {
if (DNS_LABEL_ISNORMAL(count)) {
INSIST(nlen >= count);
while (count > 0) {
c = *ndata;
@@ -1363,10 +1363,10 @@ dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot,
labels--;
count = *ndata++;
nlen--;
if (count == 0) {
if (DNS_LABEL_ISROOT(count)) {
break;
}
if (count < 64) {
if (DNS_LABEL_ISNORMAL(count)) {
INSIST(nlen >= count);
while (count > 0) {
c = *ndata;
@@ -1496,14 +1496,14 @@ set_offsets(const dns_name_t *name, unsigned char *offsets,
nlabels = 0;
absolute = false;
while (offset != length) {
INSIST(nlabels < 128);
INSIST(nlabels < DNS_NAME_MAXLABELS);
offsets[nlabels++] = offset;
count = *ndata;
INSIST(count <= 63);
INSIST(DNS_LABEL_ISNORMAL(count));
offset += count + 1;
ndata += count + 1;
INSIST(offset <= length);
if (count == 0) {
if (DNS_LABEL_ISROOT(count)) {
absolute = true;
break;
}
@@ -1520,174 +1520,91 @@ set_offsets(const dns_name_t *name, unsigned char *offsets,
}
isc_result_t
dns_name_fromwire(dns_name_t *const name, isc_buffer_t *const source,
const dns_decompress_t dctx, unsigned int options,
isc_buffer_t *target) {
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
dns_decompress_t *dctx, isc_buffer_t *buffer) {
/*
* Copy the name at source into target, decompressing it.
* Copy the name at source into target, maybe decompressing it.
*
* *** WARNING ***
*
* dns_name_fromwire() deals with raw network data. An error in this
* routine could result in the failure or hijacking of the server.
*
* The description of name compression in RFC 1035 section 4.1.4 is
* subtle wrt certain edge cases. The first important sentence is:
*
* > In this scheme, an entire domain name or a list of labels at the
* > end of a domain name is replaced with a pointer to a prior
* > occurance of the same name.
*
* The key word is "prior". This says that compression pointers must
* point strictly earlier in the message (before our "marker" variable),
* which is enough to prevent DoS attacks due to compression loops.
*
* The next important sentence is:
*
* > If a domain name is contained in a part of the message subject to a
* > length field (such as the RDATA section of an RR), and compression
* > is used, the length of the compressed name is used in the length
* > calculation, rather than the length of the expanded name.
*
* When decompressing, this means that the amount of the source buffer
* that we consumed (which is checked wrt the container's length field)
* is the length of the compressed name. A compressed name is defined as
* a sequence of labels ending with the root label or a compression
* pointer, that is, the segment of the name that dns_name_fromwire()
* examines first.
*
* This matters when handling names that play dirty tricks, like:
*
* +---+---+---+---+---+---+
* | 4 | 1 |'a'|192| 0 | 0 |
* +---+---+---+---+---+---+
*
* We start at octet 1. There is an ordinary single character label "a",
* followed by a compression pointer that refers back to octet zero.
* Here there is a label of length 4, which weirdly re-uses the octets
* we already examined as the data for the label. It is followed by the
* root label,
*
* The specification says that the compressed name ends after the first
* zero octet (after the compression pointer) not the second zero octet,
* even though the second octet is later in the message. This shows the
* correct way to set our "consumed" variable.
* This parser is specialized to handle uncompressed names efficiently.
* When we encounter a compression pointer, we collect however much of
* the name we have so far, and hand over to the decompression routines.
*/
REQUIRE((options & DNS_NAME_DOWNCASE) == 0);
REQUIRE(VALID_NAME(name));
REQUIRE(BINDABLE(name));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
if (target == NULL && name->buffer != NULL) {
target = name->buffer;
isc_buffer_clear(target);
}
uint8_t *const name_buf = isc_buffer_used(target);
const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
isc_buffer_availablelength(target));
uint32_t name_len = 0;
MAKE_EMPTY(name); /* in case of failure */
REQUIRE((buffer != NULL && ISC_BUFFER_VALID(buffer)) ||
(buffer == NULL && ISC_BUFFER_VALID(name->buffer)));
dns_offsets_t odata;
uint8_t *offsets = NULL;
uint32_t labels = 0;
INIT_OFFSETS(name, offsets, odata);
DNS_NAME_RESET(name); /* in case of failure */
/*
* After chasing a compression pointer, these variables refer to the
* source buffer as follows:
*
* sb --- mr --- cr --- st --- cd --- sm
*
* sb = source_buf (const)
* mr = marker
* cr = cursor
* st = start (const)
* cd = consumed
* sm = source_max (const)
*
* The marker hops backwards for each pointer.
* The cursor steps forwards for each label.
* The amount of the source we consumed is set once.
*/
const uint8_t *const source_buf = isc_buffer_base(source);
const uint8_t *const source_max = isc_buffer_used(source);
isc_buffer_t *target = buffer != NULL ? buffer : name->buffer;
const uint32_t target_available = isc_buffer_availablelength(target);
const uint32_t source_remaining = isc_buffer_remaininglength(source);
const uint8_t *const start = isc_buffer_current(source);
const uint8_t *marker = start;
const uint8_t *cursor = start;
const uint8_t *consumed = NULL;
uint32_t labels = 0;
uint32_t name_len = 0;
uint32_t max_len = ISC_MIN(DNS_NAME_MAXWIRE,
ISC_MIN(target_available, source_remaining));
/*
* One iteration per label.
* One iteration per label. Checking the bounds on the name
* length also ensures we don't overrun the offsets array.
*/
while (cursor < source_max) {
const uint8_t label_len = *cursor++;
if (label_len < 64) {
/*
* Normal label: record its offset, and check bounds on
* the name length, which also ensures we don't overrun
* the offsets array. Don't touch any source bytes yet!
* The source bounds check will happen when we loop.
*/
while (name_len < max_len) {
uint8_t label_len = start[name_len];
if (DNS_LABEL_ISROOT(label_len)) {
goto root_label;
} else if (DNS_LABEL_ISNORMAL(label_len)) {
offsets[labels++] = name_len;
/* and then a step to the ri-i-i-i-i-ight */
cursor += label_len;
name_len += label_len + 1;
if (name_len > name_max) {
return (name_max == DNS_NAME_MAXWIRE
? DNS_R_NAMETOOLONG
: ISC_R_NOSPACE);
} else if (label_len == 0) {
goto root_label;
}
} else if (label_len < 192) {
} else if (DNS_LABEL_INVALID(label_len)) {
return (DNS_R_BADLABELTYPE);
} else if (!dns_decompress_getpermitted(dctx)) {
} else if (dns_decompress_getpermitted(dctx)) {
goto compressed;
} else {
return (DNS_R_DISALLOWED);
} else if (cursor < source_max) {
/*
* Compression pointer. Ensure it does not loop.
*
* Copy multiple labels in one go, to make the most of
* memmove() performance. Start at the marker and finish
* just before the pointer's hi+lo bytes, before the
* cursor. Bounds were already checked.
*/
const uint32_t hi = label_len & 0x3F;
const uint32_t lo = *cursor++;
const uint8_t *pointer = source_buf + (256 * hi + lo);
if (pointer >= marker) {
return (DNS_R_BADPOINTER);
}
const uint32_t copy_len = (cursor - 2) - marker;
uint8_t *const dest = name_buf + name_len - copy_len;
memmove(dest, marker, copy_len);
consumed = consumed != NULL ? consumed : cursor;
/* it's just a jump to the left */
cursor = marker = pointer;
}
}
return (ISC_R_UNEXPECTEDEND);
root_label:;
/*
* Copy labels almost like we do for compression pointers,
* from the marker up to and including the root label.
*/
const uint32_t copy_len = cursor - marker;
memmove(name_buf + name_len - copy_len, marker, copy_len);
consumed = consumed != NULL ? consumed : cursor;
isc_buffer_forward(source, consumed - start);
if (name_len > DNS_NAME_MAXWIRE) {
return (DNS_R_NAMETOOLONG);
} else if (name_len > target_available) {
return (ISC_R_NOSPACE);
} else {
return (ISC_R_UNEXPECTEDEND);
}
root_label:
offsets[labels++] = name_len++;
name->attributes.absolute = true;
name->ndata = name_buf;
name->labels = labels;
name->length = name_len;
isc_buffer_add(target, name_len);
name->ndata = isc_buffer_used(target);
isc_buffer_putmem(target, start, name_len);
if (dns_decompress_getpermitted(dctx)) {
dns_decompress_add(dctx, source, name);
} else {
isc_buffer_forward(source, name_len);
}
return (ISC_R_SUCCESS);
compressed:
name->labels = labels;
name->length = name_len;
name->ndata = isc_buffer_used(target);
isc_buffer_putmem(target, start, name_len);
return (dns_decompress_pointer(dctx, source, name, buffer));
}
isc_result_t
@@ -1722,11 +1639,11 @@ dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
* Write a compression pointer directly if the caller passed us
* a pointer to this name's offset that we saved previously.
*/
if (compress && name_coff != NULL && *name_coff < 0x4000) {
if (compress && name_coff != NULL && *name_coff <= DNS_NAME_MAXPTR) {
if (isc_buffer_availablelength(target) < 2) {
return (ISC_R_NOSPACE);
}
isc_buffer_putuint16(target, *name_coff | 0xc000);
isc_buffer_putuint16(target, *name_coff | DNS_NAME_PTRBITS);
return (ISC_R_SUCCESS);
}
@@ -1750,10 +1667,10 @@ dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
/*
* Return this name's compression offset for use next time, provided
* it isn't too short for compression to help (i.e. it's the root)
* it isn't too short for compression to help (i.e. it isn't the root)
*/
here = isc_buffer_usedlength(target);
if (name_coff != NULL && here < 0x4000 && prefix_length > 1) {
if (name_coff != NULL && here <= DNS_NAME_MAXPTR && prefix_length > 1) {
*name_coff = (uint16_t)here;
}
@@ -1772,7 +1689,46 @@ dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
if (isc_buffer_availablelength(target) < 2) {
return (ISC_R_NOSPACE);
}
isc_buffer_putuint16(target, suffix_coff | 0xc000);
isc_buffer_putuint16(target, suffix_coff | DNS_NAME_PTRBITS);
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_name_append(dns_name_t *name, const dns_name_t *suffix,
isc_buffer_t *target) {
unsigned int length;
/*
* Append 'suffix' onto 'name'
*/
REQUIRE(VALID_NAME(name));
REQUIRE(VALID_NAME(suffix));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
REQUIRE(!dns_name_isabsolute(name) || suffix->labels == 0);
if (target == NULL) {
target = name->buffer;
}
length = name->length + suffix->length;
if (length > DNS_NAME_MAXWIRE) {
return (DNS_R_NAMETOOLONG);
}
if (length > isc_buffer_availablelength(target)) {
return (ISC_R_NOSPACE);
}
name->length = length;
name->labels += suffix->labels;
name->attributes.absolute = suffix->attributes.absolute;
isc_buffer_putmem(target, suffix->ndata, suffix->length);
if (name->offsets != NULL) {
set_offsets(name, name->offsets, NULL);
}
return (ISC_R_SUCCESS);
+2 -2
View File
@@ -991,8 +991,8 @@ dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
isc_buffer_setactive(&buf1, src->length - 1);
isc_buffer_init(&buf2, buf, (unsigned int)buflen);
result = dns_rdata_fromwire(target, src->rdclass,
dns_rdatatype_nsec3param, &buf1,
DNS_DECOMPRESS_NEVER, 0, &buf2);
dns_rdatatype_nsec3param, &buf1, NULL,
&buf2);
return (result == ISC_R_SUCCESS);
}
+8 -12
View File
@@ -98,10 +98,9 @@
#define ARGS_FROMWIRE \
int rdclass, dns_rdatatype_t type, isc_buffer_t *source, \
dns_decompress_t dctx, unsigned int options, \
isc_buffer_t *target
dns_decompress_t *dctx, isc_buffer_t *target
#define CALL_FROMWIRE rdclass, type, source, dctx, options, target
#define CALL_FROMWIRE rdclass, type, source, dctx, target
#define ARGS_TOWIRE \
dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target
@@ -604,7 +603,7 @@ check_private(isc_buffer_t *source, dns_secalg_t alg) {
dns_fixedname_t fixed;
RETERR(dns_name_fromwire(dns_fixedname_initname(&fixed), source,
DNS_DECOMPRESS_DEFAULT, 0, NULL));
NULL, NULL));
/*
* There should be a public key or signature after the key name.
*/
@@ -795,8 +794,7 @@ dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
isc_result_t
dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
dns_rdatatype_t type, isc_buffer_t *source,
dns_decompress_t dctx, unsigned int options,
isc_buffer_t *target) {
dns_decompress_t *dctx, isc_buffer_t *target) {
isc_result_t result = ISC_R_NOTIMPLEMENTED;
isc_region_t region;
isc_buffer_t ss;
@@ -860,6 +858,9 @@ dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
if (result != ISC_R_SUCCESS) {
*source = ss;
*target = st;
if (dns_decompress_getpermitted(dctx)) {
dns_decompress_rollback(dctx, source);
}
}
return (result);
}
@@ -911,13 +912,8 @@ dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
static isc_result_t
rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
dns_rdatatype_t type) {
isc_result_t result;
isc_buffer_setactive(src, isc_buffer_usedlength(src));
result = dns_rdata_fromwire(NULL, rdclass, type, src,
DNS_DECOMPRESS_NEVER, 0, dest);
return (result);
return (dns_rdata_fromwire(NULL, rdclass, type, src, NULL, dest));
}
static isc_result_t
+2 -2
View File
@@ -264,13 +264,13 @@ fromwire_any_tsig(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
/*
* Algorithm Name.
*/
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
isc_buffer_activeregion(source, &sr);
/*
+2 -2
View File
@@ -105,11 +105,11 @@ fromwire_ch_a(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
isc_buffer_activeregion(source, &sregion);
isc_buffer_availableregion(target, &tregion);
+2 -2
View File
@@ -101,7 +101,7 @@ fromwire_afsdb(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -116,7 +116,7 @@ fromwire_afsdb(ARGS_FROMWIRE) {
memmove(tr.base, sr.base, 2);
isc_buffer_forward(source, 2);
isc_buffer_add(target, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -3
View File
@@ -192,7 +192,7 @@ fromwire_amtrelay(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
isc_buffer_activeregion(source, &region);
if (region.length < 2) {
@@ -225,8 +225,7 @@ fromwire_amtrelay(ARGS_FROMWIRE) {
RETERR(mem_tobuffer(target, region.base, 2));
isc_buffer_forward(source, 2);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options,
target));
return (dns_name_fromwire(&name, source, dctx, target));
default:
isc_buffer_forward(source, region.length);
-1
View File
@@ -371,7 +371,6 @@ fromwire_caa(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
/*
* Flags
-1
View File
@@ -124,7 +124,6 @@ fromwire_cert(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 6) {
+2 -2
View File
@@ -71,10 +71,10 @@ fromwire_cname(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -89,7 +89,6 @@ fromwire_csync(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(options);
UNUSED(dctx);
/*
+2 -2
View File
@@ -72,10 +72,10 @@ fromwire_dname(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -131,7 +131,6 @@ fromwire_doa(ARGS_FROMWIRE) {
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
REQUIRE(type == dns_rdatatype_doa);
-1
View File
@@ -163,7 +163,6 @@ generic_fromwire_ds(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
-1
View File
@@ -74,7 +74,6 @@ fromwire_eui48(ARGS_FROMWIRE) {
REQUIRE(type == dns_rdatatype_eui48);
UNUSED(type);
UNUSED(options);
UNUSED(rdclass);
UNUSED(dctx);
-1
View File
@@ -77,7 +77,6 @@ fromwire_eui64(ARGS_FROMWIRE) {
REQUIRE(type == dns_rdatatype_eui64);
UNUSED(type);
UNUSED(options);
UNUSED(rdclass);
UNUSED(dctx);
-1
View File
@@ -70,7 +70,6 @@ fromwire_gpos(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
for (i = 0; i < 3; i++) {
RETERR(txt_fromwire(source, target));
-1
View File
@@ -58,7 +58,6 @@ fromwire_hinfo(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
RETERR(txt_fromwire(source, target));
return (txt_fromwire(source, target));
+2 -2
View File
@@ -226,10 +226,10 @@ fromwire_hip(ARGS_FROMWIRE) {
RETERR(mem_tobuffer(target, rr.base, 4 + len));
isc_buffer_forward(source, 4 + len);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
while (isc_buffer_activelength(source) > 0) {
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
}
return (ISC_R_SUCCESS);
}
+2 -2
View File
@@ -221,7 +221,7 @@ fromwire_ipseckey(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -255,7 +255,7 @@ fromwire_ipseckey(ARGS_FROMWIRE) {
case 3:
RETERR(mem_tobuffer(target, region.base, 3));
isc_buffer_forward(source, 3);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
isc_buffer_activeregion(source, &region);
isc_buffer_forward(source, region.length);
if (region.length < 1) {
-1
View File
@@ -73,7 +73,6 @@ fromwire_isdn(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
RETERR(txt_fromwire(source, target));
if (buffer_empty(source)) {
-1
View File
@@ -234,7 +234,6 @@ generic_fromwire_key(ARGS_FROMWIRE) {
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 4) {
-1
View File
@@ -258,7 +258,6 @@ fromwire_keydata(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
isc_buffer_forward(source, sr.length);
-1
View File
@@ -85,7 +85,6 @@ fromwire_l32(ARGS_FROMWIRE) {
REQUIRE(type == dns_rdatatype_l32);
UNUSED(type);
UNUSED(options);
UNUSED(rdclass);
UNUSED(dctx);
-1
View File
@@ -83,7 +83,6 @@ fromwire_l64(ARGS_FROMWIRE) {
REQUIRE(type == dns_rdatatype_l64);
UNUSED(type);
UNUSED(options);
UNUSED(rdclass);
UNUSED(dctx);
-1
View File
@@ -566,7 +566,6 @@ fromwire_loc(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 1) {
+2 -2
View File
@@ -88,7 +88,7 @@ fromwire_lp(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
@@ -98,7 +98,7 @@ fromwire_lp(ARGS_FROMWIRE) {
}
RETERR(mem_tobuffer(target, sregion.base, 2));
isc_buffer_forward(source, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -70,10 +70,10 @@ fromwire_mb(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -70,10 +70,10 @@ fromwire_md(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -70,10 +70,10 @@ fromwire_mf(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -70,10 +70,10 @@ fromwire_mg(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+3 -3
View File
@@ -98,13 +98,13 @@ fromwire_minfo(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&rmail, NULL);
dns_name_init(&email, NULL);
RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
return (dns_name_fromwire(&email, source, dctx, options, target));
RETERR(dns_name_fromwire(&rmail, source, dctx, target));
return (dns_name_fromwire(&email, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -70,10 +70,10 @@ fromwire_mr(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -134,7 +134,7 @@ fromwire_mx(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
@@ -144,7 +144,7 @@ fromwire_mx(ARGS_FROMWIRE) {
}
RETERR(mem_tobuffer(target, sregion.base, 2));
isc_buffer_forward(source, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -311,7 +311,7 @@ fromwire_naptr(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -345,7 +345,7 @@ fromwire_naptr(ARGS_FROMWIRE) {
/*
* Replacement.
*/
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -83,7 +83,6 @@ fromwire_nid(ARGS_FROMWIRE) {
REQUIRE(type == dns_rdatatype_nid);
UNUSED(type);
UNUSED(options);
UNUSED(rdclass);
UNUSED(dctx);
+2 -2
View File
@@ -81,10 +81,10 @@ fromwire_ns(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -190,7 +190,6 @@ fromwire_nsec3(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(options);
UNUSED(dctx);
isc_buffer_activeregion(source, &sr);
-1
View File
@@ -149,7 +149,6 @@ fromwire_nsec3param(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(options);
UNUSED(dctx);
isc_buffer_activeregion(source, &sr);
+2 -2
View File
@@ -85,10 +85,10 @@ fromwire_nsec(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
isc_buffer_activeregion(source, &sr);
RETERR(typemap_test(&sr, false));
-1
View File
@@ -47,7 +47,6 @@ fromwire_null(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
isc_buffer_forward(source, sr.length);
+2 -2
View File
@@ -144,10 +144,10 @@ fromwire_nxt(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
isc_buffer_activeregion(source, &sr);
if (sr.length > 0 && ((sr.base[0] & 0x80) != 0 || sr.length > 16 ||
-1
View File
@@ -75,7 +75,6 @@ fromwire_openpgpkey(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
/*
* Keyring.
-1
View File
@@ -104,7 +104,6 @@ fromwire_opt(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sregion);
if (sregion.length == 0) {
+1 -1
View File
@@ -41,7 +41,7 @@ static isc_result_t fromwire_ #(ARGS_FROMWIRE) {
REQUIRE(rdclass == #);
/* see RFC 3597 */
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
return (ISC_R_NOTIMPLEMENTED);
}
+2 -2
View File
@@ -83,10 +83,10 @@ fromwire_ptr(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+3 -3
View File
@@ -99,13 +99,13 @@ fromwire_rp(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&rmail, NULL);
dns_name_init(&email, NULL);
RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
return (dns_name_fromwire(&email, source, dctx, options, target));
RETERR(dns_name_fromwire(&rmail, source, dctx, target));
return (dns_name_fromwire(&email, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -303,7 +303,7 @@ fromwire_rrsig(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
isc_buffer_activeregion(source, &sr);
/*
@@ -328,7 +328,7 @@ fromwire_rrsig(ARGS_FROMWIRE) {
* Signer.
*/
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
/*
* Sig.
+2 -2
View File
@@ -97,7 +97,7 @@ fromwire_rt(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -112,7 +112,7 @@ fromwire_rt(ARGS_FROMWIRE) {
memmove(tregion.base, sregion.base, 2);
isc_buffer_forward(source, 2);
isc_buffer_add(target, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -266,7 +266,7 @@ fromwire_sig(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
isc_buffer_activeregion(source, &sr);
/*
@@ -291,7 +291,7 @@ fromwire_sig(ARGS_FROMWIRE) {
* Signer.
*/
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
/*
* Sig.
-1
View File
@@ -112,7 +112,6 @@ fromwire_sink(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 3) {
+3 -3
View File
@@ -165,13 +165,13 @@ fromwire_soa(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, true);
dns_decompress_setpermitted(dctx, true);
dns_name_init(&mname, NULL);
dns_name_init(&rname, NULL);
RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
RETERR(dns_name_fromwire(&mname, source, dctx, target));
RETERR(dns_name_fromwire(&rname, source, dctx, target));
isc_buffer_activeregion(source, &sregion);
isc_buffer_availableregion(target, &tregion);
-1
View File
@@ -132,7 +132,6 @@ fromwire_sshfp(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 2) {
+3 -3
View File
@@ -88,13 +88,13 @@ fromwire_talink(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&prev, NULL);
dns_name_init(&next, NULL);
RETERR(dns_name_fromwire(&prev, source, dctx, options, target));
return (dns_name_fromwire(&next, source, dctx, options, target));
RETERR(dns_name_fromwire(&prev, source, dctx, target));
return (dns_name_fromwire(&next, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -254,13 +254,13 @@ fromwire_tkey(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
/*
* Algorithm.
*/
dns_name_init(&name, NULL);
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
/*
* Inception: 4
-1
View File
@@ -126,7 +126,6 @@ generic_fromwire_tlsa(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
-1
View File
@@ -76,7 +76,6 @@ generic_fromwire_txt(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
do {
result = txt_fromwire(source, target);
-1
View File
@@ -105,7 +105,6 @@ fromwire_uri(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
/*
* Priority, weight
-1
View File
@@ -69,7 +69,6 @@ fromwire_x25(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length < 5 || sr.base[0] != (sr.length - 1)) {
-1
View File
@@ -148,7 +148,6 @@ fromwire_zonemd(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
-1
View File
@@ -71,7 +71,6 @@ fromwire_hs_a(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &sregion);
+2 -2
View File
@@ -158,7 +158,7 @@ fromwire_in_a6(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
isc_buffer_activeregion(source, &sr);
/*
@@ -196,7 +196,7 @@ fromwire_in_a6(ARGS_FROMWIRE) {
}
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -74,7 +74,6 @@ fromwire_in_a(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &sregion);
-1
View File
@@ -90,7 +90,6 @@ fromwire_in_aaaa(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &sregion);
+1 -3
View File
@@ -193,7 +193,6 @@ fromwire_in_apl(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(rdclass);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
isc_buffer_availableregion(target, &tr);
@@ -276,8 +275,7 @@ fromstruct_in_apl(ARGS_FROMSTRUCT) {
isc_buffer_init(&b, apl->apl, apl->apl_len);
isc_buffer_add(&b, apl->apl_len);
isc_buffer_setactive(&b, apl->apl_len);
return (fromwire_in_apl(rdclass, type, &b, DNS_DECOMPRESS_DEFAULT,
false, target));
return (fromwire_in_apl(rdclass, type, &b, NULL, target));
}
static isc_result_t
-1
View File
@@ -149,7 +149,6 @@ fromwire_in_atma(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &region);
-1
View File
@@ -76,7 +76,6 @@ fromwire_in_dhcid(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
UNUSED(dctx);
UNUSED(options);
isc_buffer_activeregion(source, &sr);
if (sr.length == 0) {
-1
View File
@@ -66,7 +66,6 @@ fromwire_in_eid(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &region);
+2 -2
View File
@@ -89,7 +89,7 @@ fromwire_in_kx(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -99,7 +99,7 @@ fromwire_in_kx(ARGS_FROMWIRE) {
}
RETERR(mem_tobuffer(target, sregion.base, 2));
isc_buffer_forward(source, 2);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -66,7 +66,6 @@ fromwire_in_nimloc(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &region);
+2 -2
View File
@@ -75,10 +75,10 @@ fromwire_in_nsap_ptr(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
-1
View File
@@ -101,7 +101,6 @@ fromwire_in_nsap(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &region);
+3 -3
View File
@@ -119,7 +119,7 @@ fromwire_in_px(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -136,12 +136,12 @@ fromwire_in_px(ARGS_FROMWIRE) {
/*
* MAP822.
*/
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
/*
* MAPX400.
*/
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -149,7 +149,7 @@ fromwire_in_srv(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -166,7 +166,7 @@ fromwire_in_srv(ARGS_FROMWIRE) {
/*
* Target.
*/
return (dns_name_fromwire(&name, source, dctx, options, target));
return (dns_name_fromwire(&name, source, dctx, target));
}
static isc_result_t
+2 -2
View File
@@ -806,7 +806,7 @@ generic_fromwire_in_svcb(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(rdclass);
dctx = dns_decompress_setpermitted(dctx, false);
dns_decompress_setpermitted(dctx, false);
dns_name_init(&name, NULL);
@@ -824,7 +824,7 @@ generic_fromwire_in_svcb(ARGS_FROMWIRE) {
/*
* TargetName.
*/
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
RETERR(dns_name_fromwire(&name, source, dctx, target));
if (alias) {
return (ISC_R_SUCCESS);
-1
View File
@@ -217,7 +217,6 @@ fromwire_in_wks(ARGS_FROMWIRE) {
UNUSED(type);
UNUSED(dctx);
UNUSED(options);
UNUSED(rdclass);
isc_buffer_activeregion(source, &sr);
+3 -2
View File
@@ -53,6 +53,7 @@
#include <dns/keytable.h>
#include <dns/log.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/ncache.h>
#include <dns/nsec.h>
#include <dns/nsec3.h>
@@ -4361,7 +4362,7 @@ resume_qmin(isc_task_t *task, isc_event_t *event) {
case ISC_R_FAILURE:
if ((fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
/* Disable minimization in relaxed mode */
fctx->qmin_labels = DNS_MAX_LABELS + 1;
fctx->qmin_labels = DNS_NAME_MAXLABELS;
/*
* We store the result. If we succeed in the end
* we'll issue a warning that the server is
@@ -10464,7 +10465,7 @@ fctx_minimize_qname(fetchctx_t *fctx) {
fctx->qmin_labels = nlabels;
}
} else if (fctx->qmin_labels > DNS_QMIN_MAXLABELS) {
fctx->qmin_labels = DNS_MAX_LABELS + 1;
fctx->qmin_labels = DNS_NAME_MAXLABELS;
}
if (fctx->qmin_labels < nlabels) {
+37 -33
View File
@@ -17,6 +17,7 @@
#include <isc/ascii.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/random.h>
#include <isc/time.h>
#include <isc/util.h>
@@ -28,22 +29,16 @@
#include "old.h"
static uint32_t
old_bench(const uint8_t *data, size_t size) {
old_bench(dns_decompress_t *dctx, isc_buffer_t *source) {
isc_result_t result;
dns_fixedname_t fixed;
dns_name_t *name = dns_fixedname_initname(&fixed);
dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
isc_buffer_t buf;
uint32_t count = 0;
isc_buffer_constinit(&buf, data, size);
isc_buffer_add(&buf, size);
isc_buffer_setactive(&buf, size);
while (isc_buffer_consumedlength(&buf) < size) {
result = old_name_fromwire(name, &buf, dctx, 0, NULL);
while (isc_buffer_remaininglength(source) > 0) {
result = old_name_fromwire(name, source, dctx, NULL);
if (result != ISC_R_SUCCESS) {
isc_buffer_forward(&buf, 1);
isc_buffer_forward(source, 1);
}
count++;
}
@@ -51,22 +46,16 @@ old_bench(const uint8_t *data, size_t size) {
}
static uint32_t
new_bench(const uint8_t *data, size_t size) {
new_bench(dns_decompress_t *dctx, isc_buffer_t *source) {
isc_result_t result;
dns_fixedname_t fixed;
dns_name_t *name = dns_fixedname_initname(&fixed);
dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
isc_buffer_t buf;
uint32_t count = 0;
isc_buffer_constinit(&buf, data, size);
isc_buffer_add(&buf, size);
isc_buffer_setactive(&buf, size);
while (isc_buffer_consumedlength(&buf) < size) {
result = dns_name_fromwire(name, &buf, dctx, 0, NULL);
while (isc_buffer_remaininglength(source) > 0) {
result = dns_name_fromwire(name, source, dctx, NULL);
if (result != ISC_R_SUCCESS) {
isc_buffer_forward(&buf, 1);
isc_buffer_forward(source, 1);
}
count++;
}
@@ -75,20 +64,35 @@ new_bench(const uint8_t *data, size_t size) {
static void
oldnew_bench(const uint8_t *data, size_t size) {
isc_time_t t0;
isc_time_now_hires(&t0);
uint32_t n1 = old_bench(data, size);
isc_time_t t1;
isc_time_now_hires(&t1);
uint32_t n2 = new_bench(data, size);
isc_time_t t2;
isc_time_now_hires(&t2);
dns_decompress_t dctx;
isc_buffer_t source;
double t01 = (double)isc_time_microdiff(&t1, &t0);
double t12 = (double)isc_time_microdiff(&t2, &t1);
printf(" old %u / %f ms; %f / us\n", n1, t01 / 1000.0, n1 / t01);
printf(" new %u / %f ms; %f / us\n", n2, t12 / 1000.0, n2 / t12);
printf(" old/new %f or %f\n", t01 / t12, t12 / t01);
isc_buffer_constinit(&source, data, size);
isc_buffer_add(&source, size);
isc_buffer_setactive(&source, size);
dns_decompress_init(&dctx, &source);
isc_time_t s1;
isc_time_now_hires(&s1);
uint32_t n1 = old_bench(&dctx, &source);
isc_time_t e1;
isc_time_now_hires(&e1);
dns_decompress_invalidate(&dctx);
isc_buffer_first(&source);
isc_buffer_setactive(&source, size);
dns_decompress_init(&dctx, &source);
isc_time_t s2;
isc_time_now_hires(&s2);
uint32_t n2 = new_bench(&dctx, &source);
isc_time_t e2;
isc_time_now_hires(&e2);
dns_decompress_invalidate(&dctx);
double t1 = (double)isc_time_microdiff(&e1, &s1);
double t2 = (double)isc_time_microdiff(&e2, &s2);
printf(" old %u / %f ms; %f / us\n", n1, t1 / 1000.0, n1 / t1);
printf(" new %u / %f ms; %f / us\n", n2, t2 / 1000.0, n2 / t2);
printf(" old/new %f or %f\n", t1 / t2, t2 / t1);
}
#define NAMES 1000
+42 -116
View File
@@ -125,13 +125,15 @@ static void
compress_test(const dns_name_t *name1, const dns_name_t *name2,
const dns_name_t *name3, unsigned char *compressed,
unsigned int compressed_length, unsigned char *expanded,
unsigned int expanded_length, dns_compress_t *cctx,
dns_decompress_t dctx, bool rdata) {
unsigned int expanded_length, bool enabled, bool permitted,
bool rdata) {
isc_buffer_t source;
isc_buffer_t target;
dns_name_t name;
unsigned char buf1[1024];
unsigned char buf2[1024];
dns_compress_t cstr, *cctx = &cstr;
dns_decompress_t dstr, *dctx = &dstr;
isc_buffer_init(&source, buf1, sizeof(buf1));
isc_buffer_init(&target, buf2, sizeof(buf2));
@@ -143,6 +145,13 @@ compress_test(const dns_name_t *name1, const dns_name_t *name2,
isc_buffer_putuint16(&source, 0xEAD);
isc_buffer_putuint16(&target, 0xEAD);
dns_compress_init(cctx, mctx, enabled ? 0 : DNS_COMPRESS_DISABLED);
dns_compress_setpermitted(cctx, permitted);
dns_decompress_init(dctx, &source);
if (!permitted) {
dctx = NULL;
}
if (rdata) {
/* RDATA compression */
assert_int_equal(dns_name_towire(name1, cctx, &source),
@@ -180,24 +189,25 @@ compress_test(const dns_name_t *name1, const dns_name_t *name2,
dns_name_init(&name, NULL);
RUNTIME_CHECK(isc_buffer_getuint16(&source) == 0xEAD);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, &target) ==
ISC_R_SUCCESS);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, &target) ==
ISC_R_SUCCESS);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, &target) ==
ISC_R_SUCCESS);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, 0, &target) ==
RUNTIME_CHECK(dns_name_fromwire(&name, &source, dctx, &target) ==
ISC_R_SUCCESS);
assert_int_equal(target.used, expanded_length);
assert_true(memcmp(target.base, expanded, target.used) == 0);
dns_compress_rollback(cctx, 0);
dns_compress_invalidate(&cstr);
dns_decompress_invalidate(&dstr);
}
/* name compression test */
ISC_RUN_TEST_IMPL(compression) {
bool permitted;
dns_compress_t cctx;
dns_decompress_t dctx;
dns_name_t name1;
dns_name_t name2;
dns_name_t name3;
@@ -255,128 +265,48 @@ ISC_RUN_TEST_IMPL(compression) {
r.length = sizeof(plain3);
dns_name_fromregion(&name4, &r);
/* Test 1: off, rdata */
permitted = false;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
/* Test1: enabled, off, rdata */
compress_test(&name1, &name2, &name3, plain, sizeof(plain), plain,
sizeof(plain), &cctx, dctx, true);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test2: on, rdata */
permitted = true;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(plain), true, false, true);
/* Test2: enabled, on, rdata */
compress_test(&name1, &name2, &name3, compressed, sizeof(compressed),
plain, sizeof(plain), &cctx, dctx, true);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test3: off, disabled, rdata */
permitted = false;
dns_compress_init(&cctx, mctx, DNS_COMPRESS_DISABLED);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
plain, sizeof(plain), true, true, true);
/* Test3: disabled, off, rdata */
compress_test(&name1, &name2, &name3, plain, sizeof(plain), plain,
sizeof(plain), &cctx, dctx, true);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test4: on, disabled, rdata */
permitted = true;
dns_compress_init(&cctx, mctx, DNS_COMPRESS_DISABLED);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(plain), false, false, true);
/* Test4: disabled, on, rdata */
compress_test(&name1, &name2, &name3, plain, sizeof(plain), plain,
sizeof(plain), &cctx, dctx, true);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test5: on, rdata */
permitted = true;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(plain), false, true, true);
/* Test5: enabled, on, rdata */
compress_test(&name1, dns_rootname, &name4, root_plain,
sizeof(root_plain), root_plain, sizeof(root_plain), &cctx,
dctx, true);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test 6: off, owner */
permitted = false;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(root_plain), root_plain, sizeof(root_plain), true,
true, true);
/* Test6: enabled, off, owner */
compress_test(&name1, &name2, &name3, plain, sizeof(plain), plain,
sizeof(plain), &cctx, dctx, false);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test7: on, owner */
permitted = true;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(plain), true, false, false);
/* Test7: enabled,on, owner */
compress_test(&name1, &name2, &name3, compressed, sizeof(compressed),
plain, sizeof(plain), &cctx, dctx, false);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test8: off, disabled, owner */
permitted = false;
dns_compress_init(&cctx, mctx, DNS_COMPRESS_DISABLED);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
plain, sizeof(plain), true, true, false);
/* Test8: disabled, off, owner */
compress_test(&name1, &name2, &name3, plain, sizeof(plain), plain,
sizeof(plain), &cctx, dctx, false);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test9: on, disabled, owner */
permitted = true;
dns_compress_init(&cctx, mctx, DNS_COMPRESS_DISABLED);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
sizeof(plain), false, false, false);
/* Test9: disabled, on, owner */
compress_test(&name1, &name2, &name3, disabled_owner,
sizeof(disabled_owner), plain, sizeof(plain), &cctx, dctx,
sizeof(disabled_owner), plain, sizeof(plain), false, true,
false);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
/* Test10: on, owner */
permitted = true;
dns_compress_init(&cctx, mctx, 0);
dns_compress_setpermitted(&cctx, permitted);
dctx = dns_decompress_setpermitted(DNS_DECOMPRESS_DEFAULT, permitted);
/* Test10: enabled, on, owner */
compress_test(&name1, dns_rootname, &name4, root_plain,
sizeof(root_plain), root_plain, sizeof(root_plain), &cctx,
dctx, false);
dns_compress_rollback(&cctx, 0);
dns_compress_invalidate(&cctx);
sizeof(root_plain), root_plain, sizeof(root_plain), true,
true, false);
}
#define NAME_LO 25
@@ -842,13 +772,9 @@ ISC_RUN_TEST_IMPL(fromwire_thread(void *arg) {
unsigned char output_data[DNS_NAME_MAXWIRE];
isc_buffer_t source, target;
unsigned int i;
dns_decompress_t dctx;
UNUSED(arg);
dns_decompress_init(&dctx, DNS_DECOMPRESS_STRICT);
dns_decompress_setmethods(&dctx, DNS_COMPRESS_NONE);
isc_buffer_init(&source, data, sizeof(data));
isc_buffer_add(&source, sizeof(data));
isc_buffer_init(&target, output_data, sizeof(output_data));
@@ -863,7 +789,7 @@ ISC_RUN_TEST_IMPL(fromwire_thread(void *arg) {
isc_buffer_setactive(&source, sizeof(data));
dns_name_init(&name, NULL);
(void)dns_name_fromwire(&name, &source, &dctx, 0, &target);
(void)dns_name_fromwire(&name, &source, NULL, &target);
}
return (NULL);

Some files were not shown because too many files have changed in this diff Show More