compress.c revision 1d6572f9d4766a7329e2d207b9f7af50092663ae
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 1999 Internet Software Consortium.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Permission to use, copy, modify, and distribute this software for any
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * purpose with or without fee is hereby granted, provided that the above
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15a44745412679c30a6d022733925af70a38b715David Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15a44745412679c30a6d022733925af70a38b715David Lawrence * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15a44745412679c30a6d022733925af70a38b715David Lawrence * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
dcc7ea97174501f0409c0c919b3ca04083e4e1b8Andreas Gustafsson /* $Id: compress.c,v 1.14 1999/04/28 03:16:50 marka Exp $ */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#define VALID_CCTX(x) ((x) != NULL && (x)->magic == CCTX_MAGIC)
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington#define VALID_DCTX(x) ((x) != NULL && (x)->magic == DCTX_MAGIC)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void free_offset(void *offset, void *mctx);
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrenceisc_boolean_t compress_find(dns_rbt_t *root, dns_name_t *name,
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrencevoid compress_add(dns_rbt_t *root, dns_name_t *prefix,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff *** Compression
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graffdns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx)
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff cctx->global16 = (edns >= 1) ? ISC_TRUE : ISC_FALSE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews result = dns_rbt_create(mctx, free_offset, mctx, &cctx->global);
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graffdns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner,
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff unsigned int labels;
ca9739800f045cd4d39014f98b920d4354b5bd14Michael Graff unsigned int ll; /* logical label length w/o root label */
19d1b1667d073850d4366352aaf8319efc5debeeBrian Wellington unsigned int bits;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(dns_name_isabsolute(owner) == ISC_TRUE);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews REQUIRE(isc_buffer_type(target) == ISC_BUFFERTYPE_BINARY);
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson result = dns_rbt_create(cctx->mctx, free_offset, cctx->mctx,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Errors from here on are not passed back up.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews cctx->rdata = target->used; /* XXX layer violation */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews if (labels <= 1) /* can't compress root label */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ll = 0; /* logical label index 0 == TLD not root */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Work from the TLD label to the least signfiant label.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_name_getlabelsequence(owner, labels - wl, wl, &name);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * If it is not a bit string label add to tree.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (dns_label_type(&label) != dns_labeltype_bitstring) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews "dns_rbt_addname(local, \"%.*s\", %d)\n",
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_rbt_addname(cctx->local, &name, data);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Have to compute logical for bit string labels.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* XXX MPA need to test once rbt supports bit labels fully */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_name_getlabelsequence(owner, 1, wl - 1, &suffix);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * It is easier to do this the reverse way.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * Adding 'bits' to 'll' may exceed the maximum logical
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * offset index. Throw away bits until ll <= 254.
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews /* clear bit */
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * Add entries to tree.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_name_concatenate(&prefix, &suffix, &name,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews "dns_rbt_addname(local, \"%.*s\", %d)\n",
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews result = dns_rbt_addname(cctx->local, &name, data);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* clear bit */
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington buf[2 + bits / 8] &= ~(1 << (7 - (bits % 8)));
8b61d2012063306528286680bd9f086fa868d86eMark Andrews } while (bits > 0);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellingtondns_compress_invalidate(dns_compress_t *cctx) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_compress_localinvalidate(dns_compress_t *cctx) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsdns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (cctx->edns >= 1 && (allowed & DNS_COMPRESS_GLOBAL14) != 0)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews fprintf(stdout, "compress_find(global, name \"%.*s\", ...)\n",
8b61d2012063306528286680bd9f086fa868d86eMark Andrews return (compress_find(cctx->global, name, prefix, suffix, offset,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_compress_findlocal(dns_compress_t *cctx, dns_name_t *name,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews fprintf(stdout, "compress_find(local, name \"%.*s\", ...)\n",
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews return (compress_find(cctx->local, name, prefix, suffix, offset,
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_compress_add(dns_compress_t *cctx, dns_name_t *prefix,
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington if (cctx->local != NULL && (cctx->allowed & DNS_COMPRESS_LOCAL) != 0) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews compress_add(cctx->local, prefix, suffix, localoffset, ISC_TRUE,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews fprintf(stdout, "compress_add(global, ...)\n");
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews compress_add(cctx->global, prefix, suffix, offset,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsdns_compress_backout(dns_compress_t *cctx, isc_uint16_t offset) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* XXX MPA need tree walking code */
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews /* Remove all nodes in cctx->global that have *data >= offset. */
8b61d2012063306528286680bd9f086fa868d86eMark Andrews *** Decompression
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_decompress_init(dns_decompress_t *dctx, int edns, isc_boolean_t strict) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrewsdns_decompress_localinit(dns_decompress_t *dctx, dns_name_t *name,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(isc_buffer_type(source) == ISC_BUFFERTYPE_BINARY);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_decompress_invalidate(dns_decompress_t *dctx) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_decompress_localinvalidate(dns_decompress_t *dctx) {
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellingtondns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsdns_decompress_getmethods(dns_decompress_t *dctx) {
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington isc_mem_put(mctx, offset, sizeof(isc_uint16_t));
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * Add the labels in prefix to RBT.
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellingtoncompress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix,
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington isc_uint16_t offset, isc_boolean_t global16, isc_mem_t *mctx)
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson limit = dns_name_isabsolute(prefix) ? 1 : 0;
ac6afcd0caf72aaa2a537e0003de30b363b4a68bBrian Wellington dns_name_getlabelsequence(prefix, start, count, &name);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington isc_buffer_init(&target, buffer, sizeof buffer,
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington result = dns_name_concatenate(&name, suffix, &full, &target);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews "dns_rbt_addname(root, \"%.*s\", %d)\n",
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Find the loggest match of name in root.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * If match is found return ISC_TRUE. prefix, suffix and offset
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * are updated.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * If no match is found return ISC_FALSE.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewscompress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int namebits;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int bits;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned int j;
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews unsigned char buf[2 + 256/8]; /* size of biggest bit label */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = dns_rbt_findname(root, name, foundname, (void *)&data);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (result != DNS_R_SUCCESS && result != DNS_R_PARTIALMATCH)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Do we have to do bit string processing?
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews INSIST(foundlabels > 1); /* root labels are not added to tree */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (dns_label_type(&foundlabel) == dns_labeltype_bitstring) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_getlabel(name, namelabels - foundlabels, &namelabel);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews INSIST(dns_label_type(&namelabel) == dns_labeltype_bitstring);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_getlabelsequence(name, 0, prefixlen, prefix);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_getlabelsequence(foundname, 0, foundlabels, suffix);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews /* XXX MPA needs to be tested */
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * At this stage we have a bit string label to split in two.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * There is potentially a prefix before this label and definitly
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * a suffix after it (if only the root).
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_getlabelsequence(foundname, 0, foundlabels, suffix);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews dns_name_getlabelsequence(name, 0, prefixlen, &tmpprefix);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews * Copy least significant bits.
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews while (j < bits) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews bit = dns_label_getbit(&namelabel, foundbits + j);