Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / name.c
blobc48ca47d841246152b24ce45052ce17bf00a2df0
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: name.c,v 1.169 2009/09/01 17:36:51 jinmei Exp */
22 /*! \file */
24 #include <config.h>
26 #include <ctype.h>
27 #include <stdlib.h>
29 #include <isc/buffer.h>
30 #include <isc/hash.h>
31 #include <isc/mem.h>
32 #include <isc/once.h>
33 #include <isc/print.h>
34 #include <isc/string.h>
35 #include <isc/thread.h>
36 #include <isc/util.h>
38 #include <dns/compress.h>
39 #include <dns/fixedname.h>
40 #include <dns/name.h>
41 #include <dns/result.h>
43 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
45 typedef enum {
46 ft_init = 0,
47 ft_start,
48 ft_ordinary,
49 ft_initialescape,
50 ft_escape,
51 ft_escdecimal,
52 ft_at
53 } ft_state;
55 typedef enum {
56 fw_start = 0,
57 fw_ordinary,
58 fw_copy,
59 fw_newcurrent
60 } fw_state;
62 static char digitvalue[256] = {
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
66 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
67 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
69 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
76 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
77 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
78 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
81 static unsigned char maptolower[] = {
82 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
83 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
84 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
85 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
86 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
87 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
88 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
89 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
90 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
91 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
92 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
93 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
94 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
95 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
96 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
97 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
98 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
99 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
100 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
101 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
102 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
103 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
104 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
105 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
106 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
107 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
108 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
109 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
110 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
111 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
112 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
113 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
116 #define CONVERTTOASCII(c)
117 #define CONVERTFROMASCII(c)
119 #define INIT_OFFSETS(name, var, default) \
120 if (name->offsets != NULL) \
121 var = name->offsets; \
122 else \
123 var = default;
125 #define SETUP_OFFSETS(name, var, default) \
126 if (name->offsets != NULL) \
127 var = name->offsets; \
128 else { \
129 var = default; \
130 set_offsets(name, var, NULL); \
134 * Note: If additional attributes are added that should not be set for
135 * empty names, MAKE_EMPTY() must be changed so it clears them.
137 #define MAKE_EMPTY(name) \
138 do { \
139 name->ndata = NULL; \
140 name->length = 0; \
141 name->labels = 0; \
142 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
143 } while (0);
146 * A name is "bindable" if it can be set to point to a new value, i.e.
147 * name->ndata and name->length may be changed.
149 #define BINDABLE(name) \
150 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
151 == 0)
154 * Note that the name data must be a char array, not a string
155 * literal, to avoid compiler warnings about discarding
156 * the const attribute of a string.
158 static unsigned char root_ndata[] = { '\0' };
159 static unsigned char root_offsets[] = { 0 };
161 static dns_name_t root =
163 DNS_NAME_MAGIC,
164 root_ndata, 1, 1,
165 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
166 root_offsets, NULL,
167 {(void *)-1, (void *)-1},
168 {NULL, NULL}
171 /* XXXDCL make const? */
172 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
174 static unsigned char wild_ndata[] = { '\001', '*' };
175 static unsigned char wild_offsets[] = { 0 };
177 static dns_name_t wild =
179 DNS_NAME_MAGIC,
180 wild_ndata, 2, 1,
181 DNS_NAMEATTR_READONLY,
182 wild_offsets, NULL,
183 {(void *)-1, (void *)-1},
184 {NULL, NULL}
187 /* XXXDCL make const? */
188 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
190 unsigned int
191 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
194 * dns_name_t to text post-conversion procedure.
196 #ifdef ISC_PLATFORM_USETHREADS
197 static int thread_key_initialized = 0;
198 static isc_mutex_t thread_key_mutex;
199 static isc_mem_t *thread_key_mctx = NULL;
200 static isc_thread_key_t totext_filter_proc_key;
201 static isc_once_t once = ISC_ONCE_INIT;
202 #else
203 static dns_name_totextfilter_t totext_filter_proc = NULL;
204 #endif
206 static void
207 set_offsets(const dns_name_t *name, unsigned char *offsets,
208 dns_name_t *set_name);
210 void
211 dns_name_init(dns_name_t *name, unsigned char *offsets) {
213 * Initialize 'name'.
215 DNS_NAME_INIT(name, offsets);
218 void
219 dns_name_reset(dns_name_t *name) {
220 REQUIRE(VALID_NAME(name));
221 REQUIRE(BINDABLE(name));
223 DNS_NAME_RESET(name);
226 void
227 dns_name_invalidate(dns_name_t *name) {
229 * Make 'name' invalid.
232 REQUIRE(VALID_NAME(name));
234 name->magic = 0;
235 name->ndata = NULL;
236 name->length = 0;
237 name->labels = 0;
238 name->attributes = 0;
239 name->offsets = NULL;
240 name->buffer = NULL;
241 ISC_LINK_INIT(name, link);
244 void
245 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
247 * Dedicate a buffer for use with 'name'.
250 REQUIRE(VALID_NAME(name));
251 REQUIRE((buffer != NULL && name->buffer == NULL) ||
252 (buffer == NULL));
254 name->buffer = buffer;
257 isc_boolean_t
258 dns_name_hasbuffer(const dns_name_t *name) {
260 * Does 'name' have a dedicated buffer?
263 REQUIRE(VALID_NAME(name));
265 if (name->buffer != NULL)
266 return (ISC_TRUE);
268 return (ISC_FALSE);
271 isc_boolean_t
272 dns_name_isabsolute(const dns_name_t *name) {
275 * Does 'name' end in the root label?
278 REQUIRE(VALID_NAME(name));
280 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
281 return (ISC_TRUE);
282 return (ISC_FALSE);
285 #define hyphenchar(c) ((c) == 0x2d)
286 #define asterchar(c) ((c) == 0x2a)
287 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
288 || ((c) >= 0x61 && (c) <= 0x7a))
289 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
290 #define borderchar(c) (alphachar(c) || digitchar(c))
291 #define middlechar(c) (borderchar(c) || hyphenchar(c))
292 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
294 isc_boolean_t
295 dns_name_ismailbox(const dns_name_t *name) {
296 unsigned char *ndata, ch;
297 unsigned int n;
298 isc_boolean_t first;
300 REQUIRE(VALID_NAME(name));
301 REQUIRE(name->labels > 0);
302 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
305 * Root label.
307 if (name->length == 1)
308 return (ISC_TRUE);
310 ndata = name->ndata;
311 n = *ndata++;
312 INSIST(n <= 63);
313 while (n--) {
314 ch = *ndata++;
315 if (!domainchar(ch))
316 return (ISC_FALSE);
319 if (ndata == name->ndata + name->length)
320 return (ISC_FALSE);
323 * RFC292/RFC1123 hostname.
325 while (ndata < (name->ndata + name->length)) {
326 n = *ndata++;
327 INSIST(n <= 63);
328 first = ISC_TRUE;
329 while (n--) {
330 ch = *ndata++;
331 if (first || n == 0) {
332 if (!borderchar(ch))
333 return (ISC_FALSE);
334 } else {
335 if (!middlechar(ch))
336 return (ISC_FALSE);
338 first = ISC_FALSE;
341 return (ISC_TRUE);
344 isc_boolean_t
345 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
346 unsigned char *ndata, ch;
347 unsigned int n;
348 isc_boolean_t first;
350 REQUIRE(VALID_NAME(name));
351 REQUIRE(name->labels > 0);
352 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
355 * Root label.
357 if (name->length == 1)
358 return (ISC_TRUE);
361 * Skip wildcard if this is a ownername.
363 ndata = name->ndata;
364 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
365 ndata += 2;
368 * RFC292/RFC1123 hostname.
370 while (ndata < (name->ndata + name->length)) {
371 n = *ndata++;
372 INSIST(n <= 63);
373 first = ISC_TRUE;
374 while (n--) {
375 ch = *ndata++;
376 if (first || n == 0) {
377 if (!borderchar(ch))
378 return (ISC_FALSE);
379 } else {
380 if (!middlechar(ch))
381 return (ISC_FALSE);
383 first = ISC_FALSE;
386 return (ISC_TRUE);
389 isc_boolean_t
390 dns_name_iswildcard(const dns_name_t *name) {
391 unsigned char *ndata;
394 * Is 'name' a wildcard name?
397 REQUIRE(VALID_NAME(name));
398 REQUIRE(name->labels > 0);
400 if (name->length >= 2) {
401 ndata = name->ndata;
402 if (ndata[0] == 1 && ndata[1] == '*')
403 return (ISC_TRUE);
406 return (ISC_FALSE);
409 isc_boolean_t
410 dns_name_internalwildcard(const dns_name_t *name) {
411 unsigned char *ndata;
412 unsigned int count;
413 unsigned int label;
416 * Does 'name' contain a internal wildcard?
419 REQUIRE(VALID_NAME(name));
420 REQUIRE(name->labels > 0);
423 * Skip first label.
425 ndata = name->ndata;
426 count = *ndata++;
427 INSIST(count <= 63);
428 ndata += count;
429 label = 1;
431 * Check all but the last of the remaining labels.
433 while (label + 1 < name->labels) {
434 count = *ndata++;
435 INSIST(count <= 63);
436 if (count == 1 && *ndata == '*')
437 return (ISC_TRUE);
438 ndata += count;
439 label++;
441 return (ISC_FALSE);
444 static inline unsigned int
445 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
446 unsigned int length;
447 const unsigned char *s;
448 unsigned int h = 0;
449 unsigned char c;
451 length = name->length;
452 if (length > 16)
453 length = 16;
456 * This hash function is similar to the one Ousterhout
457 * uses in Tcl.
459 s = name->ndata;
460 if (case_sensitive) {
461 while (length > 0) {
462 h += ( h << 3 ) + *s;
463 s++;
464 length--;
466 } else {
467 while (length > 0) {
468 c = maptolower[*s];
469 h += ( h << 3 ) + c;
470 s++;
471 length--;
475 return (h);
478 unsigned int
479 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
481 * Provide a hash value for 'name'.
483 REQUIRE(VALID_NAME(name));
485 if (name->labels == 0)
486 return (0);
488 return (name_hash(name, case_sensitive));
491 unsigned int
492 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
494 * Provide a hash value for 'name'.
496 REQUIRE(VALID_NAME(name));
498 if (name->labels == 0)
499 return (0);
501 return (isc_hash_calc((const unsigned char *)name->ndata,
502 name->length, case_sensitive));
505 unsigned int
506 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
508 * This function was deprecated due to the breakage of the name space
509 * convention. We only keep this internally to provide binary backward
510 * compatibility.
512 REQUIRE(VALID_NAME(name));
514 return (dns_name_fullhash(name, case_sensitive));
517 unsigned int
518 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
519 unsigned char *offsets;
520 dns_offsets_t odata;
521 dns_name_t tname;
522 unsigned int h = 0;
523 unsigned int i;
526 * Provide a hash value for 'name'.
528 REQUIRE(VALID_NAME(name));
530 if (name->labels == 0)
531 return (0);
532 else if (name->labels == 1)
533 return (name_hash(name, case_sensitive));
535 SETUP_OFFSETS(name, offsets, odata);
536 DNS_NAME_INIT(&tname, NULL);
537 tname.labels = 1;
538 h = 0;
539 for (i = 0; i < name->labels; i++) {
540 tname.ndata = name->ndata + offsets[i];
541 if (i == name->labels - 1)
542 tname.length = name->length - offsets[i];
543 else
544 tname.length = offsets[i + 1] - offsets[i];
545 h += name_hash(&tname, case_sensitive);
548 return (h);
551 dns_namereln_t
552 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
553 int *orderp, unsigned int *nlabelsp)
555 unsigned int l1, l2, l, count1, count2, count, nlabels;
556 int cdiff, ldiff, chdiff;
557 unsigned char *label1, *label2;
558 unsigned char *offsets1, *offsets2;
559 dns_offsets_t odata1, odata2;
560 dns_namereln_t namereln = dns_namereln_none;
563 * Determine the relative ordering under the DNSSEC order relation of
564 * 'name1' and 'name2', and also determine the hierarchical
565 * relationship of the names.
567 * Note: It makes no sense for one of the names to be relative and the
568 * other absolute. If both names are relative, then to be meaningfully
569 * compared the caller must ensure that they are both relative to the
570 * same domain.
573 REQUIRE(VALID_NAME(name1));
574 REQUIRE(VALID_NAME(name2));
575 REQUIRE(orderp != NULL);
576 REQUIRE(nlabelsp != NULL);
578 * Either name1 is absolute and name2 is absolute, or neither is.
580 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
581 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
583 SETUP_OFFSETS(name1, offsets1, odata1);
584 SETUP_OFFSETS(name2, offsets2, odata2);
586 nlabels = 0;
587 l1 = name1->labels;
588 l2 = name2->labels;
589 ldiff = (int)l1 - (int)l2;
590 if (ldiff < 0)
591 l = l1;
592 else
593 l = l2;
595 while (l > 0) {
596 l--;
597 l1--;
598 l2--;
599 label1 = &name1->ndata[offsets1[l1]];
600 label2 = &name2->ndata[offsets2[l2]];
601 count1 = *label1++;
602 count2 = *label2++;
605 * We dropped bitstring labels, and we don't support any
606 * other extended label types.
608 INSIST(count1 <= 63 && count2 <= 63);
610 cdiff = (int)count1 - (int)count2;
611 if (cdiff < 0)
612 count = count1;
613 else
614 count = count2;
616 while (count > 0) {
617 chdiff = (int)maptolower[*label1] -
618 (int)maptolower[*label2];
619 if (chdiff != 0) {
620 *orderp = chdiff;
621 goto done;
623 count--;
624 label1++;
625 label2++;
627 if (cdiff != 0) {
628 *orderp = cdiff;
629 goto done;
631 nlabels++;
634 *orderp = ldiff;
635 if (ldiff < 0)
636 namereln = dns_namereln_contains;
637 else if (ldiff > 0)
638 namereln = dns_namereln_subdomain;
639 else
640 namereln = dns_namereln_equal;
642 done:
643 *nlabelsp = nlabels;
645 if (nlabels > 0 && namereln == dns_namereln_none)
646 namereln = dns_namereln_commonancestor;
648 return (namereln);
652 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
653 int order;
654 unsigned int nlabels;
657 * Determine the relative ordering under the DNSSEC order relation of
658 * 'name1' and 'name2'.
660 * Note: It makes no sense for one of the names to be relative and the
661 * other absolute. If both names are relative, then to be meaningfully
662 * compared the caller must ensure that they are both relative to the
663 * same domain.
666 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
668 return (order);
671 isc_boolean_t
672 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
673 unsigned int l, count;
674 unsigned char c;
675 unsigned char *label1, *label2;
678 * Are 'name1' and 'name2' equal?
680 * Note: It makes no sense for one of the names to be relative and the
681 * other absolute. If both names are relative, then to be meaningfully
682 * compared the caller must ensure that they are both relative to the
683 * same domain.
686 REQUIRE(VALID_NAME(name1));
687 REQUIRE(VALID_NAME(name2));
689 * Either name1 is absolute and name2 is absolute, or neither is.
691 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
692 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
694 if (name1->length != name2->length)
695 return (ISC_FALSE);
697 l = name1->labels;
699 if (l != name2->labels)
700 return (ISC_FALSE);
702 label1 = name1->ndata;
703 label2 = name2->ndata;
704 while (l > 0) {
705 l--;
706 count = *label1++;
707 if (count != *label2++)
708 return (ISC_FALSE);
710 INSIST(count <= 63); /* no bitstring support */
712 while (count > 0) {
713 count--;
714 c = maptolower[*label1++];
715 if (c != maptolower[*label2++])
716 return (ISC_FALSE);
720 return (ISC_TRUE);
723 isc_boolean_t
724 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
727 * Are 'name1' and 'name2' equal?
729 * Note: It makes no sense for one of the names to be relative and the
730 * other absolute. If both names are relative, then to be meaningfully
731 * compared the caller must ensure that they are both relative to the
732 * same domain.
735 REQUIRE(VALID_NAME(name1));
736 REQUIRE(VALID_NAME(name2));
738 * Either name1 is absolute and name2 is absolute, or neither is.
740 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
741 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
743 if (name1->length != name2->length)
744 return (ISC_FALSE);
746 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
747 return (ISC_FALSE);
749 return (ISC_TRUE);
753 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
754 unsigned int l1, l2, l, count1, count2, count;
755 unsigned char c1, c2;
756 unsigned char *label1, *label2;
759 * Compare two absolute names as rdata.
762 REQUIRE(VALID_NAME(name1));
763 REQUIRE(name1->labels > 0);
764 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
765 REQUIRE(VALID_NAME(name2));
766 REQUIRE(name2->labels > 0);
767 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
769 l1 = name1->labels;
770 l2 = name2->labels;
772 l = (l1 < l2) ? l1 : l2;
774 label1 = name1->ndata;
775 label2 = name2->ndata;
776 while (l > 0) {
777 l--;
778 count1 = *label1++;
779 count2 = *label2++;
781 /* no bitstring support */
782 INSIST(count1 <= 63 && count2 <= 63);
784 if (count1 != count2)
785 return ((count1 < count2) ? -1 : 1);
786 count = count1;
787 while (count > 0) {
788 count--;
789 c1 = maptolower[*label1++];
790 c2 = maptolower[*label2++];
791 if (c1 < c2)
792 return (-1);
793 else if (c1 > c2)
794 return (1);
799 * If one name had more labels than the other, their common
800 * prefix must have been different because the shorter name
801 * ended with the root label and the longer one can't have
802 * a root label in the middle of it. Therefore, if we get
803 * to this point, the lengths must be equal.
805 INSIST(l1 == l2);
807 return (0);
810 isc_boolean_t
811 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
812 int order;
813 unsigned int nlabels;
814 dns_namereln_t namereln;
817 * Is 'name1' a subdomain of 'name2'?
819 * Note: It makes no sense for one of the names to be relative and the
820 * other absolute. If both names are relative, then to be meaningfully
821 * compared the caller must ensure that they are both relative to the
822 * same domain.
825 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
826 if (namereln == dns_namereln_subdomain ||
827 namereln == dns_namereln_equal)
828 return (ISC_TRUE);
830 return (ISC_FALSE);
833 isc_boolean_t
834 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
835 int order;
836 unsigned int nlabels, labels;
837 dns_name_t tname;
839 REQUIRE(VALID_NAME(name));
840 REQUIRE(name->labels > 0);
841 REQUIRE(VALID_NAME(wname));
842 labels = wname->labels;
843 REQUIRE(labels > 0);
844 REQUIRE(dns_name_iswildcard(wname));
846 DNS_NAME_INIT(&tname, NULL);
847 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
848 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
849 dns_namereln_subdomain)
850 return (ISC_TRUE);
851 return (ISC_FALSE);
854 unsigned int
855 dns_name_countlabels(const dns_name_t *name) {
857 * How many labels does 'name' have?
860 REQUIRE(VALID_NAME(name));
862 ENSURE(name->labels <= 128);
864 return (name->labels);
867 void
868 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
869 unsigned char *offsets;
870 dns_offsets_t odata;
873 * Make 'label' refer to the 'n'th least significant label of 'name'.
876 REQUIRE(VALID_NAME(name));
877 REQUIRE(name->labels > 0);
878 REQUIRE(n < name->labels);
879 REQUIRE(label != NULL);
881 SETUP_OFFSETS(name, offsets, odata);
883 label->base = &name->ndata[offsets[n]];
884 if (n == name->labels - 1)
885 label->length = name->length - offsets[n];
886 else
887 label->length = offsets[n + 1] - offsets[n];
890 void
891 dns_name_getlabelsequence(const dns_name_t *source,
892 unsigned int first, unsigned int n,
893 dns_name_t *target)
895 unsigned char *offsets;
896 dns_offsets_t odata;
897 unsigned int firstoffset, endoffset;
900 * Make 'target' refer to the 'n' labels including and following
901 * 'first' in 'source'.
904 REQUIRE(VALID_NAME(source));
905 REQUIRE(VALID_NAME(target));
906 REQUIRE(first <= source->labels);
907 REQUIRE(first + n <= source->labels);
908 REQUIRE(BINDABLE(target));
910 SETUP_OFFSETS(source, offsets, odata);
912 if (first == source->labels)
913 firstoffset = source->length;
914 else
915 firstoffset = offsets[first];
917 if (first + n == source->labels)
918 endoffset = source->length;
919 else
920 endoffset = offsets[first + n];
922 target->ndata = &source->ndata[firstoffset];
923 target->length = endoffset - firstoffset;
925 if (first + n == source->labels && n > 0 &&
926 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
927 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
928 else
929 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
931 target->labels = n;
934 * If source and target are the same, and we're making target
935 * a prefix of source, the offsets table is correct already
936 * so we don't need to call set_offsets().
938 if (target->offsets != NULL &&
939 (target != source || first != 0))
940 set_offsets(target, target->offsets, NULL);
943 void
944 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
947 * Make 'target' refer to the same name as 'source'.
950 REQUIRE(VALID_NAME(source));
951 REQUIRE(VALID_NAME(target));
952 REQUIRE(BINDABLE(target));
954 target->ndata = source->ndata;
955 target->length = source->length;
956 target->labels = source->labels;
957 target->attributes = source->attributes &
958 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
959 DNS_NAMEATTR_DYNOFFSETS);
960 if (target->offsets != NULL && source->labels > 0) {
961 if (source->offsets != NULL)
962 memcpy(target->offsets, source->offsets,
963 source->labels);
964 else
965 set_offsets(target, target->offsets, NULL);
969 void
970 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
971 unsigned char *offsets;
972 dns_offsets_t odata;
973 unsigned int len;
974 isc_region_t r2;
977 * Make 'name' refer to region 'r'.
980 REQUIRE(VALID_NAME(name));
981 REQUIRE(r != NULL);
982 REQUIRE(BINDABLE(name));
984 INIT_OFFSETS(name, offsets, odata);
986 if (name->buffer != NULL) {
987 isc_buffer_clear(name->buffer);
988 isc_buffer_availableregion(name->buffer, &r2);
989 len = (r->length < r2.length) ? r->length : r2.length;
990 if (len > DNS_NAME_MAXWIRE)
991 len = DNS_NAME_MAXWIRE;
992 memcpy(r2.base, r->base, len);
993 name->ndata = r2.base;
994 name->length = len;
995 } else {
996 name->ndata = r->base;
997 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
998 r->length : DNS_NAME_MAXWIRE;
1001 if (r->length > 0)
1002 set_offsets(name, offsets, name);
1003 else {
1004 name->labels = 0;
1005 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1008 if (name->buffer != NULL)
1009 isc_buffer_add(name->buffer, name->length);
1012 void
1013 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1015 * Make 'r' refer to 'name'.
1018 REQUIRE(VALID_NAME(name));
1019 REQUIRE(r != NULL);
1021 DNS_NAME_TOREGION(name, r);
1024 isc_result_t
1025 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1026 dns_name_t *origin, unsigned int options,
1027 isc_buffer_t *target)
1029 unsigned char *ndata, *label;
1030 char *tdata;
1031 char c;
1032 ft_state state;
1033 unsigned int value, count;
1034 unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
1035 isc_boolean_t done;
1036 unsigned char *offsets;
1037 dns_offsets_t odata;
1038 isc_boolean_t downcase;
1041 * Convert the textual representation of a DNS name at source
1042 * into uncompressed wire form stored in target.
1044 * Notes:
1045 * Relative domain names will have 'origin' appended to them
1046 * unless 'origin' is NULL, in which case relative domain names
1047 * will remain relative.
1050 REQUIRE(VALID_NAME(name));
1051 REQUIRE(ISC_BUFFER_VALID(source));
1052 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1053 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1055 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1057 if (target == NULL && name->buffer != NULL) {
1058 target = name->buffer;
1059 isc_buffer_clear(target);
1062 REQUIRE(BINDABLE(name));
1064 INIT_OFFSETS(name, offsets, odata);
1065 offsets[0] = 0;
1068 * Initialize things to make the compiler happy; they're not required.
1070 n1 = 0;
1071 n2 = 0;
1072 label = NULL;
1073 digits = 0;
1074 value = 0;
1075 count = 0;
1078 * Make 'name' empty in case of failure.
1080 MAKE_EMPTY(name);
1083 * Set up the state machine.
1085 tdata = (char *)source->base + source->current;
1086 tlen = isc_buffer_remaininglength(source);
1087 tused = 0;
1088 ndata = isc_buffer_used(target);
1089 nrem = isc_buffer_availablelength(target);
1090 if (nrem > 255)
1091 nrem = 255;
1092 nused = 0;
1093 labels = 0;
1094 done = ISC_FALSE;
1095 state = ft_init;
1097 while (nrem > 0 && tlen > 0 && !done) {
1098 c = *tdata++;
1099 tlen--;
1100 tused++;
1102 switch (state) {
1103 case ft_init:
1105 * Is this the root name?
1107 if (c == '.') {
1108 if (tlen != 0)
1109 return (DNS_R_EMPTYLABEL);
1110 labels++;
1111 *ndata++ = 0;
1112 nrem--;
1113 nused++;
1114 done = ISC_TRUE;
1115 break;
1117 if (c == '@' && tlen == 0) {
1118 state = ft_at;
1119 break;
1122 /* FALLTHROUGH */
1123 case ft_start:
1124 label = ndata;
1125 ndata++;
1126 nrem--;
1127 nused++;
1128 count = 0;
1129 if (c == '\\') {
1130 state = ft_initialescape;
1131 break;
1133 state = ft_ordinary;
1134 if (nrem == 0)
1135 return (ISC_R_NOSPACE);
1136 /* FALLTHROUGH */
1137 case ft_ordinary:
1138 if (c == '.') {
1139 if (count == 0)
1140 return (DNS_R_EMPTYLABEL);
1141 *label = count;
1142 labels++;
1143 INSIST(labels <= 127);
1144 offsets[labels] = nused;
1145 if (tlen == 0) {
1146 labels++;
1147 *ndata++ = 0;
1148 nrem--;
1149 nused++;
1150 done = ISC_TRUE;
1152 state = ft_start;
1153 } else if (c == '\\') {
1154 state = ft_escape;
1155 } else {
1156 if (count >= 63)
1157 return (DNS_R_LABELTOOLONG);
1158 count++;
1159 CONVERTTOASCII(c);
1160 if (downcase)
1161 c = maptolower[(int)c];
1162 *ndata++ = c;
1163 nrem--;
1164 nused++;
1166 break;
1167 case ft_initialescape:
1168 if (c == '[') {
1170 * This looks like a bitstring label, which
1171 * was deprecated. Intentionally drop it.
1173 return (DNS_R_BADLABELTYPE);
1175 state = ft_escape;
1176 /* FALLTHROUGH */
1177 case ft_escape:
1178 if (!isdigit(c & 0xff)) {
1179 if (count >= 63)
1180 return (DNS_R_LABELTOOLONG);
1181 count++;
1182 CONVERTTOASCII(c);
1183 if (downcase)
1184 c = maptolower[(int)c];
1185 *ndata++ = c;
1186 nrem--;
1187 nused++;
1188 state = ft_ordinary;
1189 break;
1191 digits = 0;
1192 value = 0;
1193 state = ft_escdecimal;
1194 /* FALLTHROUGH */
1195 case ft_escdecimal:
1196 if (!isdigit(c & 0xff))
1197 return (DNS_R_BADESCAPE);
1198 value *= 10;
1199 value += digitvalue[(int)c];
1200 digits++;
1201 if (digits == 3) {
1202 if (value > 255)
1203 return (DNS_R_BADESCAPE);
1204 if (count >= 63)
1205 return (DNS_R_LABELTOOLONG);
1206 count++;
1207 if (downcase)
1208 value = maptolower[value];
1209 *ndata++ = value;
1210 nrem--;
1211 nused++;
1212 state = ft_ordinary;
1214 break;
1215 default:
1216 FATAL_ERROR(__FILE__, __LINE__,
1217 "Unexpected state %d", state);
1218 /* Does not return. */
1222 if (!done) {
1223 if (nrem == 0)
1224 return (ISC_R_NOSPACE);
1225 INSIST(tlen == 0);
1226 if (state != ft_ordinary && state != ft_at)
1227 return (ISC_R_UNEXPECTEDEND);
1228 if (state == ft_ordinary) {
1229 INSIST(count != 0);
1230 *label = count;
1231 labels++;
1232 INSIST(labels <= 127);
1233 offsets[labels] = nused;
1235 if (origin != NULL) {
1236 if (nrem < origin->length)
1237 return (ISC_R_NOSPACE);
1238 label = origin->ndata;
1239 n1 = origin->length;
1240 nrem -= n1;
1241 while (n1 > 0) {
1242 n2 = *label++;
1243 INSIST(n2 <= 63); /* no bitstring support */
1244 *ndata++ = n2;
1245 n1 -= n2 + 1;
1246 nused += n2 + 1;
1247 while (n2 > 0) {
1248 c = *label++;
1249 if (downcase)
1250 c = maptolower[(int)c];
1251 *ndata++ = c;
1252 n2--;
1254 labels++;
1255 if (n1 > 0) {
1256 INSIST(labels <= 127);
1257 offsets[labels] = nused;
1260 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1261 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1263 } else
1264 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1266 name->ndata = (unsigned char *)target->base + target->used;
1267 name->labels = labels;
1268 name->length = nused;
1270 isc_buffer_forward(source, tused);
1271 isc_buffer_add(target, name->length);
1273 return (ISC_R_SUCCESS);
1276 #ifdef ISC_PLATFORM_USETHREADS
1277 static void
1278 free_specific(void *arg) {
1279 dns_name_totextfilter_t *mem = arg;
1280 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1281 /* Stop use being called again. */
1282 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1285 static void
1286 thread_key_mutex_init(void) {
1287 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1290 static isc_result_t
1291 totext_filter_proc_key_init(void) {
1292 isc_result_t result;
1295 * We need the call to isc_once_do() to support profiled mutex
1296 * otherwise thread_key_mutex could be initialized at compile time.
1298 result = isc_once_do(&once, thread_key_mutex_init);
1299 if (result != ISC_R_SUCCESS)
1300 return (result);
1302 if (!thread_key_initialized) {
1303 LOCK(&thread_key_mutex);
1304 if (thread_key_mctx == NULL)
1305 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1306 if (result != ISC_R_SUCCESS)
1307 goto unlock;
1308 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1309 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1311 if (!thread_key_initialized &&
1312 isc_thread_key_create(&totext_filter_proc_key,
1313 free_specific) != 0) {
1314 result = ISC_R_FAILURE;
1315 isc_mem_detach(&thread_key_mctx);
1316 } else
1317 thread_key_initialized = 1;
1318 unlock:
1319 UNLOCK(&thread_key_mutex);
1321 return (result);
1323 #endif
1325 isc_result_t
1326 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1327 isc_buffer_t *target)
1329 unsigned char *ndata;
1330 char *tdata;
1331 unsigned int nlen, tlen;
1332 unsigned char c;
1333 unsigned int trem, count;
1334 unsigned int labels;
1335 isc_boolean_t saw_root = ISC_FALSE;
1336 unsigned int oused = target->used;
1337 #ifdef ISC_PLATFORM_USETHREADS
1338 dns_name_totextfilter_t *mem;
1339 dns_name_totextfilter_t totext_filter_proc = NULL;
1340 isc_result_t result;
1341 #endif
1344 * This function assumes the name is in proper uncompressed
1345 * wire format.
1347 REQUIRE(VALID_NAME(name));
1348 REQUIRE(ISC_BUFFER_VALID(target));
1350 #ifdef ISC_PLATFORM_USETHREADS
1351 result = totext_filter_proc_key_init();
1352 if (result != ISC_R_SUCCESS)
1353 return (result);
1354 #endif
1355 ndata = name->ndata;
1356 nlen = name->length;
1357 labels = name->labels;
1358 tdata = isc_buffer_used(target);
1359 tlen = isc_buffer_availablelength(target);
1361 trem = tlen;
1363 if (labels == 0 && nlen == 0) {
1365 * Special handling for an empty name.
1367 if (trem == 0)
1368 return (ISC_R_NOSPACE);
1371 * The names of these booleans are misleading in this case.
1372 * This empty name is not necessarily from the root node of
1373 * the DNS root zone, nor is a final dot going to be included.
1374 * They need to be set this way, though, to keep the "@"
1375 * from being trounced.
1377 saw_root = ISC_TRUE;
1378 omit_final_dot = ISC_FALSE;
1379 *tdata++ = '@';
1380 trem--;
1383 * Skip the while() loop.
1385 nlen = 0;
1386 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1388 * Special handling for the root label.
1390 if (trem == 0)
1391 return (ISC_R_NOSPACE);
1393 saw_root = ISC_TRUE;
1394 omit_final_dot = ISC_FALSE;
1395 *tdata++ = '.';
1396 trem--;
1399 * Skip the while() loop.
1401 nlen = 0;
1404 while (labels > 0 && nlen > 0 && trem > 0) {
1405 labels--;
1406 count = *ndata++;
1407 nlen--;
1408 if (count == 0) {
1409 saw_root = ISC_TRUE;
1410 break;
1412 if (count < 64) {
1413 INSIST(nlen >= count);
1414 while (count > 0) {
1415 c = *ndata;
1416 switch (c) {
1417 case 0x22: /* '"' */
1418 case 0x28: /* '(' */
1419 case 0x29: /* ')' */
1420 case 0x2E: /* '.' */
1421 case 0x3B: /* ';' */
1422 case 0x5C: /* '\\' */
1423 /* Special modifiers in zone files. */
1424 case 0x40: /* '@' */
1425 case 0x24: /* '$' */
1426 if (trem < 2)
1427 return (ISC_R_NOSPACE);
1428 *tdata++ = '\\';
1429 CONVERTFROMASCII(c);
1430 *tdata++ = c;
1431 ndata++;
1432 trem -= 2;
1433 nlen--;
1434 break;
1435 default:
1436 if (c > 0x20 && c < 0x7f) {
1437 if (trem == 0)
1438 return (ISC_R_NOSPACE);
1439 CONVERTFROMASCII(c);
1440 *tdata++ = c;
1441 ndata++;
1442 trem--;
1443 nlen--;
1444 } else {
1445 if (trem < 4)
1446 return (ISC_R_NOSPACE);
1447 *tdata++ = 0x5c;
1448 *tdata++ = 0x30 +
1449 ((c / 100) % 10);
1450 *tdata++ = 0x30 +
1451 ((c / 10) % 10);
1452 *tdata++ = 0x30 + (c % 10);
1453 trem -= 4;
1454 ndata++;
1455 nlen--;
1458 count--;
1460 } else {
1461 FATAL_ERROR(__FILE__, __LINE__,
1462 "Unexpected label type %02x", count);
1463 /* NOTREACHED */
1467 * The following assumes names are absolute. If not, we
1468 * fix things up later. Note that this means that in some
1469 * cases one more byte of text buffer is required than is
1470 * needed in the final output.
1472 if (trem == 0)
1473 return (ISC_R_NOSPACE);
1474 *tdata++ = '.';
1475 trem--;
1478 if (nlen != 0 && trem == 0)
1479 return (ISC_R_NOSPACE);
1481 if (!saw_root || omit_final_dot)
1482 trem++;
1484 isc_buffer_add(target, tlen - trem);
1486 #ifdef ISC_PLATFORM_USETHREADS
1487 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1488 if (mem != NULL)
1489 totext_filter_proc = *mem;
1490 #endif
1491 if (totext_filter_proc != NULL)
1492 return ((*totext_filter_proc)(target, oused, saw_root));
1494 return (ISC_R_SUCCESS);
1497 isc_result_t
1498 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1499 isc_buffer_t *target)
1501 unsigned char *ndata;
1502 char *tdata;
1503 unsigned int nlen, tlen;
1504 unsigned char c;
1505 unsigned int trem, count;
1506 unsigned int labels;
1509 * This function assumes the name is in proper uncompressed
1510 * wire format.
1512 REQUIRE(VALID_NAME(name));
1513 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1514 REQUIRE(ISC_BUFFER_VALID(target));
1516 ndata = name->ndata;
1517 nlen = name->length;
1518 labels = name->labels;
1519 tdata = isc_buffer_used(target);
1520 tlen = isc_buffer_availablelength(target);
1522 trem = tlen;
1524 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1526 * Special handling for the root label.
1528 if (trem == 0)
1529 return (ISC_R_NOSPACE);
1531 omit_final_dot = ISC_FALSE;
1532 *tdata++ = '.';
1533 trem--;
1536 * Skip the while() loop.
1538 nlen = 0;
1541 while (labels > 0 && nlen > 0 && trem > 0) {
1542 labels--;
1543 count = *ndata++;
1544 nlen--;
1545 if (count == 0)
1546 break;
1547 if (count < 64) {
1548 INSIST(nlen >= count);
1549 while (count > 0) {
1550 c = *ndata;
1551 if ((c >= 0x30 && c <= 0x39) || /* digit */
1552 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1553 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1554 c == 0x2D || /* hyphen */
1555 c == 0x5F) /* underscore */
1557 if (trem == 0)
1558 return (ISC_R_NOSPACE);
1559 /* downcase */
1560 if (c >= 0x41 && c <= 0x5A)
1561 c += 0x20;
1562 CONVERTFROMASCII(c);
1563 *tdata++ = c;
1564 ndata++;
1565 trem--;
1566 nlen--;
1567 } else {
1568 if (trem < 3)
1569 return (ISC_R_NOSPACE);
1570 sprintf(tdata, "%%%02X", c);
1571 tdata += 3;
1572 trem -= 3;
1573 ndata++;
1574 nlen--;
1576 count--;
1578 } else {
1579 FATAL_ERROR(__FILE__, __LINE__,
1580 "Unexpected label type %02x", count);
1581 /* NOTREACHED */
1585 * The following assumes names are absolute. If not, we
1586 * fix things up later. Note that this means that in some
1587 * cases one more byte of text buffer is required than is
1588 * needed in the final output.
1590 if (trem == 0)
1591 return (ISC_R_NOSPACE);
1592 *tdata++ = '.';
1593 trem--;
1596 if (nlen != 0 && trem == 0)
1597 return (ISC_R_NOSPACE);
1599 if (omit_final_dot)
1600 trem++;
1602 isc_buffer_add(target, tlen - trem);
1604 return (ISC_R_SUCCESS);
1607 isc_result_t
1608 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1609 unsigned char *sndata, *ndata;
1610 unsigned int nlen, count, labels;
1611 isc_buffer_t buffer;
1614 * Downcase 'source'.
1617 REQUIRE(VALID_NAME(source));
1618 REQUIRE(VALID_NAME(name));
1619 if (source == name) {
1620 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1621 isc_buffer_init(&buffer, source->ndata, source->length);
1622 target = &buffer;
1623 ndata = source->ndata;
1624 } else {
1625 REQUIRE(BINDABLE(name));
1626 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1627 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1628 if (target == NULL) {
1629 target = name->buffer;
1630 isc_buffer_clear(name->buffer);
1632 ndata = (unsigned char *)target->base + target->used;
1633 name->ndata = ndata;
1636 sndata = source->ndata;
1637 nlen = source->length;
1638 labels = source->labels;
1640 if (nlen > (target->length - target->used)) {
1641 MAKE_EMPTY(name);
1642 return (ISC_R_NOSPACE);
1645 while (labels > 0 && nlen > 0) {
1646 labels--;
1647 count = *sndata++;
1648 *ndata++ = count;
1649 nlen--;
1650 if (count < 64) {
1651 INSIST(nlen >= count);
1652 while (count > 0) {
1653 *ndata++ = maptolower[(*sndata++)];
1654 nlen--;
1655 count--;
1657 } else {
1658 FATAL_ERROR(__FILE__, __LINE__,
1659 "Unexpected label type %02x", count);
1660 /* Does not return. */
1664 if (source != name) {
1665 name->labels = source->labels;
1666 name->length = source->length;
1667 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1668 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1669 else
1670 name->attributes = 0;
1671 if (name->labels > 0 && name->offsets != NULL)
1672 set_offsets(name, name->offsets, NULL);
1675 isc_buffer_add(target, name->length);
1677 return (ISC_R_SUCCESS);
1680 static void
1681 set_offsets(const dns_name_t *name, unsigned char *offsets,
1682 dns_name_t *set_name)
1684 unsigned int offset, count, length, nlabels;
1685 unsigned char *ndata;
1686 isc_boolean_t absolute;
1688 ndata = name->ndata;
1689 length = name->length;
1690 offset = 0;
1691 nlabels = 0;
1692 absolute = ISC_FALSE;
1693 while (offset != length) {
1694 INSIST(nlabels < 128);
1695 offsets[nlabels++] = offset;
1696 count = *ndata++;
1697 offset++;
1698 INSIST(count <= 63);
1699 offset += count;
1700 ndata += count;
1701 INSIST(offset <= length);
1702 if (count == 0) {
1703 absolute = ISC_TRUE;
1704 break;
1707 if (set_name != NULL) {
1708 INSIST(set_name == name);
1710 set_name->labels = nlabels;
1711 set_name->length = offset;
1712 if (absolute)
1713 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1714 else
1715 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1717 INSIST(nlabels == name->labels);
1718 INSIST(offset == name->length);
1721 isc_result_t
1722 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1723 dns_decompress_t *dctx, unsigned int options,
1724 isc_buffer_t *target)
1726 unsigned char *cdata, *ndata;
1727 unsigned int cused; /* Bytes of compressed name data used */
1728 unsigned int nused, labels, n, nmax;
1729 unsigned int current, new_current, biggest_pointer;
1730 isc_boolean_t done;
1731 fw_state state = fw_start;
1732 unsigned int c;
1733 unsigned char *offsets;
1734 dns_offsets_t odata;
1735 isc_boolean_t downcase;
1736 isc_boolean_t seen_pointer;
1739 * Copy the possibly-compressed name at source into target,
1740 * decompressing it. Loop prevention is performed by checking
1741 * the new pointer against biggest_pointer.
1744 REQUIRE(VALID_NAME(name));
1745 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1746 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1748 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1750 if (target == NULL && name->buffer != NULL) {
1751 target = name->buffer;
1752 isc_buffer_clear(target);
1755 REQUIRE(dctx != NULL);
1756 REQUIRE(BINDABLE(name));
1758 INIT_OFFSETS(name, offsets, odata);
1761 * Make 'name' empty in case of failure.
1763 MAKE_EMPTY(name);
1766 * Initialize things to make the compiler happy; they're not required.
1768 n = 0;
1769 new_current = 0;
1772 * Set up.
1774 labels = 0;
1775 done = ISC_FALSE;
1777 ndata = isc_buffer_used(target);
1778 nused = 0;
1779 seen_pointer = ISC_FALSE;
1782 * Find the maximum number of uncompressed target name
1783 * bytes we are willing to generate. This is the smaller
1784 * of the available target buffer length and the
1785 * maximum legal domain name length (255).
1787 nmax = isc_buffer_availablelength(target);
1788 if (nmax > DNS_NAME_MAXWIRE)
1789 nmax = DNS_NAME_MAXWIRE;
1791 cdata = isc_buffer_current(source);
1792 cused = 0;
1794 current = source->current;
1795 biggest_pointer = current;
1798 * Note: The following code is not optimized for speed, but
1799 * rather for correctness. Speed will be addressed in the future.
1802 while (current < source->active && !done) {
1803 c = *cdata++;
1804 current++;
1805 if (!seen_pointer)
1806 cused++;
1808 switch (state) {
1809 case fw_start:
1810 if (c < 64) {
1811 offsets[labels] = nused;
1812 labels++;
1813 if (nused + c + 1 > nmax)
1814 goto full;
1815 nused += c + 1;
1816 *ndata++ = c;
1817 if (c == 0)
1818 done = ISC_TRUE;
1819 n = c;
1820 state = fw_ordinary;
1821 } else if (c >= 128 && c < 192) {
1823 * 14 bit local compression pointer.
1824 * Local compression is no longer an
1825 * IETF draft.
1827 return (DNS_R_BADLABELTYPE);
1828 } else if (c >= 192) {
1830 * Ordinary 14-bit pointer.
1832 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1834 return (DNS_R_DISALLOWED);
1835 new_current = c & 0x3F;
1836 n = 1;
1837 state = fw_newcurrent;
1838 } else
1839 return (DNS_R_BADLABELTYPE);
1840 break;
1841 case fw_ordinary:
1842 if (downcase)
1843 c = maptolower[c];
1844 /* FALLTHROUGH */
1845 case fw_copy:
1846 *ndata++ = c;
1847 n--;
1848 if (n == 0)
1849 state = fw_start;
1850 break;
1851 case fw_newcurrent:
1852 new_current *= 256;
1853 new_current += c;
1854 n--;
1855 if (n != 0)
1856 break;
1857 if (new_current >= biggest_pointer)
1858 return (DNS_R_BADPOINTER);
1859 biggest_pointer = new_current;
1860 current = new_current;
1861 cdata = (unsigned char *)source->base + current;
1862 seen_pointer = ISC_TRUE;
1863 state = fw_start;
1864 break;
1865 default:
1866 FATAL_ERROR(__FILE__, __LINE__,
1867 "Unknown state %d", state);
1868 /* Does not return. */
1872 if (!done)
1873 return (ISC_R_UNEXPECTEDEND);
1875 name->ndata = (unsigned char *)target->base + target->used;
1876 name->labels = labels;
1877 name->length = nused;
1878 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1880 isc_buffer_forward(source, cused);
1881 isc_buffer_add(target, name->length);
1883 return (ISC_R_SUCCESS);
1885 full:
1886 if (nmax == DNS_NAME_MAXWIRE)
1888 * The name did not fit even though we had a buffer
1889 * big enough to fit a maximum-length name.
1891 return (DNS_R_NAMETOOLONG);
1892 else
1894 * The name might fit if only the caller could give us a
1895 * big enough buffer.
1897 return (ISC_R_NOSPACE);
1900 isc_result_t
1901 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1902 isc_buffer_t *target)
1904 unsigned int methods;
1905 isc_uint16_t offset;
1906 dns_name_t gp; /* Global compression prefix */
1907 isc_boolean_t gf; /* Global compression target found */
1908 isc_uint16_t go; /* Global compression offset */
1909 dns_offsets_t clo;
1910 dns_name_t clname;
1913 * Convert 'name' into wire format, compressing it as specified by the
1914 * compression context 'cctx', and storing the result in 'target'.
1917 REQUIRE(VALID_NAME(name));
1918 REQUIRE(cctx != NULL);
1919 REQUIRE(ISC_BUFFER_VALID(target));
1922 * If 'name' doesn't have an offsets table, make a clone which
1923 * has one.
1925 if (name->offsets == NULL) {
1926 DNS_NAME_INIT(&clname, clo);
1927 dns_name_clone(name, &clname);
1928 name = &clname;
1930 DNS_NAME_INIT(&gp, NULL);
1932 offset = target->used; /*XXX*/
1934 methods = dns_compress_getmethods(cctx);
1936 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1937 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1938 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1939 else
1940 gf = ISC_FALSE;
1943 * If the offset is too high for 14 bit global compression, we're
1944 * out of luck.
1946 if (gf && go >= 0x4000)
1947 gf = ISC_FALSE;
1950 * Will the compression pointer reduce the message size?
1952 if (gf && (gp.length + 2) >= name->length)
1953 gf = ISC_FALSE;
1955 if (gf) {
1956 if (target->length - target->used < gp.length)
1957 return (ISC_R_NOSPACE);
1958 (void)memcpy((unsigned char *)target->base + target->used,
1959 gp.ndata, (size_t)gp.length);
1960 isc_buffer_add(target, gp.length);
1961 go |= 0xc000;
1962 if (target->length - target->used < 2)
1963 return (ISC_R_NOSPACE);
1964 isc_buffer_putuint16(target, go);
1965 if (gp.length != 0)
1966 dns_compress_add(cctx, name, &gp, offset);
1967 } else {
1968 if (target->length - target->used < name->length)
1969 return (ISC_R_NOSPACE);
1970 (void)memcpy((unsigned char *)target->base + target->used,
1971 name->ndata, (size_t)name->length);
1972 isc_buffer_add(target, name->length);
1973 dns_compress_add(cctx, name, name, offset);
1975 return (ISC_R_SUCCESS);
1978 isc_result_t
1979 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1980 isc_buffer_t *target)
1982 unsigned char *ndata, *offsets;
1983 unsigned int nrem, labels, prefix_length, length;
1984 isc_boolean_t copy_prefix = ISC_TRUE;
1985 isc_boolean_t copy_suffix = ISC_TRUE;
1986 isc_boolean_t absolute = ISC_FALSE;
1987 dns_name_t tmp_name;
1988 dns_offsets_t odata;
1991 * Concatenate 'prefix' and 'suffix'.
1994 REQUIRE(prefix == NULL || VALID_NAME(prefix));
1995 REQUIRE(suffix == NULL || VALID_NAME(suffix));
1996 REQUIRE(name == NULL || VALID_NAME(name));
1997 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1998 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1999 if (prefix == NULL || prefix->labels == 0)
2000 copy_prefix = ISC_FALSE;
2001 if (suffix == NULL || suffix->labels == 0)
2002 copy_suffix = ISC_FALSE;
2003 if (copy_prefix &&
2004 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2005 absolute = ISC_TRUE;
2006 REQUIRE(!copy_suffix);
2008 if (name == NULL) {
2009 DNS_NAME_INIT(&tmp_name, odata);
2010 name = &tmp_name;
2012 if (target == NULL) {
2013 INSIST(name->buffer != NULL);
2014 target = name->buffer;
2015 isc_buffer_clear(name->buffer);
2018 REQUIRE(BINDABLE(name));
2021 * Set up.
2023 nrem = target->length - target->used;
2024 ndata = (unsigned char *)target->base + target->used;
2025 if (nrem > DNS_NAME_MAXWIRE)
2026 nrem = DNS_NAME_MAXWIRE;
2027 length = 0;
2028 prefix_length = 0;
2029 labels = 0;
2030 if (copy_prefix) {
2031 prefix_length = prefix->length;
2032 length += prefix_length;
2033 labels += prefix->labels;
2035 if (copy_suffix) {
2036 length += suffix->length;
2037 labels += suffix->labels;
2039 if (length > DNS_NAME_MAXWIRE) {
2040 MAKE_EMPTY(name);
2041 return (DNS_R_NAMETOOLONG);
2043 if (length > nrem) {
2044 MAKE_EMPTY(name);
2045 return (ISC_R_NOSPACE);
2048 if (copy_suffix) {
2049 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2050 absolute = ISC_TRUE;
2051 if (suffix == name && suffix->buffer == target)
2052 memmove(ndata + prefix_length, suffix->ndata,
2053 suffix->length);
2054 else
2055 memcpy(ndata + prefix_length, suffix->ndata,
2056 suffix->length);
2060 * If 'prefix' and 'name' are the same object, and the object has
2061 * a dedicated buffer, and we're using it, then we don't have to
2062 * copy anything.
2064 if (copy_prefix && (prefix != name || prefix->buffer != target))
2065 memcpy(ndata, prefix->ndata, prefix_length);
2067 name->ndata = ndata;
2068 name->labels = labels;
2069 name->length = length;
2070 if (absolute)
2071 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2072 else
2073 name->attributes = 0;
2075 if (name->labels > 0 && name->offsets != NULL) {
2076 INIT_OFFSETS(name, offsets, odata);
2077 set_offsets(name, offsets, NULL);
2080 isc_buffer_add(target, name->length);
2082 return (ISC_R_SUCCESS);
2085 void
2086 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2087 dns_name_t *prefix, dns_name_t *suffix)
2090 unsigned int splitlabel;
2092 REQUIRE(VALID_NAME(name));
2093 REQUIRE(suffixlabels > 0);
2094 REQUIRE(suffixlabels < name->labels);
2095 REQUIRE(prefix != NULL || suffix != NULL);
2096 REQUIRE(prefix == NULL ||
2097 (VALID_NAME(prefix) &&
2098 prefix->buffer != NULL &&
2099 BINDABLE(prefix)));
2100 REQUIRE(suffix == NULL ||
2101 (VALID_NAME(suffix) &&
2102 suffix->buffer != NULL &&
2103 BINDABLE(suffix)));
2105 splitlabel = name->labels - suffixlabels;
2107 if (prefix != NULL)
2108 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2110 if (suffix != NULL)
2111 dns_name_getlabelsequence(name, splitlabel,
2112 suffixlabels, suffix);
2114 return;
2117 isc_result_t
2118 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2119 dns_name_t *target)
2122 * Make 'target' a dynamically allocated copy of 'source'.
2125 REQUIRE(VALID_NAME(source));
2126 REQUIRE(source->length > 0);
2127 REQUIRE(VALID_NAME(target));
2128 REQUIRE(BINDABLE(target));
2131 * Make 'target' empty in case of failure.
2133 MAKE_EMPTY(target);
2135 target->ndata = isc_mem_get(mctx, source->length);
2136 if (target->ndata == NULL)
2137 return (ISC_R_NOMEMORY);
2139 memcpy(target->ndata, source->ndata, source->length);
2141 target->length = source->length;
2142 target->labels = source->labels;
2143 target->attributes = DNS_NAMEATTR_DYNAMIC;
2144 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2145 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2146 if (target->offsets != NULL) {
2147 if (source->offsets != NULL)
2148 memcpy(target->offsets, source->offsets,
2149 source->labels);
2150 else
2151 set_offsets(target, target->offsets, NULL);
2154 return (ISC_R_SUCCESS);
2157 isc_result_t
2158 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2159 dns_name_t *target)
2162 * Make 'target' a read-only dynamically allocated copy of 'source'.
2163 * 'target' will also have a dynamically allocated offsets table.
2166 REQUIRE(VALID_NAME(source));
2167 REQUIRE(source->length > 0);
2168 REQUIRE(VALID_NAME(target));
2169 REQUIRE(BINDABLE(target));
2170 REQUIRE(target->offsets == NULL);
2173 * Make 'target' empty in case of failure.
2175 MAKE_EMPTY(target);
2177 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2178 if (target->ndata == NULL)
2179 return (ISC_R_NOMEMORY);
2181 memcpy(target->ndata, source->ndata, source->length);
2183 target->length = source->length;
2184 target->labels = source->labels;
2185 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2186 DNS_NAMEATTR_READONLY;
2187 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2188 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2189 target->offsets = target->ndata + source->length;
2190 if (source->offsets != NULL)
2191 memcpy(target->offsets, source->offsets, source->labels);
2192 else
2193 set_offsets(target, target->offsets, NULL);
2195 return (ISC_R_SUCCESS);
2198 void
2199 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2200 size_t size;
2203 * Free 'name'.
2206 REQUIRE(VALID_NAME(name));
2207 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2209 size = name->length;
2210 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2211 size += name->labels;
2212 isc_mem_put(mctx, name->ndata, size);
2213 dns_name_invalidate(name);
2216 isc_result_t
2217 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2218 dns_name_t downname;
2219 unsigned char data[256];
2220 isc_buffer_t buffer;
2221 isc_result_t result;
2222 isc_region_t r;
2225 * Send 'name' in DNSSEC canonical form to 'digest'.
2228 REQUIRE(VALID_NAME(name));
2229 REQUIRE(digest != NULL);
2231 DNS_NAME_INIT(&downname, NULL);
2232 isc_buffer_init(&buffer, data, sizeof(data));
2234 result = dns_name_downcase(name, &downname, &buffer);
2235 if (result != ISC_R_SUCCESS)
2236 return (result);
2238 isc_buffer_usedregion(&buffer, &r);
2240 return ((digest)(arg, &r));
2243 isc_boolean_t
2244 dns_name_dynamic(dns_name_t *name) {
2245 REQUIRE(VALID_NAME(name));
2248 * Returns whether there is dynamic memory associated with this name.
2251 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2252 ISC_TRUE : ISC_FALSE);
2255 isc_result_t
2256 dns_name_print(dns_name_t *name, FILE *stream) {
2257 isc_result_t result;
2258 isc_buffer_t b;
2259 isc_region_t r;
2260 char t[1024];
2263 * Print 'name' on 'stream'.
2266 REQUIRE(VALID_NAME(name));
2268 isc_buffer_init(&b, t, sizeof(t));
2269 result = dns_name_totext(name, ISC_FALSE, &b);
2270 if (result != ISC_R_SUCCESS)
2271 return (result);
2272 isc_buffer_usedregion(&b, &r);
2273 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2275 return (ISC_R_SUCCESS);
2278 isc_result_t
2279 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2280 #ifdef ISC_PLATFORM_USETHREADS
2281 isc_result_t result;
2282 dns_name_totextfilter_t *mem;
2283 int res;
2285 result = totext_filter_proc_key_init();
2286 if (result != ISC_R_SUCCESS)
2287 return (result);
2290 * If we already have been here set / clear as appropriate.
2291 * Otherwise allocate memory.
2293 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2294 if (mem != NULL && proc != NULL) {
2295 *mem = proc;
2296 return (ISC_R_SUCCESS);
2298 if (proc == NULL) {
2299 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2300 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2301 if (res != 0)
2302 result = ISC_R_UNEXPECTED;
2303 return (result);
2306 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2307 if (mem == NULL)
2308 return (ISC_R_NOMEMORY);
2309 *mem = proc;
2310 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2311 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2312 result = ISC_R_UNEXPECTED;
2314 return (result);
2315 #else
2316 totext_filter_proc = proc;
2317 return (ISC_R_SUCCESS);
2318 #endif
2321 void
2322 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2323 isc_result_t result;
2324 isc_buffer_t buf;
2326 REQUIRE(size > 0);
2329 * Leave room for null termination after buffer.
2331 isc_buffer_init(&buf, cp, size - 1);
2332 result = dns_name_totext(name, ISC_TRUE, &buf);
2333 if (result == ISC_R_SUCCESS) {
2335 * Null terminate.
2337 isc_region_t r;
2338 isc_buffer_usedregion(&buf, &r);
2339 ((char *) r.base)[r.length] = '\0';
2341 } else
2342 snprintf(cp, size, "<unknown>");
2346 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2347 * memory.
2349 isc_result_t
2350 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2351 isc_result_t result;
2352 isc_buffer_t buf;
2353 isc_region_t reg;
2354 char *p, txt[DNS_NAME_FORMATSIZE];
2356 REQUIRE(VALID_NAME(name));
2357 REQUIRE(target != NULL && *target == NULL);
2359 isc_buffer_init(&buf, txt, sizeof(txt));
2360 result = dns_name_totext(name, ISC_FALSE, &buf);
2361 if (result != ISC_R_SUCCESS)
2362 return (result);
2364 isc_buffer_usedregion(&buf, &reg);
2365 p = isc_mem_allocate(mctx, reg.length + 1);
2366 memcpy(p, (char *) reg.base, (int) reg.length);
2367 p[reg.length] = '\0';
2369 *target = p;
2370 return (ISC_R_SUCCESS);
2374 * dns_name_fromstring() -- convert directly from a string to a name,
2375 * allocating memory as needed
2377 isc_result_t
2378 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2379 isc_mem_t *mctx)
2381 isc_result_t result;
2382 isc_buffer_t buf;
2383 dns_fixedname_t fn;
2384 dns_name_t *name;
2386 REQUIRE(src != NULL);
2388 isc_buffer_init(&buf, src, strlen(src));
2389 isc_buffer_add(&buf, strlen(src));
2390 dns_fixedname_init(&fn);
2391 name = dns_fixedname_name(&fn);
2393 result = dns_name_fromtext(name, &buf, dns_rootname, options, NULL);
2394 if (result != ISC_R_SUCCESS)
2395 return (result);
2397 result = dns_name_dup(name, mctx, target);
2398 return (result);
2401 isc_result_t
2402 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2403 unsigned char *ndata;
2406 * Make dest a copy of source.
2409 REQUIRE(VALID_NAME(source));
2410 REQUIRE(VALID_NAME(dest));
2411 REQUIRE(target != NULL || dest->buffer != NULL);
2413 if (target == NULL) {
2414 target = dest->buffer;
2415 isc_buffer_clear(dest->buffer);
2418 REQUIRE(BINDABLE(dest));
2421 * Set up.
2423 if (target->length - target->used < source->length)
2424 return (ISC_R_NOSPACE);
2426 ndata = (unsigned char *)target->base + target->used;
2427 dest->ndata = target->base;
2429 memcpy(ndata, source->ndata, source->length);
2431 dest->ndata = ndata;
2432 dest->labels = source->labels;
2433 dest->length = source->length;
2434 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2435 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2436 else
2437 dest->attributes = 0;
2439 if (dest->labels > 0 && dest->offsets != NULL) {
2440 if (source->offsets != NULL)
2441 memcpy(dest->offsets, source->offsets, source->labels);
2442 else
2443 set_offsets(dest, dest->offsets, NULL);
2446 isc_buffer_add(target, dest->length);
2448 return (ISC_R_SUCCESS);
2451 void
2452 dns_name_destroy(void) {
2453 #ifdef ISC_PLATFORM_USETHREADS
2454 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2455 == ISC_R_SUCCESS);
2457 LOCK(&thread_key_mutex);
2458 if (thread_key_initialized) {
2459 isc_mem_detach(&thread_key_mctx);
2460 isc_thread_key_delete(totext_filter_proc_key);
2461 thread_key_initialized = 0;
2463 UNLOCK(&thread_key_mutex);
2465 #endif