2 * Copyright (C) 2004-2012 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.
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>
37 #include <dns/fixedname.h>
39 #include <dns/result.h>
41 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
60 static char digitvalue[256] = {
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
64 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
65 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
67 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
76 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
79 static unsigned char maptolower[] = {
80 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
81 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
82 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
83 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
84 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
85 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
86 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
87 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
88 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
89 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
90 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
91 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
92 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
93 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
94 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
95 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
96 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
97 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
98 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
99 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
100 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
101 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
102 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
103 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
104 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
105 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
106 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
107 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
108 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
109 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
110 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
111 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
114 #define CONVERTTOASCII(c)
115 #define CONVERTFROMASCII(c)
117 #define INIT_OFFSETS(name, var, default) \
118 if (name->offsets != NULL) \
119 var = name->offsets; \
123 #define SETUP_OFFSETS(name, var, default) \
124 if (name->offsets != NULL) \
125 var = name->offsets; \
128 set_offsets(name, var, NULL); \
132 * Note: If additional attributes are added that should not be set for
133 * empty names, MAKE_EMPTY() must be changed so it clears them.
135 #define MAKE_EMPTY(name) \
137 name->ndata = NULL; \
140 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
144 * A name is "bindable" if it can be set to point to a new value, i.e.
145 * name->ndata and name->length may be changed.
147 #define BINDABLE(name) \
148 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
152 * Note that the name data must be a char array, not a string
153 * literal, to avoid compiler warnings about discarding
154 * the const attribute of a string.
156 static unsigned char root_ndata[] = { '\0' };
157 static unsigned char root_offsets[] = { 0 };
159 static dns_name_t root =
163 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
165 {(void *)-1, (void *)-1},
169 /* XXXDCL make const? */
170 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
172 static unsigned char wild_ndata[] = { '\001', '*' };
173 static unsigned char wild_offsets[] = { 0 };
175 static dns_name_t wild =
179 DNS_NAMEATTR_READONLY,
181 {(void *)-1, (void *)-1},
185 /* XXXDCL make const? */
186 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
189 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
192 * dns_name_t to text post-conversion procedure.
194 #ifdef ISC_PLATFORM_USETHREADS
195 static int thread_key_initialized = 0;
196 static isc_mutex_t thread_key_mutex;
197 static isc_mem_t *thread_key_mctx = NULL;
198 static isc_thread_key_t totext_filter_proc_key;
199 static isc_once_t once = ISC_ONCE_INIT;
201 static dns_name_totextfilter_t totext_filter_proc = NULL;
205 set_offsets(const dns_name_t *name, unsigned char *offsets,
206 dns_name_t *set_name);
209 dns_name_init(dns_name_t *name, unsigned char *offsets) {
213 DNS_NAME_INIT(name, offsets);
217 dns_name_reset(dns_name_t *name) {
218 REQUIRE(VALID_NAME(name));
219 REQUIRE(BINDABLE(name));
221 DNS_NAME_RESET(name);
225 dns_name_invalidate(dns_name_t *name) {
227 * Make 'name' invalid.
230 REQUIRE(VALID_NAME(name));
236 name->attributes = 0;
237 name->offsets = NULL;
239 ISC_LINK_INIT(name, link);
243 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
245 * Dedicate a buffer for use with 'name'.
248 REQUIRE(VALID_NAME(name));
249 REQUIRE((buffer != NULL && name->buffer == NULL) ||
252 name->buffer = buffer;
256 dns_name_hasbuffer(const dns_name_t *name) {
258 * Does 'name' have a dedicated buffer?
261 REQUIRE(VALID_NAME(name));
263 if (name->buffer != NULL)
270 dns_name_isabsolute(const dns_name_t *name) {
273 * Does 'name' end in the root label?
276 REQUIRE(VALID_NAME(name));
278 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
283 #define hyphenchar(c) ((c) == 0x2d)
284 #define asterchar(c) ((c) == 0x2a)
285 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
286 || ((c) >= 0x61 && (c) <= 0x7a))
287 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
288 #define borderchar(c) (alphachar(c) || digitchar(c))
289 #define middlechar(c) (borderchar(c) || hyphenchar(c))
290 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
293 dns_name_ismailbox(const dns_name_t *name) {
294 unsigned char *ndata, ch;
298 REQUIRE(VALID_NAME(name));
299 REQUIRE(name->labels > 0);
300 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
305 if (name->length == 1)
317 if (ndata == name->ndata + name->length)
321 * RFC292/RFC1123 hostname.
323 while (ndata < (name->ndata + name->length)) {
329 if (first || n == 0) {
343 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
344 unsigned char *ndata, ch;
348 REQUIRE(VALID_NAME(name));
349 REQUIRE(name->labels > 0);
350 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
355 if (name->length == 1)
359 * Skip wildcard if this is a ownername.
362 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
366 * RFC292/RFC1123 hostname.
368 while (ndata < (name->ndata + name->length)) {
374 if (first || n == 0) {
388 dns_name_iswildcard(const dns_name_t *name) {
389 unsigned char *ndata;
392 * Is 'name' a wildcard name?
395 REQUIRE(VALID_NAME(name));
396 REQUIRE(name->labels > 0);
398 if (name->length >= 2) {
400 if (ndata[0] == 1 && ndata[1] == '*')
408 dns_name_internalwildcard(const dns_name_t *name) {
409 unsigned char *ndata;
414 * Does 'name' contain a internal wildcard?
417 REQUIRE(VALID_NAME(name));
418 REQUIRE(name->labels > 0);
429 * Check all but the last of the remaining labels.
431 while (label + 1 < name->labels) {
434 if (count == 1 && *ndata == '*')
442 static inline unsigned int
443 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
445 const unsigned char *s;
449 length = name->length;
454 * This hash function is similar to the one Ousterhout
458 if (case_sensitive) {
460 h += ( h << 3 ) + *s;
477 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
479 * Provide a hash value for 'name'.
481 REQUIRE(VALID_NAME(name));
483 if (name->labels == 0)
486 return (name_hash(name, case_sensitive));
490 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
492 * Provide a hash value for 'name'.
494 REQUIRE(VALID_NAME(name));
496 if (name->labels == 0)
499 return (isc_hash_calc((const unsigned char *)name->ndata,
500 name->length, case_sensitive));
504 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
506 * This function was deprecated due to the breakage of the name space
507 * convention. We only keep this internally to provide binary backward
510 REQUIRE(VALID_NAME(name));
512 return (dns_name_fullhash(name, case_sensitive));
516 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
517 unsigned char *offsets;
524 * Provide a hash value for 'name'.
526 REQUIRE(VALID_NAME(name));
528 if (name->labels == 0)
530 else if (name->labels == 1)
531 return (name_hash(name, case_sensitive));
533 SETUP_OFFSETS(name, offsets, odata);
534 DNS_NAME_INIT(&tname, NULL);
537 for (i = 0; i < name->labels; i++) {
538 tname.ndata = name->ndata + offsets[i];
539 if (i == name->labels - 1)
540 tname.length = name->length - offsets[i];
542 tname.length = offsets[i + 1] - offsets[i];
543 h += name_hash(&tname, case_sensitive);
550 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
551 int *orderp, unsigned int *nlabelsp)
553 unsigned int l1, l2, l, count1, count2, count, nlabels;
554 int cdiff, ldiff, chdiff;
555 unsigned char *label1, *label2;
556 unsigned char *offsets1, *offsets2;
557 dns_offsets_t odata1, odata2;
558 dns_namereln_t namereln = dns_namereln_none;
561 * Determine the relative ordering under the DNSSEC order relation of
562 * 'name1' and 'name2', and also determine the hierarchical
563 * relationship of the names.
565 * Note: It makes no sense for one of the names to be relative and the
566 * other absolute. If both names are relative, then to be meaningfully
567 * compared the caller must ensure that they are both relative to the
571 REQUIRE(VALID_NAME(name1));
572 REQUIRE(VALID_NAME(name2));
573 REQUIRE(orderp != NULL);
574 REQUIRE(nlabelsp != NULL);
576 * Either name1 is absolute and name2 is absolute, or neither is.
578 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
579 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
581 SETUP_OFFSETS(name1, offsets1, odata1);
582 SETUP_OFFSETS(name2, offsets2, odata2);
589 ldiff = 0 - (l2 - l1);
599 label1 = &name1->ndata[offsets1[l1]];
600 label2 = &name2->ndata[offsets2[l2]];
605 * We dropped bitstring labels, and we don't support any
606 * other extended label types.
608 INSIST(count1 <= 63 && count2 <= 63);
610 cdiff = (int)count1 - (int)count2;
617 chdiff = (int)maptolower[*label1] -
618 (int)maptolower[*label2];
636 namereln = dns_namereln_contains;
638 namereln = dns_namereln_subdomain;
640 namereln = dns_namereln_equal;
645 if (nlabels > 0 && namereln == dns_namereln_none)
646 namereln = dns_namereln_commonancestor;
652 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
654 unsigned int nlabels;
657 * Determine the relative ordering under the DNSSEC order relation of
658 * 'name1' and 'name2'.
660 * Note: It makes no sense for one of the names to be relative and the
661 * other absolute. If both names are relative, then to be meaningfully
662 * compared the caller must ensure that they are both relative to the
666 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
672 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
673 unsigned int l, count;
675 unsigned char *label1, *label2;
678 * Are 'name1' and 'name2' equal?
680 * Note: It makes no sense for one of the names to be relative and the
681 * other absolute. If both names are relative, then to be meaningfully
682 * compared the caller must ensure that they are both relative to the
686 REQUIRE(VALID_NAME(name1));
687 REQUIRE(VALID_NAME(name2));
689 * Either name1 is absolute and name2 is absolute, or neither is.
691 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
692 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
694 if (name1->length != name2->length)
699 if (l != name2->labels)
702 label1 = name1->ndata;
703 label2 = name2->ndata;
707 if (count != *label2++)
710 INSIST(count <= 63); /* no bitstring support */
714 c = maptolower[*label1++];
715 if (c != maptolower[*label2++])
724 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
727 * Are 'name1' and 'name2' equal?
729 * Note: It makes no sense for one of the names to be relative and the
730 * other absolute. If both names are relative, then to be meaningfully
731 * compared the caller must ensure that they are both relative to the
735 REQUIRE(VALID_NAME(name1));
736 REQUIRE(VALID_NAME(name2));
738 * Either name1 is absolute and name2 is absolute, or neither is.
740 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
741 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
743 if (name1->length != name2->length)
746 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
753 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
754 unsigned int l1, l2, l, count1, count2, count;
755 unsigned char c1, c2;
756 unsigned char *label1, *label2;
759 * Compare two absolute names as rdata.
762 REQUIRE(VALID_NAME(name1));
763 REQUIRE(name1->labels > 0);
764 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
765 REQUIRE(VALID_NAME(name2));
766 REQUIRE(name2->labels > 0);
767 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
772 l = (l1 < l2) ? l1 : l2;
774 label1 = name1->ndata;
775 label2 = name2->ndata;
781 /* no bitstring support */
782 INSIST(count1 <= 63 && count2 <= 63);
784 if (count1 != count2)
785 return ((count1 < count2) ? -1 : 1);
789 c1 = maptolower[*label1++];
790 c2 = maptolower[*label2++];
799 * If one name had more labels than the other, their common
800 * prefix must have been different because the shorter name
801 * ended with the root label and the longer one can't have
802 * a root label in the middle of it. Therefore, if we get
803 * to this point, the lengths must be equal.
811 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
813 unsigned int nlabels;
814 dns_namereln_t namereln;
817 * Is 'name1' a subdomain of 'name2'?
819 * Note: It makes no sense for one of the names to be relative and the
820 * other absolute. If both names are relative, then to be meaningfully
821 * compared the caller must ensure that they are both relative to the
825 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
826 if (namereln == dns_namereln_subdomain ||
827 namereln == dns_namereln_equal)
834 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
836 unsigned int nlabels, labels;
839 REQUIRE(VALID_NAME(name));
840 REQUIRE(name->labels > 0);
841 REQUIRE(VALID_NAME(wname));
842 labels = wname->labels;
844 REQUIRE(dns_name_iswildcard(wname));
846 #if defined(__clang__) && \
847 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
848 memset(&tname, 0, sizeof(tname));
850 DNS_NAME_INIT(&tname, NULL);
851 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
852 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
853 dns_namereln_subdomain)
859 dns_name_countlabels(const dns_name_t *name) {
861 * How many labels does 'name' have?
864 REQUIRE(VALID_NAME(name));
866 ENSURE(name->labels <= 128);
868 return (name->labels);
872 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
873 unsigned char *offsets;
877 * Make 'label' refer to the 'n'th least significant label of 'name'.
880 REQUIRE(VALID_NAME(name));
881 REQUIRE(name->labels > 0);
882 REQUIRE(n < name->labels);
883 REQUIRE(label != NULL);
885 SETUP_OFFSETS(name, offsets, odata);
887 label->base = &name->ndata[offsets[n]];
888 if (n == name->labels - 1)
889 label->length = name->length - offsets[n];
891 label->length = offsets[n + 1] - offsets[n];
895 dns_name_getlabelsequence(const dns_name_t *source,
896 unsigned int first, unsigned int n,
899 unsigned char *offsets;
901 unsigned int firstoffset, endoffset;
904 * Make 'target' refer to the 'n' labels including and following
905 * 'first' in 'source'.
908 REQUIRE(VALID_NAME(source));
909 REQUIRE(VALID_NAME(target));
910 REQUIRE(first <= source->labels);
911 REQUIRE(n <= source->labels - first); /* note first+n could overflow */
912 REQUIRE(BINDABLE(target));
914 SETUP_OFFSETS(source, offsets, odata);
916 if (first == source->labels)
917 firstoffset = source->length;
919 firstoffset = offsets[first];
921 if (first + n == source->labels)
922 endoffset = source->length;
924 endoffset = offsets[first + n];
926 target->ndata = &source->ndata[firstoffset];
927 target->length = endoffset - firstoffset;
929 if (first + n == source->labels && n > 0 &&
930 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
931 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
933 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
938 * If source and target are the same, and we're making target
939 * a prefix of source, the offsets table is correct already
940 * so we don't need to call set_offsets().
942 if (target->offsets != NULL &&
943 (target != source || first != 0))
944 set_offsets(target, target->offsets, NULL);
948 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
951 * Make 'target' refer to the same name as 'source'.
954 REQUIRE(VALID_NAME(source));
955 REQUIRE(VALID_NAME(target));
956 REQUIRE(BINDABLE(target));
958 target->ndata = source->ndata;
959 target->length = source->length;
960 target->labels = source->labels;
961 target->attributes = source->attributes &
962 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
963 DNS_NAMEATTR_DYNOFFSETS);
964 if (target->offsets != NULL && source->labels > 0) {
965 if (source->offsets != NULL)
966 memcpy(target->offsets, source->offsets,
969 set_offsets(target, target->offsets, NULL);
974 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
975 unsigned char *offsets;
981 * Make 'name' refer to region 'r'.
984 REQUIRE(VALID_NAME(name));
986 REQUIRE(BINDABLE(name));
988 INIT_OFFSETS(name, offsets, odata);
990 if (name->buffer != NULL) {
991 isc_buffer_clear(name->buffer);
992 isc_buffer_availableregion(name->buffer, &r2);
993 len = (r->length < r2.length) ? r->length : r2.length;
994 if (len > DNS_NAME_MAXWIRE)
995 len = DNS_NAME_MAXWIRE;
996 memcpy(r2.base, r->base, len);
997 name->ndata = r2.base;
1000 name->ndata = r->base;
1001 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1002 r->length : DNS_NAME_MAXWIRE;
1006 set_offsets(name, offsets, name);
1009 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1012 if (name->buffer != NULL)
1013 isc_buffer_add(name->buffer, name->length);
1017 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1019 * Make 'r' refer to 'name'.
1022 REQUIRE(VALID_NAME(name));
1025 DNS_NAME_TOREGION(name, r);
1029 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1030 const dns_name_t *origin, unsigned int options,
1031 isc_buffer_t *target)
1033 unsigned char *ndata, *label = NULL;
1037 unsigned int value = 0, count = 0;
1038 unsigned int n1 = 0, n2 = 0;
1039 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1041 unsigned char *offsets;
1042 dns_offsets_t odata;
1043 isc_boolean_t downcase;
1046 * Convert the textual representation of a DNS name at source
1047 * into uncompressed wire form stored in target.
1050 * Relative domain names will have 'origin' appended to them
1051 * unless 'origin' is NULL, in which case relative domain names
1052 * will remain relative.
1055 REQUIRE(VALID_NAME(name));
1056 REQUIRE(ISC_BUFFER_VALID(source));
1057 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1058 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1060 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1062 if (target == NULL && name->buffer != NULL) {
1063 target = name->buffer;
1064 isc_buffer_clear(target);
1067 REQUIRE(BINDABLE(name));
1069 INIT_OFFSETS(name, offsets, odata);
1073 * Make 'name' empty in case of failure.
1078 * Set up the state machine.
1080 tdata = (char *)source->base + source->current;
1081 tlen = isc_buffer_remaininglength(source);
1083 ndata = isc_buffer_used(target);
1084 nrem = isc_buffer_availablelength(target);
1092 while (nrem > 0 && tlen > 0 && !done) {
1100 * Is this the root name?
1104 return (DNS_R_EMPTYLABEL);
1112 if (c == '@' && tlen == 0) {
1125 state = ft_initialescape;
1128 state = ft_ordinary;
1130 return (ISC_R_NOSPACE);
1135 return (DNS_R_EMPTYLABEL);
1138 INSIST(labels <= 127);
1139 offsets[labels] = nused;
1148 } else if (c == '\\') {
1152 return (DNS_R_LABELTOOLONG);
1156 c = maptolower[(int)c];
1162 case ft_initialescape:
1165 * This looks like a bitstring label, which
1166 * was deprecated. Intentionally drop it.
1168 return (DNS_R_BADLABELTYPE);
1174 if (!isdigit(c & 0xff)) {
1176 return (DNS_R_LABELTOOLONG);
1180 c = maptolower[(int)c];
1184 state = ft_ordinary;
1189 state = ft_escdecimal;
1192 if (!isdigit(c & 0xff))
1193 return (DNS_R_BADESCAPE);
1195 value += digitvalue[(int)c];
1199 return (DNS_R_BADESCAPE);
1201 return (DNS_R_LABELTOOLONG);
1204 value = maptolower[value];
1208 state = ft_ordinary;
1212 FATAL_ERROR(__FILE__, __LINE__,
1213 "Unexpected state %d", state);
1214 /* Does not return. */
1220 return (ISC_R_NOSPACE);
1222 if (state != ft_ordinary && state != ft_at)
1223 return (ISC_R_UNEXPECTEDEND);
1224 if (state == ft_ordinary) {
1228 INSIST(labels <= 127);
1229 offsets[labels] = nused;
1231 if (origin != NULL) {
1232 if (nrem < origin->length)
1233 return (ISC_R_NOSPACE);
1234 label = origin->ndata;
1235 n1 = origin->length;
1240 INSIST(n2 <= 63); /* no bitstring support */
1247 c = maptolower[(int)c];
1253 INSIST(labels <= 127);
1254 offsets[labels] = nused;
1257 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1258 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1261 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1263 name->ndata = (unsigned char *)target->base + target->used;
1264 name->labels = labels;
1265 name->length = nused;
1267 isc_buffer_forward(source, tused);
1268 isc_buffer_add(target, name->length);
1270 return (ISC_R_SUCCESS);
1273 #ifdef ISC_PLATFORM_USETHREADS
1275 free_specific(void *arg) {
1276 dns_name_totextfilter_t *mem = arg;
1277 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1278 /* Stop use being called again. */
1279 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1283 thread_key_mutex_init(void) {
1284 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1288 totext_filter_proc_key_init(void) {
1289 isc_result_t result;
1292 * We need the call to isc_once_do() to support profiled mutex
1293 * otherwise thread_key_mutex could be initialized at compile time.
1295 result = isc_once_do(&once, thread_key_mutex_init);
1296 if (result != ISC_R_SUCCESS)
1299 if (!thread_key_initialized) {
1300 LOCK(&thread_key_mutex);
1301 if (thread_key_mctx == NULL)
1302 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1303 if (result != ISC_R_SUCCESS)
1305 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
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 int options = DNS_NAME_MASTERFILE;
1329 options |= DNS_NAME_OMITFINALDOT;
1330 return (dns_name_totext2(name, options, target));
1334 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1335 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1339 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1341 unsigned char *ndata;
1343 unsigned int nlen, tlen;
1345 unsigned int trem, count;
1346 unsigned int labels;
1347 isc_boolean_t saw_root = ISC_FALSE;
1348 unsigned int oused = target->used;
1349 #ifdef ISC_PLATFORM_USETHREADS
1350 dns_name_totextfilter_t *mem;
1351 dns_name_totextfilter_t totext_filter_proc = NULL;
1352 isc_result_t result;
1354 isc_boolean_t omit_final_dot =
1355 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1358 * This function assumes the name is in proper uncompressed
1361 REQUIRE(VALID_NAME(name));
1362 REQUIRE(ISC_BUFFER_VALID(target));
1364 #ifdef ISC_PLATFORM_USETHREADS
1365 result = totext_filter_proc_key_init();
1366 if (result != ISC_R_SUCCESS)
1369 ndata = name->ndata;
1370 nlen = name->length;
1371 labels = name->labels;
1372 tdata = isc_buffer_used(target);
1373 tlen = isc_buffer_availablelength(target);
1377 if (labels == 0 && nlen == 0) {
1379 * Special handling for an empty name.
1382 return (ISC_R_NOSPACE);
1385 * The names of these booleans are misleading in this case.
1386 * This empty name is not necessarily from the root node of
1387 * the DNS root zone, nor is a final dot going to be included.
1388 * They need to be set this way, though, to keep the "@"
1389 * from being trounced.
1391 saw_root = ISC_TRUE;
1392 omit_final_dot = ISC_FALSE;
1397 * Skip the while() loop.
1400 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1402 * Special handling for the root label.
1405 return (ISC_R_NOSPACE);
1407 saw_root = ISC_TRUE;
1408 omit_final_dot = ISC_FALSE;
1413 * Skip the while() loop.
1418 while (labels > 0 && nlen > 0 && trem > 0) {
1423 saw_root = ISC_TRUE;
1427 INSIST(nlen >= count);
1431 /* Special modifiers in zone files. */
1432 case 0x40: /* '@' */
1433 case 0x24: /* '$' */
1434 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 #if defined(__clang__) && \
1945 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1946 memset(&clname, 0, sizeof(clname));
1948 DNS_NAME_INIT(&clname, clo);
1949 dns_name_clone(name, &clname);
1952 DNS_NAME_INIT(&gp, NULL);
1954 offset = target->used; /*XXX*/
1956 methods = dns_compress_getmethods(cctx);
1958 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1959 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1960 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1965 * If the offset is too high for 14 bit global compression, we're
1968 if (gf && go >= 0x4000)
1972 * Will the compression pointer reduce the message size?
1974 if (gf && (gp.length + 2) >= name->length)
1978 if (target->length - target->used < gp.length)
1979 return (ISC_R_NOSPACE);
1980 (void)memcpy((unsigned char *)target->base + target->used,
1981 gp.ndata, (size_t)gp.length);
1982 isc_buffer_add(target, gp.length);
1984 if (target->length - target->used < 2)
1985 return (ISC_R_NOSPACE);
1986 isc_buffer_putuint16(target, go);
1988 dns_compress_add(cctx, name, &gp, offset);
1990 if (target->length - target->used < name->length)
1991 return (ISC_R_NOSPACE);
1992 (void)memcpy((unsigned char *)target->base + target->used,
1993 name->ndata, (size_t)name->length);
1994 isc_buffer_add(target, name->length);
1995 dns_compress_add(cctx, name, name, offset);
1997 return (ISC_R_SUCCESS);
2001 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2002 isc_buffer_t *target)
2004 unsigned char *ndata, *offsets;
2005 unsigned int nrem, labels, prefix_length, length;
2006 isc_boolean_t copy_prefix = ISC_TRUE;
2007 isc_boolean_t copy_suffix = ISC_TRUE;
2008 isc_boolean_t absolute = ISC_FALSE;
2009 dns_name_t tmp_name;
2010 dns_offsets_t odata;
2013 * Concatenate 'prefix' and 'suffix'.
2016 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2017 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2018 REQUIRE(name == NULL || VALID_NAME(name));
2019 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2020 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2021 if (prefix == NULL || prefix->labels == 0)
2022 copy_prefix = ISC_FALSE;
2023 if (suffix == NULL || suffix->labels == 0)
2024 copy_suffix = ISC_FALSE;
2026 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2027 absolute = ISC_TRUE;
2028 REQUIRE(!copy_suffix);
2031 DNS_NAME_INIT(&tmp_name, odata);
2034 if (target == NULL) {
2035 INSIST(name->buffer != NULL);
2036 target = name->buffer;
2037 isc_buffer_clear(name->buffer);
2040 REQUIRE(BINDABLE(name));
2045 nrem = target->length - target->used;
2046 ndata = (unsigned char *)target->base + target->used;
2047 if (nrem > DNS_NAME_MAXWIRE)
2048 nrem = DNS_NAME_MAXWIRE;
2053 prefix_length = prefix->length;
2054 length += prefix_length;
2055 labels += prefix->labels;
2058 length += suffix->length;
2059 labels += suffix->labels;
2061 if (length > DNS_NAME_MAXWIRE) {
2063 return (DNS_R_NAMETOOLONG);
2065 if (length > nrem) {
2067 return (ISC_R_NOSPACE);
2071 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2072 absolute = ISC_TRUE;
2073 if (suffix == name && suffix->buffer == target)
2074 memmove(ndata + prefix_length, suffix->ndata,
2077 memcpy(ndata + prefix_length, suffix->ndata,
2082 * If 'prefix' and 'name' are the same object, and the object has
2083 * a dedicated buffer, and we're using it, then we don't have to
2086 if (copy_prefix && (prefix != name || prefix->buffer != target))
2087 memcpy(ndata, prefix->ndata, prefix_length);
2089 name->ndata = ndata;
2090 name->labels = labels;
2091 name->length = length;
2093 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2095 name->attributes = 0;
2097 if (name->labels > 0 && name->offsets != NULL) {
2098 INIT_OFFSETS(name, offsets, odata);
2099 set_offsets(name, offsets, NULL);
2102 isc_buffer_add(target, name->length);
2104 return (ISC_R_SUCCESS);
2108 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2109 dns_name_t *prefix, dns_name_t *suffix)
2112 unsigned int splitlabel;
2114 REQUIRE(VALID_NAME(name));
2115 REQUIRE(suffixlabels > 0);
2116 REQUIRE(suffixlabels < name->labels);
2117 REQUIRE(prefix != NULL || suffix != NULL);
2118 REQUIRE(prefix == NULL ||
2119 (VALID_NAME(prefix) &&
2120 prefix->buffer != NULL &&
2122 REQUIRE(suffix == NULL ||
2123 (VALID_NAME(suffix) &&
2124 suffix->buffer != NULL &&
2127 splitlabel = name->labels - suffixlabels;
2130 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2133 dns_name_getlabelsequence(name, splitlabel,
2134 suffixlabels, suffix);
2140 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2144 * Make 'target' a dynamically allocated copy of 'source'.
2147 REQUIRE(VALID_NAME(source));
2148 REQUIRE(source->length > 0);
2149 REQUIRE(VALID_NAME(target));
2150 REQUIRE(BINDABLE(target));
2153 * Make 'target' empty in case of failure.
2157 target->ndata = isc_mem_get(mctx, source->length);
2158 if (target->ndata == NULL)
2159 return (ISC_R_NOMEMORY);
2161 memcpy(target->ndata, source->ndata, source->length);
2163 target->length = source->length;
2164 target->labels = source->labels;
2165 target->attributes = DNS_NAMEATTR_DYNAMIC;
2166 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2167 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2168 if (target->offsets != NULL) {
2169 if (source->offsets != NULL)
2170 memcpy(target->offsets, source->offsets,
2173 set_offsets(target, target->offsets, NULL);
2176 return (ISC_R_SUCCESS);
2180 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2184 * Make 'target' a read-only dynamically allocated copy of 'source'.
2185 * 'target' will also have a dynamically allocated offsets table.
2188 REQUIRE(VALID_NAME(source));
2189 REQUIRE(source->length > 0);
2190 REQUIRE(VALID_NAME(target));
2191 REQUIRE(BINDABLE(target));
2192 REQUIRE(target->offsets == NULL);
2195 * Make 'target' empty in case of failure.
2199 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2200 if (target->ndata == NULL)
2201 return (ISC_R_NOMEMORY);
2203 memcpy(target->ndata, source->ndata, source->length);
2205 target->length = source->length;
2206 target->labels = source->labels;
2207 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2208 DNS_NAMEATTR_READONLY;
2209 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2210 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2211 target->offsets = target->ndata + source->length;
2212 if (source->offsets != NULL)
2213 memcpy(target->offsets, source->offsets, source->labels);
2215 set_offsets(target, target->offsets, NULL);
2217 return (ISC_R_SUCCESS);
2221 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2228 REQUIRE(VALID_NAME(name));
2229 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2231 size = name->length;
2232 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2233 size += name->labels;
2234 isc_mem_put(mctx, name->ndata, size);
2235 dns_name_invalidate(name);
2239 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2240 dns_name_t downname;
2241 unsigned char data[256];
2242 isc_buffer_t buffer;
2243 isc_result_t result;
2247 * Send 'name' in DNSSEC canonical form to 'digest'.
2250 REQUIRE(VALID_NAME(name));
2251 REQUIRE(digest != NULL);
2253 #if defined(__clang__) && \
2254 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2255 memset(&downname, 0, sizeof(downname));
2257 DNS_NAME_INIT(&downname, NULL);
2259 isc_buffer_init(&buffer, data, sizeof(data));
2261 result = dns_name_downcase(name, &downname, &buffer);
2262 if (result != ISC_R_SUCCESS)
2265 isc_buffer_usedregion(&buffer, &r);
2267 return ((digest)(arg, &r));
2271 dns_name_dynamic(dns_name_t *name) {
2272 REQUIRE(VALID_NAME(name));
2275 * Returns whether there is dynamic memory associated with this name.
2278 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2279 ISC_TRUE : ISC_FALSE);
2283 dns_name_print(dns_name_t *name, FILE *stream) {
2284 isc_result_t result;
2290 * Print 'name' on 'stream'.
2293 REQUIRE(VALID_NAME(name));
2295 isc_buffer_init(&b, t, sizeof(t));
2296 result = dns_name_totext(name, ISC_FALSE, &b);
2297 if (result != ISC_R_SUCCESS)
2299 isc_buffer_usedregion(&b, &r);
2300 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2302 return (ISC_R_SUCCESS);
2306 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2307 #ifdef ISC_PLATFORM_USETHREADS
2308 isc_result_t result;
2309 dns_name_totextfilter_t *mem;
2312 result = totext_filter_proc_key_init();
2313 if (result != ISC_R_SUCCESS)
2317 * If we already have been here set / clear as appropriate.
2318 * Otherwise allocate memory.
2320 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2321 if (mem != NULL && proc != NULL) {
2323 return (ISC_R_SUCCESS);
2326 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2327 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2329 result = ISC_R_UNEXPECTED;
2333 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2335 return (ISC_R_NOMEMORY);
2337 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2338 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2339 result = ISC_R_UNEXPECTED;
2343 totext_filter_proc = proc;
2344 return (ISC_R_SUCCESS);
2349 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2350 isc_result_t result;
2356 * Leave room for null termination after buffer.
2358 isc_buffer_init(&buf, cp, size - 1);
2359 result = dns_name_totext(name, ISC_TRUE, &buf);
2360 if (result == ISC_R_SUCCESS) {
2365 isc_buffer_usedregion(&buf, &r);
2366 ((char *) r.base)[r.length] = '\0';
2369 snprintf(cp, size, "<unknown>");
2373 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2377 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2378 isc_result_t result;
2381 char *p, txt[DNS_NAME_FORMATSIZE];
2383 REQUIRE(VALID_NAME(name));
2384 REQUIRE(target != NULL && *target == NULL);
2386 isc_buffer_init(&buf, txt, sizeof(txt));
2387 result = dns_name_totext(name, ISC_FALSE, &buf);
2388 if (result != ISC_R_SUCCESS)
2391 isc_buffer_usedregion(&buf, ®);
2392 p = isc_mem_allocate(mctx, reg.length + 1);
2393 memcpy(p, (char *) reg.base, (int) reg.length);
2394 p[reg.length] = '\0';
2397 return (ISC_R_SUCCESS);
2401 * dns_name_fromstring() -- convert directly from a string to a name,
2402 * allocating memory as needed
2405 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2408 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2412 dns_name_fromstring2(dns_name_t *target, const char *src,
2413 const dns_name_t *origin, unsigned int options,
2416 isc_result_t result;
2421 REQUIRE(src != NULL);
2423 isc_buffer_constinit(&buf, src, strlen(src));
2424 isc_buffer_add(&buf, strlen(src));
2425 if (BINDABLE(target) && target->buffer != NULL)
2428 dns_fixedname_init(&fn);
2429 name = dns_fixedname_name(&fn);
2432 result = dns_name_fromtext(name, &buf, origin, options, NULL);
2433 if (result != ISC_R_SUCCESS)
2437 result = dns_name_dupwithoffsets(name, mctx, target);
2442 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2443 unsigned char *ndata;
2446 * Make dest a copy of source.
2449 REQUIRE(VALID_NAME(source));
2450 REQUIRE(VALID_NAME(dest));
2451 REQUIRE(target != NULL || dest->buffer != NULL);
2453 if (target == NULL) {
2454 target = dest->buffer;
2455 isc_buffer_clear(dest->buffer);
2458 REQUIRE(BINDABLE(dest));
2463 if (target->length - target->used < source->length)
2464 return (ISC_R_NOSPACE);
2466 ndata = (unsigned char *)target->base + target->used;
2467 dest->ndata = target->base;
2469 memcpy(ndata, source->ndata, source->length);
2471 dest->ndata = ndata;
2472 dest->labels = source->labels;
2473 dest->length = source->length;
2474 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2475 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2477 dest->attributes = 0;
2479 if (dest->labels > 0 && dest->offsets != NULL) {
2480 if (source->offsets != NULL)
2481 memcpy(dest->offsets, source->offsets, source->labels);
2483 set_offsets(dest, dest->offsets, NULL);
2486 isc_buffer_add(target, dest->length);
2488 return (ISC_R_SUCCESS);
2492 dns_name_destroy(void) {
2493 #ifdef ISC_PLATFORM_USETHREADS
2494 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2497 LOCK(&thread_key_mutex);
2498 if (thread_key_initialized) {
2499 isc_mem_detach(&thread_key_mctx);
2500 isc_thread_key_delete(totext_filter_proc_key);
2501 thread_key_initialized = 0;
2503 UNLOCK(&thread_key_mutex);