Commit 1ef89653 authored by Mark Andrews's avatar Mark Andrews
Browse files

Add decompression.

parent 1783fac3
......@@ -69,7 +69,6 @@ dns_result_t printmessage(dns_message_t *message);
void
dump_packet(unsigned char *buf, u_int len)
{
extern dns_decompress_t dctx;
extern unsigned int rdcount, rlcount, ncount;
char t[5000]; /* XXX */
dns_message_t message;
......@@ -81,9 +80,6 @@ dump_packet(unsigned char *buf, u_int len)
rlcount = 0;
ncount = 0;
dctx.allowed = DNS_COMPRESS_GLOBAL14;
dns_name_init(&dctx.owner_name, NULL);
for (i = 0 ; i < len ; /* */ ) {
fprintf(stdout, "%02x", buf[i]);
if ((++i % 20) == 0)
......@@ -153,9 +149,7 @@ resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target)
INSIST(message.aucount == 0);
INSIST(message.adcount == 0);
dctx.allowed = DNS_COMPRESS_GLOBAL14;
dns_name_init(&dctx.owner_name, NULL);
dns_decompress_init(&dctx, -1, ISC_FALSE);
result = dns_compress_init(&cctx, -1, db->mctx);
if (result != DNS_R_SUCCESS)
return (result);
......@@ -167,6 +161,10 @@ resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target)
dns_name_init(&name, NULL);
isc_buffer_remaining(source, &r);
isc_buffer_setactive(source, r.length);
if (!dns_decompress_strict(&dctx))
dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL);
else
dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
result = dns_name_fromwire(&name, source, &dctx, ISC_FALSE, &tbuf);
qtype = getshort(source);
qclass = getshort(source);
......
......@@ -12,3 +12,4 @@ rdata_test
master_test
rbt_test
db_test
compress_test
......@@ -27,7 +27,8 @@ TARGETS = lex_test \
rwlock_test \
wire_test \
master_test \
db_test
db_test \
compress_test
@BIND9_MAKE_RULES@
......@@ -67,5 +68,8 @@ master_test: master_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a
db_test: db_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a
${CC} -o $@ db_test.o ${LIBS}
compress_test: compress_test.o ../../lib/isc/libisc.a ../../lib/dns/libdns.a
${CC} -o $@ compress_test.o ${LIBS}
clean distclean::
rm -f ${TARGETS}
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <isc/assertions.h>
#include <isc/error.h>
#include <dns/compress.h>
#include <dns/name.h>
unsigned char plain1[] = "\003foo";
unsigned char plain2[] = "\003bar\003foo";
unsigned char plain3[] = "\003xxx\003bar\003foo";
unsigned char plain[] =
"\003foo\0\003bar\003foo\0\003bar\003foo\0\003xxx\003bar\003foo";
unsigned char bit1[] = "\101\010b";
unsigned char bit2[] = "\101\014b\260";
unsigned char bit3[] = "\101\020b\264";
unsigned char bit[] = "\101\010b\0\101\014b\260\0\101\014b\260\0\101\020b\264";
int raw = 0;
void test(unsigned int, dns_name_t *, dns_name_t *, dns_name_t *,
unsigned char *, unsigned int);
int
main(int argc, char *argv[]) {
dns_name_t name1;
dns_name_t name2;
dns_name_t name3;
isc_region_t region;
int c;
while ((c = getopt(argc, argv, "r")) != -1) {
switch (c) {
case 'r':
raw++;
break;
}
}
dns_name_init(&name1, NULL);
region.base = plain1;
region.length = sizeof plain1;
dns_name_fromregion(&name1, &region);
dns_name_init(&name2, NULL);
region.base = plain2;
region.length = sizeof plain2;
dns_name_fromregion(&name2, &region);
dns_name_init(&name3, NULL);
region.base = plain3;
region.length = sizeof plain3;
dns_name_fromregion(&name3, &region);
test(DNS_COMPRESS_NONE, &name1, &name2, &name3, plain, sizeof plain);
test(DNS_COMPRESS_GLOBAL14, &name1, &name2, &name3, plain,
sizeof plain);
test(DNS_COMPRESS_GLOBAL, &name1, &name2, &name3, plain, sizeof plain);
test(DNS_COMPRESS_LOCAL, &name1, &name2, &name3, plain, sizeof plain);
test(DNS_COMPRESS_ALL, &name1, &name2, &name3, plain, sizeof plain);
dns_name_init(&name1, NULL);
region.base = bit1;
region.length = sizeof bit1;
dns_name_fromregion(&name1, &region);
dns_name_init(&name2, NULL);
region.base = bit2;
region.length = sizeof bit2;
dns_name_fromregion(&name2, &region);
dns_name_init(&name3, NULL);
region.base = bit3;
region.length = sizeof bit3;
dns_name_fromregion(&name3, &region);
test(DNS_COMPRESS_NONE, &name1, &name2, &name3, bit, sizeof bit);
test(DNS_COMPRESS_GLOBAL14, &name1, &name2, &name3, bit, sizeof bit);
test(DNS_COMPRESS_GLOBAL, &name1, &name2, &name3, bit, sizeof bit);
test(DNS_COMPRESS_LOCAL, &name1, &name2, &name3, bit, sizeof bit);
test(DNS_COMPRESS_ALL, &name1, &name2, &name3, bit, sizeof bit);
exit(0);
}
void
test(unsigned int allowed, dns_name_t *name1, dns_name_t *name2,
dns_name_t *name3, unsigned char *result, unsigned int length)
{
isc_mem_t *mctx = NULL;
dns_compress_t cctx;
dns_decompress_t dctx;
isc_buffer_t source;
isc_buffer_t target;
dns_name_t name;
unsigned char buf1[1024];
unsigned char buf2[1024];
RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
isc_buffer_init(&source, buf1, sizeof buf1, ISC_BUFFERTYPE_BINARY);
RUNTIME_CHECK(dns_compress_init(&cctx, -1, mctx) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_name_towire(name1, &cctx, &source) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_compress_localinit(&cctx, name1, &source) ==
DNS_R_SUCCESS);
dns_compress_setmethods(&cctx, allowed);
RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_name_towire(name3, &cctx, &source) == DNS_R_SUCCESS);
dns_compress_localinvalidate(&cctx);
dns_compress_invalidate(&cctx);
if (raw) {
unsigned int i;
for (i = 0 ; i < source.used ; /* */ ) {
fprintf(stdout, "%02x",
((unsigned char *)source.base)[i]);
if ((++i % 20) == 0)
fputs("\n", stdout);
else
if (i == source.used)
fputs("\n", stdout);
else
fputs(" ", stdout);
}
}
isc_buffer_setactive(&source, source.used);
isc_buffer_init(&target, buf2, sizeof buf2, ISC_BUFFERTYPE_BINARY);
dns_decompress_init(&dctx, -1, ISC_TRUE);
dns_name_init(&name, NULL);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
&target) == DNS_R_SUCCESS);
dns_decompress_setmethods(&dctx, allowed);
dns_decompress_localinit(&dctx, &name, &source);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
&target) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
&target) == DNS_R_SUCCESS);
RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
&target) == DNS_R_SUCCESS);
dns_decompress_localinvalidate(&dctx);
dns_decompress_invalidate(&dctx);
if (raw) {
unsigned int i;
for (i = 0 ; i < target.used ; /* */ ) {
fprintf(stdout, "%02x",
((unsigned char *)target.base)[i]);
if ((++i % 20) == 0)
fputs("\n", stdout);
else
if (i == target.used)
fputs("\n", stdout);
else
fputs(" ", stdout);
}
fputs("\n", stdout);
}
RUNTIME_CHECK(target.used == length);
RUNTIME_CHECK(memcmp(target.base, result, target.used) == 0);
isc_mem_destroy(&mctx);
}
......@@ -187,7 +187,6 @@ main(int argc, char *argv[]) {
dns_rdata_init(&rdata);
isc_buffer_init(&dbuf, inbuf, sizeof(inbuf),
ISC_BUFFERTYPE_BINARY);
RUNTIME_CHECK(dns_compress_init(&cctx, -1, mctx) == DNS_R_SUCCESS);
result = dns_rdata_fromtext(&rdata, class, type, lex,
NULL, ISC_FALSE, &dbuf, NULL);
if (result != DNS_R_SUCCESS) {
......@@ -195,7 +194,6 @@ main(int argc, char *argv[]) {
"dns_rdata_fromtext returned %s(%d)\n",
dns_result_totext(result), result);
fflush(stdout);
dns_compress_invalidate(&cctx);
continue;
}
if (raw) {
......@@ -214,14 +212,21 @@ main(int argc, char *argv[]) {
/* Convert to wire and back? */
if (wire) {
result = dns_compress_init(&cctx, -1, mctx);
if (result != DNS_R_SUCCESS) {
fprintf(stdout,
"dns_compress_init returned %s(%d)\n",
dns_result_totext(result), result);
continue;
}
isc_buffer_init(&wbuf, wirebuf, sizeof(wirebuf),
ISC_BUFFERTYPE_BINARY);
result = dns_rdata_towire(&rdata, &cctx, &wbuf);
dns_compress_invalidate(&cctx);
if (result != DNS_R_SUCCESS) {
fprintf(stdout,
"dns_rdata_towire returned %s(%d)\n",
dns_result_totext(result), result);
dns_compress_invalidate(&cctx);
continue;
}
len = wbuf.used - wbuf.current;
......@@ -253,14 +258,15 @@ main(int argc, char *argv[]) {
dns_rdata_init(&rdata);
isc_buffer_init(&dbuf, inbuf, sizeof(inbuf),
ISC_BUFFERTYPE_BINARY);
dns_decompress_init(&dctx, -1, ISC_FALSE);
result = dns_rdata_fromwire(&rdata, class, type, &wbuf,
&dctx, ISC_FALSE, &dbuf);
dns_decompress_invalidate(&dctx);
if (result != DNS_R_SUCCESS) {
fprintf(stdout,
fprintf(stdout,
"dns_rdata_fromwire returned %s(%d)\n",
dns_result_totext(result), result);
fflush(stdout);
dns_compress_invalidate(&cctx);
continue;
}
}
......@@ -289,7 +295,6 @@ main(int argc, char *argv[]) {
fprintf(stdout, "\"%.*s\"\n",
(int)tbuf.used, (char*)tbuf.base);
fflush(stdout);
dns_compress_invalidate(&cctx);
if (lasttype == type) {
fprintf(stdout, "dns_rdata_compare = %d\n",
dns_rdata_compare(&rdata, &last));
......
......@@ -125,6 +125,10 @@ getname(dns_name_t *name, isc_buffer_t *source, isc_buffer_t *target) {
dns_name_init(name, NULL);
current = source->current;
if (dns_decompress_edns(&dctx) > 1 || !dns_decompress_strict(&dctx))
dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL);
else
dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
result = dns_name_fromwire(name, source, &dctx, ISC_FALSE, target);
#ifdef NOISY
......@@ -259,9 +263,11 @@ getsection(isc_buffer_t *source, dns_namelist_t *section, unsigned int count,
exit(1);
}
rdata = &rdatas[rdcount++];
dns_decompress_localinit(&dctx, name, source);
result = dns_rdata_fromwire(rdata, class, type,
source, &dctx, ISC_FALSE,
target);
dns_decompress_localinvalidate(&dctx);
if (result != DNS_R_SUCCESS) {
printf("%s\n", dns_result_totext(result));
exit(1);
......@@ -306,10 +312,12 @@ getmessage(dns_message_t *message, isc_buffer_t *source,
message->aucount = getshort(source);
message->adcount = getshort(source);
dns_decompress_init(&dctx, -1, ISC_FALSE);
getquestions(source, &message->question, message->qcount, target);
getsection(source, &message->answer, message->ancount, target);
getsection(source, &message->authority, message->aucount, target);
getsection(source, &message->additional, message->adcount, target);
dns_decompress_invalidate(&dctx);
isc_buffer_remaining(source, &r);
if (r.length != 0)
......@@ -558,13 +566,10 @@ main(int argc, char *argv[]) {
rlcount = 0;
ncount = 0;
dctx.allowed = DNS_COMPRESS_GLOBAL14;
dns_name_init(&dctx.owner_name, NULL);
isc_buffer_init(&source, b, sizeof b, ISC_BUFFERTYPE_BINARY);
isc_buffer_add(&source, bp - b);
isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_BINARY);
getmessage(&message, &source, &target);
result = printmessage(&message);
if (result != DNS_R_SUCCESS)
......
Name Decompression
$Id: decompression,v 1.2 1999/02/24 00:57:57 marka Exp $
$Id: decompression,v 1.3 1999/02/24 06:31:31 marka Exp $
Overview.
......@@ -49,13 +49,13 @@ Types:
Functions:
dns_result_t
void
dns_decompress_init(dns_decompress_t *dctx, int edns,
isc_boolean_t strict, isc_mctx_t *mctx);
isc_boolean_t strict);
initalise dctx
dctx->ownername is invalidated
dns_result_t
void
dns_decompress_localinit(dns_decompress_t *dctx, dns_name_t *name,
isc_buffer_t *source);
initalise dctx->ownername
......
......@@ -218,6 +218,16 @@ fromwire_<I>classname_typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
isc_buffer_t *source, dns_decompress_t *dctx,
isc_boolean_t downcase, isc_buffer_t *target);</CODE>
</PRE>
<P>
<CODE>fromwire_<I>classname_typename</I>()</CODE> is required to set the valid
decompression methods if there is a domain name in the rdata.
<PRE>
<CODE>if (dns_decompress_edns(dctx) >= # || !dns_decompress_strict(dctx))
dns_decompress_setmethods(dctx, DNS_COMPRESS_ALL);
else
dns_decompress_setmethods(dctx, DNS_COMPRESS_LOCAL);</CODE>
</PRE>
<DL>
<DT><CODE>class</CODE></DT>
<DD>
......
......@@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: compress.c,v 1.2 1999/02/23 02:25:39 marka Exp $ */
/* $Id: compress.c,v 1.3 1999/02/24 06:31:31 marka Exp $ */
#include <config.h>
......@@ -25,9 +25,12 @@
#include <dns/compress.h>
#define CCTX_MAGIC 0x43435458U
#define CCTX_MAGIC 0x43435458U /* CCTX */
#define VALID_CCTX(x) ((x) != NULL && (x)->magic == CCTX_MAGIC)
#define DCTX_MAGIC 0x44435458U /* DCTX */
#define VALID_DCTX(x) ((x) != NULL && (x)->magic == DCTX_MAGIC)
static void free_offset(void *offset, void *mctx);
isc_boolean_t compress_find(dns_rbt_t *root, dns_name_t *name,
dns_name_t *prefix, dns_name_t *suffix,
......@@ -37,6 +40,9 @@ void compress_add(dns_rbt_t *root, dns_name_t *prefix,
dns_name_t *suffix, isc_uint16_t offset,
isc_boolean_t global16, isc_mem_t *mctx);
/***
*** Compression
***/
dns_result_t
dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx)
......@@ -82,7 +88,7 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner,
REQUIRE(VALID_CCTX(cctx));
REQUIRE(cctx->local == NULL);
REQUIRE(dns_name_isabsolute(owner) == ISC_TRUE);
REQUIRE(target != NULL);
REQUIRE(isc_buffer_type(target) == ISC_BUFFERTYPE_BINARY);
result = dns_rbt_create(cctx->mctx, free_offset, cctx->mctx,
&cctx->local);
......@@ -107,7 +113,7 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner,
while (labels > 0) {
dns_name_getlabelsequence(owner, wl, labels, &name);
data = isc_mem_get(cctx->mctx, sizeof *data);
if (data != NULL)
if (data == NULL)
return (DNS_R_SUCCESS);
*data = ll;
result = dns_rbt_addname(cctx->local, &name, data);
......@@ -143,7 +149,7 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner,
if (result != DNS_R_SUCCESS)
return (DNS_R_SUCCESS);
data = isc_mem_get(cctx->mctx, sizeof *data);
if (data != NULL)
if (data == NULL)
return (DNS_R_SUCCESS);
*data = ll;
result = dns_rbt_addname(cctx->local, &name, data);
......@@ -259,6 +265,85 @@ dns_compress_backout(dns_compress_t *cctx, isc_uint16_t offset) {
}
/***
*** Decompression
***/
void
dns_decompress_init(dns_decompress_t *dctx, int edns, isc_boolean_t strict) {
REQUIRE(dctx != NULL);
REQUIRE(edns >= -1 && edns <= 255);
dctx->allowed = DNS_COMPRESS_NONE;
dctx->edns = edns;
dctx->strict = strict;
dctx->rdata = 0;
dns_name_init(&dctx->owner_name, NULL);
dns_name_invalidate(&dctx->owner_name);
dctx->magic = DCTX_MAGIC;
}
void
dns_decompress_localinit(dns_decompress_t *dctx, dns_name_t *name,
isc_buffer_t *source)
{
REQUIRE(VALID_DCTX(dctx));
REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
REQUIRE(isc_buffer_type(source) == ISC_BUFFERTYPE_BINARY);
dctx->rdata = source->current;
dctx->owner_name = *name;
}
void
dns_decompress_invalidate(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
dctx->magic = 0;
}
void
dns_decompress_localinvalidate(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
dns_name_invalidate(&dctx->owner_name);
}
void
dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
REQUIRE(VALID_DCTX(dctx));
dctx->allowed = allowed;
}
unsigned int
dns_decompress_getmethods(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
return (dctx->allowed);
}
int
dns_decompress_edns(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
return (dctx->edns);
}
isc_boolean_t
dns_decompress_strict(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
return (dctx->strict);
}
/***
*** Private
***/
......
......@@ -48,8 +48,12 @@ struct dns_compress {
};
struct dns_decompress {
unsigned int allowed; /* Allowed methods. */
dns_name_t owner_name; /* For local compression. */
unsigned int magic; /* Magic number. */
unsigned int allowed; /* Allowed methods. */
unsigned int rdata; /* Start of local rdata. */
int edns; /* Edns version or -1. */
isc_boolean_t strict; /* Strict checking */
dns_name_t owner_name; /* For local compression. */
};
dns_result_t dns_compress_init(dns_compress_t *cctx, int edns,
......@@ -220,4 +224,29 @@ dns_compress_backout(dns_compress_t *cctx, isc_uint16_t offset);
* 'cctx' is initalised.
*/
void
dns_decompress_init(dns_decompress_t *dctx, int edns, isc_boolean_t strict);
void
dns_decompress_localinit(dns_decompress_t *dctx, dns_name_t *name,
isc_buffer_t *source);
void
dns_decompress_invalidate(dns_decompress_t *dctx);
void
dns_decompress_localinvalidate(dns_decompress_t *dctx);
void
dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed);
unsigned int
dns_decompress_getmethods(dns_decompress_t *dctx);
int
dns_decompress_edns(dns_decompress_t *dctx);
isc_boolean_t
dns_decompress_strict(dns_decompress_t *dctx);
#endif /* DNS_COMPRESS_H */
......@@ -1670,13 +1670,18 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
isc_buffer_t *target)
{
unsigned char *cdata, *ndata;
unsigned int cused, hops, nrem, nused, labels, n;
unsigned int current, new_current, biggest_pointer;
isc_boolean_t saw_bitstring, done;
unsigned int cused, hops, nrem, nused, labels, n, i, ll;
unsigned int current, new_current, biggest_pointer, lcount;
isc_boolean_t saw_bitstring, done, local;
fw_state state = fw_start;
unsigned int c;
unsigned char *offsets;
dns_offsets_t odata;
dns_name_t suffix;
dns_label_t label;
dns_labeltype_t labeltype;
unsigned int bits;
dns_bitlabel_t bit;
/*
* Copy the possibly-compressed name at source into target,
......@@ -1711,6 +1716,7 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
*/
labels = 0;
hops = 0;
local = ISC_FALSE;
saw_bitstring = ISC_FALSE;
done = ISC_FALSE;
ndata = (unsigned char *)target->base + target->used;
......@@ -1747,6 +1753,17 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
done = ISC_TRUE;
n = c;
state = fw_ordinary;