mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Rewrite the name compression code to use a hashtable instead of an RBT and
avoid allocating memory in most cases. This increases performance by about 225% on the rc query test (~305 q/s to 990 q/s).
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: compress.c,v 1.36 2000/11/14 23:29:49 bwelling Exp $ */
|
/* $Id: compress.c,v 1.37 2000/12/29 00:59:38 bwelling Exp $ */
|
||||||
|
|
||||||
#define DNS_NAME_USEINLINE 1
|
#define DNS_NAME_USEINLINE 1
|
||||||
|
|
||||||
@@ -36,17 +36,12 @@
|
|||||||
#define DCTX_MAGIC 0x44435458U /* DCTX */
|
#define DCTX_MAGIC 0x44435458U /* DCTX */
|
||||||
#define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
|
#define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
|
||||||
|
|
||||||
static void
|
|
||||||
free_offset(void *offset, void *mctx);
|
|
||||||
|
|
||||||
static isc_boolean_t
|
static isc_boolean_t
|
||||||
compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix,
|
compress_find(dns_compress_t *cctx, dns_name_t *name, dns_name_t *prefix,
|
||||||
dns_name_t *suffix, isc_uint16_t *offset,
|
dns_name_t *suffix, isc_uint16_t *offset);
|
||||||
isc_buffer_t *workspace);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
compress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix,
|
compress_add(dns_compress_t *cctx, dns_name_t *name, isc_uint16_t offset);
|
||||||
isc_uint16_t offset, isc_boolean_t global16, isc_mem_t *mctx);
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Compression
|
*** Compression
|
||||||
@@ -54,35 +49,44 @@ compress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix,
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
|
dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
|
||||||
isc_result_t result;
|
unsigned int i;
|
||||||
|
|
||||||
REQUIRE(cctx != NULL);
|
REQUIRE(cctx != NULL);
|
||||||
REQUIRE(mctx != NULL);
|
REQUIRE(mctx != NULL);
|
||||||
|
|
||||||
cctx->allowed = 0;
|
cctx->allowed = 0;
|
||||||
cctx->rdata = 0;
|
cctx->rdata = 0;
|
||||||
cctx->global16 = ISC_FALSE;
|
|
||||||
cctx->edns = edns;
|
cctx->edns = edns;
|
||||||
cctx->global = NULL;
|
for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++)
|
||||||
result = dns_rbt_create(mctx, free_offset, mctx, &cctx->global);
|
cctx->table[i] = NULL;
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
return (result);
|
|
||||||
cctx->mctx = mctx;
|
cctx->mctx = mctx;
|
||||||
|
cctx->count = 0;
|
||||||
cctx->magic = CCTX_MAGIC;
|
cctx->magic = CCTX_MAGIC;
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_compress_invalidate(dns_compress_t *cctx) {
|
dns_compress_invalidate(dns_compress_t *cctx) {
|
||||||
|
dns_compressnode_t *node;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
REQUIRE(VALID_CCTX(cctx));
|
REQUIRE(VALID_CCTX(cctx));
|
||||||
|
|
||||||
cctx->magic = 0;
|
cctx->magic = 0;
|
||||||
if (cctx->global != NULL)
|
if (cctx->table != NULL) {
|
||||||
dns_rbt_destroy(&cctx->global);
|
for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
|
||||||
|
while (cctx->table[i] != NULL) {
|
||||||
|
node = cctx->table[i];
|
||||||
|
cctx->table[i] = cctx->table[i]->next;
|
||||||
|
if (node->count < DNS_COMPRESS_INITIALNODES)
|
||||||
|
continue;
|
||||||
|
isc_mem_put(cctx->mctx, node,
|
||||||
|
sizeof(dns_compressnode_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
cctx->allowed = 0;
|
cctx->allowed = 0;
|
||||||
cctx->rdata = 0;
|
cctx->rdata = 0;
|
||||||
cctx->global16 = ISC_FALSE;
|
|
||||||
cctx->edns = -1;
|
cctx->edns = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,86 +112,41 @@ dns_compress_getedns(dns_compress_t *cctx) {
|
|||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
|
dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
|
||||||
dns_name_t *prefix, dns_name_t *suffix,
|
dns_name_t *prefix, dns_name_t *suffix,
|
||||||
isc_uint16_t *offset, isc_buffer_t *workspace)
|
isc_uint16_t *offset)
|
||||||
{
|
{
|
||||||
REQUIRE(VALID_CCTX(cctx));
|
REQUIRE(VALID_CCTX(cctx));
|
||||||
REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
|
REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
|
||||||
REQUIRE(offset != NULL);
|
REQUIRE(offset != NULL);
|
||||||
|
|
||||||
return (compress_find(cctx->global, name, prefix, suffix, offset,
|
return (compress_find(cctx, name, prefix, suffix, offset));
|
||||||
workspace));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_compress_add(dns_compress_t *cctx, dns_name_t *prefix,
|
dns_compress_add(dns_compress_t *cctx, dns_name_t *name, isc_uint16_t offset) {
|
||||||
dns_name_t *suffix, isc_uint16_t offset)
|
|
||||||
{
|
|
||||||
REQUIRE(VALID_CCTX(cctx));
|
REQUIRE(VALID_CCTX(cctx));
|
||||||
|
REQUIRE(dns_name_isabsolute(name));
|
||||||
|
|
||||||
compress_add(cctx->global, prefix, suffix, offset,
|
compress_add(cctx, name, offset);
|
||||||
cctx->global16, cctx->mctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
|
dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
|
||||||
dns_rbtnode_t *node;
|
unsigned int i;
|
||||||
dns_fixedname_t foundfixed;
|
dns_compressnode_t *node;
|
||||||
dns_fixedname_t fullfixed;
|
|
||||||
dns_fixedname_t originfixed;
|
|
||||||
dns_name_t *foundname;
|
|
||||||
dns_name_t *fullname;
|
|
||||||
dns_name_t *origin;
|
|
||||||
dns_rbtnodechain_t chain;
|
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
REQUIRE(VALID_CCTX(cctx));
|
REQUIRE(VALID_CCTX(cctx));
|
||||||
|
|
||||||
/*
|
for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
|
||||||
* Initalise things.
|
node = cctx->table[i];
|
||||||
*/
|
while (node != NULL && node->offset >= offset) {
|
||||||
dns_fixedname_init(&foundfixed);
|
cctx->table[i] = node->next;
|
||||||
foundname = dns_fixedname_name(&foundfixed);
|
if (node->count >= DNS_COMPRESS_INITIALNODES)
|
||||||
dns_fixedname_init(&fullfixed);
|
isc_mem_put(cctx->mctx, node,
|
||||||
fullname = dns_fixedname_name(&fullfixed);
|
sizeof(dns_compressnode_t));
|
||||||
dns_fixedname_init(&originfixed);
|
cctx->count--;
|
||||||
origin = dns_fixedname_name(&originfixed);
|
node = cctx->table[i];
|
||||||
dns_rbtnodechain_init(&chain, cctx->mctx);
|
|
||||||
|
|
||||||
again:
|
|
||||||
result = dns_rbtnodechain_first(&chain, cctx->global, foundname,
|
|
||||||
origin);
|
|
||||||
|
|
||||||
while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
|
|
||||||
result = dns_rbtnodechain_current(&chain, foundname,
|
|
||||||
origin, &node);
|
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (node->data != NULL &&
|
|
||||||
(*(isc_uint16_t*)node->data >= offset)) {
|
|
||||||
result = dns_name_concatenate(foundname,
|
|
||||||
dns_name_isabsolute(foundname) ?
|
|
||||||
NULL : origin,
|
|
||||||
fullname, NULL);
|
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
break;
|
|
||||||
|
|
||||||
result = dns_rbt_deletename(cctx->global, fullname,
|
|
||||||
ISC_FALSE);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
* If the delete is successful the chain is broken.
|
|
||||||
*/
|
|
||||||
dns_rbtnodechain_reset(&chain);
|
|
||||||
goto again;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rbtnodechain_next(&chain, foundname, origin);
|
|
||||||
}
|
}
|
||||||
dns_rbtnodechain_invalidate(&chain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -262,177 +221,102 @@ dns_decompress_type(dns_decompress_t *dctx) {
|
|||||||
*** Private
|
*** Private
|
||||||
***/
|
***/
|
||||||
|
|
||||||
static void
|
|
||||||
free_offset(void *offset, void *mctx) {
|
|
||||||
REQUIRE(offset != NULL);
|
|
||||||
REQUIRE(mctx != NULL);
|
|
||||||
isc_mem_put(mctx, offset, sizeof(isc_uint16_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the labels in prefix to RBT.
|
* Add the labels in prefix to the compression table.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
compress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix,
|
compress_add(dns_compress_t *cctx, dns_name_t *name, isc_uint16_t offset) {
|
||||||
isc_uint16_t offset, isc_boolean_t global16, isc_mem_t *mctx)
|
dns_name_t tname, nname;
|
||||||
{
|
|
||||||
|
|
||||||
dns_name_t name;
|
|
||||||
dns_name_t full;
|
|
||||||
dns_label_t label;
|
dns_label_t label;
|
||||||
unsigned int count;
|
|
||||||
unsigned int start;
|
unsigned int start;
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
isc_uint16_t *data;
|
unsigned int hash;
|
||||||
isc_result_t result;
|
dns_compressnode_t *node;
|
||||||
unsigned char buffer[255];
|
|
||||||
isc_buffer_t target;
|
|
||||||
dns_offsets_t offsets;
|
|
||||||
|
|
||||||
count = dns_name_countlabels(prefix);
|
dns_name_init(&tname, NULL);
|
||||||
if (dns_name_isabsolute(prefix))
|
dns_name_init(&nname, NULL);
|
||||||
count--;
|
|
||||||
|
n = dns_name_countlabels(name);
|
||||||
start = 0;
|
start = 0;
|
||||||
dns_name_init(&full, offsets);
|
while (n > 1) {
|
||||||
dns_name_init(&name, NULL);
|
if (offset >= 0x4000)
|
||||||
isc_buffer_init(&target, buffer, sizeof(buffer));
|
|
||||||
result = dns_name_concatenate(prefix, suffix, &full, &target);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
return;
|
|
||||||
n = dns_name_countlabels(&full);
|
|
||||||
while (count > 0) {
|
|
||||||
if (offset >= 16384 && !global16)
|
|
||||||
break;
|
break;
|
||||||
dns_name_getlabelsequence(&full, start, n, &name);
|
dns_name_getlabelsequence(name, start, n, &tname);
|
||||||
data = isc_mem_get(mctx, sizeof *data);
|
hash = dns_name_hash(&tname, ISC_FALSE) % DNS_COMPRESS_TABLESIZE;
|
||||||
if (data == NULL)
|
/*
|
||||||
return;
|
* Look for the name in the hash bucket. If it's there,
|
||||||
*data = offset;
|
* we're done.
|
||||||
result = dns_rbt_addname(root, &name, data);
|
*/
|
||||||
if (result != ISC_R_SUCCESS) {
|
for (node = cctx->table[hash]; node != NULL; node = node->next)
|
||||||
isc_mem_put(mctx, data, sizeof *data);
|
{
|
||||||
return;
|
dns_name_fromregion(&nname, &node->r);
|
||||||
|
if (dns_name_equal(&nname, &tname))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
dns_name_getlabel(&name, 0, &label);
|
/*
|
||||||
|
* It's not there. Create a new node and add it.
|
||||||
|
*/
|
||||||
|
if (cctx->count < DNS_COMPRESS_INITIALNODES)
|
||||||
|
node = &cctx->initialnodes[cctx->count];
|
||||||
|
else {
|
||||||
|
node = isc_mem_get(cctx->mctx,
|
||||||
|
sizeof(dns_compressnode_t));
|
||||||
|
if (node == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node->count = cctx->count++;
|
||||||
|
node->offset = offset;
|
||||||
|
dns_name_toregion(&tname, &node->r);
|
||||||
|
node->next = cctx->table[hash];
|
||||||
|
cctx->table[hash] = node;
|
||||||
|
dns_name_getlabel(&tname, 0, &label);
|
||||||
offset += label.length;
|
offset += label.length;
|
||||||
start++;
|
start++;
|
||||||
n--;
|
n--;
|
||||||
count--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the longest match of name in root.
|
* Find the longest match of name in the table.
|
||||||
* If match is found return ISC_TRUE. prefix, suffix and offset
|
* If match is found return ISC_TRUE. prefix, suffix and offset are updated.
|
||||||
* are updated.
|
* If no match is found return ISC_FALSE.
|
||||||
* If no match is found return ISC_FALSE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static isc_boolean_t
|
static isc_boolean_t
|
||||||
compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix,
|
compress_find(dns_compress_t *cctx,
|
||||||
dns_name_t *suffix, isc_uint16_t *offset,
|
dns_name_t *name, dns_name_t *prefix,
|
||||||
isc_buffer_t *workspace)
|
dns_name_t *suffix, isc_uint16_t *offset)
|
||||||
{
|
{
|
||||||
dns_fixedname_t found;
|
dns_name_t tname, nname;
|
||||||
dns_name_t *foundname;
|
dns_compressnode_t *node;
|
||||||
dns_name_t tmpprefix;
|
unsigned int labels, hash, n;
|
||||||
dns_name_t tmpsuffix;
|
|
||||||
isc_result_t result;
|
|
||||||
isc_uint16_t *data = NULL;
|
|
||||||
dns_label_t foundlabel;
|
|
||||||
dns_label_t namelabel;
|
|
||||||
unsigned int foundlabels;
|
|
||||||
unsigned int namelabels;
|
|
||||||
unsigned int foundbits;
|
|
||||||
unsigned int namebits;
|
|
||||||
unsigned int bits;
|
|
||||||
unsigned int prefixlen;
|
|
||||||
unsigned int j;
|
|
||||||
unsigned char buf[2 + 256/8]; /* size of biggest bit label */
|
|
||||||
dns_bitlabel_t bit;
|
|
||||||
isc_region_t region;
|
|
||||||
|
|
||||||
dns_fixedname_init(&found);
|
labels = dns_name_countlabels(name);
|
||||||
foundname = dns_fixedname_name(&found);
|
INSIST(labels > 0);
|
||||||
/*
|
|
||||||
* Getting rid of the offsets table for foundname improves
|
|
||||||
* perfomance, since the offsets table is not needed and maintaining
|
|
||||||
* it has costs.
|
|
||||||
*/
|
|
||||||
foundname->offsets = NULL;
|
|
||||||
result = dns_rbt_findname(root, name, 0, foundname, (void *)&data);
|
|
||||||
if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH)
|
|
||||||
return (ISC_FALSE);
|
|
||||||
if (data == NULL) /* root label */
|
|
||||||
return (ISC_FALSE);
|
|
||||||
/*
|
|
||||||
* Do we have to do bit string processing?
|
|
||||||
*/
|
|
||||||
dns_name_getlabel(foundname, 0, &foundlabel);
|
|
||||||
foundlabels = dns_name_countlabels(foundname);
|
|
||||||
INSIST(foundlabels > 1); /* root labels are not added to tree */
|
|
||||||
namelabels = dns_name_countlabels(name);
|
|
||||||
if (dns_label_type(&foundlabel) == dns_labeltype_bitstring) {
|
|
||||||
dns_name_getlabel(name, namelabels - foundlabels, &namelabel);
|
|
||||||
INSIST(dns_label_type(&namelabel) == dns_labeltype_bitstring);
|
|
||||||
foundbits = dns_label_countbits(&foundlabel);
|
|
||||||
namebits = dns_label_countbits(&namelabel);
|
|
||||||
} else
|
|
||||||
namebits = foundbits = 0;
|
|
||||||
|
|
||||||
if (namebits == foundbits) {
|
dns_name_init(&tname, NULL);
|
||||||
INSIST(namelabels >= foundlabels);
|
dns_name_init(&nname, NULL);
|
||||||
prefixlen = namelabels - foundlabels;
|
|
||||||
if (prefixlen == 0) {
|
for (n = 0; n < labels - 1; n++) {
|
||||||
prefix->length = 0;
|
dns_name_getlabelsequence(name, n, labels - n, &tname);
|
||||||
prefix->labels = 0;
|
hash = dns_name_hash(&tname, ISC_FALSE) % DNS_COMPRESS_TABLESIZE;
|
||||||
} else
|
for (node = cctx->table[hash]; node != NULL; node = node->next)
|
||||||
dns_name_getlabelsequence(name, 0, prefixlen, prefix);
|
{
|
||||||
result = dns_name_concatenate(NULL, foundname, suffix,
|
dns_name_fromregion(&nname, &node->r);
|
||||||
workspace);
|
if (dns_name_equal(&nname, &tname))
|
||||||
if (result != ISC_R_SUCCESS)
|
break;
|
||||||
return (ISC_FALSE);
|
}
|
||||||
*offset = *data;
|
if (node != NULL)
|
||||||
return (ISC_TRUE);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this stage we have a bit string label to split in two.
|
* If node == NULL, we found no match at all.
|
||||||
* There is potentially a prefix before this label and definitly
|
|
||||||
* a suffix after it (if only the root).
|
|
||||||
*/
|
*/
|
||||||
INSIST(result == DNS_R_PARTIALMATCH);
|
if (node == NULL)
|
||||||
result = dns_name_concatenate(NULL, foundname, suffix, workspace);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
return (ISC_FALSE);
|
return (ISC_FALSE);
|
||||||
prefixlen = namelabels - foundlabels;
|
|
||||||
dns_name_init(&tmpprefix, NULL);
|
dns_name_clone(&tname, suffix);
|
||||||
dns_name_init(&tmpsuffix, NULL);
|
dns_name_getlabelsequence(name, 0, n, prefix);
|
||||||
if (prefixlen != 0) {
|
*offset = node->offset;
|
||||||
dns_name_getlabelsequence(name, 0, prefixlen, &tmpprefix);
|
|
||||||
}
|
|
||||||
INSIST(namebits > foundbits);
|
|
||||||
bits = namebits - foundbits;
|
|
||||||
j = 0;
|
|
||||||
memset(buf, 0, sizeof buf);
|
|
||||||
INSIST((bits / 8 + 1) < sizeof buf);
|
|
||||||
/*
|
|
||||||
* Copy least significant bits.
|
|
||||||
*/
|
|
||||||
while (j < bits) {
|
|
||||||
bit = dns_label_getbit(&namelabel, foundbits + j);
|
|
||||||
if (bit)
|
|
||||||
buf[2 + j / 8] |= (1 << (7 - (j % 8)));
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
buf[0] = DNS_LABELTYPE_BITSTRING;
|
|
||||||
buf[1] = j;
|
|
||||||
region.base = buf;
|
|
||||||
region.length = 2 + (j + 7) / 8;
|
|
||||||
dns_name_fromregion(&tmpsuffix, ®ion);
|
|
||||||
result = dns_name_concatenate(&tmpprefix, &tmpsuffix, prefix,
|
|
||||||
workspace);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
return (ISC_FALSE);
|
|
||||||
*offset = *data;
|
|
||||||
return (ISC_TRUE);
|
return (ISC_TRUE);
|
||||||
}
|
}
|
||||||
|
@@ -15,12 +15,13 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: compress.h,v 1.20 2000/12/28 00:42:56 bwelling Exp $ */
|
/* $Id: compress.h,v 1.21 2000/12/29 00:59:41 bwelling Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_COMPRESS_H
|
#ifndef DNS_COMPRESS_H
|
||||||
#define DNS_COMPRESS_H 1
|
#define DNS_COMPRESS_H 1
|
||||||
|
|
||||||
#include <isc/lang.h>
|
#include <isc/lang.h>
|
||||||
|
#include <isc/region.h>
|
||||||
|
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
|
||||||
@@ -28,28 +29,35 @@ ISC_LANG_BEGINDECLS
|
|||||||
|
|
||||||
#define DNS_COMPRESS_NONE 0x00 /* no compression */
|
#define DNS_COMPRESS_NONE 0x00 /* no compression */
|
||||||
#define DNS_COMPRESS_GLOBAL14 0x01 /* "normal" compression. */
|
#define DNS_COMPRESS_GLOBAL14 0x01 /* "normal" compression. */
|
||||||
#define DNS_COMPRESS_GLOBAL 0x01 /* all global comp. */
|
#define DNS_COMPRESS_ALL 0x01 /* all compression. */
|
||||||
/*
|
|
||||||
* Synonymous with DNS_COMPRESS_GLOBAL. A genuine difference existed when
|
|
||||||
* local compression was an IETF draft, but that draft has been retired without
|
|
||||||
* becoming a standard. Numerous bits of code referred to DNS_COMPRESS_ALL
|
|
||||||
* already, and rather than change them all, the DNS_COMPRESS_ALL definition
|
|
||||||
* was left in, but no longer refers to local compression.
|
|
||||||
*/
|
|
||||||
#define DNS_COMPRESS_ALL 0x03 /* all compression. */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Direct manipulation of the structures is strongly discouraged.
|
* Direct manipulation of the structures is strongly discouraged.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define DNS_COMPRESS_TABLESIZE 64
|
||||||
|
#define DNS_COMPRESS_INITIALNODES 16
|
||||||
|
|
||||||
|
typedef struct dns_compressnode dns_compressnode_t;
|
||||||
|
|
||||||
|
struct dns_compressnode {
|
||||||
|
isc_region_t r;
|
||||||
|
isc_uint16_t offset;
|
||||||
|
isc_uint16_t count;
|
||||||
|
dns_compressnode_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct dns_compress {
|
struct dns_compress {
|
||||||
unsigned int magic; /* Magic number. */
|
unsigned int magic; /* Magic number. */
|
||||||
unsigned int allowed; /* Allowed methods. */
|
unsigned int allowed; /* Allowed methods. */
|
||||||
unsigned int rdata; /* Start of local rdata. */
|
unsigned int rdata; /* Start of local rdata. */
|
||||||
isc_boolean_t global16; /* 16 bit offsets allowed. */
|
int edns; /* Edns version or -1. */
|
||||||
int edns; /* Edns version or -1. */
|
/* Global compression table. */
|
||||||
dns_rbt_t *global; /* Global RBT. */
|
dns_compressnode_t *table[DNS_COMPRESS_TABLESIZE];
|
||||||
isc_mem_t *mctx; /* Memeory context. */
|
/* Preallocated nodes for the table. */
|
||||||
|
dns_compressnode_t initialnodes[DNS_COMPRESS_INITIALNODES];
|
||||||
|
isc_uint16_t count; /* Number of nodes. */
|
||||||
|
isc_mem_t *mctx; /* Memory context. */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -73,9 +81,9 @@ dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx);
|
|||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' is a valid dns_compress_t structure.
|
* 'cctx' is a valid dns_compress_t structure.
|
||||||
* 'mctx' is a initalised memory context.
|
* 'mctx' is an initialized memory context.
|
||||||
* Ensures:
|
* Ensures:
|
||||||
* cctx->global is initalised.
|
* cctx->global is initialized.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* ISC_R_SUCCESS
|
* ISC_R_SUCCESS
|
||||||
@@ -87,10 +95,9 @@ dns_compress_invalidate(dns_compress_t *cctx);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalidate the compression structure pointed to by cctx.
|
* Invalidate the compression structure pointed to by cctx.
|
||||||
* Destroys 'cctx->glocal' and 'cctx->local' RBT.
|
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' to be initalised.
|
* 'cctx' to be initialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -100,7 +107,7 @@ dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed);
|
|||||||
* Sets allowed compression methods.
|
* Sets allowed compression methods.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' to be initalised.
|
* 'cctx' to be initialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -110,7 +117,7 @@ dns_compress_getmethods(dns_compress_t *cctx);
|
|||||||
* Gets allowed compression methods.
|
* Gets allowed compression methods.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' to be initalised.
|
* 'cctx' to be initialized.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* allowed compression bitmap.
|
* allowed compression bitmap.
|
||||||
@@ -123,7 +130,7 @@ dns_compress_getedns(dns_compress_t *cctx);
|
|||||||
* Gets edns value.
|
* Gets edns value.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' to be initalised.
|
* 'cctx' to be initialized.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* -1 .. 255
|
* -1 .. 255
|
||||||
@@ -132,19 +139,16 @@ dns_compress_getedns(dns_compress_t *cctx);
|
|||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
|
dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
|
||||||
dns_name_t *prefix, dns_name_t *suffix,
|
dns_name_t *prefix, dns_name_t *suffix,
|
||||||
isc_uint16_t *offset, isc_buffer_t *workspace);
|
isc_uint16_t *offset);
|
||||||
/*
|
/*
|
||||||
* Finds longest possible match of 'name' in the global compression
|
* Finds longest possible match of 'name' in the global compression table.
|
||||||
* RBT. Workspace needs to be large enough to hold 'name' when split
|
|
||||||
* in two (length->name + 3).
|
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' to be initalised.
|
* 'cctx' to be initialized.
|
||||||
* 'name' to be a absolute name.
|
* 'name' to be a absolute name.
|
||||||
* 'prefix' to be initalised.
|
* 'prefix' to be initialized.
|
||||||
* 'suffix' to be initalised.
|
* 'suffix' to be initialized.
|
||||||
* 'offset' to point it a isc_uint16_t.
|
* 'offset' to point it a isc_uint16_t.
|
||||||
* 'workspace' to be initalised.
|
|
||||||
*
|
*
|
||||||
* Ensures:
|
* Ensures:
|
||||||
* 'prefix', 'suffix' and 'offset' are valid if ISC_TRUE is
|
* 'prefix', 'suffix' and 'offset' are valid if ISC_TRUE is
|
||||||
@@ -155,27 +159,24 @@ dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_compress_add(dns_compress_t *cctx, dns_name_t *prefix,
|
dns_compress_add(dns_compress_t *cctx, dns_name_t *name, isc_uint16_t offset);
|
||||||
dns_name_t *suffix, isc_uint16_t offset);
|
|
||||||
/*
|
/*
|
||||||
* Add compression pointers for labels in prefix to RBT's.
|
* Add compression pointers for name to the compression table,
|
||||||
* If 'prefix' is absolute 'suffix' must be NULL otherwise
|
* not replacing existing pointers.
|
||||||
* suffix must be absolute.
|
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' initalised
|
* 'cctx' initialized
|
||||||
* 'prefix' to be initalised
|
* 'name' must be initialized and absolute
|
||||||
* 'suffix' to be initalised or NULL
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset);
|
dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove any compression pointers from global RBT >= offset.
|
* Remove any compression pointers from global table >= offset.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'cctx' is initalised.
|
* 'cctx' is initialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -197,7 +198,7 @@ dns_decompress_invalidate(dns_decompress_t *dctx);
|
|||||||
* Invalidates 'dctx'.
|
* Invalidates 'dctx'.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'dctx' to be initalised
|
* 'dctx' to be initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -207,7 +208,7 @@ dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed);
|
|||||||
* Sets 'dctx->allowed' to 'allowed'.
|
* Sets 'dctx->allowed' to 'allowed'.
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'dctx' to be initalised
|
* 'dctx' to be initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -217,7 +218,7 @@ dns_decompress_getmethods(dns_decompress_t *dctx);
|
|||||||
* Returns 'dctx->allowed'
|
* Returns 'dctx->allowed'
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'dctx' to be initalised
|
* 'dctx' to be initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -227,7 +228,7 @@ dns_decompress_edns(dns_decompress_t *dctx);
|
|||||||
* Returns 'dctx->edns'
|
* Returns 'dctx->edns'
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'dctx' to be initalised
|
* 'dctx' to be initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dns_decompresstype_t
|
dns_decompresstype_t
|
||||||
@@ -237,7 +238,7 @@ dns_decompress_type(dns_decompress_t *dctx);
|
|||||||
* Returns 'dctx->type'
|
* Returns 'dctx->type'
|
||||||
*
|
*
|
||||||
* Requires:
|
* Requires:
|
||||||
* 'dctx' to be initalised
|
* 'dctx' to be initialized
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ISC_LANG_ENDDECLS
|
ISC_LANG_ENDDECLS
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: name.c,v 1.110 2000/12/28 00:42:55 bwelling Exp $ */
|
/* $Id: name.c,v 1.111 2000/12/29 00:59:39 bwelling Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -2385,8 +2385,6 @@ dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
|
|||||||
dns_name_t gp, gs;
|
dns_name_t gp, gs;
|
||||||
isc_boolean_t gf;
|
isc_boolean_t gf;
|
||||||
isc_uint16_t go;
|
isc_uint16_t go;
|
||||||
unsigned char gb[257];
|
|
||||||
isc_buffer_t gws;
|
|
||||||
dns_offsets_t po, so, clo;
|
dns_offsets_t po, so, clo;
|
||||||
dns_name_t clname;
|
dns_name_t clname;
|
||||||
|
|
||||||
@@ -2409,14 +2407,13 @@ dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
|
|||||||
}
|
}
|
||||||
dns_name_init(&gp, po);
|
dns_name_init(&gp, po);
|
||||||
dns_name_init(&gs, so);
|
dns_name_init(&gs, so);
|
||||||
isc_buffer_init(&gws, gb, sizeof (gb));
|
|
||||||
|
|
||||||
offset = target->used; /*XXX*/
|
offset = target->used; /*XXX*/
|
||||||
|
|
||||||
methods = dns_compress_getmethods(cctx);
|
methods = dns_compress_getmethods(cctx);
|
||||||
|
|
||||||
if ((methods & DNS_COMPRESS_GLOBAL) != 0)
|
if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
|
||||||
gf = dns_compress_findglobal(cctx, name, &gp, &gs, &go, &gws);
|
gf = dns_compress_findglobal(cctx, name, &gp, &gs, &go);
|
||||||
else
|
else
|
||||||
gf = ISC_FALSE;
|
gf = ISC_FALSE;
|
||||||
|
|
||||||
@@ -2444,14 +2441,14 @@ dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
|
|||||||
return (ISC_R_NOSPACE);
|
return (ISC_R_NOSPACE);
|
||||||
isc_buffer_putuint16(target, go);
|
isc_buffer_putuint16(target, go);
|
||||||
if (gp.length != 0)
|
if (gp.length != 0)
|
||||||
dns_compress_add(cctx, &gp, &gs, offset);
|
dns_compress_add(cctx, name, offset);
|
||||||
} else {
|
} else {
|
||||||
if (target->length - target->used < name->length)
|
if (target->length - target->used < name->length)
|
||||||
return (ISC_R_NOSPACE);
|
return (ISC_R_NOSPACE);
|
||||||
(void)memcpy((unsigned char *)target->base + target->used,
|
(void)memcpy((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, NULL, offset);
|
dns_compress_add(cctx, name, offset);
|
||||||
}
|
}
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user