2 * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
27 #include <isc/buffer.h>
31 #include <isc/print.h>
32 #include <isc/string.h>
33 #include <isc/thread.h>
36 #include <dns/compress.h>
37 #include <dns/fixedname.h>
39 #include <dns/result.h>
41 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
60 static char digitvalue[256] = {
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
64 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
65 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
67 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
79 static unsigned char maptolower[] = {
80 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
81 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
82 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
83 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
84 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
85 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
86 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
87 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
88 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
89 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
90 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
91 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
92 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
93 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
94 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
95 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
96 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
97 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
98 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
99 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
100 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
101 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
102 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
103 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
104 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
105 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
106 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
107 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
108 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
109 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
110 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
111 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
114 #define CONVERTTOASCII(c)
115 #define CONVERTFROMASCII(c)
117 #define INIT_OFFSETS(name, var, default) \
118 if (name->offsets != NULL) \
119 var = name->offsets; \
123 #define SETUP_OFFSETS(name, var, default) \
124 if (name->offsets != NULL) \
125 var = name->offsets; \
128 set_offsets(name, var, NULL); \
132 * Note: If additional attributes are added that should not be set for
133 * empty names, MAKE_EMPTY() must be changed so it clears them.
135 #define MAKE_EMPTY(name) \
137 name->ndata = NULL; \
140 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
144 * A name is "bindable" if it can be set to point to a new value, i.e.
145 * name->ndata and name->length may be changed.
147 #define BINDABLE(name) \
148 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
152 * Note that the name data must be a char array, not a string
153 * literal, to avoid compiler warnings about discarding
154 * the const attribute of a string.
156 static unsigned char root_ndata[] = { '\0' };
157 static unsigned char root_offsets[] = { 0 };
159 static dns_name_t root =
163 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
165 {(void *)-1, (void *)-1},
169 /* XXXDCL make const? */
170 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
172 static unsigned char wild_ndata[] = { '\001', '*' };
173 static unsigned char wild_offsets[] = { 0 };
175 static dns_name_t wild =
179 DNS_NAMEATTR_READONLY,
181 {(void *)-1, (void *)-1},
185 /* XXXDCL make const? */
186 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
189 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
192 * dns_name_t to text post-conversion procedure.
194 #ifdef ISC_PLATFORM_USETHREADS
195 static int thread_key_initialized = 0;
196 static isc_mutex_t thread_key_mutex;
197 static isc_mem_t *thread_key_mctx = NULL;
198 static isc_thread_key_t totext_filter_proc_key;
199 static isc_once_t once = ISC_ONCE_INIT;
201 static dns_name_totextfilter_t totext_filter_proc = NULL;
205 set_offsets(const dns_name_t *name, unsigned char *offsets,
206 dns_name_t *set_name);
209 dns_name_init(dns_name_t *name, unsigned char *offsets) {
213 DNS_NAME_INIT(name, offsets);
217 dns_name_reset(dns_name_t *name) {
218 REQUIRE(VALID_NAME(name));
219 REQUIRE(BINDABLE(name));
221 DNS_NAME_RESET(name);
225 dns_name_invalidate(dns_name_t *name) {
227 * Make 'name' invalid.
230 REQUIRE(VALID_NAME(name));
236 name->attributes = 0;
237 name->offsets = NULL;
239 ISC_LINK_INIT(name, link);
243 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
245 * Dedicate a buffer for use with 'name'.
248 REQUIRE(VALID_NAME(name));
249 REQUIRE((buffer != NULL && name->buffer == NULL) ||
252 name->buffer = buffer;
256 dns_name_hasbuffer(const dns_name_t *name) {
258 * Does 'name' have a dedicated buffer?
261 REQUIRE(VALID_NAME(name));
263 if (name->buffer != NULL)
270 dns_name_isabsolute(const dns_name_t *name) {
273 * Does 'name' end in the root label?
276 REQUIRE(VALID_NAME(name));
278 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
283 #define hyphenchar(c) ((c) == 0x2d)
284 #define asterchar(c) ((c) == 0x2a)
285 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
286 || ((c) >= 0x61 && (c) <= 0x7a))
287 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
288 #define borderchar(c) (alphachar(c) || digitchar(c))
289 #define middlechar(c) (borderchar(c) || hyphenchar(c))
290 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
293 dns_name_ismailbox(const dns_name_t *name) {
294 unsigned char *ndata, ch;
298 REQUIRE(VALID_NAME(name));
299 REQUIRE(name->labels > 0);
300 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
305 if (name->length == 1)
317 if (ndata == name->ndata + name->length)
321 * RFC292/RFC1123 hostname.
323 while (ndata < (name->ndata + name->length)) {
329 if (first || n == 0) {
343 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
344 unsigned char *ndata, ch;
348 REQUIRE(VALID_NAME(name));
349 REQUIRE(name->labels > 0);
350 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
355 if (name->length == 1)
359 * Skip wildcard if this is a ownername.
362 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
366 * RFC292/RFC1123 hostname.
368 while (ndata < (name->ndata + name->length)) {
374 if (first || n == 0) {
388 dns_name_iswildcard(const dns_name_t *name) {
389 unsigned char *ndata;
392 * Is 'name' a wildcard name?
395 REQUIRE(VALID_NAME(name));
396 REQUIRE(name->labels > 0);
398 if (name->length >= 2) {
400 if (ndata[0] == 1 && ndata[1] == '*')
408 dns_name_internalwildcard(const dns_name_t *name) {
409 unsigned char *ndata;
414 * Does 'name' contain a internal wildcard?
417 REQUIRE(VALID_NAME(name));
418 REQUIRE(name->labels > 0);
429 * Check all but the last of the remaining labels.
431 while (label + 1 < name->labels) {
434 if (count == 1 && *ndata == '*')
442 static inline unsigned int
443 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
445 const unsigned char *s;
449 length = name->length;
454 * This hash function is similar to the one Ousterhout
458 if (case_sensitive) {
460 h += ( h << 3 ) + *s;
477 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
479 * Provide a hash value for 'name'.
481 REQUIRE(VALID_NAME(name));
483 if (name->labels == 0)
486 return (name_hash(name, case_sensitive));
490 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
492 * Provide a hash value for 'name'.
494 REQUIRE(VALID_NAME(name));
496 if (name->labels == 0)
499 return (isc_hash_calc((const unsigned char *)name->ndata,
500 name->length, case_sensitive));
504 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
506 * This function was deprecated due to the breakage of the name space
507 * convention. We only keep this internally to provide binary backward
510 REQUIRE(VALID_NAME(name));
512 return (dns_name_fullhash(name, case_sensitive));
516 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
517 unsigned char *offsets;
524 * Provide a hash value for 'name'.
526 REQUIRE(VALID_NAME(name));
528 if (name->labels == 0)
530 else if (name->labels == 1)
531 return (name_hash(name, case_sensitive));
533 SETUP_OFFSETS(name, offsets, odata);
534 DNS_NAME_INIT(&tname, NULL);
537 for (i = 0; i < name->labels; i++) {
538 tname.ndata = name->ndata + offsets[i];
539 if (i == name->labels - 1)
540 tname.length = name->length - offsets[i];
542 tname.length = offsets[i + 1] - offsets[i];
543 h += name_hash(&tname, case_sensitive);
550 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
551 int *orderp, unsigned int *nlabelsp)
553 unsigned int l1, l2, l, count1, count2, count, nlabels;
554 int cdiff, ldiff, chdiff;
555 unsigned char *label1, *label2;
556 unsigned char *offsets1, *offsets2;
557 dns_offsets_t odata1, odata2;
558 dns_namereln_t namereln = dns_namereln_none;
561 * Determine the relative ordering under the DNSSEC order relation of
562 * 'name1' and 'name2', and also determine the hierarchical
563 * relationship of the names.
565 * Note: It makes no sense for one of the names to be relative and the
566 * other absolute. If both names are relative, then to be meaningfully
567 * compared the caller must ensure that they are both relative to the
571 REQUIRE(VALID_NAME(name1));
572 REQUIRE(VALID_NAME(name2));
573 REQUIRE(orderp != NULL);
574 REQUIRE(nlabelsp != NULL);
576 * Either name1 is absolute and name2 is absolute, or neither is.
578 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
579 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
581 SETUP_OFFSETS(name1, offsets1, odata1);
582 SETUP_OFFSETS(name2, offsets2, odata2);
587 ldiff = (int)l1 - (int)l2;
597 label1 = &name1->ndata[offsets1[l1]];
598 label2 = &name2->ndata[offsets2[l2]];
603 * We dropped bitstring labels, and we don't support any
604 * other extended label types.
606 INSIST(count1 <= 63 && count2 <= 63);
608 cdiff = (int)count1 - (int)count2;
615 chdiff = (int)maptolower[*label1] -
616 (int)maptolower[*label2];
634 namereln = dns_namereln_contains;
636 namereln = dns_namereln_subdomain;
638 namereln = dns_namereln_equal;
643 if (nlabels > 0 && namereln == dns_namereln_none)
644 namereln = dns_namereln_commonancestor;
650 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
652 unsigned int nlabels;
655 * Determine the relative ordering under the DNSSEC order relation of
656 * 'name1' and 'name2'.
658 * Note: It makes no sense for one of the names to be relative and the
659 * other absolute. If both names are relative, then to be meaningfully
660 * compared the caller must ensure that they are both relative to the
664 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
670 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
671 unsigned int l, count;
673 unsigned char *label1, *label2;
676 * Are 'name1' and 'name2' equal?
678 * Note: It makes no sense for one of the names to be relative and the
679 * other absolute. If both names are relative, then to be meaningfully
680 * compared the caller must ensure that they are both relative to the
684 REQUIRE(VALID_NAME(name1));
685 REQUIRE(VALID_NAME(name2));
687 * Either name1 is absolute and name2 is absolute, or neither is.
689 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
690 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
692 if (name1->length != name2->length)
697 if (l != name2->labels)
700 label1 = name1->ndata;
701 label2 = name2->ndata;
705 if (count != *label2++)
708 INSIST(count <= 63); /* no bitstring support */
712 c = maptolower[*label1++];
713 if (c != maptolower[*label2++])
722 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
725 * Are 'name1' and 'name2' equal?
727 * Note: It makes no sense for one of the names to be relative and the
728 * other absolute. If both names are relative, then to be meaningfully
729 * compared the caller must ensure that they are both relative to the
733 REQUIRE(VALID_NAME(name1));
734 REQUIRE(VALID_NAME(name2));
736 * Either name1 is absolute and name2 is absolute, or neither is.
738 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
739 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
741 if (name1->length != name2->length)
744 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
751 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
752 unsigned int l1, l2, l, count1, count2, count;
753 unsigned char c1, c2;
754 unsigned char *label1, *label2;
757 * Compare two absolute names as rdata.
760 REQUIRE(VALID_NAME(name1));
761 REQUIRE(name1->labels > 0);
762 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
763 REQUIRE(VALID_NAME(name2));
764 REQUIRE(name2->labels > 0);
765 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
770 l = (l1 < l2) ? l1 : l2;
772 label1 = name1->ndata;
773 label2 = name2->ndata;
779 /* no bitstring support */
780 INSIST(count1 <= 63 && count2 <= 63);
782 if (count1 != count2)
783 return ((count1 < count2) ? -1 : 1);
787 c1 = maptolower[*label1++];
788 c2 = maptolower[*label2++];
797 * If one name had more labels than the other, their common
798 * prefix must have been different because the shorter name
799 * ended with the root label and the longer one can't have
800 * a root label in the middle of it. Therefore, if we get
801 * to this point, the lengths must be equal.
809 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
811 unsigned int nlabels;
812 dns_namereln_t namereln;
815 * Is 'name1' a subdomain of 'name2'?
817 * Note: It makes no sense for one of the names to be relative and the
818 * other absolute. If both names are relative, then to be meaningfully
819 * compared the caller must ensure that they are both relative to the
823 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
824 if (namereln == dns_namereln_subdomain ||
825 namereln == dns_namereln_equal)
832 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
834 unsigned int nlabels, labels;
837 REQUIRE(VALID_NAME(name));
838 REQUIRE(name->labels > 0);
839 REQUIRE(VALID_NAME(wname));
840 labels = wname->labels;
842 REQUIRE(dns_name_iswildcard(wname));
844 DNS_NAME_INIT(&tname, NULL);
845 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
846 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
847 dns_namereln_subdomain)
853 dns_name_countlabels(const dns_name_t *name) {
855 * How many labels does 'name' have?
858 REQUIRE(VALID_NAME(name));
860 ENSURE(name->labels <= 128);
862 return (name->labels);
866 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
867 unsigned char *offsets;
871 * Make 'label' refer to the 'n'th least significant label of 'name'.
874 REQUIRE(VALID_NAME(name));
875 REQUIRE(name->labels > 0);
876 REQUIRE(n < name->labels);
877 REQUIRE(label != NULL);
879 SETUP_OFFSETS(name, offsets, odata);
881 label->base = &name->ndata[offsets[n]];
882 if (n == name->labels - 1)
883 label->length = name->length - offsets[n];
885 label->length = offsets[n + 1] - offsets[n];
889 dns_name_getlabelsequence(const dns_name_t *source,
890 unsigned int first, unsigned int n,
893 unsigned char *offsets;
895 unsigned int firstoffset, endoffset;
898 * Make 'target' refer to the 'n' labels including and following
899 * 'first' in 'source'.
902 REQUIRE(VALID_NAME(source));
903 REQUIRE(VALID_NAME(target));
904 REQUIRE(first <= source->labels);
905 REQUIRE(n <= source->labels - first); /* note first+n could overflow */
906 REQUIRE(BINDABLE(target));
908 SETUP_OFFSETS(source, offsets, odata);
910 if (first == source->labels)
911 firstoffset = source->length;
913 firstoffset = offsets[first];
915 if (first + n == source->labels)
916 endoffset = source->length;
918 endoffset = offsets[first + n];
920 target->ndata = &source->ndata[firstoffset];
921 target->length = endoffset - firstoffset;
923 if (first + n == source->labels && n > 0 &&
924 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
925 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
927 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
932 * If source and target are the same, and we're making target
933 * a prefix of source, the offsets table is correct already
934 * so we don't need to call set_offsets().
936 if (target->offsets != NULL &&
937 (target != source || first != 0))
938 set_offsets(target, target->offsets, NULL);
942 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
945 * Make 'target' refer to the same name as 'source'.
948 REQUIRE(VALID_NAME(source));
949 REQUIRE(VALID_NAME(target));
950 REQUIRE(BINDABLE(target));
952 target->ndata = source->ndata;
953 target->length = source->length;
954 target->labels = source->labels;
955 target->attributes = source->attributes &
956 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
957 DNS_NAMEATTR_DYNOFFSETS);
958 if (target->offsets != NULL && source->labels > 0) {
959 if (source->offsets != NULL)
960 memcpy(target->offsets, source->offsets,
963 set_offsets(target, target->offsets, NULL);
968 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
969 unsigned char *offsets;
975 * Make 'name' refer to region 'r'.
978 REQUIRE(VALID_NAME(name));
980 REQUIRE(BINDABLE(name));
982 INIT_OFFSETS(name, offsets, odata);
984 if (name->buffer != NULL) {
985 isc_buffer_clear(name->buffer);
986 isc_buffer_availableregion(name->buffer, &r2);
987 len = (r->length < r2.length) ? r->length : r2.length;
988 if (len > DNS_NAME_MAXWIRE)
989 len = DNS_NAME_MAXWIRE;
990 memcpy(r2.base, r->base, len);
991 name->ndata = r2.base;
994 name->ndata = r->base;
995 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
996 r->length : DNS_NAME_MAXWIRE;
1000 set_offsets(name, offsets, name);
1003 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1006 if (name->buffer != NULL)
1007 isc_buffer_add(name->buffer, name->length);
1011 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1013 * Make 'r' refer to 'name'.
1016 REQUIRE(VALID_NAME(name));
1019 DNS_NAME_TOREGION(name, r);
1023 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1024 const dns_name_t *origin, unsigned int options,
1025 isc_buffer_t *target)
1027 unsigned char *ndata, *label = NULL;
1031 unsigned int value = 0, count = 0;
1032 unsigned int n1 = 0, n2 = 0;
1033 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1035 unsigned char *offsets;
1036 dns_offsets_t odata;
1037 isc_boolean_t downcase;
1040 * Convert the textual representation of a DNS name at source
1041 * into uncompressed wire form stored in target.
1044 * Relative domain names will have 'origin' appended to them
1045 * unless 'origin' is NULL, in which case relative domain names
1046 * will remain relative.
1049 REQUIRE(VALID_NAME(name));
1050 REQUIRE(ISC_BUFFER_VALID(source));
1051 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1052 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1054 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1056 if (target == NULL && name->buffer != NULL) {
1057 target = name->buffer;
1058 isc_buffer_clear(target);
1061 REQUIRE(BINDABLE(name));
1063 INIT_OFFSETS(name, offsets, odata);
1067 * Make 'name' empty in case of failure.
1072 * Set up the state machine.
1074 tdata = (char *)source->base + source->current;
1075 tlen = isc_buffer_remaininglength(source);
1077 ndata = isc_buffer_used(target);
1078 nrem = isc_buffer_availablelength(target);
1086 while (nrem > 0 && tlen > 0 && !done) {
1094 * Is this the root name?
1098 return (DNS_R_EMPTYLABEL);
1106 if (c == '@' && tlen == 0) {
1119 state = ft_initialescape;
1122 state = ft_ordinary;
1124 return (ISC_R_NOSPACE);
1129 return (DNS_R_EMPTYLABEL);
1132 INSIST(labels <= 127);
1133 offsets[labels] = nused;
1142 } else if (c == '\\') {
1146 return (DNS_R_LABELTOOLONG);
1150 c = maptolower[(int)c];
1156 case ft_initialescape:
1159 * This looks like a bitstring label, which
1160 * was deprecated. Intentionally drop it.
1162 return (DNS_R_BADLABELTYPE);
1168 if (!isdigit(c & 0xff)) {
1170 return (DNS_R_LABELTOOLONG);
1174 c = maptolower[(int)c];
1178 state = ft_ordinary;
1183 state = ft_escdecimal;
1186 if (!isdigit(c & 0xff))
1187 return (DNS_R_BADESCAPE);
1189 value += digitvalue[(int)c];
1193 return (DNS_R_BADESCAPE);
1195 return (DNS_R_LABELTOOLONG);
1198 value = maptolower[value];
1202 state = ft_ordinary;
1206 FATAL_ERROR(__FILE__, __LINE__,
1207 "Unexpected state %d", state);
1208 /* Does not return. */
1214 return (ISC_R_NOSPACE);
1216 if (state != ft_ordinary && state != ft_at)
1217 return (ISC_R_UNEXPECTEDEND);
1218 if (state == ft_ordinary) {
1222 INSIST(labels <= 127);
1223 offsets[labels] = nused;
1225 if (origin != NULL) {
1226 if (nrem < origin->length)
1227 return (ISC_R_NOSPACE);
1228 label = origin->ndata;
1229 n1 = origin->length;
1234 INSIST(n2 <= 63); /* no bitstring support */
1241 c = maptolower[(int)c];
1247 INSIST(labels <= 127);
1248 offsets[labels] = nused;
1251 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1252 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1255 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1257 name->ndata = (unsigned char *)target->base + target->used;
1258 name->labels = labels;
1259 name->length = nused;
1261 isc_buffer_forward(source, tused);
1262 isc_buffer_add(target, name->length);
1264 return (ISC_R_SUCCESS);
1267 #ifdef ISC_PLATFORM_USETHREADS
1269 free_specific(void *arg) {
1270 dns_name_totextfilter_t *mem = arg;
1271 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1272 /* Stop use being called again. */
1273 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1277 thread_key_mutex_init(void) {
1278 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1282 totext_filter_proc_key_init(void) {
1283 isc_result_t result;
1286 * We need the call to isc_once_do() to support profiled mutex
1287 * otherwise thread_key_mutex could be initialized at compile time.
1289 result = isc_once_do(&once, thread_key_mutex_init);
1290 if (result != ISC_R_SUCCESS)
1293 if (!thread_key_initialized) {
1294 LOCK(&thread_key_mutex);
1295 if (thread_key_mctx == NULL)
1296 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1297 if (result != ISC_R_SUCCESS)
1299 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1300 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1302 if (!thread_key_initialized &&
1303 isc_thread_key_create(&totext_filter_proc_key,
1304 free_specific) != 0) {
1305 result = ISC_R_FAILURE;
1306 isc_mem_detach(&thread_key_mctx);
1308 thread_key_initialized = 1;
1310 UNLOCK(&thread_key_mutex);
1317 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1318 isc_buffer_t *target)
1320 unsigned int options = DNS_NAME_MASTERFILE;
1323 options |= DNS_NAME_OMITFINALDOT;
1324 return (dns_name_totext2(name, options, target));
1328 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1329 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1333 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1335 unsigned char *ndata;
1337 unsigned int nlen, tlen;
1339 unsigned int trem, count;
1340 unsigned int labels;
1341 isc_boolean_t saw_root = ISC_FALSE;
1342 unsigned int oused = target->used;
1343 #ifdef ISC_PLATFORM_USETHREADS
1344 dns_name_totextfilter_t *mem;
1345 dns_name_totextfilter_t totext_filter_proc = NULL;
1346 isc_result_t result;
1348 isc_boolean_t omit_final_dot =
1349 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1352 * This function assumes the name is in proper uncompressed
1355 REQUIRE(VALID_NAME(name));
1356 REQUIRE(ISC_BUFFER_VALID(target));
1358 #ifdef ISC_PLATFORM_USETHREADS
1359 result = totext_filter_proc_key_init();
1360 if (result != ISC_R_SUCCESS)
1363 ndata = name->ndata;
1364 nlen = name->length;
1365 labels = name->labels;
1366 tdata = isc_buffer_used(target);
1367 tlen = isc_buffer_availablelength(target);
1371 if (labels == 0 && nlen == 0) {
1373 * Special handling for an empty name.
1376 return (ISC_R_NOSPACE);
1379 * The names of these booleans are misleading in this case.
1380 * This empty name is not necessarily from the root node of
1381 * the DNS root zone, nor is a final dot going to be included.
1382 * They need to be set this way, though, to keep the "@"
1383 * from being trounced.
1385 saw_root = ISC_TRUE;
1386 omit_final_dot = ISC_FALSE;
1391 * Skip the while() loop.
1394 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1396 * Special handling for the root label.
1399 return (ISC_R_NOSPACE);
1401 saw_root = ISC_TRUE;
1402 omit_final_dot = ISC_FALSE;
1407 * Skip the while() loop.
1412 while (labels > 0 && nlen > 0 && trem > 0) {
1417 saw_root = ISC_TRUE;
1421 INSIST(nlen >= count);
1425 /* Special modifiers in zone files. */
1426 case 0x40: /* '@' */
1427 case 0x24: /* '$' */
1428 if ((options & DNS_NAME_MASTERFILE) == 0)
1430 case 0x22: /* '"' */
1431 case 0x28: /* '(' */
1432 case 0x29: /* ')' */
1433 case 0x2E: /* '.' */
1434 case 0x3B: /* ';' */
1435 case 0x5C: /* '\\' */
1437 return (ISC_R_NOSPACE);
1439 CONVERTFROMASCII(c);
1447 if (c > 0x20 && c < 0x7f) {
1449 return (ISC_R_NOSPACE);
1450 CONVERTFROMASCII(c);
1457 return (ISC_R_NOSPACE);
1463 *tdata++ = 0x30 + (c % 10);
1472 FATAL_ERROR(__FILE__, __LINE__,
1473 "Unexpected label type %02x", count);
1478 * The following assumes names are absolute. If not, we
1479 * fix things up later. Note that this means that in some
1480 * cases one more byte of text buffer is required than is
1481 * needed in the final output.
1484 return (ISC_R_NOSPACE);
1489 if (nlen != 0 && trem == 0)
1490 return (ISC_R_NOSPACE);
1492 if (!saw_root || omit_final_dot)
1495 isc_buffer_add(target, tlen - trem);
1497 #ifdef ISC_PLATFORM_USETHREADS
1498 mem = isc_thread_key_getspecific(totext_filter_proc_key);
1500 totext_filter_proc = *mem;
1502 if (totext_filter_proc != NULL)
1503 return ((*totext_filter_proc)(target, oused, saw_root));
1505 return (ISC_R_SUCCESS);
1509 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1510 isc_buffer_t *target)
1512 unsigned char *ndata;
1514 unsigned int nlen, tlen;
1516 unsigned int trem, count;
1517 unsigned int labels;
1520 * This function assumes the name is in proper uncompressed
1523 REQUIRE(VALID_NAME(name));
1524 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1525 REQUIRE(ISC_BUFFER_VALID(target));
1527 ndata = name->ndata;
1528 nlen = name->length;
1529 labels = name->labels;
1530 tdata = isc_buffer_used(target);
1531 tlen = isc_buffer_availablelength(target);
1535 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1537 * Special handling for the root label.
1540 return (ISC_R_NOSPACE);
1542 omit_final_dot = ISC_FALSE;
1547 * Skip the while() loop.
1552 while (labels > 0 && nlen > 0 && trem > 0) {
1559 INSIST(nlen >= count);
1562 if ((c >= 0x30 && c <= 0x39) || /* digit */
1563 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1564 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1565 c == 0x2D || /* hyphen */
1566 c == 0x5F) /* underscore */
1569 return (ISC_R_NOSPACE);
1571 if (c >= 0x41 && c <= 0x5A)
1573 CONVERTFROMASCII(c);
1580 return (ISC_R_NOSPACE);
1581 sprintf(tdata, "%%%02X", c);
1590 FATAL_ERROR(__FILE__, __LINE__,
1591 "Unexpected label type %02x", count);
1596 * The following assumes names are absolute. If not, we
1597 * fix things up later. Note that this means that in some
1598 * cases one more byte of text buffer is required than is
1599 * needed in the final output.
1602 return (ISC_R_NOSPACE);
1607 if (nlen != 0 && trem == 0)
1608 return (ISC_R_NOSPACE);
1613 isc_buffer_add(target, tlen - trem);
1615 return (ISC_R_SUCCESS);
1619 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1620 unsigned char *sndata, *ndata;
1621 unsigned int nlen, count, labels;
1622 isc_buffer_t buffer;
1625 * Downcase 'source'.
1628 REQUIRE(VALID_NAME(source));
1629 REQUIRE(VALID_NAME(name));
1630 if (source == name) {
1631 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1632 isc_buffer_init(&buffer, source->ndata, source->length);
1634 ndata = source->ndata;
1636 REQUIRE(BINDABLE(name));
1637 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1638 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1639 if (target == NULL) {
1640 target = name->buffer;
1641 isc_buffer_clear(name->buffer);
1643 ndata = (unsigned char *)target->base + target->used;
1644 name->ndata = ndata;
1647 sndata = source->ndata;
1648 nlen = source->length;
1649 labels = source->labels;
1651 if (nlen > (target->length - target->used)) {
1653 return (ISC_R_NOSPACE);
1656 while (labels > 0 && nlen > 0) {
1662 INSIST(nlen >= count);
1664 *ndata++ = maptolower[(*sndata++)];
1669 FATAL_ERROR(__FILE__, __LINE__,
1670 "Unexpected label type %02x", count);
1671 /* Does not return. */
1675 if (source != name) {
1676 name->labels = source->labels;
1677 name->length = source->length;
1678 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1679 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1681 name->attributes = 0;
1682 if (name->labels > 0 && name->offsets != NULL)
1683 set_offsets(name, name->offsets, NULL);
1686 isc_buffer_add(target, name->length);
1688 return (ISC_R_SUCCESS);
1692 set_offsets(const dns_name_t *name, unsigned char *offsets,
1693 dns_name_t *set_name)
1695 unsigned int offset, count, length, nlabels;
1696 unsigned char *ndata;
1697 isc_boolean_t absolute;
1699 ndata = name->ndata;
1700 length = name->length;
1703 absolute = ISC_FALSE;
1704 while (offset != length) {
1705 INSIST(nlabels < 128);
1706 offsets[nlabels++] = offset;
1709 INSIST(count <= 63);
1712 INSIST(offset <= length);
1714 absolute = ISC_TRUE;
1718 if (set_name != NULL) {
1719 INSIST(set_name == name);
1721 set_name->labels = nlabels;
1722 set_name->length = offset;
1724 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1726 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1728 INSIST(nlabels == name->labels);
1729 INSIST(offset == name->length);
1733 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1734 dns_decompress_t *dctx, unsigned int options,
1735 isc_buffer_t *target)
1737 unsigned char *cdata, *ndata;
1738 unsigned int cused; /* Bytes of compressed name data used */
1739 unsigned int nused, labels, n, nmax;
1740 unsigned int current, new_current, biggest_pointer;
1742 fw_state state = fw_start;
1744 unsigned char *offsets;
1745 dns_offsets_t odata;
1746 isc_boolean_t downcase;
1747 isc_boolean_t seen_pointer;
1750 * Copy the possibly-compressed name at source into target,
1751 * decompressing it. Loop prevention is performed by checking
1752 * the new pointer against biggest_pointer.
1755 REQUIRE(VALID_NAME(name));
1756 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1757 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1759 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1761 if (target == NULL && name->buffer != NULL) {
1762 target = name->buffer;
1763 isc_buffer_clear(target);
1766 REQUIRE(dctx != NULL);
1767 REQUIRE(BINDABLE(name));
1769 INIT_OFFSETS(name, offsets, odata);
1772 * Make 'name' empty in case of failure.
1777 * Initialize things to make the compiler happy; they're not required.
1788 ndata = isc_buffer_used(target);
1790 seen_pointer = ISC_FALSE;
1793 * Find the maximum number of uncompressed target name
1794 * bytes we are willing to generate. This is the smaller
1795 * of the available target buffer length and the
1796 * maximum legal domain name length (255).
1798 nmax = isc_buffer_availablelength(target);
1799 if (nmax > DNS_NAME_MAXWIRE)
1800 nmax = DNS_NAME_MAXWIRE;
1802 cdata = isc_buffer_current(source);
1805 current = source->current;
1806 biggest_pointer = current;
1809 * Note: The following code is not optimized for speed, but
1810 * rather for correctness. Speed will be addressed in the future.
1813 while (current < source->active && !done) {
1822 offsets[labels] = nused;
1824 if (nused + c + 1 > nmax)
1831 state = fw_ordinary;
1832 } else if (c >= 128 && c < 192) {
1834 * 14 bit local compression pointer.
1835 * Local compression is no longer an
1838 return (DNS_R_BADLABELTYPE);
1839 } else if (c >= 192) {
1841 * Ordinary 14-bit pointer.
1843 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1845 return (DNS_R_DISALLOWED);
1846 new_current = c & 0x3F;
1848 state = fw_newcurrent;
1850 return (DNS_R_BADLABELTYPE);
1868 if (new_current >= biggest_pointer)
1869 return (DNS_R_BADPOINTER);
1870 biggest_pointer = new_current;
1871 current = new_current;
1872 cdata = (unsigned char *)source->base + current;
1873 seen_pointer = ISC_TRUE;
1877 FATAL_ERROR(__FILE__, __LINE__,
1878 "Unknown state %d", state);
1879 /* Does not return. */
1884 return (ISC_R_UNEXPECTEDEND);
1886 name->ndata = (unsigned char *)target->base + target->used;
1887 name->labels = labels;
1888 name->length = nused;
1889 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1891 isc_buffer_forward(source, cused);
1892 isc_buffer_add(target, name->length);
1894 return (ISC_R_SUCCESS);
1897 if (nmax == DNS_NAME_MAXWIRE)
1899 * The name did not fit even though we had a buffer
1900 * big enough to fit a maximum-length name.
1902 return (DNS_R_NAMETOOLONG);
1905 * The name might fit if only the caller could give us a
1906 * big enough buffer.
1908 return (ISC_R_NOSPACE);
1912 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1913 isc_buffer_t *target)
1915 unsigned int methods;
1916 isc_uint16_t offset;
1917 dns_name_t gp; /* Global compression prefix */
1918 isc_boolean_t gf; /* Global compression target found */
1919 isc_uint16_t go; /* Global compression offset */
1924 * Convert 'name' into wire format, compressing it as specified by the
1925 * compression context 'cctx', and storing the result in 'target'.
1928 REQUIRE(VALID_NAME(name));
1929 REQUIRE(cctx != NULL);
1930 REQUIRE(ISC_BUFFER_VALID(target));
1933 * If 'name' doesn't have an offsets table, make a clone which
1936 if (name->offsets == NULL) {
1937 DNS_NAME_INIT(&clname, clo);
1938 dns_name_clone(name, &clname);
1941 DNS_NAME_INIT(&gp, NULL);
1943 offset = target->used; /*XXX*/
1945 methods = dns_compress_getmethods(cctx);
1947 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1948 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1949 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1954 * If the offset is too high for 14 bit global compression, we're
1957 if (gf && go >= 0x4000)
1961 * Will the compression pointer reduce the message size?
1963 if (gf && (gp.length + 2) >= name->length)
1967 if (target->length - target->used < gp.length)
1968 return (ISC_R_NOSPACE);
1969 (void)memcpy((unsigned char *)target->base + target->used,
1970 gp.ndata, (size_t)gp.length);
1971 isc_buffer_add(target, gp.length);
1973 if (target->length - target->used < 2)
1974 return (ISC_R_NOSPACE);
1975 isc_buffer_putuint16(target, go);
1977 dns_compress_add(cctx, name, &gp, offset);
1979 if (target->length - target->used < name->length)
1980 return (ISC_R_NOSPACE);
1981 (void)memcpy((unsigned char *)target->base + target->used,
1982 name->ndata, (size_t)name->length);
1983 isc_buffer_add(target, name->length);
1984 dns_compress_add(cctx, name, name, offset);
1986 return (ISC_R_SUCCESS);
1990 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1991 isc_buffer_t *target)
1993 unsigned char *ndata, *offsets;
1994 unsigned int nrem, labels, prefix_length, length;
1995 isc_boolean_t copy_prefix = ISC_TRUE;
1996 isc_boolean_t copy_suffix = ISC_TRUE;
1997 isc_boolean_t absolute = ISC_FALSE;
1998 dns_name_t tmp_name;
1999 dns_offsets_t odata;
2002 * Concatenate 'prefix' and 'suffix'.
2005 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2006 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2007 REQUIRE(name == NULL || VALID_NAME(name));
2008 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2009 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2010 if (prefix == NULL || prefix->labels == 0)
2011 copy_prefix = ISC_FALSE;
2012 if (suffix == NULL || suffix->labels == 0)
2013 copy_suffix = ISC_FALSE;
2015 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2016 absolute = ISC_TRUE;
2017 REQUIRE(!copy_suffix);
2020 DNS_NAME_INIT(&tmp_name, odata);
2023 if (target == NULL) {
2024 INSIST(name->buffer != NULL);
2025 target = name->buffer;
2026 isc_buffer_clear(name->buffer);
2029 REQUIRE(BINDABLE(name));
2034 nrem = target->length - target->used;
2035 ndata = (unsigned char *)target->base + target->used;
2036 if (nrem > DNS_NAME_MAXWIRE)
2037 nrem = DNS_NAME_MAXWIRE;
2042 prefix_length = prefix->length;
2043 length += prefix_length;
2044 labels += prefix->labels;
2047 length += suffix->length;
2048 labels += suffix->labels;
2050 if (length > DNS_NAME_MAXWIRE) {
2052 return (DNS_R_NAMETOOLONG);
2054 if (length > nrem) {
2056 return (ISC_R_NOSPACE);
2060 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2061 absolute = ISC_TRUE;
2062 if (suffix == name && suffix->buffer == target)
2063 memmove(ndata + prefix_length, suffix->ndata,
2066 memcpy(ndata + prefix_length, suffix->ndata,
2071 * If 'prefix' and 'name' are the same object, and the object has
2072 * a dedicated buffer, and we're using it, then we don't have to
2075 if (copy_prefix && (prefix != name || prefix->buffer != target))
2076 memcpy(ndata, prefix->ndata, prefix_length);
2078 name->ndata = ndata;
2079 name->labels = labels;
2080 name->length = length;
2082 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2084 name->attributes = 0;
2086 if (name->labels > 0 && name->offsets != NULL) {
2087 INIT_OFFSETS(name, offsets, odata);
2088 set_offsets(name, offsets, NULL);
2091 isc_buffer_add(target, name->length);
2093 return (ISC_R_SUCCESS);
2097 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2098 dns_name_t *prefix, dns_name_t *suffix)
2101 unsigned int splitlabel;
2103 REQUIRE(VALID_NAME(name));
2104 REQUIRE(suffixlabels > 0);
2105 REQUIRE(suffixlabels < name->labels);
2106 REQUIRE(prefix != NULL || suffix != NULL);
2107 REQUIRE(prefix == NULL ||
2108 (VALID_NAME(prefix) &&
2109 prefix->buffer != NULL &&
2111 REQUIRE(suffix == NULL ||
2112 (VALID_NAME(suffix) &&
2113 suffix->buffer != NULL &&
2116 splitlabel = name->labels - suffixlabels;
2119 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2122 dns_name_getlabelsequence(name, splitlabel,
2123 suffixlabels, suffix);
2129 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2133 * Make 'target' a dynamically allocated copy of 'source'.
2136 REQUIRE(VALID_NAME(source));
2137 REQUIRE(source->length > 0);
2138 REQUIRE(VALID_NAME(target));
2139 REQUIRE(BINDABLE(target));
2142 * Make 'target' empty in case of failure.
2146 target->ndata = isc_mem_get(mctx, source->length);
2147 if (target->ndata == NULL)
2148 return (ISC_R_NOMEMORY);
2150 memcpy(target->ndata, source->ndata, source->length);
2152 target->length = source->length;
2153 target->labels = source->labels;
2154 target->attributes = DNS_NAMEATTR_DYNAMIC;
2155 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2156 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2157 if (target->offsets != NULL) {
2158 if (source->offsets != NULL)
2159 memcpy(target->offsets, source->offsets,
2162 set_offsets(target, target->offsets, NULL);
2165 return (ISC_R_SUCCESS);
2169 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2173 * Make 'target' a read-only dynamically allocated copy of 'source'.
2174 * 'target' will also have a dynamically allocated offsets table.
2177 REQUIRE(VALID_NAME(source));
2178 REQUIRE(source->length > 0);
2179 REQUIRE(VALID_NAME(target));
2180 REQUIRE(BINDABLE(target));
2181 REQUIRE(target->offsets == NULL);
2184 * Make 'target' empty in case of failure.
2188 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2189 if (target->ndata == NULL)
2190 return (ISC_R_NOMEMORY);
2192 memcpy(target->ndata, source->ndata, source->length);
2194 target->length = source->length;
2195 target->labels = source->labels;
2196 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2197 DNS_NAMEATTR_READONLY;
2198 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2199 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2200 target->offsets = target->ndata + source->length;
2201 if (source->offsets != NULL)
2202 memcpy(target->offsets, source->offsets, source->labels);
2204 set_offsets(target, target->offsets, NULL);
2206 return (ISC_R_SUCCESS);
2210 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2217 REQUIRE(VALID_NAME(name));
2218 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2220 size = name->length;
2221 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2222 size += name->labels;
2223 isc_mem_put(mctx, name->ndata, size);
2224 dns_name_invalidate(name);
2228 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2229 dns_name_t downname;
2230 unsigned char data[256];
2231 isc_buffer_t buffer;
2232 isc_result_t result;
2236 * Send 'name' in DNSSEC canonical form to 'digest'.
2239 REQUIRE(VALID_NAME(name));
2240 REQUIRE(digest != NULL);
2242 DNS_NAME_INIT(&downname, NULL);
2243 isc_buffer_init(&buffer, data, sizeof(data));
2245 result = dns_name_downcase(name, &downname, &buffer);
2246 if (result != ISC_R_SUCCESS)
2249 isc_buffer_usedregion(&buffer, &r);
2251 return ((digest)(arg, &r));
2255 dns_name_dynamic(dns_name_t *name) {
2256 REQUIRE(VALID_NAME(name));
2259 * Returns whether there is dynamic memory associated with this name.
2262 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2263 ISC_TRUE : ISC_FALSE);
2267 dns_name_print(dns_name_t *name, FILE *stream) {
2268 isc_result_t result;
2274 * Print 'name' on 'stream'.
2277 REQUIRE(VALID_NAME(name));
2279 isc_buffer_init(&b, t, sizeof(t));
2280 result = dns_name_totext(name, ISC_FALSE, &b);
2281 if (result != ISC_R_SUCCESS)
2283 isc_buffer_usedregion(&b, &r);
2284 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2286 return (ISC_R_SUCCESS);
2290 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2291 #ifdef ISC_PLATFORM_USETHREADS
2292 isc_result_t result;
2293 dns_name_totextfilter_t *mem;
2296 result = totext_filter_proc_key_init();
2297 if (result != ISC_R_SUCCESS)
2301 * If we already have been here set / clear as appropriate.
2302 * Otherwise allocate memory.
2304 mem = isc_thread_key_getspecific(totext_filter_proc_key);
2305 if (mem != NULL && proc != NULL) {
2307 return (ISC_R_SUCCESS);
2310 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2311 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2313 result = ISC_R_UNEXPECTED;
2317 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2319 return (ISC_R_NOMEMORY);
2321 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2322 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2323 result = ISC_R_UNEXPECTED;
2327 totext_filter_proc = proc;
2328 return (ISC_R_SUCCESS);
2333 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2334 isc_result_t result;
2340 * Leave room for null termination after buffer.
2342 isc_buffer_init(&buf, cp, size - 1);
2343 result = dns_name_totext(name, ISC_TRUE, &buf);
2344 if (result == ISC_R_SUCCESS) {
2349 isc_buffer_usedregion(&buf, &r);
2350 ((char *) r.base)[r.length] = '\0';
2353 snprintf(cp, size, "<unknown>");
2357 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2361 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2362 isc_result_t result;
2365 char *p, txt[DNS_NAME_FORMATSIZE];
2367 REQUIRE(VALID_NAME(name));
2368 REQUIRE(target != NULL && *target == NULL);
2370 isc_buffer_init(&buf, txt, sizeof(txt));
2371 result = dns_name_totext(name, ISC_FALSE, &buf);
2372 if (result != ISC_R_SUCCESS)
2375 isc_buffer_usedregion(&buf, ®);
2376 p = isc_mem_allocate(mctx, reg.length + 1);
2377 memcpy(p, (char *) reg.base, (int) reg.length);
2378 p[reg.length] = '\0';
2381 return (ISC_R_SUCCESS);
2385 * dns_name_fromstring() -- convert directly from a string to a name,
2386 * allocating memory as needed
2389 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2392 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2396 dns_name_fromstring2(dns_name_t *target, const char *src,
2397 const dns_name_t *origin, unsigned int options,
2400 isc_result_t result;
2405 REQUIRE(src != NULL);
2407 isc_buffer_init(&buf, src, strlen(src));
2408 isc_buffer_add(&buf, strlen(src));
2409 if (BINDABLE(target) && target->buffer != NULL)
2412 dns_fixedname_init(&fn);
2413 name = dns_fixedname_name(&fn);
2416 result = dns_name_fromtext(name, &buf, origin, options, NULL);
2417 if (result != ISC_R_SUCCESS)
2421 result = dns_name_dupwithoffsets(name, mctx, target);
2426 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2427 unsigned char *ndata;
2430 * Make dest a copy of source.
2433 REQUIRE(VALID_NAME(source));
2434 REQUIRE(VALID_NAME(dest));
2435 REQUIRE(target != NULL || dest->buffer != NULL);
2437 if (target == NULL) {
2438 target = dest->buffer;
2439 isc_buffer_clear(dest->buffer);
2442 REQUIRE(BINDABLE(dest));
2447 if (target->length - target->used < source->length)
2448 return (ISC_R_NOSPACE);
2450 ndata = (unsigned char *)target->base + target->used;
2451 dest->ndata = target->base;
2453 memcpy(ndata, source->ndata, source->length);
2455 dest->ndata = ndata;
2456 dest->labels = source->labels;
2457 dest->length = source->length;
2458 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2459 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2461 dest->attributes = 0;
2463 if (dest->labels > 0 && dest->offsets != NULL) {
2464 if (source->offsets != NULL)
2465 memcpy(dest->offsets, source->offsets, source->labels);
2467 set_offsets(dest, dest->offsets, NULL);
2470 isc_buffer_add(target, dest->length);
2472 return (ISC_R_SUCCESS);
2476 dns_name_destroy(void) {
2477 #ifdef ISC_PLATFORM_USETHREADS
2478 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2481 LOCK(&thread_key_mutex);
2482 if (thread_key_initialized) {
2483 isc_mem_detach(&thread_key_mctx);
2484 isc_thread_key_delete(totext_filter_proc_key);
2485 thread_key_initialized = 0;
2487 UNLOCK(&thread_key_mutex);