2 * Copyright (C) 2004-2014 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 if (name1 == name2) {
583 return (dns_namereln_equal);
586 SETUP_OFFSETS(name1, offsets1, odata1);
587 SETUP_OFFSETS(name2, offsets2, odata2);
594 ldiff = 0 - (l2 - l1);
604 label1 = &name1->ndata[offsets1[l1]];
605 label2 = &name2->ndata[offsets2[l2]];
610 * We dropped bitstring labels, and we don't support any
611 * other extended label types.
613 INSIST(count1 <= 63 && count2 <= 63);
615 cdiff = (int)count1 - (int)count2;
622 chdiff = (int)maptolower[*label1] -
623 (int)maptolower[*label2];
641 namereln = dns_namereln_contains;
643 namereln = dns_namereln_subdomain;
645 namereln = dns_namereln_equal;
650 if (nlabels > 0 && namereln == dns_namereln_none)
651 namereln = dns_namereln_commonancestor;
657 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
659 unsigned int nlabels;
662 * Determine the relative ordering under the DNSSEC order relation of
663 * 'name1' and 'name2'.
665 * Note: It makes no sense for one of the names to be relative and the
666 * other absolute. If both names are relative, then to be meaningfully
667 * compared the caller must ensure that they are both relative to the
671 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
677 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
678 unsigned int l, count;
680 unsigned char *label1, *label2;
683 * Are 'name1' and 'name2' equal?
685 * Note: It makes no sense for one of the names to be relative and the
686 * other absolute. If both names are relative, then to be meaningfully
687 * compared the caller must ensure that they are both relative to the
691 REQUIRE(VALID_NAME(name1));
692 REQUIRE(VALID_NAME(name2));
694 * Either name1 is absolute and name2 is absolute, or neither is.
696 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
697 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
702 if (name1->length != name2->length)
707 if (l != name2->labels)
710 label1 = name1->ndata;
711 label2 = name2->ndata;
715 if (count != *label2++)
718 INSIST(count <= 63); /* no bitstring support */
722 c = maptolower[*label1++];
723 if (c != maptolower[*label2++])
732 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
735 * Are 'name1' and 'name2' equal?
737 * Note: It makes no sense for one of the names to be relative and the
738 * other absolute. If both names are relative, then to be meaningfully
739 * compared the caller must ensure that they are both relative to the
743 REQUIRE(VALID_NAME(name1));
744 REQUIRE(VALID_NAME(name2));
746 * Either name1 is absolute and name2 is absolute, or neither is.
748 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
749 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
751 if (name1->length != name2->length)
754 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
761 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
762 unsigned int l1, l2, l, count1, count2, count;
763 unsigned char c1, c2;
764 unsigned char *label1, *label2;
767 * Compare two absolute names as rdata.
770 REQUIRE(VALID_NAME(name1));
771 REQUIRE(name1->labels > 0);
772 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
773 REQUIRE(VALID_NAME(name2));
774 REQUIRE(name2->labels > 0);
775 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
780 l = (l1 < l2) ? l1 : l2;
782 label1 = name1->ndata;
783 label2 = name2->ndata;
789 /* no bitstring support */
790 INSIST(count1 <= 63 && count2 <= 63);
792 if (count1 != count2)
793 return ((count1 < count2) ? -1 : 1);
797 c1 = maptolower[*label1++];
798 c2 = maptolower[*label2++];
807 * If one name had more labels than the other, their common
808 * prefix must have been different because the shorter name
809 * ended with the root label and the longer one can't have
810 * a root label in the middle of it. Therefore, if we get
811 * to this point, the lengths must be equal.
819 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
821 unsigned int nlabels;
822 dns_namereln_t namereln;
825 * Is 'name1' a subdomain of 'name2'?
827 * Note: It makes no sense for one of the names to be relative and the
828 * other absolute. If both names are relative, then to be meaningfully
829 * compared the caller must ensure that they are both relative to the
833 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
834 if (namereln == dns_namereln_subdomain ||
835 namereln == dns_namereln_equal)
842 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
844 unsigned int nlabels, labels;
847 REQUIRE(VALID_NAME(name));
848 REQUIRE(name->labels > 0);
849 REQUIRE(VALID_NAME(wname));
850 labels = wname->labels;
852 REQUIRE(dns_name_iswildcard(wname));
854 #if defined(__clang__) && \
855 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
856 memset(&tname, 0, sizeof(tname));
858 DNS_NAME_INIT(&tname, NULL);
859 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
860 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
861 dns_namereln_subdomain)
867 dns_name_countlabels(const dns_name_t *name) {
869 * How many labels does 'name' have?
872 REQUIRE(VALID_NAME(name));
874 ENSURE(name->labels <= 128);
876 return (name->labels);
880 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
881 unsigned char *offsets;
885 * Make 'label' refer to the 'n'th least significant label of 'name'.
888 REQUIRE(VALID_NAME(name));
889 REQUIRE(name->labels > 0);
890 REQUIRE(n < name->labels);
891 REQUIRE(label != NULL);
893 SETUP_OFFSETS(name, offsets, odata);
895 label->base = &name->ndata[offsets[n]];
896 if (n == name->labels - 1)
897 label->length = name->length - offsets[n];
899 label->length = offsets[n + 1] - offsets[n];
903 dns_name_getlabelsequence(const dns_name_t *source,
904 unsigned int first, unsigned int n,
907 unsigned char *offsets;
909 unsigned int firstoffset, endoffset;
912 * Make 'target' refer to the 'n' labels including and following
913 * 'first' in 'source'.
916 REQUIRE(VALID_NAME(source));
917 REQUIRE(VALID_NAME(target));
918 REQUIRE(first <= source->labels);
919 REQUIRE(n <= source->labels - first); /* note first+n could overflow */
920 REQUIRE(BINDABLE(target));
922 SETUP_OFFSETS(source, offsets, odata);
924 if (first == source->labels)
925 firstoffset = source->length;
927 firstoffset = offsets[first];
929 if (first + n == source->labels)
930 endoffset = source->length;
932 endoffset = offsets[first + n];
934 target->ndata = &source->ndata[firstoffset];
935 target->length = endoffset - firstoffset;
937 if (first + n == source->labels && n > 0 &&
938 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
939 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
941 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
946 * If source and target are the same, and we're making target
947 * a prefix of source, the offsets table is correct already
948 * so we don't need to call set_offsets().
950 if (target->offsets != NULL &&
951 (target != source || first != 0))
952 set_offsets(target, target->offsets, NULL);
956 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
959 * Make 'target' refer to the same name as 'source'.
962 REQUIRE(VALID_NAME(source));
963 REQUIRE(VALID_NAME(target));
964 REQUIRE(BINDABLE(target));
966 target->ndata = source->ndata;
967 target->length = source->length;
968 target->labels = source->labels;
969 target->attributes = source->attributes &
970 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
971 DNS_NAMEATTR_DYNOFFSETS);
972 if (target->offsets != NULL && source->labels > 0) {
973 if (source->offsets != NULL)
974 memmove(target->offsets, source->offsets,
977 set_offsets(target, target->offsets, NULL);
982 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
983 unsigned char *offsets;
989 * Make 'name' refer to region 'r'.
992 REQUIRE(VALID_NAME(name));
994 REQUIRE(BINDABLE(name));
996 INIT_OFFSETS(name, offsets, odata);
998 if (name->buffer != NULL) {
999 isc_buffer_clear(name->buffer);
1000 isc_buffer_availableregion(name->buffer, &r2);
1001 len = (r->length < r2.length) ? r->length : r2.length;
1002 if (len > DNS_NAME_MAXWIRE)
1003 len = DNS_NAME_MAXWIRE;
1004 memmove(r2.base, r->base, len);
1005 name->ndata = r2.base;
1008 name->ndata = r->base;
1009 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1010 r->length : DNS_NAME_MAXWIRE;
1014 set_offsets(name, offsets, name);
1017 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1020 if (name->buffer != NULL)
1021 isc_buffer_add(name->buffer, name->length);
1025 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1027 * Make 'r' refer to 'name'.
1030 REQUIRE(VALID_NAME(name));
1033 DNS_NAME_TOREGION(name, r);
1037 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1038 const dns_name_t *origin, unsigned int options,
1039 isc_buffer_t *target)
1041 unsigned char *ndata, *label = NULL;
1045 unsigned int value = 0, count = 0;
1046 unsigned int n1 = 0, n2 = 0;
1047 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1049 unsigned char *offsets;
1050 dns_offsets_t odata;
1051 isc_boolean_t downcase;
1054 * Convert the textual representation of a DNS name at source
1055 * into uncompressed wire form stored in target.
1058 * Relative domain names will have 'origin' appended to them
1059 * unless 'origin' is NULL, in which case relative domain names
1060 * will remain relative.
1063 REQUIRE(VALID_NAME(name));
1064 REQUIRE(ISC_BUFFER_VALID(source));
1065 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1066 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1068 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1070 if (target == NULL && name->buffer != NULL) {
1071 target = name->buffer;
1072 isc_buffer_clear(target);
1075 REQUIRE(BINDABLE(name));
1077 INIT_OFFSETS(name, offsets, odata);
1081 * Make 'name' empty in case of failure.
1086 * Set up the state machine.
1088 tdata = (char *)source->base + source->current;
1089 tlen = isc_buffer_remaininglength(source);
1091 ndata = isc_buffer_used(target);
1092 nrem = isc_buffer_availablelength(target);
1100 while (nrem > 0 && tlen > 0 && !done) {
1108 * Is this the root name?
1112 return (DNS_R_EMPTYLABEL);
1120 if (c == '@' && tlen == 0) {
1133 state = ft_initialescape;
1136 state = ft_ordinary;
1138 return (ISC_R_NOSPACE);
1143 return (DNS_R_EMPTYLABEL);
1146 INSIST(labels <= 127);
1147 offsets[labels] = nused;
1156 } else if (c == '\\') {
1160 return (DNS_R_LABELTOOLONG);
1164 c = maptolower[(int)c];
1170 case ft_initialescape:
1173 * This looks like a bitstring label, which
1174 * was deprecated. Intentionally drop it.
1176 return (DNS_R_BADLABELTYPE);
1182 if (!isdigit(c & 0xff)) {
1184 return (DNS_R_LABELTOOLONG);
1188 c = maptolower[(int)c];
1192 state = ft_ordinary;
1197 state = ft_escdecimal;
1200 if (!isdigit(c & 0xff))
1201 return (DNS_R_BADESCAPE);
1203 value += digitvalue[(int)c];
1207 return (DNS_R_BADESCAPE);
1209 return (DNS_R_LABELTOOLONG);
1212 value = maptolower[value];
1216 state = ft_ordinary;
1220 FATAL_ERROR(__FILE__, __LINE__,
1221 "Unexpected state %d", state);
1222 /* Does not return. */
1228 return (ISC_R_NOSPACE);
1230 if (state != ft_ordinary && state != ft_at)
1231 return (ISC_R_UNEXPECTEDEND);
1232 if (state == ft_ordinary) {
1236 INSIST(labels <= 127);
1237 offsets[labels] = nused;
1239 if (origin != NULL) {
1240 if (nrem < origin->length)
1241 return (ISC_R_NOSPACE);
1242 label = origin->ndata;
1243 n1 = origin->length;
1248 INSIST(n2 <= 63); /* no bitstring support */
1255 c = maptolower[(int)c];
1261 INSIST(labels <= 127);
1262 offsets[labels] = nused;
1265 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1266 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1269 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1271 name->ndata = (unsigned char *)target->base + target->used;
1272 name->labels = labels;
1273 name->length = nused;
1275 isc_buffer_forward(source, tused);
1276 isc_buffer_add(target, name->length);
1278 return (ISC_R_SUCCESS);
1281 #ifdef ISC_PLATFORM_USETHREADS
1283 free_specific(void *arg) {
1284 dns_name_totextfilter_t *mem = arg;
1285 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1286 /* Stop use being called again. */
1287 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1291 thread_key_mutex_init(void) {
1292 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1296 totext_filter_proc_key_init(void) {
1297 isc_result_t result;
1300 * We need the call to isc_once_do() to support profiled mutex
1301 * otherwise thread_key_mutex could be initialized at compile time.
1303 result = isc_once_do(&once, thread_key_mutex_init);
1304 if (result != ISC_R_SUCCESS)
1307 if (!thread_key_initialized) {
1308 LOCK(&thread_key_mutex);
1309 if (thread_key_mctx == NULL)
1310 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1311 if (result != ISC_R_SUCCESS)
1313 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1314 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1316 if (!thread_key_initialized &&
1317 isc_thread_key_create(&totext_filter_proc_key,
1318 free_specific) != 0) {
1319 result = ISC_R_FAILURE;
1320 isc_mem_detach(&thread_key_mctx);
1322 thread_key_initialized = 1;
1324 UNLOCK(&thread_key_mutex);
1331 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1332 isc_buffer_t *target)
1334 unsigned int options = DNS_NAME_MASTERFILE;
1337 options |= DNS_NAME_OMITFINALDOT;
1338 return (dns_name_totext2(name, options, target));
1342 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1343 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1347 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1349 unsigned char *ndata;
1351 unsigned int nlen, tlen;
1353 unsigned int trem, count;
1354 unsigned int labels;
1355 isc_boolean_t saw_root = ISC_FALSE;
1356 unsigned int oused = target->used;
1357 #ifdef ISC_PLATFORM_USETHREADS
1358 dns_name_totextfilter_t *mem;
1359 dns_name_totextfilter_t totext_filter_proc = NULL;
1360 isc_result_t result;
1362 isc_boolean_t omit_final_dot =
1363 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1366 * This function assumes the name is in proper uncompressed
1369 REQUIRE(VALID_NAME(name));
1370 REQUIRE(ISC_BUFFER_VALID(target));
1372 #ifdef ISC_PLATFORM_USETHREADS
1373 result = totext_filter_proc_key_init();
1374 if (result != ISC_R_SUCCESS)
1377 ndata = name->ndata;
1378 nlen = name->length;
1379 labels = name->labels;
1380 tdata = isc_buffer_used(target);
1381 tlen = isc_buffer_availablelength(target);
1385 if (labels == 0 && nlen == 0) {
1387 * Special handling for an empty name.
1390 return (ISC_R_NOSPACE);
1393 * The names of these booleans are misleading in this case.
1394 * This empty name is not necessarily from the root node of
1395 * the DNS root zone, nor is a final dot going to be included.
1396 * They need to be set this way, though, to keep the "@"
1397 * from being trounced.
1399 saw_root = ISC_TRUE;
1400 omit_final_dot = ISC_FALSE;
1405 * Skip the while() loop.
1408 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1410 * Special handling for the root label.
1413 return (ISC_R_NOSPACE);
1415 saw_root = ISC_TRUE;
1416 omit_final_dot = ISC_FALSE;
1421 * Skip the while() loop.
1426 while (labels > 0 && nlen > 0 && trem > 0) {
1431 saw_root = ISC_TRUE;
1435 INSIST(nlen >= count);
1439 /* Special modifiers in zone files. */
1440 case 0x40: /* '@' */
1441 case 0x24: /* '$' */
1442 if ((options & DNS_NAME_MASTERFILE) == 0)
1445 case 0x22: /* '"' */
1446 case 0x28: /* '(' */
1447 case 0x29: /* ')' */
1448 case 0x2E: /* '.' */
1449 case 0x3B: /* ';' */
1450 case 0x5C: /* '\\' */
1452 return (ISC_R_NOSPACE);
1454 CONVERTFROMASCII(c);
1462 if (c > 0x20 && c < 0x7f) {
1464 return (ISC_R_NOSPACE);
1465 CONVERTFROMASCII(c);
1472 return (ISC_R_NOSPACE);
1478 *tdata++ = 0x30 + (c % 10);
1487 FATAL_ERROR(__FILE__, __LINE__,
1488 "Unexpected label type %02x", count);
1493 * The following assumes names are absolute. If not, we
1494 * fix things up later. Note that this means that in some
1495 * cases one more byte of text buffer is required than is
1496 * needed in the final output.
1499 return (ISC_R_NOSPACE);
1504 if (nlen != 0 && trem == 0)
1505 return (ISC_R_NOSPACE);
1507 if (!saw_root || omit_final_dot)
1510 isc_buffer_add(target, tlen - trem);
1512 #ifdef ISC_PLATFORM_USETHREADS
1513 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1515 totext_filter_proc = *mem;
1517 if (totext_filter_proc != NULL)
1518 return ((*totext_filter_proc)(target, oused, saw_root));
1520 return (ISC_R_SUCCESS);
1524 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1525 isc_buffer_t *target)
1527 unsigned char *ndata;
1529 unsigned int nlen, tlen;
1531 unsigned int trem, count;
1532 unsigned int labels;
1535 * This function assumes the name is in proper uncompressed
1538 REQUIRE(VALID_NAME(name));
1539 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1540 REQUIRE(ISC_BUFFER_VALID(target));
1542 ndata = name->ndata;
1543 nlen = name->length;
1544 labels = name->labels;
1545 tdata = isc_buffer_used(target);
1546 tlen = isc_buffer_availablelength(target);
1550 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1552 * Special handling for the root label.
1555 return (ISC_R_NOSPACE);
1557 omit_final_dot = ISC_FALSE;
1562 * Skip the while() loop.
1567 while (labels > 0 && nlen > 0 && trem > 0) {
1574 INSIST(nlen >= count);
1577 if ((c >= 0x30 && c <= 0x39) || /* digit */
1578 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1579 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1580 c == 0x2D || /* hyphen */
1581 c == 0x5F) /* underscore */
1584 return (ISC_R_NOSPACE);
1586 if (c >= 0x41 && c <= 0x5A)
1588 CONVERTFROMASCII(c);
1595 return (ISC_R_NOSPACE);
1596 sprintf(tdata, "%%%02X", c);
1605 FATAL_ERROR(__FILE__, __LINE__,
1606 "Unexpected label type %02x", count);
1611 * The following assumes names are absolute. If not, we
1612 * fix things up later. Note that this means that in some
1613 * cases one more byte of text buffer is required than is
1614 * needed in the final output.
1617 return (ISC_R_NOSPACE);
1622 if (nlen != 0 && trem == 0)
1623 return (ISC_R_NOSPACE);
1628 isc_buffer_add(target, tlen - trem);
1630 return (ISC_R_SUCCESS);
1634 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1635 unsigned char *sndata, *ndata;
1636 unsigned int nlen, count, labels;
1637 isc_buffer_t buffer;
1640 * Downcase 'source'.
1643 REQUIRE(VALID_NAME(source));
1644 REQUIRE(VALID_NAME(name));
1645 if (source == name) {
1646 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1647 isc_buffer_init(&buffer, source->ndata, source->length);
1649 ndata = source->ndata;
1651 REQUIRE(BINDABLE(name));
1652 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1653 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1654 if (target == NULL) {
1655 target = name->buffer;
1656 isc_buffer_clear(name->buffer);
1658 ndata = (unsigned char *)target->base + target->used;
1659 name->ndata = ndata;
1662 sndata = source->ndata;
1663 nlen = source->length;
1664 labels = source->labels;
1666 if (nlen > (target->length - target->used)) {
1668 return (ISC_R_NOSPACE);
1671 while (labels > 0 && nlen > 0) {
1677 INSIST(nlen >= count);
1679 *ndata++ = maptolower[(*sndata++)];
1684 FATAL_ERROR(__FILE__, __LINE__,
1685 "Unexpected label type %02x", count);
1686 /* Does not return. */
1690 if (source != name) {
1691 name->labels = source->labels;
1692 name->length = source->length;
1693 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1694 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1696 name->attributes = 0;
1697 if (name->labels > 0 && name->offsets != NULL)
1698 set_offsets(name, name->offsets, NULL);
1701 isc_buffer_add(target, name->length);
1703 return (ISC_R_SUCCESS);
1707 set_offsets(const dns_name_t *name, unsigned char *offsets,
1708 dns_name_t *set_name)
1710 unsigned int offset, count, length, nlabels;
1711 unsigned char *ndata;
1712 isc_boolean_t absolute;
1714 ndata = name->ndata;
1715 length = name->length;
1718 absolute = ISC_FALSE;
1719 while (offset != length) {
1720 INSIST(nlabels < 128);
1721 offsets[nlabels++] = offset;
1724 INSIST(count <= 63);
1727 INSIST(offset <= length);
1729 absolute = ISC_TRUE;
1733 if (set_name != NULL) {
1734 INSIST(set_name == name);
1736 set_name->labels = nlabels;
1737 set_name->length = offset;
1739 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1741 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1743 INSIST(nlabels == name->labels);
1744 INSIST(offset == name->length);
1748 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1749 dns_decompress_t *dctx, unsigned int options,
1750 isc_buffer_t *target)
1752 unsigned char *cdata, *ndata;
1753 unsigned int cused; /* Bytes of compressed name data used */
1754 unsigned int nused, labels, n, nmax;
1755 unsigned int current, new_current, biggest_pointer;
1757 fw_state state = fw_start;
1759 unsigned char *offsets;
1760 dns_offsets_t odata;
1761 isc_boolean_t downcase;
1762 isc_boolean_t seen_pointer;
1765 * Copy the possibly-compressed name at source into target,
1766 * decompressing it. Loop prevention is performed by checking
1767 * the new pointer against biggest_pointer.
1770 REQUIRE(VALID_NAME(name));
1771 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1772 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1774 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1776 if (target == NULL && name->buffer != NULL) {
1777 target = name->buffer;
1778 isc_buffer_clear(target);
1781 REQUIRE(dctx != NULL);
1782 REQUIRE(BINDABLE(name));
1784 INIT_OFFSETS(name, offsets, odata);
1787 * Make 'name' empty in case of failure.
1792 * Initialize things to make the compiler happy; they're not required.
1803 ndata = isc_buffer_used(target);
1805 seen_pointer = ISC_FALSE;
1808 * Find the maximum number of uncompressed target name
1809 * bytes we are willing to generate. This is the smaller
1810 * of the available target buffer length and the
1811 * maximum legal domain name length (255).
1813 nmax = isc_buffer_availablelength(target);
1814 if (nmax > DNS_NAME_MAXWIRE)
1815 nmax = DNS_NAME_MAXWIRE;
1817 cdata = isc_buffer_current(source);
1820 current = source->current;
1821 biggest_pointer = current;
1824 * Note: The following code is not optimized for speed, but
1825 * rather for correctness. Speed will be addressed in the future.
1828 while (current < source->active && !done) {
1837 offsets[labels] = nused;
1839 if (nused + c + 1 > nmax)
1846 state = fw_ordinary;
1847 } else if (c >= 128 && c < 192) {
1849 * 14 bit local compression pointer.
1850 * Local compression is no longer an
1853 return (DNS_R_BADLABELTYPE);
1854 } else if (c >= 192) {
1856 * Ordinary 14-bit pointer.
1858 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1860 return (DNS_R_DISALLOWED);
1861 new_current = c & 0x3F;
1863 state = fw_newcurrent;
1865 return (DNS_R_BADLABELTYPE);
1883 if (new_current >= biggest_pointer)
1884 return (DNS_R_BADPOINTER);
1885 biggest_pointer = new_current;
1886 current = new_current;
1887 cdata = (unsigned char *)source->base + current;
1888 seen_pointer = ISC_TRUE;
1892 FATAL_ERROR(__FILE__, __LINE__,
1893 "Unknown state %d", state);
1894 /* Does not return. */
1899 return (ISC_R_UNEXPECTEDEND);
1901 name->ndata = (unsigned char *)target->base + target->used;
1902 name->labels = labels;
1903 name->length = nused;
1904 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1906 isc_buffer_forward(source, cused);
1907 isc_buffer_add(target, name->length);
1909 return (ISC_R_SUCCESS);
1912 if (nmax == DNS_NAME_MAXWIRE)
1914 * The name did not fit even though we had a buffer
1915 * big enough to fit a maximum-length name.
1917 return (DNS_R_NAMETOOLONG);
1920 * The name might fit if only the caller could give us a
1921 * big enough buffer.
1923 return (ISC_R_NOSPACE);
1927 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1928 isc_buffer_t *target)
1930 unsigned int methods;
1931 isc_uint16_t offset;
1932 dns_name_t gp; /* Global compression prefix */
1933 isc_boolean_t gf; /* Global compression target found */
1934 isc_uint16_t go; /* Global compression offset */
1939 * Convert 'name' into wire format, compressing it as specified by the
1940 * compression context 'cctx', and storing the result in 'target'.
1943 REQUIRE(VALID_NAME(name));
1944 REQUIRE(cctx != NULL);
1945 REQUIRE(ISC_BUFFER_VALID(target));
1948 * If 'name' doesn't have an offsets table, make a clone which
1951 if (name->offsets == NULL) {
1952 #if defined(__clang__) && \
1953 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1954 memset(&clname, 0, sizeof(clname));
1956 DNS_NAME_INIT(&clname, clo);
1957 dns_name_clone(name, &clname);
1960 DNS_NAME_INIT(&gp, NULL);
1962 offset = target->used; /*XXX*/
1964 methods = dns_compress_getmethods(cctx);
1966 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1967 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1968 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1973 * If the offset is too high for 14 bit global compression, we're
1976 if (gf && go >= 0x4000)
1980 * Will the compression pointer reduce the message size?
1982 if (gf && (gp.length + 2) >= name->length)
1986 if (target->length - target->used < gp.length)
1987 return (ISC_R_NOSPACE);
1988 (void)memmove((unsigned char *)target->base + target->used,
1989 gp.ndata, (size_t)gp.length);
1990 isc_buffer_add(target, gp.length);
1992 if (target->length - target->used < 2)
1993 return (ISC_R_NOSPACE);
1994 isc_buffer_putuint16(target, go);
1996 dns_compress_add(cctx, name, &gp, offset);
1998 if (target->length - target->used < name->length)
1999 return (ISC_R_NOSPACE);
2000 (void)memmove((unsigned char *)target->base + target->used,
2001 name->ndata, (size_t)name->length);
2002 isc_buffer_add(target, name->length);
2003 dns_compress_add(cctx, name, name, offset);
2005 return (ISC_R_SUCCESS);
2009 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2010 isc_buffer_t *target)
2012 unsigned char *ndata, *offsets;
2013 unsigned int nrem, labels, prefix_length, length;
2014 isc_boolean_t copy_prefix = ISC_TRUE;
2015 isc_boolean_t copy_suffix = ISC_TRUE;
2016 isc_boolean_t absolute = ISC_FALSE;
2017 dns_name_t tmp_name;
2018 dns_offsets_t odata;
2021 * Concatenate 'prefix' and 'suffix'.
2024 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2025 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2026 REQUIRE(name == NULL || VALID_NAME(name));
2027 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2028 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2029 if (prefix == NULL || prefix->labels == 0)
2030 copy_prefix = ISC_FALSE;
2031 if (suffix == NULL || suffix->labels == 0)
2032 copy_suffix = ISC_FALSE;
2034 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2035 absolute = ISC_TRUE;
2036 REQUIRE(!copy_suffix);
2039 DNS_NAME_INIT(&tmp_name, odata);
2042 if (target == NULL) {
2043 INSIST(name->buffer != NULL);
2044 target = name->buffer;
2045 isc_buffer_clear(name->buffer);
2048 REQUIRE(BINDABLE(name));
2053 nrem = target->length - target->used;
2054 ndata = (unsigned char *)target->base + target->used;
2055 if (nrem > DNS_NAME_MAXWIRE)
2056 nrem = DNS_NAME_MAXWIRE;
2061 prefix_length = prefix->length;
2062 length += prefix_length;
2063 labels += prefix->labels;
2066 length += suffix->length;
2067 labels += suffix->labels;
2069 if (length > DNS_NAME_MAXWIRE) {
2071 return (DNS_R_NAMETOOLONG);
2073 if (length > nrem) {
2075 return (ISC_R_NOSPACE);
2079 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2080 absolute = ISC_TRUE;
2081 memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2085 * If 'prefix' and 'name' are the same object, and the object has
2086 * a dedicated buffer, and we're using it, then we don't have to
2089 if (copy_prefix && (prefix != name || prefix->buffer != target))
2090 memmove(ndata, prefix->ndata, prefix_length);
2092 name->ndata = ndata;
2093 name->labels = labels;
2094 name->length = length;
2096 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2098 name->attributes = 0;
2100 if (name->labels > 0 && name->offsets != NULL) {
2101 INIT_OFFSETS(name, offsets, odata);
2102 set_offsets(name, offsets, NULL);
2105 isc_buffer_add(target, name->length);
2107 return (ISC_R_SUCCESS);
2111 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2112 dns_name_t *prefix, dns_name_t *suffix)
2115 unsigned int splitlabel;
2117 REQUIRE(VALID_NAME(name));
2118 REQUIRE(suffixlabels > 0);
2119 REQUIRE(suffixlabels < name->labels);
2120 REQUIRE(prefix != NULL || suffix != NULL);
2121 REQUIRE(prefix == NULL ||
2122 (VALID_NAME(prefix) &&
2123 prefix->buffer != NULL &&
2125 REQUIRE(suffix == NULL ||
2126 (VALID_NAME(suffix) &&
2127 suffix->buffer != NULL &&
2130 splitlabel = name->labels - suffixlabels;
2133 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2136 dns_name_getlabelsequence(name, splitlabel,
2137 suffixlabels, suffix);
2143 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2147 * Make 'target' a dynamically allocated copy of 'source'.
2150 REQUIRE(VALID_NAME(source));
2151 REQUIRE(source->length > 0);
2152 REQUIRE(VALID_NAME(target));
2153 REQUIRE(BINDABLE(target));
2156 * Make 'target' empty in case of failure.
2160 target->ndata = isc_mem_get(mctx, source->length);
2161 if (target->ndata == NULL)
2162 return (ISC_R_NOMEMORY);
2164 memmove(target->ndata, source->ndata, source->length);
2166 target->length = source->length;
2167 target->labels = source->labels;
2168 target->attributes = DNS_NAMEATTR_DYNAMIC;
2169 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2170 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2171 if (target->offsets != NULL) {
2172 if (source->offsets != NULL)
2173 memmove(target->offsets, source->offsets,
2176 set_offsets(target, target->offsets, NULL);
2179 return (ISC_R_SUCCESS);
2183 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2187 * Make 'target' a read-only dynamically allocated copy of 'source'.
2188 * 'target' will also have a dynamically allocated offsets table.
2191 REQUIRE(VALID_NAME(source));
2192 REQUIRE(source->length > 0);
2193 REQUIRE(VALID_NAME(target));
2194 REQUIRE(BINDABLE(target));
2195 REQUIRE(target->offsets == NULL);
2198 * Make 'target' empty in case of failure.
2202 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2203 if (target->ndata == NULL)
2204 return (ISC_R_NOMEMORY);
2206 memmove(target->ndata, source->ndata, source->length);
2208 target->length = source->length;
2209 target->labels = source->labels;
2210 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2211 DNS_NAMEATTR_READONLY;
2212 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2213 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2214 target->offsets = target->ndata + source->length;
2215 if (source->offsets != NULL)
2216 memmove(target->offsets, source->offsets, source->labels);
2218 set_offsets(target, target->offsets, NULL);
2220 return (ISC_R_SUCCESS);
2224 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2231 REQUIRE(VALID_NAME(name));
2232 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2234 size = name->length;
2235 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2236 size += name->labels;
2237 isc_mem_put(mctx, name->ndata, size);
2238 dns_name_invalidate(name);
2242 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2243 dns_name_t downname;
2244 unsigned char data[256];
2245 isc_buffer_t buffer;
2246 isc_result_t result;
2250 * Send 'name' in DNSSEC canonical form to 'digest'.
2253 REQUIRE(VALID_NAME(name));
2254 REQUIRE(digest != NULL);
2256 #if defined(__clang__) && \
2257 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2258 memset(&downname, 0, sizeof(downname));
2260 DNS_NAME_INIT(&downname, NULL);
2262 isc_buffer_init(&buffer, data, sizeof(data));
2264 result = dns_name_downcase(name, &downname, &buffer);
2265 if (result != ISC_R_SUCCESS)
2268 isc_buffer_usedregion(&buffer, &r);
2270 return ((digest)(arg, &r));
2274 dns_name_dynamic(dns_name_t *name) {
2275 REQUIRE(VALID_NAME(name));
2278 * Returns whether there is dynamic memory associated with this name.
2281 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2282 ISC_TRUE : ISC_FALSE);
2286 dns_name_print(dns_name_t *name, FILE *stream) {
2287 isc_result_t result;
2293 * Print 'name' on 'stream'.
2296 REQUIRE(VALID_NAME(name));
2298 isc_buffer_init(&b, t, sizeof(t));
2299 result = dns_name_totext(name, ISC_FALSE, &b);
2300 if (result != ISC_R_SUCCESS)
2302 isc_buffer_usedregion(&b, &r);
2303 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2305 return (ISC_R_SUCCESS);
2309 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2310 #ifdef ISC_PLATFORM_USETHREADS
2311 isc_result_t result;
2312 dns_name_totextfilter_t *mem;
2315 result = totext_filter_proc_key_init();
2316 if (result != ISC_R_SUCCESS)
2320 * If we already have been here set / clear as appropriate.
2321 * Otherwise allocate memory.
2323 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2324 if (mem != NULL && proc != NULL) {
2326 return (ISC_R_SUCCESS);
2329 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2330 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2332 result = ISC_R_UNEXPECTED;
2336 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2338 return (ISC_R_NOMEMORY);
2340 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2341 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2342 result = ISC_R_UNEXPECTED;
2346 totext_filter_proc = proc;
2347 return (ISC_R_SUCCESS);
2352 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2353 isc_result_t result;
2359 * Leave room for null termination after buffer.
2361 isc_buffer_init(&buf, cp, size - 1);
2362 result = dns_name_totext(name, ISC_TRUE, &buf);
2363 if (result == ISC_R_SUCCESS) {
2368 isc_buffer_usedregion(&buf, &r);
2369 ((char *) r.base)[r.length] = '\0';
2372 snprintf(cp, size, "<unknown>");
2376 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2380 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2381 isc_result_t result;
2384 char *p, txt[DNS_NAME_FORMATSIZE];
2386 REQUIRE(VALID_NAME(name));
2387 REQUIRE(target != NULL && *target == NULL);
2389 isc_buffer_init(&buf, txt, sizeof(txt));
2390 result = dns_name_totext(name, ISC_FALSE, &buf);
2391 if (result != ISC_R_SUCCESS)
2394 isc_buffer_usedregion(&buf, ®);
2395 p = isc_mem_allocate(mctx, reg.length + 1);
2396 memmove(p, (char *) reg.base, (int) reg.length);
2397 p[reg.length] = '\0';
2400 return (ISC_R_SUCCESS);
2404 * dns_name_fromstring() -- convert directly from a string to a name,
2405 * allocating memory as needed
2408 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2411 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2415 dns_name_fromstring2(dns_name_t *target, const char *src,
2416 const dns_name_t *origin, unsigned int options,
2419 isc_result_t result;
2424 REQUIRE(src != NULL);
2426 isc_buffer_constinit(&buf, src, strlen(src));
2427 isc_buffer_add(&buf, strlen(src));
2428 if (BINDABLE(target) && target->buffer != NULL)
2431 dns_fixedname_init(&fn);
2432 name = dns_fixedname_name(&fn);
2435 result = dns_name_fromtext(name, &buf, origin, options, NULL);
2436 if (result != ISC_R_SUCCESS)
2440 result = dns_name_dupwithoffsets(name, mctx, target);
2445 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2446 unsigned char *ndata;
2449 * Make dest a copy of source.
2452 REQUIRE(VALID_NAME(source));
2453 REQUIRE(VALID_NAME(dest));
2454 REQUIRE(target != NULL || dest->buffer != NULL);
2456 if (target == NULL) {
2457 target = dest->buffer;
2458 isc_buffer_clear(dest->buffer);
2461 REQUIRE(BINDABLE(dest));
2466 if (target->length - target->used < source->length)
2467 return (ISC_R_NOSPACE);
2469 ndata = (unsigned char *)target->base + target->used;
2470 dest->ndata = target->base;
2472 memmove(ndata, source->ndata, source->length);
2474 dest->ndata = ndata;
2475 dest->labels = source->labels;
2476 dest->length = source->length;
2477 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2478 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2480 dest->attributes = 0;
2482 if (dest->labels > 0 && dest->offsets != NULL) {
2483 if (source->offsets != NULL)
2484 memmove(dest->offsets, source->offsets, source->labels);
2486 set_offsets(dest, dest->offsets, NULL);
2489 isc_buffer_add(target, dest->length);
2491 return (ISC_R_SUCCESS);
2495 dns_name_destroy(void) {
2496 #ifdef ISC_PLATFORM_USETHREADS
2497 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2500 LOCK(&thread_key_mutex);
2501 if (thread_key_initialized) {
2502 isc_mem_detach(&thread_key_mctx);
2503 isc_thread_key_delete(totext_filter_proc_key);
2504 thread_key_initialized = 0;
2506 UNLOCK(&thread_key_mutex);