2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.127.2.7.2.16 2006/03/02 00:37:20 marka Exp $ */
24 #include <isc/buffer.h>
27 #include <isc/print.h>
28 #include <isc/string.h>
31 #include <dns/compress.h>
33 #include <dns/result.h>
35 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
54 static char digitvalue[256] = {
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
58 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
59 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
61 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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, /*256*/
73 static unsigned char maptolower[] = {
74 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
76 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
77 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
78 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
79 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
80 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
81 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
82 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
83 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
84 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
85 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
86 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
87 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
88 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
89 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
90 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
91 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
92 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
93 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
94 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
95 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
96 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
97 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
98 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
99 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
100 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
101 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
102 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
103 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
104 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
105 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
108 #define CONVERTTOASCII(c)
109 #define CONVERTFROMASCII(c)
111 #define INIT_OFFSETS(name, var, default) \
112 if (name->offsets != NULL) \
113 var = name->offsets; \
117 #define SETUP_OFFSETS(name, var, default) \
118 if (name->offsets != NULL) \
119 var = name->offsets; \
122 set_offsets(name, var, NULL); \
126 * Note: If additional attributes are added that should not be set for
127 * empty names, MAKE_EMPTY() must be changed so it clears them.
129 #define MAKE_EMPTY(name) \
131 name->ndata = NULL; \
134 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
138 * A name is "bindable" if it can be set to point to a new value, i.e.
139 * name->ndata and name->length may be changed.
141 #define BINDABLE(name) \
142 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
146 * Note that the name data must be a char array, not a string
147 * literal, to avoid compiler warnings about discarding
148 * the const attribute of a string.
150 static unsigned char root_ndata[] = { '\0' };
151 static unsigned char root_offsets[] = { 0 };
153 static dns_name_t root =
157 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
159 {(void *)-1, (void *)-1},
163 /* XXXDCL make const? */
164 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
166 static unsigned char wild_ndata[] = { '\001', '*' };
167 static unsigned char wild_offsets[] = { 0 };
169 static dns_name_t wild =
173 DNS_NAMEATTR_READONLY,
175 {(void *)-1, (void *)-1},
179 /* XXXDCL make const? */
180 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
183 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
186 set_offsets(const dns_name_t *name, unsigned char *offsets,
187 dns_name_t *set_name);
190 dns_name_init(dns_name_t *name, unsigned char *offsets) {
194 DNS_NAME_INIT(name, offsets);
198 dns_name_reset(dns_name_t *name) {
199 REQUIRE(VALID_NAME(name));
200 REQUIRE(BINDABLE(name));
202 DNS_NAME_RESET(name);
206 dns_name_invalidate(dns_name_t *name) {
208 * Make 'name' invalid.
211 REQUIRE(VALID_NAME(name));
217 name->attributes = 0;
218 name->offsets = NULL;
220 ISC_LINK_INIT(name, link);
224 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
226 * Dedicate a buffer for use with 'name'.
229 REQUIRE(VALID_NAME(name));
230 REQUIRE((buffer != NULL && name->buffer == NULL) ||
233 name->buffer = buffer;
237 dns_name_hasbuffer(const dns_name_t *name) {
239 * Does 'name' have a dedicated buffer?
242 REQUIRE(VALID_NAME(name));
244 if (name->buffer != NULL)
251 dns_name_isabsolute(const dns_name_t *name) {
254 * Does 'name' end in the root label?
257 REQUIRE(VALID_NAME(name));
259 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
264 #define hyphenchar(c) ((c) == 0x2d)
265 #define asterchar(c) ((c) == 0x2a)
266 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
267 || ((c) >= 0x61 && (c) <= 0x7a))
268 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
269 #define borderchar(c) (alphachar(c) || digitchar(c))
270 #define middlechar(c) (borderchar(c) || hyphenchar(c))
271 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
274 dns_name_ismailbox(const dns_name_t *name) {
275 unsigned char *ndata, ch;
279 REQUIRE(VALID_NAME(name));
280 REQUIRE(name->labels > 0);
281 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
286 if (name->length == 1)
298 if (ndata == name->ndata + name->length)
302 * RFC292/RFC1123 hostname.
304 while (ndata < (name->ndata + name->length)) {
310 if (first || n == 0) {
324 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
325 unsigned char *ndata, ch;
329 REQUIRE(VALID_NAME(name));
330 REQUIRE(name->labels > 0);
331 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
336 if (name->length == 1)
340 * Skip wildcard if this is a ownername.
343 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
347 * RFC292/RFC1123 hostname.
349 while (ndata < (name->ndata + name->length)) {
355 if (first || n == 0) {
369 dns_name_iswildcard(const dns_name_t *name) {
370 unsigned char *ndata;
373 * Is 'name' a wildcard name?
376 REQUIRE(VALID_NAME(name));
377 REQUIRE(name->labels > 0);
379 if (name->length >= 2) {
381 if (ndata[0] == 1 && ndata[1] == '*')
388 static inline unsigned int
389 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
391 const unsigned char *s;
395 length = name->length;
400 * This hash function is similar to the one Ousterhout
404 if (case_sensitive) {
406 h += ( h << 3 ) + *s;
423 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
425 * Provide a hash value for 'name'.
427 REQUIRE(VALID_NAME(name));
429 if (name->labels == 0)
432 return (name_hash(name, case_sensitive));
436 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
438 * Provide a hash value for 'name'.
440 REQUIRE(VALID_NAME(name));
442 if (name->labels == 0)
445 return (isc_hash_calc((const unsigned char *)name->ndata,
446 name->length, case_sensitive));
450 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
452 * This function was deprecated due to the breakage of the name space
453 * convention. We only keep this internally to provide binary backward
456 REQUIRE(VALID_NAME(name));
458 return (dns_name_fullhash(name, case_sensitive));
462 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
463 unsigned char *offsets;
470 * Provide a hash value for 'name'.
472 REQUIRE(VALID_NAME(name));
474 if (name->labels == 0)
476 else if (name->labels == 1)
477 return (name_hash(name, case_sensitive));
479 SETUP_OFFSETS(name, offsets, odata);
480 DNS_NAME_INIT(&tname, NULL);
483 for (i = 0; i < name->labels; i++) {
484 tname.ndata = name->ndata + offsets[i];
485 if (i == name->labels - 1)
486 tname.length = name->length - offsets[i];
488 tname.length = offsets[i + 1] - offsets[i];
489 h += name_hash(&tname, case_sensitive);
496 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
497 int *orderp, unsigned int *nlabelsp)
499 unsigned int l1, l2, l, count1, count2, count, nlabels;
500 int cdiff, ldiff, chdiff;
501 unsigned char *label1, *label2;
502 unsigned char *offsets1, *offsets2;
503 dns_offsets_t odata1, odata2;
504 dns_namereln_t namereln = dns_namereln_none;
507 * Determine the relative ordering under the DNSSEC order relation of
508 * 'name1' and 'name2', and also determine the hierarchical
509 * relationship of the names.
511 * Note: It makes no sense for one of the names to be relative and the
512 * other absolute. If both names are relative, then to be meaningfully
513 * compared the caller must ensure that they are both relative to the
517 REQUIRE(VALID_NAME(name1));
518 REQUIRE(VALID_NAME(name2));
519 REQUIRE(orderp != NULL);
520 REQUIRE(nlabelsp != NULL);
522 * Either name1 is absolute and name2 is absolute, or neither is.
524 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
525 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
527 SETUP_OFFSETS(name1, offsets1, odata1);
528 SETUP_OFFSETS(name2, offsets2, odata2);
533 ldiff = (int)l1 - (int)l2;
543 label1 = &name1->ndata[offsets1[l1]];
544 label2 = &name2->ndata[offsets2[l2]];
549 * We dropped bitstring labels, and we don't support any
550 * other extended label types.
552 INSIST(count1 <= 63 && count2 <= 63);
554 cdiff = (int)count1 - (int)count2;
561 chdiff = (int)maptolower[*label1] -
562 (int)maptolower[*label2];
580 namereln = dns_namereln_contains;
582 namereln = dns_namereln_subdomain;
584 namereln = dns_namereln_equal;
589 if (nlabels > 0 && namereln == dns_namereln_none)
590 namereln = dns_namereln_commonancestor;
596 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
598 unsigned int nlabels;
601 * Determine the relative ordering under the DNSSEC order relation of
602 * 'name1' and 'name2'.
604 * Note: It makes no sense for one of the names to be relative and the
605 * other absolute. If both names are relative, then to be meaningfully
606 * compared the caller must ensure that they are both relative to the
610 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
616 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
617 unsigned int l, count;
619 unsigned char *label1, *label2;
622 * Are 'name1' and 'name2' equal?
624 * Note: It makes no sense for one of the names to be relative and the
625 * other absolute. If both names are relative, then to be meaningfully
626 * compared the caller must ensure that they are both relative to the
630 REQUIRE(VALID_NAME(name1));
631 REQUIRE(VALID_NAME(name2));
633 * Either name1 is absolute and name2 is absolute, or neither is.
635 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
636 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
638 if (name1->length != name2->length)
643 if (l != name2->labels)
646 label1 = name1->ndata;
647 label2 = name2->ndata;
651 if (count != *label2++)
654 INSIST(count <= 63); /* no bitstring support */
658 c = maptolower[*label1++];
659 if (c != maptolower[*label2++])
668 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
669 unsigned int l1, l2, l, count1, count2, count;
670 unsigned char c1, c2;
671 unsigned char *label1, *label2;
674 * Compare two absolute names as rdata.
677 REQUIRE(VALID_NAME(name1));
678 REQUIRE(name1->labels > 0);
679 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
680 REQUIRE(VALID_NAME(name2));
681 REQUIRE(name2->labels > 0);
682 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
687 l = (l1 < l2) ? l1 : l2;
689 label1 = name1->ndata;
690 label2 = name2->ndata;
696 /* no bitstring support */
697 INSIST(count1 <= 63 && count2 <= 63);
699 if (count1 != count2)
700 return ((count1 < count2) ? -1 : 1);
704 c1 = maptolower[*label1++];
705 c2 = maptolower[*label2++];
714 * If one name had more labels than the other, their common
715 * prefix must have been different because the shorter name
716 * ended with the root label and the longer one can't have
717 * a root label in the middle of it. Therefore, if we get
718 * to this point, the lengths must be equal.
726 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
728 unsigned int nlabels;
729 dns_namereln_t namereln;
732 * Is 'name1' a subdomain of 'name2'?
734 * Note: It makes no sense for one of the names to be relative and the
735 * other absolute. If both names are relative, then to be meaningfully
736 * compared the caller must ensure that they are both relative to the
740 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
741 if (namereln == dns_namereln_subdomain ||
742 namereln == dns_namereln_equal)
749 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
751 unsigned int nlabels, labels;
754 REQUIRE(VALID_NAME(name));
755 REQUIRE(name->labels > 0);
756 REQUIRE(VALID_NAME(wname));
757 labels = wname->labels;
759 REQUIRE(dns_name_iswildcard(wname));
761 DNS_NAME_INIT(&tname, NULL);
762 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
763 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
764 dns_namereln_subdomain)
770 dns_name_countlabels(const dns_name_t *name) {
772 * How many labels does 'name' have?
775 REQUIRE(VALID_NAME(name));
777 ENSURE(name->labels <= 128);
779 return (name->labels);
783 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
784 unsigned char *offsets;
788 * Make 'label' refer to the 'n'th least significant label of 'name'.
791 REQUIRE(VALID_NAME(name));
792 REQUIRE(name->labels > 0);
793 REQUIRE(n < name->labels);
794 REQUIRE(label != NULL);
796 SETUP_OFFSETS(name, offsets, odata);
798 label->base = &name->ndata[offsets[n]];
799 if (n == name->labels - 1)
800 label->length = name->length - offsets[n];
802 label->length = offsets[n + 1] - offsets[n];
806 dns_name_getlabelsequence(const dns_name_t *source,
807 unsigned int first, unsigned int n,
810 unsigned char *offsets;
812 unsigned int firstoffset, endoffset;
815 * Make 'target' refer to the 'n' labels including and following
816 * 'first' in 'source'.
819 REQUIRE(VALID_NAME(source));
820 REQUIRE(VALID_NAME(target));
821 REQUIRE(first <= source->labels);
822 REQUIRE(first + n <= source->labels);
823 REQUIRE(BINDABLE(target));
825 SETUP_OFFSETS(source, offsets, odata);
827 if (first == source->labels)
828 firstoffset = source->length;
830 firstoffset = offsets[first];
832 if (first + n == source->labels)
833 endoffset = source->length;
835 endoffset = offsets[first + n];
837 target->ndata = &source->ndata[firstoffset];
838 target->length = endoffset - firstoffset;
840 if (first + n == source->labels && n > 0 &&
841 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
842 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
844 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
849 * If source and target are the same, and we're making target
850 * a prefix of source, the offsets table is correct already
851 * so we don't need to call set_offsets().
853 if (target->offsets != NULL &&
854 (target != source || first != 0))
855 set_offsets(target, target->offsets, NULL);
859 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
862 * Make 'target' refer to the same name as 'source'.
865 REQUIRE(VALID_NAME(source));
866 REQUIRE(VALID_NAME(target));
867 REQUIRE(BINDABLE(target));
869 target->ndata = source->ndata;
870 target->length = source->length;
871 target->labels = source->labels;
872 target->attributes = source->attributes &
873 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
874 DNS_NAMEATTR_DYNOFFSETS);
875 if (target->offsets != NULL && source->labels > 0) {
876 if (source->offsets != NULL)
877 memcpy(target->offsets, source->offsets,
880 set_offsets(target, target->offsets, NULL);
885 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
886 unsigned char *offsets;
892 * Make 'name' refer to region 'r'.
895 REQUIRE(VALID_NAME(name));
897 REQUIRE(BINDABLE(name));
899 INIT_OFFSETS(name, offsets, odata);
901 if (name->buffer != NULL) {
902 isc_buffer_clear(name->buffer);
903 isc_buffer_availableregion(name->buffer, &r2);
904 len = (r->length < r2.length) ? r->length : r2.length;
905 if (len > DNS_NAME_MAXWIRE)
906 len = DNS_NAME_MAXWIRE;
907 memcpy(r2.base, r->base, len);
908 name->ndata = r2.base;
911 name->ndata = r->base;
912 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
913 r->length : DNS_NAME_MAXWIRE;
917 set_offsets(name, offsets, name);
920 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
923 if (name->buffer != NULL)
924 isc_buffer_add(name->buffer, name->length);
928 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
930 * Make 'r' refer to 'name'.
933 REQUIRE(VALID_NAME(name));
936 DNS_NAME_TOREGION(name, r);
941 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
942 dns_name_t *origin, unsigned int options,
943 isc_buffer_t *target)
945 unsigned char *ndata, *label;
949 unsigned int value, count;
950 unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
952 unsigned char *offsets;
954 isc_boolean_t downcase;
957 * Convert the textual representation of a DNS name at source
958 * into uncompressed wire form stored in target.
961 * Relative domain names will have 'origin' appended to them
962 * unless 'origin' is NULL, in which case relative domain names
963 * will remain relative.
966 REQUIRE(VALID_NAME(name));
967 REQUIRE(ISC_BUFFER_VALID(source));
968 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
969 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
971 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
973 if (target == NULL && name->buffer != NULL) {
974 target = name->buffer;
975 isc_buffer_clear(target);
978 REQUIRE(BINDABLE(name));
980 INIT_OFFSETS(name, offsets, odata);
984 * Initialize things to make the compiler happy; they're not required.
994 * Make 'name' empty in case of failure.
999 * Set up the state machine.
1001 tdata = (char *)source->base + source->current;
1002 tlen = isc_buffer_remaininglength(source);
1004 ndata = isc_buffer_used(target);
1005 nrem = isc_buffer_availablelength(target);
1013 while (nrem > 0 && tlen > 0 && !done) {
1021 * Is this the root name?
1025 return (DNS_R_EMPTYLABEL);
1033 if (c == '@' && tlen == 0) {
1046 state = ft_initialescape;
1049 state = ft_ordinary;
1051 return (ISC_R_NOSPACE);
1056 return (DNS_R_EMPTYLABEL);
1059 INSIST(labels <= 127);
1060 offsets[labels] = nused;
1069 } else if (c == '\\') {
1073 return (DNS_R_LABELTOOLONG);
1077 c = maptolower[(int)c];
1083 case ft_initialescape:
1086 * This looks like a bitstring label, which
1087 * was deprecated. Intentionally drop it.
1089 return (DNS_R_BADLABELTYPE);
1094 if (!isdigit(c & 0xff)) {
1096 return (DNS_R_LABELTOOLONG);
1100 c = maptolower[(int)c];
1104 state = ft_ordinary;
1109 state = ft_escdecimal;
1112 if (!isdigit(c & 0xff))
1113 return (DNS_R_BADESCAPE);
1115 value += digitvalue[(int)c];
1119 return (DNS_R_BADESCAPE);
1121 return (DNS_R_LABELTOOLONG);
1124 value = maptolower[value];
1128 state = ft_ordinary;
1132 FATAL_ERROR(__FILE__, __LINE__,
1133 "Unexpected state %d", state);
1134 /* Does not return. */
1140 return (ISC_R_NOSPACE);
1142 if (state != ft_ordinary && state != ft_at)
1143 return (ISC_R_UNEXPECTEDEND);
1144 if (state == ft_ordinary) {
1148 INSIST(labels <= 127);
1149 offsets[labels] = nused;
1151 if (origin != NULL) {
1152 if (nrem < origin->length)
1153 return (ISC_R_NOSPACE);
1154 label = origin->ndata;
1155 n1 = origin->length;
1159 INSIST(n2 <= 63); /* no bitstring support */
1166 c = maptolower[(int)c];
1172 INSIST(labels <= 127);
1173 offsets[labels] = nused;
1176 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1177 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1180 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1182 name->ndata = (unsigned char *)target->base + target->used;
1183 name->labels = labels;
1184 name->length = nused;
1186 isc_buffer_forward(source, tused);
1187 isc_buffer_add(target, name->length);
1189 return (ISC_R_SUCCESS);
1193 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1194 isc_buffer_t *target)
1196 unsigned char *ndata;
1198 unsigned int nlen, tlen;
1200 unsigned int trem, count;
1201 unsigned int labels;
1202 isc_boolean_t saw_root = ISC_FALSE;
1205 * This function assumes the name is in proper uncompressed
1208 REQUIRE(VALID_NAME(name));
1209 REQUIRE(ISC_BUFFER_VALID(target));
1211 ndata = name->ndata;
1212 nlen = name->length;
1213 labels = name->labels;
1214 tdata = isc_buffer_used(target);
1215 tlen = isc_buffer_availablelength(target);
1219 if (labels == 0 && nlen == 0) {
1221 * Special handling for an empty name.
1224 return (ISC_R_NOSPACE);
1227 * The names of these booleans are misleading in this case.
1228 * This empty name is not necessarily from the root node of
1229 * the DNS root zone, nor is a final dot going to be included.
1230 * They need to be set this way, though, to keep the "@"
1231 * from being trounced.
1233 saw_root = ISC_TRUE;
1234 omit_final_dot = ISC_FALSE;
1239 * Skip the while() loop.
1242 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1244 * Special handling for the root label.
1247 return (ISC_R_NOSPACE);
1249 saw_root = ISC_TRUE;
1250 omit_final_dot = ISC_FALSE;
1255 * Skip the while() loop.
1260 while (labels > 0 && nlen > 0 && trem > 0) {
1265 saw_root = ISC_TRUE;
1269 INSIST(nlen >= count);
1273 case 0x22: /* '"' */
1274 case 0x28: /* '(' */
1275 case 0x29: /* ')' */
1276 case 0x2E: /* '.' */
1277 case 0x3B: /* ';' */
1278 case 0x5C: /* '\\' */
1279 /* Special modifiers in zone files. */
1280 case 0x40: /* '@' */
1281 case 0x24: /* '$' */
1283 return (ISC_R_NOSPACE);
1285 CONVERTFROMASCII(c);
1292 if (c > 0x20 && c < 0x7f) {
1294 return (ISC_R_NOSPACE);
1295 CONVERTFROMASCII(c);
1302 return (ISC_R_NOSPACE);
1308 *tdata++ = 0x30 + (c % 10);
1317 FATAL_ERROR(__FILE__, __LINE__,
1318 "Unexpected label type %02x", count);
1323 * The following assumes names are absolute. If not, we
1324 * fix things up later. Note that this means that in some
1325 * cases one more byte of text buffer is required than is
1326 * needed in the final output.
1329 return (ISC_R_NOSPACE);
1334 if (nlen != 0 && trem == 0)
1335 return (ISC_R_NOSPACE);
1337 if (!saw_root || omit_final_dot)
1340 isc_buffer_add(target, tlen - trem);
1342 return (ISC_R_SUCCESS);
1346 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1347 isc_buffer_t *target)
1349 unsigned char *ndata;
1351 unsigned int nlen, tlen;
1353 unsigned int trem, count;
1354 unsigned int labels;
1357 * This function assumes the name is in proper uncompressed
1360 REQUIRE(VALID_NAME(name));
1361 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1362 REQUIRE(ISC_BUFFER_VALID(target));
1364 ndata = name->ndata;
1365 nlen = name->length;
1366 labels = name->labels;
1367 tdata = isc_buffer_used(target);
1368 tlen = isc_buffer_availablelength(target);
1372 if (nlen == 1 && labels == 1 && *ndata == '\0') {
1374 * Special handling for the root label.
1377 return (ISC_R_NOSPACE);
1379 omit_final_dot = ISC_FALSE;
1384 * Skip the while() loop.
1389 while (labels > 0 && nlen > 0 && trem > 0) {
1396 INSIST(nlen >= count);
1399 if ((c >= 0x30 && c <= 0x39) || /* digit */
1400 (c >= 0x41 && c <= 0x5A) || /* uppercase */
1401 (c >= 0x61 && c <= 0x7A) || /* lowercase */
1402 c == 0x2D || /* hyphen */
1403 c == 0x5F) /* underscore */
1406 return (ISC_R_NOSPACE);
1408 if (c >= 0x41 && c <= 0x5A)
1410 CONVERTFROMASCII(c);
1417 return (ISC_R_NOSPACE);
1418 sprintf(tdata, "%%%02X", c);
1427 FATAL_ERROR(__FILE__, __LINE__,
1428 "Unexpected label type %02x", count);
1433 * The following assumes names are absolute. If not, we
1434 * fix things up later. Note that this means that in some
1435 * cases one more byte of text buffer is required than is
1436 * needed in the final output.
1439 return (ISC_R_NOSPACE);
1444 if (nlen != 0 && trem == 0)
1445 return (ISC_R_NOSPACE);
1450 isc_buffer_add(target, tlen - trem);
1452 return (ISC_R_SUCCESS);
1456 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1457 unsigned char *sndata, *ndata;
1458 unsigned int nlen, count, labels;
1459 isc_buffer_t buffer;
1462 * Downcase 'source'.
1465 REQUIRE(VALID_NAME(source));
1466 REQUIRE(VALID_NAME(name));
1467 if (source == name) {
1468 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1469 isc_buffer_init(&buffer, source->ndata, source->length);
1471 ndata = source->ndata;
1473 REQUIRE(BINDABLE(name));
1474 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1475 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1476 if (target == NULL) {
1477 target = name->buffer;
1478 isc_buffer_clear(name->buffer);
1480 ndata = (unsigned char *)target->base + target->used;
1481 name->ndata = ndata;
1484 sndata = source->ndata;
1485 nlen = source->length;
1486 labels = source->labels;
1488 if (nlen > (target->length - target->used)) {
1490 return (ISC_R_NOSPACE);
1493 while (labels > 0 && nlen > 0) {
1499 INSIST(nlen >= count);
1501 *ndata++ = maptolower[(*sndata++)];
1506 FATAL_ERROR(__FILE__, __LINE__,
1507 "Unexpected label type %02x", count);
1508 /* Does not return. */
1512 if (source != name) {
1513 name->labels = source->labels;
1514 name->length = source->length;
1515 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1516 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1518 name->attributes = 0;
1519 if (name->labels > 0 && name->offsets != NULL)
1520 set_offsets(name, name->offsets, NULL);
1523 isc_buffer_add(target, name->length);
1525 return (ISC_R_SUCCESS);
1529 set_offsets(const dns_name_t *name, unsigned char *offsets,
1530 dns_name_t *set_name)
1532 unsigned int offset, count, length, nlabels;
1533 unsigned char *ndata;
1534 isc_boolean_t absolute;
1536 ndata = name->ndata;
1537 length = name->length;
1540 absolute = ISC_FALSE;
1541 while (offset != length) {
1542 INSIST(nlabels < 128);
1543 offsets[nlabels++] = offset;
1546 INSIST(count <= 63);
1549 INSIST(offset <= length);
1551 absolute = ISC_TRUE;
1555 if (set_name != NULL) {
1556 INSIST(set_name == name);
1558 set_name->labels = nlabels;
1559 set_name->length = offset;
1561 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1563 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1565 INSIST(nlabels == name->labels);
1566 INSIST(offset == name->length);
1570 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1571 dns_decompress_t *dctx, unsigned int options,
1572 isc_buffer_t *target)
1574 unsigned char *cdata, *ndata;
1575 unsigned int cused; /* Bytes of compressed name data used */
1576 unsigned int hops, nused, labels, n, nmax;
1577 unsigned int current, new_current, biggest_pointer;
1579 fw_state state = fw_start;
1581 unsigned char *offsets;
1582 dns_offsets_t odata;
1583 isc_boolean_t downcase;
1586 * Copy the possibly-compressed name at source into target,
1590 REQUIRE(VALID_NAME(name));
1591 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1592 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1594 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1596 if (target == NULL && name->buffer != NULL) {
1597 target = name->buffer;
1598 isc_buffer_clear(target);
1601 REQUIRE(dctx != NULL);
1602 REQUIRE(BINDABLE(name));
1604 INIT_OFFSETS(name, offsets, odata);
1607 * Make 'name' empty in case of failure.
1612 * Initialize things to make the compiler happy; they're not required.
1624 ndata = isc_buffer_used(target);
1628 * Find the maximum number of uncompressed target name
1629 * bytes we are willing to generate. This is the smaller
1630 * of the available target buffer length and the
1631 * maximum legal domain name length (255).
1633 nmax = isc_buffer_availablelength(target);
1634 if (nmax > DNS_NAME_MAXWIRE)
1635 nmax = DNS_NAME_MAXWIRE;
1637 cdata = isc_buffer_current(source);
1640 current = source->current;
1641 biggest_pointer = current;
1644 * Note: The following code is not optimized for speed, but
1645 * rather for correctness. Speed will be addressed in the future.
1648 while (current < source->active && !done) {
1657 offsets[labels] = nused;
1659 if (nused + c + 1 > nmax)
1666 state = fw_ordinary;
1667 } else if (c >= 128 && c < 192) {
1669 * 14 bit local compression pointer.
1670 * Local compression is no longer an
1673 return (DNS_R_BADLABELTYPE);
1674 } else if (c >= 192) {
1676 * Ordinary 14-bit pointer.
1678 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1680 return (DNS_R_DISALLOWED);
1681 new_current = c & 0x3F;
1683 state = fw_newcurrent;
1685 return (DNS_R_BADLABELTYPE);
1703 if (new_current >= biggest_pointer)
1704 return (DNS_R_BADPOINTER);
1705 biggest_pointer = new_current;
1706 current = new_current;
1707 cdata = (unsigned char *)source->base +
1710 if (hops > DNS_POINTER_MAXHOPS)
1711 return (DNS_R_TOOMANYHOPS);
1715 FATAL_ERROR(__FILE__, __LINE__,
1716 "Unknown state %d", state);
1717 /* Does not return. */
1722 return (ISC_R_UNEXPECTEDEND);
1724 name->ndata = (unsigned char *)target->base + target->used;
1725 name->labels = labels;
1726 name->length = nused;
1727 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1729 isc_buffer_forward(source, cused);
1730 isc_buffer_add(target, name->length);
1732 return (ISC_R_SUCCESS);
1735 if (nmax == DNS_NAME_MAXWIRE)
1737 * The name did not fit even though we had a buffer
1738 * big enough to fit a maximum-length name.
1740 return (DNS_R_NAMETOOLONG);
1743 * The name might fit if only the caller could give us a
1744 * big enough buffer.
1746 return (ISC_R_NOSPACE);
1751 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1752 isc_buffer_t *target)
1754 unsigned int methods;
1755 isc_uint16_t offset;
1756 dns_name_t gp; /* Global compression prefix */
1757 isc_boolean_t gf; /* Global compression target found */
1758 isc_uint16_t go; /* Global compression offset */
1763 * Convert 'name' into wire format, compressing it as specified by the
1764 * compression context 'cctx', and storing the result in 'target'.
1767 REQUIRE(VALID_NAME(name));
1768 REQUIRE(cctx != NULL);
1769 REQUIRE(ISC_BUFFER_VALID(target));
1772 * If 'name' doesn't have an offsets table, make a clone which
1775 if (name->offsets == NULL) {
1776 DNS_NAME_INIT(&clname, clo);
1777 dns_name_clone(name, &clname);
1780 DNS_NAME_INIT(&gp, NULL);
1782 offset = target->used; /*XXX*/
1784 methods = dns_compress_getmethods(cctx);
1786 if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
1787 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1792 * If the offset is too high for 14 bit global compression, we're
1795 if (gf && go >= 0x4000)
1799 * Will the compression pointer reduce the message size?
1801 if (gf && (gp.length + 2) >= name->length)
1805 if (target->length - target->used < gp.length)
1806 return (ISC_R_NOSPACE);
1807 (void)memcpy((unsigned char *)target->base + target->used,
1808 gp.ndata, (size_t)gp.length);
1809 isc_buffer_add(target, gp.length);
1811 if (target->length - target->used < 2)
1812 return (ISC_R_NOSPACE);
1813 isc_buffer_putuint16(target, go);
1815 dns_compress_add(cctx, name, &gp, offset);
1817 if (target->length - target->used < name->length)
1818 return (ISC_R_NOSPACE);
1819 (void)memcpy((unsigned char *)target->base + target->used,
1820 name->ndata, (size_t)name->length);
1821 isc_buffer_add(target, name->length);
1822 dns_compress_add(cctx, name, name, offset);
1824 return (ISC_R_SUCCESS);
1828 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1829 isc_buffer_t *target)
1831 unsigned char *ndata, *offsets;
1832 unsigned int nrem, labels, prefix_length, length;
1833 isc_boolean_t copy_prefix = ISC_TRUE;
1834 isc_boolean_t copy_suffix = ISC_TRUE;
1835 isc_boolean_t absolute = ISC_FALSE;
1836 dns_name_t tmp_name;
1837 dns_offsets_t odata;
1840 * Concatenate 'prefix' and 'suffix'.
1843 REQUIRE(prefix == NULL || VALID_NAME(prefix));
1844 REQUIRE(suffix == NULL || VALID_NAME(suffix));
1845 REQUIRE(name == NULL || VALID_NAME(name));
1846 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1847 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1848 if (prefix == NULL || prefix->labels == 0)
1849 copy_prefix = ISC_FALSE;
1850 if (suffix == NULL || suffix->labels == 0)
1851 copy_suffix = ISC_FALSE;
1853 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1854 absolute = ISC_TRUE;
1855 REQUIRE(!copy_suffix);
1858 DNS_NAME_INIT(&tmp_name, odata);
1861 if (target == NULL) {
1862 INSIST(name->buffer != NULL);
1863 target = name->buffer;
1864 isc_buffer_clear(name->buffer);
1867 REQUIRE(BINDABLE(name));
1872 nrem = target->length - target->used;
1873 ndata = (unsigned char *)target->base + target->used;
1874 if (nrem > DNS_NAME_MAXWIRE)
1875 nrem = DNS_NAME_MAXWIRE;
1880 prefix_length = prefix->length;
1881 length += prefix_length;
1882 labels += prefix->labels;
1885 length += suffix->length;
1886 labels += suffix->labels;
1888 if (length > DNS_NAME_MAXWIRE) {
1890 return (DNS_R_NAMETOOLONG);
1892 if (length > nrem) {
1894 return (ISC_R_NOSPACE);
1898 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1899 absolute = ISC_TRUE;
1900 if (suffix == name && suffix->buffer == target)
1901 memmove(ndata + prefix_length, suffix->ndata,
1904 memcpy(ndata + prefix_length, suffix->ndata,
1909 * If 'prefix' and 'name' are the same object, and the object has
1910 * a dedicated buffer, and we're using it, then we don't have to
1913 if (copy_prefix && (prefix != name || prefix->buffer != target))
1914 memcpy(ndata, prefix->ndata, prefix_length);
1916 name->ndata = ndata;
1917 name->labels = labels;
1918 name->length = length;
1920 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1922 name->attributes = 0;
1924 if (name->labels > 0 && name->offsets != NULL) {
1925 INIT_OFFSETS(name, offsets, odata);
1926 set_offsets(name, offsets, NULL);
1929 isc_buffer_add(target, name->length);
1931 return (ISC_R_SUCCESS);
1935 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
1936 dns_name_t *prefix, dns_name_t *suffix)
1939 unsigned int splitlabel;
1941 REQUIRE(VALID_NAME(name));
1942 REQUIRE(suffixlabels > 0);
1943 REQUIRE(suffixlabels < name->labels);
1944 REQUIRE(prefix != NULL || suffix != NULL);
1945 REQUIRE(prefix == NULL ||
1946 (VALID_NAME(prefix) &&
1947 prefix->buffer != NULL &&
1949 REQUIRE(suffix == NULL ||
1950 (VALID_NAME(suffix) &&
1951 suffix->buffer != NULL &&
1954 splitlabel = name->labels - suffixlabels;
1957 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
1960 dns_name_getlabelsequence(name, splitlabel,
1961 suffixlabels, suffix);
1967 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
1971 * Make 'target' a dynamically allocated copy of 'source'.
1974 REQUIRE(VALID_NAME(source));
1975 REQUIRE(source->length > 0);
1976 REQUIRE(VALID_NAME(target));
1977 REQUIRE(BINDABLE(target));
1980 * Make 'target' empty in case of failure.
1984 target->ndata = isc_mem_get(mctx, source->length);
1985 if (target->ndata == NULL)
1986 return (ISC_R_NOMEMORY);
1988 memcpy(target->ndata, source->ndata, source->length);
1990 target->length = source->length;
1991 target->labels = source->labels;
1992 target->attributes = DNS_NAMEATTR_DYNAMIC;
1993 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1994 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
1995 if (target->offsets != NULL) {
1996 if (source->offsets != NULL)
1997 memcpy(target->offsets, source->offsets,
2000 set_offsets(target, target->offsets, NULL);
2003 return (ISC_R_SUCCESS);
2007 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2011 * Make 'target' a read-only dynamically allocated copy of 'source'.
2012 * 'target' will also have a dynamically allocated offsets table.
2015 REQUIRE(VALID_NAME(source));
2016 REQUIRE(source->length > 0);
2017 REQUIRE(VALID_NAME(target));
2018 REQUIRE(BINDABLE(target));
2019 REQUIRE(target->offsets == NULL);
2022 * Make 'target' empty in case of failure.
2026 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2027 if (target->ndata == NULL)
2028 return (ISC_R_NOMEMORY);
2030 memcpy(target->ndata, source->ndata, source->length);
2032 target->length = source->length;
2033 target->labels = source->labels;
2034 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2035 DNS_NAMEATTR_READONLY;
2036 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2037 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2038 target->offsets = target->ndata + source->length;
2039 if (source->offsets != NULL)
2040 memcpy(target->offsets, source->offsets, source->labels);
2042 set_offsets(target, target->offsets, NULL);
2044 return (ISC_R_SUCCESS);
2048 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2055 REQUIRE(VALID_NAME(name));
2056 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2058 size = name->length;
2059 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2060 size += name->labels;
2061 isc_mem_put(mctx, name->ndata, size);
2062 dns_name_invalidate(name);
2066 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2067 dns_name_t downname;
2068 unsigned char data[256];
2069 isc_buffer_t buffer;
2070 isc_result_t result;
2074 * Send 'name' in DNSSEC canonical form to 'digest'.
2077 REQUIRE(VALID_NAME(name));
2078 REQUIRE(digest != NULL);
2080 DNS_NAME_INIT(&downname, NULL);
2081 isc_buffer_init(&buffer, data, sizeof(data));
2083 result = dns_name_downcase(name, &downname, &buffer);
2084 if (result != ISC_R_SUCCESS)
2087 isc_buffer_usedregion(&buffer, &r);
2089 return ((digest)(arg, &r));
2093 dns_name_dynamic(dns_name_t *name) {
2094 REQUIRE(VALID_NAME(name));
2097 * Returns whether there is dynamic memory associated with this name.
2100 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2101 ISC_TRUE : ISC_FALSE);
2105 dns_name_print(dns_name_t *name, FILE *stream) {
2106 isc_result_t result;
2112 * Print 'name' on 'stream'.
2115 REQUIRE(VALID_NAME(name));
2117 isc_buffer_init(&b, t, sizeof(t));
2118 result = dns_name_totext(name, ISC_FALSE, &b);
2119 if (result != ISC_R_SUCCESS)
2121 isc_buffer_usedregion(&b, &r);
2122 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2124 return (ISC_R_SUCCESS);
2128 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2129 isc_result_t result;
2135 * Leave room for null termination after buffer.
2137 isc_buffer_init(&buf, cp, size - 1);
2138 result = dns_name_totext(name, ISC_TRUE, &buf);
2139 if (result == ISC_R_SUCCESS) {
2144 isc_buffer_usedregion(&buf, &r);
2145 ((char *) r.base)[r.length] = '\0';
2148 snprintf(cp, size, "<unknown>");
2152 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2153 unsigned char *ndata;
2156 * Make dest a copy of source.
2159 REQUIRE(VALID_NAME(source));
2160 REQUIRE(VALID_NAME(dest));
2161 REQUIRE(target != NULL || dest->buffer != NULL);
2163 if (target == NULL) {
2164 target = dest->buffer;
2165 isc_buffer_clear(dest->buffer);
2168 REQUIRE(BINDABLE(dest));
2173 if (target->length - target->used < source->length)
2174 return (ISC_R_NOSPACE);
2176 ndata = (unsigned char *)target->base + target->used;
2177 dest->ndata = target->base;
2179 memcpy(ndata, source->ndata, source->length);
2181 dest->ndata = ndata;
2182 dest->labels = source->labels;
2183 dest->length = source->length;
2184 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2185 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2187 dest->attributes = 0;
2189 if (dest->labels > 0 && dest->offsets != NULL) {
2190 if (source->offsets != NULL)
2191 memcpy(dest->offsets, source->offsets, source->labels);
2193 set_offsets(dest, dest->offsets, NULL);
2196 isc_buffer_add(target, dest->length);
2198 return (ISC_R_SUCCESS);