2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.144.18.16 2006/12/07 07:03:10 marka Exp $ */
27 #include <isc/buffer.h>
31 #include <isc/print.h>
32 #include <isc/string.h>
33 #include <isc/thread.h>
36 #include <dns/compress.h>
38 #include <dns/result.h>
40 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
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; \
122 #define SETUP_OFFSETS(name, var, default) \
123 if (name->offsets != NULL) \
124 var = name->offsets; \
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) \
136 name->ndata = NULL; \
139 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
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)) \
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 =
162 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
164 {(void *)-1, (void *)-1},
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 =
178 DNS_NAMEATTR_READONLY,
180 {(void *)-1, (void *)-1},
184 /* XXXDCL make const? */
185 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
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;
200 static dns_name_totextfilter_t totext_filter_proc = NULL;
204 set_offsets(const dns_name_t *name, unsigned char *offsets,
205 dns_name_t *set_name);
208 dns_name_init(dns_name_t *name, unsigned char *offsets) {
212 DNS_NAME_INIT(name, offsets);
216 dns_name_reset(dns_name_t *name) {
217 REQUIRE(VALID_NAME(name));
218 REQUIRE(BINDABLE(name));
220 DNS_NAME_RESET(name);
224 dns_name_invalidate(dns_name_t *name) {
226 * Make 'name' invalid.
229 REQUIRE(VALID_NAME(name));
235 name->attributes = 0;
236 name->offsets = NULL;
238 ISC_LINK_INIT(name, link);
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) ||
251 name->buffer = buffer;
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)
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)
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)
292 dns_name_ismailbox(const dns_name_t *name) {
293 unsigned char *ndata, ch;
297 REQUIRE(VALID_NAME(name));
298 REQUIRE(name->labels > 0);
299 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
304 if (name->length == 1)
316 if (ndata == name->ndata + name->length)
320 * RFC292/RFC1123 hostname.
322 while (ndata < (name->ndata + name->length)) {
328 if (first || n == 0) {
342 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
343 unsigned char *ndata, ch;
347 REQUIRE(VALID_NAME(name));
348 REQUIRE(name->labels > 0);
349 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
354 if (name->length == 1)
358 * Skip wildcard if this is a ownername.
361 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
365 * RFC292/RFC1123 hostname.
367 while (ndata < (name->ndata + name->length)) {
373 if (first || n == 0) {
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) {
399 if (ndata[0] == 1 && ndata[1] == '*')
407 dns_name_internalwildcard(const dns_name_t *name) {
408 unsigned char *ndata;
413 * Does 'name' contain a internal wildcard?
416 REQUIRE(VALID_NAME(name));
417 REQUIRE(name->labels > 0);
428 * Check all but the last of the remaining labels.
430 while (label + 1 < name->labels) {
433 if (count == 1 && *ndata == '*')
441 static inline unsigned int
442 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
444 const unsigned char *s;
448 length = name->length;
453 * This hash function is similar to the one Ousterhout
457 if (case_sensitive) {
459 h += ( h << 3 ) + *s;
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)
485 return (name_hash(name, case_sensitive));
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)
498 return (isc_hash_calc((const unsigned char *)name->ndata,
499 name->length, case_sensitive));
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
509 REQUIRE(VALID_NAME(name));
511 return (dns_name_fullhash(name, case_sensitive));
515 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
516 unsigned char *offsets;
523 * Provide a hash value for 'name'.
525 REQUIRE(VALID_NAME(name));
527 if (name->labels == 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);
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];
541 tname.length = offsets[i + 1] - offsets[i];
542 h += name_hash(&tname, case_sensitive);
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
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);
586 ldiff = (int)l1 - (int)l2;
596 label1 = &name1->ndata[offsets1[l1]];
597 label2 = &name2->ndata[offsets2[l2]];
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;
614 chdiff = (int)maptolower[*label1] -
615 (int)maptolower[*label2];
633 namereln = dns_namereln_contains;
635 namereln = dns_namereln_subdomain;
637 namereln = dns_namereln_equal;
642 if (nlabels > 0 && namereln == dns_namereln_none)
643 namereln = dns_namereln_commonancestor;
649 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
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
663 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
669 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
670 unsigned int l, count;
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
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)
696 if (l != name2->labels)
699 label1 = name1->ndata;
700 label2 = name2->ndata;
704 if (count != *label2++)
707 INSIST(count <= 63); /* no bitstring support */
711 c = maptolower[*label1++];
712 if (c != maptolower[*label2++])
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
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)
743 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
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);
769 l = (l1 < l2) ? l1 : l2;
771 label1 = name1->ndata;
772 label2 = name2->ndata;
778 /* no bitstring support */
779 INSIST(count1 <= 63 && count2 <= 63);
781 if (count1 != count2)
782 return ((count1 < count2) ? -1 : 1);
786 c1 = maptolower[*label1++];
787 c2 = maptolower[*label2++];
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.
808 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
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
822 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
823 if (namereln == dns_namereln_subdomain ||
824 namereln == dns_namereln_equal)
831 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
833 unsigned int nlabels, labels;
836 REQUIRE(VALID_NAME(name));
837 REQUIRE(name->labels > 0);
838 REQUIRE(VALID_NAME(wname));
839 labels = wname->labels;
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)
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);
865 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
866 unsigned char *offsets;
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];
884 label->length = offsets[n + 1] - offsets[n];
888 dns_name_getlabelsequence(const dns_name_t *source,
889 unsigned int first, unsigned int n,
892 unsigned char *offsets;
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;
912 firstoffset = offsets[first];
914 if (first + n == source->labels)
915 endoffset = source->length;
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;
926 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
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);
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,
962 set_offsets(target, target->offsets, NULL);
967 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
968 unsigned char *offsets;
974 * Make 'name' refer to region 'r'.
977 REQUIRE(VALID_NAME(name));
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;
993 name->ndata = r->base;
994 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
995 r->length : DNS_NAME_MAXWIRE;
999 set_offsets(name, offsets, name);
1002 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1005 if (name->buffer != NULL)
1006 isc_buffer_add(name->buffer, name->length);
1010 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1012 * Make 'r' refer to 'name'.
1015 REQUIRE(VALID_NAME(name));
1018 DNS_NAME_TOREGION(name, r);
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;
1031 unsigned int value, count;
1032 unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
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.
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);
1066 * Initialize things to make the compiler happy; they're not required.
1076 * Make 'name' empty in case of failure.
1081 * Set up the state machine.
1083 tdata = (char *)source->base + source->current;
1084 tlen = isc_buffer_remaininglength(source);
1086 ndata = isc_buffer_used(target);
1087 nrem = isc_buffer_availablelength(target);
1095 while (nrem > 0 && tlen > 0 && !done) {
1103 * Is this the root name?
1107 return (DNS_R_EMPTYLABEL);
1115 if (c == '@' && tlen == 0) {
1128 state = ft_initialescape;
1131 state = ft_ordinary;
1133 return (ISC_R_NOSPACE);
1138 return (DNS_R_EMPTYLABEL);
1141 INSIST(labels <= 127);
1142 offsets[labels] = nused;
1151 } else if (c == '\\') {
1155 return (DNS_R_LABELTOOLONG);
1159 c = maptolower[(int)c];
1165 case ft_initialescape:
1168 * This looks like a bitstring label, which
1169 * was deprecated. Intentionally drop it.
1171 return (DNS_R_BADLABELTYPE);
1176 if (!isdigit(c & 0xff)) {
1178 return (DNS_R_LABELTOOLONG);
1182 c = maptolower[(int)c];
1186 state = ft_ordinary;
1191 state = ft_escdecimal;
1194 if (!isdigit(c & 0xff))
1195 return (DNS_R_BADESCAPE);
1197 value += digitvalue[(int)c];
1201 return (DNS_R_BADESCAPE);
1203 return (DNS_R_LABELTOOLONG);
1206 value = maptolower[value];
1210 state = ft_ordinary;
1214 FATAL_ERROR(__FILE__, __LINE__,
1215 "Unexpected state %d", state);
1216 /* Does not return. */
1222 return (ISC_R_NOSPACE);
1224 if (state != ft_ordinary && state != ft_at)
1225 return (ISC_R_UNEXPECTEDEND);
1226 if (state == ft_ordinary) {
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;
1241 INSIST(n2 <= 63); /* no bitstring support */
1248 c = maptolower[(int)c];
1254 INSIST(labels <= 127);
1255 offsets[labels] = nused;
1258 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1259 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
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
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);
1284 thread_key_mutex_init(void) {
1285 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
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)
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)
1306 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1308 if (!thread_key_initialized &&
1309 isc_thread_key_create(&totext_filter_proc_key,
1310 free_specific) != 0) {
1311 result = ISC_R_FAILURE;
1312 isc_mem_detach(&thread_key_mctx);
1314 thread_key_initialized = 1;
1316 UNLOCK(&thread_key_mutex);
1323 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1324 isc_buffer_t *target)
1326 unsigned char *ndata;
1328 unsigned int nlen, tlen;
1330 unsigned int trem, count;
1331 unsigned int labels;
1332 isc_boolean_t saw_root = ISC_FALSE;
1333 unsigned int oused = target->used;
1334 #ifdef ISC_PLATFORM_USETHREADS
1335 dns_name_totextfilter_t *mem;
1336 dns_name_totextfilter_t totext_filter_proc = NULL;
1337 isc_result_t result;
1341 * This function assumes the name is in proper uncompressed
1344 REQUIRE(VALID_NAME(name));
1345 REQUIRE(ISC_BUFFER_VALID(target));
1347 #ifdef ISC_PLATFORM_USETHREADS
1348 result = totext_filter_proc_key_init();
1349 if (result != ISC_R_SUCCESS)
1352 ndata = name->ndata;
1353 nlen = name->length;
1354 labels = name->labels;
1355 tdata = isc_buffer_used(target);
1356 tlen = isc_buffer_availablelength(target);
1360 if (labels == 0 && nlen == 0) {
1362 * Special handling for an empty name.
1365 return (ISC_R_NOSPACE);
1368 * The names of these booleans are misleading in this case.
1369 * This empty name is not necessarily from the root node of
1370 * the DNS root zone, nor is a final dot going to be included.
1371 * They need to be set this way, though, to keep the "@"
1372 * from being trounced.
1374 saw_root = ISC_TRUE;
1375 omit_final_dot = ISC_FALSE;
1380 * Skip the while() loop.
1383 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1385 * Special handling for the root label.
1388 return (ISC_R_NOSPACE);
1390 saw_root = ISC_TRUE;
1391 omit_final_dot = ISC_FALSE;
1396 * Skip the while() loop.
1401 while (labels > 0 && nlen > 0 && trem > 0) {
1406 saw_root = ISC_TRUE;
1410 INSIST(nlen >= count);
1414 case 0x22: /* '"' */
1415 case 0x28: /* '(' */
1416 case 0x29: /* ')' */
1417 case 0x2E: /* '.' */
1418 case 0x3B: /* ';' */
1419 case 0x5C: /* '\\' */
1420 /* Special modifiers in zone files. */
1421 case 0x40: /* '@' */
1422 case 0x24: /* '$' */
1424 return (ISC_R_NOSPACE);
1426 CONVERTFROMASCII(c);
1433 if (c > 0x20 && c < 0x7f) {
1435 return (ISC_R_NOSPACE);
1436 CONVERTFROMASCII(c);
1443 return (ISC_R_NOSPACE);
1449 *tdata++ = 0x30 + (c % 10);
1458 FATAL_ERROR(__FILE__, __LINE__,
1459 "Unexpected label type %02x", count);
1464 * The following assumes names are absolute. If not, we
1465 * fix things up later. Note that this means that in some
1466 * cases one more byte of text buffer is required than is
1467 * needed in the final output.
1470 return (ISC_R_NOSPACE);
1475 if (nlen != 0 && trem == 0)
1476 return (ISC_R_NOSPACE);
1478 if (!saw_root || omit_final_dot)
1481 isc_buffer_add(target, tlen - trem);
1483 #ifdef ISC_PLATFORM_USETHREADS
1484 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1486 totext_filter_proc = *mem;
1488 if (totext_filter_proc != NULL)
1489 return ((*totext_filter_proc)(target, oused, saw_root));
1491 return (ISC_R_SUCCESS);
1495 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1496 isc_buffer_t *target)
1498 unsigned char *ndata;
1500 unsigned int nlen, tlen;
1502 unsigned int trem, count;
1503 unsigned int labels;
1506 * This function assumes the name is in proper uncompressed
1509 REQUIRE(VALID_NAME(name));
1510 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1511 REQUIRE(ISC_BUFFER_VALID(target));
1513 ndata = name->ndata;
1514 nlen = name->length;
1515 labels = name->labels;
1516 tdata = isc_buffer_used(target);
1517 tlen = isc_buffer_availablelength(target);
1521 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1523 * Special handling for the root label.
1526 return (ISC_R_NOSPACE);
1528 omit_final_dot = ISC_FALSE;
1533 * Skip the while() loop.
1538 while (labels > 0 && nlen > 0 && trem > 0) {
1545 INSIST(nlen >= count);
1548 if ((c >= 0x30 && c <= 0x39) || /* digit */
1549 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1550 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1551 c == 0x2D || /* hyphen */
1552 c == 0x5F) /* underscore */
1555 return (ISC_R_NOSPACE);
1557 if (c >= 0x41 && c <= 0x5A)
1559 CONVERTFROMASCII(c);
1566 return (ISC_R_NOSPACE);
1567 sprintf(tdata, "%%%02X", c);
1576 FATAL_ERROR(__FILE__, __LINE__,
1577 "Unexpected label type %02x", count);
1582 * The following assumes names are absolute. If not, we
1583 * fix things up later. Note that this means that in some
1584 * cases one more byte of text buffer is required than is
1585 * needed in the final output.
1588 return (ISC_R_NOSPACE);
1593 if (nlen != 0 && trem == 0)
1594 return (ISC_R_NOSPACE);
1599 isc_buffer_add(target, tlen - trem);
1601 return (ISC_R_SUCCESS);
1605 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1606 unsigned char *sndata, *ndata;
1607 unsigned int nlen, count, labels;
1608 isc_buffer_t buffer;
1611 * Downcase 'source'.
1614 REQUIRE(VALID_NAME(source));
1615 REQUIRE(VALID_NAME(name));
1616 if (source == name) {
1617 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1618 isc_buffer_init(&buffer, source->ndata, source->length);
1620 ndata = source->ndata;
1622 REQUIRE(BINDABLE(name));
1623 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1624 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1625 if (target == NULL) {
1626 target = name->buffer;
1627 isc_buffer_clear(name->buffer);
1629 ndata = (unsigned char *)target->base + target->used;
1630 name->ndata = ndata;
1633 sndata = source->ndata;
1634 nlen = source->length;
1635 labels = source->labels;
1637 if (nlen > (target->length - target->used)) {
1639 return (ISC_R_NOSPACE);
1642 while (labels > 0 && nlen > 0) {
1648 INSIST(nlen >= count);
1650 *ndata++ = maptolower[(*sndata++)];
1655 FATAL_ERROR(__FILE__, __LINE__,
1656 "Unexpected label type %02x", count);
1657 /* Does not return. */
1661 if (source != name) {
1662 name->labels = source->labels;
1663 name->length = source->length;
1664 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1665 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1667 name->attributes = 0;
1668 if (name->labels > 0 && name->offsets != NULL)
1669 set_offsets(name, name->offsets, NULL);
1672 isc_buffer_add(target, name->length);
1674 return (ISC_R_SUCCESS);
1678 set_offsets(const dns_name_t *name, unsigned char *offsets,
1679 dns_name_t *set_name)
1681 unsigned int offset, count, length, nlabels;
1682 unsigned char *ndata;
1683 isc_boolean_t absolute;
1685 ndata = name->ndata;
1686 length = name->length;
1689 absolute = ISC_FALSE;
1690 while (offset != length) {
1691 INSIST(nlabels < 128);
1692 offsets[nlabels++] = offset;
1695 INSIST(count <= 63);
1698 INSIST(offset <= length);
1700 absolute = ISC_TRUE;
1704 if (set_name != NULL) {
1705 INSIST(set_name == name);
1707 set_name->labels = nlabels;
1708 set_name->length = offset;
1710 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1712 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1714 INSIST(nlabels == name->labels);
1715 INSIST(offset == name->length);
1719 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1720 dns_decompress_t *dctx, unsigned int options,
1721 isc_buffer_t *target)
1723 unsigned char *cdata, *ndata;
1724 unsigned int cused; /* Bytes of compressed name data used */
1725 unsigned int nused, labels, n, nmax;
1726 unsigned int current, new_current, biggest_pointer;
1728 fw_state state = fw_start;
1730 unsigned char *offsets;
1731 dns_offsets_t odata;
1732 isc_boolean_t downcase;
1733 isc_boolean_t seen_pointer;
1736 * Copy the possibly-compressed name at source into target,
1737 * decompressing it. Loop prevention is performed by checking
1738 * the new pointer against biggest_pointer.
1741 REQUIRE(VALID_NAME(name));
1742 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1743 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1745 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1747 if (target == NULL && name->buffer != NULL) {
1748 target = name->buffer;
1749 isc_buffer_clear(target);
1752 REQUIRE(dctx != NULL);
1753 REQUIRE(BINDABLE(name));
1755 INIT_OFFSETS(name, offsets, odata);
1758 * Make 'name' empty in case of failure.
1763 * Initialize things to make the compiler happy; they're not required.
1774 ndata = isc_buffer_used(target);
1776 seen_pointer = ISC_FALSE;
1779 * Find the maximum number of uncompressed target name
1780 * bytes we are willing to generate. This is the smaller
1781 * of the available target buffer length and the
1782 * maximum legal domain name length (255).
1784 nmax = isc_buffer_availablelength(target);
1785 if (nmax > DNS_NAME_MAXWIRE)
1786 nmax = DNS_NAME_MAXWIRE;
1788 cdata = isc_buffer_current(source);
1791 current = source->current;
1792 biggest_pointer = current;
1795 * Note: The following code is not optimized for speed, but
1796 * rather for correctness. Speed will be addressed in the future.
1799 while (current < source->active && !done) {
1808 offsets[labels] = nused;
1810 if (nused + c + 1 > nmax)
1817 state = fw_ordinary;
1818 } else if (c >= 128 && c < 192) {
1820 * 14 bit local compression pointer.
1821 * Local compression is no longer an
1824 return (DNS_R_BADLABELTYPE);
1825 } else if (c >= 192) {
1827 * Ordinary 14-bit pointer.
1829 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1831 return (DNS_R_DISALLOWED);
1832 new_current = c & 0x3F;
1834 state = fw_newcurrent;
1836 return (DNS_R_BADLABELTYPE);
1854 if (new_current >= biggest_pointer)
1855 return (DNS_R_BADPOINTER);
1856 biggest_pointer = new_current;
1857 current = new_current;
1858 cdata = (unsigned char *)source->base + current;
1859 seen_pointer = ISC_TRUE;
1863 FATAL_ERROR(__FILE__, __LINE__,
1864 "Unknown state %d", state);
1865 /* Does not return. */
1870 return (ISC_R_UNEXPECTEDEND);
1872 name->ndata = (unsigned char *)target->base + target->used;
1873 name->labels = labels;
1874 name->length = nused;
1875 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1877 isc_buffer_forward(source, cused);
1878 isc_buffer_add(target, name->length);
1880 return (ISC_R_SUCCESS);
1883 if (nmax == DNS_NAME_MAXWIRE)
1885 * The name did not fit even though we had a buffer
1886 * big enough to fit a maximum-length name.
1888 return (DNS_R_NAMETOOLONG);
1891 * The name might fit if only the caller could give us a
1892 * big enough buffer.
1894 return (ISC_R_NOSPACE);
1898 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1899 isc_buffer_t *target)
1901 unsigned int methods;
1902 isc_uint16_t offset;
1903 dns_name_t gp; /* Global compression prefix */
1904 isc_boolean_t gf; /* Global compression target found */
1905 isc_uint16_t go; /* Global compression offset */
1910 * Convert 'name' into wire format, compressing it as specified by the
1911 * compression context 'cctx', and storing the result in 'target'.
1914 REQUIRE(VALID_NAME(name));
1915 REQUIRE(cctx != NULL);
1916 REQUIRE(ISC_BUFFER_VALID(target));
1919 * If 'name' doesn't have an offsets table, make a clone which
1922 if (name->offsets == NULL) {
1923 DNS_NAME_INIT(&clname, clo);
1924 dns_name_clone(name, &clname);
1927 DNS_NAME_INIT(&gp, NULL);
1929 offset = target->used; /*XXX*/
1931 methods = dns_compress_getmethods(cctx);
1933 if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
1934 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1939 * If the offset is too high for 14 bit global compression, we're
1942 if (gf && go >= 0x4000)
1946 * Will the compression pointer reduce the message size?
1948 if (gf && (gp.length + 2) >= name->length)
1952 if (target->length - target->used < gp.length)
1953 return (ISC_R_NOSPACE);
1954 (void)memcpy((unsigned char *)target->base + target->used,
1955 gp.ndata, (size_t)gp.length);
1956 isc_buffer_add(target, gp.length);
1958 if (target->length - target->used < 2)
1959 return (ISC_R_NOSPACE);
1960 isc_buffer_putuint16(target, go);
1962 dns_compress_add(cctx, name, &gp, offset);
1964 if (target->length - target->used < name->length)
1965 return (ISC_R_NOSPACE);
1966 (void)memcpy((unsigned char *)target->base + target->used,
1967 name->ndata, (size_t)name->length);
1968 isc_buffer_add(target, name->length);
1969 dns_compress_add(cctx, name, name, offset);
1971 return (ISC_R_SUCCESS);
1975 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1976 isc_buffer_t *target)
1978 unsigned char *ndata, *offsets;
1979 unsigned int nrem, labels, prefix_length, length;
1980 isc_boolean_t copy_prefix = ISC_TRUE;
1981 isc_boolean_t copy_suffix = ISC_TRUE;
1982 isc_boolean_t absolute = ISC_FALSE;
1983 dns_name_t tmp_name;
1984 dns_offsets_t odata;
1987 * Concatenate 'prefix' and 'suffix'.
1990 REQUIRE(prefix == NULL || VALID_NAME(prefix));
1991 REQUIRE(suffix == NULL || VALID_NAME(suffix));
1992 REQUIRE(name == NULL || VALID_NAME(name));
1993 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1994 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1995 if (prefix == NULL || prefix->labels == 0)
1996 copy_prefix = ISC_FALSE;
1997 if (suffix == NULL || suffix->labels == 0)
1998 copy_suffix = ISC_FALSE;
2000 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2001 absolute = ISC_TRUE;
2002 REQUIRE(!copy_suffix);
2005 DNS_NAME_INIT(&tmp_name, odata);
2008 if (target == NULL) {
2009 INSIST(name->buffer != NULL);
2010 target = name->buffer;
2011 isc_buffer_clear(name->buffer);
2014 REQUIRE(BINDABLE(name));
2019 nrem = target->length - target->used;
2020 ndata = (unsigned char *)target->base + target->used;
2021 if (nrem > DNS_NAME_MAXWIRE)
2022 nrem = DNS_NAME_MAXWIRE;
2027 prefix_length = prefix->length;
2028 length += prefix_length;
2029 labels += prefix->labels;
2032 length += suffix->length;
2033 labels += suffix->labels;
2035 if (length > DNS_NAME_MAXWIRE) {
2037 return (DNS_R_NAMETOOLONG);
2039 if (length > nrem) {
2041 return (ISC_R_NOSPACE);
2045 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2046 absolute = ISC_TRUE;
2047 if (suffix == name && suffix->buffer == target)
2048 memmove(ndata + prefix_length, suffix->ndata,
2051 memcpy(ndata + prefix_length, suffix->ndata,
2056 * If 'prefix' and 'name' are the same object, and the object has
2057 * a dedicated buffer, and we're using it, then we don't have to
2060 if (copy_prefix && (prefix != name || prefix->buffer != target))
2061 memcpy(ndata, prefix->ndata, prefix_length);
2063 name->ndata = ndata;
2064 name->labels = labels;
2065 name->length = length;
2067 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2069 name->attributes = 0;
2071 if (name->labels > 0 && name->offsets != NULL) {
2072 INIT_OFFSETS(name, offsets, odata);
2073 set_offsets(name, offsets, NULL);
2076 isc_buffer_add(target, name->length);
2078 return (ISC_R_SUCCESS);
2082 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2083 dns_name_t *prefix, dns_name_t *suffix)
2086 unsigned int splitlabel;
2088 REQUIRE(VALID_NAME(name));
2089 REQUIRE(suffixlabels > 0);
2090 REQUIRE(suffixlabels < name->labels);
2091 REQUIRE(prefix != NULL || suffix != NULL);
2092 REQUIRE(prefix == NULL ||
2093 (VALID_NAME(prefix) &&
2094 prefix->buffer != NULL &&
2096 REQUIRE(suffix == NULL ||
2097 (VALID_NAME(suffix) &&
2098 suffix->buffer != NULL &&
2101 splitlabel = name->labels - suffixlabels;
2104 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2107 dns_name_getlabelsequence(name, splitlabel,
2108 suffixlabels, suffix);
2114 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2118 * Make 'target' a dynamically allocated copy of 'source'.
2121 REQUIRE(VALID_NAME(source));
2122 REQUIRE(source->length > 0);
2123 REQUIRE(VALID_NAME(target));
2124 REQUIRE(BINDABLE(target));
2127 * Make 'target' empty in case of failure.
2131 target->ndata = isc_mem_get(mctx, source->length);
2132 if (target->ndata == NULL)
2133 return (ISC_R_NOMEMORY);
2135 memcpy(target->ndata, source->ndata, source->length);
2137 target->length = source->length;
2138 target->labels = source->labels;
2139 target->attributes = DNS_NAMEATTR_DYNAMIC;
2140 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2141 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2142 if (target->offsets != NULL) {
2143 if (source->offsets != NULL)
2144 memcpy(target->offsets, source->offsets,
2147 set_offsets(target, target->offsets, NULL);
2150 return (ISC_R_SUCCESS);
2154 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2158 * Make 'target' a read-only dynamically allocated copy of 'source'.
2159 * 'target' will also have a dynamically allocated offsets table.
2162 REQUIRE(VALID_NAME(source));
2163 REQUIRE(source->length > 0);
2164 REQUIRE(VALID_NAME(target));
2165 REQUIRE(BINDABLE(target));
2166 REQUIRE(target->offsets == NULL);
2169 * Make 'target' empty in case of failure.
2173 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2174 if (target->ndata == NULL)
2175 return (ISC_R_NOMEMORY);
2177 memcpy(target->ndata, source->ndata, source->length);
2179 target->length = source->length;
2180 target->labels = source->labels;
2181 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2182 DNS_NAMEATTR_READONLY;
2183 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2184 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2185 target->offsets = target->ndata + source->length;
2186 if (source->offsets != NULL)
2187 memcpy(target->offsets, source->offsets, source->labels);
2189 set_offsets(target, target->offsets, NULL);
2191 return (ISC_R_SUCCESS);
2195 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2202 REQUIRE(VALID_NAME(name));
2203 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2205 size = name->length;
2206 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2207 size += name->labels;
2208 isc_mem_put(mctx, name->ndata, size);
2209 dns_name_invalidate(name);
2213 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2214 dns_name_t downname;
2215 unsigned char data[256];
2216 isc_buffer_t buffer;
2217 isc_result_t result;
2221 * Send 'name' in DNSSEC canonical form to 'digest'.
2224 REQUIRE(VALID_NAME(name));
2225 REQUIRE(digest != NULL);
2227 DNS_NAME_INIT(&downname, NULL);
2228 isc_buffer_init(&buffer, data, sizeof(data));
2230 result = dns_name_downcase(name, &downname, &buffer);
2231 if (result != ISC_R_SUCCESS)
2234 isc_buffer_usedregion(&buffer, &r);
2236 return ((digest)(arg, &r));
2240 dns_name_dynamic(dns_name_t *name) {
2241 REQUIRE(VALID_NAME(name));
2244 * Returns whether there is dynamic memory associated with this name.
2247 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2248 ISC_TRUE : ISC_FALSE);
2252 dns_name_print(dns_name_t *name, FILE *stream) {
2253 isc_result_t result;
2259 * Print 'name' on 'stream'.
2262 REQUIRE(VALID_NAME(name));
2264 isc_buffer_init(&b, t, sizeof(t));
2265 result = dns_name_totext(name, ISC_FALSE, &b);
2266 if (result != ISC_R_SUCCESS)
2268 isc_buffer_usedregion(&b, &r);
2269 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2271 return (ISC_R_SUCCESS);
2275 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2276 #ifdef ISC_PLATFORM_USETHREADS
2277 isc_result_t result;
2278 dns_name_totextfilter_t *mem;
2281 result = totext_filter_proc_key_init();
2282 if (result != ISC_R_SUCCESS)
2286 * If we already have been here set / clear as appropriate.
2287 * Otherwise allocate memory.
2289 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2290 if (mem != NULL && proc != NULL) {
2292 return (ISC_R_SUCCESS);
2295 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2296 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2298 result = ISC_R_UNEXPECTED;
2302 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2304 return (ISC_R_NOMEMORY);
2306 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2307 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2308 result = ISC_R_UNEXPECTED;
2312 totext_filter_proc = proc;
2313 return (ISC_R_SUCCESS);
2318 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2319 isc_result_t result;
2325 * Leave room for null termination after buffer.
2327 isc_buffer_init(&buf, cp, size - 1);
2328 result = dns_name_totext(name, ISC_TRUE, &buf);
2329 if (result == ISC_R_SUCCESS) {
2334 isc_buffer_usedregion(&buf, &r);
2335 ((char *) r.base)[r.length] = '\0';
2338 snprintf(cp, size, "<unknown>");
2342 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2343 unsigned char *ndata;
2346 * Make dest a copy of source.
2349 REQUIRE(VALID_NAME(source));
2350 REQUIRE(VALID_NAME(dest));
2351 REQUIRE(target != NULL || dest->buffer != NULL);
2353 if (target == NULL) {
2354 target = dest->buffer;
2355 isc_buffer_clear(dest->buffer);
2358 REQUIRE(BINDABLE(dest));
2363 if (target->length - target->used < source->length)
2364 return (ISC_R_NOSPACE);
2366 ndata = (unsigned char *)target->base + target->used;
2367 dest->ndata = target->base;
2369 memcpy(ndata, source->ndata, source->length);
2371 dest->ndata = ndata;
2372 dest->labels = source->labels;
2373 dest->length = source->length;
2374 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2375 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2377 dest->attributes = 0;
2379 if (dest->labels > 0 && dest->offsets != NULL) {
2380 if (source->offsets != NULL)
2381 memcpy(dest->offsets, source->offsets, source->labels);
2383 set_offsets(dest, dest->offsets, NULL);
2386 isc_buffer_add(target, dest->length);
2388 return (ISC_R_SUCCESS);
2392 dns_name_destroy(void) {
2393 #ifdef ISC_PLATFORM_USETHREADS
2394 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2397 LOCK(&thread_key_mutex);
2398 if (thread_key_initialized) {
2399 isc_mem_detach(&thread_key_mctx);
2400 isc_thread_key_delete(totext_filter_proc_key);
2401 thread_key_initialized = 0;
2403 UNLOCK(&thread_key_mutex);