Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / name.c
blob638cdc86d00742ab2f4eefe499272f7eeab6f234
1 /*
2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 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: name.c,v 1.163.128.2 2008/03/31 23:46:42 tbox Exp $ */
20 /*! \file */
22 #include <config.h>
24 #include <ctype.h>
25 #include <stdlib.h>
27 #include <isc/buffer.h>
28 #include <isc/hash.h>
29 #include <isc/mem.h>
30 #include <isc/once.h>
31 #include <isc/print.h>
32 #include <isc/string.h>
33 #include <isc/thread.h>
34 #include <isc/util.h>
36 #include <dns/compress.h>
37 #include <dns/name.h>
38 #include <dns/result.h>
40 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
42 typedef enum {
43 ft_init = 0,
44 ft_start,
45 ft_ordinary,
46 ft_initialescape,
47 ft_escape,
48 ft_escdecimal,
49 ft_at
50 } ft_state;
52 typedef enum {
53 fw_start = 0,
54 fw_ordinary,
55 fw_copy,
56 fw_newcurrent
57 } fw_state;
59 static char digitvalue[256] = {
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
63 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
64 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
66 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
78 static unsigned char maptolower[] = {
79 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
80 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
81 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
82 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
83 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
84 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
85 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
86 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
87 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
88 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
89 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
90 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
91 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
92 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
93 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
94 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
95 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
96 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
97 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
98 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
99 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
100 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
101 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
102 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
103 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
104 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
105 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
106 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
107 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
108 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
109 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
110 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
113 #define CONVERTTOASCII(c)
114 #define CONVERTFROMASCII(c)
116 #define INIT_OFFSETS(name, var, default) \
117 if (name->offsets != NULL) \
118 var = name->offsets; \
119 else \
120 var = default;
122 #define SETUP_OFFSETS(name, var, default) \
123 if (name->offsets != NULL) \
124 var = name->offsets; \
125 else { \
126 var = default; \
127 set_offsets(name, var, NULL); \
131 * Note: If additional attributes are added that should not be set for
132 * empty names, MAKE_EMPTY() must be changed so it clears them.
134 #define MAKE_EMPTY(name) \
135 do { \
136 name->ndata = NULL; \
137 name->length = 0; \
138 name->labels = 0; \
139 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
140 } while (0);
143 * A name is "bindable" if it can be set to point to a new value, i.e.
144 * name->ndata and name->length may be changed.
146 #define BINDABLE(name) \
147 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
148 == 0)
151 * Note that the name data must be a char array, not a string
152 * literal, to avoid compiler warnings about discarding
153 * the const attribute of a string.
155 static unsigned char root_ndata[] = { '\0' };
156 static unsigned char root_offsets[] = { 0 };
158 static dns_name_t root =
160 DNS_NAME_MAGIC,
161 root_ndata, 1, 1,
162 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
163 root_offsets, NULL,
164 {(void *)-1, (void *)-1},
165 {NULL, NULL}
168 /* XXXDCL make const? */
169 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
171 static unsigned char wild_ndata[] = { '\001', '*' };
172 static unsigned char wild_offsets[] = { 0 };
174 static dns_name_t wild =
176 DNS_NAME_MAGIC,
177 wild_ndata, 2, 1,
178 DNS_NAMEATTR_READONLY,
179 wild_offsets, NULL,
180 {(void *)-1, (void *)-1},
181 {NULL, NULL}
184 /* XXXDCL make const? */
185 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
187 unsigned int
188 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
191 * dns_name_t to text post-conversion procedure.
193 #ifdef ISC_PLATFORM_USETHREADS
194 static int thread_key_initialized = 0;
195 static isc_mutex_t thread_key_mutex;
196 static isc_mem_t *thread_key_mctx = NULL;
197 static isc_thread_key_t totext_filter_proc_key;
198 static isc_once_t once = ISC_ONCE_INIT;
199 #else
200 static dns_name_totextfilter_t totext_filter_proc = NULL;
201 #endif
203 static void
204 set_offsets(const dns_name_t *name, unsigned char *offsets,
205 dns_name_t *set_name);
207 void
208 dns_name_init(dns_name_t *name, unsigned char *offsets) {
210 * Initialize 'name'.
212 DNS_NAME_INIT(name, offsets);
215 void
216 dns_name_reset(dns_name_t *name) {
217 REQUIRE(VALID_NAME(name));
218 REQUIRE(BINDABLE(name));
220 DNS_NAME_RESET(name);
223 void
224 dns_name_invalidate(dns_name_t *name) {
226 * Make 'name' invalid.
229 REQUIRE(VALID_NAME(name));
231 name->magic = 0;
232 name->ndata = NULL;
233 name->length = 0;
234 name->labels = 0;
235 name->attributes = 0;
236 name->offsets = NULL;
237 name->buffer = NULL;
238 ISC_LINK_INIT(name, link);
241 void
242 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
244 * Dedicate a buffer for use with 'name'.
247 REQUIRE(VALID_NAME(name));
248 REQUIRE((buffer != NULL && name->buffer == NULL) ||
249 (buffer == NULL));
251 name->buffer = buffer;
254 isc_boolean_t
255 dns_name_hasbuffer(const dns_name_t *name) {
257 * Does 'name' have a dedicated buffer?
260 REQUIRE(VALID_NAME(name));
262 if (name->buffer != NULL)
263 return (ISC_TRUE);
265 return (ISC_FALSE);
268 isc_boolean_t
269 dns_name_isabsolute(const dns_name_t *name) {
272 * Does 'name' end in the root label?
275 REQUIRE(VALID_NAME(name));
277 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
278 return (ISC_TRUE);
279 return (ISC_FALSE);
282 #define hyphenchar(c) ((c) == 0x2d)
283 #define asterchar(c) ((c) == 0x2a)
284 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
285 || ((c) >= 0x61 && (c) <= 0x7a))
286 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
287 #define borderchar(c) (alphachar(c) || digitchar(c))
288 #define middlechar(c) (borderchar(c) || hyphenchar(c))
289 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
291 isc_boolean_t
292 dns_name_ismailbox(const dns_name_t *name) {
293 unsigned char *ndata, ch;
294 unsigned int n;
295 isc_boolean_t first;
297 REQUIRE(VALID_NAME(name));
298 REQUIRE(name->labels > 0);
299 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
302 * Root label.
304 if (name->length == 1)
305 return (ISC_TRUE);
307 ndata = name->ndata;
308 n = *ndata++;
309 INSIST(n <= 63);
310 while (n--) {
311 ch = *ndata++;
312 if (!domainchar(ch))
313 return (ISC_FALSE);
316 if (ndata == name->ndata + name->length)
317 return (ISC_FALSE);
320 * RFC292/RFC1123 hostname.
322 while (ndata < (name->ndata + name->length)) {
323 n = *ndata++;
324 INSIST(n <= 63);
325 first = ISC_TRUE;
326 while (n--) {
327 ch = *ndata++;
328 if (first || n == 0) {
329 if (!borderchar(ch))
330 return (ISC_FALSE);
331 } else {
332 if (!middlechar(ch))
333 return (ISC_FALSE);
335 first = ISC_FALSE;
338 return (ISC_TRUE);
341 isc_boolean_t
342 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
343 unsigned char *ndata, ch;
344 unsigned int n;
345 isc_boolean_t first;
347 REQUIRE(VALID_NAME(name));
348 REQUIRE(name->labels > 0);
349 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
352 * Root label.
354 if (name->length == 1)
355 return (ISC_TRUE);
358 * Skip wildcard if this is a ownername.
360 ndata = name->ndata;
361 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
362 ndata += 2;
365 * RFC292/RFC1123 hostname.
367 while (ndata < (name->ndata + name->length)) {
368 n = *ndata++;
369 INSIST(n <= 63);
370 first = ISC_TRUE;
371 while (n--) {
372 ch = *ndata++;
373 if (first || n == 0) {
374 if (!borderchar(ch))
375 return (ISC_FALSE);
376 } else {
377 if (!middlechar(ch))
378 return (ISC_FALSE);
380 first = ISC_FALSE;
383 return (ISC_TRUE);
386 isc_boolean_t
387 dns_name_iswildcard(const dns_name_t *name) {
388 unsigned char *ndata;
391 * Is 'name' a wildcard name?
394 REQUIRE(VALID_NAME(name));
395 REQUIRE(name->labels > 0);
397 if (name->length >= 2) {
398 ndata = name->ndata;
399 if (ndata[0] == 1 && ndata[1] == '*')
400 return (ISC_TRUE);
403 return (ISC_FALSE);
406 isc_boolean_t
407 dns_name_internalwildcard(const dns_name_t *name) {
408 unsigned char *ndata;
409 unsigned int count;
410 unsigned int label;
413 * Does 'name' contain a internal wildcard?
416 REQUIRE(VALID_NAME(name));
417 REQUIRE(name->labels > 0);
420 * Skip first label.
422 ndata = name->ndata;
423 count = *ndata++;
424 INSIST(count <= 63);
425 ndata += count;
426 label = 1;
428 * Check all but the last of the remaining labels.
430 while (label + 1 < name->labels) {
431 count = *ndata++;
432 INSIST(count <= 63);
433 if (count == 1 && *ndata == '*')
434 return (ISC_TRUE);
435 ndata += count;
436 label++;
438 return (ISC_FALSE);
441 static inline unsigned int
442 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
443 unsigned int length;
444 const unsigned char *s;
445 unsigned int h = 0;
446 unsigned char c;
448 length = name->length;
449 if (length > 16)
450 length = 16;
453 * This hash function is similar to the one Ousterhout
454 * uses in Tcl.
456 s = name->ndata;
457 if (case_sensitive) {
458 while (length > 0) {
459 h += ( h << 3 ) + *s;
460 s++;
461 length--;
463 } else {
464 while (length > 0) {
465 c = maptolower[*s];
466 h += ( h << 3 ) + c;
467 s++;
468 length--;
472 return (h);
475 unsigned int
476 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
478 * Provide a hash value for 'name'.
480 REQUIRE(VALID_NAME(name));
482 if (name->labels == 0)
483 return (0);
485 return (name_hash(name, case_sensitive));
488 unsigned int
489 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
491 * Provide a hash value for 'name'.
493 REQUIRE(VALID_NAME(name));
495 if (name->labels == 0)
496 return (0);
498 return (isc_hash_calc((const unsigned char *)name->ndata,
499 name->length, case_sensitive));
502 unsigned int
503 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
505 * This function was deprecated due to the breakage of the name space
506 * convention. We only keep this internally to provide binary backward
507 * compatibility.
509 REQUIRE(VALID_NAME(name));
511 return (dns_name_fullhash(name, case_sensitive));
514 unsigned int
515 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
516 unsigned char *offsets;
517 dns_offsets_t odata;
518 dns_name_t tname;
519 unsigned int h = 0;
520 unsigned int i;
523 * Provide a hash value for 'name'.
525 REQUIRE(VALID_NAME(name));
527 if (name->labels == 0)
528 return (0);
529 else if (name->labels == 1)
530 return (name_hash(name, case_sensitive));
532 SETUP_OFFSETS(name, offsets, odata);
533 DNS_NAME_INIT(&tname, NULL);
534 tname.labels = 1;
535 h = 0;
536 for (i = 0; i < name->labels; i++) {
537 tname.ndata = name->ndata + offsets[i];
538 if (i == name->labels - 1)
539 tname.length = name->length - offsets[i];
540 else
541 tname.length = offsets[i + 1] - offsets[i];
542 h += name_hash(&tname, case_sensitive);
545 return (h);
548 dns_namereln_t
549 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
550 int *orderp, unsigned int *nlabelsp)
552 unsigned int l1, l2, l, count1, count2, count, nlabels;
553 int cdiff, ldiff, chdiff;
554 unsigned char *label1, *label2;
555 unsigned char *offsets1, *offsets2;
556 dns_offsets_t odata1, odata2;
557 dns_namereln_t namereln = dns_namereln_none;
560 * Determine the relative ordering under the DNSSEC order relation of
561 * 'name1' and 'name2', and also determine the hierarchical
562 * relationship of the names.
564 * Note: It makes no sense for one of the names to be relative and the
565 * other absolute. If both names are relative, then to be meaningfully
566 * compared the caller must ensure that they are both relative to the
567 * same domain.
570 REQUIRE(VALID_NAME(name1));
571 REQUIRE(VALID_NAME(name2));
572 REQUIRE(orderp != NULL);
573 REQUIRE(nlabelsp != NULL);
575 * Either name1 is absolute and name2 is absolute, or neither is.
577 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
578 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
580 SETUP_OFFSETS(name1, offsets1, odata1);
581 SETUP_OFFSETS(name2, offsets2, odata2);
583 nlabels = 0;
584 l1 = name1->labels;
585 l2 = name2->labels;
586 ldiff = (int)l1 - (int)l2;
587 if (ldiff < 0)
588 l = l1;
589 else
590 l = l2;
592 while (l > 0) {
593 l--;
594 l1--;
595 l2--;
596 label1 = &name1->ndata[offsets1[l1]];
597 label2 = &name2->ndata[offsets2[l2]];
598 count1 = *label1++;
599 count2 = *label2++;
602 * We dropped bitstring labels, and we don't support any
603 * other extended label types.
605 INSIST(count1 <= 63 && count2 <= 63);
607 cdiff = (int)count1 - (int)count2;
608 if (cdiff < 0)
609 count = count1;
610 else
611 count = count2;
613 while (count > 0) {
614 chdiff = (int)maptolower[*label1] -
615 (int)maptolower[*label2];
616 if (chdiff != 0) {
617 *orderp = chdiff;
618 goto done;
620 count--;
621 label1++;
622 label2++;
624 if (cdiff != 0) {
625 *orderp = cdiff;
626 goto done;
628 nlabels++;
631 *orderp = ldiff;
632 if (ldiff < 0)
633 namereln = dns_namereln_contains;
634 else if (ldiff > 0)
635 namereln = dns_namereln_subdomain;
636 else
637 namereln = dns_namereln_equal;
639 done:
640 *nlabelsp = nlabels;
642 if (nlabels > 0 && namereln == dns_namereln_none)
643 namereln = dns_namereln_commonancestor;
645 return (namereln);
649 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
650 int order;
651 unsigned int nlabels;
654 * Determine the relative ordering under the DNSSEC order relation of
655 * 'name1' and 'name2'.
657 * Note: It makes no sense for one of the names to be relative and the
658 * other absolute. If both names are relative, then to be meaningfully
659 * compared the caller must ensure that they are both relative to the
660 * same domain.
663 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
665 return (order);
668 isc_boolean_t
669 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
670 unsigned int l, count;
671 unsigned char c;
672 unsigned char *label1, *label2;
675 * Are 'name1' and 'name2' equal?
677 * Note: It makes no sense for one of the names to be relative and the
678 * other absolute. If both names are relative, then to be meaningfully
679 * compared the caller must ensure that they are both relative to the
680 * same domain.
683 REQUIRE(VALID_NAME(name1));
684 REQUIRE(VALID_NAME(name2));
686 * Either name1 is absolute and name2 is absolute, or neither is.
688 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
689 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
691 if (name1->length != name2->length)
692 return (ISC_FALSE);
694 l = name1->labels;
696 if (l != name2->labels)
697 return (ISC_FALSE);
699 label1 = name1->ndata;
700 label2 = name2->ndata;
701 while (l > 0) {
702 l--;
703 count = *label1++;
704 if (count != *label2++)
705 return (ISC_FALSE);
707 INSIST(count <= 63); /* no bitstring support */
709 while (count > 0) {
710 count--;
711 c = maptolower[*label1++];
712 if (c != maptolower[*label2++])
713 return (ISC_FALSE);
717 return (ISC_TRUE);
720 isc_boolean_t
721 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
724 * Are 'name1' and 'name2' equal?
726 * Note: It makes no sense for one of the names to be relative and the
727 * other absolute. If both names are relative, then to be meaningfully
728 * compared the caller must ensure that they are both relative to the
729 * same domain.
732 REQUIRE(VALID_NAME(name1));
733 REQUIRE(VALID_NAME(name2));
735 * Either name1 is absolute and name2 is absolute, or neither is.
737 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
738 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
740 if (name1->length != name2->length)
741 return (ISC_FALSE);
743 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
744 return (ISC_FALSE);
746 return (ISC_TRUE);
750 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
751 unsigned int l1, l2, l, count1, count2, count;
752 unsigned char c1, c2;
753 unsigned char *label1, *label2;
756 * Compare two absolute names as rdata.
759 REQUIRE(VALID_NAME(name1));
760 REQUIRE(name1->labels > 0);
761 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
762 REQUIRE(VALID_NAME(name2));
763 REQUIRE(name2->labels > 0);
764 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
766 l1 = name1->labels;
767 l2 = name2->labels;
769 l = (l1 < l2) ? l1 : l2;
771 label1 = name1->ndata;
772 label2 = name2->ndata;
773 while (l > 0) {
774 l--;
775 count1 = *label1++;
776 count2 = *label2++;
778 /* no bitstring support */
779 INSIST(count1 <= 63 && count2 <= 63);
781 if (count1 != count2)
782 return ((count1 < count2) ? -1 : 1);
783 count = count1;
784 while (count > 0) {
785 count--;
786 c1 = maptolower[*label1++];
787 c2 = maptolower[*label2++];
788 if (c1 < c2)
789 return (-1);
790 else if (c1 > c2)
791 return (1);
796 * If one name had more labels than the other, their common
797 * prefix must have been different because the shorter name
798 * ended with the root label and the longer one can't have
799 * a root label in the middle of it. Therefore, if we get
800 * to this point, the lengths must be equal.
802 INSIST(l1 == l2);
804 return (0);
807 isc_boolean_t
808 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
809 int order;
810 unsigned int nlabels;
811 dns_namereln_t namereln;
814 * Is 'name1' a subdomain of 'name2'?
816 * Note: It makes no sense for one of the names to be relative and the
817 * other absolute. If both names are relative, then to be meaningfully
818 * compared the caller must ensure that they are both relative to the
819 * same domain.
822 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
823 if (namereln == dns_namereln_subdomain ||
824 namereln == dns_namereln_equal)
825 return (ISC_TRUE);
827 return (ISC_FALSE);
830 isc_boolean_t
831 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
832 int order;
833 unsigned int nlabels, labels;
834 dns_name_t tname;
836 REQUIRE(VALID_NAME(name));
837 REQUIRE(name->labels > 0);
838 REQUIRE(VALID_NAME(wname));
839 labels = wname->labels;
840 REQUIRE(labels > 0);
841 REQUIRE(dns_name_iswildcard(wname));
843 DNS_NAME_INIT(&tname, NULL);
844 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
845 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
846 dns_namereln_subdomain)
847 return (ISC_TRUE);
848 return (ISC_FALSE);
851 unsigned int
852 dns_name_countlabels(const dns_name_t *name) {
854 * How many labels does 'name' have?
857 REQUIRE(VALID_NAME(name));
859 ENSURE(name->labels <= 128);
861 return (name->labels);
864 void
865 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
866 unsigned char *offsets;
867 dns_offsets_t odata;
870 * Make 'label' refer to the 'n'th least significant label of 'name'.
873 REQUIRE(VALID_NAME(name));
874 REQUIRE(name->labels > 0);
875 REQUIRE(n < name->labels);
876 REQUIRE(label != NULL);
878 SETUP_OFFSETS(name, offsets, odata);
880 label->base = &name->ndata[offsets[n]];
881 if (n == name->labels - 1)
882 label->length = name->length - offsets[n];
883 else
884 label->length = offsets[n + 1] - offsets[n];
887 void
888 dns_name_getlabelsequence(const dns_name_t *source,
889 unsigned int first, unsigned int n,
890 dns_name_t *target)
892 unsigned char *offsets;
893 dns_offsets_t odata;
894 unsigned int firstoffset, endoffset;
897 * Make 'target' refer to the 'n' labels including and following
898 * 'first' in 'source'.
901 REQUIRE(VALID_NAME(source));
902 REQUIRE(VALID_NAME(target));
903 REQUIRE(first <= source->labels);
904 REQUIRE(first + n <= source->labels);
905 REQUIRE(BINDABLE(target));
907 SETUP_OFFSETS(source, offsets, odata);
909 if (first == source->labels)
910 firstoffset = source->length;
911 else
912 firstoffset = offsets[first];
914 if (first + n == source->labels)
915 endoffset = source->length;
916 else
917 endoffset = offsets[first + n];
919 target->ndata = &source->ndata[firstoffset];
920 target->length = endoffset - firstoffset;
922 if (first + n == source->labels && n > 0 &&
923 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
924 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
925 else
926 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
928 target->labels = n;
931 * If source and target are the same, and we're making target
932 * a prefix of source, the offsets table is correct already
933 * so we don't need to call set_offsets().
935 if (target->offsets != NULL &&
936 (target != source || first != 0))
937 set_offsets(target, target->offsets, NULL);
940 void
941 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
944 * Make 'target' refer to the same name as 'source'.
947 REQUIRE(VALID_NAME(source));
948 REQUIRE(VALID_NAME(target));
949 REQUIRE(BINDABLE(target));
951 target->ndata = source->ndata;
952 target->length = source->length;
953 target->labels = source->labels;
954 target->attributes = source->attributes &
955 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
956 DNS_NAMEATTR_DYNOFFSETS);
957 if (target->offsets != NULL && source->labels > 0) {
958 if (source->offsets != NULL)
959 memcpy(target->offsets, source->offsets,
960 source->labels);
961 else
962 set_offsets(target, target->offsets, NULL);
966 void
967 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
968 unsigned char *offsets;
969 dns_offsets_t odata;
970 unsigned int len;
971 isc_region_t r2;
974 * Make 'name' refer to region 'r'.
977 REQUIRE(VALID_NAME(name));
978 REQUIRE(r != NULL);
979 REQUIRE(BINDABLE(name));
981 INIT_OFFSETS(name, offsets, odata);
983 if (name->buffer != NULL) {
984 isc_buffer_clear(name->buffer);
985 isc_buffer_availableregion(name->buffer, &r2);
986 len = (r->length < r2.length) ? r->length : r2.length;
987 if (len > DNS_NAME_MAXWIRE)
988 len = DNS_NAME_MAXWIRE;
989 memcpy(r2.base, r->base, len);
990 name->ndata = r2.base;
991 name->length = len;
992 } else {
993 name->ndata = r->base;
994 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
995 r->length : DNS_NAME_MAXWIRE;
998 if (r->length > 0)
999 set_offsets(name, offsets, name);
1000 else {
1001 name->labels = 0;
1002 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1005 if (name->buffer != NULL)
1006 isc_buffer_add(name->buffer, name->length);
1009 void
1010 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1012 * Make 'r' refer to 'name'.
1015 REQUIRE(VALID_NAME(name));
1016 REQUIRE(r != NULL);
1018 DNS_NAME_TOREGION(name, r);
1022 isc_result_t
1023 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1024 dns_name_t *origin, unsigned int options,
1025 isc_buffer_t *target)
1027 unsigned char *ndata, *label;
1028 char *tdata;
1029 char c;
1030 ft_state state;
1031 unsigned int value, count;
1032 unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
1033 isc_boolean_t done;
1034 unsigned char *offsets;
1035 dns_offsets_t odata;
1036 isc_boolean_t downcase;
1039 * Convert the textual representation of a DNS name at source
1040 * into uncompressed wire form stored in target.
1042 * Notes:
1043 * Relative domain names will have 'origin' appended to them
1044 * unless 'origin' is NULL, in which case relative domain names
1045 * will remain relative.
1048 REQUIRE(VALID_NAME(name));
1049 REQUIRE(ISC_BUFFER_VALID(source));
1050 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1051 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1053 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1055 if (target == NULL && name->buffer != NULL) {
1056 target = name->buffer;
1057 isc_buffer_clear(target);
1060 REQUIRE(BINDABLE(name));
1062 INIT_OFFSETS(name, offsets, odata);
1063 offsets[0] = 0;
1066 * Initialize things to make the compiler happy; they're not required.
1068 n1 = 0;
1069 n2 = 0;
1070 label = NULL;
1071 digits = 0;
1072 value = 0;
1073 count = 0;
1076 * Make 'name' empty in case of failure.
1078 MAKE_EMPTY(name);
1081 * Set up the state machine.
1083 tdata = (char *)source->base + source->current;
1084 tlen = isc_buffer_remaininglength(source);
1085 tused = 0;
1086 ndata = isc_buffer_used(target);
1087 nrem = isc_buffer_availablelength(target);
1088 if (nrem > 255)
1089 nrem = 255;
1090 nused = 0;
1091 labels = 0;
1092 done = ISC_FALSE;
1093 state = ft_init;
1095 while (nrem > 0 && tlen > 0 && !done) {
1096 c = *tdata++;
1097 tlen--;
1098 tused++;
1100 switch (state) {
1101 case ft_init:
1103 * Is this the root name?
1105 if (c == '.') {
1106 if (tlen != 0)
1107 return (DNS_R_EMPTYLABEL);
1108 labels++;
1109 *ndata++ = 0;
1110 nrem--;
1111 nused++;
1112 done = ISC_TRUE;
1113 break;
1115 if (c == '@' && tlen == 0) {
1116 state = ft_at;
1117 break;
1120 /* FALLTHROUGH */
1121 case ft_start:
1122 label = ndata;
1123 ndata++;
1124 nrem--;
1125 nused++;
1126 count = 0;
1127 if (c == '\\') {
1128 state = ft_initialescape;
1129 break;
1131 state = ft_ordinary;
1132 if (nrem == 0)
1133 return (ISC_R_NOSPACE);
1134 /* FALLTHROUGH */
1135 case ft_ordinary:
1136 if (c == '.') {
1137 if (count == 0)
1138 return (DNS_R_EMPTYLABEL);
1139 *label = count;
1140 labels++;
1141 INSIST(labels <= 127);
1142 offsets[labels] = nused;
1143 if (tlen == 0) {
1144 labels++;
1145 *ndata++ = 0;
1146 nrem--;
1147 nused++;
1148 done = ISC_TRUE;
1150 state = ft_start;
1151 } else if (c == '\\') {
1152 state = ft_escape;
1153 } else {
1154 if (count >= 63)
1155 return (DNS_R_LABELTOOLONG);
1156 count++;
1157 CONVERTTOASCII(c);
1158 if (downcase)
1159 c = maptolower[(int)c];
1160 *ndata++ = c;
1161 nrem--;
1162 nused++;
1164 break;
1165 case ft_initialescape:
1166 if (c == '[') {
1168 * This looks like a bitstring label, which
1169 * was deprecated. Intentionally drop it.
1171 return (DNS_R_BADLABELTYPE);
1173 state = ft_escape;
1174 /* FALLTHROUGH */
1175 case ft_escape:
1176 if (!isdigit(c & 0xff)) {
1177 if (count >= 63)
1178 return (DNS_R_LABELTOOLONG);
1179 count++;
1180 CONVERTTOASCII(c);
1181 if (downcase)
1182 c = maptolower[(int)c];
1183 *ndata++ = c;
1184 nrem--;
1185 nused++;
1186 state = ft_ordinary;
1187 break;
1189 digits = 0;
1190 value = 0;
1191 state = ft_escdecimal;
1192 /* FALLTHROUGH */
1193 case ft_escdecimal:
1194 if (!isdigit(c & 0xff))
1195 return (DNS_R_BADESCAPE);
1196 value *= 10;
1197 value += digitvalue[(int)c];
1198 digits++;
1199 if (digits == 3) {
1200 if (value > 255)
1201 return (DNS_R_BADESCAPE);
1202 if (count >= 63)
1203 return (DNS_R_LABELTOOLONG);
1204 count++;
1205 if (downcase)
1206 value = maptolower[value];
1207 *ndata++ = value;
1208 nrem--;
1209 nused++;
1210 state = ft_ordinary;
1212 break;
1213 default:
1214 FATAL_ERROR(__FILE__, __LINE__,
1215 "Unexpected state %d", state);
1216 /* Does not return. */
1220 if (!done) {
1221 if (nrem == 0)
1222 return (ISC_R_NOSPACE);
1223 INSIST(tlen == 0);
1224 if (state != ft_ordinary && state != ft_at)
1225 return (ISC_R_UNEXPECTEDEND);
1226 if (state == ft_ordinary) {
1227 INSIST(count != 0);
1228 *label = count;
1229 labels++;
1230 INSIST(labels <= 127);
1231 offsets[labels] = nused;
1233 if (origin != NULL) {
1234 if (nrem < origin->length)
1235 return (ISC_R_NOSPACE);
1236 label = origin->ndata;
1237 n1 = origin->length;
1238 nrem -= n1;
1239 while (n1 > 0) {
1240 n2 = *label++;
1241 INSIST(n2 <= 63); /* no bitstring support */
1242 *ndata++ = n2;
1243 n1 -= n2 + 1;
1244 nused += n2 + 1;
1245 while (n2 > 0) {
1246 c = *label++;
1247 if (downcase)
1248 c = maptolower[(int)c];
1249 *ndata++ = c;
1250 n2--;
1252 labels++;
1253 if (n1 > 0) {
1254 INSIST(labels <= 127);
1255 offsets[labels] = nused;
1258 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1259 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1261 } else
1262 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1264 name->ndata = (unsigned char *)target->base + target->used;
1265 name->labels = labels;
1266 name->length = nused;
1268 isc_buffer_forward(source, tused);
1269 isc_buffer_add(target, name->length);
1271 return (ISC_R_SUCCESS);
1274 #ifdef ISC_PLATFORM_USETHREADS
1275 static void
1276 free_specific(void *arg) {
1277 dns_name_totextfilter_t *mem = arg;
1278 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1279 /* Stop use being called again. */
1280 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1283 static void
1284 thread_key_mutex_init(void) {
1285 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1288 static isc_result_t
1289 totext_filter_proc_key_init(void) {
1290 isc_result_t result;
1293 * We need the call to isc_once_do() to support profiled mutex
1294 * otherwise thread_key_mutex could be initialized at compile time.
1296 result = isc_once_do(&once, thread_key_mutex_init);
1297 if (result != ISC_R_SUCCESS)
1298 return (result);
1300 if (!thread_key_initialized) {
1301 LOCK(&thread_key_mutex);
1302 if (thread_key_mctx == NULL)
1303 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1304 if (result != ISC_R_SUCCESS)
1305 goto unlock;
1306 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1307 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1309 if (!thread_key_initialized &&
1310 isc_thread_key_create(&totext_filter_proc_key,
1311 free_specific) != 0) {
1312 result = ISC_R_FAILURE;
1313 isc_mem_detach(&thread_key_mctx);
1314 } else
1315 thread_key_initialized = 1;
1316 unlock:
1317 UNLOCK(&thread_key_mutex);
1319 return (result);
1321 #endif
1323 isc_result_t
1324 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1325 isc_buffer_t *target)
1327 unsigned char *ndata;
1328 char *tdata;
1329 unsigned int nlen, tlen;
1330 unsigned char c;
1331 unsigned int trem, count;
1332 unsigned int labels;
1333 isc_boolean_t saw_root = ISC_FALSE;
1334 unsigned int oused = target->used;
1335 #ifdef ISC_PLATFORM_USETHREADS
1336 dns_name_totextfilter_t *mem;
1337 dns_name_totextfilter_t totext_filter_proc = NULL;
1338 isc_result_t result;
1339 #endif
1342 * This function assumes the name is in proper uncompressed
1343 * wire format.
1345 REQUIRE(VALID_NAME(name));
1346 REQUIRE(ISC_BUFFER_VALID(target));
1348 #ifdef ISC_PLATFORM_USETHREADS
1349 result = totext_filter_proc_key_init();
1350 if (result != ISC_R_SUCCESS)
1351 return (result);
1352 #endif
1353 ndata = name->ndata;
1354 nlen = name->length;
1355 labels = name->labels;
1356 tdata = isc_buffer_used(target);
1357 tlen = isc_buffer_availablelength(target);
1359 trem = tlen;
1361 if (labels == 0 && nlen == 0) {
1363 * Special handling for an empty name.
1365 if (trem == 0)
1366 return (ISC_R_NOSPACE);
1369 * The names of these booleans are misleading in this case.
1370 * This empty name is not necessarily from the root node of
1371 * the DNS root zone, nor is a final dot going to be included.
1372 * They need to be set this way, though, to keep the "@"
1373 * from being trounced.
1375 saw_root = ISC_TRUE;
1376 omit_final_dot = ISC_FALSE;
1377 *tdata++ = '@';
1378 trem--;
1381 * Skip the while() loop.
1383 nlen = 0;
1384 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1386 * Special handling for the root label.
1388 if (trem == 0)
1389 return (ISC_R_NOSPACE);
1391 saw_root = ISC_TRUE;
1392 omit_final_dot = ISC_FALSE;
1393 *tdata++ = '.';
1394 trem--;
1397 * Skip the while() loop.
1399 nlen = 0;
1402 while (labels > 0 && nlen > 0 && trem > 0) {
1403 labels--;
1404 count = *ndata++;
1405 nlen--;
1406 if (count == 0) {
1407 saw_root = ISC_TRUE;
1408 break;
1410 if (count < 64) {
1411 INSIST(nlen >= count);
1412 while (count > 0) {
1413 c = *ndata;
1414 switch (c) {
1415 case 0x22: /* '"' */
1416 case 0x28: /* '(' */
1417 case 0x29: /* ')' */
1418 case 0x2E: /* '.' */
1419 case 0x3B: /* ';' */
1420 case 0x5C: /* '\\' */
1421 /* Special modifiers in zone files. */
1422 case 0x40: /* '@' */
1423 case 0x24: /* '$' */
1424 if (trem < 2)
1425 return (ISC_R_NOSPACE);
1426 *tdata++ = '\\';
1427 CONVERTFROMASCII(c);
1428 *tdata++ = c;
1429 ndata++;
1430 trem -= 2;
1431 nlen--;
1432 break;
1433 default:
1434 if (c > 0x20 && c < 0x7f) {
1435 if (trem == 0)
1436 return (ISC_R_NOSPACE);
1437 CONVERTFROMASCII(c);
1438 *tdata++ = c;
1439 ndata++;
1440 trem--;
1441 nlen--;
1442 } else {
1443 if (trem < 4)
1444 return (ISC_R_NOSPACE);
1445 *tdata++ = 0x5c;
1446 *tdata++ = 0x30 +
1447 ((c / 100) % 10);
1448 *tdata++ = 0x30 +
1449 ((c / 10) % 10);
1450 *tdata++ = 0x30 + (c % 10);
1451 trem -= 4;
1452 ndata++;
1453 nlen--;
1456 count--;
1458 } else {
1459 FATAL_ERROR(__FILE__, __LINE__,
1460 "Unexpected label type %02x", count);
1461 /* NOTREACHED */
1465 * The following assumes names are absolute. If not, we
1466 * fix things up later. Note that this means that in some
1467 * cases one more byte of text buffer is required than is
1468 * needed in the final output.
1470 if (trem == 0)
1471 return (ISC_R_NOSPACE);
1472 *tdata++ = '.';
1473 trem--;
1476 if (nlen != 0 && trem == 0)
1477 return (ISC_R_NOSPACE);
1479 if (!saw_root || omit_final_dot)
1480 trem++;
1482 isc_buffer_add(target, tlen - trem);
1484 #ifdef ISC_PLATFORM_USETHREADS
1485 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1486 if (mem != NULL)
1487 totext_filter_proc = *mem;
1488 #endif
1489 if (totext_filter_proc != NULL)
1490 return ((*totext_filter_proc)(target, oused, saw_root));
1492 return (ISC_R_SUCCESS);
1495 isc_result_t
1496 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1497 isc_buffer_t *target)
1499 unsigned char *ndata;
1500 char *tdata;
1501 unsigned int nlen, tlen;
1502 unsigned char c;
1503 unsigned int trem, count;
1504 unsigned int labels;
1507 * This function assumes the name is in proper uncompressed
1508 * wire format.
1510 REQUIRE(VALID_NAME(name));
1511 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1512 REQUIRE(ISC_BUFFER_VALID(target));
1514 ndata = name->ndata;
1515 nlen = name->length;
1516 labels = name->labels;
1517 tdata = isc_buffer_used(target);
1518 tlen = isc_buffer_availablelength(target);
1520 trem = tlen;
1522 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1524 * Special handling for the root label.
1526 if (trem == 0)
1527 return (ISC_R_NOSPACE);
1529 omit_final_dot = ISC_FALSE;
1530 *tdata++ = '.';
1531 trem--;
1534 * Skip the while() loop.
1536 nlen = 0;
1539 while (labels > 0 && nlen > 0 && trem > 0) {
1540 labels--;
1541 count = *ndata++;
1542 nlen--;
1543 if (count == 0)
1544 break;
1545 if (count < 64) {
1546 INSIST(nlen >= count);
1547 while (count > 0) {
1548 c = *ndata;
1549 if ((c >= 0x30 && c <= 0x39) || /* digit */
1550 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1551 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1552 c == 0x2D || /* hyphen */
1553 c == 0x5F) /* underscore */
1555 if (trem == 0)
1556 return (ISC_R_NOSPACE);
1557 /* downcase */
1558 if (c >= 0x41 && c <= 0x5A)
1559 c += 0x20;
1560 CONVERTFROMASCII(c);
1561 *tdata++ = c;
1562 ndata++;
1563 trem--;
1564 nlen--;
1565 } else {
1566 if (trem < 3)
1567 return (ISC_R_NOSPACE);
1568 sprintf(tdata, "%%%02X", c);
1569 tdata += 3;
1570 trem -= 3;
1571 ndata++;
1572 nlen--;
1574 count--;
1576 } else {
1577 FATAL_ERROR(__FILE__, __LINE__,
1578 "Unexpected label type %02x", count);
1579 /* NOTREACHED */
1583 * The following assumes names are absolute. If not, we
1584 * fix things up later. Note that this means that in some
1585 * cases one more byte of text buffer is required than is
1586 * needed in the final output.
1588 if (trem == 0)
1589 return (ISC_R_NOSPACE);
1590 *tdata++ = '.';
1591 trem--;
1594 if (nlen != 0 && trem == 0)
1595 return (ISC_R_NOSPACE);
1597 if (omit_final_dot)
1598 trem++;
1600 isc_buffer_add(target, tlen - trem);
1602 return (ISC_R_SUCCESS);
1605 isc_result_t
1606 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1607 unsigned char *sndata, *ndata;
1608 unsigned int nlen, count, labels;
1609 isc_buffer_t buffer;
1612 * Downcase 'source'.
1615 REQUIRE(VALID_NAME(source));
1616 REQUIRE(VALID_NAME(name));
1617 if (source == name) {
1618 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1619 isc_buffer_init(&buffer, source->ndata, source->length);
1620 target = &buffer;
1621 ndata = source->ndata;
1622 } else {
1623 REQUIRE(BINDABLE(name));
1624 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1625 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1626 if (target == NULL) {
1627 target = name->buffer;
1628 isc_buffer_clear(name->buffer);
1630 ndata = (unsigned char *)target->base + target->used;
1631 name->ndata = ndata;
1634 sndata = source->ndata;
1635 nlen = source->length;
1636 labels = source->labels;
1638 if (nlen > (target->length - target->used)) {
1639 MAKE_EMPTY(name);
1640 return (ISC_R_NOSPACE);
1643 while (labels > 0 && nlen > 0) {
1644 labels--;
1645 count = *sndata++;
1646 *ndata++ = count;
1647 nlen--;
1648 if (count < 64) {
1649 INSIST(nlen >= count);
1650 while (count > 0) {
1651 *ndata++ = maptolower[(*sndata++)];
1652 nlen--;
1653 count--;
1655 } else {
1656 FATAL_ERROR(__FILE__, __LINE__,
1657 "Unexpected label type %02x", count);
1658 /* Does not return. */
1662 if (source != name) {
1663 name->labels = source->labels;
1664 name->length = source->length;
1665 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1666 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1667 else
1668 name->attributes = 0;
1669 if (name->labels > 0 && name->offsets != NULL)
1670 set_offsets(name, name->offsets, NULL);
1673 isc_buffer_add(target, name->length);
1675 return (ISC_R_SUCCESS);
1678 static void
1679 set_offsets(const dns_name_t *name, unsigned char *offsets,
1680 dns_name_t *set_name)
1682 unsigned int offset, count, length, nlabels;
1683 unsigned char *ndata;
1684 isc_boolean_t absolute;
1686 ndata = name->ndata;
1687 length = name->length;
1688 offset = 0;
1689 nlabels = 0;
1690 absolute = ISC_FALSE;
1691 while (offset != length) {
1692 INSIST(nlabels < 128);
1693 offsets[nlabels++] = offset;
1694 count = *ndata++;
1695 offset++;
1696 INSIST(count <= 63);
1697 offset += count;
1698 ndata += count;
1699 INSIST(offset <= length);
1700 if (count == 0) {
1701 absolute = ISC_TRUE;
1702 break;
1705 if (set_name != NULL) {
1706 INSIST(set_name == name);
1708 set_name->labels = nlabels;
1709 set_name->length = offset;
1710 if (absolute)
1711 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1712 else
1713 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1715 INSIST(nlabels == name->labels);
1716 INSIST(offset == name->length);
1719 isc_result_t
1720 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1721 dns_decompress_t *dctx, unsigned int options,
1722 isc_buffer_t *target)
1724 unsigned char *cdata, *ndata;
1725 unsigned int cused; /* Bytes of compressed name data used */
1726 unsigned int nused, labels, n, nmax;
1727 unsigned int current, new_current, biggest_pointer;
1728 isc_boolean_t done;
1729 fw_state state = fw_start;
1730 unsigned int c;
1731 unsigned char *offsets;
1732 dns_offsets_t odata;
1733 isc_boolean_t downcase;
1734 isc_boolean_t seen_pointer;
1737 * Copy the possibly-compressed name at source into target,
1738 * decompressing it. Loop prevention is performed by checking
1739 * the new pointer against biggest_pointer.
1742 REQUIRE(VALID_NAME(name));
1743 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1744 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1746 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1748 if (target == NULL && name->buffer != NULL) {
1749 target = name->buffer;
1750 isc_buffer_clear(target);
1753 REQUIRE(dctx != NULL);
1754 REQUIRE(BINDABLE(name));
1756 INIT_OFFSETS(name, offsets, odata);
1759 * Make 'name' empty in case of failure.
1761 MAKE_EMPTY(name);
1764 * Initialize things to make the compiler happy; they're not required.
1766 n = 0;
1767 new_current = 0;
1770 * Set up.
1772 labels = 0;
1773 done = ISC_FALSE;
1775 ndata = isc_buffer_used(target);
1776 nused = 0;
1777 seen_pointer = ISC_FALSE;
1780 * Find the maximum number of uncompressed target name
1781 * bytes we are willing to generate. This is the smaller
1782 * of the available target buffer length and the
1783 * maximum legal domain name length (255).
1785 nmax = isc_buffer_availablelength(target);
1786 if (nmax > DNS_NAME_MAXWIRE)
1787 nmax = DNS_NAME_MAXWIRE;
1789 cdata = isc_buffer_current(source);
1790 cused = 0;
1792 current = source->current;
1793 biggest_pointer = current;
1796 * Note: The following code is not optimized for speed, but
1797 * rather for correctness. Speed will be addressed in the future.
1800 while (current < source->active && !done) {
1801 c = *cdata++;
1802 current++;
1803 if (!seen_pointer)
1804 cused++;
1806 switch (state) {
1807 case fw_start:
1808 if (c < 64) {
1809 offsets[labels] = nused;
1810 labels++;
1811 if (nused + c + 1 > nmax)
1812 goto full;
1813 nused += c + 1;
1814 *ndata++ = c;
1815 if (c == 0)
1816 done = ISC_TRUE;
1817 n = c;
1818 state = fw_ordinary;
1819 } else if (c >= 128 && c < 192) {
1821 * 14 bit local compression pointer.
1822 * Local compression is no longer an
1823 * IETF draft.
1825 return (DNS_R_BADLABELTYPE);
1826 } else if (c >= 192) {
1828 * Ordinary 14-bit pointer.
1830 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1832 return (DNS_R_DISALLOWED);
1833 new_current = c & 0x3F;
1834 n = 1;
1835 state = fw_newcurrent;
1836 } else
1837 return (DNS_R_BADLABELTYPE);
1838 break;
1839 case fw_ordinary:
1840 if (downcase)
1841 c = maptolower[c];
1842 /* FALLTHROUGH */
1843 case fw_copy:
1844 *ndata++ = c;
1845 n--;
1846 if (n == 0)
1847 state = fw_start;
1848 break;
1849 case fw_newcurrent:
1850 new_current *= 256;
1851 new_current += c;
1852 n--;
1853 if (n != 0)
1854 break;
1855 if (new_current >= biggest_pointer)
1856 return (DNS_R_BADPOINTER);
1857 biggest_pointer = new_current;
1858 current = new_current;
1859 cdata = (unsigned char *)source->base + current;
1860 seen_pointer = ISC_TRUE;
1861 state = fw_start;
1862 break;
1863 default:
1864 FATAL_ERROR(__FILE__, __LINE__,
1865 "Unknown state %d", state);
1866 /* Does not return. */
1870 if (!done)
1871 return (ISC_R_UNEXPECTEDEND);
1873 name->ndata = (unsigned char *)target->base + target->used;
1874 name->labels = labels;
1875 name->length = nused;
1876 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1878 isc_buffer_forward(source, cused);
1879 isc_buffer_add(target, name->length);
1881 return (ISC_R_SUCCESS);
1883 full:
1884 if (nmax == DNS_NAME_MAXWIRE)
1886 * The name did not fit even though we had a buffer
1887 * big enough to fit a maximum-length name.
1889 return (DNS_R_NAMETOOLONG);
1890 else
1892 * The name might fit if only the caller could give us a
1893 * big enough buffer.
1895 return (ISC_R_NOSPACE);
1898 isc_result_t
1899 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1900 isc_buffer_t *target)
1902 unsigned int methods;
1903 isc_uint16_t offset;
1904 dns_name_t gp; /* Global compression prefix */
1905 isc_boolean_t gf; /* Global compression target found */
1906 isc_uint16_t go; /* Global compression offset */
1907 dns_offsets_t clo;
1908 dns_name_t clname;
1911 * Convert 'name' into wire format, compressing it as specified by the
1912 * compression context 'cctx', and storing the result in 'target'.
1915 REQUIRE(VALID_NAME(name));
1916 REQUIRE(cctx != NULL);
1917 REQUIRE(ISC_BUFFER_VALID(target));
1920 * If 'name' doesn't have an offsets table, make a clone which
1921 * has one.
1923 if (name->offsets == NULL) {
1924 DNS_NAME_INIT(&clname, clo);
1925 dns_name_clone(name, &clname);
1926 name = &clname;
1928 DNS_NAME_INIT(&gp, NULL);
1930 offset = target->used; /*XXX*/
1932 methods = dns_compress_getmethods(cctx);
1934 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1935 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1936 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1937 else
1938 gf = ISC_FALSE;
1941 * If the offset is too high for 14 bit global compression, we're
1942 * out of luck.
1944 if (gf && go >= 0x4000)
1945 gf = ISC_FALSE;
1948 * Will the compression pointer reduce the message size?
1950 if (gf && (gp.length + 2) >= name->length)
1951 gf = ISC_FALSE;
1953 if (gf) {
1954 if (target->length - target->used < gp.length)
1955 return (ISC_R_NOSPACE);
1956 (void)memcpy((unsigned char *)target->base + target->used,
1957 gp.ndata, (size_t)gp.length);
1958 isc_buffer_add(target, gp.length);
1959 go |= 0xc000;
1960 if (target->length - target->used < 2)
1961 return (ISC_R_NOSPACE);
1962 isc_buffer_putuint16(target, go);
1963 if (gp.length != 0)
1964 dns_compress_add(cctx, name, &gp, offset);
1965 } else {
1966 if (target->length - target->used < name->length)
1967 return (ISC_R_NOSPACE);
1968 (void)memcpy((unsigned char *)target->base + target->used,
1969 name->ndata, (size_t)name->length);
1970 isc_buffer_add(target, name->length);
1971 dns_compress_add(cctx, name, name, offset);
1973 return (ISC_R_SUCCESS);
1976 isc_result_t
1977 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1978 isc_buffer_t *target)
1980 unsigned char *ndata, *offsets;
1981 unsigned int nrem, labels, prefix_length, length;
1982 isc_boolean_t copy_prefix = ISC_TRUE;
1983 isc_boolean_t copy_suffix = ISC_TRUE;
1984 isc_boolean_t absolute = ISC_FALSE;
1985 dns_name_t tmp_name;
1986 dns_offsets_t odata;
1989 * Concatenate 'prefix' and 'suffix'.
1992 REQUIRE(prefix == NULL || VALID_NAME(prefix));
1993 REQUIRE(suffix == NULL || VALID_NAME(suffix));
1994 REQUIRE(name == NULL || VALID_NAME(name));
1995 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1996 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1997 if (prefix == NULL || prefix->labels == 0)
1998 copy_prefix = ISC_FALSE;
1999 if (suffix == NULL || suffix->labels == 0)
2000 copy_suffix = ISC_FALSE;
2001 if (copy_prefix &&
2002 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2003 absolute = ISC_TRUE;
2004 REQUIRE(!copy_suffix);
2006 if (name == NULL) {
2007 DNS_NAME_INIT(&tmp_name, odata);
2008 name = &tmp_name;
2010 if (target == NULL) {
2011 INSIST(name->buffer != NULL);
2012 target = name->buffer;
2013 isc_buffer_clear(name->buffer);
2016 REQUIRE(BINDABLE(name));
2019 * Set up.
2021 nrem = target->length - target->used;
2022 ndata = (unsigned char *)target->base + target->used;
2023 if (nrem > DNS_NAME_MAXWIRE)
2024 nrem = DNS_NAME_MAXWIRE;
2025 length = 0;
2026 prefix_length = 0;
2027 labels = 0;
2028 if (copy_prefix) {
2029 prefix_length = prefix->length;
2030 length += prefix_length;
2031 labels += prefix->labels;
2033 if (copy_suffix) {
2034 length += suffix->length;
2035 labels += suffix->labels;
2037 if (length > DNS_NAME_MAXWIRE) {
2038 MAKE_EMPTY(name);
2039 return (DNS_R_NAMETOOLONG);
2041 if (length > nrem) {
2042 MAKE_EMPTY(name);
2043 return (ISC_R_NOSPACE);
2046 if (copy_suffix) {
2047 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2048 absolute = ISC_TRUE;
2049 if (suffix == name && suffix->buffer == target)
2050 memmove(ndata + prefix_length, suffix->ndata,
2051 suffix->length);
2052 else
2053 memcpy(ndata + prefix_length, suffix->ndata,
2054 suffix->length);
2058 * If 'prefix' and 'name' are the same object, and the object has
2059 * a dedicated buffer, and we're using it, then we don't have to
2060 * copy anything.
2062 if (copy_prefix && (prefix != name || prefix->buffer != target))
2063 memcpy(ndata, prefix->ndata, prefix_length);
2065 name->ndata = ndata;
2066 name->labels = labels;
2067 name->length = length;
2068 if (absolute)
2069 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2070 else
2071 name->attributes = 0;
2073 if (name->labels > 0 && name->offsets != NULL) {
2074 INIT_OFFSETS(name, offsets, odata);
2075 set_offsets(name, offsets, NULL);
2078 isc_buffer_add(target, name->length);
2080 return (ISC_R_SUCCESS);
2083 void
2084 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2085 dns_name_t *prefix, dns_name_t *suffix)
2088 unsigned int splitlabel;
2090 REQUIRE(VALID_NAME(name));
2091 REQUIRE(suffixlabels > 0);
2092 REQUIRE(suffixlabels < name->labels);
2093 REQUIRE(prefix != NULL || suffix != NULL);
2094 REQUIRE(prefix == NULL ||
2095 (VALID_NAME(prefix) &&
2096 prefix->buffer != NULL &&
2097 BINDABLE(prefix)));
2098 REQUIRE(suffix == NULL ||
2099 (VALID_NAME(suffix) &&
2100 suffix->buffer != NULL &&
2101 BINDABLE(suffix)));
2103 splitlabel = name->labels - suffixlabels;
2105 if (prefix != NULL)
2106 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2108 if (suffix != NULL)
2109 dns_name_getlabelsequence(name, splitlabel,
2110 suffixlabels, suffix);
2112 return;
2115 isc_result_t
2116 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2117 dns_name_t *target)
2120 * Make 'target' a dynamically allocated copy of 'source'.
2123 REQUIRE(VALID_NAME(source));
2124 REQUIRE(source->length > 0);
2125 REQUIRE(VALID_NAME(target));
2126 REQUIRE(BINDABLE(target));
2129 * Make 'target' empty in case of failure.
2131 MAKE_EMPTY(target);
2133 target->ndata = isc_mem_get(mctx, source->length);
2134 if (target->ndata == NULL)
2135 return (ISC_R_NOMEMORY);
2137 memcpy(target->ndata, source->ndata, source->length);
2139 target->length = source->length;
2140 target->labels = source->labels;
2141 target->attributes = DNS_NAMEATTR_DYNAMIC;
2142 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2143 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2144 if (target->offsets != NULL) {
2145 if (source->offsets != NULL)
2146 memcpy(target->offsets, source->offsets,
2147 source->labels);
2148 else
2149 set_offsets(target, target->offsets, NULL);
2152 return (ISC_R_SUCCESS);
2155 isc_result_t
2156 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2157 dns_name_t *target)
2160 * Make 'target' a read-only dynamically allocated copy of 'source'.
2161 * 'target' will also have a dynamically allocated offsets table.
2164 REQUIRE(VALID_NAME(source));
2165 REQUIRE(source->length > 0);
2166 REQUIRE(VALID_NAME(target));
2167 REQUIRE(BINDABLE(target));
2168 REQUIRE(target->offsets == NULL);
2171 * Make 'target' empty in case of failure.
2173 MAKE_EMPTY(target);
2175 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2176 if (target->ndata == NULL)
2177 return (ISC_R_NOMEMORY);
2179 memcpy(target->ndata, source->ndata, source->length);
2181 target->length = source->length;
2182 target->labels = source->labels;
2183 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2184 DNS_NAMEATTR_READONLY;
2185 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2186 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2187 target->offsets = target->ndata + source->length;
2188 if (source->offsets != NULL)
2189 memcpy(target->offsets, source->offsets, source->labels);
2190 else
2191 set_offsets(target, target->offsets, NULL);
2193 return (ISC_R_SUCCESS);
2196 void
2197 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2198 size_t size;
2201 * Free 'name'.
2204 REQUIRE(VALID_NAME(name));
2205 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2207 size = name->length;
2208 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2209 size += name->labels;
2210 isc_mem_put(mctx, name->ndata, size);
2211 dns_name_invalidate(name);
2214 isc_result_t
2215 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2216 dns_name_t downname;
2217 unsigned char data[256];
2218 isc_buffer_t buffer;
2219 isc_result_t result;
2220 isc_region_t r;
2223 * Send 'name' in DNSSEC canonical form to 'digest'.
2226 REQUIRE(VALID_NAME(name));
2227 REQUIRE(digest != NULL);
2229 DNS_NAME_INIT(&downname, NULL);
2230 isc_buffer_init(&buffer, data, sizeof(data));
2232 result = dns_name_downcase(name, &downname, &buffer);
2233 if (result != ISC_R_SUCCESS)
2234 return (result);
2236 isc_buffer_usedregion(&buffer, &r);
2238 return ((digest)(arg, &r));
2241 isc_boolean_t
2242 dns_name_dynamic(dns_name_t *name) {
2243 REQUIRE(VALID_NAME(name));
2246 * Returns whether there is dynamic memory associated with this name.
2249 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2250 ISC_TRUE : ISC_FALSE);
2253 isc_result_t
2254 dns_name_print(dns_name_t *name, FILE *stream) {
2255 isc_result_t result;
2256 isc_buffer_t b;
2257 isc_region_t r;
2258 char t[1024];
2261 * Print 'name' on 'stream'.
2264 REQUIRE(VALID_NAME(name));
2266 isc_buffer_init(&b, t, sizeof(t));
2267 result = dns_name_totext(name, ISC_FALSE, &b);
2268 if (result != ISC_R_SUCCESS)
2269 return (result);
2270 isc_buffer_usedregion(&b, &r);
2271 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2273 return (ISC_R_SUCCESS);
2276 isc_result_t
2277 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2278 #ifdef ISC_PLATFORM_USETHREADS
2279 isc_result_t result;
2280 dns_name_totextfilter_t *mem;
2281 int res;
2283 result = totext_filter_proc_key_init();
2284 if (result != ISC_R_SUCCESS)
2285 return (result);
2288 * If we already have been here set / clear as appropriate.
2289 * Otherwise allocate memory.
2291 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2292 if (mem != NULL && proc != NULL) {
2293 *mem = proc;
2294 return (ISC_R_SUCCESS);
2296 if (proc == NULL) {
2297 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2298 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2299 if (res != 0)
2300 result = ISC_R_UNEXPECTED;
2301 return (result);
2304 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2305 if (mem == NULL)
2306 return (ISC_R_NOMEMORY);
2307 *mem = proc;
2308 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2309 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2310 result = ISC_R_UNEXPECTED;
2312 return (result);
2313 #else
2314 totext_filter_proc = proc;
2315 return (ISC_R_SUCCESS);
2316 #endif
2319 void
2320 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2321 isc_result_t result;
2322 isc_buffer_t buf;
2324 REQUIRE(size > 0);
2327 * Leave room for null termination after buffer.
2329 isc_buffer_init(&buf, cp, size - 1);
2330 result = dns_name_totext(name, ISC_TRUE, &buf);
2331 if (result == ISC_R_SUCCESS) {
2333 * Null terminate.
2335 isc_region_t r;
2336 isc_buffer_usedregion(&buf, &r);
2337 ((char *) r.base)[r.length] = '\0';
2339 } else
2340 snprintf(cp, size, "<unknown>");
2343 isc_result_t
2344 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2345 unsigned char *ndata;
2348 * Make dest a copy of source.
2351 REQUIRE(VALID_NAME(source));
2352 REQUIRE(VALID_NAME(dest));
2353 REQUIRE(target != NULL || dest->buffer != NULL);
2355 if (target == NULL) {
2356 target = dest->buffer;
2357 isc_buffer_clear(dest->buffer);
2360 REQUIRE(BINDABLE(dest));
2363 * Set up.
2365 if (target->length - target->used < source->length)
2366 return (ISC_R_NOSPACE);
2368 ndata = (unsigned char *)target->base + target->used;
2369 dest->ndata = target->base;
2371 memcpy(ndata, source->ndata, source->length);
2373 dest->ndata = ndata;
2374 dest->labels = source->labels;
2375 dest->length = source->length;
2376 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2377 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2378 else
2379 dest->attributes = 0;
2381 if (dest->labels > 0 && dest->offsets != NULL) {
2382 if (source->offsets != NULL)
2383 memcpy(dest->offsets, source->offsets, source->labels);
2384 else
2385 set_offsets(dest, dest->offsets, NULL);
2388 isc_buffer_add(target, dest->length);
2390 return (ISC_R_SUCCESS);
2393 void
2394 dns_name_destroy(void) {
2395 #ifdef ISC_PLATFORM_USETHREADS
2396 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2397 == ISC_R_SUCCESS);
2399 LOCK(&thread_key_mutex);
2400 if (thread_key_initialized) {
2401 isc_mem_detach(&thread_key_mctx);
2402 isc_thread_key_delete(totext_filter_proc_key);
2403 thread_key_initialized = 0;
2405 UNLOCK(&thread_key_mutex);
2407 #endif