Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82a5d96407 | ||
|
|
180885fb46 | ||
|
|
8de253181e | ||
|
|
0fc505df97 | ||
|
|
da2abb8840 |
@@ -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]
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ®ion);
|
||||
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);
|
||||
|
||||
@@ -371,7 +371,6 @@ fromwire_caa(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
/*
|
||||
* Flags
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -89,7 +89,6 @@ fromwire_csync(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(options);
|
||||
UNUSED(dctx);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -131,7 +131,6 @@ fromwire_doa(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
REQUIRE(type == dns_rdatatype_doa);
|
||||
|
||||
|
||||
@@ -163,7 +163,6 @@ generic_fromwire_ds(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ fromwire_eui48(ARGS_FROMWIRE) {
|
||||
REQUIRE(type == dns_rdatatype_eui48);
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ fromwire_eui64(ARGS_FROMWIRE) {
|
||||
REQUIRE(type == dns_rdatatype_eui64);
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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, ®ion);
|
||||
isc_buffer_forward(source, region.length);
|
||||
if (region.length < 1) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -234,7 +234,6 @@ generic_fromwire_key(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
if (sr.length < 4) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -85,7 +85,6 @@ fromwire_l32(ARGS_FROMWIRE) {
|
||||
REQUIRE(type == dns_rdatatype_l32);
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ fromwire_l64(ARGS_FROMWIRE) {
|
||||
REQUIRE(type == dns_rdatatype_l64);
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -83,7 +83,6 @@ fromwire_nid(ARGS_FROMWIRE) {
|
||||
REQUIRE(type == dns_rdatatype_nid);
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -190,7 +190,6 @@ fromwire_nsec3(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(options);
|
||||
UNUSED(dctx);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
@@ -149,7 +149,6 @@ fromwire_nsec3param(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(options);
|
||||
UNUSED(dctx);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -75,7 +75,6 @@ fromwire_openpgpkey(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
/*
|
||||
* Keyring.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -126,7 +126,6 @@ generic_fromwire_tlsa(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ generic_fromwire_txt(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(options);
|
||||
|
||||
do {
|
||||
result = txt_fromwire(source, target);
|
||||
|
||||
@@ -105,7 +105,6 @@ fromwire_uri(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
/*
|
||||
* Priority, weight
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -148,7 +148,6 @@ fromwire_zonemd(ARGS_FROMWIRE) {
|
||||
UNUSED(type);
|
||||
UNUSED(rdclass);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ fromwire_hs_a(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, &sregion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -74,7 +74,6 @@ fromwire_in_a(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, &sregion);
|
||||
|
||||
@@ -90,7 +90,6 @@ fromwire_in_aaaa(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, &sregion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -149,7 +149,6 @@ fromwire_in_atma(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, ®ion);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -66,7 +66,6 @@ fromwire_in_eid(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, ®ion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -66,7 +66,6 @@ fromwire_in_nimloc(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, ®ion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -101,7 +101,6 @@ fromwire_in_nsap(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, ®ion);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -217,7 +217,6 @@ fromwire_in_wks(ARGS_FROMWIRE) {
|
||||
|
||||
UNUSED(type);
|
||||
UNUSED(dctx);
|
||||
UNUSED(options);
|
||||
UNUSED(rdclass);
|
||||
|
||||
isc_buffer_activeregion(source, &sr);
|
||||
|
||||
+3
-2
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user