2 * Copyright (C) 2004-2016 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/random.h>
33 #include <isc/string.h>
34 #include <isc/thread.h>
37 #include <dns/compress.h>
38 #include <dns/fixedname.h>
40 #include <dns/result.h>
42 #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 == '*')
443 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
447 * Provide a hash value for 'name'.
449 REQUIRE(VALID_NAME(name));
451 if (name->labels == 0)
454 length = name->length;
458 return (isc_hash_function_reverse(name->ndata, length,
459 case_sensitive, NULL));
463 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
465 * Provide a hash value for 'name'.
467 REQUIRE(VALID_NAME(name));
469 if (name->labels == 0)
472 return (isc_hash_function_reverse(name->ndata, name->length,
473 case_sensitive, NULL));
477 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
479 * This function was deprecated due to the breakage of the name space
480 * convention. We only keep this internally to provide binary backward
483 return (dns_name_fullhash(name, case_sensitive));
487 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
488 unsigned char *offsets;
495 * Provide a hash value for 'name'.
497 REQUIRE(VALID_NAME(name));
499 if (name->labels == 0)
501 else if (name->labels == 1)
502 return (isc_hash_function_reverse(name->ndata, name->length,
503 case_sensitive, NULL));
505 SETUP_OFFSETS(name, offsets, odata);
506 DNS_NAME_INIT(&tname, NULL);
509 for (i = 0; i < name->labels; i++) {
510 tname.ndata = name->ndata + offsets[i];
511 if (i == name->labels - 1)
512 tname.length = name->length - offsets[i];
514 tname.length = offsets[i + 1] - offsets[i];
515 h += isc_hash_function_reverse(tname.ndata, tname.length,
516 case_sensitive, NULL);
523 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
524 int *orderp, unsigned int *nlabelsp)
526 unsigned int l1, l2, l, count1, count2, count, nlabels;
527 int cdiff, ldiff, chdiff;
528 unsigned char *label1, *label2;
529 unsigned char *offsets1, *offsets2;
530 dns_offsets_t odata1, odata2;
531 dns_namereln_t namereln = dns_namereln_none;
534 * Determine the relative ordering under the DNSSEC order relation of
535 * 'name1' and 'name2', and also determine the hierarchical
536 * relationship of the names.
538 * Note: It makes no sense for one of the names to be relative and the
539 * other absolute. If both names are relative, then to be meaningfully
540 * compared the caller must ensure that they are both relative to the
544 REQUIRE(VALID_NAME(name1));
545 REQUIRE(VALID_NAME(name2));
546 REQUIRE(orderp != NULL);
547 REQUIRE(nlabelsp != NULL);
549 * Either name1 is absolute and name2 is absolute, or neither is.
551 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
552 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
554 if (ISC_UNLIKELY(name1 == name2)) {
556 *nlabelsp = name1->labels;
557 return (dns_namereln_equal);
560 SETUP_OFFSETS(name1, offsets1, odata1);
561 SETUP_OFFSETS(name2, offsets2, odata2);
568 ldiff = 0 - (l2 - l1);
577 while (ISC_LIKELY(l > 0)) {
581 label1 = &name1->ndata[*offsets1];
582 label2 = &name2->ndata[*offsets2];
587 * We dropped bitstring labels, and we don't support any
588 * other extended label types.
590 INSIST(count1 <= 63 && count2 <= 63);
592 cdiff = (int)count1 - (int)count2;
598 /* Loop unrolled for performance */
599 while (ISC_LIKELY(count > 3)) {
600 chdiff = (int)maptolower[label1[0]] -
601 (int)maptolower[label2[0]];
606 chdiff = (int)maptolower[label1[1]] -
607 (int)maptolower[label2[1]];
612 chdiff = (int)maptolower[label1[2]] -
613 (int)maptolower[label2[2]];
618 chdiff = (int)maptolower[label1[3]] -
619 (int)maptolower[label2[3]];
628 while (ISC_LIKELY(count-- > 0)) {
629 chdiff = (int)maptolower[*label1++] -
630 (int)maptolower[*label2++];
645 namereln = dns_namereln_contains;
647 namereln = dns_namereln_subdomain;
649 namereln = dns_namereln_equal;
656 namereln = dns_namereln_commonancestor;
662 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
664 unsigned int nlabels;
667 * Determine the relative ordering under the DNSSEC order relation of
668 * 'name1' and 'name2'.
670 * Note: It makes no sense for one of the names to be relative and the
671 * other absolute. If both names are relative, then to be meaningfully
672 * compared the caller must ensure that they are both relative to the
676 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
682 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
683 unsigned int l, count;
685 unsigned char *label1, *label2;
688 * Are 'name1' and 'name2' equal?
690 * Note: It makes no sense for one of the names to be relative and the
691 * other absolute. If both names are relative, then to be meaningfully
692 * compared the caller must ensure that they are both relative to the
696 REQUIRE(VALID_NAME(name1));
697 REQUIRE(VALID_NAME(name2));
699 * Either name1 is absolute and name2 is absolute, or neither is.
701 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
702 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
704 if (ISC_UNLIKELY(name1 == name2))
707 if (name1->length != name2->length)
712 if (l != name2->labels)
715 label1 = name1->ndata;
716 label2 = name2->ndata;
717 while (ISC_LIKELY(l-- > 0)) {
719 if (count != *label2++)
722 INSIST(count <= 63); /* no bitstring support */
724 /* Loop unrolled for performance */
725 while (ISC_LIKELY(count > 3)) {
726 c = maptolower[label1[0]];
727 if (c != maptolower[label2[0]])
729 c = maptolower[label1[1]];
730 if (c != maptolower[label2[1]])
732 c = maptolower[label1[2]];
733 if (c != maptolower[label2[2]])
735 c = maptolower[label1[3]];
736 if (c != maptolower[label2[3]])
742 while (ISC_LIKELY(count-- > 0)) {
743 c = maptolower[*label1++];
744 if (c != maptolower[*label2++])
753 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
756 * Are 'name1' and 'name2' equal?
758 * Note: It makes no sense for one of the names to be relative and the
759 * other absolute. If both names are relative, then to be meaningfully
760 * compared the caller must ensure that they are both relative to the
764 REQUIRE(VALID_NAME(name1));
765 REQUIRE(VALID_NAME(name2));
767 * Either name1 is absolute and name2 is absolute, or neither is.
769 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
770 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
772 if (name1->length != name2->length)
775 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
782 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
783 unsigned int l1, l2, l, count1, count2, count;
784 unsigned char c1, c2;
785 unsigned char *label1, *label2;
788 * Compare two absolute names as rdata.
791 REQUIRE(VALID_NAME(name1));
792 REQUIRE(name1->labels > 0);
793 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
794 REQUIRE(VALID_NAME(name2));
795 REQUIRE(name2->labels > 0);
796 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
801 l = (l1 < l2) ? l1 : l2;
803 label1 = name1->ndata;
804 label2 = name2->ndata;
810 /* no bitstring support */
811 INSIST(count1 <= 63 && count2 <= 63);
813 if (count1 != count2)
814 return ((count1 < count2) ? -1 : 1);
818 c1 = maptolower[*label1++];
819 c2 = maptolower[*label2++];
828 * If one name had more labels than the other, their common
829 * prefix must have been different because the shorter name
830 * ended with the root label and the longer one can't have
831 * a root label in the middle of it. Therefore, if we get
832 * to this point, the lengths must be equal.
840 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
842 unsigned int nlabels;
843 dns_namereln_t namereln;
846 * Is 'name1' a subdomain of 'name2'?
848 * Note: It makes no sense for one of the names to be relative and the
849 * other absolute. If both names are relative, then to be meaningfully
850 * compared the caller must ensure that they are both relative to the
854 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
855 if (namereln == dns_namereln_subdomain ||
856 namereln == dns_namereln_equal)
863 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
865 unsigned int nlabels, labels;
868 REQUIRE(VALID_NAME(name));
869 REQUIRE(name->labels > 0);
870 REQUIRE(VALID_NAME(wname));
871 labels = wname->labels;
873 REQUIRE(dns_name_iswildcard(wname));
875 #if defined(__clang__) && \
876 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
877 memset(&tname, 0, sizeof(tname));
879 DNS_NAME_INIT(&tname, NULL);
880 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
881 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
882 dns_namereln_subdomain)
888 dns_name_countlabels(const dns_name_t *name) {
890 * How many labels does 'name' have?
893 REQUIRE(VALID_NAME(name));
895 ENSURE(name->labels <= 128);
897 return (name->labels);
901 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
902 unsigned char *offsets;
906 * Make 'label' refer to the 'n'th least significant label of 'name'.
909 REQUIRE(VALID_NAME(name));
910 REQUIRE(name->labels > 0);
911 REQUIRE(n < name->labels);
912 REQUIRE(label != NULL);
914 SETUP_OFFSETS(name, offsets, odata);
916 label->base = &name->ndata[offsets[n]];
917 if (n == name->labels - 1)
918 label->length = name->length - offsets[n];
920 label->length = offsets[n + 1] - offsets[n];
924 dns_name_getlabelsequence(const dns_name_t *source,
925 unsigned int first, unsigned int n,
928 unsigned char *offsets;
930 unsigned int firstoffset, endoffset;
933 * Make 'target' refer to the 'n' labels including and following
934 * 'first' in 'source'.
937 REQUIRE(VALID_NAME(source));
938 REQUIRE(VALID_NAME(target));
939 REQUIRE(first <= source->labels);
940 REQUIRE(n <= source->labels - first); /* note first+n could overflow */
941 REQUIRE(BINDABLE(target));
943 SETUP_OFFSETS(source, offsets, odata);
945 if (first == source->labels)
946 firstoffset = source->length;
948 firstoffset = offsets[first];
950 if (first + n == source->labels)
951 endoffset = source->length;
953 endoffset = offsets[first + n];
955 target->ndata = &source->ndata[firstoffset];
956 target->length = endoffset - firstoffset;
958 if (first + n == source->labels && n > 0 &&
959 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
960 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
962 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
967 * If source and target are the same, and we're making target
968 * a prefix of source, the offsets table is correct already
969 * so we don't need to call set_offsets().
971 if (target->offsets != NULL &&
972 (target != source || first != 0))
973 set_offsets(target, target->offsets, NULL);
977 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
980 * Make 'target' refer to the same name as 'source'.
983 REQUIRE(VALID_NAME(source));
984 REQUIRE(VALID_NAME(target));
985 REQUIRE(BINDABLE(target));
987 target->ndata = source->ndata;
988 target->length = source->length;
989 target->labels = source->labels;
990 target->attributes = source->attributes &
991 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
992 DNS_NAMEATTR_DYNOFFSETS);
993 if (target->offsets != NULL && source->labels > 0) {
994 if (source->offsets != NULL)
995 memmove(target->offsets, source->offsets,
998 set_offsets(target, target->offsets, NULL);
1003 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
1004 unsigned char *offsets;
1005 dns_offsets_t odata;
1010 * Make 'name' refer to region 'r'.
1013 REQUIRE(VALID_NAME(name));
1015 REQUIRE(BINDABLE(name));
1017 INIT_OFFSETS(name, offsets, odata);
1019 if (name->buffer != NULL) {
1020 isc_buffer_clear(name->buffer);
1021 isc_buffer_availableregion(name->buffer, &r2);
1022 len = (r->length < r2.length) ? r->length : r2.length;
1023 if (len > DNS_NAME_MAXWIRE)
1024 len = DNS_NAME_MAXWIRE;
1025 memmove(r2.base, r->base, len);
1026 name->ndata = r2.base;
1029 name->ndata = r->base;
1030 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1031 r->length : DNS_NAME_MAXWIRE;
1035 set_offsets(name, offsets, name);
1038 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1041 if (name->buffer != NULL)
1042 isc_buffer_add(name->buffer, name->length);
1046 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1048 * Make 'r' refer to 'name'.
1051 REQUIRE(VALID_NAME(name));
1054 DNS_NAME_TOREGION(name, r);
1058 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1059 const dns_name_t *origin, unsigned int options,
1060 isc_buffer_t *target)
1062 unsigned char *ndata, *label = NULL;
1066 unsigned int value = 0, count = 0;
1067 unsigned int n1 = 0, n2 = 0;
1068 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1070 unsigned char *offsets;
1071 dns_offsets_t odata;
1072 isc_boolean_t downcase;
1075 * Convert the textual representation of a DNS name at source
1076 * into uncompressed wire form stored in target.
1079 * Relative domain names will have 'origin' appended to them
1080 * unless 'origin' is NULL, in which case relative domain names
1081 * will remain relative.
1084 REQUIRE(VALID_NAME(name));
1085 REQUIRE(ISC_BUFFER_VALID(source));
1086 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1087 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1089 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1091 if (target == NULL && name->buffer != NULL) {
1092 target = name->buffer;
1093 isc_buffer_clear(target);
1096 REQUIRE(BINDABLE(name));
1098 INIT_OFFSETS(name, offsets, odata);
1102 * Make 'name' empty in case of failure.
1107 * Set up the state machine.
1109 tdata = (char *)source->base + source->current;
1110 tlen = isc_buffer_remaininglength(source);
1112 ndata = isc_buffer_used(target);
1113 nrem = isc_buffer_availablelength(target);
1121 while (nrem > 0 && tlen > 0 && !done) {
1129 * Is this the root name?
1133 return (DNS_R_EMPTYLABEL);
1141 if (c == '@' && tlen == 0) {
1154 state = ft_initialescape;
1157 state = ft_ordinary;
1159 return (ISC_R_NOSPACE);
1164 return (DNS_R_EMPTYLABEL);
1167 INSIST(labels <= 127);
1168 offsets[labels] = nused;
1177 } else if (c == '\\') {
1181 return (DNS_R_LABELTOOLONG);
1185 c = maptolower[c & 0xff];
1191 case ft_initialescape:
1194 * This looks like a bitstring label, which
1195 * was deprecated. Intentionally drop it.
1197 return (DNS_R_BADLABELTYPE);
1203 if (!isdigit(c & 0xff)) {
1205 return (DNS_R_LABELTOOLONG);
1209 c = maptolower[c & 0xff];
1213 state = ft_ordinary;
1218 state = ft_escdecimal;
1221 if (!isdigit(c & 0xff))
1222 return (DNS_R_BADESCAPE);
1224 value += digitvalue[c & 0xff];
1228 return (DNS_R_BADESCAPE);
1230 return (DNS_R_LABELTOOLONG);
1233 value = maptolower[value];
1237 state = ft_ordinary;
1241 FATAL_ERROR(__FILE__, __LINE__,
1242 "Unexpected state %d", state);
1243 /* Does not return. */
1249 return (ISC_R_NOSPACE);
1251 if (state != ft_ordinary && state != ft_at)
1252 return (ISC_R_UNEXPECTEDEND);
1253 if (state == ft_ordinary) {
1257 INSIST(labels <= 127);
1258 offsets[labels] = nused;
1260 if (origin != NULL) {
1261 if (nrem < origin->length)
1262 return (ISC_R_NOSPACE);
1263 label = origin->ndata;
1264 n1 = origin->length;
1269 INSIST(n2 <= 63); /* no bitstring support */
1276 c = maptolower[c & 0xff];
1282 INSIST(labels <= 127);
1283 offsets[labels] = nused;
1286 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1287 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1290 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1292 name->ndata = (unsigned char *)target->base + target->used;
1293 name->labels = labels;
1294 name->length = nused;
1296 isc_buffer_forward(source, tused);
1297 isc_buffer_add(target, name->length);
1299 return (ISC_R_SUCCESS);
1302 #ifdef ISC_PLATFORM_USETHREADS
1304 free_specific(void *arg) {
1305 dns_name_totextfilter_t *mem = arg;
1306 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1307 /* Stop use being called again. */
1308 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1312 thread_key_mutex_init(void) {
1313 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1317 totext_filter_proc_key_init(void) {
1318 isc_result_t result;
1321 * We need the call to isc_once_do() to support profiled mutex
1322 * otherwise thread_key_mutex could be initialized at compile time.
1324 result = isc_once_do(&once, thread_key_mutex_init);
1325 if (result != ISC_R_SUCCESS)
1328 if (!thread_key_initialized) {
1329 LOCK(&thread_key_mutex);
1330 if (thread_key_mctx == NULL)
1331 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1332 if (result != ISC_R_SUCCESS)
1334 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1335 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1337 if (!thread_key_initialized &&
1338 isc_thread_key_create(&totext_filter_proc_key,
1339 free_specific) != 0) {
1340 result = ISC_R_FAILURE;
1341 isc_mem_detach(&thread_key_mctx);
1343 thread_key_initialized = 1;
1345 UNLOCK(&thread_key_mutex);
1352 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1353 isc_buffer_t *target)
1355 unsigned int options = DNS_NAME_MASTERFILE;
1358 options |= DNS_NAME_OMITFINALDOT;
1359 return (dns_name_totext2(name, options, target));
1363 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1364 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1368 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1370 unsigned char *ndata;
1372 unsigned int nlen, tlen;
1374 unsigned int trem, count;
1375 unsigned int labels;
1376 isc_boolean_t saw_root = ISC_FALSE;
1377 unsigned int oused = target->used;
1378 #ifdef ISC_PLATFORM_USETHREADS
1379 dns_name_totextfilter_t *mem;
1380 dns_name_totextfilter_t totext_filter_proc = NULL;
1381 isc_result_t result;
1383 isc_boolean_t omit_final_dot =
1384 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1387 * This function assumes the name is in proper uncompressed
1390 REQUIRE(VALID_NAME(name));
1391 REQUIRE(ISC_BUFFER_VALID(target));
1393 #ifdef ISC_PLATFORM_USETHREADS
1394 result = totext_filter_proc_key_init();
1395 if (result != ISC_R_SUCCESS)
1398 ndata = name->ndata;
1399 nlen = name->length;
1400 labels = name->labels;
1401 tdata = isc_buffer_used(target);
1402 tlen = isc_buffer_availablelength(target);
1406 if (labels == 0 && nlen == 0) {
1408 * Special handling for an empty name.
1411 return (ISC_R_NOSPACE);
1414 * The names of these booleans are misleading in this case.
1415 * This empty name is not necessarily from the root node of
1416 * the DNS root zone, nor is a final dot going to be included.
1417 * They need to be set this way, though, to keep the "@"
1418 * from being trounced.
1420 saw_root = ISC_TRUE;
1421 omit_final_dot = ISC_FALSE;
1426 * Skip the while() loop.
1429 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1431 * Special handling for the root label.
1434 return (ISC_R_NOSPACE);
1436 saw_root = ISC_TRUE;
1437 omit_final_dot = ISC_FALSE;
1442 * Skip the while() loop.
1447 while (labels > 0 && nlen > 0 && trem > 0) {
1452 saw_root = ISC_TRUE;
1456 INSIST(nlen >= count);
1460 /* Special modifiers in zone files. */
1461 case 0x40: /* '@' */
1462 case 0x24: /* '$' */
1463 if ((options & DNS_NAME_MASTERFILE) == 0)
1466 case 0x22: /* '"' */
1467 case 0x28: /* '(' */
1468 case 0x29: /* ')' */
1469 case 0x2E: /* '.' */
1470 case 0x3B: /* ';' */
1471 case 0x5C: /* '\\' */
1473 return (ISC_R_NOSPACE);
1475 CONVERTFROMASCII(c);
1483 if (c > 0x20 && c < 0x7f) {
1485 return (ISC_R_NOSPACE);
1486 CONVERTFROMASCII(c);
1493 return (ISC_R_NOSPACE);
1499 *tdata++ = 0x30 + (c % 10);
1508 FATAL_ERROR(__FILE__, __LINE__,
1509 "Unexpected label type %02x", count);
1514 * The following assumes names are absolute. If not, we
1515 * fix things up later. Note that this means that in some
1516 * cases one more byte of text buffer is required than is
1517 * needed in the final output.
1520 return (ISC_R_NOSPACE);
1525 if (nlen != 0 && trem == 0)
1526 return (ISC_R_NOSPACE);
1528 if (!saw_root || omit_final_dot)
1531 isc_buffer_add(target, tlen - trem);
1533 #ifdef ISC_PLATFORM_USETHREADS
1534 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1536 totext_filter_proc = *mem;
1538 if (totext_filter_proc != NULL)
1539 return ((*totext_filter_proc)(target, oused, saw_root));
1541 return (ISC_R_SUCCESS);
1545 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1546 isc_buffer_t *target)
1548 unsigned char *ndata;
1550 unsigned int nlen, tlen;
1552 unsigned int trem, count;
1553 unsigned int labels;
1556 * This function assumes the name is in proper uncompressed
1559 REQUIRE(VALID_NAME(name));
1560 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1561 REQUIRE(ISC_BUFFER_VALID(target));
1563 ndata = name->ndata;
1564 nlen = name->length;
1565 labels = name->labels;
1566 tdata = isc_buffer_used(target);
1567 tlen = isc_buffer_availablelength(target);
1571 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1573 * Special handling for the root label.
1576 return (ISC_R_NOSPACE);
1578 omit_final_dot = ISC_FALSE;
1583 * Skip the while() loop.
1588 while (labels > 0 && nlen > 0 && trem > 0) {
1595 INSIST(nlen >= count);
1598 if ((c >= 0x30 && c <= 0x39) || /* digit */
1599 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1600 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1601 c == 0x2D || /* hyphen */
1602 c == 0x5F) /* underscore */
1605 return (ISC_R_NOSPACE);
1607 if (c >= 0x41 && c <= 0x5A)
1609 CONVERTFROMASCII(c);
1616 return (ISC_R_NOSPACE);
1617 sprintf(tdata, "%%%02X", c);
1626 FATAL_ERROR(__FILE__, __LINE__,
1627 "Unexpected label type %02x", count);
1632 * The following assumes names are absolute. If not, we
1633 * fix things up later. Note that this means that in some
1634 * cases one more byte of text buffer is required than is
1635 * needed in the final output.
1638 return (ISC_R_NOSPACE);
1643 if (nlen != 0 && trem == 0)
1644 return (ISC_R_NOSPACE);
1649 isc_buffer_add(target, tlen - trem);
1651 return (ISC_R_SUCCESS);
1655 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1656 unsigned char *sndata, *ndata;
1657 unsigned int nlen, count, labels;
1658 isc_buffer_t buffer;
1661 * Downcase 'source'.
1664 REQUIRE(VALID_NAME(source));
1665 REQUIRE(VALID_NAME(name));
1666 if (source == name) {
1667 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1668 isc_buffer_init(&buffer, source->ndata, source->length);
1670 ndata = source->ndata;
1672 REQUIRE(BINDABLE(name));
1673 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1674 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1675 if (target == NULL) {
1676 target = name->buffer;
1677 isc_buffer_clear(name->buffer);
1679 ndata = (unsigned char *)target->base + target->used;
1680 name->ndata = ndata;
1683 sndata = source->ndata;
1684 nlen = source->length;
1685 labels = source->labels;
1687 if (nlen > (target->length - target->used)) {
1689 return (ISC_R_NOSPACE);
1692 while (labels > 0 && nlen > 0) {
1698 INSIST(nlen >= count);
1700 *ndata++ = maptolower[(*sndata++)];
1705 FATAL_ERROR(__FILE__, __LINE__,
1706 "Unexpected label type %02x", count);
1707 /* Does not return. */
1711 if (source != name) {
1712 name->labels = source->labels;
1713 name->length = source->length;
1714 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1715 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1717 name->attributes = 0;
1718 if (name->labels > 0 && name->offsets != NULL)
1719 set_offsets(name, name->offsets, NULL);
1722 isc_buffer_add(target, name->length);
1724 return (ISC_R_SUCCESS);
1728 set_offsets(const dns_name_t *name, unsigned char *offsets,
1729 dns_name_t *set_name)
1731 unsigned int offset, count, length, nlabels;
1732 unsigned char *ndata;
1733 isc_boolean_t absolute;
1735 ndata = name->ndata;
1736 length = name->length;
1739 absolute = ISC_FALSE;
1740 while (offset != length) {
1741 INSIST(nlabels < 128);
1742 offsets[nlabels++] = offset;
1745 INSIST(count <= 63);
1748 INSIST(offset <= length);
1750 absolute = ISC_TRUE;
1754 if (set_name != NULL) {
1755 INSIST(set_name == name);
1757 set_name->labels = nlabels;
1758 set_name->length = offset;
1760 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1762 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1764 INSIST(nlabels == name->labels);
1765 INSIST(offset == name->length);
1769 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1770 dns_decompress_t *dctx, unsigned int options,
1771 isc_buffer_t *target)
1773 unsigned char *cdata, *ndata;
1774 unsigned int cused; /* Bytes of compressed name data used */
1775 unsigned int nused, labels, n, nmax;
1776 unsigned int current, new_current, biggest_pointer;
1778 fw_state state = fw_start;
1780 unsigned char *offsets;
1781 dns_offsets_t odata;
1782 isc_boolean_t downcase;
1783 isc_boolean_t seen_pointer;
1786 * Copy the possibly-compressed name at source into target,
1787 * decompressing it. Loop prevention is performed by checking
1788 * the new pointer against biggest_pointer.
1791 REQUIRE(VALID_NAME(name));
1792 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1793 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1795 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1797 if (target == NULL && name->buffer != NULL) {
1798 target = name->buffer;
1799 isc_buffer_clear(target);
1802 REQUIRE(dctx != NULL);
1803 REQUIRE(BINDABLE(name));
1805 INIT_OFFSETS(name, offsets, odata);
1808 * Make 'name' empty in case of failure.
1813 * Initialize things to make the compiler happy; they're not required.
1824 ndata = isc_buffer_used(target);
1826 seen_pointer = ISC_FALSE;
1829 * Find the maximum number of uncompressed target name
1830 * bytes we are willing to generate. This is the smaller
1831 * of the available target buffer length and the
1832 * maximum legal domain name length (255).
1834 nmax = isc_buffer_availablelength(target);
1835 if (nmax > DNS_NAME_MAXWIRE)
1836 nmax = DNS_NAME_MAXWIRE;
1838 cdata = isc_buffer_current(source);
1841 current = source->current;
1842 biggest_pointer = current;
1845 * Note: The following code is not optimized for speed, but
1846 * rather for correctness. Speed will be addressed in the future.
1849 while (current < source->active && !done) {
1858 offsets[labels] = nused;
1860 if (nused + c + 1 > nmax)
1867 state = fw_ordinary;
1868 } else if (c >= 128 && c < 192) {
1870 * 14 bit local compression pointer.
1871 * Local compression is no longer an
1874 return (DNS_R_BADLABELTYPE);
1875 } else if (c >= 192) {
1877 * Ordinary 14-bit pointer.
1879 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1881 return (DNS_R_DISALLOWED);
1882 new_current = c & 0x3F;
1883 state = fw_newcurrent;
1885 return (DNS_R_BADLABELTYPE);
1898 if (new_current >= biggest_pointer)
1899 return (DNS_R_BADPOINTER);
1900 biggest_pointer = new_current;
1901 current = new_current;
1902 cdata = (unsigned char *)source->base + current;
1903 seen_pointer = ISC_TRUE;
1907 FATAL_ERROR(__FILE__, __LINE__,
1908 "Unknown state %d", state);
1909 /* Does not return. */
1914 return (ISC_R_UNEXPECTEDEND);
1916 name->ndata = (unsigned char *)target->base + target->used;
1917 name->labels = labels;
1918 name->length = nused;
1919 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1921 isc_buffer_forward(source, cused);
1922 isc_buffer_add(target, name->length);
1924 return (ISC_R_SUCCESS);
1927 if (nmax == DNS_NAME_MAXWIRE)
1929 * The name did not fit even though we had a buffer
1930 * big enough to fit a maximum-length name.
1932 return (DNS_R_NAMETOOLONG);
1935 * The name might fit if only the caller could give us a
1936 * big enough buffer.
1938 return (ISC_R_NOSPACE);
1942 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1943 isc_buffer_t *target)
1945 unsigned int methods;
1946 isc_uint16_t offset;
1947 dns_name_t gp; /* Global compression prefix */
1948 isc_boolean_t gf; /* Global compression target found */
1949 isc_uint16_t go; /* Global compression offset */
1954 * Convert 'name' into wire format, compressing it as specified by the
1955 * compression context 'cctx', and storing the result in 'target'.
1958 REQUIRE(VALID_NAME(name));
1959 REQUIRE(cctx != NULL);
1960 REQUIRE(ISC_BUFFER_VALID(target));
1963 * If 'name' doesn't have an offsets table, make a clone which
1966 if (name->offsets == NULL) {
1967 #if defined(__clang__) && \
1968 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1969 memset(&clname, 0, sizeof(clname));
1971 DNS_NAME_INIT(&clname, clo);
1972 dns_name_clone(name, &clname);
1975 DNS_NAME_INIT(&gp, NULL);
1977 offset = target->used; /*XXX*/
1979 methods = dns_compress_getmethods(cctx);
1981 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1982 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1983 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1988 * If the offset is too high for 14 bit global compression, we're
1991 if (gf && go >= 0x4000)
1995 * Will the compression pointer reduce the message size?
1997 if (gf && (gp.length + 2) >= name->length)
2001 if (target->length - target->used < gp.length)
2002 return (ISC_R_NOSPACE);
2003 (void)memmove((unsigned char *)target->base + target->used,
2004 gp.ndata, (size_t)gp.length);
2005 isc_buffer_add(target, gp.length);
2007 if (target->length - target->used < 2)
2008 return (ISC_R_NOSPACE);
2009 isc_buffer_putuint16(target, go);
2011 dns_compress_add(cctx, name, &gp, offset);
2013 if (target->length - target->used < name->length)
2014 return (ISC_R_NOSPACE);
2015 (void)memmove((unsigned char *)target->base + target->used,
2016 name->ndata, (size_t)name->length);
2017 isc_buffer_add(target, name->length);
2018 dns_compress_add(cctx, name, name, offset);
2020 return (ISC_R_SUCCESS);
2024 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2025 isc_buffer_t *target)
2027 unsigned char *ndata, *offsets;
2028 unsigned int nrem, labels, prefix_length, length;
2029 isc_boolean_t copy_prefix = ISC_TRUE;
2030 isc_boolean_t copy_suffix = ISC_TRUE;
2031 isc_boolean_t absolute = ISC_FALSE;
2032 dns_name_t tmp_name;
2033 dns_offsets_t odata;
2036 * Concatenate 'prefix' and 'suffix'.
2039 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2040 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2041 REQUIRE(name == NULL || VALID_NAME(name));
2042 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2043 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2044 if (prefix == NULL || prefix->labels == 0)
2045 copy_prefix = ISC_FALSE;
2046 if (suffix == NULL || suffix->labels == 0)
2047 copy_suffix = ISC_FALSE;
2049 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2050 absolute = ISC_TRUE;
2051 REQUIRE(!copy_suffix);
2054 DNS_NAME_INIT(&tmp_name, odata);
2057 if (target == NULL) {
2058 INSIST(name->buffer != NULL);
2059 target = name->buffer;
2060 isc_buffer_clear(name->buffer);
2063 REQUIRE(BINDABLE(name));
2068 nrem = target->length - target->used;
2069 ndata = (unsigned char *)target->base + target->used;
2070 if (nrem > DNS_NAME_MAXWIRE)
2071 nrem = DNS_NAME_MAXWIRE;
2076 prefix_length = prefix->length;
2077 length += prefix_length;
2078 labels += prefix->labels;
2081 length += suffix->length;
2082 labels += suffix->labels;
2084 if (length > DNS_NAME_MAXWIRE) {
2086 return (DNS_R_NAMETOOLONG);
2088 if (length > nrem) {
2090 return (ISC_R_NOSPACE);
2094 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2095 absolute = ISC_TRUE;
2096 memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2100 * If 'prefix' and 'name' are the same object, and the object has
2101 * a dedicated buffer, and we're using it, then we don't have to
2104 if (copy_prefix && (prefix != name || prefix->buffer != target))
2105 memmove(ndata, prefix->ndata, prefix_length);
2107 name->ndata = ndata;
2108 name->labels = labels;
2109 name->length = length;
2111 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2113 name->attributes = 0;
2115 if (name->labels > 0 && name->offsets != NULL) {
2116 INIT_OFFSETS(name, offsets, odata);
2117 set_offsets(name, offsets, NULL);
2120 isc_buffer_add(target, name->length);
2122 return (ISC_R_SUCCESS);
2126 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2127 dns_name_t *prefix, dns_name_t *suffix)
2130 unsigned int splitlabel;
2132 REQUIRE(VALID_NAME(name));
2133 REQUIRE(suffixlabels > 0);
2134 REQUIRE(suffixlabels < name->labels);
2135 REQUIRE(prefix != NULL || suffix != NULL);
2136 REQUIRE(prefix == NULL ||
2137 (VALID_NAME(prefix) &&
2139 REQUIRE(suffix == NULL ||
2140 (VALID_NAME(suffix) &&
2143 splitlabel = name->labels - suffixlabels;
2146 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2149 dns_name_getlabelsequence(name, splitlabel,
2150 suffixlabels, suffix);
2156 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2160 * Make 'target' a dynamically allocated copy of 'source'.
2163 REQUIRE(VALID_NAME(source));
2164 REQUIRE(source->length > 0);
2165 REQUIRE(VALID_NAME(target));
2166 REQUIRE(BINDABLE(target));
2169 * Make 'target' empty in case of failure.
2173 target->ndata = isc_mem_get(mctx, source->length);
2174 if (target->ndata == NULL)
2175 return (ISC_R_NOMEMORY);
2177 memmove(target->ndata, source->ndata, source->length);
2179 target->length = source->length;
2180 target->labels = source->labels;
2181 target->attributes = DNS_NAMEATTR_DYNAMIC;
2182 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2183 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2184 if (target->offsets != NULL) {
2185 if (source->offsets != NULL)
2186 memmove(target->offsets, source->offsets,
2189 set_offsets(target, target->offsets, NULL);
2192 return (ISC_R_SUCCESS);
2196 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2200 * Make 'target' a read-only dynamically allocated copy of 'source'.
2201 * 'target' will also have a dynamically allocated offsets table.
2204 REQUIRE(VALID_NAME(source));
2205 REQUIRE(source->length > 0);
2206 REQUIRE(VALID_NAME(target));
2207 REQUIRE(BINDABLE(target));
2208 REQUIRE(target->offsets == NULL);
2211 * Make 'target' empty in case of failure.
2215 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2216 if (target->ndata == NULL)
2217 return (ISC_R_NOMEMORY);
2219 memmove(target->ndata, source->ndata, source->length);
2221 target->length = source->length;
2222 target->labels = source->labels;
2223 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2224 DNS_NAMEATTR_READONLY;
2225 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2226 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2227 target->offsets = target->ndata + source->length;
2228 if (source->offsets != NULL)
2229 memmove(target->offsets, source->offsets, source->labels);
2231 set_offsets(target, target->offsets, NULL);
2233 return (ISC_R_SUCCESS);
2237 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2244 REQUIRE(VALID_NAME(name));
2245 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2247 size = name->length;
2248 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2249 size += name->labels;
2250 isc_mem_put(mctx, name->ndata, size);
2251 dns_name_invalidate(name);
2255 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2256 dns_name_t downname;
2257 unsigned char data[256];
2258 isc_buffer_t buffer;
2259 isc_result_t result;
2263 * Send 'name' in DNSSEC canonical form to 'digest'.
2266 REQUIRE(VALID_NAME(name));
2267 REQUIRE(digest != NULL);
2269 #if defined(__clang__) && \
2270 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2271 memset(&downname, 0, sizeof(downname));
2273 DNS_NAME_INIT(&downname, NULL);
2275 isc_buffer_init(&buffer, data, sizeof(data));
2277 result = dns_name_downcase(name, &downname, &buffer);
2278 if (result != ISC_R_SUCCESS)
2281 isc_buffer_usedregion(&buffer, &r);
2283 return ((digest)(arg, &r));
2287 dns_name_dynamic(dns_name_t *name) {
2288 REQUIRE(VALID_NAME(name));
2291 * Returns whether there is dynamic memory associated with this name.
2294 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2295 ISC_TRUE : ISC_FALSE);
2299 dns_name_print(dns_name_t *name, FILE *stream) {
2300 isc_result_t result;
2306 * Print 'name' on 'stream'.
2309 REQUIRE(VALID_NAME(name));
2311 isc_buffer_init(&b, t, sizeof(t));
2312 result = dns_name_totext(name, ISC_FALSE, &b);
2313 if (result != ISC_R_SUCCESS)
2315 isc_buffer_usedregion(&b, &r);
2316 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2318 return (ISC_R_SUCCESS);
2322 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2323 #ifdef ISC_PLATFORM_USETHREADS
2324 isc_result_t result;
2325 dns_name_totextfilter_t *mem;
2328 result = totext_filter_proc_key_init();
2329 if (result != ISC_R_SUCCESS)
2333 * If we already have been here set / clear as appropriate.
2334 * Otherwise allocate memory.
2336 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2337 if (mem != NULL && proc != NULL) {
2339 return (ISC_R_SUCCESS);
2342 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2343 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2345 result = ISC_R_UNEXPECTED;
2349 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2351 return (ISC_R_NOMEMORY);
2353 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2354 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2355 result = ISC_R_UNEXPECTED;
2359 totext_filter_proc = proc;
2360 return (ISC_R_SUCCESS);
2365 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2366 isc_result_t result;
2372 * Leave room for null termination after buffer.
2374 isc_buffer_init(&buf, cp, size - 1);
2375 result = dns_name_totext(name, ISC_TRUE, &buf);
2376 if (result == ISC_R_SUCCESS) {
2381 isc_buffer_usedregion(&buf, &r);
2382 ((char *) r.base)[r.length] = '\0';
2385 snprintf(cp, size, "<unknown>");
2389 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2393 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2394 isc_result_t result;
2397 char *p, txt[DNS_NAME_FORMATSIZE];
2399 REQUIRE(VALID_NAME(name));
2400 REQUIRE(target != NULL && *target == NULL);
2402 isc_buffer_init(&buf, txt, sizeof(txt));
2403 result = dns_name_totext(name, ISC_FALSE, &buf);
2404 if (result != ISC_R_SUCCESS)
2407 isc_buffer_usedregion(&buf, ®);
2408 p = isc_mem_allocate(mctx, reg.length + 1);
2410 return (ISC_R_NOMEMORY);
2411 memmove(p, (char *) reg.base, (int) reg.length);
2412 p[reg.length] = '\0';
2415 return (ISC_R_SUCCESS);
2419 * dns_name_fromstring() -- convert directly from a string to a name,
2420 * allocating memory as needed
2423 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2426 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2430 dns_name_fromstring2(dns_name_t *target, const char *src,
2431 const dns_name_t *origin, unsigned int options,
2434 isc_result_t result;
2439 REQUIRE(src != NULL);
2441 isc_buffer_constinit(&buf, src, strlen(src));
2442 isc_buffer_add(&buf, strlen(src));
2443 if (BINDABLE(target) && target->buffer != NULL)
2446 dns_fixedname_init(&fn);
2447 name = dns_fixedname_name(&fn);
2450 result = dns_name_fromtext(name, &buf, origin, options, NULL);
2451 if (result != ISC_R_SUCCESS)
2455 result = dns_name_dupwithoffsets(name, mctx, target);
2460 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2461 unsigned char *ndata;
2464 * Make dest a copy of source.
2467 REQUIRE(VALID_NAME(source));
2468 REQUIRE(VALID_NAME(dest));
2469 REQUIRE(target != NULL || dest->buffer != NULL);
2471 if (target == NULL) {
2472 target = dest->buffer;
2473 isc_buffer_clear(dest->buffer);
2476 REQUIRE(BINDABLE(dest));
2481 if (target->length - target->used < source->length)
2482 return (ISC_R_NOSPACE);
2484 ndata = (unsigned char *)target->base + target->used;
2485 dest->ndata = target->base;
2487 memmove(ndata, source->ndata, source->length);
2489 dest->ndata = ndata;
2490 dest->labels = source->labels;
2491 dest->length = source->length;
2492 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2493 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2495 dest->attributes = 0;
2497 if (dest->labels > 0 && dest->offsets != NULL) {
2498 if (source->offsets != NULL)
2499 memmove(dest->offsets, source->offsets, source->labels);
2501 set_offsets(dest, dest->offsets, NULL);
2504 isc_buffer_add(target, dest->length);
2506 return (ISC_R_SUCCESS);
2510 dns_name_destroy(void) {
2511 #ifdef ISC_PLATFORM_USETHREADS
2512 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2515 LOCK(&thread_key_mutex);
2516 if (thread_key_initialized) {
2517 isc_mem_detach(&thread_key_mctx);
2518 isc_thread_key_delete(totext_filter_proc_key);
2519 thread_key_initialized = 0;
2521 UNLOCK(&thread_key_mutex);
2527 * Service Discovery Prefixes RFC 6763.
2529 static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
2530 static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
2531 static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
2532 static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
2533 static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
2534 static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
2535 static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
2536 static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
2537 static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
2538 static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
2540 static const dns_name_t dns_sd[] = {
2543 b_dns_sd_udp_data, 15, 3,
2544 DNS_NAMEATTR_READONLY,
2545 b_dns_sd_udp_offsets, NULL,
2546 {(void *)-1, (void *)-1},
2551 db_dns_sd_udp_data, 16, 3,
2552 DNS_NAMEATTR_READONLY,
2553 db_dns_sd_udp_offsets, NULL,
2554 {(void *)-1, (void *)-1},
2559 r_dns_sd_udp_data, 15, 3,
2560 DNS_NAMEATTR_READONLY,
2561 r_dns_sd_udp_offsets, NULL,
2562 {(void *)-1, (void *)-1},
2567 dr_dns_sd_udp_data, 16, 3,
2568 DNS_NAMEATTR_READONLY,
2569 dr_dns_sd_udp_offsets, NULL,
2570 {(void *)-1, (void *)-1},
2575 lb_dns_sd_udp_data, 16, 3,
2576 DNS_NAMEATTR_READONLY,
2577 lb_dns_sd_udp_offsets, NULL,
2578 {(void *)-1, (void *)-1},
2584 dns_name_isdnssd(const dns_name_t *name) {
2588 if (dns_name_countlabels(name) > 3U) {
2589 dns_name_init(&prefix, NULL);
2590 dns_name_getlabelsequence(name, 0, 3, &prefix);
2591 for (i = 0; i < (sizeof(dns_sd)/sizeof(dns_sd[0])); i++)
2592 if (dns_name_equal(&prefix, &dns_sd[i]))
2599 #define NS_NAME_INIT(A,B) \
2602 A, sizeof(A), sizeof(B), \
2603 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
2604 B, NULL, { (void *)-1, (void *)-1}, \
2608 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
2609 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
2610 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
2612 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
2614 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
2615 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
2616 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
2617 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
2618 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
2619 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
2620 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
2621 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
2622 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
2623 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
2624 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
2625 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
2626 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
2627 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
2628 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
2629 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
2631 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
2633 static dns_name_t const rfc1918names[] = {
2634 NS_NAME_INIT(inaddr10, inaddr10_offsets),
2635 NS_NAME_INIT(inaddr16172, inaddr172_offsets),
2636 NS_NAME_INIT(inaddr17172, inaddr172_offsets),
2637 NS_NAME_INIT(inaddr18172, inaddr172_offsets),
2638 NS_NAME_INIT(inaddr19172, inaddr172_offsets),
2639 NS_NAME_INIT(inaddr20172, inaddr172_offsets),
2640 NS_NAME_INIT(inaddr21172, inaddr172_offsets),
2641 NS_NAME_INIT(inaddr22172, inaddr172_offsets),
2642 NS_NAME_INIT(inaddr23172, inaddr172_offsets),
2643 NS_NAME_INIT(inaddr24172, inaddr172_offsets),
2644 NS_NAME_INIT(inaddr25172, inaddr172_offsets),
2645 NS_NAME_INIT(inaddr26172, inaddr172_offsets),
2646 NS_NAME_INIT(inaddr27172, inaddr172_offsets),
2647 NS_NAME_INIT(inaddr28172, inaddr172_offsets),
2648 NS_NAME_INIT(inaddr29172, inaddr172_offsets),
2649 NS_NAME_INIT(inaddr30172, inaddr172_offsets),
2650 NS_NAME_INIT(inaddr31172, inaddr172_offsets),
2651 NS_NAME_INIT(inaddr168192, inaddr192_offsets)
2655 dns_name_isrfc1918(const dns_name_t *name) {
2658 for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++)
2659 if (dns_name_issubdomain(name, &rfc1918names[i]))
2664 static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
2665 static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
2666 static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
2668 static dns_name_t const ulanames[] = {
2669 NS_NAME_INIT(ip6fc, ulaoffsets),
2670 NS_NAME_INIT(ip6fd, ulaoffsets),
2674 dns_name_isula(const dns_name_t *name) {
2677 for (i = 0; i < (sizeof(ulanames)/sizeof(*ulanames)); i++)
2678 if (dns_name_issubdomain(name, &ulanames[i]))