4 * Copyright (C) 2004-2009 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.
20 /* Id: name.c,v 1.169 2009/09/01 17:36:51 jinmei Exp */
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)
62 static char digitvalue
[256] = {
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
66 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
67 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
68 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
69 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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,
78 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
81 static unsigned char maptolower
[] = {
82 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
83 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
84 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
85 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
86 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
87 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
88 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
89 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
90 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
91 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
92 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
93 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
94 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
95 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
96 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
97 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
98 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
99 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
100 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
101 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
102 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
103 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
104 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
105 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
106 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
107 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
108 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
109 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
110 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
111 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
112 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
113 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
116 #define CONVERTTOASCII(c)
117 #define CONVERTFROMASCII(c)
119 #define INIT_OFFSETS(name, var, default) \
120 if (name->offsets != NULL) \
121 var = name->offsets; \
125 #define SETUP_OFFSETS(name, var, default) \
126 if (name->offsets != NULL) \
127 var = name->offsets; \
130 set_offsets(name, var, NULL); \
134 * Note: If additional attributes are added that should not be set for
135 * empty names, MAKE_EMPTY() must be changed so it clears them.
137 #define MAKE_EMPTY(name) \
139 name->ndata = NULL; \
142 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
146 * A name is "bindable" if it can be set to point to a new value, i.e.
147 * name->ndata and name->length may be changed.
149 #define BINDABLE(name) \
150 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
154 * Note that the name data must be a char array, not a string
155 * literal, to avoid compiler warnings about discarding
156 * the const attribute of a string.
158 static unsigned char root_ndata
[] = { '\0' };
159 static unsigned char root_offsets
[] = { 0 };
161 static dns_name_t root
=
165 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
167 {(void *)-1, (void *)-1},
171 /* XXXDCL make const? */
172 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_rootname
= &root
;
174 static unsigned char wild_ndata
[] = { '\001', '*' };
175 static unsigned char wild_offsets
[] = { 0 };
177 static dns_name_t wild
=
181 DNS_NAMEATTR_READONLY
,
183 {(void *)-1, (void *)-1},
187 /* XXXDCL make const? */
188 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_wildcardname
= &wild
;
191 dns_fullname_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
);
194 * dns_name_t to text post-conversion procedure.
196 #ifdef ISC_PLATFORM_USETHREADS
197 static int thread_key_initialized
= 0;
198 static isc_mutex_t thread_key_mutex
;
199 static isc_mem_t
*thread_key_mctx
= NULL
;
200 static isc_thread_key_t totext_filter_proc_key
;
201 static isc_once_t once
= ISC_ONCE_INIT
;
203 static dns_name_totextfilter_t totext_filter_proc
= NULL
;
207 set_offsets(const dns_name_t
*name
, unsigned char *offsets
,
208 dns_name_t
*set_name
);
211 dns_name_init(dns_name_t
*name
, unsigned char *offsets
) {
215 DNS_NAME_INIT(name
, offsets
);
219 dns_name_reset(dns_name_t
*name
) {
220 REQUIRE(VALID_NAME(name
));
221 REQUIRE(BINDABLE(name
));
223 DNS_NAME_RESET(name
);
227 dns_name_invalidate(dns_name_t
*name
) {
229 * Make 'name' invalid.
232 REQUIRE(VALID_NAME(name
));
238 name
->attributes
= 0;
239 name
->offsets
= NULL
;
241 ISC_LINK_INIT(name
, link
);
245 dns_name_setbuffer(dns_name_t
*name
, isc_buffer_t
*buffer
) {
247 * Dedicate a buffer for use with 'name'.
250 REQUIRE(VALID_NAME(name
));
251 REQUIRE((buffer
!= NULL
&& name
->buffer
== NULL
) ||
254 name
->buffer
= buffer
;
258 dns_name_hasbuffer(const dns_name_t
*name
) {
260 * Does 'name' have a dedicated buffer?
263 REQUIRE(VALID_NAME(name
));
265 if (name
->buffer
!= NULL
)
272 dns_name_isabsolute(const dns_name_t
*name
) {
275 * Does 'name' end in the root label?
278 REQUIRE(VALID_NAME(name
));
280 if ((name
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
285 #define hyphenchar(c) ((c) == 0x2d)
286 #define asterchar(c) ((c) == 0x2a)
287 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
288 || ((c) >= 0x61 && (c) <= 0x7a))
289 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
290 #define borderchar(c) (alphachar(c) || digitchar(c))
291 #define middlechar(c) (borderchar(c) || hyphenchar(c))
292 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
295 dns_name_ismailbox(const dns_name_t
*name
) {
296 unsigned char *ndata
, ch
;
300 REQUIRE(VALID_NAME(name
));
301 REQUIRE(name
->labels
> 0);
302 REQUIRE(name
->attributes
& DNS_NAMEATTR_ABSOLUTE
);
307 if (name
->length
== 1)
319 if (ndata
== name
->ndata
+ name
->length
)
323 * RFC292/RFC1123 hostname.
325 while (ndata
< (name
->ndata
+ name
->length
)) {
331 if (first
|| n
== 0) {
345 dns_name_ishostname(const dns_name_t
*name
, isc_boolean_t wildcard
) {
346 unsigned char *ndata
, ch
;
350 REQUIRE(VALID_NAME(name
));
351 REQUIRE(name
->labels
> 0);
352 REQUIRE(name
->attributes
& DNS_NAMEATTR_ABSOLUTE
);
357 if (name
->length
== 1)
361 * Skip wildcard if this is a ownername.
364 if (wildcard
&& ndata
[0] == 1 && ndata
[1] == '*')
368 * RFC292/RFC1123 hostname.
370 while (ndata
< (name
->ndata
+ name
->length
)) {
376 if (first
|| n
== 0) {
390 dns_name_iswildcard(const dns_name_t
*name
) {
391 unsigned char *ndata
;
394 * Is 'name' a wildcard name?
397 REQUIRE(VALID_NAME(name
));
398 REQUIRE(name
->labels
> 0);
400 if (name
->length
>= 2) {
402 if (ndata
[0] == 1 && ndata
[1] == '*')
410 dns_name_internalwildcard(const dns_name_t
*name
) {
411 unsigned char *ndata
;
416 * Does 'name' contain a internal wildcard?
419 REQUIRE(VALID_NAME(name
));
420 REQUIRE(name
->labels
> 0);
431 * Check all but the last of the remaining labels.
433 while (label
+ 1 < name
->labels
) {
436 if (count
== 1 && *ndata
== '*')
444 static inline unsigned int
445 name_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
447 const unsigned char *s
;
451 length
= name
->length
;
456 * This hash function is similar to the one Ousterhout
460 if (case_sensitive
) {
462 h
+= ( h
<< 3 ) + *s
;
479 dns_name_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
481 * Provide a hash value for 'name'.
483 REQUIRE(VALID_NAME(name
));
485 if (name
->labels
== 0)
488 return (name_hash(name
, case_sensitive
));
492 dns_name_fullhash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
494 * Provide a hash value for 'name'.
496 REQUIRE(VALID_NAME(name
));
498 if (name
->labels
== 0)
501 return (isc_hash_calc((const unsigned char *)name
->ndata
,
502 name
->length
, case_sensitive
));
506 dns_fullname_hash(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
508 * This function was deprecated due to the breakage of the name space
509 * convention. We only keep this internally to provide binary backward
512 REQUIRE(VALID_NAME(name
));
514 return (dns_name_fullhash(name
, case_sensitive
));
518 dns_name_hashbylabel(dns_name_t
*name
, isc_boolean_t case_sensitive
) {
519 unsigned char *offsets
;
526 * Provide a hash value for 'name'.
528 REQUIRE(VALID_NAME(name
));
530 if (name
->labels
== 0)
532 else if (name
->labels
== 1)
533 return (name_hash(name
, case_sensitive
));
535 SETUP_OFFSETS(name
, offsets
, odata
);
536 DNS_NAME_INIT(&tname
, NULL
);
539 for (i
= 0; i
< name
->labels
; i
++) {
540 tname
.ndata
= name
->ndata
+ offsets
[i
];
541 if (i
== name
->labels
- 1)
542 tname
.length
= name
->length
- offsets
[i
];
544 tname
.length
= offsets
[i
+ 1] - offsets
[i
];
545 h
+= name_hash(&tname
, case_sensitive
);
552 dns_name_fullcompare(const dns_name_t
*name1
, const dns_name_t
*name2
,
553 int *orderp
, unsigned int *nlabelsp
)
555 unsigned int l1
, l2
, l
, count1
, count2
, count
, nlabels
;
556 int cdiff
, ldiff
, chdiff
;
557 unsigned char *label1
, *label2
;
558 unsigned char *offsets1
, *offsets2
;
559 dns_offsets_t odata1
, odata2
;
560 dns_namereln_t namereln
= dns_namereln_none
;
563 * Determine the relative ordering under the DNSSEC order relation of
564 * 'name1' and 'name2', and also determine the hierarchical
565 * relationship of the names.
567 * Note: It makes no sense for one of the names to be relative and the
568 * other absolute. If both names are relative, then to be meaningfully
569 * compared the caller must ensure that they are both relative to the
573 REQUIRE(VALID_NAME(name1
));
574 REQUIRE(VALID_NAME(name2
));
575 REQUIRE(orderp
!= NULL
);
576 REQUIRE(nlabelsp
!= NULL
);
578 * Either name1 is absolute and name2 is absolute, or neither is.
580 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) ==
581 (name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
));
583 SETUP_OFFSETS(name1
, offsets1
, odata1
);
584 SETUP_OFFSETS(name2
, offsets2
, odata2
);
589 ldiff
= (int)l1
- (int)l2
;
599 label1
= &name1
->ndata
[offsets1
[l1
]];
600 label2
= &name2
->ndata
[offsets2
[l2
]];
605 * We dropped bitstring labels, and we don't support any
606 * other extended label types.
608 INSIST(count1
<= 63 && count2
<= 63);
610 cdiff
= (int)count1
- (int)count2
;
617 chdiff
= (int)maptolower
[*label1
] -
618 (int)maptolower
[*label2
];
636 namereln
= dns_namereln_contains
;
638 namereln
= dns_namereln_subdomain
;
640 namereln
= dns_namereln_equal
;
645 if (nlabels
> 0 && namereln
== dns_namereln_none
)
646 namereln
= dns_namereln_commonancestor
;
652 dns_name_compare(const dns_name_t
*name1
, const dns_name_t
*name2
) {
654 unsigned int nlabels
;
657 * Determine the relative ordering under the DNSSEC order relation of
658 * 'name1' and 'name2'.
660 * Note: It makes no sense for one of the names to be relative and the
661 * other absolute. If both names are relative, then to be meaningfully
662 * compared the caller must ensure that they are both relative to the
666 (void)dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
672 dns_name_equal(const dns_name_t
*name1
, const dns_name_t
*name2
) {
673 unsigned int l
, count
;
675 unsigned char *label1
, *label2
;
678 * Are 'name1' and 'name2' equal?
680 * Note: It makes no sense for one of the names to be relative and the
681 * other absolute. If both names are relative, then to be meaningfully
682 * compared the caller must ensure that they are both relative to the
686 REQUIRE(VALID_NAME(name1
));
687 REQUIRE(VALID_NAME(name2
));
689 * Either name1 is absolute and name2 is absolute, or neither is.
691 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) ==
692 (name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
));
694 if (name1
->length
!= name2
->length
)
699 if (l
!= name2
->labels
)
702 label1
= name1
->ndata
;
703 label2
= name2
->ndata
;
707 if (count
!= *label2
++)
710 INSIST(count
<= 63); /* no bitstring support */
714 c
= maptolower
[*label1
++];
715 if (c
!= maptolower
[*label2
++])
724 dns_name_caseequal(const dns_name_t
*name1
, const dns_name_t
*name2
) {
727 * Are 'name1' and 'name2' equal?
729 * Note: It makes no sense for one of the names to be relative and the
730 * other absolute. If both names are relative, then to be meaningfully
731 * compared the caller must ensure that they are both relative to the
735 REQUIRE(VALID_NAME(name1
));
736 REQUIRE(VALID_NAME(name2
));
738 * Either name1 is absolute and name2 is absolute, or neither is.
740 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) ==
741 (name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
));
743 if (name1
->length
!= name2
->length
)
746 if (memcmp(name1
->ndata
, name2
->ndata
, name1
->length
) != 0)
753 dns_name_rdatacompare(const dns_name_t
*name1
, const dns_name_t
*name2
) {
754 unsigned int l1
, l2
, l
, count1
, count2
, count
;
755 unsigned char c1
, c2
;
756 unsigned char *label1
, *label2
;
759 * Compare two absolute names as rdata.
762 REQUIRE(VALID_NAME(name1
));
763 REQUIRE(name1
->labels
> 0);
764 REQUIRE((name1
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
765 REQUIRE(VALID_NAME(name2
));
766 REQUIRE(name2
->labels
> 0);
767 REQUIRE((name2
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
772 l
= (l1
< l2
) ? l1
: l2
;
774 label1
= name1
->ndata
;
775 label2
= name2
->ndata
;
781 /* no bitstring support */
782 INSIST(count1
<= 63 && count2
<= 63);
784 if (count1
!= count2
)
785 return ((count1
< count2
) ? -1 : 1);
789 c1
= maptolower
[*label1
++];
790 c2
= maptolower
[*label2
++];
799 * If one name had more labels than the other, their common
800 * prefix must have been different because the shorter name
801 * ended with the root label and the longer one can't have
802 * a root label in the middle of it. Therefore, if we get
803 * to this point, the lengths must be equal.
811 dns_name_issubdomain(const dns_name_t
*name1
, const dns_name_t
*name2
) {
813 unsigned int nlabels
;
814 dns_namereln_t namereln
;
817 * Is 'name1' a subdomain of 'name2'?
819 * Note: It makes no sense for one of the names to be relative and the
820 * other absolute. If both names are relative, then to be meaningfully
821 * compared the caller must ensure that they are both relative to the
825 namereln
= dns_name_fullcompare(name1
, name2
, &order
, &nlabels
);
826 if (namereln
== dns_namereln_subdomain
||
827 namereln
== dns_namereln_equal
)
834 dns_name_matcheswildcard(const dns_name_t
*name
, const dns_name_t
*wname
) {
836 unsigned int nlabels
, labels
;
839 REQUIRE(VALID_NAME(name
));
840 REQUIRE(name
->labels
> 0);
841 REQUIRE(VALID_NAME(wname
));
842 labels
= wname
->labels
;
844 REQUIRE(dns_name_iswildcard(wname
));
846 DNS_NAME_INIT(&tname
, NULL
);
847 dns_name_getlabelsequence(wname
, 1, labels
- 1, &tname
);
848 if (dns_name_fullcompare(name
, &tname
, &order
, &nlabels
) ==
849 dns_namereln_subdomain
)
855 dns_name_countlabels(const dns_name_t
*name
) {
857 * How many labels does 'name' have?
860 REQUIRE(VALID_NAME(name
));
862 ENSURE(name
->labels
<= 128);
864 return (name
->labels
);
868 dns_name_getlabel(const dns_name_t
*name
, unsigned int n
, dns_label_t
*label
) {
869 unsigned char *offsets
;
873 * Make 'label' refer to the 'n'th least significant label of 'name'.
876 REQUIRE(VALID_NAME(name
));
877 REQUIRE(name
->labels
> 0);
878 REQUIRE(n
< name
->labels
);
879 REQUIRE(label
!= NULL
);
881 SETUP_OFFSETS(name
, offsets
, odata
);
883 label
->base
= &name
->ndata
[offsets
[n
]];
884 if (n
== name
->labels
- 1)
885 label
->length
= name
->length
- offsets
[n
];
887 label
->length
= offsets
[n
+ 1] - offsets
[n
];
891 dns_name_getlabelsequence(const dns_name_t
*source
,
892 unsigned int first
, unsigned int n
,
895 unsigned char *offsets
;
897 unsigned int firstoffset
, endoffset
;
900 * Make 'target' refer to the 'n' labels including and following
901 * 'first' in 'source'.
904 REQUIRE(VALID_NAME(source
));
905 REQUIRE(VALID_NAME(target
));
906 REQUIRE(first
<= source
->labels
);
907 REQUIRE(first
+ n
<= source
->labels
);
908 REQUIRE(BINDABLE(target
));
910 SETUP_OFFSETS(source
, offsets
, odata
);
912 if (first
== source
->labels
)
913 firstoffset
= source
->length
;
915 firstoffset
= offsets
[first
];
917 if (first
+ n
== source
->labels
)
918 endoffset
= source
->length
;
920 endoffset
= offsets
[first
+ n
];
922 target
->ndata
= &source
->ndata
[firstoffset
];
923 target
->length
= endoffset
- firstoffset
;
925 if (first
+ n
== source
->labels
&& n
> 0 &&
926 (source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
927 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
929 target
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
934 * If source and target are the same, and we're making target
935 * a prefix of source, the offsets table is correct already
936 * so we don't need to call set_offsets().
938 if (target
->offsets
!= NULL
&&
939 (target
!= source
|| first
!= 0))
940 set_offsets(target
, target
->offsets
, NULL
);
944 dns_name_clone(const dns_name_t
*source
, dns_name_t
*target
) {
947 * Make 'target' refer to the same name as 'source'.
950 REQUIRE(VALID_NAME(source
));
951 REQUIRE(VALID_NAME(target
));
952 REQUIRE(BINDABLE(target
));
954 target
->ndata
= source
->ndata
;
955 target
->length
= source
->length
;
956 target
->labels
= source
->labels
;
957 target
->attributes
= source
->attributes
&
958 (unsigned int)~(DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_DYNAMIC
|
959 DNS_NAMEATTR_DYNOFFSETS
);
960 if (target
->offsets
!= NULL
&& source
->labels
> 0) {
961 if (source
->offsets
!= NULL
)
962 memcpy(target
->offsets
, source
->offsets
,
965 set_offsets(target
, target
->offsets
, NULL
);
970 dns_name_fromregion(dns_name_t
*name
, const isc_region_t
*r
) {
971 unsigned char *offsets
;
977 * Make 'name' refer to region 'r'.
980 REQUIRE(VALID_NAME(name
));
982 REQUIRE(BINDABLE(name
));
984 INIT_OFFSETS(name
, offsets
, odata
);
986 if (name
->buffer
!= NULL
) {
987 isc_buffer_clear(name
->buffer
);
988 isc_buffer_availableregion(name
->buffer
, &r2
);
989 len
= (r
->length
< r2
.length
) ? r
->length
: r2
.length
;
990 if (len
> DNS_NAME_MAXWIRE
)
991 len
= DNS_NAME_MAXWIRE
;
992 memcpy(r2
.base
, r
->base
, len
);
993 name
->ndata
= r2
.base
;
996 name
->ndata
= r
->base
;
997 name
->length
= (r
->length
<= DNS_NAME_MAXWIRE
) ?
998 r
->length
: DNS_NAME_MAXWIRE
;
1002 set_offsets(name
, offsets
, name
);
1005 name
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
1008 if (name
->buffer
!= NULL
)
1009 isc_buffer_add(name
->buffer
, name
->length
);
1013 dns_name_toregion(dns_name_t
*name
, isc_region_t
*r
) {
1015 * Make 'r' refer to 'name'.
1018 REQUIRE(VALID_NAME(name
));
1021 DNS_NAME_TOREGION(name
, r
);
1025 dns_name_fromtext(dns_name_t
*name
, isc_buffer_t
*source
,
1026 dns_name_t
*origin
, unsigned int options
,
1027 isc_buffer_t
*target
)
1029 unsigned char *ndata
, *label
;
1033 unsigned int value
, count
;
1034 unsigned int n1
, n2
, tlen
, nrem
, nused
, digits
, labels
, tused
;
1036 unsigned char *offsets
;
1037 dns_offsets_t odata
;
1038 isc_boolean_t downcase
;
1041 * Convert the textual representation of a DNS name at source
1042 * into uncompressed wire form stored in target.
1045 * Relative domain names will have 'origin' appended to them
1046 * unless 'origin' is NULL, in which case relative domain names
1047 * will remain relative.
1050 REQUIRE(VALID_NAME(name
));
1051 REQUIRE(ISC_BUFFER_VALID(source
));
1052 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1053 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1055 downcase
= ISC_TF((options
& DNS_NAME_DOWNCASE
) != 0);
1057 if (target
== NULL
&& name
->buffer
!= NULL
) {
1058 target
= name
->buffer
;
1059 isc_buffer_clear(target
);
1062 REQUIRE(BINDABLE(name
));
1064 INIT_OFFSETS(name
, offsets
, odata
);
1068 * Initialize things to make the compiler happy; they're not required.
1078 * Make 'name' empty in case of failure.
1083 * Set up the state machine.
1085 tdata
= (char *)source
->base
+ source
->current
;
1086 tlen
= isc_buffer_remaininglength(source
);
1088 ndata
= isc_buffer_used(target
);
1089 nrem
= isc_buffer_availablelength(target
);
1097 while (nrem
> 0 && tlen
> 0 && !done
) {
1105 * Is this the root name?
1109 return (DNS_R_EMPTYLABEL
);
1117 if (c
== '@' && tlen
== 0) {
1130 state
= ft_initialescape
;
1133 state
= ft_ordinary
;
1135 return (ISC_R_NOSPACE
);
1140 return (DNS_R_EMPTYLABEL
);
1143 INSIST(labels
<= 127);
1144 offsets
[labels
] = nused
;
1153 } else if (c
== '\\') {
1157 return (DNS_R_LABELTOOLONG
);
1161 c
= maptolower
[(int)c
];
1167 case ft_initialescape
:
1170 * This looks like a bitstring label, which
1171 * was deprecated. Intentionally drop it.
1173 return (DNS_R_BADLABELTYPE
);
1178 if (!isdigit(c
& 0xff)) {
1180 return (DNS_R_LABELTOOLONG
);
1184 c
= maptolower
[(int)c
];
1188 state
= ft_ordinary
;
1193 state
= ft_escdecimal
;
1196 if (!isdigit(c
& 0xff))
1197 return (DNS_R_BADESCAPE
);
1199 value
+= digitvalue
[(int)c
];
1203 return (DNS_R_BADESCAPE
);
1205 return (DNS_R_LABELTOOLONG
);
1208 value
= maptolower
[value
];
1212 state
= ft_ordinary
;
1216 FATAL_ERROR(__FILE__
, __LINE__
,
1217 "Unexpected state %d", state
);
1218 /* Does not return. */
1224 return (ISC_R_NOSPACE
);
1226 if (state
!= ft_ordinary
&& state
!= ft_at
)
1227 return (ISC_R_UNEXPECTEDEND
);
1228 if (state
== ft_ordinary
) {
1232 INSIST(labels
<= 127);
1233 offsets
[labels
] = nused
;
1235 if (origin
!= NULL
) {
1236 if (nrem
< origin
->length
)
1237 return (ISC_R_NOSPACE
);
1238 label
= origin
->ndata
;
1239 n1
= origin
->length
;
1243 INSIST(n2
<= 63); /* no bitstring support */
1250 c
= maptolower
[(int)c
];
1256 INSIST(labels
<= 127);
1257 offsets
[labels
] = nused
;
1260 if ((origin
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
1261 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1264 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1266 name
->ndata
= (unsigned char *)target
->base
+ target
->used
;
1267 name
->labels
= labels
;
1268 name
->length
= nused
;
1270 isc_buffer_forward(source
, tused
);
1271 isc_buffer_add(target
, name
->length
);
1273 return (ISC_R_SUCCESS
);
1276 #ifdef ISC_PLATFORM_USETHREADS
1278 free_specific(void *arg
) {
1279 dns_name_totextfilter_t
*mem
= arg
;
1280 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
1281 /* Stop use being called again. */
1282 (void)isc_thread_key_setspecific(totext_filter_proc_key
, NULL
);
1286 thread_key_mutex_init(void) {
1287 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex
) == ISC_R_SUCCESS
);
1291 totext_filter_proc_key_init(void) {
1292 isc_result_t result
;
1295 * We need the call to isc_once_do() to support profiled mutex
1296 * otherwise thread_key_mutex could be initialized at compile time.
1298 result
= isc_once_do(&once
, thread_key_mutex_init
);
1299 if (result
!= ISC_R_SUCCESS
)
1302 if (!thread_key_initialized
) {
1303 LOCK(&thread_key_mutex
);
1304 if (thread_key_mctx
== NULL
)
1305 result
= isc_mem_create2(0, 0, &thread_key_mctx
, 0);
1306 if (result
!= ISC_R_SUCCESS
)
1308 isc_mem_setname(thread_key_mctx
, "threadkey", NULL
);
1309 isc_mem_setdestroycheck(thread_key_mctx
, ISC_FALSE
);
1311 if (!thread_key_initialized
&&
1312 isc_thread_key_create(&totext_filter_proc_key
,
1313 free_specific
) != 0) {
1314 result
= ISC_R_FAILURE
;
1315 isc_mem_detach(&thread_key_mctx
);
1317 thread_key_initialized
= 1;
1319 UNLOCK(&thread_key_mutex
);
1326 dns_name_totext(dns_name_t
*name
, isc_boolean_t omit_final_dot
,
1327 isc_buffer_t
*target
)
1329 unsigned char *ndata
;
1331 unsigned int nlen
, tlen
;
1333 unsigned int trem
, count
;
1334 unsigned int labels
;
1335 isc_boolean_t saw_root
= ISC_FALSE
;
1336 unsigned int oused
= target
->used
;
1337 #ifdef ISC_PLATFORM_USETHREADS
1338 dns_name_totextfilter_t
*mem
;
1339 dns_name_totextfilter_t totext_filter_proc
= NULL
;
1340 isc_result_t result
;
1344 * This function assumes the name is in proper uncompressed
1347 REQUIRE(VALID_NAME(name
));
1348 REQUIRE(ISC_BUFFER_VALID(target
));
1350 #ifdef ISC_PLATFORM_USETHREADS
1351 result
= totext_filter_proc_key_init();
1352 if (result
!= ISC_R_SUCCESS
)
1355 ndata
= name
->ndata
;
1356 nlen
= name
->length
;
1357 labels
= name
->labels
;
1358 tdata
= isc_buffer_used(target
);
1359 tlen
= isc_buffer_availablelength(target
);
1363 if (labels
== 0 && nlen
== 0) {
1365 * Special handling for an empty name.
1368 return (ISC_R_NOSPACE
);
1371 * The names of these booleans are misleading in this case.
1372 * This empty name is not necessarily from the root node of
1373 * the DNS root zone, nor is a final dot going to be included.
1374 * They need to be set this way, though, to keep the "@"
1375 * from being trounced.
1377 saw_root
= ISC_TRUE
;
1378 omit_final_dot
= ISC_FALSE
;
1383 * Skip the while() loop.
1386 } else if (nlen
== 1 && labels
== 1 && *ndata
== '\0') {
1388 * Special handling for the root label.
1391 return (ISC_R_NOSPACE
);
1393 saw_root
= ISC_TRUE
;
1394 omit_final_dot
= ISC_FALSE
;
1399 * Skip the while() loop.
1404 while (labels
> 0 && nlen
> 0 && trem
> 0) {
1409 saw_root
= ISC_TRUE
;
1413 INSIST(nlen
>= count
);
1417 case 0x22: /* '"' */
1418 case 0x28: /* '(' */
1419 case 0x29: /* ')' */
1420 case 0x2E: /* '.' */
1421 case 0x3B: /* ';' */
1422 case 0x5C: /* '\\' */
1423 /* Special modifiers in zone files. */
1424 case 0x40: /* '@' */
1425 case 0x24: /* '$' */
1427 return (ISC_R_NOSPACE
);
1429 CONVERTFROMASCII(c
);
1436 if (c
> 0x20 && c
< 0x7f) {
1438 return (ISC_R_NOSPACE
);
1439 CONVERTFROMASCII(c
);
1446 return (ISC_R_NOSPACE
);
1452 *tdata
++ = 0x30 + (c
% 10);
1461 FATAL_ERROR(__FILE__
, __LINE__
,
1462 "Unexpected label type %02x", count
);
1467 * The following assumes names are absolute. If not, we
1468 * fix things up later. Note that this means that in some
1469 * cases one more byte of text buffer is required than is
1470 * needed in the final output.
1473 return (ISC_R_NOSPACE
);
1478 if (nlen
!= 0 && trem
== 0)
1479 return (ISC_R_NOSPACE
);
1481 if (!saw_root
|| omit_final_dot
)
1484 isc_buffer_add(target
, tlen
- trem
);
1486 #ifdef ISC_PLATFORM_USETHREADS
1487 mem
= isc_thread_key_getspecific(totext_filter_proc_key
);
1489 totext_filter_proc
= *mem
;
1491 if (totext_filter_proc
!= NULL
)
1492 return ((*totext_filter_proc
)(target
, oused
, saw_root
));
1494 return (ISC_R_SUCCESS
);
1498 dns_name_tofilenametext(dns_name_t
*name
, isc_boolean_t omit_final_dot
,
1499 isc_buffer_t
*target
)
1501 unsigned char *ndata
;
1503 unsigned int nlen
, tlen
;
1505 unsigned int trem
, count
;
1506 unsigned int labels
;
1509 * This function assumes the name is in proper uncompressed
1512 REQUIRE(VALID_NAME(name
));
1513 REQUIRE((name
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0);
1514 REQUIRE(ISC_BUFFER_VALID(target
));
1516 ndata
= name
->ndata
;
1517 nlen
= name
->length
;
1518 labels
= name
->labels
;
1519 tdata
= isc_buffer_used(target
);
1520 tlen
= isc_buffer_availablelength(target
);
1524 if (nlen
== 1 && labels
== 1 && *ndata
== '\0') {
1526 * Special handling for the root label.
1529 return (ISC_R_NOSPACE
);
1531 omit_final_dot
= ISC_FALSE
;
1536 * Skip the while() loop.
1541 while (labels
> 0 && nlen
> 0 && trem
> 0) {
1548 INSIST(nlen
>= count
);
1551 if ((c
>= 0x30 && c
<= 0x39) || /* digit */
1552 (c
>= 0x41 && c
<= 0x5A) || /* uppercase */
1553 (c
>= 0x61 && c
<= 0x7A) || /* lowercase */
1554 c
== 0x2D || /* hyphen */
1555 c
== 0x5F) /* underscore */
1558 return (ISC_R_NOSPACE
);
1560 if (c
>= 0x41 && c
<= 0x5A)
1562 CONVERTFROMASCII(c
);
1569 return (ISC_R_NOSPACE
);
1570 sprintf(tdata
, "%%%02X", c
);
1579 FATAL_ERROR(__FILE__
, __LINE__
,
1580 "Unexpected label type %02x", count
);
1585 * The following assumes names are absolute. If not, we
1586 * fix things up later. Note that this means that in some
1587 * cases one more byte of text buffer is required than is
1588 * needed in the final output.
1591 return (ISC_R_NOSPACE
);
1596 if (nlen
!= 0 && trem
== 0)
1597 return (ISC_R_NOSPACE
);
1602 isc_buffer_add(target
, tlen
- trem
);
1604 return (ISC_R_SUCCESS
);
1608 dns_name_downcase(dns_name_t
*source
, dns_name_t
*name
, isc_buffer_t
*target
) {
1609 unsigned char *sndata
, *ndata
;
1610 unsigned int nlen
, count
, labels
;
1611 isc_buffer_t buffer
;
1614 * Downcase 'source'.
1617 REQUIRE(VALID_NAME(source
));
1618 REQUIRE(VALID_NAME(name
));
1619 if (source
== name
) {
1620 REQUIRE((name
->attributes
& DNS_NAMEATTR_READONLY
) == 0);
1621 isc_buffer_init(&buffer
, source
->ndata
, source
->length
);
1623 ndata
= source
->ndata
;
1625 REQUIRE(BINDABLE(name
));
1626 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1627 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1628 if (target
== NULL
) {
1629 target
= name
->buffer
;
1630 isc_buffer_clear(name
->buffer
);
1632 ndata
= (unsigned char *)target
->base
+ target
->used
;
1633 name
->ndata
= ndata
;
1636 sndata
= source
->ndata
;
1637 nlen
= source
->length
;
1638 labels
= source
->labels
;
1640 if (nlen
> (target
->length
- target
->used
)) {
1642 return (ISC_R_NOSPACE
);
1645 while (labels
> 0 && nlen
> 0) {
1651 INSIST(nlen
>= count
);
1653 *ndata
++ = maptolower
[(*sndata
++)];
1658 FATAL_ERROR(__FILE__
, __LINE__
,
1659 "Unexpected label type %02x", count
);
1660 /* Does not return. */
1664 if (source
!= name
) {
1665 name
->labels
= source
->labels
;
1666 name
->length
= source
->length
;
1667 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
1668 name
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
1670 name
->attributes
= 0;
1671 if (name
->labels
> 0 && name
->offsets
!= NULL
)
1672 set_offsets(name
, name
->offsets
, NULL
);
1675 isc_buffer_add(target
, name
->length
);
1677 return (ISC_R_SUCCESS
);
1681 set_offsets(const dns_name_t
*name
, unsigned char *offsets
,
1682 dns_name_t
*set_name
)
1684 unsigned int offset
, count
, length
, nlabels
;
1685 unsigned char *ndata
;
1686 isc_boolean_t absolute
;
1688 ndata
= name
->ndata
;
1689 length
= name
->length
;
1692 absolute
= ISC_FALSE
;
1693 while (offset
!= length
) {
1694 INSIST(nlabels
< 128);
1695 offsets
[nlabels
++] = offset
;
1698 INSIST(count
<= 63);
1701 INSIST(offset
<= length
);
1703 absolute
= ISC_TRUE
;
1707 if (set_name
!= NULL
) {
1708 INSIST(set_name
== name
);
1710 set_name
->labels
= nlabels
;
1711 set_name
->length
= offset
;
1713 set_name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1715 set_name
->attributes
&= ~DNS_NAMEATTR_ABSOLUTE
;
1717 INSIST(nlabels
== name
->labels
);
1718 INSIST(offset
== name
->length
);
1722 dns_name_fromwire(dns_name_t
*name
, isc_buffer_t
*source
,
1723 dns_decompress_t
*dctx
, unsigned int options
,
1724 isc_buffer_t
*target
)
1726 unsigned char *cdata
, *ndata
;
1727 unsigned int cused
; /* Bytes of compressed name data used */
1728 unsigned int nused
, labels
, n
, nmax
;
1729 unsigned int current
, new_current
, biggest_pointer
;
1731 fw_state state
= fw_start
;
1733 unsigned char *offsets
;
1734 dns_offsets_t odata
;
1735 isc_boolean_t downcase
;
1736 isc_boolean_t seen_pointer
;
1739 * Copy the possibly-compressed name at source into target,
1740 * decompressing it. Loop prevention is performed by checking
1741 * the new pointer against biggest_pointer.
1744 REQUIRE(VALID_NAME(name
));
1745 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1746 (target
== NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1748 downcase
= ISC_TF((options
& DNS_NAME_DOWNCASE
) != 0);
1750 if (target
== NULL
&& name
->buffer
!= NULL
) {
1751 target
= name
->buffer
;
1752 isc_buffer_clear(target
);
1755 REQUIRE(dctx
!= NULL
);
1756 REQUIRE(BINDABLE(name
));
1758 INIT_OFFSETS(name
, offsets
, odata
);
1761 * Make 'name' empty in case of failure.
1766 * Initialize things to make the compiler happy; they're not required.
1777 ndata
= isc_buffer_used(target
);
1779 seen_pointer
= ISC_FALSE
;
1782 * Find the maximum number of uncompressed target name
1783 * bytes we are willing to generate. This is the smaller
1784 * of the available target buffer length and the
1785 * maximum legal domain name length (255).
1787 nmax
= isc_buffer_availablelength(target
);
1788 if (nmax
> DNS_NAME_MAXWIRE
)
1789 nmax
= DNS_NAME_MAXWIRE
;
1791 cdata
= isc_buffer_current(source
);
1794 current
= source
->current
;
1795 biggest_pointer
= current
;
1798 * Note: The following code is not optimized for speed, but
1799 * rather for correctness. Speed will be addressed in the future.
1802 while (current
< source
->active
&& !done
) {
1811 offsets
[labels
] = nused
;
1813 if (nused
+ c
+ 1 > nmax
)
1820 state
= fw_ordinary
;
1821 } else if (c
>= 128 && c
< 192) {
1823 * 14 bit local compression pointer.
1824 * Local compression is no longer an
1827 return (DNS_R_BADLABELTYPE
);
1828 } else if (c
>= 192) {
1830 * Ordinary 14-bit pointer.
1832 if ((dctx
->allowed
& DNS_COMPRESS_GLOBAL14
) ==
1834 return (DNS_R_DISALLOWED
);
1835 new_current
= c
& 0x3F;
1837 state
= fw_newcurrent
;
1839 return (DNS_R_BADLABELTYPE
);
1857 if (new_current
>= biggest_pointer
)
1858 return (DNS_R_BADPOINTER
);
1859 biggest_pointer
= new_current
;
1860 current
= new_current
;
1861 cdata
= (unsigned char *)source
->base
+ current
;
1862 seen_pointer
= ISC_TRUE
;
1866 FATAL_ERROR(__FILE__
, __LINE__
,
1867 "Unknown state %d", state
);
1868 /* Does not return. */
1873 return (ISC_R_UNEXPECTEDEND
);
1875 name
->ndata
= (unsigned char *)target
->base
+ target
->used
;
1876 name
->labels
= labels
;
1877 name
->length
= nused
;
1878 name
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
1880 isc_buffer_forward(source
, cused
);
1881 isc_buffer_add(target
, name
->length
);
1883 return (ISC_R_SUCCESS
);
1886 if (nmax
== DNS_NAME_MAXWIRE
)
1888 * The name did not fit even though we had a buffer
1889 * big enough to fit a maximum-length name.
1891 return (DNS_R_NAMETOOLONG
);
1894 * The name might fit if only the caller could give us a
1895 * big enough buffer.
1897 return (ISC_R_NOSPACE
);
1901 dns_name_towire(const dns_name_t
*name
, dns_compress_t
*cctx
,
1902 isc_buffer_t
*target
)
1904 unsigned int methods
;
1905 isc_uint16_t offset
;
1906 dns_name_t gp
; /* Global compression prefix */
1907 isc_boolean_t gf
; /* Global compression target found */
1908 isc_uint16_t go
; /* Global compression offset */
1913 * Convert 'name' into wire format, compressing it as specified by the
1914 * compression context 'cctx', and storing the result in 'target'.
1917 REQUIRE(VALID_NAME(name
));
1918 REQUIRE(cctx
!= NULL
);
1919 REQUIRE(ISC_BUFFER_VALID(target
));
1922 * If 'name' doesn't have an offsets table, make a clone which
1925 if (name
->offsets
== NULL
) {
1926 DNS_NAME_INIT(&clname
, clo
);
1927 dns_name_clone(name
, &clname
);
1930 DNS_NAME_INIT(&gp
, NULL
);
1932 offset
= target
->used
; /*XXX*/
1934 methods
= dns_compress_getmethods(cctx
);
1936 if ((name
->attributes
& DNS_NAMEATTR_NOCOMPRESS
) == 0 &&
1937 (methods
& DNS_COMPRESS_GLOBAL14
) != 0)
1938 gf
= dns_compress_findglobal(cctx
, name
, &gp
, &go
);
1943 * If the offset is too high for 14 bit global compression, we're
1946 if (gf
&& go
>= 0x4000)
1950 * Will the compression pointer reduce the message size?
1952 if (gf
&& (gp
.length
+ 2) >= name
->length
)
1956 if (target
->length
- target
->used
< gp
.length
)
1957 return (ISC_R_NOSPACE
);
1958 (void)memcpy((unsigned char *)target
->base
+ target
->used
,
1959 gp
.ndata
, (size_t)gp
.length
);
1960 isc_buffer_add(target
, gp
.length
);
1962 if (target
->length
- target
->used
< 2)
1963 return (ISC_R_NOSPACE
);
1964 isc_buffer_putuint16(target
, go
);
1966 dns_compress_add(cctx
, name
, &gp
, offset
);
1968 if (target
->length
- target
->used
< name
->length
)
1969 return (ISC_R_NOSPACE
);
1970 (void)memcpy((unsigned char *)target
->base
+ target
->used
,
1971 name
->ndata
, (size_t)name
->length
);
1972 isc_buffer_add(target
, name
->length
);
1973 dns_compress_add(cctx
, name
, name
, offset
);
1975 return (ISC_R_SUCCESS
);
1979 dns_name_concatenate(dns_name_t
*prefix
, dns_name_t
*suffix
, dns_name_t
*name
,
1980 isc_buffer_t
*target
)
1982 unsigned char *ndata
, *offsets
;
1983 unsigned int nrem
, labels
, prefix_length
, length
;
1984 isc_boolean_t copy_prefix
= ISC_TRUE
;
1985 isc_boolean_t copy_suffix
= ISC_TRUE
;
1986 isc_boolean_t absolute
= ISC_FALSE
;
1987 dns_name_t tmp_name
;
1988 dns_offsets_t odata
;
1991 * Concatenate 'prefix' and 'suffix'.
1994 REQUIRE(prefix
== NULL
|| VALID_NAME(prefix
));
1995 REQUIRE(suffix
== NULL
|| VALID_NAME(suffix
));
1996 REQUIRE(name
== NULL
|| VALID_NAME(name
));
1997 REQUIRE((target
!= NULL
&& ISC_BUFFER_VALID(target
)) ||
1998 (target
== NULL
&& name
!= NULL
&& ISC_BUFFER_VALID(name
->buffer
)));
1999 if (prefix
== NULL
|| prefix
->labels
== 0)
2000 copy_prefix
= ISC_FALSE
;
2001 if (suffix
== NULL
|| suffix
->labels
== 0)
2002 copy_suffix
= ISC_FALSE
;
2004 (prefix
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0) {
2005 absolute
= ISC_TRUE
;
2006 REQUIRE(!copy_suffix
);
2009 DNS_NAME_INIT(&tmp_name
, odata
);
2012 if (target
== NULL
) {
2013 INSIST(name
->buffer
!= NULL
);
2014 target
= name
->buffer
;
2015 isc_buffer_clear(name
->buffer
);
2018 REQUIRE(BINDABLE(name
));
2023 nrem
= target
->length
- target
->used
;
2024 ndata
= (unsigned char *)target
->base
+ target
->used
;
2025 if (nrem
> DNS_NAME_MAXWIRE
)
2026 nrem
= DNS_NAME_MAXWIRE
;
2031 prefix_length
= prefix
->length
;
2032 length
+= prefix_length
;
2033 labels
+= prefix
->labels
;
2036 length
+= suffix
->length
;
2037 labels
+= suffix
->labels
;
2039 if (length
> DNS_NAME_MAXWIRE
) {
2041 return (DNS_R_NAMETOOLONG
);
2043 if (length
> nrem
) {
2045 return (ISC_R_NOSPACE
);
2049 if ((suffix
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2050 absolute
= ISC_TRUE
;
2051 if (suffix
== name
&& suffix
->buffer
== target
)
2052 memmove(ndata
+ prefix_length
, suffix
->ndata
,
2055 memcpy(ndata
+ prefix_length
, suffix
->ndata
,
2060 * If 'prefix' and 'name' are the same object, and the object has
2061 * a dedicated buffer, and we're using it, then we don't have to
2064 if (copy_prefix
&& (prefix
!= name
|| prefix
->buffer
!= target
))
2065 memcpy(ndata
, prefix
->ndata
, prefix_length
);
2067 name
->ndata
= ndata
;
2068 name
->labels
= labels
;
2069 name
->length
= length
;
2071 name
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
2073 name
->attributes
= 0;
2075 if (name
->labels
> 0 && name
->offsets
!= NULL
) {
2076 INIT_OFFSETS(name
, offsets
, odata
);
2077 set_offsets(name
, offsets
, NULL
);
2080 isc_buffer_add(target
, name
->length
);
2082 return (ISC_R_SUCCESS
);
2086 dns_name_split(dns_name_t
*name
, unsigned int suffixlabels
,
2087 dns_name_t
*prefix
, dns_name_t
*suffix
)
2090 unsigned int splitlabel
;
2092 REQUIRE(VALID_NAME(name
));
2093 REQUIRE(suffixlabels
> 0);
2094 REQUIRE(suffixlabels
< name
->labels
);
2095 REQUIRE(prefix
!= NULL
|| suffix
!= NULL
);
2096 REQUIRE(prefix
== NULL
||
2097 (VALID_NAME(prefix
) &&
2098 prefix
->buffer
!= NULL
&&
2100 REQUIRE(suffix
== NULL
||
2101 (VALID_NAME(suffix
) &&
2102 suffix
->buffer
!= NULL
&&
2105 splitlabel
= name
->labels
- suffixlabels
;
2108 dns_name_getlabelsequence(name
, 0, splitlabel
, prefix
);
2111 dns_name_getlabelsequence(name
, splitlabel
,
2112 suffixlabels
, suffix
);
2118 dns_name_dup(const dns_name_t
*source
, isc_mem_t
*mctx
,
2122 * Make 'target' a dynamically allocated copy of 'source'.
2125 REQUIRE(VALID_NAME(source
));
2126 REQUIRE(source
->length
> 0);
2127 REQUIRE(VALID_NAME(target
));
2128 REQUIRE(BINDABLE(target
));
2131 * Make 'target' empty in case of failure.
2135 target
->ndata
= isc_mem_get(mctx
, source
->length
);
2136 if (target
->ndata
== NULL
)
2137 return (ISC_R_NOMEMORY
);
2139 memcpy(target
->ndata
, source
->ndata
, source
->length
);
2141 target
->length
= source
->length
;
2142 target
->labels
= source
->labels
;
2143 target
->attributes
= DNS_NAMEATTR_DYNAMIC
;
2144 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2145 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
2146 if (target
->offsets
!= NULL
) {
2147 if (source
->offsets
!= NULL
)
2148 memcpy(target
->offsets
, source
->offsets
,
2151 set_offsets(target
, target
->offsets
, NULL
);
2154 return (ISC_R_SUCCESS
);
2158 dns_name_dupwithoffsets(dns_name_t
*source
, isc_mem_t
*mctx
,
2162 * Make 'target' a read-only dynamically allocated copy of 'source'.
2163 * 'target' will also have a dynamically allocated offsets table.
2166 REQUIRE(VALID_NAME(source
));
2167 REQUIRE(source
->length
> 0);
2168 REQUIRE(VALID_NAME(target
));
2169 REQUIRE(BINDABLE(target
));
2170 REQUIRE(target
->offsets
== NULL
);
2173 * Make 'target' empty in case of failure.
2177 target
->ndata
= isc_mem_get(mctx
, source
->length
+ source
->labels
);
2178 if (target
->ndata
== NULL
)
2179 return (ISC_R_NOMEMORY
);
2181 memcpy(target
->ndata
, source
->ndata
, source
->length
);
2183 target
->length
= source
->length
;
2184 target
->labels
= source
->labels
;
2185 target
->attributes
= DNS_NAMEATTR_DYNAMIC
| DNS_NAMEATTR_DYNOFFSETS
|
2186 DNS_NAMEATTR_READONLY
;
2187 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2188 target
->attributes
|= DNS_NAMEATTR_ABSOLUTE
;
2189 target
->offsets
= target
->ndata
+ source
->length
;
2190 if (source
->offsets
!= NULL
)
2191 memcpy(target
->offsets
, source
->offsets
, source
->labels
);
2193 set_offsets(target
, target
->offsets
, NULL
);
2195 return (ISC_R_SUCCESS
);
2199 dns_name_free(dns_name_t
*name
, isc_mem_t
*mctx
) {
2206 REQUIRE(VALID_NAME(name
));
2207 REQUIRE((name
->attributes
& DNS_NAMEATTR_DYNAMIC
) != 0);
2209 size
= name
->length
;
2210 if ((name
->attributes
& DNS_NAMEATTR_DYNOFFSETS
) != 0)
2211 size
+= name
->labels
;
2212 isc_mem_put(mctx
, name
->ndata
, size
);
2213 dns_name_invalidate(name
);
2217 dns_name_digest(dns_name_t
*name
, dns_digestfunc_t digest
, void *arg
) {
2218 dns_name_t downname
;
2219 unsigned char data
[256];
2220 isc_buffer_t buffer
;
2221 isc_result_t result
;
2225 * Send 'name' in DNSSEC canonical form to 'digest'.
2228 REQUIRE(VALID_NAME(name
));
2229 REQUIRE(digest
!= NULL
);
2231 DNS_NAME_INIT(&downname
, NULL
);
2232 isc_buffer_init(&buffer
, data
, sizeof(data
));
2234 result
= dns_name_downcase(name
, &downname
, &buffer
);
2235 if (result
!= ISC_R_SUCCESS
)
2238 isc_buffer_usedregion(&buffer
, &r
);
2240 return ((digest
)(arg
, &r
));
2244 dns_name_dynamic(dns_name_t
*name
) {
2245 REQUIRE(VALID_NAME(name
));
2248 * Returns whether there is dynamic memory associated with this name.
2251 return ((name
->attributes
& DNS_NAMEATTR_DYNAMIC
) != 0 ?
2252 ISC_TRUE
: ISC_FALSE
);
2256 dns_name_print(dns_name_t
*name
, FILE *stream
) {
2257 isc_result_t result
;
2263 * Print 'name' on 'stream'.
2266 REQUIRE(VALID_NAME(name
));
2268 isc_buffer_init(&b
, t
, sizeof(t
));
2269 result
= dns_name_totext(name
, ISC_FALSE
, &b
);
2270 if (result
!= ISC_R_SUCCESS
)
2272 isc_buffer_usedregion(&b
, &r
);
2273 fprintf(stream
, "%.*s", (int)r
.length
, (char *)r
.base
);
2275 return (ISC_R_SUCCESS
);
2279 dns_name_settotextfilter(dns_name_totextfilter_t proc
) {
2280 #ifdef ISC_PLATFORM_USETHREADS
2281 isc_result_t result
;
2282 dns_name_totextfilter_t
*mem
;
2285 result
= totext_filter_proc_key_init();
2286 if (result
!= ISC_R_SUCCESS
)
2290 * If we already have been here set / clear as appropriate.
2291 * Otherwise allocate memory.
2293 mem
= isc_thread_key_getspecific(totext_filter_proc_key
);
2294 if (mem
!= NULL
&& proc
!= NULL
) {
2296 return (ISC_R_SUCCESS
);
2299 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
2300 res
= isc_thread_key_setspecific(totext_filter_proc_key
, NULL
);
2302 result
= ISC_R_UNEXPECTED
;
2306 mem
= isc_mem_get(thread_key_mctx
, sizeof(*mem
));
2308 return (ISC_R_NOMEMORY
);
2310 if (isc_thread_key_setspecific(totext_filter_proc_key
, mem
) != 0) {
2311 isc_mem_put(thread_key_mctx
, mem
, sizeof(*mem
));
2312 result
= ISC_R_UNEXPECTED
;
2316 totext_filter_proc
= proc
;
2317 return (ISC_R_SUCCESS
);
2322 dns_name_format(dns_name_t
*name
, char *cp
, unsigned int size
) {
2323 isc_result_t result
;
2329 * Leave room for null termination after buffer.
2331 isc_buffer_init(&buf
, cp
, size
- 1);
2332 result
= dns_name_totext(name
, ISC_TRUE
, &buf
);
2333 if (result
== ISC_R_SUCCESS
) {
2338 isc_buffer_usedregion(&buf
, &r
);
2339 ((char *) r
.base
)[r
.length
] = '\0';
2342 snprintf(cp
, size
, "<unknown>");
2346 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2350 dns_name_tostring(dns_name_t
*name
, char **target
, isc_mem_t
*mctx
) {
2351 isc_result_t result
;
2354 char *p
, txt
[DNS_NAME_FORMATSIZE
];
2356 REQUIRE(VALID_NAME(name
));
2357 REQUIRE(target
!= NULL
&& *target
== NULL
);
2359 isc_buffer_init(&buf
, txt
, sizeof(txt
));
2360 result
= dns_name_totext(name
, ISC_FALSE
, &buf
);
2361 if (result
!= ISC_R_SUCCESS
)
2364 isc_buffer_usedregion(&buf
, ®
);
2365 p
= isc_mem_allocate(mctx
, reg
.length
+ 1);
2366 memcpy(p
, (char *) reg
.base
, (int) reg
.length
);
2367 p
[reg
.length
] = '\0';
2370 return (ISC_R_SUCCESS
);
2374 * dns_name_fromstring() -- convert directly from a string to a name,
2375 * allocating memory as needed
2378 dns_name_fromstring(dns_name_t
*target
, const char *src
, unsigned int options
,
2381 isc_result_t result
;
2386 REQUIRE(src
!= NULL
);
2388 isc_buffer_init(&buf
, src
, strlen(src
));
2389 isc_buffer_add(&buf
, strlen(src
));
2390 dns_fixedname_init(&fn
);
2391 name
= dns_fixedname_name(&fn
);
2393 result
= dns_name_fromtext(name
, &buf
, dns_rootname
, options
, NULL
);
2394 if (result
!= ISC_R_SUCCESS
)
2397 result
= dns_name_dup(name
, mctx
, target
);
2402 dns_name_copy(dns_name_t
*source
, dns_name_t
*dest
, isc_buffer_t
*target
) {
2403 unsigned char *ndata
;
2406 * Make dest a copy of source.
2409 REQUIRE(VALID_NAME(source
));
2410 REQUIRE(VALID_NAME(dest
));
2411 REQUIRE(target
!= NULL
|| dest
->buffer
!= NULL
);
2413 if (target
== NULL
) {
2414 target
= dest
->buffer
;
2415 isc_buffer_clear(dest
->buffer
);
2418 REQUIRE(BINDABLE(dest
));
2423 if (target
->length
- target
->used
< source
->length
)
2424 return (ISC_R_NOSPACE
);
2426 ndata
= (unsigned char *)target
->base
+ target
->used
;
2427 dest
->ndata
= target
->base
;
2429 memcpy(ndata
, source
->ndata
, source
->length
);
2431 dest
->ndata
= ndata
;
2432 dest
->labels
= source
->labels
;
2433 dest
->length
= source
->length
;
2434 if ((source
->attributes
& DNS_NAMEATTR_ABSOLUTE
) != 0)
2435 dest
->attributes
= DNS_NAMEATTR_ABSOLUTE
;
2437 dest
->attributes
= 0;
2439 if (dest
->labels
> 0 && dest
->offsets
!= NULL
) {
2440 if (source
->offsets
!= NULL
)
2441 memcpy(dest
->offsets
, source
->offsets
, source
->labels
);
2443 set_offsets(dest
, dest
->offsets
, NULL
);
2446 isc_buffer_add(target
, dest
->length
);
2448 return (ISC_R_SUCCESS
);
2452 dns_name_destroy(void) {
2453 #ifdef ISC_PLATFORM_USETHREADS
2454 RUNTIME_CHECK(isc_once_do(&once
, thread_key_mutex_init
)
2457 LOCK(&thread_key_mutex
);
2458 if (thread_key_initialized
) {
2459 isc_mem_detach(&thread_key_mctx
);
2460 isc_thread_key_delete(totext_filter_proc_key
);
2461 thread_key_initialized
= 0;
2463 UNLOCK(&thread_key_mutex
);