2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: name.c,v 1.165 2008/04/01 23:47:10 tbox Exp $ */
27 #include <isc/buffer.h>
31 #include <isc/print.h>
32 #include <isc/string.h>
33 #include <isc/thread.h>
36 #include <dns/compress.h>
38 #include <dns/result.h>
40 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
59 static char digitvalue[256] = {
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
63 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
64 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
66 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
78 static unsigned char maptolower[] = {
79 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
80 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
81 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
82 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
83 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
84 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
85 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
86 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
87 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
88 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
89 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
90 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
91 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
92 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
93 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
94 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
95 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
96 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
97 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
98 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
99 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
100 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
101 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
102 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
103 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
104 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
105 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
106 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
107 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
108 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
109 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
110 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
113 #define CONVERTTOASCII(c)
114 #define CONVERTFROMASCII(c)
116 #define INIT_OFFSETS(name, var, default) \
117 if (name->offsets != NULL) \
118 var = name->offsets; \
122 #define SETUP_OFFSETS(name, var, default) \
123 if (name->offsets != NULL) \
124 var = name->offsets; \
127 set_offsets(name, var, NULL); \
131 * Note: If additional attributes are added that should not be set for
132 * empty names, MAKE_EMPTY() must be changed so it clears them.
134 #define MAKE_EMPTY(name) \
136 name->ndata = NULL; \
139 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
143 * A name is "bindable" if it can be set to point to a new value, i.e.
144 * name->ndata and name->length may be changed.
146 #define BINDABLE(name) \
147 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
151 * Note that the name data must be a char array, not a string
152 * literal, to avoid compiler warnings about discarding
153 * the const attribute of a string.
155 static unsigned char root_ndata[] = { '\0' };
156 static unsigned char root_offsets[] = { 0 };
158 static dns_name_t root =
162 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
164 {(void *)-1, (void *)-1},
168 /* XXXDCL make const? */
169 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
171 static unsigned char wild_ndata[] = { '\001', '*' };
172 static unsigned char wild_offsets[] = { 0 };
174 static dns_name_t wild =
178 DNS_NAMEATTR_READONLY,
180 {(void *)-1, (void *)-1},
184 /* XXXDCL make const? */
185 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
188 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
191 * dns_name_t to text post-conversion procedure.
193 #ifdef ISC_PLATFORM_USETHREADS
194 static int thread_key_initialized = 0;
195 static isc_mutex_t thread_key_mutex;
196 static isc_mem_t *thread_key_mctx = NULL;
197 static isc_thread_key_t totext_filter_proc_key;
198 static isc_once_t once = ISC_ONCE_INIT;
200 static dns_name_totextfilter_t totext_filter_proc = NULL;
204 set_offsets(const dns_name_t *name, unsigned char *offsets,
205 dns_name_t *set_name);
208 dns_name_init(dns_name_t *name, unsigned char *offsets) {
212 DNS_NAME_INIT(name, offsets);
216 dns_name_reset(dns_name_t *name) {
217 REQUIRE(VALID_NAME(name));
218 REQUIRE(BINDABLE(name));
220 DNS_NAME_RESET(name);
224 dns_name_invalidate(dns_name_t *name) {
226 * Make 'name' invalid.
229 REQUIRE(VALID_NAME(name));
235 name->attributes = 0;
236 name->offsets = NULL;
238 ISC_LINK_INIT(name, link);
242 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
244 * Dedicate a buffer for use with 'name'.
247 REQUIRE(VALID_NAME(name));
248 REQUIRE((buffer != NULL && name->buffer == NULL) ||
251 name->buffer = buffer;
255 dns_name_hasbuffer(const dns_name_t *name) {
257 * Does 'name' have a dedicated buffer?
260 REQUIRE(VALID_NAME(name));
262 if (name->buffer != NULL)
269 dns_name_isabsolute(const dns_name_t *name) {
272 * Does 'name' end in the root label?
275 REQUIRE(VALID_NAME(name));
277 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
282 #define hyphenchar(c) ((c) == 0x2d)
283 #define asterchar(c) ((c) == 0x2a)
284 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
285 || ((c) >= 0x61 && (c) <= 0x7a))
286 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
287 #define borderchar(c) (alphachar(c) || digitchar(c))
288 #define middlechar(c) (borderchar(c) || hyphenchar(c))
289 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
292 dns_name_ismailbox(const dns_name_t *name) {
293 unsigned char *ndata, ch;
297 REQUIRE(VALID_NAME(name));
298 REQUIRE(name->labels > 0);
299 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
304 if (name->length == 1)
316 if (ndata == name->ndata + name->length)
320 * RFC292/RFC1123 hostname.
322 while (ndata < (name->ndata + name->length)) {
328 if (first || n == 0) {
342 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
343 unsigned char *ndata, ch;
347 REQUIRE(VALID_NAME(name));
348 REQUIRE(name->labels > 0);
349 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
354 if (name->length == 1)
358 * Skip wildcard if this is a ownername.
361 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
365 * RFC292/RFC1123 hostname.
367 while (ndata < (name->ndata + name->length)) {
373 if (first || n == 0) {
387 dns_name_iswildcard(const dns_name_t *name) {
388 unsigned char *ndata;
391 * Is 'name' a wildcard name?
394 REQUIRE(VALID_NAME(name));
395 REQUIRE(name->labels > 0);
397 if (name->length >= 2) {
399 if (ndata[0] == 1 && ndata[1] == '*')
407 dns_name_internalwildcard(const dns_name_t *name) {
408 unsigned char *ndata;
413 * Does 'name' contain a internal wildcard?
416 REQUIRE(VALID_NAME(name));
417 REQUIRE(name->labels > 0);
428 * Check all but the last of the remaining labels.
430 while (label + 1 < name->labels) {
433 if (count == 1 && *ndata == '*')
441 static inline unsigned int
442 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
444 const unsigned char *s;
448 length = name->length;
453 * This hash function is similar to the one Ousterhout
457 if (case_sensitive) {
459 h += ( h << 3 ) + *s;
476 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
478 * Provide a hash value for 'name'.
480 REQUIRE(VALID_NAME(name));
482 if (name->labels == 0)
485 return (name_hash(name, case_sensitive));
489 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
491 * Provide a hash value for 'name'.
493 REQUIRE(VALID_NAME(name));
495 if (name->labels == 0)
498 return (isc_hash_calc((const unsigned char *)name->ndata,
499 name->length, case_sensitive));
503 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
505 * This function was deprecated due to the breakage of the name space
506 * convention. We only keep this internally to provide binary backward
509 REQUIRE(VALID_NAME(name));
511 return (dns_name_fullhash(name, case_sensitive));
515 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
516 unsigned char *offsets;
523 * Provide a hash value for 'name'.
525 REQUIRE(VALID_NAME(name));
527 if (name->labels == 0)
529 else if (name->labels == 1)
530 return (name_hash(name, case_sensitive));
532 SETUP_OFFSETS(name, offsets, odata);
533 DNS_NAME_INIT(&tname, NULL);
536 for (i = 0; i < name->labels; i++) {
537 tname.ndata = name->ndata + offsets[i];
538 if (i == name->labels - 1)
539 tname.length = name->length - offsets[i];
541 tname.length = offsets[i + 1] - offsets[i];
542 h += name_hash(&tname, case_sensitive);
549 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
550 int *orderp, unsigned int *nlabelsp)
552 unsigned int l1, l2, l, count1, count2, count, nlabels;
553 int cdiff, ldiff, chdiff;
554 unsigned char *label1, *label2;
555 unsigned char *offsets1, *offsets2;
556 dns_offsets_t odata1, odata2;
557 dns_namereln_t namereln = dns_namereln_none;
560 * Determine the relative ordering under the DNSSEC order relation of
561 * 'name1' and 'name2', and also determine the hierarchical
562 * relationship of the names.
564 * Note: It makes no sense for one of the names to be relative and the
565 * other absolute. If both names are relative, then to be meaningfully
566 * compared the caller must ensure that they are both relative to the
570 REQUIRE(VALID_NAME(name1));
571 REQUIRE(VALID_NAME(name2));
572 REQUIRE(orderp != NULL);
573 REQUIRE(nlabelsp != NULL);
575 * Either name1 is absolute and name2 is absolute, or neither is.
577 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
578 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
580 SETUP_OFFSETS(name1, offsets1, odata1);
581 SETUP_OFFSETS(name2, offsets2, odata2);
586 ldiff = (int)l1 - (int)l2;
596 label1 = &name1->ndata[offsets1[l1]];
597 label2 = &name2->ndata[offsets2[l2]];
602 * We dropped bitstring labels, and we don't support any
603 * other extended label types.
605 INSIST(count1 <= 63 && count2 <= 63);
607 cdiff = (int)count1 - (int)count2;
614 chdiff = (int)maptolower[*label1] -
615 (int)maptolower[*label2];
633 namereln = dns_namereln_contains;
635 namereln = dns_namereln_subdomain;
637 namereln = dns_namereln_equal;
642 if (nlabels > 0 && namereln == dns_namereln_none)
643 namereln = dns_namereln_commonancestor;
649 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
651 unsigned int nlabels;
654 * Determine the relative ordering under the DNSSEC order relation of
655 * 'name1' and 'name2'.
657 * Note: It makes no sense for one of the names to be relative and the
658 * other absolute. If both names are relative, then to be meaningfully
659 * compared the caller must ensure that they are both relative to the
663 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
669 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
670 unsigned int l, count;
672 unsigned char *label1, *label2;
675 * Are 'name1' and 'name2' equal?
677 * Note: It makes no sense for one of the names to be relative and the
678 * other absolute. If both names are relative, then to be meaningfully
679 * compared the caller must ensure that they are both relative to the
683 REQUIRE(VALID_NAME(name1));
684 REQUIRE(VALID_NAME(name2));
686 * Either name1 is absolute and name2 is absolute, or neither is.
688 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
689 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
691 if (name1->length != name2->length)
696 if (l != name2->labels)
699 label1 = name1->ndata;
700 label2 = name2->ndata;
704 if (count != *label2++)
707 INSIST(count <= 63); /* no bitstring support */
711 c = maptolower[*label1++];
712 if (c != maptolower[*label2++])
721 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
724 * Are 'name1' and 'name2' equal?
726 * Note: It makes no sense for one of the names to be relative and the
727 * other absolute. If both names are relative, then to be meaningfully
728 * compared the caller must ensure that they are both relative to the
732 REQUIRE(VALID_NAME(name1));
733 REQUIRE(VALID_NAME(name2));
735 * Either name1 is absolute and name2 is absolute, or neither is.
737 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
738 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
740 if (name1->length != name2->length)
743 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
750 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
751 unsigned int l1, l2, l, count1, count2, count;
752 unsigned char c1, c2;
753 unsigned char *label1, *label2;
756 * Compare two absolute names as rdata.
759 REQUIRE(VALID_NAME(name1));
760 REQUIRE(name1->labels > 0);
761 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
762 REQUIRE(VALID_NAME(name2));
763 REQUIRE(name2->labels > 0);
764 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
769 l = (l1 < l2) ? l1 : l2;
771 label1 = name1->ndata;
772 label2 = name2->ndata;
778 /* no bitstring support */
779 INSIST(count1 <= 63 && count2 <= 63);
781 if (count1 != count2)
782 return ((count1 < count2) ? -1 : 1);
786 c1 = maptolower[*label1++];
787 c2 = maptolower[*label2++];
796 * If one name had more labels than the other, their common
797 * prefix must have been different because the shorter name
798 * ended with the root label and the longer one can't have
799 * a root label in the middle of it. Therefore, if we get
800 * to this point, the lengths must be equal.
808 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
810 unsigned int nlabels;
811 dns_namereln_t namereln;
814 * Is 'name1' a subdomain of 'name2'?
816 * Note: It makes no sense for one of the names to be relative and the
817 * other absolute. If both names are relative, then to be meaningfully
818 * compared the caller must ensure that they are both relative to the
822 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
823 if (namereln == dns_namereln_subdomain ||
824 namereln == dns_namereln_equal)
831 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
833 unsigned int nlabels, labels;
836 REQUIRE(VALID_NAME(name));
837 REQUIRE(name->labels > 0);
838 REQUIRE(VALID_NAME(wname));
839 labels = wname->labels;
841 REQUIRE(dns_name_iswildcard(wname));
843 DNS_NAME_INIT(&tname, NULL);
844 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
845 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
846 dns_namereln_subdomain)
852 dns_name_countlabels(const dns_name_t *name) {
854 * How many labels does 'name' have?
857 REQUIRE(VALID_NAME(name));
859 ENSURE(name->labels <= 128);
861 return (name->labels);
865 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
866 unsigned char *offsets;
870 * Make 'label' refer to the 'n'th least significant label of 'name'.
873 REQUIRE(VALID_NAME(name));
874 REQUIRE(name->labels > 0);
875 REQUIRE(n < name->labels);
876 REQUIRE(label != NULL);
878 SETUP_OFFSETS(name, offsets, odata);
880 label->base = &name->ndata[offsets[n]];
881 if (n == name->labels - 1)
882 label->length = name->length - offsets[n];
884 label->length = offsets[n + 1] - offsets[n];
888 dns_name_getlabelsequence(const dns_name_t *source,
889 unsigned int first, unsigned int n,
892 unsigned char *offsets;
894 unsigned int firstoffset, endoffset;
897 * Make 'target' refer to the 'n' labels including and following
898 * 'first' in 'source'.
901 REQUIRE(VALID_NAME(source));
902 REQUIRE(VALID_NAME(target));
903 REQUIRE(first <= source->labels);
904 REQUIRE(first + n <= source->labels);
905 REQUIRE(BINDABLE(target));
907 SETUP_OFFSETS(source, offsets, odata);
909 if (first == source->labels)
910 firstoffset = source->length;
912 firstoffset = offsets[first];
914 if (first + n == source->labels)
915 endoffset = source->length;
917 endoffset = offsets[first + n];
919 target->ndata = &source->ndata[firstoffset];
920 target->length = endoffset - firstoffset;
922 if (first + n == source->labels && n > 0 &&
923 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
924 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
926 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
931 * If source and target are the same, and we're making target
932 * a prefix of source, the offsets table is correct already
933 * so we don't need to call set_offsets().
935 if (target->offsets != NULL &&
936 (target != source || first != 0))
937 set_offsets(target, target->offsets, NULL);
941 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
944 * Make 'target' refer to the same name as 'source'.
947 REQUIRE(VALID_NAME(source));
948 REQUIRE(VALID_NAME(target));
949 REQUIRE(BINDABLE(target));
951 target->ndata = source->ndata;
952 target->length = source->length;
953 target->labels = source->labels;
954 target->attributes = source->attributes &
955 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
956 DNS_NAMEATTR_DYNOFFSETS);
957 if (target->offsets != NULL && source->labels > 0) {
958 if (source->offsets != NULL)
959 memcpy(target->offsets, source->offsets,
962 set_offsets(target, target->offsets, NULL);
967 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
968 unsigned char *offsets;
974 * Make 'name' refer to region 'r'.
977 REQUIRE(VALID_NAME(name));
979 REQUIRE(BINDABLE(name));
981 INIT_OFFSETS(name, offsets, odata);
983 if (name->buffer != NULL) {
984 isc_buffer_clear(name->buffer);
985 isc_buffer_availableregion(name->buffer, &r2);
986 len = (r->length < r2.length) ? r->length : r2.length;
987 if (len > DNS_NAME_MAXWIRE)
988 len = DNS_NAME_MAXWIRE;
989 memcpy(r2.base, r->base, len);
990 name->ndata = r2.base;
993 name->ndata = r->base;
994 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
995 r->length : DNS_NAME_MAXWIRE;
999 set_offsets(name, offsets, name);
1002 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1005 if (name->buffer != NULL)
1006 isc_buffer_add(name->buffer, name->length);
1010 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1012 * Make 'r' refer to 'name'.
1015 REQUIRE(VALID_NAME(name));
1018 DNS_NAME_TOREGION(name, r);
1023 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1024 dns_name_t *origin, unsigned int options,
1025 isc_buffer_t *target)
1027 unsigned char *ndata, *label;
1031 unsigned int value, count;
1032 unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
1034 unsigned char *offsets;
1035 dns_offsets_t odata;
1036 isc_boolean_t downcase;
1039 * Convert the textual representation of a DNS name at source
1040 * into uncompressed wire form stored in target.
1043 * Relative domain names will have 'origin' appended to them
1044 * unless 'origin' is NULL, in which case relative domain names
1045 * will remain relative.
1048 REQUIRE(VALID_NAME(name));
1049 REQUIRE(ISC_BUFFER_VALID(source));
1050 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1051 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1053 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1055 if (target == NULL && name->buffer != NULL) {
1056 target = name->buffer;
1057 isc_buffer_clear(target);
1060 REQUIRE(BINDABLE(name));
1062 INIT_OFFSETS(name, offsets, odata);
1066 * Initialize things to make the compiler happy; they're not required.
1076 * Make 'name' empty in case of failure.
1081 * Set up the state machine.
1083 tdata = (char *)source->base + source->current;
1084 tlen = isc_buffer_remaininglength(source);
1086 ndata = isc_buffer_used(target);
1087 nrem = isc_buffer_availablelength(target);
1095 while (nrem > 0 && tlen > 0 && !done) {
1103 * Is this the root name?
1107 return (DNS_R_EMPTYLABEL);
1115 if (c == '@' && tlen == 0) {
1128 state = ft_initialescape;
1131 state = ft_ordinary;
1133 return (ISC_R_NOSPACE);
1138 return (DNS_R_EMPTYLABEL);
1141 INSIST(labels <= 127);
1142 offsets[labels] = nused;
1151 } else if (c == '\\') {
1155 return (DNS_R_LABELTOOLONG);
1159 c = maptolower[(int)c];
1165 case ft_initialescape:
1168 * This looks like a bitstring label, which
1169 * was deprecated. Intentionally drop it.
1171 return (DNS_R_BADLABELTYPE);
1176 if (!isdigit(c & 0xff)) {
1178 return (DNS_R_LABELTOOLONG);
1182 c = maptolower[(int)c];
1186 state = ft_ordinary;
1191 state = ft_escdecimal;
1194 if (!isdigit(c & 0xff))
1195 return (DNS_R_BADESCAPE);
1197 value += digitvalue[(int)c];
1201 return (DNS_R_BADESCAPE);
1203 return (DNS_R_LABELTOOLONG);
1206 value = maptolower[value];
1210 state = ft_ordinary;
1214 FATAL_ERROR(__FILE__, __LINE__,
1215 "Unexpected state %d", state);
1216 /* Does not return. */
1222 return (ISC_R_NOSPACE);
1224 if (state != ft_ordinary && state != ft_at)
1225 return (ISC_R_UNEXPECTEDEND);
1226 if (state == ft_ordinary) {
1230 INSIST(labels <= 127);
1231 offsets[labels] = nused;
1233 if (origin != NULL) {
1234 if (nrem < origin->length)
1235 return (ISC_R_NOSPACE);
1236 label = origin->ndata;
1237 n1 = origin->length;
1241 INSIST(n2 <= 63); /* no bitstring support */
1248 c = maptolower[(int)c];
1254 INSIST(labels <= 127);
1255 offsets[labels] = nused;
1258 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1259 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1262 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1264 name->ndata = (unsigned char *)target->base + target->used;
1265 name->labels = labels;
1266 name->length = nused;
1268 isc_buffer_forward(source, tused);
1269 isc_buffer_add(target, name->length);
1271 return (ISC_R_SUCCESS);
1274 #ifdef ISC_PLATFORM_USETHREADS
1276 free_specific(void *arg) {
1277 dns_name_totextfilter_t *mem = arg;
1278 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1279 /* Stop use being called again. */
1280 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1284 thread_key_mutex_init(void) {
1285 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1289 totext_filter_proc_key_init(void) {
1290 isc_result_t result;
1293 * We need the call to isc_once_do() to support profiled mutex
1294 * otherwise thread_key_mutex could be initialized at compile time.
1296 result = isc_once_do(&once, thread_key_mutex_init);
1297 if (result != ISC_R_SUCCESS)
1300 if (!thread_key_initialized) {
1301 LOCK(&thread_key_mutex);
1302 if (thread_key_mctx == NULL)
1303 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1304 if (result != ISC_R_SUCCESS)
1306 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1307 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1309 if (!thread_key_initialized &&
1310 isc_thread_key_create(&totext_filter_proc_key,
1311 free_specific) != 0) {
1312 result = ISC_R_FAILURE;
1313 isc_mem_detach(&thread_key_mctx);
1315 thread_key_initialized = 1;
1317 UNLOCK(&thread_key_mutex);
1324 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1325 isc_buffer_t *target)
1327 unsigned char *ndata;
1329 unsigned int nlen, tlen;
1331 unsigned int trem, count;
1332 unsigned int labels;
1333 isc_boolean_t saw_root = ISC_FALSE;
1334 unsigned int oused = target->used;
1335 #ifdef ISC_PLATFORM_USETHREADS
1336 dns_name_totextfilter_t *mem;
1337 dns_name_totextfilter_t totext_filter_proc = NULL;
1338 isc_result_t result;
1342 * This function assumes the name is in proper uncompressed
1345 REQUIRE(VALID_NAME(name));
1346 REQUIRE(ISC_BUFFER_VALID(target));
1348 #ifdef ISC_PLATFORM_USETHREADS
1349 result = totext_filter_proc_key_init();
1350 if (result != ISC_R_SUCCESS)
1353 ndata = name->ndata;
1354 nlen = name->length;
1355 labels = name->labels;
1356 tdata = isc_buffer_used(target);
1357 tlen = isc_buffer_availablelength(target);
1361 if (labels == 0 && nlen == 0) {
1363 * Special handling for an empty name.
1366 return (ISC_R_NOSPACE);
1369 * The names of these booleans are misleading in this case.
1370 * This empty name is not necessarily from the root node of
1371 * the DNS root zone, nor is a final dot going to be included.
1372 * They need to be set this way, though, to keep the "@"
1373 * from being trounced.
1375 saw_root = ISC_TRUE;
1376 omit_final_dot = ISC_FALSE;
1381 * Skip the while() loop.
1384 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1386 * Special handling for the root label.
1389 return (ISC_R_NOSPACE);
1391 saw_root = ISC_TRUE;
1392 omit_final_dot = ISC_FALSE;
1397 * Skip the while() loop.
1402 while (labels > 0 && nlen > 0 && trem > 0) {
1407 saw_root = ISC_TRUE;
1411 INSIST(nlen >= count);
1415 case 0x22: /* '"' */
1416 case 0x28: /* '(' */
1417 case 0x29: /* ')' */
1418 case 0x2E: /* '.' */
1419 case 0x3B: /* ';' */
1420 case 0x5C: /* '\\' */
1421 /* Special modifiers in zone files. */
1422 case 0x40: /* '@' */
1423 case 0x24: /* '$' */
1425 return (ISC_R_NOSPACE);
1427 CONVERTFROMASCII(c);
1434 if (c > 0x20 && c < 0x7f) {
1436 return (ISC_R_NOSPACE);
1437 CONVERTFROMASCII(c);
1444 return (ISC_R_NOSPACE);
1450 *tdata++ = 0x30 + (c % 10);
1459 FATAL_ERROR(__FILE__, __LINE__,
1460 "Unexpected label type %02x", count);
1465 * The following assumes names are absolute. If not, we
1466 * fix things up later. Note that this means that in some
1467 * cases one more byte of text buffer is required than is
1468 * needed in the final output.
1471 return (ISC_R_NOSPACE);
1476 if (nlen != 0 && trem == 0)
1477 return (ISC_R_NOSPACE);
1479 if (!saw_root || omit_final_dot)
1482 isc_buffer_add(target, tlen - trem);
1484 #ifdef ISC_PLATFORM_USETHREADS
1485 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1487 totext_filter_proc = *mem;
1489 if (totext_filter_proc != NULL)
1490 return ((*totext_filter_proc)(target, oused, saw_root));
1492 return (ISC_R_SUCCESS);
1496 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1497 isc_buffer_t *target)
1499 unsigned char *ndata;
1501 unsigned int nlen, tlen;
1503 unsigned int trem, count;
1504 unsigned int labels;
1507 * This function assumes the name is in proper uncompressed
1510 REQUIRE(VALID_NAME(name));
1511 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1512 REQUIRE(ISC_BUFFER_VALID(target));
1514 ndata = name->ndata;
1515 nlen = name->length;
1516 labels = name->labels;
1517 tdata = isc_buffer_used(target);
1518 tlen = isc_buffer_availablelength(target);
1522 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1524 * Special handling for the root label.
1527 return (ISC_R_NOSPACE);
1529 omit_final_dot = ISC_FALSE;
1534 * Skip the while() loop.
1539 while (labels > 0 && nlen > 0 && trem > 0) {
1546 INSIST(nlen >= count);
1549 if ((c >= 0x30 && c <= 0x39) || /* digit */
1550 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1551 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1552 c == 0x2D || /* hyphen */
1553 c == 0x5F) /* underscore */
1556 return (ISC_R_NOSPACE);
1558 if (c >= 0x41 && c <= 0x5A)
1560 CONVERTFROMASCII(c);
1567 return (ISC_R_NOSPACE);
1568 sprintf(tdata, "%%%02X", c);
1577 FATAL_ERROR(__FILE__, __LINE__,
1578 "Unexpected label type %02x", count);
1583 * The following assumes names are absolute. If not, we
1584 * fix things up later. Note that this means that in some
1585 * cases one more byte of text buffer is required than is
1586 * needed in the final output.
1589 return (ISC_R_NOSPACE);
1594 if (nlen != 0 && trem == 0)
1595 return (ISC_R_NOSPACE);
1600 isc_buffer_add(target, tlen - trem);
1602 return (ISC_R_SUCCESS);
1606 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1607 unsigned char *sndata, *ndata;
1608 unsigned int nlen, count, labels;
1609 isc_buffer_t buffer;
1612 * Downcase 'source'.
1615 REQUIRE(VALID_NAME(source));
1616 REQUIRE(VALID_NAME(name));
1617 if (source == name) {
1618 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1619 isc_buffer_init(&buffer, source->ndata, source->length);
1621 ndata = source->ndata;
1623 REQUIRE(BINDABLE(name));
1624 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1625 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1626 if (target == NULL) {
1627 target = name->buffer;
1628 isc_buffer_clear(name->buffer);
1630 ndata = (unsigned char *)target->base + target->used;
1631 name->ndata = ndata;
1634 sndata = source->ndata;
1635 nlen = source->length;
1636 labels = source->labels;
1638 if (nlen > (target->length - target->used)) {
1640 return (ISC_R_NOSPACE);
1643 while (labels > 0 && nlen > 0) {
1649 INSIST(nlen >= count);
1651 *ndata++ = maptolower[(*sndata++)];
1656 FATAL_ERROR(__FILE__, __LINE__,
1657 "Unexpected label type %02x", count);
1658 /* Does not return. */
1662 if (source != name) {
1663 name->labels = source->labels;
1664 name->length = source->length;
1665 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1666 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1668 name->attributes = 0;
1669 if (name->labels > 0 && name->offsets != NULL)
1670 set_offsets(name, name->offsets, NULL);
1673 isc_buffer_add(target, name->length);
1675 return (ISC_R_SUCCESS);
1679 set_offsets(const dns_name_t *name, unsigned char *offsets,
1680 dns_name_t *set_name)
1682 unsigned int offset, count, length, nlabels;
1683 unsigned char *ndata;
1684 isc_boolean_t absolute;
1686 ndata = name->ndata;
1687 length = name->length;
1690 absolute = ISC_FALSE;
1691 while (offset != length) {
1692 INSIST(nlabels < 128);
1693 offsets[nlabels++] = offset;
1696 INSIST(count <= 63);
1699 INSIST(offset <= length);
1701 absolute = ISC_TRUE;
1705 if (set_name != NULL) {
1706 INSIST(set_name == name);
1708 set_name->labels = nlabels;
1709 set_name->length = offset;
1711 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1713 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1715 INSIST(nlabels == name->labels);
1716 INSIST(offset == name->length);
1720 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1721 dns_decompress_t *dctx, unsigned int options,
1722 isc_buffer_t *target)
1724 unsigned char *cdata, *ndata;
1725 unsigned int cused; /* Bytes of compressed name data used */
1726 unsigned int nused, labels, n, nmax;
1727 unsigned int current, new_current, biggest_pointer;
1729 fw_state state = fw_start;
1731 unsigned char *offsets;
1732 dns_offsets_t odata;
1733 isc_boolean_t downcase;
1734 isc_boolean_t seen_pointer;
1737 * Copy the possibly-compressed name at source into target,
1738 * decompressing it. Loop prevention is performed by checking
1739 * the new pointer against biggest_pointer.
1742 REQUIRE(VALID_NAME(name));
1743 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1744 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1746 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1748 if (target == NULL && name->buffer != NULL) {
1749 target = name->buffer;
1750 isc_buffer_clear(target);
1753 REQUIRE(dctx != NULL);
1754 REQUIRE(BINDABLE(name));
1756 INIT_OFFSETS(name, offsets, odata);
1759 * Make 'name' empty in case of failure.
1764 * Initialize things to make the compiler happy; they're not required.
1775 ndata = isc_buffer_used(target);
1777 seen_pointer = ISC_FALSE;
1780 * Find the maximum number of uncompressed target name
1781 * bytes we are willing to generate. This is the smaller
1782 * of the available target buffer length and the
1783 * maximum legal domain name length (255).
1785 nmax = isc_buffer_availablelength(target);
1786 if (nmax > DNS_NAME_MAXWIRE)
1787 nmax = DNS_NAME_MAXWIRE;
1789 cdata = isc_buffer_current(source);
1792 current = source->current;
1793 biggest_pointer = current;
1796 * Note: The following code is not optimized for speed, but
1797 * rather for correctness. Speed will be addressed in the future.
1800 while (current < source->active && !done) {
1809 offsets[labels] = nused;
1811 if (nused + c + 1 > nmax)
1818 state = fw_ordinary;
1819 } else if (c >= 128 && c < 192) {
1821 * 14 bit local compression pointer.
1822 * Local compression is no longer an
1825 return (DNS_R_BADLABELTYPE);
1826 } else if (c >= 192) {
1828 * Ordinary 14-bit pointer.
1830 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1832 return (DNS_R_DISALLOWED);
1833 new_current = c & 0x3F;
1835 state = fw_newcurrent;
1837 return (DNS_R_BADLABELTYPE);
1855 if (new_current >= biggest_pointer)
1856 return (DNS_R_BADPOINTER);
1857 biggest_pointer = new_current;
1858 current = new_current;
1859 cdata = (unsigned char *)source->base + current;
1860 seen_pointer = ISC_TRUE;
1864 FATAL_ERROR(__FILE__, __LINE__,
1865 "Unknown state %d", state);
1866 /* Does not return. */
1871 return (ISC_R_UNEXPECTEDEND);
1873 name->ndata = (unsigned char *)target->base + target->used;
1874 name->labels = labels;
1875 name->length = nused;
1876 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1878 isc_buffer_forward(source, cused);
1879 isc_buffer_add(target, name->length);
1881 return (ISC_R_SUCCESS);
1884 if (nmax == DNS_NAME_MAXWIRE)
1886 * The name did not fit even though we had a buffer
1887 * big enough to fit a maximum-length name.
1889 return (DNS_R_NAMETOOLONG);
1892 * The name might fit if only the caller could give us a
1893 * big enough buffer.
1895 return (ISC_R_NOSPACE);
1899 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1900 isc_buffer_t *target)
1902 unsigned int methods;
1903 isc_uint16_t offset;
1904 dns_name_t gp; /* Global compression prefix */
1905 isc_boolean_t gf; /* Global compression target found */
1906 isc_uint16_t go; /* Global compression offset */
1911 * Convert 'name' into wire format, compressing it as specified by the
1912 * compression context 'cctx', and storing the result in 'target'.
1915 REQUIRE(VALID_NAME(name));
1916 REQUIRE(cctx != NULL);
1917 REQUIRE(ISC_BUFFER_VALID(target));
1920 * If 'name' doesn't have an offsets table, make a clone which
1923 if (name->offsets == NULL) {
1924 DNS_NAME_INIT(&clname, clo);
1925 dns_name_clone(name, &clname);
1928 DNS_NAME_INIT(&gp, NULL);
1930 offset = target->used; /*XXX*/
1932 methods = dns_compress_getmethods(cctx);
1934 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1935 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1936 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1941 * If the offset is too high for 14 bit global compression, we're
1944 if (gf && go >= 0x4000)
1948 * Will the compression pointer reduce the message size?
1950 if (gf && (gp.length + 2) >= name->length)
1954 if (target->length - target->used < gp.length)
1955 return (ISC_R_NOSPACE);
1956 (void)memcpy((unsigned char *)target->base + target->used,
1957 gp.ndata, (size_t)gp.length);
1958 isc_buffer_add(target, gp.length);
1960 if (target->length - target->used < 2)
1961 return (ISC_R_NOSPACE);
1962 isc_buffer_putuint16(target, go);
1964 dns_compress_add(cctx, name, &gp, offset);
1966 if (target->length - target->used < name->length)
1967 return (ISC_R_NOSPACE);
1968 (void)memcpy((unsigned char *)target->base + target->used,
1969 name->ndata, (size_t)name->length);
1970 isc_buffer_add(target, name->length);
1971 dns_compress_add(cctx, name, name, offset);
1973 return (ISC_R_SUCCESS);
1977 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1978 isc_buffer_t *target)
1980 unsigned char *ndata, *offsets;
1981 unsigned int nrem, labels, prefix_length, length;
1982 isc_boolean_t copy_prefix = ISC_TRUE;
1983 isc_boolean_t copy_suffix = ISC_TRUE;
1984 isc_boolean_t absolute = ISC_FALSE;
1985 dns_name_t tmp_name;
1986 dns_offsets_t odata;
1989 * Concatenate 'prefix' and 'suffix'.
1992 REQUIRE(prefix == NULL || VALID_NAME(prefix));
1993 REQUIRE(suffix == NULL || VALID_NAME(suffix));
1994 REQUIRE(name == NULL || VALID_NAME(name));
1995 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1996 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1997 if (prefix == NULL || prefix->labels == 0)
1998 copy_prefix = ISC_FALSE;
1999 if (suffix == NULL || suffix->labels == 0)
2000 copy_suffix = ISC_FALSE;
2002 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2003 absolute = ISC_TRUE;
2004 REQUIRE(!copy_suffix);
2007 DNS_NAME_INIT(&tmp_name, odata);
2010 if (target == NULL) {
2011 INSIST(name->buffer != NULL);
2012 target = name->buffer;
2013 isc_buffer_clear(name->buffer);
2016 REQUIRE(BINDABLE(name));
2021 nrem = target->length - target->used;
2022 ndata = (unsigned char *)target->base + target->used;
2023 if (nrem > DNS_NAME_MAXWIRE)
2024 nrem = DNS_NAME_MAXWIRE;
2029 prefix_length = prefix->length;
2030 length += prefix_length;
2031 labels += prefix->labels;
2034 length += suffix->length;
2035 labels += suffix->labels;
2037 if (length > DNS_NAME_MAXWIRE) {
2039 return (DNS_R_NAMETOOLONG);
2041 if (length > nrem) {
2043 return (ISC_R_NOSPACE);
2047 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2048 absolute = ISC_TRUE;
2049 if (suffix == name && suffix->buffer == target)
2050 memmove(ndata + prefix_length, suffix->ndata,
2053 memcpy(ndata + prefix_length, suffix->ndata,
2058 * If 'prefix' and 'name' are the same object, and the object has
2059 * a dedicated buffer, and we're using it, then we don't have to
2062 if (copy_prefix && (prefix != name || prefix->buffer != target))
2063 memcpy(ndata, prefix->ndata, prefix_length);
2065 name->ndata = ndata;
2066 name->labels = labels;
2067 name->length = length;
2069 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2071 name->attributes = 0;
2073 if (name->labels > 0 && name->offsets != NULL) {
2074 INIT_OFFSETS(name, offsets, odata);
2075 set_offsets(name, offsets, NULL);
2078 isc_buffer_add(target, name->length);
2080 return (ISC_R_SUCCESS);
2084 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2085 dns_name_t *prefix, dns_name_t *suffix)
2088 unsigned int splitlabel;
2090 REQUIRE(VALID_NAME(name));
2091 REQUIRE(suffixlabels > 0);
2092 REQUIRE(suffixlabels < name->labels);
2093 REQUIRE(prefix != NULL || suffix != NULL);
2094 REQUIRE(prefix == NULL ||
2095 (VALID_NAME(prefix) &&
2096 prefix->buffer != NULL &&
2098 REQUIRE(suffix == NULL ||
2099 (VALID_NAME(suffix) &&
2100 suffix->buffer != NULL &&
2103 splitlabel = name->labels - suffixlabels;
2106 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2109 dns_name_getlabelsequence(name, splitlabel,
2110 suffixlabels, suffix);
2116 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2120 * Make 'target' a dynamically allocated copy of 'source'.
2123 REQUIRE(VALID_NAME(source));
2124 REQUIRE(source->length > 0);
2125 REQUIRE(VALID_NAME(target));
2126 REQUIRE(BINDABLE(target));
2129 * Make 'target' empty in case of failure.
2133 target->ndata = isc_mem_get(mctx, source->length);
2134 if (target->ndata == NULL)
2135 return (ISC_R_NOMEMORY);
2137 memcpy(target->ndata, source->ndata, source->length);
2139 target->length = source->length;
2140 target->labels = source->labels;
2141 target->attributes = DNS_NAMEATTR_DYNAMIC;
2142 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2143 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2144 if (target->offsets != NULL) {
2145 if (source->offsets != NULL)
2146 memcpy(target->offsets, source->offsets,
2149 set_offsets(target, target->offsets, NULL);
2152 return (ISC_R_SUCCESS);
2156 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2160 * Make 'target' a read-only dynamically allocated copy of 'source'.
2161 * 'target' will also have a dynamically allocated offsets table.
2164 REQUIRE(VALID_NAME(source));
2165 REQUIRE(source->length > 0);
2166 REQUIRE(VALID_NAME(target));
2167 REQUIRE(BINDABLE(target));
2168 REQUIRE(target->offsets == NULL);
2171 * Make 'target' empty in case of failure.
2175 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2176 if (target->ndata == NULL)
2177 return (ISC_R_NOMEMORY);
2179 memcpy(target->ndata, source->ndata, source->length);
2181 target->length = source->length;
2182 target->labels = source->labels;
2183 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2184 DNS_NAMEATTR_READONLY;
2185 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2186 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2187 target->offsets = target->ndata + source->length;
2188 if (source->offsets != NULL)
2189 memcpy(target->offsets, source->offsets, source->labels);
2191 set_offsets(target, target->offsets, NULL);
2193 return (ISC_R_SUCCESS);
2197 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2204 REQUIRE(VALID_NAME(name));
2205 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2207 size = name->length;
2208 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2209 size += name->labels;
2210 isc_mem_put(mctx, name->ndata, size);
2211 dns_name_invalidate(name);
2215 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2216 dns_name_t downname;
2217 unsigned char data[256];
2218 isc_buffer_t buffer;
2219 isc_result_t result;
2223 * Send 'name' in DNSSEC canonical form to 'digest'.
2226 REQUIRE(VALID_NAME(name));
2227 REQUIRE(digest != NULL);
2229 DNS_NAME_INIT(&downname, NULL);
2230 isc_buffer_init(&buffer, data, sizeof(data));
2232 result = dns_name_downcase(name, &downname, &buffer);
2233 if (result != ISC_R_SUCCESS)
2236 isc_buffer_usedregion(&buffer, &r);
2238 return ((digest)(arg, &r));
2242 dns_name_dynamic(dns_name_t *name) {
2243 REQUIRE(VALID_NAME(name));
2246 * Returns whether there is dynamic memory associated with this name.
2249 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2250 ISC_TRUE : ISC_FALSE);
2254 dns_name_print(dns_name_t *name, FILE *stream) {
2255 isc_result_t result;
2261 * Print 'name' on 'stream'.
2264 REQUIRE(VALID_NAME(name));
2266 isc_buffer_init(&b, t, sizeof(t));
2267 result = dns_name_totext(name, ISC_FALSE, &b);
2268 if (result != ISC_R_SUCCESS)
2270 isc_buffer_usedregion(&b, &r);
2271 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2273 return (ISC_R_SUCCESS);
2277 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2278 #ifdef ISC_PLATFORM_USETHREADS
2279 isc_result_t result;
2280 dns_name_totextfilter_t *mem;
2283 result = totext_filter_proc_key_init();
2284 if (result != ISC_R_SUCCESS)
2288 * If we already have been here set / clear as appropriate.
2289 * Otherwise allocate memory.
2291 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2292 if (mem != NULL && proc != NULL) {
2294 return (ISC_R_SUCCESS);
2297 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2298 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2300 result = ISC_R_UNEXPECTED;
2304 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2306 return (ISC_R_NOMEMORY);
2308 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2309 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2310 result = ISC_R_UNEXPECTED;
2314 totext_filter_proc = proc;
2315 return (ISC_R_SUCCESS);
2320 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2321 isc_result_t result;
2327 * Leave room for null termination after buffer.
2329 isc_buffer_init(&buf, cp, size - 1);
2330 result = dns_name_totext(name, ISC_TRUE, &buf);
2331 if (result == ISC_R_SUCCESS) {
2336 isc_buffer_usedregion(&buf, &r);
2337 ((char *) r.base)[r.length] = '\0';
2340 snprintf(cp, size, "<unknown>");
2344 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2345 unsigned char *ndata;
2348 * Make dest a copy of source.
2351 REQUIRE(VALID_NAME(source));
2352 REQUIRE(VALID_NAME(dest));
2353 REQUIRE(target != NULL || dest->buffer != NULL);
2355 if (target == NULL) {
2356 target = dest->buffer;
2357 isc_buffer_clear(dest->buffer);
2360 REQUIRE(BINDABLE(dest));
2365 if (target->length - target->used < source->length)
2366 return (ISC_R_NOSPACE);
2368 ndata = (unsigned char *)target->base + target->used;
2369 dest->ndata = target->base;
2371 memcpy(ndata, source->ndata, source->length);
2373 dest->ndata = ndata;
2374 dest->labels = source->labels;
2375 dest->length = source->length;
2376 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2377 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2379 dest->attributes = 0;
2381 if (dest->labels > 0 && dest->offsets != NULL) {
2382 if (source->offsets != NULL)
2383 memcpy(dest->offsets, source->offsets, source->labels);
2385 set_offsets(dest, dest->offsets, NULL);
2388 isc_buffer_add(target, dest->length);
2390 return (ISC_R_SUCCESS);
2394 dns_name_destroy(void) {
2395 #ifdef ISC_PLATFORM_USETHREADS
2396 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2399 LOCK(&thread_key_mutex);
2400 if (thread_key_initialized) {
2401 isc_mem_detach(&thread_key_mctx);
2402 isc_thread_key_delete(totext_filter_proc_key);
2403 thread_key_initialized = 0;
2405 UNLOCK(&thread_key_mutex);