compress.c revision 5e93bad21b6d68fce862ff8aace3bb29b658f4f6
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt/*
45c5f403619029a363cf089e0a4b1bb44425dd84Tinderbox User * Copyright (C) 2004-2007, 2015 Internet Systems Consortium, Inc. ("ISC")
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * Copyright (C) 1999-2001 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * copyright notice and this permission notice appear in all copies.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt *
2f4561bc9cd5e5cdc58e29e600303c812f6902eeAutomatic Updater * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * PERFORMANCE OF THIS SOFTWARE.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt/* $Id$ */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
99f6179191e583d23f3c5567d3c00b57b64eb52dEvan Hunt/*! \file */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define DNS_NAME_USEINLINE 1
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <config.h>
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <isc/mem.h>
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <isc/string.h>
39f2d1a96a7c7494b1db0ea0f45e063a6a5ef9bbEvan Hunt#include <isc/util.h>
99f6179191e583d23f3c5567d3c00b57b64eb52dEvan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <dns/compress.h>
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <dns/fixedname.h>
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <dns/rbt.h>
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt#include <dns/result.h>
4eb998928b9aef0ceda42d7529980d658138698aEvan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define CCTX_MAGIC ISC_MAGIC('C', 'C', 'T', 'X')
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define VALID_CCTX(x) ISC_MAGIC_VALID(x, CCTX_MAGIC)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt#define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X')
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt/***
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt *** Compression
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt ***/
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntisc_result_t
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt unsigned int i;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(cctx != NULL);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(mctx != NULL); /* See: rdataset.c:towiresorted(). */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt cctx->allowed = 0;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt cctx->edns = edns;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++)
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt cctx->table[i] = NULL;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt cctx->mctx = mctx;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt cctx->count = 0;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->magic = CCTX_MAGIC;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt return (ISC_R_SUCCESS);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Huntvoid
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_invalidate(dns_compress_t *cctx) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt dns_compressnode_t *node;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt unsigned int i;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->magic = 0;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt while (cctx->table[i] != NULL) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt node = cctx->table[i];
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->table[i] = cctx->table[i]->next;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt if ((node->offset & 0x8000) != 0)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt isc_mem_put(cctx->mctx, node->r.base,
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt node->r.length);
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt if (node->count < DNS_COMPRESS_INITIALNODES)
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt continue;
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt isc_mem_put(cctx->mctx, node, sizeof(*node));
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt }
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt }
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt cctx->allowed = 0;
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt cctx->edns = -1;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntvoid
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed) {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->allowed &= ~DNS_COMPRESS_ALL;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->allowed |= (allowed & DNS_COMPRESS_ALL);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntunsigned int
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Huntdns_compress_getmethods(dns_compress_t *cctx) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt return (cctx->allowed & DNS_COMPRESS_ALL);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntvoid
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive) {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt if (sensitive)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->allowed |= DNS_COMPRESS_CASESENSITIVE;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt else
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt cctx->allowed &= ~DNS_COMPRESS_CASESENSITIVE;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntisc_boolean_t
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_getsensitive(dns_compress_t *cctx) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntint
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_getedns(dns_compress_t *cctx) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt REQUIRE(VALID_CCTX(cctx));
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt return (cctx->edns);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt}
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt#define NODENAME(node, name) \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdo { \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt (name)->length = (node)->r.length; \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt (name)->labels = (node)->labels; \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt (name)->ndata = (node)->r.base; \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt (name)->attributes = DNS_NAMEATTR_ABSOLUTE; \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt} while (0)
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt/*
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * Find the longest match of name in the table.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * If no match is found return ISC_FALSE.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntisc_boolean_t
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Huntdns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt dns_name_t *prefix, isc_uint16_t *offset)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt{
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt dns_name_t tname, nname;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt dns_compressnode_t *node = NULL;
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt unsigned int labels, hash, n;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt REQUIRE(VALID_CCTX(cctx));
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt REQUIRE(offset != NULL);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt if (cctx->count == 0)
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt return (ISC_FALSE);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt labels = dns_name_countlabels(name);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt INSIST(labels > 0);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt dns_name_init(&tname, NULL);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt dns_name_init(&nname, NULL);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt for (n = 0; n < labels - 1; n++) {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt dns_name_getlabelsequence(name, n, labels - n, &tname);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt hash = dns_name_hash(&tname, ISC_FALSE) %
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt DNS_COMPRESS_TABLESIZE;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt for (node = cctx->table[hash]; node != NULL; node = node->next)
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt NODENAME(node, &nname);
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt if (dns_name_caseequal(&nname, &tname))
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt break;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt } else {
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews if (dns_name_equal(&nname, &tname))
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews break;
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews }
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews }
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews if (node != NULL)
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews break;
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews }
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt /*
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt * If node == NULL, we found no match at all.
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt */
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt if (node == NULL)
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt return (ISC_FALSE);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt if (n == 0)
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt dns_name_reset(prefix);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt else
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt dns_name_getlabelsequence(name, 0, n, prefix);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt *offset = (node->offset & 0x7fff);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt return (ISC_TRUE);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt}
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntstatic inline unsigned int
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntname_length(const dns_name_t *name) {
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_region_t r;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt dns_name_toregion(name, &r);
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt return (r.length);
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt}
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntvoid
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntdns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt const dns_name_t *prefix, isc_uint16_t offset)
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt{
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt dns_name_t tname, xname;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int start;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int n;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int count;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int hash;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt dns_compressnode_t *node;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int length;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int tlength;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_uint16_t toffset;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned char *tmp;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_region_t r;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt REQUIRE(VALID_CCTX(cctx));
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt REQUIRE(dns_name_isabsolute(name));
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt if (offset > 0x4000)
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt return;
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt dns_name_init(&tname, NULL);
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt dns_name_init(&xname, NULL);
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt n = dns_name_countlabels(name);
319b8a14881a95996af3a9ba4a20f144eb766b31Evan Hunt count = dns_name_countlabels(prefix);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt if (dns_name_isabsolute(prefix))
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt count--;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt if (count == 0)
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt return;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt start = 0;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt dns_name_toregion(name, &r);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt length = r.length;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt tmp = isc_mem_get(cctx->mctx, length);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt if (tmp == NULL)
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt return;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt memmove(tmp, r.base, r.length);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt r.base = tmp;
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt dns_name_fromregion(&xname, &r);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews while (count > 0) {
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews if (offset >= 0x4000)
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews break;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews dns_name_getlabelsequence(&xname, start, n, &tname);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews hash = dns_name_hash(&tname, ISC_FALSE) %
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews DNS_COMPRESS_TABLESIZE;
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews tlength = name_length(&tname);
e939674d53a127ddeeaf4b41fd72933f0b493308Mark Andrews toffset = (isc_uint16_t)(offset + (length - tlength));
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews /*
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews * Create a new node and add it.
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews */
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews if (cctx->count < DNS_COMPRESS_INITIALNODES)
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews node = &cctx->initialnodes[cctx->count];
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews else {
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews node = isc_mem_get(cctx->mctx,
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews sizeof(dns_compressnode_t));
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews if (node == NULL) {
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews if (start == 0)
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews isc_mem_put(cctx->mctx,
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews r.base, r.length);
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews return;
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews }
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews }
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews node->count = cctx->count++;
677f507de7c546c187c1505c48bc7b440545485cMark Andrews if (start == 0)
677f507de7c546c187c1505c48bc7b440545485cMark Andrews toffset |= 0x8000;
677f507de7c546c187c1505c48bc7b440545485cMark Andrews node->offset = toffset;
677f507de7c546c187c1505c48bc7b440545485cMark Andrews dns_name_toregion(&tname, &node->r);
677f507de7c546c187c1505c48bc7b440545485cMark Andrews node->labels = (isc_uint8_t)dns_name_countlabels(&tname);
677f507de7c546c187c1505c48bc7b440545485cMark Andrews node->next = cctx->table[hash];
677f507de7c546c187c1505c48bc7b440545485cMark Andrews cctx->table[hash] = node;
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews start++;
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews n--;
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews count--;
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews }
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews}
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrewsvoid
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntdns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
unsigned int i;
dns_compressnode_t *node;
REQUIRE(VALID_CCTX(cctx));
for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
node = cctx->table[i];
/*
* This relies on nodes with greater offsets being
* closer to the beginning of the list, and the
* items with the greatest offsets being at the end
* of the initialnodes[] array.
*/
while (node != NULL && (node->offset & 0x7fff) >= offset) {
cctx->table[i] = node->next;
if ((node->offset & 0x8000) != 0)
isc_mem_put(cctx->mctx, node->r.base,
node->r.length);
if (node->count >= DNS_COMPRESS_INITIALNODES)
isc_mem_put(cctx->mctx, node, sizeof(*node));
cctx->count--;
node = cctx->table[i];
}
}
}
/***
*** Decompression
***/
void
dns_decompress_init(dns_decompress_t *dctx, int edns,
dns_decompresstype_t type) {
REQUIRE(dctx != NULL);
REQUIRE(edns >= -1 && edns <= 255);
dctx->allowed = DNS_COMPRESS_NONE;
dctx->edns = edns;
dctx->type = type;
dctx->magic = DCTX_MAGIC;
}
void
dns_decompress_invalidate(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
dctx->magic = 0;
}
void
dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
REQUIRE(VALID_DCTX(dctx));
switch (dctx->type) {
case DNS_DECOMPRESS_ANY:
dctx->allowed = DNS_COMPRESS_ALL;
break;
case DNS_DECOMPRESS_NONE:
dctx->allowed = DNS_COMPRESS_NONE;
break;
case DNS_DECOMPRESS_STRICT:
dctx->allowed = allowed;
break;
}
}
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);
}
dns_decompresstype_t
dns_decompress_type(dns_decompress_t *dctx) {
REQUIRE(VALID_DCTX(dctx));
return (dctx->type);
}