1 /* $NetBSD: name.c,v 1.11 2015/07/08 17:28:58 christos Exp $ */
4 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
29 #include <isc/buffer.h>
33 #include <isc/print.h>
34 #include <isc/string.h>
35 #include <isc/thread.h>
38 #include <dns/compress.h>
39 #include <dns/fixedname.h>
41 #include <dns/result.h>
43 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
61 static char digitvalue
[256] = {
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
65 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
66 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
68 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
69 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
77 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
80 static unsigned char maptolower
[] = {
81 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
82 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
83 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
84 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
85 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
86 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
87 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
88 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
89 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
90 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
91 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
92 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
93 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
94 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
95 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
96 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
97 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
98 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
99 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
100 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
101 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
102 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
103 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
104 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
105 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
106 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
107 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
108 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
109 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
110 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
111 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
112 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
115 #define CONVERTTOASCII(c)
116 #define CONVERTFROMASCII(c)
118 #define INIT_OFFSETS(name, var, default) \
119 if (name->offsets != NULL) \
120 var = name->offsets; \
124 #define SETUP_OFFSETS(name, var, default) \
125 if (name->offsets != NULL) \
126 var = name->offsets; \
129 set_offsets(name, var, NULL); \
133 * Note: If additional attributes are added that should not be set for
134 * empty names, MAKE_EMPTY() must be changed so it clears them.
136 #define MAKE_EMPTY(name) \
138 name->ndata = NULL; \
141 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
142 } while (/*CONSTCOND*/0);
145 * A name is "bindable" if it can be set to point to a new value, i.e.
146 * name->ndata and name->length may be changed.
148 #define BINDABLE(name) \
149 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
153 * Note that the name data must be a char array, not a string
154 * literal, to avoid compiler warnings about discarding
155 * the const attribute of a string.
157 static unsigned char root_ndata
[] = { '\0' };
158 static unsigned char root_offsets
[] = { 0 };
160 static dns_name_t root
=
164 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
166 {(void *)-1, (void *)-1},
170 /* XXXDCL make const? */
171 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_rootname
= &root
;
173 static unsigned char wild_ndata
[] = { '\001', '*' };
174 static unsigned char wild_offsets
[] = { 0 };
176 static dns_name_t wild
=
180 DNS_NAMEATTR_READONLY
,
182 {(void *)-1, (void *)-1},
186 /* XXXDCL make const? */
187 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_wildcardname
= &wild
;
190 dns_fullname_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
);
193 * dns_name_t to text post-conversion procedure.
195 #ifdef ISC_PLATFORM_USETHREADS
196 static int thread_key_initialized
= 0;
197 static isc_mutex_t thread_key_mutex
;
198 static isc_mem_t
*thread_key_mctx
= NULL
;
199 static isc_thread_key_t totext_filter_proc_key
;
200 static isc_once_t once
= ISC_ONCE_INIT
;
202 static dns_name_totextfilter_t totext_filter_proc
= NULL
;
206 set_offsets(const dns_name_t
*name
, unsigned char *offsets
,
207 dns_name_t
*set_name
);
210 dns_name_init(dns_name_t
*name
, unsigned char *offsets
) {
214 DNS_NAME_INIT(name
, offsets
);
218 dns_name_reset(dns_name_t
*name
) {
219 REQUIRE(VALID_NAME(name
));
220 REQUIRE(BINDABLE(name
));
222 DNS_NAME_RESET(name
);
226 dns_name_invalidate(dns_name_t
*name
) {
228 * Make 'name' invalid.
231 REQUIRE(VALID_NAME(name
));
237 name
->attributes
= 0;
238 name
->offsets
= NULL
;
240 ISC_LINK_INIT(name
, link
);
244 dns_name_isvalid(const dns_name_t
*name
) {
245 unsigned char *ndata
, *offsets
;
246 unsigned int offset
, count
, length
, nlabels
;
248 if (!VALID_NAME(name
))
251 if (name
->length
> 255U || name
->labels
> 127U)
255 length
= name
->length
;
256 offsets
= name
->offsets
;
260 while (offset
!= length
) {
264 if (offsets
!= NULL
&& offsets
[nlabels
] != offset
)
277 if (nlabels
!= name
->labels
|| offset
!= name
->length
)
284 dns_name_setbuffer(dns_name_t
*name
, isc_buffer_t
*buffer
) {
286 * Dedicate a buffer for use with 'name'.
289 REQUIRE(VALID_NAME(name
));
290 REQUIRE((buffer
!= NULL
&& name
->buffer
== NULL
) ||
293 name
->buffer
= buffer
;
297 dns_name_hasbuffer(const dns_name_t
*name
) {
299 * Does 'name' have a dedicated buffer?
302 REQUIRE(VALID_NAME(name
));
304 if (name
->buffer
!= NULL
)
311 dns_name_isabsolute(const dns_name_t
*name
) {
314 * Does 'name' end in the root label?
317 REQUIRE(VALID_NAME(name
));
319 if ((name
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
324 #define hyphenchar(c) ((c) == 0x2d)
325 #define asterchar(c) ((c) == 0x2a)
326 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
327 || ((c) >= 0x61 && (c) <= 0x7a))
328 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
329 #define borderchar(c) (alphachar(c) || digitchar(c))
330 #define middlechar(c) (borderchar(c) || hyphenchar(c))
331 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
334 dns_name_ismailbox(const dns_name_t
*name
) {
335 unsigned char *ndata
, ch
;
339 REQUIRE(VALID_NAME(name
));
340 REQUIRE(name
->labels
> 0);
341 REQUIRE(name
->attributes
& DNS_NAMEATTR_ABSOLUTE
);
346 if (name
->length
== 1)
358 if (ndata
== name
->ndata
+ name
->length
)
362 * RFC952/RFC1123 hostname.
364 while (ndata
< (name
->ndata
+ name
->length
)) {
370 if (first
|| n
== 0) {
384 dns_name_ishostname(const dns_name_t
*name
, isc_boolean_t wildcard
) {
385 unsigned char *ndata
, ch
;
389 REQUIRE(VALID_NAME(name
));
390 REQUIRE(name
->labels
> 0);
391 REQUIRE(name
->attributes
& DNS_NAMEATTR_ABSOLUTE
);
396 if (name
->length
== 1)
400 * Skip wildcard if this is a ownername.
403 if (wildcard
&& ndata
[0] == 1 && ndata
[1] == '*')
407 * RFC292/RFC1123 hostname.
409 while (ndata
< (name
->ndata
+ name
->length
)) {
415 if (first
|| n
== 0) {
429 dns_name_iswildcard(const dns_name_t
*name
) {
430 unsigned char *ndata
;
433 * Is 'name' a wildcard name?
436 REQUIRE(VALID_NAME(name
));
437 REQUIRE(name
->labels
> 0);
439 if (name
->length
>= 2) {
441 if (ndata
[0] == 1 && ndata
[1] == '*')
449 dns_name_internalwildcard(const dns_name_t
*name
) {
450 unsigned char *ndata
;
455 * Does 'name' contain a internal wildcard?
458 REQUIRE(VALID_NAME(name
));
459 REQUIRE(name
->labels
> 0);
470 * Check all but the last of the remaining labels.
472 while (label
+ 1 < name
->labels
) {
475 if (count
== 1 && *ndata
== '*')
483 static inline unsigned int
484 name_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
486 const unsigned char *s
;
490 length
= name
->length
;
495 * This hash function is similar to the one Ousterhout
499 if (case_sensitive
) {
501 h
+= ( h
<< 3 ) + *s
;
518 dns_name_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
520 * Provide a hash value for 'name'.
522 REQUIRE(VALID_NAME(name
));
524 if (name
->labels
== 0)
527 return (name_hash(name
, case_sensitive
));
531 dns_name_fullhash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
533 * Provide a hash value for 'name'.
535 REQUIRE(VALID_NAME(name
));
537 if (name
->labels
== 0)
540 return (isc_hash_calc((const unsigned char *)name
->ndata
,
541 name
->length
, case_sensitive
));
545 dns_fullname_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
547 * This function was deprecated due to the breakage of the name space
548 * convention. We only keep this internally to provide binary backward
551 REQUIRE(VALID_NAME(name
));
553 return (dns_name_fullhash(name
, case_sensitive
));
557 dns_name_hashbylabel(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
558 unsigned char *offsets
;
565 * Provide a hash value for 'name'.
567 REQUIRE(VALID_NAME(name
));
569 if (name
->labels
== 0)
571 else if (name
->labels
== 1)
572 return (name_hash(name
, case_sensitive
));
574 SETUP_OFFSETS(name
, offsets
, odata
);
575 DNS_NAME_INIT(&tname
, NULL
);
578 for (i
= 0; i
< name
->labels
; i
++) {
579 tname
.ndata
= name
->ndata
+ offsets
[i
];
580 if (i
== name
->labels
- 1)
581 tname
.length
= name
->length
- offsets
[i
];
583 tname
.length
= offsets
[i
+ 1] - offsets
[i
];
584 h
+= name_hash(&tname
, case_sensitive
);
591 dns_name_fullcompare(const dns_name_t
*name1
, const dns_name_t
*name2
,
592 int *orderp
, unsigned int *nlabelsp
)
594 unsigned int l1
, l2
, l
, count1
, count2
, count
, nlabels
;
595 int cdiff
, ldiff
, chdiff
;
596 unsigned char *label1
, *label2
;
597 unsigned char *offsets1
, *offsets2
;
598 dns_offsets_t odata1
, odata2
;
599 dns_namereln_t namereln
= dns_namereln_none
;
602 * Determine the relative ordering under the DNSSEC order relation of
603 * 'name1' and 'name2', and also determine the hierarchical
604 * relationship of the names.
606 * Note: It makes no sense for one of the names to be relative and the
607 * other absolute. If both names are relative, then to be meaningfully
608 * compared the caller must ensure that they are both relative to the
612 REQUIRE(VALID_NAME(name1
));
613 REQUIRE(VALID_NAME(name2
));
614 REQUIRE(orderp
!= NULL
);
615 REQUIRE(nlabelsp
!= NULL
);
617 * Either name1 is absolute and name2 is absolute, or neither is.
619 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) ==
620 (name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
));
622 if (name1
== name2
) {
624 *nlabelsp
= name1
->labels
;
625 return (dns_namereln_equal
);
628 SETUP_OFFSETS(name1
, offsets1
, odata1
);
629 SETUP_OFFSETS(name2
, offsets2
, odata2
);
636 ldiff
= 0 - (l2
- l1
);
646 label1
= &name1
->ndata
[offsets1
[l1
]];
647 label2
= &name2
->ndata
[offsets2
[l2
]];
652 * We dropped bitstring labels, and we don't support any
653 * other extended label types.
655 INSIST(count1
<= 63 && count2
<= 63);
657 cdiff
= (int)count1
- (int)count2
;
664 chdiff
= (int)maptolower
[*label1
] -
665 (int)maptolower
[*label2
];
683 namereln
= dns_namereln_contains
;
685 namereln
= dns_namereln_subdomain
;
687 namereln
= dns_namereln_equal
;
692 if (nlabels
> 0 && namereln
== dns_namereln_none
)
693 namereln
= dns_namereln_commonancestor
;
699 dns_name_compare(const dns_name_t
*name1
, const dns_name_t
*name2
) {
701 unsigned int nlabels
;
704 * Determine the relative ordering under the DNSSEC order relation of
705 * 'name1' and 'name2'.
707 * Note: It makes no sense for one of the names to be relative and the
708 * other absolute. If both names are relative, then to be meaningfully
709 * compared the caller must ensure that they are both relative to the
713 (void)dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
719 dns_name_equal(const dns_name_t
*name1
, const dns_name_t
*name2
) {
720 unsigned int l
, count
;
722 unsigned char *label1
, *label2
;
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
));
744 if (name1
->length
!= name2
->length
)
749 if (l
!= name2
->labels
)
752 label1
= name1
->ndata
;
753 label2
= name2
->ndata
;
757 if (count
!= *label2
++)
760 INSIST(count
<= 63); /* no bitstring support */
764 c
= maptolower
[*label1
++];
765 if (c
!= maptolower
[*label2
++])
774 dns_name_caseequal(const dns_name_t
*name1
, const dns_name_t
*name2
) {
777 * Are 'name1' and 'name2' equal?
779 * Note: It makes no sense for one of the names to be relative and the
780 * other absolute. If both names are relative, then to be meaningfully
781 * compared the caller must ensure that they are both relative to the
785 REQUIRE(VALID_NAME(name1
));
786 REQUIRE(VALID_NAME(name2
));
788 * Either name1 is absolute and name2 is absolute, or neither is.
790 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) ==
791 (name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
));
793 if (name1
->length
!= name2
->length
)
796 if (memcmp(name1
->ndata
, name2
->ndata
, name1
->length
) != 0)
803 dns_name_rdatacompare(const dns_name_t
*name1
, const dns_name_t
*name2
) {
804 unsigned int l1
, l2
, l
, count1
, count2
, count
;
805 unsigned char c1
, c2
;
806 unsigned char *label1
, *label2
;
809 * Compare two absolute names as rdata.
812 REQUIRE(VALID_NAME(name1
));
813 REQUIRE(name1
->labels
> 0);
814 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
815 REQUIRE(VALID_NAME(name2
));
816 REQUIRE(name2
->labels
> 0);
817 REQUIRE((name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
822 l
= (l1
< l2
) ? l1
: l2
;
824 label1
= name1
->ndata
;
825 label2
= name2
->ndata
;
831 /* no bitstring support */
832 INSIST(count1
<= 63 && count2
<= 63);
834 if (count1
!= count2
)
835 return ((count1
< count2
) ? -1 : 1);
839 c1
= maptolower
[*label1
++];
840 c2
= maptolower
[*label2
++];
849 * If one name had more labels than the other, their common
850 * prefix must have been different because the shorter name
851 * ended with the root label and the longer one can't have
852 * a root label in the middle of it. Therefore, if we get
853 * to this point, the lengths must be equal.
861 dns_name_issubdomain(const dns_name_t
*name1
, const dns_name_t
*name2
) {
863 unsigned int nlabels
;
864 dns_namereln_t namereln
;
867 * Is 'name1' a subdomain of 'name2'?
869 * Note: It makes no sense for one of the names to be relative and the
870 * other absolute. If both names are relative, then to be meaningfully
871 * compared the caller must ensure that they are both relative to the
875 namereln
= dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
876 if (namereln
== dns_namereln_subdomain
||
877 namereln
== dns_namereln_equal
)
884 dns_name_matcheswildcard(const dns_name_t
*name
, const dns_name_t
*wname
) {
886 unsigned int nlabels
, labels
;
889 REQUIRE(VALID_NAME(name
));
890 REQUIRE(name
->labels
> 0);
891 REQUIRE(VALID_NAME(wname
));
892 labels
= wname
->labels
;
894 REQUIRE(dns_name_iswildcard(wname
));
896 #if defined(__clang__) && \
897 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
898 memset(&tname
, 0, sizeof(tname
));
900 DNS_NAME_INIT(&tname
, NULL
);
901 dns_name_getlabelsequence(wname
, 1, labels
- 1, &tname
);
902 if (dns_name_fullcompare(name
, &tname
, &order
, &nlabels
) ==
903 dns_namereln_subdomain
)
909 dns_name_countlabels(const dns_name_t
*name
) {
911 * How many labels does 'name' have?
914 REQUIRE(VALID_NAME(name
));
916 ENSURE(name
->labels
<= 128);
918 return (name
->labels
);
922 dns_name_getlabel(const dns_name_t
*name
, unsigned int n
, dns_label_t
*label
) {
923 unsigned char *offsets
;
927 * Make 'label' refer to the 'n'th least significant label of 'name'.
930 REQUIRE(VALID_NAME(name
));
931 REQUIRE(name
->labels
> 0);
932 REQUIRE(n
< name
->labels
);
933 REQUIRE(label
!= NULL
);
935 SETUP_OFFSETS(name
, offsets
, odata
);
937 label
->base
= &name
->ndata
[offsets
[n
]];
938 if (n
== name
->labels
- 1)
939 label
->length
= name
->length
- offsets
[n
];
941 label
->length
= offsets
[n
+ 1] - offsets
[n
];
945 dns_name_getlabelsequence(const dns_name_t
*source
,
946 unsigned int first
, unsigned int n
,
949 unsigned char *offsets
;
951 unsigned int firstoffset
, endoffset
;
954 * Make 'target' refer to the 'n' labels including and following
955 * 'first' in 'source'.
958 REQUIRE(VALID_NAME(source
));
959 REQUIRE(VALID_NAME(target
));
960 REQUIRE(first
<= source
->labels
);
961 REQUIRE(n
<= source
->labels
- first
); /* note first+n could overflow */
962 REQUIRE(BINDABLE(target
));
964 SETUP_OFFSETS(source
, offsets
, odata
);
966 if (first
== source
->labels
)
967 firstoffset
= source
->length
;
969 firstoffset
= offsets
[first
];
971 if (first
+ n
== source
->labels
)
972 endoffset
= source
->length
;
974 endoffset
= offsets
[first
+ n
];
976 target
->ndata
= &source
->ndata
[firstoffset
];
977 target
->length
= endoffset
- firstoffset
;
979 if (first
+ n
== source
->labels
&& n
> 0 &&
980 (source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
981 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
983 target
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
988 * If source and target are the same, and we're making target
989 * a prefix of source, the offsets table is correct already
990 * so we don't need to call set_offsets().
992 if (target
->offsets
!= NULL
&&
993 (target
!= source
|| first
!= 0))
994 set_offsets(target
, target
->offsets
, NULL
);
998 dns_name_clone(const dns_name_t
*source
, dns_name_t
*target
) {
1001 * Make 'target' refer to the same name as 'source'.
1004 REQUIRE(VALID_NAME(source
));
1005 REQUIRE(VALID_NAME(target
));
1006 REQUIRE(BINDABLE(target
));
1008 target
->ndata
= source
->ndata
;
1009 target
->length
= source
->length
;
1010 target
->labels
= source
->labels
;
1011 target
->attributes
= source
->attributes
&
1012 (unsigned int)~(DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_DYNAMIC
|
1013 DNS_NAMEATTR_DYNOFFSETS
);
1014 if (target
->offsets
!= NULL
&& source
->labels
> 0) {
1015 if (source
->offsets
!= NULL
)
1016 memmove(target
->offsets
, source
->offsets
,
1019 set_offsets(target
, target
->offsets
, NULL
);
1024 dns_name_fromregion(dns_name_t
*name
, const isc_region_t
*r
) {
1025 unsigned char *offsets
;
1026 dns_offsets_t odata
;
1031 * Make 'name' refer to region 'r'.
1034 REQUIRE(VALID_NAME(name
));
1036 REQUIRE(BINDABLE(name
));
1038 INIT_OFFSETS(name
, offsets
, odata
);
1040 if (name
->buffer
!= NULL
) {
1041 isc_buffer_clear(name
->buffer
);
1042 isc_buffer_availableregion(name
->buffer
, &r2
);
1043 len
= (r
->length
< r2
.length
) ? r
->length
: r2
.length
;
1044 if (len
> DNS_NAME_MAXWIRE
)
1045 len
= DNS_NAME_MAXWIRE
;
1046 memmove(r2
.base
, r
->base
, len
);
1047 name
->ndata
= r2
.base
;
1050 name
->ndata
= r
->base
;
1051 name
->length
= (r
->length
<= DNS_NAME_MAXWIRE
) ?
1052 r
->length
: DNS_NAME_MAXWIRE
;
1056 set_offsets(name
, offsets
, name
);
1059 name
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
1062 if (name
->buffer
!= NULL
)
1063 isc_buffer_add(name
->buffer
, name
->length
);
1067 dns_name_toregion(dns_name_t
*name
, isc_region_t
*r
) {
1069 * Make 'r' refer to 'name'.
1072 REQUIRE(VALID_NAME(name
));
1075 DNS_NAME_TOREGION(name
, r
);
1079 dns_name_fromtext(dns_name_t
*name
, isc_buffer_t
*source
,
1080 const dns_name_t
*origin
, unsigned int options
,
1081 isc_buffer_t
*target
)
1083 unsigned char *ndata
, *label
= NULL
;
1087 unsigned int value
= 0, count
= 0;
1088 unsigned int n1
= 0, n2
= 0;
1089 unsigned int tlen
, nrem
, nused
, digits
= 0, labels
, tused
;
1091 unsigned char *offsets
;
1092 dns_offsets_t odata
;
1093 isc_boolean_t downcase
;
1096 * Convert the textual representation of a DNS name at source
1097 * into uncompressed wire form stored in target.
1100 * Relative domain names will have 'origin' appended to them
1101 * unless 'origin' is NULL, in which case relative domain names
1102 * will remain relative.
1105 REQUIRE(VALID_NAME(name
));
1106 REQUIRE(ISC_BUFFER_VALID(source
));
1107 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1108 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1110 downcase
= ISC_TF((options
& DNS_NAME_DOWNCASE
) != 0);
1112 if (target
== NULL
&& name
->buffer
!= NULL
) {
1113 target
= name
->buffer
;
1114 isc_buffer_clear(target
);
1117 REQUIRE(BINDABLE(name
));
1119 INIT_OFFSETS(name
, offsets
, odata
);
1123 * Make 'name' empty in case of failure.
1128 * Set up the state machine.
1130 tdata
= (char *)source
->base
+ source
->current
;
1131 tlen
= isc_buffer_remaininglength(source
);
1133 ndata
= isc_buffer_used(target
);
1134 nrem
= isc_buffer_availablelength(target
);
1142 while (nrem
> 0 && tlen
> 0 && !done
) {
1150 * Is this the root name?
1154 return (DNS_R_EMPTYLABEL
);
1162 if (c
== '@' && tlen
== 0) {
1175 state
= ft_initialescape
;
1178 state
= ft_ordinary
;
1180 return (ISC_R_NOSPACE
);
1185 return (DNS_R_EMPTYLABEL
);
1188 INSIST(labels
<= 127);
1189 offsets
[labels
] = nused
;
1198 } else if (c
== '\\') {
1202 return (DNS_R_LABELTOOLONG
);
1206 c
= maptolower
[c
& 0xff];
1212 case ft_initialescape
:
1215 * This looks like a bitstring label, which
1216 * was deprecated. Intentionally drop it.
1218 return (DNS_R_BADLABELTYPE
);
1224 if (!isdigit(c
& 0xff)) {
1226 return (DNS_R_LABELTOOLONG
);
1230 c
= maptolower
[c
& 0xff];
1234 state
= ft_ordinary
;
1239 state
= ft_escdecimal
;
1242 if (!isdigit(c
& 0xff))
1243 return (DNS_R_BADESCAPE
);
1245 value
+= digitvalue
[c
& 0xff];
1249 return (DNS_R_BADESCAPE
);
1251 return (DNS_R_LABELTOOLONG
);
1254 value
= maptolower
[value
];
1258 state
= ft_ordinary
;
1262 FATAL_ERROR(__FILE__
, __LINE__
,
1263 "Unexpected state %d", state
);
1264 /* Does not return. */
1270 return (ISC_R_NOSPACE
);
1272 if (state
!= ft_ordinary
&& state
!= ft_at
)
1273 return (ISC_R_UNEXPECTEDEND
);
1274 if (state
== ft_ordinary
) {
1278 INSIST(labels
<= 127);
1279 offsets
[labels
] = nused
;
1281 if (origin
!= NULL
) {
1282 if (nrem
< origin
->length
)
1283 return (ISC_R_NOSPACE
);
1284 label
= origin
->ndata
;
1285 n1
= origin
->length
;
1290 INSIST(n2
<= 63); /* no bitstring support */
1297 c
= maptolower
[c
& 0xff];
1303 INSIST(labels
<= 127);
1304 offsets
[labels
] = nused
;
1307 if ((origin
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
1308 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1311 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1313 name
->ndata
= (unsigned char *)target
->base
+ target
->used
;
1314 name
->labels
= labels
;
1315 name
->length
= nused
;
1317 isc_buffer_forward(source
, tused
);
1318 isc_buffer_add(target
, name
->length
);
1320 return (ISC_R_SUCCESS
);
1323 #ifdef ISC_PLATFORM_USETHREADS
1325 free_specific(void *arg
) {
1326 dns_name_totextfilter_t
*mem
= arg
;
1327 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
1328 /* Stop use being called again. */
1329 (void)isc_thread_key_setspecific(totext_filter_proc_key
, NULL
);
1333 thread_key_mutex_init(void) {
1334 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex
) == ISC_R_SUCCESS
);
1338 totext_filter_proc_key_init(void) {
1339 isc_result_t result
;
1342 * We need the call to isc_once_do() to support profiled mutex
1343 * otherwise thread_key_mutex could be initialized at compile time.
1345 result
= isc_once_do(&once
, thread_key_mutex_init
);
1346 if (result
!= ISC_R_SUCCESS
)
1349 if (!thread_key_initialized
) {
1350 LOCK(&thread_key_mutex
);
1351 if (thread_key_mctx
== NULL
)
1352 result
= isc_mem_create2(0, 0, &thread_key_mctx
, 0);
1353 if (result
!= ISC_R_SUCCESS
)
1355 isc_mem_setname(thread_key_mctx
, "threadkey", NULL
);
1356 isc_mem_setdestroycheck(thread_key_mctx
, ISC_FALSE
);
1358 if (!thread_key_initialized
&&
1359 isc_thread_key_create(&totext_filter_proc_key
,
1360 free_specific
) != 0) {
1361 result
= ISC_R_FAILURE
;
1362 isc_mem_detach(&thread_key_mctx
);
1364 thread_key_initialized
= 1;
1366 UNLOCK(&thread_key_mutex
);
1373 dns_name_totext(dns_name_t
*name
, isc_boolean_t omit_final_dot
,
1374 isc_buffer_t
*target
)
1376 unsigned int options
= DNS_NAME_MASTERFILE
;
1379 options
|= DNS_NAME_OMITFINALDOT
;
1380 return (dns_name_totext2(name
, options
, target
));
1384 dns_name_toprincipal(dns_name_t
*name
, isc_buffer_t
*target
) {
1385 return (dns_name_totext2(name
, DNS_NAME_OMITFINALDOT
, target
));
1389 dns_name_totext2(dns_name_t
*name
, unsigned int options
, isc_buffer_t
*target
)
1391 unsigned char *ndata
;
1393 unsigned int nlen
, tlen
;
1395 unsigned int trem
, count
;
1396 unsigned int labels
;
1397 isc_boolean_t saw_root
= ISC_FALSE
;
1398 unsigned int oused
= target
->used
;
1399 #ifdef ISC_PLATFORM_USETHREADS
1400 dns_name_totextfilter_t
*mem
;
1401 dns_name_totextfilter_t totext_filter_proc
= NULL
;
1402 isc_result_t result
;
1404 isc_boolean_t omit_final_dot
=
1405 ISC_TF(options
& DNS_NAME_OMITFINALDOT
);
1408 * This function assumes the name is in proper uncompressed
1411 REQUIRE(VALID_NAME(name
));
1412 REQUIRE(ISC_BUFFER_VALID(target
));
1414 #ifdef ISC_PLATFORM_USETHREADS
1415 result
= totext_filter_proc_key_init();
1416 if (result
!= ISC_R_SUCCESS
)
1419 ndata
= name
->ndata
;
1420 nlen
= name
->length
;
1421 labels
= name
->labels
;
1422 tdata
= isc_buffer_used(target
);
1423 tlen
= isc_buffer_availablelength(target
);
1427 if (labels
== 0 && nlen
== 0) {
1429 * Special handling for an empty name.
1432 return (ISC_R_NOSPACE
);
1435 * The names of these booleans are misleading in this case.
1436 * This empty name is not necessarily from the root node of
1437 * the DNS root zone, nor is a final dot going to be included.
1438 * They need to be set this way, though, to keep the "@"
1439 * from being trounced.
1441 saw_root
= ISC_TRUE
;
1442 omit_final_dot
= ISC_FALSE
;
1447 * Skip the while() loop.
1450 } else if (nlen
== 1 && labels
== 1 && *ndata
== '\0') {
1452 * Special handling for the root label.
1455 return (ISC_R_NOSPACE
);
1457 saw_root
= ISC_TRUE
;
1458 omit_final_dot
= ISC_FALSE
;
1463 * Skip the while() loop.
1468 while (labels
> 0 && nlen
> 0 && trem
> 0) {
1473 saw_root
= ISC_TRUE
;
1477 INSIST(nlen
>= count
);
1481 /* Special modifiers in zone files. */
1482 case 0x40: /* '@' */
1483 case 0x24: /* '$' */
1484 if ((options
& DNS_NAME_MASTERFILE
) == 0)
1487 case 0x22: /* '"' */
1488 case 0x28: /* '(' */
1489 case 0x29: /* ')' */
1490 case 0x2E: /* '.' */
1491 case 0x3B: /* ';' */
1492 case 0x5C: /* '\\' */
1494 return (ISC_R_NOSPACE
);
1496 CONVERTFROMASCII(c
);
1504 if (c
> 0x20 && c
< 0x7f) {
1506 return (ISC_R_NOSPACE
);
1507 CONVERTFROMASCII(c
);
1514 return (ISC_R_NOSPACE
);
1520 *tdata
++ = 0x30 + (c
% 10);
1529 FATAL_ERROR(__FILE__
, __LINE__
,
1530 "Unexpected label type %02x", count
);
1535 * The following assumes names are absolute. If not, we
1536 * fix things up later. Note that this means that in some
1537 * cases one more byte of text buffer is required than is
1538 * needed in the final output.
1541 return (ISC_R_NOSPACE
);
1546 if (nlen
!= 0 && trem
== 0)
1547 return (ISC_R_NOSPACE
);
1549 if (!saw_root
|| omit_final_dot
)
1552 isc_buffer_add(target
, tlen
- trem
);
1554 #ifdef ISC_PLATFORM_USETHREADS
1555 mem
= isc_thread_key_getspecific(totext_filter_proc_key
);
1557 totext_filter_proc
= *mem
;
1559 if (totext_filter_proc
!= NULL
)
1560 return ((*totext_filter_proc
)(target
, oused
, saw_root
));
1562 return (ISC_R_SUCCESS
);
1566 dns_name_tofilenametext(dns_name_t
*name
, isc_boolean_t omit_final_dot
,
1567 isc_buffer_t
*target
)
1569 unsigned char *ndata
;
1571 unsigned int nlen
, tlen
;
1573 unsigned int trem
, count
;
1574 unsigned int labels
;
1577 * This function assumes the name is in proper uncompressed
1580 REQUIRE(VALID_NAME(name
));
1581 REQUIRE((name
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
1582 REQUIRE(ISC_BUFFER_VALID(target
));
1584 ndata
= name
->ndata
;
1585 nlen
= name
->length
;
1586 labels
= name
->labels
;
1587 tdata
= isc_buffer_used(target
);
1588 tlen
= isc_buffer_availablelength(target
);
1592 if (nlen
== 1 && labels
== 1 && *ndata
== '\0') {
1594 * Special handling for the root label.
1597 return (ISC_R_NOSPACE
);
1599 omit_final_dot
= ISC_FALSE
;
1604 * Skip the while() loop.
1609 while (labels
> 0 && nlen
> 0 && trem
> 0) {
1616 INSIST(nlen
>= count
);
1619 if ((c
>= 0x30 && c
<= 0x39) || /* digit */
1620 (c
>= 0x41 && c
<= 0x5A) || /* uppercase */
1621 (c
>= 0x61 && c
<= 0x7A) || /* lowercase */
1622 c
== 0x2D || /* hyphen */
1623 c
== 0x5F) /* underscore */
1626 return (ISC_R_NOSPACE
);
1628 if (c
>= 0x41 && c
<= 0x5A)
1630 CONVERTFROMASCII(c
);
1637 return (ISC_R_NOSPACE
);
1638 sprintf(tdata
, "%%%02X", c
);
1647 FATAL_ERROR(__FILE__
, __LINE__
,
1648 "Unexpected label type %02x", count
);
1653 * The following assumes names are absolute. If not, we
1654 * fix things up later. Note that this means that in some
1655 * cases one more byte of text buffer is required than is
1656 * needed in the final output.
1659 return (ISC_R_NOSPACE
);
1664 if (nlen
!= 0 && trem
== 0)
1665 return (ISC_R_NOSPACE
);
1670 isc_buffer_add(target
, tlen
- trem
);
1672 return (ISC_R_SUCCESS
);
1676 dns_name_downcase(dns_name_t
*source
, dns_name_t
*name
, isc_buffer_t
*target
) {
1677 unsigned char *sndata
, *ndata
;
1678 unsigned int nlen
, count
, labels
;
1679 isc_buffer_t buffer
;
1682 * Downcase 'source'.
1685 REQUIRE(VALID_NAME(source
));
1686 REQUIRE(VALID_NAME(name
));
1687 if (source
== name
) {
1688 REQUIRE((name
->attributes
& DNS_NAMEATTR_READONLY
) == 0);
1689 isc_buffer_init(&buffer
, source
->ndata
, source
->length
);
1691 ndata
= source
->ndata
;
1693 REQUIRE(BINDABLE(name
));
1694 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1695 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1696 if (target
== NULL
) {
1697 target
= name
->buffer
;
1698 isc_buffer_clear(name
->buffer
);
1700 ndata
= (unsigned char *)target
->base
+ target
->used
;
1701 name
->ndata
= ndata
;
1704 sndata
= source
->ndata
;
1705 nlen
= source
->length
;
1706 labels
= source
->labels
;
1708 if (nlen
> (target
->length
- target
->used
)) {
1710 return (ISC_R_NOSPACE
);
1713 while (labels
> 0 && nlen
> 0) {
1719 INSIST(nlen
>= count
);
1721 *ndata
++ = maptolower
[(*sndata
++)];
1726 FATAL_ERROR(__FILE__
, __LINE__
,
1727 "Unexpected label type %02x", count
);
1728 /* Does not return. */
1732 if (source
!= name
) {
1733 name
->labels
= source
->labels
;
1734 name
->length
= source
->length
;
1735 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
1736 name
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
1738 name
->attributes
= 0;
1739 if (name
->labels
> 0 && name
->offsets
!= NULL
)
1740 set_offsets(name
, name
->offsets
, NULL
);
1743 isc_buffer_add(target
, name
->length
);
1745 return (ISC_R_SUCCESS
);
1749 set_offsets(const dns_name_t
*name
, unsigned char *offsets
,
1750 dns_name_t
*set_name
)
1752 unsigned int offset
, count
, length
, nlabels
;
1753 unsigned char *ndata
;
1754 isc_boolean_t absolute
;
1756 ndata
= name
->ndata
;
1757 length
= name
->length
;
1760 absolute
= ISC_FALSE
;
1761 while (offset
!= length
) {
1762 INSIST(nlabels
< 128);
1763 offsets
[nlabels
++] = offset
;
1766 INSIST(count
<= 63);
1769 INSIST(offset
<= length
);
1771 absolute
= ISC_TRUE
;
1775 if (set_name
!= NULL
) {
1776 INSIST(set_name
== name
);
1778 set_name
->labels
= nlabels
;
1779 set_name
->length
= offset
;
1781 set_name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1783 set_name
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
1785 INSIST(nlabels
== name
->labels
);
1786 INSIST(offset
== name
->length
);
1790 dns_name_fromwire(dns_name_t
*name
, isc_buffer_t
*source
,
1791 dns_decompress_t
*dctx
, unsigned int options
,
1792 isc_buffer_t
*target
)
1794 unsigned char *cdata
, *ndata
;
1795 unsigned int cused
; /* Bytes of compressed name data used */
1796 unsigned int nused
, labels
, n
, nmax
;
1797 unsigned int current
, new_current
, biggest_pointer
;
1799 fw_state state
= fw_start
;
1801 unsigned char *offsets
;
1802 dns_offsets_t odata
;
1803 isc_boolean_t downcase
;
1804 isc_boolean_t seen_pointer
;
1807 * Copy the possibly-compressed name at source into target,
1808 * decompressing it. Loop prevention is performed by checking
1809 * the new pointer against biggest_pointer.
1812 REQUIRE(VALID_NAME(name
));
1813 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1814 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1816 downcase
= ISC_TF((options
& DNS_NAME_DOWNCASE
) != 0);
1818 if (target
== NULL
&& name
->buffer
!= NULL
) {
1819 target
= name
->buffer
;
1820 isc_buffer_clear(target
);
1823 REQUIRE(dctx
!= NULL
);
1824 REQUIRE(BINDABLE(name
));
1826 INIT_OFFSETS(name
, offsets
, odata
);
1829 * Make 'name' empty in case of failure.
1834 * Initialize things to make the compiler happy; they're not required.
1845 ndata
= isc_buffer_used(target
);
1847 seen_pointer
= ISC_FALSE
;
1850 * Find the maximum number of uncompressed target name
1851 * bytes we are willing to generate. This is the smaller
1852 * of the available target buffer length and the
1853 * maximum legal domain name length (255).
1855 nmax
= isc_buffer_availablelength(target
);
1856 if (nmax
> DNS_NAME_MAXWIRE
)
1857 nmax
= DNS_NAME_MAXWIRE
;
1859 cdata
= isc_buffer_current(source
);
1862 current
= source
->current
;
1863 biggest_pointer
= current
;
1866 * Note: The following code is not optimized for speed, but
1867 * rather for correctness. Speed will be addressed in the future.
1870 while (current
< source
->active
&& !done
) {
1879 offsets
[labels
] = nused
;
1881 if (nused
+ c
+ 1 > nmax
)
1888 state
= fw_ordinary
;
1889 } else if (c
>= 128 && c
< 192) {
1891 * 14 bit local compression pointer.
1892 * Local compression is no longer an
1895 return (DNS_R_BADLABELTYPE
);
1896 } else if (c
>= 192) {
1898 * Ordinary 14-bit pointer.
1900 if ((dctx
->allowed
& DNS_COMPRESS_GLOBAL14
) ==
1902 return (DNS_R_DISALLOWED
);
1903 new_current
= c
& 0x3F;
1904 state
= fw_newcurrent
;
1906 return (DNS_R_BADLABELTYPE
);
1919 if (new_current
>= biggest_pointer
)
1920 return (DNS_R_BADPOINTER
);
1921 biggest_pointer
= new_current
;
1922 current
= new_current
;
1923 cdata
= (unsigned char *)source
->base
+ current
;
1924 seen_pointer
= ISC_TRUE
;
1928 FATAL_ERROR(__FILE__
, __LINE__
,
1929 "Unknown state %d", state
);
1930 /* Does not return. */
1935 return (ISC_R_UNEXPECTEDEND
);
1937 name
->ndata
= (unsigned char *)target
->base
+ target
->used
;
1938 name
->labels
= labels
;
1939 name
->length
= nused
;
1940 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1942 isc_buffer_forward(source
, cused
);
1943 isc_buffer_add(target
, name
->length
);
1945 return (ISC_R_SUCCESS
);
1948 if (nmax
== DNS_NAME_MAXWIRE
)
1950 * The name did not fit even though we had a buffer
1951 * big enough to fit a maximum-length name.
1953 return (DNS_R_NAMETOOLONG
);
1956 * The name might fit if only the caller could give us a
1957 * big enough buffer.
1959 return (ISC_R_NOSPACE
);
1963 dns_name_towire(const dns_name_t
*name
, dns_compress_t
*cctx
,
1964 isc_buffer_t
*target
)
1966 unsigned int methods
;
1967 isc_uint16_t offset
;
1968 dns_name_t gp
; /* Global compression prefix */
1969 isc_boolean_t gf
; /* Global compression target found */
1970 isc_uint16_t go
; /* Global compression offset */
1975 * Convert 'name' into wire format, compressing it as specified by the
1976 * compression context 'cctx', and storing the result in 'target'.
1979 REQUIRE(VALID_NAME(name
));
1980 REQUIRE(cctx
!= NULL
);
1981 REQUIRE(ISC_BUFFER_VALID(target
));
1984 * If 'name' doesn't have an offsets table, make a clone which
1987 if (name
->offsets
== NULL
) {
1988 #if defined(__clang__) && \
1989 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1990 memset(&clname
, 0, sizeof(clname
));
1992 DNS_NAME_INIT(&clname
, clo
);
1993 dns_name_clone(name
, &clname
);
1996 DNS_NAME_INIT(&gp
, NULL
);
1998 offset
= target
->used
; /*XXX*/
2000 methods
= dns_compress_getmethods(cctx
);
2002 if ((name
->attributes
& DNS_NAMEATTR_NOCOMPRESS
) == 0 &&
2003 (methods
& DNS_COMPRESS_GLOBAL14
) != 0)
2004 gf
= dns_compress_findglobal(cctx
, name
, &gp
, &go
);
2009 * If the offset is too high for 14 bit global compression, we're
2012 if (gf
&& go
>= 0x4000)
2016 * Will the compression pointer reduce the message size?
2018 if (gf
&& (gp
.length
+ 2) >= name
->length
)
2022 if (target
->length
- target
->used
< gp
.length
)
2023 return (ISC_R_NOSPACE
);
2024 (void)memmove((unsigned char *)target
->base
+ target
->used
,
2025 gp
.ndata
, (size_t)gp
.length
);
2026 isc_buffer_add(target
, gp
.length
);
2028 if (target
->length
- target
->used
< 2)
2029 return (ISC_R_NOSPACE
);
2030 isc_buffer_putuint16(target
, go
);
2032 dns_compress_add(cctx
, name
, &gp
, offset
);
2034 if (target
->length
- target
->used
< name
->length
)
2035 return (ISC_R_NOSPACE
);
2036 (void)memmove((unsigned char *)target
->base
+ target
->used
,
2037 name
->ndata
, (size_t)name
->length
);
2038 isc_buffer_add(target
, name
->length
);
2039 dns_compress_add(cctx
, name
, name
, offset
);
2041 return (ISC_R_SUCCESS
);
2045 dns_name_concatenate(dns_name_t
*prefix
, dns_name_t
*suffix
, dns_name_t
*name
,
2046 isc_buffer_t
*target
)
2048 unsigned char *ndata
, *offsets
;
2049 unsigned int nrem
, labels
, prefix_length
, length
;
2050 isc_boolean_t copy_prefix
= ISC_TRUE
;
2051 isc_boolean_t copy_suffix
= ISC_TRUE
;
2052 isc_boolean_t absolute
= ISC_FALSE
;
2053 dns_name_t tmp_name
;
2054 dns_offsets_t odata
;
2057 * Concatenate 'prefix' and 'suffix'.
2060 REQUIRE(prefix
== NULL
|| VALID_NAME(prefix
));
2061 REQUIRE(suffix
== NULL
|| VALID_NAME(suffix
));
2062 REQUIRE(name
== NULL
|| VALID_NAME(name
));
2063 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
2064 (target
== NULL
&& name
!= NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
2065 if (prefix
== NULL
|| prefix
->labels
== 0)
2066 copy_prefix
= ISC_FALSE
;
2067 if (suffix
== NULL
|| suffix
->labels
== 0)
2068 copy_suffix
= ISC_FALSE
;
2070 (prefix
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0) {
2071 absolute
= ISC_TRUE
;
2072 REQUIRE(!copy_suffix
);
2075 DNS_NAME_INIT(&tmp_name
, odata
);
2078 if (target
== NULL
) {
2079 INSIST(name
->buffer
!= NULL
);
2080 target
= name
->buffer
;
2081 isc_buffer_clear(name
->buffer
);
2084 REQUIRE(BINDABLE(name
));
2089 nrem
= target
->length
- target
->used
;
2090 ndata
= (unsigned char *)target
->base
+ target
->used
;
2091 if (nrem
> DNS_NAME_MAXWIRE
)
2092 nrem
= DNS_NAME_MAXWIRE
;
2097 prefix_length
= prefix
->length
;
2098 length
+= prefix_length
;
2099 labels
+= prefix
->labels
;
2102 length
+= suffix
->length
;
2103 labels
+= suffix
->labels
;
2105 if (length
> DNS_NAME_MAXWIRE
) {
2107 return (DNS_R_NAMETOOLONG
);
2109 if (length
> nrem
) {
2111 return (ISC_R_NOSPACE
);
2115 if ((suffix
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2116 absolute
= ISC_TRUE
;
2117 memmove(ndata
+ prefix_length
, suffix
->ndata
, suffix
->length
);
2121 * If 'prefix' and 'name' are the same object, and the object has
2122 * a dedicated buffer, and we're using it, then we don't have to
2125 if (copy_prefix
&& (prefix
!= name
|| prefix
->buffer
!= target
))
2126 memmove(ndata
, prefix
->ndata
, prefix_length
);
2128 name
->ndata
= ndata
;
2129 name
->labels
= labels
;
2130 name
->length
= length
;
2132 name
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
2134 name
->attributes
= 0;
2136 if (name
->labels
> 0 && name
->offsets
!= NULL
) {
2137 INIT_OFFSETS(name
, offsets
, odata
);
2138 set_offsets(name
, offsets
, NULL
);
2141 isc_buffer_add(target
, name
->length
);
2143 return (ISC_R_SUCCESS
);
2147 dns_name_split(dns_name_t
*name
, unsigned int suffixlabels
,
2148 dns_name_t
*prefix
, dns_name_t
*suffix
)
2151 unsigned int splitlabel
;
2153 REQUIRE(VALID_NAME(name
));
2154 REQUIRE(suffixlabels
> 0);
2155 REQUIRE(suffixlabels
< name
->labels
);
2156 REQUIRE(prefix
!= NULL
|| suffix
!= NULL
);
2157 REQUIRE(prefix
== NULL
||
2158 (VALID_NAME(prefix
) &&
2159 prefix
->buffer
!= NULL
&&
2161 REQUIRE(suffix
== NULL
||
2162 (VALID_NAME(suffix
) &&
2163 suffix
->buffer
!= NULL
&&
2166 splitlabel
= name
->labels
- suffixlabels
;
2169 dns_name_getlabelsequence(name
, 0, splitlabel
, prefix
);
2172 dns_name_getlabelsequence(name
, splitlabel
,
2173 suffixlabels
, suffix
);
2179 dns_name_dup(const dns_name_t
*source
, isc_mem_t
*mctx
,
2183 * Make 'target' a dynamically allocated copy of 'source'.
2186 REQUIRE(VALID_NAME(source
));
2187 REQUIRE(source
->length
> 0);
2188 REQUIRE(VALID_NAME(target
));
2189 REQUIRE(BINDABLE(target
));
2192 * Make 'target' empty in case of failure.
2196 target
->ndata
= isc_mem_get(mctx
, source
->length
);
2197 if (target
->ndata
== NULL
)
2198 return (ISC_R_NOMEMORY
);
2200 memmove(target
->ndata
, source
->ndata
, source
->length
);
2202 target
->length
= source
->length
;
2203 target
->labels
= source
->labels
;
2204 target
->attributes
= DNS_NAMEATTR_DYNAMIC
;
2205 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2206 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
2207 if (target
->offsets
!= NULL
) {
2208 if (source
->offsets
!= NULL
)
2209 memmove(target
->offsets
, source
->offsets
,
2212 set_offsets(target
, target
->offsets
, NULL
);
2215 return (ISC_R_SUCCESS
);
2219 dns_name_dupwithoffsets(dns_name_t
*source
, isc_mem_t
*mctx
,
2223 * Make 'target' a read-only dynamically allocated copy of 'source'.
2224 * 'target' will also have a dynamically allocated offsets table.
2227 REQUIRE(VALID_NAME(source
));
2228 REQUIRE(source
->length
> 0);
2229 REQUIRE(VALID_NAME(target
));
2230 REQUIRE(BINDABLE(target
));
2231 REQUIRE(target
->offsets
== NULL
);
2234 * Make 'target' empty in case of failure.
2238 target
->ndata
= isc_mem_get(mctx
, source
->length
+ source
->labels
);
2239 if (target
->ndata
== NULL
)
2240 return (ISC_R_NOMEMORY
);
2242 memmove(target
->ndata
, source
->ndata
, source
->length
);
2244 target
->length
= source
->length
;
2245 target
->labels
= source
->labels
;
2246 target
->attributes
= DNS_NAMEATTR_DYNAMIC
| DNS_NAMEATTR_DYNOFFSETS
|
2247 DNS_NAMEATTR_READONLY
;
2248 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2249 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
2250 target
->offsets
= target
->ndata
+ source
->length
;
2251 if (source
->offsets
!= NULL
)
2252 memmove(target
->offsets
, source
->offsets
, source
->labels
);
2254 set_offsets(target
, target
->offsets
, NULL
);
2256 return (ISC_R_SUCCESS
);
2260 dns_name_free(dns_name_t
*name
, isc_mem_t
*mctx
) {
2267 REQUIRE(VALID_NAME(name
));
2268 REQUIRE((name
->attributes
& DNS_NAMEATTR_DYNAMIC
) != 0);
2270 size
= name
->length
;
2271 if ((name
->attributes
& DNS_NAMEATTR_DYNOFFSETS
) != 0)
2272 size
+= name
->labels
;
2273 isc_mem_put(mctx
, name
->ndata
, size
);
2274 dns_name_invalidate(name
);
2278 dns_name_digest(dns_name_t
*name
, dns_digestfunc_t digest
, void *arg
) {
2279 dns_name_t downname
;
2280 unsigned char data
[256];
2281 isc_buffer_t buffer
;
2282 isc_result_t result
;
2286 * Send 'name' in DNSSEC canonical form to 'digest'.
2289 REQUIRE(VALID_NAME(name
));
2290 REQUIRE(digest
!= NULL
);
2292 #if defined(__clang__) && \
2293 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2294 memset(&downname
, 0, sizeof(downname
));
2296 DNS_NAME_INIT(&downname
, NULL
);
2298 isc_buffer_init(&buffer
, data
, sizeof(data
));
2300 result
= dns_name_downcase(name
, &downname
, &buffer
);
2301 if (result
!= ISC_R_SUCCESS
)
2304 isc_buffer_usedregion(&buffer
, &r
);
2306 return ((digest
)(arg
, &r
));
2310 dns_name_dynamic(dns_name_t
*name
) {
2311 REQUIRE(VALID_NAME(name
));
2314 * Returns whether there is dynamic memory associated with this name.
2317 return ((name
->attributes
& DNS_NAMEATTR_DYNAMIC
) != 0 ?
2318 ISC_TRUE
: ISC_FALSE
);
2322 dns_name_print(dns_name_t
*name
, FILE *stream
) {
2323 isc_result_t result
;
2329 * Print 'name' on 'stream'.
2332 REQUIRE(VALID_NAME(name
));
2334 isc_buffer_init(&b
, t
, sizeof(t
));
2335 result
= dns_name_totext(name
, ISC_FALSE
, &b
);
2336 if (result
!= ISC_R_SUCCESS
)
2338 isc_buffer_usedregion(&b
, &r
);
2339 fprintf(stream
, "%.*s", (int)r
.length
, (char *)r
.base
);
2341 return (ISC_R_SUCCESS
);
2345 dns_name_settotextfilter(dns_name_totextfilter_t proc
) {
2346 #ifdef ISC_PLATFORM_USETHREADS
2347 isc_result_t result
;
2348 dns_name_totextfilter_t
*mem
;
2351 result
= totext_filter_proc_key_init();
2352 if (result
!= ISC_R_SUCCESS
)
2356 * If we already have been here set / clear as appropriate.
2357 * Otherwise allocate memory.
2359 mem
= isc_thread_key_getspecific(totext_filter_proc_key
);
2360 if (mem
!= NULL
&& proc
!= NULL
) {
2362 return (ISC_R_SUCCESS
);
2365 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
2366 res
= isc_thread_key_setspecific(totext_filter_proc_key
, NULL
);
2368 result
= ISC_R_UNEXPECTED
;
2372 mem
= isc_mem_get(thread_key_mctx
, sizeof(*mem
));
2374 return (ISC_R_NOMEMORY
);
2376 if (isc_thread_key_setspecific(totext_filter_proc_key
, mem
) != 0) {
2377 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
2378 result
= ISC_R_UNEXPECTED
;
2382 totext_filter_proc
= proc
;
2383 return (ISC_R_SUCCESS
);
2388 dns_name_format(dns_name_t
*name
, char *cp
, unsigned int size
) {
2389 isc_result_t result
;
2395 * Leave room for null termination after buffer.
2397 isc_buffer_init(&buf
, cp
, size
- 1);
2398 result
= dns_name_totext(name
, ISC_TRUE
, &buf
);
2399 if (result
== ISC_R_SUCCESS
) {
2404 isc_buffer_usedregion(&buf
, &r
);
2405 ((char *) r
.base
)[r
.length
] = '\0';
2408 snprintf(cp
, size
, "<unknown>");
2412 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2416 dns_name_tostring(dns_name_t
*name
, char **target
, isc_mem_t
*mctx
) {
2417 isc_result_t result
;
2420 char *p
, txt
[DNS_NAME_FORMATSIZE
];
2422 REQUIRE(VALID_NAME(name
));
2423 REQUIRE(target
!= NULL
&& *target
== NULL
);
2425 isc_buffer_init(&buf
, txt
, sizeof(txt
));
2426 result
= dns_name_totext(name
, ISC_FALSE
, &buf
);
2427 if (result
!= ISC_R_SUCCESS
)
2430 isc_buffer_usedregion(&buf
, ®
);
2431 p
= isc_mem_allocate(mctx
, reg
.length
+ 1);
2432 memmove(p
, (char *) reg
.base
, (int) reg
.length
);
2433 p
[reg
.length
] = '\0';
2436 return (ISC_R_SUCCESS
);
2440 * dns_name_fromstring() -- convert directly from a string to a name,
2441 * allocating memory as needed
2444 dns_name_fromstring(dns_name_t
*target
, const char *src
, unsigned int options
,
2447 return (dns_name_fromstring2(target
, src
, dns_rootname
, options
, mctx
));
2451 dns_name_fromstring2(dns_name_t
*target
, const char *src
,
2452 const dns_name_t
*origin
, unsigned int options
,
2455 isc_result_t result
;
2460 REQUIRE(src
!= NULL
);
2462 isc_buffer_constinit(&buf
, src
, strlen(src
));
2463 isc_buffer_add(&buf
, strlen(src
));
2464 if (BINDABLE(target
) && target
->buffer
!= NULL
)
2467 dns_fixedname_init(&fn
);
2468 name
= dns_fixedname_name(&fn
);
2471 result
= dns_name_fromtext(name
, &buf
, origin
, options
, NULL
);
2472 if (result
!= ISC_R_SUCCESS
)
2476 result
= dns_name_dupwithoffsets(name
, mctx
, target
);
2481 dns_name_copy(dns_name_t
*source
, dns_name_t
*dest
, isc_buffer_t
*target
) {
2482 unsigned char *ndata
;
2485 * Make dest a copy of source.
2488 REQUIRE(VALID_NAME(source
));
2489 REQUIRE(VALID_NAME(dest
));
2490 REQUIRE(target
!= NULL
|| dest
->buffer
!= NULL
);
2492 if (target
== NULL
) {
2493 target
= dest
->buffer
;
2494 isc_buffer_clear(dest
->buffer
);
2497 REQUIRE(BINDABLE(dest
));
2502 if (target
->length
- target
->used
< source
->length
)
2503 return (ISC_R_NOSPACE
);
2505 ndata
= (unsigned char *)target
->base
+ target
->used
;
2506 dest
->ndata
= target
->base
;
2508 memmove(ndata
, source
->ndata
, source
->length
);
2510 dest
->ndata
= ndata
;
2511 dest
->labels
= source
->labels
;
2512 dest
->length
= source
->length
;
2513 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2514 dest
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
2516 dest
->attributes
= 0;
2518 if (dest
->labels
> 0 && dest
->offsets
!= NULL
) {
2519 if (source
->offsets
!= NULL
)
2520 memmove(dest
->offsets
, source
->offsets
, source
->labels
);
2522 set_offsets(dest
, dest
->offsets
, NULL
);
2525 isc_buffer_add(target
, dest
->length
);
2527 return (ISC_R_SUCCESS
);
2531 dns_name_destroy(void) {
2532 #ifdef ISC_PLATFORM_USETHREADS
2533 RUNTIME_CHECK(isc_once_do(&once
, thread_key_mutex_init
)
2536 LOCK(&thread_key_mutex
);
2537 if (thread_key_initialized
) {
2538 isc_mem_detach(&thread_key_mctx
);
2539 isc_thread_key_delete(totext_filter_proc_key
);
2540 thread_key_initialized
= 0;
2542 UNLOCK(&thread_key_mutex
);