2 * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: name.c,v 1.165.120.3 2010-07-09 05:15:05 each 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(n <= source->labels - first); /* note first+n could overflow */
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_setname(thread_key_mctx, "threadkey", NULL);
1307 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1309 if (!thread_key_initialized &&
1310 isc_thread_key_create(&totext_filter_proc_key,
1311 free_specific) != 0) {
1312 result = ISC_R_FAILURE;
1313 isc_mem_detach(&thread_key_mctx);
1315 thread_key_initialized = 1;
1317 UNLOCK(&thread_key_mutex);
1324 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1325 isc_buffer_t *target)
1327 unsigned int options = DNS_NAME_MASTERFILE;
1330 options |= DNS_NAME_OMITFINALDOT;
1331 return (dns_name_totext2(name, options, target));
1335 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1336 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1340 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1342 unsigned char *ndata;
1344 unsigned int nlen, tlen;
1346 unsigned int trem, count;
1347 unsigned int labels;
1348 isc_boolean_t saw_root = ISC_FALSE;
1349 unsigned int oused = target->used;
1350 #ifdef ISC_PLATFORM_USETHREADS
1351 dns_name_totextfilter_t *mem;
1352 dns_name_totextfilter_t totext_filter_proc = NULL;
1353 isc_result_t result;
1355 isc_boolean_t omit_final_dot =
1356 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1359 * This function assumes the name is in proper uncompressed
1362 REQUIRE(VALID_NAME(name));
1363 REQUIRE(ISC_BUFFER_VALID(target));
1365 #ifdef ISC_PLATFORM_USETHREADS
1366 result = totext_filter_proc_key_init();
1367 if (result != ISC_R_SUCCESS)
1370 ndata = name->ndata;
1371 nlen = name->length;
1372 labels = name->labels;
1373 tdata = isc_buffer_used(target);
1374 tlen = isc_buffer_availablelength(target);
1378 if (labels == 0 && nlen == 0) {
1380 * Special handling for an empty name.
1383 return (ISC_R_NOSPACE);
1386 * The names of these booleans are misleading in this case.
1387 * This empty name is not necessarily from the root node of
1388 * the DNS root zone, nor is a final dot going to be included.
1389 * They need to be set this way, though, to keep the "@"
1390 * from being trounced.
1392 saw_root = ISC_TRUE;
1393 omit_final_dot = ISC_FALSE;
1398 * Skip the while() loop.
1401 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1403 * Special handling for the root label.
1406 return (ISC_R_NOSPACE);
1408 saw_root = ISC_TRUE;
1409 omit_final_dot = ISC_FALSE;
1414 * Skip the while() loop.
1419 while (labels > 0 && nlen > 0 && trem > 0) {
1424 saw_root = ISC_TRUE;
1428 INSIST(nlen >= count);
1432 /* Special modifiers in zone files. */
1433 case 0x40: /* '@' */
1434 case 0x24: /* '$' */
1435 if ((options & DNS_NAME_MASTERFILE) == 0)
1437 case 0x22: /* '"' */
1438 case 0x28: /* '(' */
1439 case 0x29: /* ')' */
1440 case 0x2E: /* '.' */
1441 case 0x3B: /* ';' */
1442 case 0x5C: /* '\\' */
1444 return (ISC_R_NOSPACE);
1446 CONVERTFROMASCII(c);
1454 if (c > 0x20 && c < 0x7f) {
1456 return (ISC_R_NOSPACE);
1457 CONVERTFROMASCII(c);
1464 return (ISC_R_NOSPACE);
1470 *tdata++ = 0x30 + (c % 10);
1479 FATAL_ERROR(__FILE__, __LINE__,
1480 "Unexpected label type %02x", count);
1485 * The following assumes names are absolute. If not, we
1486 * fix things up later. Note that this means that in some
1487 * cases one more byte of text buffer is required than is
1488 * needed in the final output.
1491 return (ISC_R_NOSPACE);
1496 if (nlen != 0 && trem == 0)
1497 return (ISC_R_NOSPACE);
1499 if (!saw_root || omit_final_dot)
1502 isc_buffer_add(target, tlen - trem);
1504 #ifdef ISC_PLATFORM_USETHREADS
1505 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1507 totext_filter_proc = *mem;
1509 if (totext_filter_proc != NULL)
1510 return ((*totext_filter_proc)(target, oused, saw_root));
1512 return (ISC_R_SUCCESS);
1516 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1517 isc_buffer_t *target)
1519 unsigned char *ndata;
1521 unsigned int nlen, tlen;
1523 unsigned int trem, count;
1524 unsigned int labels;
1527 * This function assumes the name is in proper uncompressed
1530 REQUIRE(VALID_NAME(name));
1531 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1532 REQUIRE(ISC_BUFFER_VALID(target));
1534 ndata = name->ndata;
1535 nlen = name->length;
1536 labels = name->labels;
1537 tdata = isc_buffer_used(target);
1538 tlen = isc_buffer_availablelength(target);
1542 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1544 * Special handling for the root label.
1547 return (ISC_R_NOSPACE);
1549 omit_final_dot = ISC_FALSE;
1554 * Skip the while() loop.
1559 while (labels > 0 && nlen > 0 && trem > 0) {
1566 INSIST(nlen >= count);
1569 if ((c >= 0x30 && c <= 0x39) || /* digit */
1570 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1571 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1572 c == 0x2D || /* hyphen */
1573 c == 0x5F) /* underscore */
1576 return (ISC_R_NOSPACE);
1578 if (c >= 0x41 && c <= 0x5A)
1580 CONVERTFROMASCII(c);
1587 return (ISC_R_NOSPACE);
1588 sprintf(tdata, "%%%02X", c);
1597 FATAL_ERROR(__FILE__, __LINE__,
1598 "Unexpected label type %02x", count);
1603 * The following assumes names are absolute. If not, we
1604 * fix things up later. Note that this means that in some
1605 * cases one more byte of text buffer is required than is
1606 * needed in the final output.
1609 return (ISC_R_NOSPACE);
1614 if (nlen != 0 && trem == 0)
1615 return (ISC_R_NOSPACE);
1620 isc_buffer_add(target, tlen - trem);
1622 return (ISC_R_SUCCESS);
1626 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1627 unsigned char *sndata, *ndata;
1628 unsigned int nlen, count, labels;
1629 isc_buffer_t buffer;
1632 * Downcase 'source'.
1635 REQUIRE(VALID_NAME(source));
1636 REQUIRE(VALID_NAME(name));
1637 if (source == name) {
1638 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1639 isc_buffer_init(&buffer, source->ndata, source->length);
1641 ndata = source->ndata;
1643 REQUIRE(BINDABLE(name));
1644 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1645 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1646 if (target == NULL) {
1647 target = name->buffer;
1648 isc_buffer_clear(name->buffer);
1650 ndata = (unsigned char *)target->base + target->used;
1651 name->ndata = ndata;
1654 sndata = source->ndata;
1655 nlen = source->length;
1656 labels = source->labels;
1658 if (nlen > (target->length - target->used)) {
1660 return (ISC_R_NOSPACE);
1663 while (labels > 0 && nlen > 0) {
1669 INSIST(nlen >= count);
1671 *ndata++ = maptolower[(*sndata++)];
1676 FATAL_ERROR(__FILE__, __LINE__,
1677 "Unexpected label type %02x", count);
1678 /* Does not return. */
1682 if (source != name) {
1683 name->labels = source->labels;
1684 name->length = source->length;
1685 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1686 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1688 name->attributes = 0;
1689 if (name->labels > 0 && name->offsets != NULL)
1690 set_offsets(name, name->offsets, NULL);
1693 isc_buffer_add(target, name->length);
1695 return (ISC_R_SUCCESS);
1699 set_offsets(const dns_name_t *name, unsigned char *offsets,
1700 dns_name_t *set_name)
1702 unsigned int offset, count, length, nlabels;
1703 unsigned char *ndata;
1704 isc_boolean_t absolute;
1706 ndata = name->ndata;
1707 length = name->length;
1710 absolute = ISC_FALSE;
1711 while (offset != length) {
1712 INSIST(nlabels < 128);
1713 offsets[nlabels++] = offset;
1716 INSIST(count <= 63);
1719 INSIST(offset <= length);
1721 absolute = ISC_TRUE;
1725 if (set_name != NULL) {
1726 INSIST(set_name == name);
1728 set_name->labels = nlabels;
1729 set_name->length = offset;
1731 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1733 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1735 INSIST(nlabels == name->labels);
1736 INSIST(offset == name->length);
1740 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1741 dns_decompress_t *dctx, unsigned int options,
1742 isc_buffer_t *target)
1744 unsigned char *cdata, *ndata;
1745 unsigned int cused; /* Bytes of compressed name data used */
1746 unsigned int nused, labels, n, nmax;
1747 unsigned int current, new_current, biggest_pointer;
1749 fw_state state = fw_start;
1751 unsigned char *offsets;
1752 dns_offsets_t odata;
1753 isc_boolean_t downcase;
1754 isc_boolean_t seen_pointer;
1757 * Copy the possibly-compressed name at source into target,
1758 * decompressing it. Loop prevention is performed by checking
1759 * the new pointer against biggest_pointer.
1762 REQUIRE(VALID_NAME(name));
1763 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1764 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1766 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1768 if (target == NULL && name->buffer != NULL) {
1769 target = name->buffer;
1770 isc_buffer_clear(target);
1773 REQUIRE(dctx != NULL);
1774 REQUIRE(BINDABLE(name));
1776 INIT_OFFSETS(name, offsets, odata);
1779 * Make 'name' empty in case of failure.
1784 * Initialize things to make the compiler happy; they're not required.
1795 ndata = isc_buffer_used(target);
1797 seen_pointer = ISC_FALSE;
1800 * Find the maximum number of uncompressed target name
1801 * bytes we are willing to generate. This is the smaller
1802 * of the available target buffer length and the
1803 * maximum legal domain name length (255).
1805 nmax = isc_buffer_availablelength(target);
1806 if (nmax > DNS_NAME_MAXWIRE)
1807 nmax = DNS_NAME_MAXWIRE;
1809 cdata = isc_buffer_current(source);
1812 current = source->current;
1813 biggest_pointer = current;
1816 * Note: The following code is not optimized for speed, but
1817 * rather for correctness. Speed will be addressed in the future.
1820 while (current < source->active && !done) {
1829 offsets[labels] = nused;
1831 if (nused + c + 1 > nmax)
1838 state = fw_ordinary;
1839 } else if (c >= 128 && c < 192) {
1841 * 14 bit local compression pointer.
1842 * Local compression is no longer an
1845 return (DNS_R_BADLABELTYPE);
1846 } else if (c >= 192) {
1848 * Ordinary 14-bit pointer.
1850 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1852 return (DNS_R_DISALLOWED);
1853 new_current = c & 0x3F;
1855 state = fw_newcurrent;
1857 return (DNS_R_BADLABELTYPE);
1875 if (new_current >= biggest_pointer)
1876 return (DNS_R_BADPOINTER);
1877 biggest_pointer = new_current;
1878 current = new_current;
1879 cdata = (unsigned char *)source->base + current;
1880 seen_pointer = ISC_TRUE;
1884 FATAL_ERROR(__FILE__, __LINE__,
1885 "Unknown state %d", state);
1886 /* Does not return. */
1891 return (ISC_R_UNEXPECTEDEND);
1893 name->ndata = (unsigned char *)target->base + target->used;
1894 name->labels = labels;
1895 name->length = nused;
1896 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1898 isc_buffer_forward(source, cused);
1899 isc_buffer_add(target, name->length);
1901 return (ISC_R_SUCCESS);
1904 if (nmax == DNS_NAME_MAXWIRE)
1906 * The name did not fit even though we had a buffer
1907 * big enough to fit a maximum-length name.
1909 return (DNS_R_NAMETOOLONG);
1912 * The name might fit if only the caller could give us a
1913 * big enough buffer.
1915 return (ISC_R_NOSPACE);
1919 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1920 isc_buffer_t *target)
1922 unsigned int methods;
1923 isc_uint16_t offset;
1924 dns_name_t gp; /* Global compression prefix */
1925 isc_boolean_t gf; /* Global compression target found */
1926 isc_uint16_t go; /* Global compression offset */
1931 * Convert 'name' into wire format, compressing it as specified by the
1932 * compression context 'cctx', and storing the result in 'target'.
1935 REQUIRE(VALID_NAME(name));
1936 REQUIRE(cctx != NULL);
1937 REQUIRE(ISC_BUFFER_VALID(target));
1940 * If 'name' doesn't have an offsets table, make a clone which
1943 if (name->offsets == NULL) {
1944 DNS_NAME_INIT(&clname, clo);
1945 dns_name_clone(name, &clname);
1948 DNS_NAME_INIT(&gp, NULL);
1950 offset = target->used; /*XXX*/
1952 methods = dns_compress_getmethods(cctx);
1954 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1955 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1956 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1961 * If the offset is too high for 14 bit global compression, we're
1964 if (gf && go >= 0x4000)
1968 * Will the compression pointer reduce the message size?
1970 if (gf && (gp.length + 2) >= name->length)
1974 if (target->length - target->used < gp.length)
1975 return (ISC_R_NOSPACE);
1976 (void)memcpy((unsigned char *)target->base + target->used,
1977 gp.ndata, (size_t)gp.length);
1978 isc_buffer_add(target, gp.length);
1980 if (target->length - target->used < 2)
1981 return (ISC_R_NOSPACE);
1982 isc_buffer_putuint16(target, go);
1984 dns_compress_add(cctx, name, &gp, offset);
1986 if (target->length - target->used < name->length)
1987 return (ISC_R_NOSPACE);
1988 (void)memcpy((unsigned char *)target->base + target->used,
1989 name->ndata, (size_t)name->length);
1990 isc_buffer_add(target, name->length);
1991 dns_compress_add(cctx, name, name, offset);
1993 return (ISC_R_SUCCESS);
1997 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1998 isc_buffer_t *target)
2000 unsigned char *ndata, *offsets;
2001 unsigned int nrem, labels, prefix_length, length;
2002 isc_boolean_t copy_prefix = ISC_TRUE;
2003 isc_boolean_t copy_suffix = ISC_TRUE;
2004 isc_boolean_t absolute = ISC_FALSE;
2005 dns_name_t tmp_name;
2006 dns_offsets_t odata;
2009 * Concatenate 'prefix' and 'suffix'.
2012 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2013 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2014 REQUIRE(name == NULL || VALID_NAME(name));
2015 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2016 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2017 if (prefix == NULL || prefix->labels == 0)
2018 copy_prefix = ISC_FALSE;
2019 if (suffix == NULL || suffix->labels == 0)
2020 copy_suffix = ISC_FALSE;
2022 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2023 absolute = ISC_TRUE;
2024 REQUIRE(!copy_suffix);
2027 DNS_NAME_INIT(&tmp_name, odata);
2030 if (target == NULL) {
2031 INSIST(name->buffer != NULL);
2032 target = name->buffer;
2033 isc_buffer_clear(name->buffer);
2036 REQUIRE(BINDABLE(name));
2041 nrem = target->length - target->used;
2042 ndata = (unsigned char *)target->base + target->used;
2043 if (nrem > DNS_NAME_MAXWIRE)
2044 nrem = DNS_NAME_MAXWIRE;
2049 prefix_length = prefix->length;
2050 length += prefix_length;
2051 labels += prefix->labels;
2054 length += suffix->length;
2055 labels += suffix->labels;
2057 if (length > DNS_NAME_MAXWIRE) {
2059 return (DNS_R_NAMETOOLONG);
2061 if (length > nrem) {
2063 return (ISC_R_NOSPACE);
2067 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2068 absolute = ISC_TRUE;
2069 if (suffix == name && suffix->buffer == target)
2070 memmove(ndata + prefix_length, suffix->ndata,
2073 memcpy(ndata + prefix_length, suffix->ndata,
2078 * If 'prefix' and 'name' are the same object, and the object has
2079 * a dedicated buffer, and we're using it, then we don't have to
2082 if (copy_prefix && (prefix != name || prefix->buffer != target))
2083 memcpy(ndata, prefix->ndata, prefix_length);
2085 name->ndata = ndata;
2086 name->labels = labels;
2087 name->length = length;
2089 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2091 name->attributes = 0;
2093 if (name->labels > 0 && name->offsets != NULL) {
2094 INIT_OFFSETS(name, offsets, odata);
2095 set_offsets(name, offsets, NULL);
2098 isc_buffer_add(target, name->length);
2100 return (ISC_R_SUCCESS);
2104 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2105 dns_name_t *prefix, dns_name_t *suffix)
2108 unsigned int splitlabel;
2110 REQUIRE(VALID_NAME(name));
2111 REQUIRE(suffixlabels > 0);
2112 REQUIRE(suffixlabels < name->labels);
2113 REQUIRE(prefix != NULL || suffix != NULL);
2114 REQUIRE(prefix == NULL ||
2115 (VALID_NAME(prefix) &&
2116 prefix->buffer != NULL &&
2118 REQUIRE(suffix == NULL ||
2119 (VALID_NAME(suffix) &&
2120 suffix->buffer != NULL &&
2123 splitlabel = name->labels - suffixlabels;
2126 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2129 dns_name_getlabelsequence(name, splitlabel,
2130 suffixlabels, suffix);
2136 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2140 * Make 'target' a dynamically allocated copy of 'source'.
2143 REQUIRE(VALID_NAME(source));
2144 REQUIRE(source->length > 0);
2145 REQUIRE(VALID_NAME(target));
2146 REQUIRE(BINDABLE(target));
2149 * Make 'target' empty in case of failure.
2153 target->ndata = isc_mem_get(mctx, source->length);
2154 if (target->ndata == NULL)
2155 return (ISC_R_NOMEMORY);
2157 memcpy(target->ndata, source->ndata, source->length);
2159 target->length = source->length;
2160 target->labels = source->labels;
2161 target->attributes = DNS_NAMEATTR_DYNAMIC;
2162 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2163 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2164 if (target->offsets != NULL) {
2165 if (source->offsets != NULL)
2166 memcpy(target->offsets, source->offsets,
2169 set_offsets(target, target->offsets, NULL);
2172 return (ISC_R_SUCCESS);
2176 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2180 * Make 'target' a read-only dynamically allocated copy of 'source'.
2181 * 'target' will also have a dynamically allocated offsets table.
2184 REQUIRE(VALID_NAME(source));
2185 REQUIRE(source->length > 0);
2186 REQUIRE(VALID_NAME(target));
2187 REQUIRE(BINDABLE(target));
2188 REQUIRE(target->offsets == NULL);
2191 * Make 'target' empty in case of failure.
2195 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2196 if (target->ndata == NULL)
2197 return (ISC_R_NOMEMORY);
2199 memcpy(target->ndata, source->ndata, source->length);
2201 target->length = source->length;
2202 target->labels = source->labels;
2203 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2204 DNS_NAMEATTR_READONLY;
2205 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2206 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2207 target->offsets = target->ndata + source->length;
2208 if (source->offsets != NULL)
2209 memcpy(target->offsets, source->offsets, source->labels);
2211 set_offsets(target, target->offsets, NULL);
2213 return (ISC_R_SUCCESS);
2217 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2224 REQUIRE(VALID_NAME(name));
2225 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2227 size = name->length;
2228 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2229 size += name->labels;
2230 isc_mem_put(mctx, name->ndata, size);
2231 dns_name_invalidate(name);
2235 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2236 dns_name_t downname;
2237 unsigned char data[256];
2238 isc_buffer_t buffer;
2239 isc_result_t result;
2243 * Send 'name' in DNSSEC canonical form to 'digest'.
2246 REQUIRE(VALID_NAME(name));
2247 REQUIRE(digest != NULL);
2249 DNS_NAME_INIT(&downname, NULL);
2250 isc_buffer_init(&buffer, data, sizeof(data));
2252 result = dns_name_downcase(name, &downname, &buffer);
2253 if (result != ISC_R_SUCCESS)
2256 isc_buffer_usedregion(&buffer, &r);
2258 return ((digest)(arg, &r));
2262 dns_name_dynamic(dns_name_t *name) {
2263 REQUIRE(VALID_NAME(name));
2266 * Returns whether there is dynamic memory associated with this name.
2269 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2270 ISC_TRUE : ISC_FALSE);
2274 dns_name_print(dns_name_t *name, FILE *stream) {
2275 isc_result_t result;
2281 * Print 'name' on 'stream'.
2284 REQUIRE(VALID_NAME(name));
2286 isc_buffer_init(&b, t, sizeof(t));
2287 result = dns_name_totext(name, ISC_FALSE, &b);
2288 if (result != ISC_R_SUCCESS)
2290 isc_buffer_usedregion(&b, &r);
2291 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2293 return (ISC_R_SUCCESS);
2297 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2298 #ifdef ISC_PLATFORM_USETHREADS
2299 isc_result_t result;
2300 dns_name_totextfilter_t *mem;
2303 result = totext_filter_proc_key_init();
2304 if (result != ISC_R_SUCCESS)
2308 * If we already have been here set / clear as appropriate.
2309 * Otherwise allocate memory.
2311 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2312 if (mem != NULL && proc != NULL) {
2314 return (ISC_R_SUCCESS);
2317 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2318 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2320 result = ISC_R_UNEXPECTED;
2324 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2326 return (ISC_R_NOMEMORY);
2328 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2329 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2330 result = ISC_R_UNEXPECTED;
2334 totext_filter_proc = proc;
2335 return (ISC_R_SUCCESS);
2340 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2341 isc_result_t result;
2347 * Leave room for null termination after buffer.
2349 isc_buffer_init(&buf, cp, size - 1);
2350 result = dns_name_totext(name, ISC_TRUE, &buf);
2351 if (result == ISC_R_SUCCESS) {
2356 isc_buffer_usedregion(&buf, &r);
2357 ((char *) r.base)[r.length] = '\0';
2360 snprintf(cp, size, "<unknown>");
2364 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2365 unsigned char *ndata;
2368 * Make dest a copy of source.
2371 REQUIRE(VALID_NAME(source));
2372 REQUIRE(VALID_NAME(dest));
2373 REQUIRE(target != NULL || dest->buffer != NULL);
2375 if (target == NULL) {
2376 target = dest->buffer;
2377 isc_buffer_clear(dest->buffer);
2380 REQUIRE(BINDABLE(dest));
2385 if (target->length - target->used < source->length)
2386 return (ISC_R_NOSPACE);
2388 ndata = (unsigned char *)target->base + target->used;
2389 dest->ndata = target->base;
2391 memcpy(ndata, source->ndata, source->length);
2393 dest->ndata = ndata;
2394 dest->labels = source->labels;
2395 dest->length = source->length;
2396 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2397 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2399 dest->attributes = 0;
2401 if (dest->labels > 0 && dest->offsets != NULL) {
2402 if (source->offsets != NULL)
2403 memcpy(dest->offsets, source->offsets, source->labels);
2405 set_offsets(dest, dest->offsets, NULL);
2408 isc_buffer_add(target, dest->length);
2410 return (ISC_R_SUCCESS);
2414 dns_name_destroy(void) {
2415 #ifdef ISC_PLATFORM_USETHREADS
2416 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2419 LOCK(&thread_key_mutex);
2420 if (thread_key_initialized) {
2421 isc_mem_detach(&thread_key_mctx);
2422 isc_thread_key_delete(totext_filter_proc_key);
2423 thread_key_initialized = 0;
2425 UNLOCK(&thread_key_mutex);