vendor/BIND: Update to 9.5.2-P3
[dragonfly.git] / contrib / bind / lib / dns / compress.c
blob11473ee95f8beed805c3d84c14d66cabe4ce2cb5
1 /*
2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: compress.c,v 1.59 2007/06/19 23:47:16 tbox Exp $ */
20 /*! \file */
22 #define DNS_NAME_USEINLINE 1
24 #include <config.h>
26 #include <isc/mem.h>
27 #include <isc/string.h>
28 #include <isc/util.h>
30 #include <dns/compress.h>
31 #include <dns/fixedname.h>
32 #include <dns/rbt.h>
33 #include <dns/result.h>
35 #define CCTX_MAGIC ISC_MAGIC('C', 'C', 'T', 'X')
36 #define VALID_CCTX(x) ISC_MAGIC_VALID(x, CCTX_MAGIC)
38 #define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X')
39 #define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
41 /***
42 *** Compression
43 ***/
45 isc_result_t
46 dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
47 unsigned int i;
49 REQUIRE(cctx != NULL);
50 REQUIRE(mctx != NULL); /* See: rdataset.c:towiresorted(). */
52 cctx->allowed = 0;
53 cctx->edns = edns;
54 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++)
55 cctx->table[i] = NULL;
56 cctx->mctx = mctx;
57 cctx->count = 0;
58 cctx->magic = CCTX_MAGIC;
59 return (ISC_R_SUCCESS);
62 void
63 dns_compress_invalidate(dns_compress_t *cctx) {
64 dns_compressnode_t *node;
65 unsigned int i;
67 REQUIRE(VALID_CCTX(cctx));
69 cctx->magic = 0;
70 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
71 while (cctx->table[i] != NULL) {
72 node = cctx->table[i];
73 cctx->table[i] = cctx->table[i]->next;
74 if (node->count < DNS_COMPRESS_INITIALNODES)
75 continue;
76 isc_mem_put(cctx->mctx, node, sizeof(*node));
79 cctx->allowed = 0;
80 cctx->edns = -1;
83 void
84 dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed) {
85 REQUIRE(VALID_CCTX(cctx));
87 cctx->allowed &= ~DNS_COMPRESS_ALL;
88 cctx->allowed |= (allowed & DNS_COMPRESS_ALL);
91 unsigned int
92 dns_compress_getmethods(dns_compress_t *cctx) {
93 REQUIRE(VALID_CCTX(cctx));
94 return (cctx->allowed & DNS_COMPRESS_ALL);
97 void
98 dns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive) {
99 REQUIRE(VALID_CCTX(cctx));
101 if (sensitive)
102 cctx->allowed |= DNS_COMPRESS_CASESENSITIVE;
103 else
104 cctx->allowed &= ~DNS_COMPRESS_CASESENSITIVE;
107 isc_boolean_t
108 dns_compress_getsensitive(dns_compress_t *cctx) {
109 REQUIRE(VALID_CCTX(cctx));
111 return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0));
115 dns_compress_getedns(dns_compress_t *cctx) {
116 REQUIRE(VALID_CCTX(cctx));
117 return (cctx->edns);
120 #define NODENAME(node, name) \
121 do { \
122 (name)->length = (node)->r.length; \
123 (name)->labels = (node)->labels; \
124 (name)->ndata = (node)->r.base; \
125 (name)->attributes = DNS_NAMEATTR_ABSOLUTE; \
126 } while (0)
129 * Find the longest match of name in the table.
130 * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
131 * If no match is found return ISC_FALSE.
133 isc_boolean_t
134 dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
135 dns_name_t *prefix, isc_uint16_t *offset)
137 dns_name_t tname, nname;
138 dns_compressnode_t *node = NULL;
139 unsigned int labels, hash, n;
141 REQUIRE(VALID_CCTX(cctx));
142 REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
143 REQUIRE(offset != NULL);
145 if (cctx->count == 0)
146 return (ISC_FALSE);
148 labels = dns_name_countlabels(name);
149 INSIST(labels > 0);
151 dns_name_init(&tname, NULL);
152 dns_name_init(&nname, NULL);
154 for (n = 0; n < labels - 1; n++) {
155 dns_name_getlabelsequence(name, n, labels - n, &tname);
156 hash = dns_name_hash(&tname, ISC_FALSE) %
157 DNS_COMPRESS_TABLESIZE;
158 for (node = cctx->table[hash]; node != NULL; node = node->next)
160 NODENAME(node, &nname);
161 if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
162 if (dns_name_caseequal(&nname, &tname))
163 break;
164 } else {
165 if (dns_name_equal(&nname, &tname))
166 break;
169 if (node != NULL)
170 break;
174 * If node == NULL, we found no match at all.
176 if (node == NULL)
177 return (ISC_FALSE);
179 if (n == 0)
180 dns_name_reset(prefix);
181 else
182 dns_name_getlabelsequence(name, 0, n, prefix);
184 *offset = node->offset;
185 return (ISC_TRUE);
188 static inline unsigned int
189 name_length(const dns_name_t *name) {
190 isc_region_t r;
191 dns_name_toregion(name, &r);
192 return (r.length);
195 void
196 dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
197 const dns_name_t *prefix, isc_uint16_t offset)
199 dns_name_t tname;
200 unsigned int start;
201 unsigned int n;
202 unsigned int count;
203 unsigned int hash;
204 dns_compressnode_t *node;
205 unsigned int length;
206 unsigned int tlength;
207 isc_uint16_t toffset;
209 REQUIRE(VALID_CCTX(cctx));
210 REQUIRE(dns_name_isabsolute(name));
212 dns_name_init(&tname, NULL);
214 n = dns_name_countlabels(name);
215 count = dns_name_countlabels(prefix);
216 if (dns_name_isabsolute(prefix))
217 count--;
218 start = 0;
219 length = name_length(name);
220 while (count > 0) {
221 if (offset >= 0x4000)
222 break;
223 dns_name_getlabelsequence(name, start, n, &tname);
224 hash = dns_name_hash(&tname, ISC_FALSE) %
225 DNS_COMPRESS_TABLESIZE;
226 tlength = name_length(&tname);
227 toffset = (isc_uint16_t)(offset + (length - tlength));
229 * Create a new node and add it.
231 if (cctx->count < DNS_COMPRESS_INITIALNODES)
232 node = &cctx->initialnodes[cctx->count];
233 else {
234 node = isc_mem_get(cctx->mctx,
235 sizeof(dns_compressnode_t));
236 if (node == NULL)
237 return;
239 node->count = cctx->count++;
240 node->offset = toffset;
241 dns_name_toregion(&tname, &node->r);
242 node->labels = (isc_uint8_t)dns_name_countlabels(&tname);
243 node->next = cctx->table[hash];
244 cctx->table[hash] = node;
245 start++;
246 n--;
247 count--;
251 void
252 dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
253 unsigned int i;
254 dns_compressnode_t *node;
256 REQUIRE(VALID_CCTX(cctx));
258 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
259 node = cctx->table[i];
261 * This relies on nodes with greater offsets being
262 * closer to the beginning of the list, and the
263 * items with the greatest offsets being at the end
264 * of the initialnodes[] array.
266 while (node != NULL && node->offset >= offset) {
267 cctx->table[i] = node->next;
268 if (node->count >= DNS_COMPRESS_INITIALNODES)
269 isc_mem_put(cctx->mctx, node, sizeof(*node));
270 cctx->count--;
271 node = cctx->table[i];
276 /***
277 *** Decompression
278 ***/
280 void
281 dns_decompress_init(dns_decompress_t *dctx, int edns,
282 dns_decompresstype_t type) {
284 REQUIRE(dctx != NULL);
285 REQUIRE(edns >= -1 && edns <= 255);
287 dctx->allowed = DNS_COMPRESS_NONE;
288 dctx->edns = edns;
289 dctx->type = type;
290 dctx->magic = DCTX_MAGIC;
293 void
294 dns_decompress_invalidate(dns_decompress_t *dctx) {
296 REQUIRE(VALID_DCTX(dctx));
298 dctx->magic = 0;
301 void
302 dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
304 REQUIRE(VALID_DCTX(dctx));
306 switch (dctx->type) {
307 case DNS_DECOMPRESS_ANY:
308 dctx->allowed = DNS_COMPRESS_ALL;
309 break;
310 case DNS_DECOMPRESS_NONE:
311 dctx->allowed = DNS_COMPRESS_NONE;
312 break;
313 case DNS_DECOMPRESS_STRICT:
314 dctx->allowed = allowed;
315 break;
319 unsigned int
320 dns_decompress_getmethods(dns_decompress_t *dctx) {
322 REQUIRE(VALID_DCTX(dctx));
324 return (dctx->allowed);
328 dns_decompress_edns(dns_decompress_t *dctx) {
330 REQUIRE(VALID_DCTX(dctx));
332 return (dctx->edns);
335 dns_decompresstype_t
336 dns_decompress_type(dns_decompress_t *dctx) {
338 REQUIRE(VALID_DCTX(dctx));
340 return (dctx->type);