2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-03 08:05:21 +00:00

4718. [func] Avoid seaching for a owner name compression pointer

more than once when writing out a RRset. [RT #45802]
This commit is contained in:
Mark Andrews
2017-09-13 09:24:34 +10:00
parent 25b33bede4
commit 4a258c3c42
4 changed files with 47 additions and 10 deletions

View File

@@ -1,3 +1,6 @@
4718. [func] Avoid seaching for a owner name compression pointer
more than once when writing out a RRset. [RT #45802]
4717. [bug] Treat replies with QCOUNT=0 as truncated if TC=1, 4717. [bug] Treat replies with QCOUNT=0 as truncated if TC=1,
FORMERR if TC=0, and log the error correctly. FORMERR if TC=0, and log the error correctly.
[RT #45836] [RT #45836]

View File

@@ -739,6 +739,9 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
isc_result_t isc_result_t
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
isc_buffer_t *target); isc_buffer_t *target);
isc_result_t
dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
isc_buffer_t *target, isc_uint16_t *comp_offsetp);
/*%< /*%<
* Convert 'name' into wire format, compressing it as specified by the * Convert 'name' into wire format, compressing it as specified by the
* compression context 'cctx', and storing the result in 'target'. * compression context 'cctx', and storing the result in 'target'.

View File

@@ -1987,6 +1987,13 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
isc_result_t isc_result_t
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
isc_buffer_t *target) isc_buffer_t *target)
{
return (dns_name_towire2(name, cctx, target, NULL));
}
isc_result_t
dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
isc_buffer_t *target, isc_uint16_t *comp_offsetp)
{ {
unsigned int methods; unsigned int methods;
isc_uint16_t offset; isc_uint16_t offset;
@@ -2005,6 +2012,23 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
REQUIRE(cctx != NULL); REQUIRE(cctx != NULL);
REQUIRE(ISC_BUFFER_VALID(target)); REQUIRE(ISC_BUFFER_VALID(target));
/*
* If this exact name was already rendered before, and the
* offset of the previously rendered name is passed to us, write
* a compression pointer directly.
*/
methods = dns_compress_getmethods(cctx);
if (comp_offsetp != NULL && *comp_offsetp < 0x4000 &&
(name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
(methods & DNS_COMPRESS_GLOBAL14) != 0) {
if (ISC_UNLIKELY(target->length - target->used < 2))
return (ISC_R_NOSPACE);
offset = *comp_offsetp;
offset |= 0xc000;
isc_buffer_putuint16(target, offset);
return (ISC_R_SUCCESS);
}
/* /*
* If 'name' doesn't have an offsets table, make a clone which * If 'name' doesn't have an offsets table, make a clone which
* has one. * has one.
@@ -2022,8 +2046,6 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
offset = target->used; /*XXX*/ offset = target->used; /*XXX*/
methods = dns_compress_getmethods(cctx);
if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 && if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
(methods & DNS_COMPRESS_GLOBAL14) != 0) (methods & DNS_COMPRESS_GLOBAL14) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &go); gf = dns_compress_findglobal(cctx, name, &gp, &go);
@@ -2034,7 +2056,7 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
* If the offset is too high for 14 bit global compression, we're * If the offset is too high for 14 bit global compression, we're
* out of luck. * out of luck.
*/ */
if (gf && go >= 0x4000) if (gf && ISC_UNLIKELY(go >= 0x4000))
gf = ISC_FALSE; gf = ISC_FALSE;
/* /*
@@ -2044,25 +2066,32 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
gf = ISC_FALSE; gf = ISC_FALSE;
if (gf) { if (gf) {
if (target->length - target->used < gp.length) if (ISC_UNLIKELY(target->length - target->used < gp.length))
return (ISC_R_NOSPACE); return (ISC_R_NOSPACE);
(void)memmove((unsigned char *)target->base + target->used, (void)memmove((unsigned char *)target->base + target->used,
gp.ndata, (size_t)gp.length); gp.ndata, (size_t)gp.length);
isc_buffer_add(target, gp.length); isc_buffer_add(target, gp.length);
go |= 0xc000; if (ISC_UNLIKELY(target->length - target->used < 2))
if (target->length - target->used < 2)
return (ISC_R_NOSPACE); return (ISC_R_NOSPACE);
isc_buffer_putuint16(target, go); isc_buffer_putuint16(target, go | 0xc000);
if (gp.length != 0) if (gp.length != 0) {
dns_compress_add(cctx, name, &gp, offset); dns_compress_add(cctx, name, &gp, offset);
if (comp_offsetp != NULL)
*comp_offsetp = offset;
} else if (comp_offsetp != NULL) {
*comp_offsetp = go;
}
} else { } else {
if (target->length - target->used < name->length) if (ISC_UNLIKELY(target->length - target->used < name->length))
return (ISC_R_NOSPACE); return (ISC_R_NOSPACE);
(void)memmove((unsigned char *)target->base + target->used, (void)memmove((unsigned char *)target->base + target->used,
name->ndata, (size_t)name->length); name->ndata, (size_t)name->length);
isc_buffer_add(target, name->length); isc_buffer_add(target, name->length);
dns_compress_add(cctx, name, name, offset); dns_compress_add(cctx, name, name, offset);
if (comp_offsetp != NULL)
*comp_offsetp = offset;
} }
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }

View File

@@ -324,6 +324,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
struct towire_sort *out = out_fixed; struct towire_sort *out = out_fixed;
dns_fixedname_t fixed; dns_fixedname_t fixed;
dns_name_t *name; dns_name_t *name;
isc_uint16_t offset;
UNUSED(state); UNUSED(state);
@@ -464,6 +465,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
name = dns_fixedname_name(&fixed); name = dns_fixedname_name(&fixed);
dns_name_copy(owner_name, name, NULL); dns_name_copy(owner_name, name, NULL);
dns_rdataset_getownercase(rdataset, name); dns_rdataset_getownercase(rdataset, name);
offset = 0xffff;
name->attributes |= owner_name->attributes & name->attributes |= owner_name->attributes &
DNS_NAMEATTR_NOCOMPRESS; DNS_NAMEATTR_NOCOMPRESS;
@@ -475,7 +477,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
rrbuffer = *target; rrbuffer = *target;
dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
result = dns_name_towire(name, cctx, target); result = dns_name_towire2(name, cctx, target, &offset);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto rollback; goto rollback;
headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t); headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);