xref: /minix/external/bsd/bind/dist/lib/dns/name.c (revision fb9c64b2)
1 /*	$NetBSD: name.c,v 1.11 2015/07/08 17:28:58 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1998-2003  Internet Software Consortium.
6  *
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.
10  *
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.
18  */
19 
20 /* Id */
21 
22 /*! \file */
23 
24 #include <config.h>
25 
26 #include <ctype.h>
27 #include <stdlib.h>
28 
29 #include <isc/buffer.h>
30 #include <isc/hash.h>
31 #include <isc/mem.h>
32 #include <isc/once.h>
33 #include <isc/print.h>
34 #include <isc/string.h>
35 #include <isc/thread.h>
36 #include <isc/util.h>
37 
38 #include <dns/compress.h>
39 #include <dns/fixedname.h>
40 #include <dns/name.h>
41 #include <dns/result.h>
42 
43 #define VALID_NAME(n)	ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
44 
45 typedef enum {
46 	ft_init = 0,
47 	ft_start,
48 	ft_ordinary,
49 	ft_initialescape,
50 	ft_escape,
51 	ft_escdecimal,
52 	ft_at
53 } ft_state;
54 
55 typedef enum {
56 	fw_start = 0,
57 	fw_ordinary,
58 	fw_newcurrent
59 } fw_state;
60 
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*/
78 };
79 
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
113 };
114 
115 #define CONVERTTOASCII(c)
116 #define CONVERTFROMASCII(c)
117 
118 #define INIT_OFFSETS(name, var, default) \
119 	if (name->offsets != NULL) \
120 		var = name->offsets; \
121 	else \
122 		var = default;
123 
124 #define SETUP_OFFSETS(name, var, default) \
125 	if (name->offsets != NULL) \
126 		var = name->offsets; \
127 	else { \
128 		var = default; \
129 		set_offsets(name, var, NULL); \
130 	}
131 
132 /*%
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.
135  */
136 #define MAKE_EMPTY(name) \
137 do { \
138 	name->ndata = NULL; \
139 	name->length = 0; \
140 	name->labels = 0; \
141 	name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
142 } while (/*CONSTCOND*/0);
143 
144 /*%
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.
147  */
148 #define BINDABLE(name) \
149 	((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
150 	 == 0)
151 
152 /*%
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.
156  */
157 static unsigned char root_ndata[] = { '\0' };
158 static unsigned char root_offsets[] = { 0 };
159 
160 static dns_name_t root =
161 {
162 	DNS_NAME_MAGIC,
163 	root_ndata, 1, 1,
164 	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
165 	root_offsets, NULL,
166 	{(void *)-1, (void *)-1},
167 	{NULL, NULL}
168 };
169 
170 /* XXXDCL make const? */
171 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
172 
173 static unsigned char wild_ndata[] = { '\001', '*' };
174 static unsigned char wild_offsets[] = { 0 };
175 
176 static dns_name_t wild =
177 {
178 	DNS_NAME_MAGIC,
179 	wild_ndata, 2, 1,
180 	DNS_NAMEATTR_READONLY,
181 	wild_offsets, NULL,
182 	{(void *)-1, (void *)-1},
183 	{NULL, NULL}
184 };
185 
186 /* XXXDCL make const? */
187 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
188 
189 unsigned int
190 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
191 
192 /*
193  * dns_name_t to text post-conversion procedure.
194  */
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;
201 #else
202 static dns_name_totextfilter_t totext_filter_proc = NULL;
203 #endif
204 
205 static void
206 set_offsets(const dns_name_t *name, unsigned char *offsets,
207 	    dns_name_t *set_name);
208 
209 void
210 dns_name_init(dns_name_t *name, unsigned char *offsets) {
211 	/*
212 	 * Initialize 'name'.
213 	 */
214 	DNS_NAME_INIT(name, offsets);
215 }
216 
217 void
218 dns_name_reset(dns_name_t *name) {
219 	REQUIRE(VALID_NAME(name));
220 	REQUIRE(BINDABLE(name));
221 
222 	DNS_NAME_RESET(name);
223 }
224 
225 void
226 dns_name_invalidate(dns_name_t *name) {
227 	/*
228 	 * Make 'name' invalid.
229 	 */
230 
231 	REQUIRE(VALID_NAME(name));
232 
233 	name->magic = 0;
234 	name->ndata = NULL;
235 	name->length = 0;
236 	name->labels = 0;
237 	name->attributes = 0;
238 	name->offsets = NULL;
239 	name->buffer = NULL;
240 	ISC_LINK_INIT(name, link);
241 }
242 
243 isc_boolean_t
244 dns_name_isvalid(const dns_name_t *name) {
245 	unsigned char *ndata, *offsets;
246 	unsigned int offset, count, length, nlabels;
247 
248 	if (!VALID_NAME(name))
249 		return (ISC_FALSE);
250 
251 	if (name->length > 255U || name->labels > 127U)
252 		return (ISC_FALSE);
253 
254 	ndata = name->ndata;
255 	length = name->length;
256 	offsets = name->offsets;
257 	offset = 0;
258 	nlabels = 0;
259 
260 	while (offset != length) {
261 		count = *ndata;
262 		if (count > 63U)
263 			return (ISC_FALSE);
264 		if (offsets != NULL && offsets[nlabels] != offset)
265 			return (ISC_FALSE);
266 
267 		nlabels++;
268 		offset += count + 1;
269 		ndata += count + 1;
270 		if (offset > length)
271 			return (ISC_FALSE);
272 
273 		if (count == 0)
274 			break;
275 	}
276 
277 	if (nlabels != name->labels || offset != name->length)
278 		return (ISC_FALSE);
279 
280 	return (ISC_TRUE);
281 }
282 
283 void
284 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
285 	/*
286 	 * Dedicate a buffer for use with 'name'.
287 	 */
288 
289 	REQUIRE(VALID_NAME(name));
290 	REQUIRE((buffer != NULL && name->buffer == NULL) ||
291 		(buffer == NULL));
292 
293 	name->buffer = buffer;
294 }
295 
296 isc_boolean_t
297 dns_name_hasbuffer(const dns_name_t *name) {
298 	/*
299 	 * Does 'name' have a dedicated buffer?
300 	 */
301 
302 	REQUIRE(VALID_NAME(name));
303 
304 	if (name->buffer != NULL)
305 		return (ISC_TRUE);
306 
307 	return (ISC_FALSE);
308 }
309 
310 isc_boolean_t
311 dns_name_isabsolute(const dns_name_t *name) {
312 
313 	/*
314 	 * Does 'name' end in the root label?
315 	 */
316 
317 	REQUIRE(VALID_NAME(name));
318 
319 	if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
320 		return (ISC_TRUE);
321 	return (ISC_FALSE);
322 }
323 
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)
332 
333 isc_boolean_t
334 dns_name_ismailbox(const dns_name_t *name) {
335 	unsigned char *ndata, ch;
336 	unsigned int n;
337 	isc_boolean_t first;
338 
339 	REQUIRE(VALID_NAME(name));
340 	REQUIRE(name->labels > 0);
341 	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
342 
343 	/*
344 	 * Root label.
345 	 */
346 	if (name->length == 1)
347 		return (ISC_TRUE);
348 
349 	ndata = name->ndata;
350 	n = *ndata++;
351 	INSIST(n <= 63);
352 	while (n--) {
353 		ch = *ndata++;
354 		if (!domainchar(ch))
355 			return (ISC_FALSE);
356 	}
357 
358 	if (ndata == name->ndata + name->length)
359 		return (ISC_FALSE);
360 
361 	/*
362 	 * RFC952/RFC1123 hostname.
363 	 */
364 	while (ndata < (name->ndata + name->length)) {
365 		n = *ndata++;
366 		INSIST(n <= 63);
367 		first = ISC_TRUE;
368 		while (n--) {
369 			ch = *ndata++;
370 			if (first || n == 0) {
371 				if (!borderchar(ch))
372 					return (ISC_FALSE);
373 			} else {
374 				if (!middlechar(ch))
375 					return (ISC_FALSE);
376 			}
377 			first = ISC_FALSE;
378 		}
379 	}
380 	return (ISC_TRUE);
381 }
382 
383 isc_boolean_t
384 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
385 	unsigned char *ndata, ch;
386 	unsigned int n;
387 	isc_boolean_t first;
388 
389 	REQUIRE(VALID_NAME(name));
390 	REQUIRE(name->labels > 0);
391 	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
392 
393 	/*
394 	 * Root label.
395 	 */
396 	if (name->length == 1)
397 		return (ISC_TRUE);
398 
399 	/*
400 	 * Skip wildcard if this is a ownername.
401 	 */
402 	ndata = name->ndata;
403 	if (wildcard && ndata[0] == 1 && ndata[1] == '*')
404 		ndata += 2;
405 
406 	/*
407 	 * RFC292/RFC1123 hostname.
408 	 */
409 	while (ndata < (name->ndata + name->length)) {
410 		n = *ndata++;
411 		INSIST(n <= 63);
412 		first = ISC_TRUE;
413 		while (n--) {
414 			ch = *ndata++;
415 			if (first || n == 0) {
416 				if (!borderchar(ch))
417 					return (ISC_FALSE);
418 			} else {
419 				if (!middlechar(ch))
420 					return (ISC_FALSE);
421 			}
422 			first = ISC_FALSE;
423 		}
424 	}
425 	return (ISC_TRUE);
426 }
427 
428 isc_boolean_t
429 dns_name_iswildcard(const dns_name_t *name) {
430 	unsigned char *ndata;
431 
432 	/*
433 	 * Is 'name' a wildcard name?
434 	 */
435 
436 	REQUIRE(VALID_NAME(name));
437 	REQUIRE(name->labels > 0);
438 
439 	if (name->length >= 2) {
440 		ndata = name->ndata;
441 		if (ndata[0] == 1 && ndata[1] == '*')
442 			return (ISC_TRUE);
443 	}
444 
445 	return (ISC_FALSE);
446 }
447 
448 isc_boolean_t
449 dns_name_internalwildcard(const dns_name_t *name) {
450 	unsigned char *ndata;
451 	unsigned int count;
452 	unsigned int label;
453 
454 	/*
455 	 * Does 'name' contain a internal wildcard?
456 	 */
457 
458 	REQUIRE(VALID_NAME(name));
459 	REQUIRE(name->labels > 0);
460 
461 	/*
462 	 * Skip first label.
463 	 */
464 	ndata = name->ndata;
465 	count = *ndata++;
466 	INSIST(count <= 63);
467 	ndata += count;
468 	label = 1;
469 	/*
470 	 * Check all but the last of the remaining labels.
471 	 */
472 	while (label + 1 < name->labels) {
473 		count = *ndata++;
474 		INSIST(count <= 63);
475 		if (count == 1 && *ndata == '*')
476 			return (ISC_TRUE);
477 		ndata += count;
478 		label++;
479 	}
480 	return (ISC_FALSE);
481 }
482 
483 static inline unsigned int
484 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
485 	unsigned int length;
486 	const unsigned char *s;
487 	unsigned int h = 0;
488 	unsigned char c;
489 
490 	length = name->length;
491 	if (length > 16)
492 		length = 16;
493 
494 	/*
495 	 * This hash function is similar to the one Ousterhout
496 	 * uses in Tcl.
497 	 */
498 	s = name->ndata;
499 	if (case_sensitive) {
500 		while (length > 0) {
501 			h += ( h << 3 ) + *s;
502 			s++;
503 			length--;
504 		}
505 	} else {
506 		while (length > 0) {
507 			c = maptolower[*s];
508 			h += ( h << 3 ) + c;
509 			s++;
510 			length--;
511 		}
512 	}
513 
514 	return (h);
515 }
516 
517 unsigned int
518 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
519 	/*
520 	 * Provide a hash value for 'name'.
521 	 */
522 	REQUIRE(VALID_NAME(name));
523 
524 	if (name->labels == 0)
525 		return (0);
526 
527 	return (name_hash(name, case_sensitive));
528 }
529 
530 unsigned int
531 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
532 	/*
533 	 * Provide a hash value for 'name'.
534 	 */
535 	REQUIRE(VALID_NAME(name));
536 
537 	if (name->labels == 0)
538 		return (0);
539 
540 	return (isc_hash_calc((const unsigned char *)name->ndata,
541 			      name->length, case_sensitive));
542 }
543 
544 unsigned int
545 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
546 	/*
547 	 * This function was deprecated due to the breakage of the name space
548 	 * convention.  We only keep this internally to provide binary backward
549 	 * compatibility.
550 	 */
551 	REQUIRE(VALID_NAME(name));
552 
553 	return (dns_name_fullhash(name, case_sensitive));
554 }
555 
556 unsigned int
557 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
558 	unsigned char *offsets;
559 	dns_offsets_t odata;
560 	dns_name_t tname;
561 	unsigned int h = 0;
562 	unsigned int i;
563 
564 	/*
565 	 * Provide a hash value for 'name'.
566 	 */
567 	REQUIRE(VALID_NAME(name));
568 
569 	if (name->labels == 0)
570 		return (0);
571 	else if (name->labels == 1)
572 		return (name_hash(name, case_sensitive));
573 
574 	SETUP_OFFSETS(name, offsets, odata);
575 	DNS_NAME_INIT(&tname, NULL);
576 	tname.labels = 1;
577 	h = 0;
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];
582 		else
583 			tname.length = offsets[i + 1] - offsets[i];
584 		h += name_hash(&tname, case_sensitive);
585 	}
586 
587 	return (h);
588 }
589 
590 dns_namereln_t
591 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
592 		     int *orderp, unsigned int *nlabelsp)
593 {
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;
600 
601 	/*
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.
605 	 *
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
609 	 * same domain.
610 	 */
611 
612 	REQUIRE(VALID_NAME(name1));
613 	REQUIRE(VALID_NAME(name2));
614 	REQUIRE(orderp != NULL);
615 	REQUIRE(nlabelsp != NULL);
616 	/*
617 	 * Either name1 is absolute and name2 is absolute, or neither is.
618 	 */
619 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
620 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
621 
622 	if (name1 == name2) {
623 		*orderp = 0;
624 		*nlabelsp = name1->labels;
625 		return (dns_namereln_equal);
626 	}
627 
628 	SETUP_OFFSETS(name1, offsets1, odata1);
629 	SETUP_OFFSETS(name2, offsets2, odata2);
630 
631 	nlabels = 0;
632 	l1 = name1->labels;
633 	l2 = name2->labels;
634 	if (l2 > l1) {
635 		l = l1;
636 		ldiff = 0 - (l2 - l1);
637 	} else {
638 		l = l2;
639 		ldiff = l1 - l2;
640 	}
641 
642 	while (l > 0) {
643 		l--;
644 		l1--;
645 		l2--;
646 		label1 = &name1->ndata[offsets1[l1]];
647 		label2 = &name2->ndata[offsets2[l2]];
648 		count1 = *label1++;
649 		count2 = *label2++;
650 
651 		/*
652 		 * We dropped bitstring labels, and we don't support any
653 		 * other extended label types.
654 		 */
655 		INSIST(count1 <= 63 && count2 <= 63);
656 
657 		cdiff = (int)count1 - (int)count2;
658 		if (cdiff < 0)
659 			count = count1;
660 		else
661 			count = count2;
662 
663 		while (count > 0) {
664 			chdiff = (int)maptolower[*label1] -
665 			    (int)maptolower[*label2];
666 			if (chdiff != 0) {
667 				*orderp = chdiff;
668 				goto done;
669 			}
670 			count--;
671 			label1++;
672 			label2++;
673 		}
674 		if (cdiff != 0) {
675 			*orderp = cdiff;
676 			goto done;
677 		}
678 		nlabels++;
679 	}
680 
681 	*orderp = ldiff;
682 	if (ldiff < 0)
683 		namereln = dns_namereln_contains;
684 	else if (ldiff > 0)
685 		namereln = dns_namereln_subdomain;
686 	else
687 		namereln = dns_namereln_equal;
688 
689  done:
690 	*nlabelsp = nlabels;
691 
692 	if (nlabels > 0 && namereln == dns_namereln_none)
693 		namereln = dns_namereln_commonancestor;
694 
695 	return (namereln);
696 }
697 
698 int
699 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
700 	int order;
701 	unsigned int nlabels;
702 
703 	/*
704 	 * Determine the relative ordering under the DNSSEC order relation of
705 	 * 'name1' and 'name2'.
706 	 *
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
710 	 * same domain.
711 	 */
712 
713 	(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
714 
715 	return (order);
716 }
717 
718 isc_boolean_t
719 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
720 	unsigned int l, count;
721 	unsigned char c;
722 	unsigned char *label1, *label2;
723 
724 	/*
725 	 * Are 'name1' and 'name2' equal?
726 	 *
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
730 	 * same domain.
731 	 */
732 
733 	REQUIRE(VALID_NAME(name1));
734 	REQUIRE(VALID_NAME(name2));
735 	/*
736 	 * Either name1 is absolute and name2 is absolute, or neither is.
737 	 */
738 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
739 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
740 
741 	if (name1 == name2)
742 		return (ISC_TRUE);
743 
744 	if (name1->length != name2->length)
745 		return (ISC_FALSE);
746 
747 	l = name1->labels;
748 
749 	if (l != name2->labels)
750 		return (ISC_FALSE);
751 
752 	label1 = name1->ndata;
753 	label2 = name2->ndata;
754 	while (l > 0) {
755 		l--;
756 		count = *label1++;
757 		if (count != *label2++)
758 			return (ISC_FALSE);
759 
760 		INSIST(count <= 63); /* no bitstring support */
761 
762 		while (count > 0) {
763 			count--;
764 			c = maptolower[*label1++];
765 			if (c != maptolower[*label2++])
766 				return (ISC_FALSE);
767 		}
768 	}
769 
770 	return (ISC_TRUE);
771 }
772 
773 isc_boolean_t
774 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
775 
776 	/*
777 	 * Are 'name1' and 'name2' equal?
778 	 *
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
782 	 * same domain.
783 	 */
784 
785 	REQUIRE(VALID_NAME(name1));
786 	REQUIRE(VALID_NAME(name2));
787 	/*
788 	 * Either name1 is absolute and name2 is absolute, or neither is.
789 	 */
790 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
791 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
792 
793 	if (name1->length != name2->length)
794 		return (ISC_FALSE);
795 
796 	if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
797 		return (ISC_FALSE);
798 
799 	return (ISC_TRUE);
800 }
801 
802 int
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;
807 
808 	/*
809 	 * Compare two absolute names as rdata.
810 	 */
811 
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);
818 
819 	l1 = name1->labels;
820 	l2 = name2->labels;
821 
822 	l = (l1 < l2) ? l1 : l2;
823 
824 	label1 = name1->ndata;
825 	label2 = name2->ndata;
826 	while (l > 0) {
827 		l--;
828 		count1 = *label1++;
829 		count2 = *label2++;
830 
831 		/* no bitstring support */
832 		INSIST(count1 <= 63 && count2 <= 63);
833 
834 		if (count1 != count2)
835 			return ((count1 < count2) ? -1 : 1);
836 		count = count1;
837 		while (count > 0) {
838 			count--;
839 			c1 = maptolower[*label1++];
840 			c2 = maptolower[*label2++];
841 			if (c1 < c2)
842 				return (-1);
843 			else if (c1 > c2)
844 				return (1);
845 		}
846 	}
847 
848 	/*
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.
854 	 */
855 	INSIST(l1 == l2);
856 
857 	return (0);
858 }
859 
860 isc_boolean_t
861 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
862 	int order;
863 	unsigned int nlabels;
864 	dns_namereln_t namereln;
865 
866 	/*
867 	 * Is 'name1' a subdomain of 'name2'?
868 	 *
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
872 	 * same domain.
873 	 */
874 
875 	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
876 	if (namereln == dns_namereln_subdomain ||
877 	    namereln == dns_namereln_equal)
878 		return (ISC_TRUE);
879 
880 	return (ISC_FALSE);
881 }
882 
883 isc_boolean_t
884 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
885 	int order;
886 	unsigned int nlabels, labels;
887 	dns_name_t tname;
888 
889 	REQUIRE(VALID_NAME(name));
890 	REQUIRE(name->labels > 0);
891 	REQUIRE(VALID_NAME(wname));
892 	labels = wname->labels;
893 	REQUIRE(labels > 0);
894 	REQUIRE(dns_name_iswildcard(wname));
895 
896 #if defined(__clang__)  && \
897        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
898 	memset(&tname, 0, sizeof(tname));
899 #endif
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)
904 		return (ISC_TRUE);
905 	return (ISC_FALSE);
906 }
907 
908 unsigned int
909 dns_name_countlabels(const dns_name_t *name) {
910 	/*
911 	 * How many labels does 'name' have?
912 	 */
913 
914 	REQUIRE(VALID_NAME(name));
915 
916 	ENSURE(name->labels <= 128);
917 
918 	return (name->labels);
919 }
920 
921 void
922 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
923 	unsigned char *offsets;
924 	dns_offsets_t odata;
925 
926 	/*
927 	 * Make 'label' refer to the 'n'th least significant label of 'name'.
928 	 */
929 
930 	REQUIRE(VALID_NAME(name));
931 	REQUIRE(name->labels > 0);
932 	REQUIRE(n < name->labels);
933 	REQUIRE(label != NULL);
934 
935 	SETUP_OFFSETS(name, offsets, odata);
936 
937 	label->base = &name->ndata[offsets[n]];
938 	if (n == name->labels - 1)
939 		label->length = name->length - offsets[n];
940 	else
941 		label->length = offsets[n + 1] - offsets[n];
942 }
943 
944 void
945 dns_name_getlabelsequence(const dns_name_t *source,
946 			  unsigned int first, unsigned int n,
947 			  dns_name_t *target)
948 {
949 	unsigned char *offsets;
950 	dns_offsets_t odata;
951 	unsigned int firstoffset, endoffset;
952 
953 	/*
954 	 * Make 'target' refer to the 'n' labels including and following
955 	 * 'first' in 'source'.
956 	 */
957 
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));
963 
964 	SETUP_OFFSETS(source, offsets, odata);
965 
966 	if (first == source->labels)
967 		firstoffset = source->length;
968 	else
969 		firstoffset = offsets[first];
970 
971 	if (first + n == source->labels)
972 		endoffset = source->length;
973 	else
974 		endoffset = offsets[first + n];
975 
976 	target->ndata = &source->ndata[firstoffset];
977 	target->length = endoffset - firstoffset;
978 
979 	if (first + n == source->labels && n > 0 &&
980 	    (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
981 		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
982 	else
983 		target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
984 
985 	target->labels = n;
986 
987 	/*
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().
991 	 */
992 	if (target->offsets != NULL &&
993 	    (target != source || first != 0))
994 		set_offsets(target, target->offsets, NULL);
995 }
996 
997 void
998 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
999 
1000 	/*
1001 	 * Make 'target' refer to the same name as 'source'.
1002 	 */
1003 
1004 	REQUIRE(VALID_NAME(source));
1005 	REQUIRE(VALID_NAME(target));
1006 	REQUIRE(BINDABLE(target));
1007 
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,
1017 				source->labels);
1018 		else
1019 			set_offsets(target, target->offsets, NULL);
1020 	}
1021 }
1022 
1023 void
1024 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
1025 	unsigned char *offsets;
1026 	dns_offsets_t odata;
1027 	unsigned int len;
1028 	isc_region_t r2;
1029 
1030 	/*
1031 	 * Make 'name' refer to region 'r'.
1032 	 */
1033 
1034 	REQUIRE(VALID_NAME(name));
1035 	REQUIRE(r != NULL);
1036 	REQUIRE(BINDABLE(name));
1037 
1038 	INIT_OFFSETS(name, offsets, odata);
1039 
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;
1048 		name->length = len;
1049 	} else {
1050 		name->ndata = r->base;
1051 		name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1052 			r->length : DNS_NAME_MAXWIRE;
1053 	}
1054 
1055 	if (r->length > 0)
1056 		set_offsets(name, offsets, name);
1057 	else {
1058 		name->labels = 0;
1059 		name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1060 	}
1061 
1062 	if (name->buffer != NULL)
1063 		isc_buffer_add(name->buffer, name->length);
1064 }
1065 
1066 void
1067 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1068 	/*
1069 	 * Make 'r' refer to 'name'.
1070 	 */
1071 
1072 	REQUIRE(VALID_NAME(name));
1073 	REQUIRE(r != NULL);
1074 
1075 	DNS_NAME_TOREGION(name, r);
1076 }
1077 
1078 isc_result_t
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)
1082 {
1083 	unsigned char *ndata, *label = NULL;
1084 	char *tdata;
1085 	char c;
1086 	ft_state state;
1087 	unsigned int value = 0, count = 0;
1088 	unsigned int n1 = 0, n2 = 0;
1089 	unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1090 	isc_boolean_t done;
1091 	unsigned char *offsets;
1092 	dns_offsets_t odata;
1093 	isc_boolean_t downcase;
1094 
1095 	/*
1096 	 * Convert the textual representation of a DNS name at source
1097 	 * into uncompressed wire form stored in target.
1098 	 *
1099 	 * Notes:
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.
1103 	 */
1104 
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)));
1109 
1110 	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1111 
1112 	if (target == NULL && name->buffer != NULL) {
1113 		target = name->buffer;
1114 		isc_buffer_clear(target);
1115 	}
1116 
1117 	REQUIRE(BINDABLE(name));
1118 
1119 	INIT_OFFSETS(name, offsets, odata);
1120 	offsets[0] = 0;
1121 
1122 	/*
1123 	 * Make 'name' empty in case of failure.
1124 	 */
1125 	MAKE_EMPTY(name);
1126 
1127 	/*
1128 	 * Set up the state machine.
1129 	 */
1130 	tdata = (char *)source->base + source->current;
1131 	tlen = isc_buffer_remaininglength(source);
1132 	tused = 0;
1133 	ndata = isc_buffer_used(target);
1134 	nrem = isc_buffer_availablelength(target);
1135 	if (nrem > 255)
1136 		nrem = 255;
1137 	nused = 0;
1138 	labels = 0;
1139 	done = ISC_FALSE;
1140 	state = ft_init;
1141 
1142 	while (nrem > 0 && tlen > 0 && !done) {
1143 		c = *tdata++;
1144 		tlen--;
1145 		tused++;
1146 
1147 		switch (state) {
1148 		case ft_init:
1149 			/*
1150 			 * Is this the root name?
1151 			 */
1152 			if (c == '.') {
1153 				if (tlen != 0)
1154 					return (DNS_R_EMPTYLABEL);
1155 				labels++;
1156 				*ndata++ = 0;
1157 				nrem--;
1158 				nused++;
1159 				done = ISC_TRUE;
1160 				break;
1161 			}
1162 			if (c == '@' && tlen == 0) {
1163 				state = ft_at;
1164 				break;
1165 			}
1166 
1167 			/* FALLTHROUGH */
1168 		case ft_start:
1169 			label = ndata;
1170 			ndata++;
1171 			nrem--;
1172 			nused++;
1173 			count = 0;
1174 			if (c == '\\') {
1175 				state = ft_initialescape;
1176 				break;
1177 			}
1178 			state = ft_ordinary;
1179 			if (nrem == 0)
1180 				return (ISC_R_NOSPACE);
1181 			/* FALLTHROUGH */
1182 		case ft_ordinary:
1183 			if (c == '.') {
1184 				if (count == 0)
1185 					return (DNS_R_EMPTYLABEL);
1186 				*label = count;
1187 				labels++;
1188 				INSIST(labels <= 127);
1189 				offsets[labels] = nused;
1190 				if (tlen == 0) {
1191 					labels++;
1192 					*ndata++ = 0;
1193 					nrem--;
1194 					nused++;
1195 					done = ISC_TRUE;
1196 				}
1197 				state = ft_start;
1198 			} else if (c == '\\') {
1199 				state = ft_escape;
1200 			} else {
1201 				if (count >= 63)
1202 					return (DNS_R_LABELTOOLONG);
1203 				count++;
1204 				CONVERTTOASCII(c);
1205 				if (downcase)
1206 					c = maptolower[c & 0xff];
1207 				*ndata++ = c;
1208 				nrem--;
1209 				nused++;
1210 			}
1211 			break;
1212 		case ft_initialescape:
1213 			if (c == '[') {
1214 				/*
1215 				 * This looks like a bitstring label, which
1216 				 * was deprecated.  Intentionally drop it.
1217 				 */
1218 				return (DNS_R_BADLABELTYPE);
1219 			}
1220 			state = ft_escape;
1221 			POST(state);
1222 			/* FALLTHROUGH */
1223 		case ft_escape:
1224 			if (!isdigit(c & 0xff)) {
1225 				if (count >= 63)
1226 					return (DNS_R_LABELTOOLONG);
1227 				count++;
1228 				CONVERTTOASCII(c);
1229 				if (downcase)
1230 					c = maptolower[c & 0xff];
1231 				*ndata++ = c;
1232 				nrem--;
1233 				nused++;
1234 				state = ft_ordinary;
1235 				break;
1236 			}
1237 			digits = 0;
1238 			value = 0;
1239 			state = ft_escdecimal;
1240 			/* FALLTHROUGH */
1241 		case ft_escdecimal:
1242 			if (!isdigit(c & 0xff))
1243 				return (DNS_R_BADESCAPE);
1244 			value *= 10;
1245 			value += digitvalue[c & 0xff];
1246 			digits++;
1247 			if (digits == 3) {
1248 				if (value > 255)
1249 					return (DNS_R_BADESCAPE);
1250 				if (count >= 63)
1251 					return (DNS_R_LABELTOOLONG);
1252 				count++;
1253 				if (downcase)
1254 					value = maptolower[value];
1255 				*ndata++ = value;
1256 				nrem--;
1257 				nused++;
1258 				state = ft_ordinary;
1259 			}
1260 			break;
1261 		default:
1262 			FATAL_ERROR(__FILE__, __LINE__,
1263 				    "Unexpected state %d", state);
1264 			/* Does not return. */
1265 		}
1266 	}
1267 
1268 	if (!done) {
1269 		if (nrem == 0)
1270 			return (ISC_R_NOSPACE);
1271 		INSIST(tlen == 0);
1272 		if (state != ft_ordinary && state != ft_at)
1273 			return (ISC_R_UNEXPECTEDEND);
1274 		if (state == ft_ordinary) {
1275 			INSIST(count != 0);
1276 			*label = count;
1277 			labels++;
1278 			INSIST(labels <= 127);
1279 			offsets[labels] = nused;
1280 		}
1281 		if (origin != NULL) {
1282 			if (nrem < origin->length)
1283 				return (ISC_R_NOSPACE);
1284 			label = origin->ndata;
1285 			n1 = origin->length;
1286 			nrem -= n1;
1287 			POST(nrem);
1288 			while (n1 > 0) {
1289 				n2 = *label++;
1290 				INSIST(n2 <= 63); /* no bitstring support */
1291 				*ndata++ = n2;
1292 				n1 -= n2 + 1;
1293 				nused += n2 + 1;
1294 				while (n2 > 0) {
1295 					c = *label++;
1296 					if (downcase)
1297 						c = maptolower[c & 0xff];
1298 					*ndata++ = c;
1299 					n2--;
1300 				}
1301 				labels++;
1302 				if (n1 > 0) {
1303 					INSIST(labels <= 127);
1304 					offsets[labels] = nused;
1305 				}
1306 			}
1307 			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1308 				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1309 		}
1310 	} else
1311 		name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1312 
1313 	name->ndata = (unsigned char *)target->base + target->used;
1314 	name->labels = labels;
1315 	name->length = nused;
1316 
1317 	isc_buffer_forward(source, tused);
1318 	isc_buffer_add(target, name->length);
1319 
1320 	return (ISC_R_SUCCESS);
1321 }
1322 
1323 #ifdef ISC_PLATFORM_USETHREADS
1324 static void
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);
1330 }
1331 
1332 static void
1333 thread_key_mutex_init(void) {
1334 	RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1335 }
1336 
1337 static isc_result_t
1338 totext_filter_proc_key_init(void) {
1339 	isc_result_t result;
1340 
1341 	/*
1342 	 * We need the call to isc_once_do() to support profiled mutex
1343 	 * otherwise thread_key_mutex could be initialized at compile time.
1344 	 */
1345 	result = isc_once_do(&once, thread_key_mutex_init);
1346 	if (result != ISC_R_SUCCESS)
1347 		return (result);
1348 
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)
1354 			goto unlock;
1355 		isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1356 		isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1357 
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);
1363 		} else
1364 			thread_key_initialized = 1;
1365  unlock:
1366 		UNLOCK(&thread_key_mutex);
1367 	}
1368 	return (result);
1369 }
1370 #endif
1371 
1372 isc_result_t
1373 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1374 		isc_buffer_t *target)
1375 {
1376 	unsigned int options = DNS_NAME_MASTERFILE;
1377 
1378 	if (omit_final_dot)
1379 		options |= DNS_NAME_OMITFINALDOT;
1380 	return (dns_name_totext2(name, options, target));
1381 }
1382 
1383 isc_result_t
1384 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1385 	return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1386 }
1387 
1388 isc_result_t
1389 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1390 {
1391 	unsigned char *ndata;
1392 	char *tdata;
1393 	unsigned int nlen, tlen;
1394 	unsigned char c;
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;
1403 #endif
1404 	isc_boolean_t omit_final_dot =
1405 		ISC_TF(options & DNS_NAME_OMITFINALDOT);
1406 
1407 	/*
1408 	 * This function assumes the name is in proper uncompressed
1409 	 * wire format.
1410 	 */
1411 	REQUIRE(VALID_NAME(name));
1412 	REQUIRE(ISC_BUFFER_VALID(target));
1413 
1414 #ifdef ISC_PLATFORM_USETHREADS
1415 	result = totext_filter_proc_key_init();
1416 	if (result != ISC_R_SUCCESS)
1417 		return (result);
1418 #endif
1419 	ndata = name->ndata;
1420 	nlen = name->length;
1421 	labels = name->labels;
1422 	tdata = isc_buffer_used(target);
1423 	tlen = isc_buffer_availablelength(target);
1424 
1425 	trem = tlen;
1426 
1427 	if (labels == 0 && nlen == 0) {
1428 		/*
1429 		 * Special handling for an empty name.
1430 		 */
1431 		if (trem == 0)
1432 			return (ISC_R_NOSPACE);
1433 
1434 		/*
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.
1440 		 */
1441 		saw_root = ISC_TRUE;
1442 		omit_final_dot = ISC_FALSE;
1443 		*tdata++ = '@';
1444 		trem--;
1445 
1446 		/*
1447 		 * Skip the while() loop.
1448 		 */
1449 		nlen = 0;
1450 	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1451 		/*
1452 		 * Special handling for the root label.
1453 		 */
1454 		if (trem == 0)
1455 			return (ISC_R_NOSPACE);
1456 
1457 		saw_root = ISC_TRUE;
1458 		omit_final_dot = ISC_FALSE;
1459 		*tdata++ = '.';
1460 		trem--;
1461 
1462 		/*
1463 		 * Skip the while() loop.
1464 		 */
1465 		nlen = 0;
1466 	}
1467 
1468 	while (labels > 0 && nlen > 0 && trem > 0) {
1469 		labels--;
1470 		count = *ndata++;
1471 		nlen--;
1472 		if (count == 0) {
1473 			saw_root = ISC_TRUE;
1474 			break;
1475 		}
1476 		if (count < 64) {
1477 			INSIST(nlen >= count);
1478 			while (count > 0) {
1479 				c = *ndata;
1480 				switch (c) {
1481 				/* Special modifiers in zone files. */
1482 				case 0x40: /* '@' */
1483 				case 0x24: /* '$' */
1484 					if ((options & DNS_NAME_MASTERFILE) == 0)
1485 						goto no_escape;
1486 					/* FALLTHROUGH */
1487 				case 0x22: /* '"' */
1488 				case 0x28: /* '(' */
1489 				case 0x29: /* ')' */
1490 				case 0x2E: /* '.' */
1491 				case 0x3B: /* ';' */
1492 				case 0x5C: /* '\\' */
1493 					if (trem < 2)
1494 						return (ISC_R_NOSPACE);
1495 					*tdata++ = '\\';
1496 					CONVERTFROMASCII(c);
1497 					*tdata++ = c;
1498 					ndata++;
1499 					trem -= 2;
1500 					nlen--;
1501 					break;
1502 				no_escape:
1503 				default:
1504 					if (c > 0x20 && c < 0x7f) {
1505 						if (trem == 0)
1506 							return (ISC_R_NOSPACE);
1507 						CONVERTFROMASCII(c);
1508 						*tdata++ = c;
1509 						ndata++;
1510 						trem--;
1511 						nlen--;
1512 					} else {
1513 						if (trem < 4)
1514 							return (ISC_R_NOSPACE);
1515 						*tdata++ = 0x5c;
1516 						*tdata++ = 0x30 +
1517 							   ((c / 100) % 10);
1518 						*tdata++ = 0x30 +
1519 							   ((c / 10) % 10);
1520 						*tdata++ = 0x30 + (c % 10);
1521 						trem -= 4;
1522 						ndata++;
1523 						nlen--;
1524 					}
1525 				}
1526 				count--;
1527 			}
1528 		} else {
1529 			FATAL_ERROR(__FILE__, __LINE__,
1530 				    "Unexpected label type %02x", count);
1531 			/* NOTREACHED */
1532 		}
1533 
1534 		/*
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.
1539 		 */
1540 		if (trem == 0)
1541 			return (ISC_R_NOSPACE);
1542 		*tdata++ = '.';
1543 		trem--;
1544 	}
1545 
1546 	if (nlen != 0 && trem == 0)
1547 		return (ISC_R_NOSPACE);
1548 
1549 	if (!saw_root || omit_final_dot)
1550 		trem++;
1551 
1552 	isc_buffer_add(target, tlen - trem);
1553 
1554 #ifdef ISC_PLATFORM_USETHREADS
1555 	mem = isc_thread_key_getspecific(totext_filter_proc_key);
1556 	if (mem != NULL)
1557 		totext_filter_proc = *mem;
1558 #endif
1559 	if (totext_filter_proc != NULL)
1560 		return ((*totext_filter_proc)(target, oused, saw_root));
1561 
1562 	return (ISC_R_SUCCESS);
1563 }
1564 
1565 isc_result_t
1566 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1567 			isc_buffer_t *target)
1568 {
1569 	unsigned char *ndata;
1570 	char *tdata;
1571 	unsigned int nlen, tlen;
1572 	unsigned char c;
1573 	unsigned int trem, count;
1574 	unsigned int labels;
1575 
1576 	/*
1577 	 * This function assumes the name is in proper uncompressed
1578 	 * wire format.
1579 	 */
1580 	REQUIRE(VALID_NAME(name));
1581 	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1582 	REQUIRE(ISC_BUFFER_VALID(target));
1583 
1584 	ndata = name->ndata;
1585 	nlen = name->length;
1586 	labels = name->labels;
1587 	tdata = isc_buffer_used(target);
1588 	tlen = isc_buffer_availablelength(target);
1589 
1590 	trem = tlen;
1591 
1592 	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1593 		/*
1594 		 * Special handling for the root label.
1595 		 */
1596 		if (trem == 0)
1597 			return (ISC_R_NOSPACE);
1598 
1599 		omit_final_dot = ISC_FALSE;
1600 		*tdata++ = '.';
1601 		trem--;
1602 
1603 		/*
1604 		 * Skip the while() loop.
1605 		 */
1606 		nlen = 0;
1607 	}
1608 
1609 	while (labels > 0 && nlen > 0 && trem > 0) {
1610 		labels--;
1611 		count = *ndata++;
1612 		nlen--;
1613 		if (count == 0)
1614 			break;
1615 		if (count < 64) {
1616 			INSIST(nlen >= count);
1617 			while (count > 0) {
1618 				c = *ndata;
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 */
1624 				{
1625 					if (trem == 0)
1626 						return (ISC_R_NOSPACE);
1627 					/* downcase */
1628 					if (c >= 0x41 && c <= 0x5A)
1629 						c += 0x20;
1630 					CONVERTFROMASCII(c);
1631 					*tdata++ = c;
1632 					ndata++;
1633 					trem--;
1634 					nlen--;
1635 				} else {
1636 					if (trem < 3)
1637 						return (ISC_R_NOSPACE);
1638 					sprintf(tdata, "%%%02X", c);
1639 					tdata += 3;
1640 					trem -= 3;
1641 					ndata++;
1642 					nlen--;
1643 				}
1644 				count--;
1645 			}
1646 		} else {
1647 			FATAL_ERROR(__FILE__, __LINE__,
1648 				    "Unexpected label type %02x", count);
1649 			/* NOTREACHED */
1650 		}
1651 
1652 		/*
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.
1657 		 */
1658 		if (trem == 0)
1659 			return (ISC_R_NOSPACE);
1660 		*tdata++ = '.';
1661 		trem--;
1662 	}
1663 
1664 	if (nlen != 0 && trem == 0)
1665 		return (ISC_R_NOSPACE);
1666 
1667 	if (omit_final_dot)
1668 		trem++;
1669 
1670 	isc_buffer_add(target, tlen - trem);
1671 
1672 	return (ISC_R_SUCCESS);
1673 }
1674 
1675 isc_result_t
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;
1680 
1681 	/*
1682 	 * Downcase 'source'.
1683 	 */
1684 
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);
1690 		target = &buffer;
1691 		ndata = source->ndata;
1692 	} else {
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);
1699 		}
1700 		ndata = (unsigned char *)target->base + target->used;
1701 		name->ndata = ndata;
1702 	}
1703 
1704 	sndata = source->ndata;
1705 	nlen = source->length;
1706 	labels = source->labels;
1707 
1708 	if (nlen > (target->length - target->used)) {
1709 		MAKE_EMPTY(name);
1710 		return (ISC_R_NOSPACE);
1711 	}
1712 
1713 	while (labels > 0 && nlen > 0) {
1714 		labels--;
1715 		count = *sndata++;
1716 		*ndata++ = count;
1717 		nlen--;
1718 		if (count < 64) {
1719 			INSIST(nlen >= count);
1720 			while (count > 0) {
1721 				*ndata++ = maptolower[(*sndata++)];
1722 				nlen--;
1723 				count--;
1724 			}
1725 		} else {
1726 			FATAL_ERROR(__FILE__, __LINE__,
1727 				    "Unexpected label type %02x", count);
1728 			/* Does not return. */
1729 		}
1730 	}
1731 
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;
1737 		else
1738 			name->attributes = 0;
1739 		if (name->labels > 0 && name->offsets != NULL)
1740 			set_offsets(name, name->offsets, NULL);
1741 	}
1742 
1743 	isc_buffer_add(target, name->length);
1744 
1745 	return (ISC_R_SUCCESS);
1746 }
1747 
1748 static void
1749 set_offsets(const dns_name_t *name, unsigned char *offsets,
1750 	    dns_name_t *set_name)
1751 {
1752 	unsigned int offset, count, length, nlabels;
1753 	unsigned char *ndata;
1754 	isc_boolean_t absolute;
1755 
1756 	ndata = name->ndata;
1757 	length = name->length;
1758 	offset = 0;
1759 	nlabels = 0;
1760 	absolute = ISC_FALSE;
1761 	while (offset != length) {
1762 		INSIST(nlabels < 128);
1763 		offsets[nlabels++] = offset;
1764 		count = *ndata++;
1765 		offset++;
1766 		INSIST(count <= 63);
1767 		offset += count;
1768 		ndata += count;
1769 		INSIST(offset <= length);
1770 		if (count == 0) {
1771 			absolute = ISC_TRUE;
1772 			break;
1773 		}
1774 	}
1775 	if (set_name != NULL) {
1776 		INSIST(set_name == name);
1777 
1778 		set_name->labels = nlabels;
1779 		set_name->length = offset;
1780 		if (absolute)
1781 			set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1782 		else
1783 			set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1784 	}
1785 	INSIST(nlabels == name->labels);
1786 	INSIST(offset == name->length);
1787 }
1788 
1789 isc_result_t
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)
1793 {
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;
1798 	isc_boolean_t done;
1799 	fw_state state = fw_start;
1800 	unsigned int c;
1801 	unsigned char *offsets;
1802 	dns_offsets_t odata;
1803 	isc_boolean_t downcase;
1804 	isc_boolean_t seen_pointer;
1805 
1806 	/*
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.
1810 	 */
1811 
1812 	REQUIRE(VALID_NAME(name));
1813 	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1814 		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1815 
1816 	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1817 
1818 	if (target == NULL && name->buffer != NULL) {
1819 		target = name->buffer;
1820 		isc_buffer_clear(target);
1821 	}
1822 
1823 	REQUIRE(dctx != NULL);
1824 	REQUIRE(BINDABLE(name));
1825 
1826 	INIT_OFFSETS(name, offsets, odata);
1827 
1828 	/*
1829 	 * Make 'name' empty in case of failure.
1830 	 */
1831 	MAKE_EMPTY(name);
1832 
1833 	/*
1834 	 * Initialize things to make the compiler happy; they're not required.
1835 	 */
1836 	n = 0;
1837 	new_current = 0;
1838 
1839 	/*
1840 	 * Set up.
1841 	 */
1842 	labels = 0;
1843 	done = ISC_FALSE;
1844 
1845 	ndata = isc_buffer_used(target);
1846 	nused = 0;
1847 	seen_pointer = ISC_FALSE;
1848 
1849 	/*
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).
1854 	 */
1855 	nmax = isc_buffer_availablelength(target);
1856 	if (nmax > DNS_NAME_MAXWIRE)
1857 		nmax = DNS_NAME_MAXWIRE;
1858 
1859 	cdata = isc_buffer_current(source);
1860 	cused = 0;
1861 
1862 	current = source->current;
1863 	biggest_pointer = current;
1864 
1865 	/*
1866 	 * Note:  The following code is not optimized for speed, but
1867 	 * rather for correctness.  Speed will be addressed in the future.
1868 	 */
1869 
1870 	while (current < source->active && !done) {
1871 		c = *cdata++;
1872 		current++;
1873 		if (!seen_pointer)
1874 			cused++;
1875 
1876 		switch (state) {
1877 		case fw_start:
1878 			if (c < 64) {
1879 				offsets[labels] = nused;
1880 				labels++;
1881 				if (nused + c + 1 > nmax)
1882 					goto full;
1883 				nused += c + 1;
1884 				*ndata++ = c;
1885 				if (c == 0)
1886 					done = ISC_TRUE;
1887 				n = c;
1888 				state = fw_ordinary;
1889 			} else if (c >= 128 && c < 192) {
1890 				/*
1891 				 * 14 bit local compression pointer.
1892 				 * Local compression is no longer an
1893 				 * IETF draft.
1894 				 */
1895 				return (DNS_R_BADLABELTYPE);
1896 			} else if (c >= 192) {
1897 				/*
1898 				 * Ordinary 14-bit pointer.
1899 				 */
1900 				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1901 				    0)
1902 					return (DNS_R_DISALLOWED);
1903 				new_current = c & 0x3F;
1904 				state = fw_newcurrent;
1905 			} else
1906 				return (DNS_R_BADLABELTYPE);
1907 			break;
1908 		case fw_ordinary:
1909 			if (downcase)
1910 				c = maptolower[c];
1911 			*ndata++ = c;
1912 			n--;
1913 			if (n == 0)
1914 				state = fw_start;
1915 			break;
1916 		case fw_newcurrent:
1917 			new_current *= 256;
1918 			new_current += c;
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;
1925 			state = fw_start;
1926 			break;
1927 		default:
1928 			FATAL_ERROR(__FILE__, __LINE__,
1929 				    "Unknown state %d", state);
1930 			/* Does not return. */
1931 		}
1932 	}
1933 
1934 	if (!done)
1935 		return (ISC_R_UNEXPECTEDEND);
1936 
1937 	name->ndata = (unsigned char *)target->base + target->used;
1938 	name->labels = labels;
1939 	name->length = nused;
1940 	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1941 
1942 	isc_buffer_forward(source, cused);
1943 	isc_buffer_add(target, name->length);
1944 
1945 	return (ISC_R_SUCCESS);
1946 
1947  full:
1948 	if (nmax == DNS_NAME_MAXWIRE)
1949 		/*
1950 		 * The name did not fit even though we had a buffer
1951 		 * big enough to fit a maximum-length name.
1952 		 */
1953 		return (DNS_R_NAMETOOLONG);
1954 	else
1955 		/*
1956 		 * The name might fit if only the caller could give us a
1957 		 * big enough buffer.
1958 		 */
1959 		return (ISC_R_NOSPACE);
1960 }
1961 
1962 isc_result_t
1963 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1964 		isc_buffer_t *target)
1965 {
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 */
1971 	dns_offsets_t clo;
1972 	dns_name_t clname;
1973 
1974 	/*
1975 	 * Convert 'name' into wire format, compressing it as specified by the
1976 	 * compression context 'cctx', and storing the result in 'target'.
1977 	 */
1978 
1979 	REQUIRE(VALID_NAME(name));
1980 	REQUIRE(cctx != NULL);
1981 	REQUIRE(ISC_BUFFER_VALID(target));
1982 
1983 	/*
1984 	 * If 'name' doesn't have an offsets table, make a clone which
1985 	 * has one.
1986 	 */
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));
1991 #endif
1992 		DNS_NAME_INIT(&clname, clo);
1993 		dns_name_clone(name, &clname);
1994 		name = &clname;
1995 	}
1996 	DNS_NAME_INIT(&gp, NULL);
1997 
1998 	offset = target->used;	/*XXX*/
1999 
2000 	methods = dns_compress_getmethods(cctx);
2001 
2002 	if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
2003 	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
2004 		gf = dns_compress_findglobal(cctx, name, &gp, &go);
2005 	else
2006 		gf = ISC_FALSE;
2007 
2008 	/*
2009 	 * If the offset is too high for 14 bit global compression, we're
2010 	 * out of luck.
2011 	 */
2012 	if (gf && go >= 0x4000)
2013 		gf = ISC_FALSE;
2014 
2015 	/*
2016 	 * Will the compression pointer reduce the message size?
2017 	 */
2018 	if (gf && (gp.length + 2) >= name->length)
2019 		gf = ISC_FALSE;
2020 
2021 	if (gf) {
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);
2027 		go |= 0xc000;
2028 		if (target->length - target->used < 2)
2029 			return (ISC_R_NOSPACE);
2030 		isc_buffer_putuint16(target, go);
2031 		if (gp.length != 0)
2032 			dns_compress_add(cctx, name, &gp, offset);
2033 	} else {
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);
2040 	}
2041 	return (ISC_R_SUCCESS);
2042 }
2043 
2044 isc_result_t
2045 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2046 		     isc_buffer_t *target)
2047 {
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;
2055 
2056 	/*
2057 	 * Concatenate 'prefix' and 'suffix'.
2058 	 */
2059 
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;
2069 	if (copy_prefix &&
2070 	    (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2071 		absolute = ISC_TRUE;
2072 		REQUIRE(!copy_suffix);
2073 	}
2074 	if (name == NULL) {
2075 		DNS_NAME_INIT(&tmp_name, odata);
2076 		name = &tmp_name;
2077 	}
2078 	if (target == NULL) {
2079 		INSIST(name->buffer != NULL);
2080 		target = name->buffer;
2081 		isc_buffer_clear(name->buffer);
2082 	}
2083 
2084 	REQUIRE(BINDABLE(name));
2085 
2086 	/*
2087 	 * Set up.
2088 	 */
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;
2093 	length = 0;
2094 	prefix_length = 0;
2095 	labels = 0;
2096 	if (copy_prefix) {
2097 		prefix_length = prefix->length;
2098 		length += prefix_length;
2099 		labels += prefix->labels;
2100 	}
2101 	if (copy_suffix) {
2102 		length += suffix->length;
2103 		labels += suffix->labels;
2104 	}
2105 	if (length > DNS_NAME_MAXWIRE) {
2106 		MAKE_EMPTY(name);
2107 		return (DNS_R_NAMETOOLONG);
2108 	}
2109 	if (length > nrem) {
2110 		MAKE_EMPTY(name);
2111 		return (ISC_R_NOSPACE);
2112 	}
2113 
2114 	if (copy_suffix) {
2115 		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2116 			absolute = ISC_TRUE;
2117 		memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2118 	}
2119 
2120 	/*
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
2123 	 * copy anything.
2124 	 */
2125 	if (copy_prefix && (prefix != name || prefix->buffer != target))
2126 		memmove(ndata, prefix->ndata, prefix_length);
2127 
2128 	name->ndata = ndata;
2129 	name->labels = labels;
2130 	name->length = length;
2131 	if (absolute)
2132 		name->attributes = DNS_NAMEATTR_ABSOLUTE;
2133 	else
2134 		name->attributes = 0;
2135 
2136 	if (name->labels > 0 && name->offsets != NULL) {
2137 		INIT_OFFSETS(name, offsets, odata);
2138 		set_offsets(name, offsets, NULL);
2139 	}
2140 
2141 	isc_buffer_add(target, name->length);
2142 
2143 	return (ISC_R_SUCCESS);
2144 }
2145 
2146 void
2147 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2148 	       dns_name_t *prefix, dns_name_t *suffix)
2149 
2150 {
2151 	unsigned int splitlabel;
2152 
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 &&
2160 		 BINDABLE(prefix)));
2161 	REQUIRE(suffix == NULL ||
2162 		(VALID_NAME(suffix) &&
2163 		 suffix->buffer != NULL &&
2164 		 BINDABLE(suffix)));
2165 
2166 	splitlabel = name->labels - suffixlabels;
2167 
2168 	if (prefix != NULL)
2169 		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2170 
2171 	if (suffix != NULL)
2172 		dns_name_getlabelsequence(name, splitlabel,
2173 					  suffixlabels, suffix);
2174 
2175 	return;
2176 }
2177 
2178 isc_result_t
2179 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2180 	     dns_name_t *target)
2181 {
2182 	/*
2183 	 * Make 'target' a dynamically allocated copy of 'source'.
2184 	 */
2185 
2186 	REQUIRE(VALID_NAME(source));
2187 	REQUIRE(source->length > 0);
2188 	REQUIRE(VALID_NAME(target));
2189 	REQUIRE(BINDABLE(target));
2190 
2191 	/*
2192 	 * Make 'target' empty in case of failure.
2193 	 */
2194 	MAKE_EMPTY(target);
2195 
2196 	target->ndata = isc_mem_get(mctx, source->length);
2197 	if (target->ndata == NULL)
2198 		return (ISC_R_NOMEMORY);
2199 
2200 	memmove(target->ndata, source->ndata, source->length);
2201 
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,
2210 				source->labels);
2211 		else
2212 			set_offsets(target, target->offsets, NULL);
2213 	}
2214 
2215 	return (ISC_R_SUCCESS);
2216 }
2217 
2218 isc_result_t
2219 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2220 			dns_name_t *target)
2221 {
2222 	/*
2223 	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2224 	 * 'target' will also have a dynamically allocated offsets table.
2225 	 */
2226 
2227 	REQUIRE(VALID_NAME(source));
2228 	REQUIRE(source->length > 0);
2229 	REQUIRE(VALID_NAME(target));
2230 	REQUIRE(BINDABLE(target));
2231 	REQUIRE(target->offsets == NULL);
2232 
2233 	/*
2234 	 * Make 'target' empty in case of failure.
2235 	 */
2236 	MAKE_EMPTY(target);
2237 
2238 	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2239 	if (target->ndata == NULL)
2240 		return (ISC_R_NOMEMORY);
2241 
2242 	memmove(target->ndata, source->ndata, source->length);
2243 
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);
2253 	else
2254 		set_offsets(target, target->offsets, NULL);
2255 
2256 	return (ISC_R_SUCCESS);
2257 }
2258 
2259 void
2260 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2261 	size_t size;
2262 
2263 	/*
2264 	 * Free 'name'.
2265 	 */
2266 
2267 	REQUIRE(VALID_NAME(name));
2268 	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2269 
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);
2275 }
2276 
2277 isc_result_t
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;
2283 	isc_region_t r;
2284 
2285 	/*
2286 	 * Send 'name' in DNSSEC canonical form to 'digest'.
2287 	 */
2288 
2289 	REQUIRE(VALID_NAME(name));
2290 	REQUIRE(digest != NULL);
2291 
2292 #if defined(__clang__)  && \
2293        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2294 	memset(&downname, 0, sizeof(downname));
2295 #endif
2296 	DNS_NAME_INIT(&downname, NULL);
2297 
2298 	isc_buffer_init(&buffer, data, sizeof(data));
2299 
2300 	result = dns_name_downcase(name, &downname, &buffer);
2301 	if (result != ISC_R_SUCCESS)
2302 		return (result);
2303 
2304 	isc_buffer_usedregion(&buffer, &r);
2305 
2306 	return ((digest)(arg, &r));
2307 }
2308 
2309 isc_boolean_t
2310 dns_name_dynamic(dns_name_t *name) {
2311 	REQUIRE(VALID_NAME(name));
2312 
2313 	/*
2314 	 * Returns whether there is dynamic memory associated with this name.
2315 	 */
2316 
2317 	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2318 		ISC_TRUE : ISC_FALSE);
2319 }
2320 
2321 isc_result_t
2322 dns_name_print(dns_name_t *name, FILE *stream) {
2323 	isc_result_t result;
2324 	isc_buffer_t b;
2325 	isc_region_t r;
2326 	char t[1024];
2327 
2328 	/*
2329 	 * Print 'name' on 'stream'.
2330 	 */
2331 
2332 	REQUIRE(VALID_NAME(name));
2333 
2334 	isc_buffer_init(&b, t, sizeof(t));
2335 	result = dns_name_totext(name, ISC_FALSE, &b);
2336 	if (result != ISC_R_SUCCESS)
2337 		return (result);
2338 	isc_buffer_usedregion(&b, &r);
2339 	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2340 
2341 	return (ISC_R_SUCCESS);
2342 }
2343 
2344 isc_result_t
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;
2349 	int res;
2350 
2351 	result = totext_filter_proc_key_init();
2352 	if (result != ISC_R_SUCCESS)
2353 		return (result);
2354 
2355 	/*
2356 	 * If we already have been here set / clear as appropriate.
2357 	 * Otherwise allocate memory.
2358 	 */
2359 	mem = isc_thread_key_getspecific(totext_filter_proc_key);
2360 	if (mem != NULL && proc != NULL) {
2361 		*mem = proc;
2362 		return (ISC_R_SUCCESS);
2363 	}
2364 	if (proc == NULL) {
2365 		isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2366 		res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2367 		if (res != 0)
2368 			result = ISC_R_UNEXPECTED;
2369 		return (result);
2370 	}
2371 
2372 	mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2373 	if (mem == NULL)
2374 		return (ISC_R_NOMEMORY);
2375 	*mem = proc;
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;
2379 	}
2380 	return (result);
2381 #else
2382 	totext_filter_proc = proc;
2383 	return (ISC_R_SUCCESS);
2384 #endif
2385 }
2386 
2387 void
2388 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2389 	isc_result_t result;
2390 	isc_buffer_t buf;
2391 
2392 	REQUIRE(size > 0);
2393 
2394 	/*
2395 	 * Leave room for null termination after buffer.
2396 	 */
2397 	isc_buffer_init(&buf, cp, size - 1);
2398 	result = dns_name_totext(name, ISC_TRUE, &buf);
2399 	if (result == ISC_R_SUCCESS) {
2400 		/*
2401 		 * Null terminate.
2402 		 */
2403 		isc_region_t r;
2404 		isc_buffer_usedregion(&buf, &r);
2405 		((char *) r.base)[r.length] = '\0';
2406 
2407 	} else
2408 		snprintf(cp, size, "<unknown>");
2409 }
2410 
2411 /*
2412  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2413  * memory.
2414  */
2415 isc_result_t
2416 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2417 	isc_result_t result;
2418 	isc_buffer_t buf;
2419 	isc_region_t reg;
2420 	char *p, txt[DNS_NAME_FORMATSIZE];
2421 
2422 	REQUIRE(VALID_NAME(name));
2423 	REQUIRE(target != NULL && *target == NULL);
2424 
2425 	isc_buffer_init(&buf, txt, sizeof(txt));
2426 	result = dns_name_totext(name, ISC_FALSE, &buf);
2427 	if (result != ISC_R_SUCCESS)
2428 		return (result);
2429 
2430 	isc_buffer_usedregion(&buf, &reg);
2431 	p = isc_mem_allocate(mctx, reg.length + 1);
2432 	memmove(p, (char *) reg.base, (int) reg.length);
2433 	p[reg.length] = '\0';
2434 
2435 	*target = p;
2436 	return (ISC_R_SUCCESS);
2437 }
2438 
2439 /*
2440  * dns_name_fromstring() -- convert directly from a string to a name,
2441  * allocating memory as needed
2442  */
2443 isc_result_t
2444 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2445 		    isc_mem_t *mctx)
2446 {
2447 	return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2448 }
2449 
2450 isc_result_t
2451 dns_name_fromstring2(dns_name_t *target, const char *src,
2452 		     const dns_name_t *origin, unsigned int options,
2453 		     isc_mem_t *mctx)
2454 {
2455 	isc_result_t result;
2456 	isc_buffer_t buf;
2457 	dns_fixedname_t fn;
2458 	dns_name_t *name;
2459 
2460 	REQUIRE(src != NULL);
2461 
2462 	isc_buffer_constinit(&buf, src, strlen(src));
2463 	isc_buffer_add(&buf, strlen(src));
2464 	if (BINDABLE(target) && target->buffer != NULL)
2465 		name = target;
2466 	else {
2467 		dns_fixedname_init(&fn);
2468 		name = dns_fixedname_name(&fn);
2469 	}
2470 
2471 	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2472 	if (result != ISC_R_SUCCESS)
2473 		return (result);
2474 
2475 	if (name != target)
2476 		result = dns_name_dupwithoffsets(name, mctx, target);
2477 	return (result);
2478 }
2479 
2480 isc_result_t
2481 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2482 	unsigned char *ndata;
2483 
2484 	/*
2485 	 * Make dest a copy of source.
2486 	 */
2487 
2488 	REQUIRE(VALID_NAME(source));
2489 	REQUIRE(VALID_NAME(dest));
2490 	REQUIRE(target != NULL || dest->buffer != NULL);
2491 
2492 	if (target == NULL) {
2493 		target = dest->buffer;
2494 		isc_buffer_clear(dest->buffer);
2495 	}
2496 
2497 	REQUIRE(BINDABLE(dest));
2498 
2499 	/*
2500 	 * Set up.
2501 	 */
2502 	if (target->length - target->used < source->length)
2503 		return (ISC_R_NOSPACE);
2504 
2505 	ndata = (unsigned char *)target->base + target->used;
2506 	dest->ndata = target->base;
2507 
2508 	memmove(ndata, source->ndata, source->length);
2509 
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;
2515 	else
2516 		dest->attributes = 0;
2517 
2518 	if (dest->labels > 0 && dest->offsets != NULL) {
2519 		if (source->offsets != NULL)
2520 			memmove(dest->offsets, source->offsets, source->labels);
2521 		else
2522 			set_offsets(dest, dest->offsets, NULL);
2523 	}
2524 
2525 	isc_buffer_add(target, dest->length);
2526 
2527 	return (ISC_R_SUCCESS);
2528 }
2529 
2530 void
2531 dns_name_destroy(void) {
2532 #ifdef ISC_PLATFORM_USETHREADS
2533 	RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2534 				  == ISC_R_SUCCESS);
2535 
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;
2541 	}
2542 	UNLOCK(&thread_key_mutex);
2543 
2544 #endif
2545 }
2546