name.c revision 254402
1/*
2 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id$ */
19
20/*! \file */
21
22#include <config.h>
23
24#include <ctype.h>
25#include <stdlib.h>
26
27#include <isc/buffer.h>
28#include <isc/hash.h>
29#include <isc/mem.h>
30#include <isc/once.h>
31#include <isc/print.h>
32#include <isc/string.h>
33#include <isc/thread.h>
34#include <isc/util.h>
35
36#include <dns/compress.h>
37#include <dns/fixedname.h>
38#include <dns/name.h>
39#include <dns/result.h>
40
41#define VALID_NAME(n)	ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
42
43typedef enum {
44	ft_init = 0,
45	ft_start,
46	ft_ordinary,
47	ft_initialescape,
48	ft_escape,
49	ft_escdecimal,
50	ft_at
51} ft_state;
52
53typedef enum {
54	fw_start = 0,
55	fw_ordinary,
56	fw_copy,
57	fw_newcurrent
58} fw_state;
59
60static char digitvalue[256] = {
61	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
62	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
63	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
64	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
65	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
66	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
67	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
68	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
69	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
77};
78
79static unsigned char maptolower[] = {
80	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
81	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
82	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
83	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
84	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
85	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
86	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
87	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
88	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
89	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
90	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
91	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
92	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
93	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
94	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
95	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
96	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
97	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
98	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
99	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
100	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
101	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
102	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
103	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
104	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
105	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
106	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
107	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
108	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
109	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
110	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
111	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
112};
113
114#define CONVERTTOASCII(c)
115#define CONVERTFROMASCII(c)
116
117#define INIT_OFFSETS(name, var, default) \
118	if (name->offsets != NULL) \
119		var = name->offsets; \
120	else \
121		var = default;
122
123#define SETUP_OFFSETS(name, var, default) \
124	if (name->offsets != NULL) \
125		var = name->offsets; \
126	else { \
127		var = default; \
128		set_offsets(name, var, NULL); \
129	}
130
131/*%
132 * Note:  If additional attributes are added that should not be set for
133 *	  empty names, MAKE_EMPTY() must be changed so it clears them.
134 */
135#define MAKE_EMPTY(name) \
136do { \
137	name->ndata = NULL; \
138	name->length = 0; \
139	name->labels = 0; \
140	name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
141} while (0);
142
143/*%
144 * A name is "bindable" if it can be set to point to a new value, i.e.
145 * name->ndata and name->length may be changed.
146 */
147#define BINDABLE(name) \
148	((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
149	 == 0)
150
151/*%
152 * Note that the name data must be a char array, not a string
153 * literal, to avoid compiler warnings about discarding
154 * the const attribute of a string.
155 */
156static unsigned char root_ndata[] = { '\0' };
157static unsigned char root_offsets[] = { 0 };
158
159static dns_name_t root =
160{
161	DNS_NAME_MAGIC,
162	root_ndata, 1, 1,
163	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
164	root_offsets, NULL,
165	{(void *)-1, (void *)-1},
166	{NULL, NULL}
167};
168
169/* XXXDCL make const? */
170LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
171
172static unsigned char wild_ndata[] = { '\001', '*' };
173static unsigned char wild_offsets[] = { 0 };
174
175static dns_name_t wild =
176{
177	DNS_NAME_MAGIC,
178	wild_ndata, 2, 1,
179	DNS_NAMEATTR_READONLY,
180	wild_offsets, NULL,
181	{(void *)-1, (void *)-1},
182	{NULL, NULL}
183};
184
185/* XXXDCL make const? */
186LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
187
188unsigned int
189dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
190
191/*
192 * dns_name_t to text post-conversion procedure.
193 */
194#ifdef ISC_PLATFORM_USETHREADS
195static int thread_key_initialized = 0;
196static isc_mutex_t thread_key_mutex;
197static isc_mem_t *thread_key_mctx = NULL;
198static isc_thread_key_t totext_filter_proc_key;
199static isc_once_t once = ISC_ONCE_INIT;
200#else
201static dns_name_totextfilter_t totext_filter_proc = NULL;
202#endif
203
204static void
205set_offsets(const dns_name_t *name, unsigned char *offsets,
206	    dns_name_t *set_name);
207
208void
209dns_name_init(dns_name_t *name, unsigned char *offsets) {
210	/*
211	 * Initialize 'name'.
212	 */
213	DNS_NAME_INIT(name, offsets);
214}
215
216void
217dns_name_reset(dns_name_t *name) {
218	REQUIRE(VALID_NAME(name));
219	REQUIRE(BINDABLE(name));
220
221	DNS_NAME_RESET(name);
222}
223
224void
225dns_name_invalidate(dns_name_t *name) {
226	/*
227	 * Make 'name' invalid.
228	 */
229
230	REQUIRE(VALID_NAME(name));
231
232	name->magic = 0;
233	name->ndata = NULL;
234	name->length = 0;
235	name->labels = 0;
236	name->attributes = 0;
237	name->offsets = NULL;
238	name->buffer = NULL;
239	ISC_LINK_INIT(name, link);
240}
241
242void
243dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
244	/*
245	 * Dedicate a buffer for use with 'name'.
246	 */
247
248	REQUIRE(VALID_NAME(name));
249	REQUIRE((buffer != NULL && name->buffer == NULL) ||
250		(buffer == NULL));
251
252	name->buffer = buffer;
253}
254
255isc_boolean_t
256dns_name_hasbuffer(const dns_name_t *name) {
257	/*
258	 * Does 'name' have a dedicated buffer?
259	 */
260
261	REQUIRE(VALID_NAME(name));
262
263	if (name->buffer != NULL)
264		return (ISC_TRUE);
265
266	return (ISC_FALSE);
267}
268
269isc_boolean_t
270dns_name_isabsolute(const dns_name_t *name) {
271
272	/*
273	 * Does 'name' end in the root label?
274	 */
275
276	REQUIRE(VALID_NAME(name));
277
278	if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
279		return (ISC_TRUE);
280	return (ISC_FALSE);
281}
282
283#define hyphenchar(c) ((c) == 0x2d)
284#define asterchar(c) ((c) == 0x2a)
285#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
286		      || ((c) >= 0x61 && (c) <= 0x7a))
287#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
288#define borderchar(c) (alphachar(c) || digitchar(c))
289#define middlechar(c) (borderchar(c) || hyphenchar(c))
290#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
291
292isc_boolean_t
293dns_name_ismailbox(const dns_name_t *name) {
294	unsigned char *ndata, ch;
295	unsigned int n;
296	isc_boolean_t first;
297
298	REQUIRE(VALID_NAME(name));
299	REQUIRE(name->labels > 0);
300	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
301
302	/*
303	 * Root label.
304	 */
305	if (name->length == 1)
306		return (ISC_TRUE);
307
308	ndata = name->ndata;
309	n = *ndata++;
310	INSIST(n <= 63);
311	while (n--) {
312		ch = *ndata++;
313		if (!domainchar(ch))
314			return (ISC_FALSE);
315	}
316
317	if (ndata == name->ndata + name->length)
318		return (ISC_FALSE);
319
320	/*
321	 * RFC292/RFC1123 hostname.
322	 */
323	while (ndata < (name->ndata + name->length)) {
324		n = *ndata++;
325		INSIST(n <= 63);
326		first = ISC_TRUE;
327		while (n--) {
328			ch = *ndata++;
329			if (first || n == 0) {
330				if (!borderchar(ch))
331					return (ISC_FALSE);
332			} else {
333				if (!middlechar(ch))
334					return (ISC_FALSE);
335			}
336			first = ISC_FALSE;
337		}
338	}
339	return (ISC_TRUE);
340}
341
342isc_boolean_t
343dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
344	unsigned char *ndata, ch;
345	unsigned int n;
346	isc_boolean_t first;
347
348	REQUIRE(VALID_NAME(name));
349	REQUIRE(name->labels > 0);
350	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
351
352	/*
353	 * Root label.
354	 */
355	if (name->length == 1)
356		return (ISC_TRUE);
357
358	/*
359	 * Skip wildcard if this is a ownername.
360	 */
361	ndata = name->ndata;
362	if (wildcard && ndata[0] == 1 && ndata[1] == '*')
363		ndata += 2;
364
365	/*
366	 * RFC292/RFC1123 hostname.
367	 */
368	while (ndata < (name->ndata + name->length)) {
369		n = *ndata++;
370		INSIST(n <= 63);
371		first = ISC_TRUE;
372		while (n--) {
373			ch = *ndata++;
374			if (first || n == 0) {
375				if (!borderchar(ch))
376					return (ISC_FALSE);
377			} else {
378				if (!middlechar(ch))
379					return (ISC_FALSE);
380			}
381			first = ISC_FALSE;
382		}
383	}
384	return (ISC_TRUE);
385}
386
387isc_boolean_t
388dns_name_iswildcard(const dns_name_t *name) {
389	unsigned char *ndata;
390
391	/*
392	 * Is 'name' a wildcard name?
393	 */
394
395	REQUIRE(VALID_NAME(name));
396	REQUIRE(name->labels > 0);
397
398	if (name->length >= 2) {
399		ndata = name->ndata;
400		if (ndata[0] == 1 && ndata[1] == '*')
401			return (ISC_TRUE);
402	}
403
404	return (ISC_FALSE);
405}
406
407isc_boolean_t
408dns_name_internalwildcard(const dns_name_t *name) {
409	unsigned char *ndata;
410	unsigned int count;
411	unsigned int label;
412
413	/*
414	 * Does 'name' contain a internal wildcard?
415	 */
416
417	REQUIRE(VALID_NAME(name));
418	REQUIRE(name->labels > 0);
419
420	/*
421	 * Skip first label.
422	 */
423	ndata = name->ndata;
424	count = *ndata++;
425	INSIST(count <= 63);
426	ndata += count;
427	label = 1;
428	/*
429	 * Check all but the last of the remaining labels.
430	 */
431	while (label + 1 < name->labels) {
432		count = *ndata++;
433		INSIST(count <= 63);
434		if (count == 1 && *ndata == '*')
435			return (ISC_TRUE);
436		ndata += count;
437		label++;
438	}
439	return (ISC_FALSE);
440}
441
442static inline unsigned int
443name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
444	unsigned int length;
445	const unsigned char *s;
446	unsigned int h = 0;
447	unsigned char c;
448
449	length = name->length;
450	if (length > 16)
451		length = 16;
452
453	/*
454	 * This hash function is similar to the one Ousterhout
455	 * uses in Tcl.
456	 */
457	s = name->ndata;
458	if (case_sensitive) {
459		while (length > 0) {
460			h += ( h << 3 ) + *s;
461			s++;
462			length--;
463		}
464	} else {
465		while (length > 0) {
466			c = maptolower[*s];
467			h += ( h << 3 ) + c;
468			s++;
469			length--;
470		}
471	}
472
473	return (h);
474}
475
476unsigned int
477dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
478	/*
479	 * Provide a hash value for 'name'.
480	 */
481	REQUIRE(VALID_NAME(name));
482
483	if (name->labels == 0)
484		return (0);
485
486	return (name_hash(name, case_sensitive));
487}
488
489unsigned int
490dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
491	/*
492	 * Provide a hash value for 'name'.
493	 */
494	REQUIRE(VALID_NAME(name));
495
496	if (name->labels == 0)
497		return (0);
498
499	return (isc_hash_calc((const unsigned char *)name->ndata,
500			      name->length, case_sensitive));
501}
502
503unsigned int
504dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
505	/*
506	 * This function was deprecated due to the breakage of the name space
507	 * convention.  We only keep this internally to provide binary backward
508	 * compatibility.
509	 */
510	REQUIRE(VALID_NAME(name));
511
512	return (dns_name_fullhash(name, case_sensitive));
513}
514
515unsigned int
516dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
517	unsigned char *offsets;
518	dns_offsets_t odata;
519	dns_name_t tname;
520	unsigned int h = 0;
521	unsigned int i;
522
523	/*
524	 * Provide a hash value for 'name'.
525	 */
526	REQUIRE(VALID_NAME(name));
527
528	if (name->labels == 0)
529		return (0);
530	else if (name->labels == 1)
531		return (name_hash(name, case_sensitive));
532
533	SETUP_OFFSETS(name, offsets, odata);
534	DNS_NAME_INIT(&tname, NULL);
535	tname.labels = 1;
536	h = 0;
537	for (i = 0; i < name->labels; i++) {
538		tname.ndata = name->ndata + offsets[i];
539		if (i == name->labels - 1)
540			tname.length = name->length - offsets[i];
541		else
542			tname.length = offsets[i + 1] - offsets[i];
543		h += name_hash(&tname, case_sensitive);
544	}
545
546	return (h);
547}
548
549dns_namereln_t
550dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
551		     int *orderp, unsigned int *nlabelsp)
552{
553	unsigned int l1, l2, l, count1, count2, count, nlabels;
554	int cdiff, ldiff, chdiff;
555	unsigned char *label1, *label2;
556	unsigned char *offsets1, *offsets2;
557	dns_offsets_t odata1, odata2;
558	dns_namereln_t namereln = dns_namereln_none;
559
560	/*
561	 * Determine the relative ordering under the DNSSEC order relation of
562	 * 'name1' and 'name2', and also determine the hierarchical
563	 * relationship of the names.
564	 *
565	 * Note: It makes no sense for one of the names to be relative and the
566	 * other absolute.  If both names are relative, then to be meaningfully
567	 * compared the caller must ensure that they are both relative to the
568	 * same domain.
569	 */
570
571	REQUIRE(VALID_NAME(name1));
572	REQUIRE(VALID_NAME(name2));
573	REQUIRE(orderp != NULL);
574	REQUIRE(nlabelsp != NULL);
575	/*
576	 * Either name1 is absolute and name2 is absolute, or neither is.
577	 */
578	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
579		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
580
581	SETUP_OFFSETS(name1, offsets1, odata1);
582	SETUP_OFFSETS(name2, offsets2, odata2);
583
584	nlabels = 0;
585	l1 = name1->labels;
586	l2 = name2->labels;
587	if (l2 > l1) {
588		l = l1;
589		ldiff = 0 - (l2 - l1);
590	} else {
591		l = l2;
592		ldiff = l1 - l2;
593	}
594
595	while (l > 0) {
596		l--;
597		l1--;
598		l2--;
599		label1 = &name1->ndata[offsets1[l1]];
600		label2 = &name2->ndata[offsets2[l2]];
601		count1 = *label1++;
602		count2 = *label2++;
603
604		/*
605		 * We dropped bitstring labels, and we don't support any
606		 * other extended label types.
607		 */
608		INSIST(count1 <= 63 && count2 <= 63);
609
610		cdiff = (int)count1 - (int)count2;
611		if (cdiff < 0)
612			count = count1;
613		else
614			count = count2;
615
616		while (count > 0) {
617			chdiff = (int)maptolower[*label1] -
618			    (int)maptolower[*label2];
619			if (chdiff != 0) {
620				*orderp = chdiff;
621				goto done;
622			}
623			count--;
624			label1++;
625			label2++;
626		}
627		if (cdiff != 0) {
628			*orderp = cdiff;
629			goto done;
630		}
631		nlabels++;
632	}
633
634	*orderp = ldiff;
635	if (ldiff < 0)
636		namereln = dns_namereln_contains;
637	else if (ldiff > 0)
638		namereln = dns_namereln_subdomain;
639	else
640		namereln = dns_namereln_equal;
641
642 done:
643	*nlabelsp = nlabels;
644
645	if (nlabels > 0 && namereln == dns_namereln_none)
646		namereln = dns_namereln_commonancestor;
647
648	return (namereln);
649}
650
651int
652dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
653	int order;
654	unsigned int nlabels;
655
656	/*
657	 * Determine the relative ordering under the DNSSEC order relation of
658	 * 'name1' and 'name2'.
659	 *
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
663	 * same domain.
664	 */
665
666	(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
667
668	return (order);
669}
670
671isc_boolean_t
672dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
673	unsigned int l, count;
674	unsigned char c;
675	unsigned char *label1, *label2;
676
677	/*
678	 * Are 'name1' and 'name2' equal?
679	 *
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
683	 * same domain.
684	 */
685
686	REQUIRE(VALID_NAME(name1));
687	REQUIRE(VALID_NAME(name2));
688	/*
689	 * Either name1 is absolute and name2 is absolute, or neither is.
690	 */
691	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
692		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
693
694	if (name1->length != name2->length)
695		return (ISC_FALSE);
696
697	l = name1->labels;
698
699	if (l != name2->labels)
700		return (ISC_FALSE);
701
702	label1 = name1->ndata;
703	label2 = name2->ndata;
704	while (l > 0) {
705		l--;
706		count = *label1++;
707		if (count != *label2++)
708			return (ISC_FALSE);
709
710		INSIST(count <= 63); /* no bitstring support */
711
712		while (count > 0) {
713			count--;
714			c = maptolower[*label1++];
715			if (c != maptolower[*label2++])
716				return (ISC_FALSE);
717		}
718	}
719
720	return (ISC_TRUE);
721}
722
723isc_boolean_t
724dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
725
726	/*
727	 * Are 'name1' and 'name2' equal?
728	 *
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
732	 * same domain.
733	 */
734
735	REQUIRE(VALID_NAME(name1));
736	REQUIRE(VALID_NAME(name2));
737	/*
738	 * Either name1 is absolute and name2 is absolute, or neither is.
739	 */
740	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
741		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
742
743	if (name1->length != name2->length)
744		return (ISC_FALSE);
745
746	if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
747		return (ISC_FALSE);
748
749	return (ISC_TRUE);
750}
751
752int
753dns_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;
757
758	/*
759	 * Compare two absolute names as rdata.
760	 */
761
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);
768
769	l1 = name1->labels;
770	l2 = name2->labels;
771
772	l = (l1 < l2) ? l1 : l2;
773
774	label1 = name1->ndata;
775	label2 = name2->ndata;
776	while (l > 0) {
777		l--;
778		count1 = *label1++;
779		count2 = *label2++;
780
781		/* no bitstring support */
782		INSIST(count1 <= 63 && count2 <= 63);
783
784		if (count1 != count2)
785			return ((count1 < count2) ? -1 : 1);
786		count = count1;
787		while (count > 0) {
788			count--;
789			c1 = maptolower[*label1++];
790			c2 = maptolower[*label2++];
791			if (c1 < c2)
792				return (-1);
793			else if (c1 > c2)
794				return (1);
795		}
796	}
797
798	/*
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.
804	 */
805	INSIST(l1 == l2);
806
807	return (0);
808}
809
810isc_boolean_t
811dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
812	int order;
813	unsigned int nlabels;
814	dns_namereln_t namereln;
815
816	/*
817	 * Is 'name1' a subdomain of 'name2'?
818	 *
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
822	 * same domain.
823	 */
824
825	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
826	if (namereln == dns_namereln_subdomain ||
827	    namereln == dns_namereln_equal)
828		return (ISC_TRUE);
829
830	return (ISC_FALSE);
831}
832
833isc_boolean_t
834dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
835	int order;
836	unsigned int nlabels, labels;
837	dns_name_t tname;
838
839	REQUIRE(VALID_NAME(name));
840	REQUIRE(name->labels > 0);
841	REQUIRE(VALID_NAME(wname));
842	labels = wname->labels;
843	REQUIRE(labels > 0);
844	REQUIRE(dns_name_iswildcard(wname));
845
846#if defined(__clang__)  && \
847       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
848	memset(&tname, 0, sizeof(tname));
849#endif
850	DNS_NAME_INIT(&tname, NULL);
851	dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
852	if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
853	    dns_namereln_subdomain)
854		return (ISC_TRUE);
855	return (ISC_FALSE);
856}
857
858unsigned int
859dns_name_countlabels(const dns_name_t *name) {
860	/*
861	 * How many labels does 'name' have?
862	 */
863
864	REQUIRE(VALID_NAME(name));
865
866	ENSURE(name->labels <= 128);
867
868	return (name->labels);
869}
870
871void
872dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
873	unsigned char *offsets;
874	dns_offsets_t odata;
875
876	/*
877	 * Make 'label' refer to the 'n'th least significant label of 'name'.
878	 */
879
880	REQUIRE(VALID_NAME(name));
881	REQUIRE(name->labels > 0);
882	REQUIRE(n < name->labels);
883	REQUIRE(label != NULL);
884
885	SETUP_OFFSETS(name, offsets, odata);
886
887	label->base = &name->ndata[offsets[n]];
888	if (n == name->labels - 1)
889		label->length = name->length - offsets[n];
890	else
891		label->length = offsets[n + 1] - offsets[n];
892}
893
894void
895dns_name_getlabelsequence(const dns_name_t *source,
896			  unsigned int first, unsigned int n,
897			  dns_name_t *target)
898{
899	unsigned char *offsets;
900	dns_offsets_t odata;
901	unsigned int firstoffset, endoffset;
902
903	/*
904	 * Make 'target' refer to the 'n' labels including and following
905	 * 'first' in 'source'.
906	 */
907
908	REQUIRE(VALID_NAME(source));
909	REQUIRE(VALID_NAME(target));
910	REQUIRE(first <= source->labels);
911	REQUIRE(n <= source->labels - first); /* note first+n could overflow */
912	REQUIRE(BINDABLE(target));
913
914	SETUP_OFFSETS(source, offsets, odata);
915
916	if (first == source->labels)
917		firstoffset = source->length;
918	else
919		firstoffset = offsets[first];
920
921	if (first + n == source->labels)
922		endoffset = source->length;
923	else
924		endoffset = offsets[first + n];
925
926	target->ndata = &source->ndata[firstoffset];
927	target->length = endoffset - firstoffset;
928
929	if (first + n == source->labels && n > 0 &&
930	    (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
931		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
932	else
933		target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
934
935	target->labels = n;
936
937	/*
938	 * If source and target are the same, and we're making target
939	 * a prefix of source, the offsets table is correct already
940	 * so we don't need to call set_offsets().
941	 */
942	if (target->offsets != NULL &&
943	    (target != source || first != 0))
944		set_offsets(target, target->offsets, NULL);
945}
946
947void
948dns_name_clone(const dns_name_t *source, dns_name_t *target) {
949
950	/*
951	 * Make 'target' refer to the same name as 'source'.
952	 */
953
954	REQUIRE(VALID_NAME(source));
955	REQUIRE(VALID_NAME(target));
956	REQUIRE(BINDABLE(target));
957
958	target->ndata = source->ndata;
959	target->length = source->length;
960	target->labels = source->labels;
961	target->attributes = source->attributes &
962		(unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
963				DNS_NAMEATTR_DYNOFFSETS);
964	if (target->offsets != NULL && source->labels > 0) {
965		if (source->offsets != NULL)
966			memcpy(target->offsets, source->offsets,
967			       source->labels);
968		else
969			set_offsets(target, target->offsets, NULL);
970	}
971}
972
973void
974dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
975	unsigned char *offsets;
976	dns_offsets_t odata;
977	unsigned int len;
978	isc_region_t r2;
979
980	/*
981	 * Make 'name' refer to region 'r'.
982	 */
983
984	REQUIRE(VALID_NAME(name));
985	REQUIRE(r != NULL);
986	REQUIRE(BINDABLE(name));
987
988	INIT_OFFSETS(name, offsets, odata);
989
990	if (name->buffer != NULL) {
991		isc_buffer_clear(name->buffer);
992		isc_buffer_availableregion(name->buffer, &r2);
993		len = (r->length < r2.length) ? r->length : r2.length;
994		if (len > DNS_NAME_MAXWIRE)
995			len = DNS_NAME_MAXWIRE;
996		memcpy(r2.base, r->base, len);
997		name->ndata = r2.base;
998		name->length = len;
999	} else {
1000		name->ndata = r->base;
1001		name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1002			r->length : DNS_NAME_MAXWIRE;
1003	}
1004
1005	if (r->length > 0)
1006		set_offsets(name, offsets, name);
1007	else {
1008		name->labels = 0;
1009		name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1010	}
1011
1012	if (name->buffer != NULL)
1013		isc_buffer_add(name->buffer, name->length);
1014}
1015
1016void
1017dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1018	/*
1019	 * Make 'r' refer to 'name'.
1020	 */
1021
1022	REQUIRE(VALID_NAME(name));
1023	REQUIRE(r != NULL);
1024
1025	DNS_NAME_TOREGION(name, r);
1026}
1027
1028isc_result_t
1029dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1030		  const dns_name_t *origin, unsigned int options,
1031		  isc_buffer_t *target)
1032{
1033	unsigned char *ndata, *label = NULL;
1034	char *tdata;
1035	char c;
1036	ft_state state;
1037	unsigned int value = 0, count = 0;
1038	unsigned int n1 = 0, n2 = 0;
1039	unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1040	isc_boolean_t done;
1041	unsigned char *offsets;
1042	dns_offsets_t odata;
1043	isc_boolean_t downcase;
1044
1045	/*
1046	 * Convert the textual representation of a DNS name at source
1047	 * into uncompressed wire form stored in target.
1048	 *
1049	 * Notes:
1050	 *	Relative domain names will have 'origin' appended to them
1051	 *	unless 'origin' is NULL, in which case relative domain names
1052	 *	will remain relative.
1053	 */
1054
1055	REQUIRE(VALID_NAME(name));
1056	REQUIRE(ISC_BUFFER_VALID(source));
1057	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1058		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1059
1060	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1061
1062	if (target == NULL && name->buffer != NULL) {
1063		target = name->buffer;
1064		isc_buffer_clear(target);
1065	}
1066
1067	REQUIRE(BINDABLE(name));
1068
1069	INIT_OFFSETS(name, offsets, odata);
1070	offsets[0] = 0;
1071
1072	/*
1073	 * Make 'name' empty in case of failure.
1074	 */
1075	MAKE_EMPTY(name);
1076
1077	/*
1078	 * Set up the state machine.
1079	 */
1080	tdata = (char *)source->base + source->current;
1081	tlen = isc_buffer_remaininglength(source);
1082	tused = 0;
1083	ndata = isc_buffer_used(target);
1084	nrem = isc_buffer_availablelength(target);
1085	if (nrem > 255)
1086		nrem = 255;
1087	nused = 0;
1088	labels = 0;
1089	done = ISC_FALSE;
1090	state = ft_init;
1091
1092	while (nrem > 0 && tlen > 0 && !done) {
1093		c = *tdata++;
1094		tlen--;
1095		tused++;
1096
1097		switch (state) {
1098		case ft_init:
1099			/*
1100			 * Is this the root name?
1101			 */
1102			if (c == '.') {
1103				if (tlen != 0)
1104					return (DNS_R_EMPTYLABEL);
1105				labels++;
1106				*ndata++ = 0;
1107				nrem--;
1108				nused++;
1109				done = ISC_TRUE;
1110				break;
1111			}
1112			if (c == '@' && tlen == 0) {
1113				state = ft_at;
1114				break;
1115			}
1116
1117			/* FALLTHROUGH */
1118		case ft_start:
1119			label = ndata;
1120			ndata++;
1121			nrem--;
1122			nused++;
1123			count = 0;
1124			if (c == '\\') {
1125				state = ft_initialescape;
1126				break;
1127			}
1128			state = ft_ordinary;
1129			if (nrem == 0)
1130				return (ISC_R_NOSPACE);
1131			/* FALLTHROUGH */
1132		case ft_ordinary:
1133			if (c == '.') {
1134				if (count == 0)
1135					return (DNS_R_EMPTYLABEL);
1136				*label = count;
1137				labels++;
1138				INSIST(labels <= 127);
1139				offsets[labels] = nused;
1140				if (tlen == 0) {
1141					labels++;
1142					*ndata++ = 0;
1143					nrem--;
1144					nused++;
1145					done = ISC_TRUE;
1146				}
1147				state = ft_start;
1148			} else if (c == '\\') {
1149				state = ft_escape;
1150			} else {
1151				if (count >= 63)
1152					return (DNS_R_LABELTOOLONG);
1153				count++;
1154				CONVERTTOASCII(c);
1155				if (downcase)
1156					c = maptolower[(int)c];
1157				*ndata++ = c;
1158				nrem--;
1159				nused++;
1160			}
1161			break;
1162		case ft_initialescape:
1163			if (c == '[') {
1164				/*
1165				 * This looks like a bitstring label, which
1166				 * was deprecated.  Intentionally drop it.
1167				 */
1168				return (DNS_R_BADLABELTYPE);
1169			}
1170			state = ft_escape;
1171			POST(state);
1172			/* FALLTHROUGH */
1173		case ft_escape:
1174			if (!isdigit(c & 0xff)) {
1175				if (count >= 63)
1176					return (DNS_R_LABELTOOLONG);
1177				count++;
1178				CONVERTTOASCII(c);
1179				if (downcase)
1180					c = maptolower[(int)c];
1181				*ndata++ = c;
1182				nrem--;
1183				nused++;
1184				state = ft_ordinary;
1185				break;
1186			}
1187			digits = 0;
1188			value = 0;
1189			state = ft_escdecimal;
1190			/* FALLTHROUGH */
1191		case ft_escdecimal:
1192			if (!isdigit(c & 0xff))
1193				return (DNS_R_BADESCAPE);
1194			value *= 10;
1195			value += digitvalue[(int)c];
1196			digits++;
1197			if (digits == 3) {
1198				if (value > 255)
1199					return (DNS_R_BADESCAPE);
1200				if (count >= 63)
1201					return (DNS_R_LABELTOOLONG);
1202				count++;
1203				if (downcase)
1204					value = maptolower[value];
1205				*ndata++ = value;
1206				nrem--;
1207				nused++;
1208				state = ft_ordinary;
1209			}
1210			break;
1211		default:
1212			FATAL_ERROR(__FILE__, __LINE__,
1213				    "Unexpected state %d", state);
1214			/* Does not return. */
1215		}
1216	}
1217
1218	if (!done) {
1219		if (nrem == 0)
1220			return (ISC_R_NOSPACE);
1221		INSIST(tlen == 0);
1222		if (state != ft_ordinary && state != ft_at)
1223			return (ISC_R_UNEXPECTEDEND);
1224		if (state == ft_ordinary) {
1225			INSIST(count != 0);
1226			*label = count;
1227			labels++;
1228			INSIST(labels <= 127);
1229			offsets[labels] = nused;
1230		}
1231		if (origin != NULL) {
1232			if (nrem < origin->length)
1233				return (ISC_R_NOSPACE);
1234			label = origin->ndata;
1235			n1 = origin->length;
1236			nrem -= n1;
1237			POST(nrem);
1238			while (n1 > 0) {
1239				n2 = *label++;
1240				INSIST(n2 <= 63); /* no bitstring support */
1241				*ndata++ = n2;
1242				n1 -= n2 + 1;
1243				nused += n2 + 1;
1244				while (n2 > 0) {
1245					c = *label++;
1246					if (downcase)
1247						c = maptolower[(int)c];
1248					*ndata++ = c;
1249					n2--;
1250				}
1251				labels++;
1252				if (n1 > 0) {
1253					INSIST(labels <= 127);
1254					offsets[labels] = nused;
1255				}
1256			}
1257			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1258				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1259		}
1260	} else
1261		name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1262
1263	name->ndata = (unsigned char *)target->base + target->used;
1264	name->labels = labels;
1265	name->length = nused;
1266
1267	isc_buffer_forward(source, tused);
1268	isc_buffer_add(target, name->length);
1269
1270	return (ISC_R_SUCCESS);
1271}
1272
1273#ifdef ISC_PLATFORM_USETHREADS
1274static void
1275free_specific(void *arg) {
1276	dns_name_totextfilter_t *mem = arg;
1277	isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1278	/* Stop use being called again. */
1279	(void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1280}
1281
1282static void
1283thread_key_mutex_init(void) {
1284	RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1285}
1286
1287static isc_result_t
1288totext_filter_proc_key_init(void) {
1289	isc_result_t result;
1290
1291	/*
1292	 * We need the call to isc_once_do() to support profiled mutex
1293	 * otherwise thread_key_mutex could be initialized at compile time.
1294	 */
1295	result = isc_once_do(&once, thread_key_mutex_init);
1296	if (result != ISC_R_SUCCESS)
1297		return (result);
1298
1299	if (!thread_key_initialized) {
1300		LOCK(&thread_key_mutex);
1301		if (thread_key_mctx == NULL)
1302			result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1303		if (result != ISC_R_SUCCESS)
1304			goto unlock;
1305		isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1306		isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1307
1308		if (!thread_key_initialized &&
1309		     isc_thread_key_create(&totext_filter_proc_key,
1310					   free_specific) != 0) {
1311			result = ISC_R_FAILURE;
1312			isc_mem_detach(&thread_key_mctx);
1313		} else
1314			thread_key_initialized = 1;
1315 unlock:
1316		UNLOCK(&thread_key_mutex);
1317	}
1318	return (result);
1319}
1320#endif
1321
1322isc_result_t
1323dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1324		isc_buffer_t *target)
1325{
1326	unsigned int options = DNS_NAME_MASTERFILE;
1327
1328	if (omit_final_dot)
1329		options |= DNS_NAME_OMITFINALDOT;
1330	return (dns_name_totext2(name, options, target));
1331}
1332
1333isc_result_t
1334dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1335	return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1336}
1337
1338isc_result_t
1339dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1340{
1341	unsigned char *ndata;
1342	char *tdata;
1343	unsigned int nlen, tlen;
1344	unsigned char c;
1345	unsigned int trem, count;
1346	unsigned int labels;
1347	isc_boolean_t saw_root = ISC_FALSE;
1348	unsigned int oused = target->used;
1349#ifdef ISC_PLATFORM_USETHREADS
1350	dns_name_totextfilter_t *mem;
1351	dns_name_totextfilter_t totext_filter_proc = NULL;
1352	isc_result_t result;
1353#endif
1354	isc_boolean_t omit_final_dot =
1355		ISC_TF(options & DNS_NAME_OMITFINALDOT);
1356
1357	/*
1358	 * This function assumes the name is in proper uncompressed
1359	 * wire format.
1360	 */
1361	REQUIRE(VALID_NAME(name));
1362	REQUIRE(ISC_BUFFER_VALID(target));
1363
1364#ifdef ISC_PLATFORM_USETHREADS
1365	result = totext_filter_proc_key_init();
1366	if (result != ISC_R_SUCCESS)
1367		return (result);
1368#endif
1369	ndata = name->ndata;
1370	nlen = name->length;
1371	labels = name->labels;
1372	tdata = isc_buffer_used(target);
1373	tlen = isc_buffer_availablelength(target);
1374
1375	trem = tlen;
1376
1377	if (labels == 0 && nlen == 0) {
1378		/*
1379		 * Special handling for an empty name.
1380		 */
1381		if (trem == 0)
1382			return (ISC_R_NOSPACE);
1383
1384		/*
1385		 * The names of these booleans are misleading in this case.
1386		 * This empty name is not necessarily from the root node of
1387		 * the DNS root zone, nor is a final dot going to be included.
1388		 * They need to be set this way, though, to keep the "@"
1389		 * from being trounced.
1390		 */
1391		saw_root = ISC_TRUE;
1392		omit_final_dot = ISC_FALSE;
1393		*tdata++ = '@';
1394		trem--;
1395
1396		/*
1397		 * Skip the while() loop.
1398		 */
1399		nlen = 0;
1400	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1401		/*
1402		 * Special handling for the root label.
1403		 */
1404		if (trem == 0)
1405			return (ISC_R_NOSPACE);
1406
1407		saw_root = ISC_TRUE;
1408		omit_final_dot = ISC_FALSE;
1409		*tdata++ = '.';
1410		trem--;
1411
1412		/*
1413		 * Skip the while() loop.
1414		 */
1415		nlen = 0;
1416	}
1417
1418	while (labels > 0 && nlen > 0 && trem > 0) {
1419		labels--;
1420		count = *ndata++;
1421		nlen--;
1422		if (count == 0) {
1423			saw_root = ISC_TRUE;
1424			break;
1425		}
1426		if (count < 64) {
1427			INSIST(nlen >= count);
1428			while (count > 0) {
1429				c = *ndata;
1430				switch (c) {
1431				/* Special modifiers in zone files. */
1432				case 0x40: /* '@' */
1433				case 0x24: /* '$' */
1434					if ((options & DNS_NAME_MASTERFILE) == 0)
1435						goto no_escape;
1436					/* FALLTHROUGH */
1437				case 0x22: /* '"' */
1438				case 0x28: /* '(' */
1439				case 0x29: /* ')' */
1440				case 0x2E: /* '.' */
1441				case 0x3B: /* ';' */
1442				case 0x5C: /* '\\' */
1443					if (trem < 2)
1444						return (ISC_R_NOSPACE);
1445					*tdata++ = '\\';
1446					CONVERTFROMASCII(c);
1447					*tdata++ = c;
1448					ndata++;
1449					trem -= 2;
1450					nlen--;
1451					break;
1452				no_escape:
1453				default:
1454					if (c > 0x20 && c < 0x7f) {
1455						if (trem == 0)
1456							return (ISC_R_NOSPACE);
1457						CONVERTFROMASCII(c);
1458						*tdata++ = c;
1459						ndata++;
1460						trem--;
1461						nlen--;
1462					} else {
1463						if (trem < 4)
1464							return (ISC_R_NOSPACE);
1465						*tdata++ = 0x5c;
1466						*tdata++ = 0x30 +
1467							   ((c / 100) % 10);
1468						*tdata++ = 0x30 +
1469							   ((c / 10) % 10);
1470						*tdata++ = 0x30 + (c % 10);
1471						trem -= 4;
1472						ndata++;
1473						nlen--;
1474					}
1475				}
1476				count--;
1477			}
1478		} else {
1479			FATAL_ERROR(__FILE__, __LINE__,
1480				    "Unexpected label type %02x", count);
1481			/* NOTREACHED */
1482		}
1483
1484		/*
1485		 * The following assumes names are absolute.  If not, we
1486		 * fix things up later.  Note that this means that in some
1487		 * cases one more byte of text buffer is required than is
1488		 * needed in the final output.
1489		 */
1490		if (trem == 0)
1491			return (ISC_R_NOSPACE);
1492		*tdata++ = '.';
1493		trem--;
1494	}
1495
1496	if (nlen != 0 && trem == 0)
1497		return (ISC_R_NOSPACE);
1498
1499	if (!saw_root || omit_final_dot)
1500		trem++;
1501
1502	isc_buffer_add(target, tlen - trem);
1503
1504#ifdef ISC_PLATFORM_USETHREADS
1505	mem = isc_thread_key_getspecific(totext_filter_proc_key);
1506	if (mem != NULL)
1507		totext_filter_proc = *mem;
1508#endif
1509	if (totext_filter_proc != NULL)
1510		return ((*totext_filter_proc)(target, oused, saw_root));
1511
1512	return (ISC_R_SUCCESS);
1513}
1514
1515isc_result_t
1516dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1517			isc_buffer_t *target)
1518{
1519	unsigned char *ndata;
1520	char *tdata;
1521	unsigned int nlen, tlen;
1522	unsigned char c;
1523	unsigned int trem, count;
1524	unsigned int labels;
1525
1526	/*
1527	 * This function assumes the name is in proper uncompressed
1528	 * wire format.
1529	 */
1530	REQUIRE(VALID_NAME(name));
1531	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1532	REQUIRE(ISC_BUFFER_VALID(target));
1533
1534	ndata = name->ndata;
1535	nlen = name->length;
1536	labels = name->labels;
1537	tdata = isc_buffer_used(target);
1538	tlen = isc_buffer_availablelength(target);
1539
1540	trem = tlen;
1541
1542	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1543		/*
1544		 * Special handling for the root label.
1545		 */
1546		if (trem == 0)
1547			return (ISC_R_NOSPACE);
1548
1549		omit_final_dot = ISC_FALSE;
1550		*tdata++ = '.';
1551		trem--;
1552
1553		/*
1554		 * Skip the while() loop.
1555		 */
1556		nlen = 0;
1557	}
1558
1559	while (labels > 0 && nlen > 0 && trem > 0) {
1560		labels--;
1561		count = *ndata++;
1562		nlen--;
1563		if (count == 0)
1564			break;
1565		if (count < 64) {
1566			INSIST(nlen >= count);
1567			while (count > 0) {
1568				c = *ndata;
1569				if ((c >= 0x30 && c <= 0x39) || /* digit */
1570				    (c >= 0x41 && c <= 0x5A) ||	/* uppercase */
1571				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
1572				    c == 0x2D ||		/* hyphen */
1573				    c == 0x5F)			/* underscore */
1574				{
1575					if (trem == 0)
1576						return (ISC_R_NOSPACE);
1577					/* downcase */
1578					if (c >= 0x41 && c <= 0x5A)
1579						c += 0x20;
1580					CONVERTFROMASCII(c);
1581					*tdata++ = c;
1582					ndata++;
1583					trem--;
1584					nlen--;
1585				} else {
1586					if (trem < 3)
1587						return (ISC_R_NOSPACE);
1588					sprintf(tdata, "%%%02X", c);
1589					tdata += 3;
1590					trem -= 3;
1591					ndata++;
1592					nlen--;
1593				}
1594				count--;
1595			}
1596		} else {
1597			FATAL_ERROR(__FILE__, __LINE__,
1598				    "Unexpected label type %02x", count);
1599			/* NOTREACHED */
1600		}
1601
1602		/*
1603		 * The following assumes names are absolute.  If not, we
1604		 * fix things up later.  Note that this means that in some
1605		 * cases one more byte of text buffer is required than is
1606		 * needed in the final output.
1607		 */
1608		if (trem == 0)
1609			return (ISC_R_NOSPACE);
1610		*tdata++ = '.';
1611		trem--;
1612	}
1613
1614	if (nlen != 0 && trem == 0)
1615		return (ISC_R_NOSPACE);
1616
1617	if (omit_final_dot)
1618		trem++;
1619
1620	isc_buffer_add(target, tlen - trem);
1621
1622	return (ISC_R_SUCCESS);
1623}
1624
1625isc_result_t
1626dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1627	unsigned char *sndata, *ndata;
1628	unsigned int nlen, count, labels;
1629	isc_buffer_t buffer;
1630
1631	/*
1632	 * Downcase 'source'.
1633	 */
1634
1635	REQUIRE(VALID_NAME(source));
1636	REQUIRE(VALID_NAME(name));
1637	if (source == name) {
1638		REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1639		isc_buffer_init(&buffer, source->ndata, source->length);
1640		target = &buffer;
1641		ndata = source->ndata;
1642	} else {
1643		REQUIRE(BINDABLE(name));
1644		REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1645			(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1646		if (target == NULL) {
1647			target = name->buffer;
1648			isc_buffer_clear(name->buffer);
1649		}
1650		ndata = (unsigned char *)target->base + target->used;
1651		name->ndata = ndata;
1652	}
1653
1654	sndata = source->ndata;
1655	nlen = source->length;
1656	labels = source->labels;
1657
1658	if (nlen > (target->length - target->used)) {
1659		MAKE_EMPTY(name);
1660		return (ISC_R_NOSPACE);
1661	}
1662
1663	while (labels > 0 && nlen > 0) {
1664		labels--;
1665		count = *sndata++;
1666		*ndata++ = count;
1667		nlen--;
1668		if (count < 64) {
1669			INSIST(nlen >= count);
1670			while (count > 0) {
1671				*ndata++ = maptolower[(*sndata++)];
1672				nlen--;
1673				count--;
1674			}
1675		} else {
1676			FATAL_ERROR(__FILE__, __LINE__,
1677				    "Unexpected label type %02x", count);
1678			/* Does not return. */
1679		}
1680	}
1681
1682	if (source != name) {
1683		name->labels = source->labels;
1684		name->length = source->length;
1685		if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1686			name->attributes = DNS_NAMEATTR_ABSOLUTE;
1687		else
1688			name->attributes = 0;
1689		if (name->labels > 0 && name->offsets != NULL)
1690			set_offsets(name, name->offsets, NULL);
1691	}
1692
1693	isc_buffer_add(target, name->length);
1694
1695	return (ISC_R_SUCCESS);
1696}
1697
1698static void
1699set_offsets(const dns_name_t *name, unsigned char *offsets,
1700	    dns_name_t *set_name)
1701{
1702	unsigned int offset, count, length, nlabels;
1703	unsigned char *ndata;
1704	isc_boolean_t absolute;
1705
1706	ndata = name->ndata;
1707	length = name->length;
1708	offset = 0;
1709	nlabels = 0;
1710	absolute = ISC_FALSE;
1711	while (offset != length) {
1712		INSIST(nlabels < 128);
1713		offsets[nlabels++] = offset;
1714		count = *ndata++;
1715		offset++;
1716		INSIST(count <= 63);
1717		offset += count;
1718		ndata += count;
1719		INSIST(offset <= length);
1720		if (count == 0) {
1721			absolute = ISC_TRUE;
1722			break;
1723		}
1724	}
1725	if (set_name != NULL) {
1726		INSIST(set_name == name);
1727
1728		set_name->labels = nlabels;
1729		set_name->length = offset;
1730		if (absolute)
1731			set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1732		else
1733			set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1734	}
1735	INSIST(nlabels == name->labels);
1736	INSIST(offset == name->length);
1737}
1738
1739isc_result_t
1740dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1741		  dns_decompress_t *dctx, unsigned int options,
1742		  isc_buffer_t *target)
1743{
1744	unsigned char *cdata, *ndata;
1745	unsigned int cused; /* Bytes of compressed name data used */
1746	unsigned int nused, labels, n, nmax;
1747	unsigned int current, new_current, biggest_pointer;
1748	isc_boolean_t done;
1749	fw_state state = fw_start;
1750	unsigned int c;
1751	unsigned char *offsets;
1752	dns_offsets_t odata;
1753	isc_boolean_t downcase;
1754	isc_boolean_t seen_pointer;
1755
1756	/*
1757	 * Copy the possibly-compressed name at source into target,
1758	 * decompressing it.  Loop prevention is performed by checking
1759	 * the new pointer against biggest_pointer.
1760	 */
1761
1762	REQUIRE(VALID_NAME(name));
1763	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1764		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1765
1766	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1767
1768	if (target == NULL && name->buffer != NULL) {
1769		target = name->buffer;
1770		isc_buffer_clear(target);
1771	}
1772
1773	REQUIRE(dctx != NULL);
1774	REQUIRE(BINDABLE(name));
1775
1776	INIT_OFFSETS(name, offsets, odata);
1777
1778	/*
1779	 * Make 'name' empty in case of failure.
1780	 */
1781	MAKE_EMPTY(name);
1782
1783	/*
1784	 * Initialize things to make the compiler happy; they're not required.
1785	 */
1786	n = 0;
1787	new_current = 0;
1788
1789	/*
1790	 * Set up.
1791	 */
1792	labels = 0;
1793	done = ISC_FALSE;
1794
1795	ndata = isc_buffer_used(target);
1796	nused = 0;
1797	seen_pointer = ISC_FALSE;
1798
1799	/*
1800	 * Find the maximum number of uncompressed target name
1801	 * bytes we are willing to generate.  This is the smaller
1802	 * of the available target buffer length and the
1803	 * maximum legal domain name length (255).
1804	 */
1805	nmax = isc_buffer_availablelength(target);
1806	if (nmax > DNS_NAME_MAXWIRE)
1807		nmax = DNS_NAME_MAXWIRE;
1808
1809	cdata = isc_buffer_current(source);
1810	cused = 0;
1811
1812	current = source->current;
1813	biggest_pointer = current;
1814
1815	/*
1816	 * Note:  The following code is not optimized for speed, but
1817	 * rather for correctness.  Speed will be addressed in the future.
1818	 */
1819
1820	while (current < source->active && !done) {
1821		c = *cdata++;
1822		current++;
1823		if (!seen_pointer)
1824			cused++;
1825
1826		switch (state) {
1827		case fw_start:
1828			if (c < 64) {
1829				offsets[labels] = nused;
1830				labels++;
1831				if (nused + c + 1 > nmax)
1832					goto full;
1833				nused += c + 1;
1834				*ndata++ = c;
1835				if (c == 0)
1836					done = ISC_TRUE;
1837				n = c;
1838				state = fw_ordinary;
1839			} else if (c >= 128 && c < 192) {
1840				/*
1841				 * 14 bit local compression pointer.
1842				 * Local compression is no longer an
1843				 * IETF draft.
1844				 */
1845				return (DNS_R_BADLABELTYPE);
1846			} else if (c >= 192) {
1847				/*
1848				 * Ordinary 14-bit pointer.
1849				 */
1850				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1851				    0)
1852					return (DNS_R_DISALLOWED);
1853				new_current = c & 0x3F;
1854				n = 1;
1855				state = fw_newcurrent;
1856			} else
1857				return (DNS_R_BADLABELTYPE);
1858			break;
1859		case fw_ordinary:
1860			if (downcase)
1861				c = maptolower[c];
1862			/* FALLTHROUGH */
1863		case fw_copy:
1864			*ndata++ = c;
1865			n--;
1866			if (n == 0)
1867				state = fw_start;
1868			break;
1869		case fw_newcurrent:
1870			new_current *= 256;
1871			new_current += c;
1872			n--;
1873			if (n != 0)
1874				break;
1875			if (new_current >= biggest_pointer)
1876				return (DNS_R_BADPOINTER);
1877			biggest_pointer = new_current;
1878			current = new_current;
1879			cdata = (unsigned char *)source->base + current;
1880			seen_pointer = ISC_TRUE;
1881			state = fw_start;
1882			break;
1883		default:
1884			FATAL_ERROR(__FILE__, __LINE__,
1885				    "Unknown state %d", state);
1886			/* Does not return. */
1887		}
1888	}
1889
1890	if (!done)
1891		return (ISC_R_UNEXPECTEDEND);
1892
1893	name->ndata = (unsigned char *)target->base + target->used;
1894	name->labels = labels;
1895	name->length = nused;
1896	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1897
1898	isc_buffer_forward(source, cused);
1899	isc_buffer_add(target, name->length);
1900
1901	return (ISC_R_SUCCESS);
1902
1903 full:
1904	if (nmax == DNS_NAME_MAXWIRE)
1905		/*
1906		 * The name did not fit even though we had a buffer
1907		 * big enough to fit a maximum-length name.
1908		 */
1909		return (DNS_R_NAMETOOLONG);
1910	else
1911		/*
1912		 * The name might fit if only the caller could give us a
1913		 * big enough buffer.
1914		 */
1915		return (ISC_R_NOSPACE);
1916}
1917
1918isc_result_t
1919dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1920		isc_buffer_t *target)
1921{
1922	unsigned int methods;
1923	isc_uint16_t offset;
1924	dns_name_t gp;	/* Global compression prefix */
1925	isc_boolean_t gf;	/* Global compression target found */
1926	isc_uint16_t go;	/* Global compression offset */
1927	dns_offsets_t clo;
1928	dns_name_t clname;
1929
1930	/*
1931	 * Convert 'name' into wire format, compressing it as specified by the
1932	 * compression context 'cctx', and storing the result in 'target'.
1933	 */
1934
1935	REQUIRE(VALID_NAME(name));
1936	REQUIRE(cctx != NULL);
1937	REQUIRE(ISC_BUFFER_VALID(target));
1938
1939	/*
1940	 * If 'name' doesn't have an offsets table, make a clone which
1941	 * has one.
1942	 */
1943	if (name->offsets == NULL) {
1944#if defined(__clang__)  && \
1945       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1946		memset(&clname, 0, sizeof(clname));
1947#endif
1948		DNS_NAME_INIT(&clname, clo);
1949		dns_name_clone(name, &clname);
1950		name = &clname;
1951	}
1952	DNS_NAME_INIT(&gp, NULL);
1953
1954	offset = target->used;	/*XXX*/
1955
1956	methods = dns_compress_getmethods(cctx);
1957
1958	if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1959	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1960		gf = dns_compress_findglobal(cctx, name, &gp, &go);
1961	else
1962		gf = ISC_FALSE;
1963
1964	/*
1965	 * If the offset is too high for 14 bit global compression, we're
1966	 * out of luck.
1967	 */
1968	if (gf && go >= 0x4000)
1969		gf = ISC_FALSE;
1970
1971	/*
1972	 * Will the compression pointer reduce the message size?
1973	 */
1974	if (gf && (gp.length + 2) >= name->length)
1975		gf = ISC_FALSE;
1976
1977	if (gf) {
1978		if (target->length - target->used < gp.length)
1979			return (ISC_R_NOSPACE);
1980		(void)memcpy((unsigned char *)target->base + target->used,
1981			     gp.ndata, (size_t)gp.length);
1982		isc_buffer_add(target, gp.length);
1983		go |= 0xc000;
1984		if (target->length - target->used < 2)
1985			return (ISC_R_NOSPACE);
1986		isc_buffer_putuint16(target, go);
1987		if (gp.length != 0)
1988			dns_compress_add(cctx, name, &gp, offset);
1989	} else {
1990		if (target->length - target->used < name->length)
1991			return (ISC_R_NOSPACE);
1992		(void)memcpy((unsigned char *)target->base + target->used,
1993			     name->ndata, (size_t)name->length);
1994		isc_buffer_add(target, name->length);
1995		dns_compress_add(cctx, name, name, offset);
1996	}
1997	return (ISC_R_SUCCESS);
1998}
1999
2000isc_result_t
2001dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2002		     isc_buffer_t *target)
2003{
2004	unsigned char *ndata, *offsets;
2005	unsigned int nrem, labels, prefix_length, length;
2006	isc_boolean_t copy_prefix = ISC_TRUE;
2007	isc_boolean_t copy_suffix = ISC_TRUE;
2008	isc_boolean_t absolute = ISC_FALSE;
2009	dns_name_t tmp_name;
2010	dns_offsets_t odata;
2011
2012	/*
2013	 * Concatenate 'prefix' and 'suffix'.
2014	 */
2015
2016	REQUIRE(prefix == NULL || VALID_NAME(prefix));
2017	REQUIRE(suffix == NULL || VALID_NAME(suffix));
2018	REQUIRE(name == NULL || VALID_NAME(name));
2019	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2020		(target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2021	if (prefix == NULL || prefix->labels == 0)
2022		copy_prefix = ISC_FALSE;
2023	if (suffix == NULL || suffix->labels == 0)
2024		copy_suffix = ISC_FALSE;
2025	if (copy_prefix &&
2026	    (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2027		absolute = ISC_TRUE;
2028		REQUIRE(!copy_suffix);
2029	}
2030	if (name == NULL) {
2031		DNS_NAME_INIT(&tmp_name, odata);
2032		name = &tmp_name;
2033	}
2034	if (target == NULL) {
2035		INSIST(name->buffer != NULL);
2036		target = name->buffer;
2037		isc_buffer_clear(name->buffer);
2038	}
2039
2040	REQUIRE(BINDABLE(name));
2041
2042	/*
2043	 * Set up.
2044	 */
2045	nrem = target->length - target->used;
2046	ndata = (unsigned char *)target->base + target->used;
2047	if (nrem > DNS_NAME_MAXWIRE)
2048		nrem = DNS_NAME_MAXWIRE;
2049	length = 0;
2050	prefix_length = 0;
2051	labels = 0;
2052	if (copy_prefix) {
2053		prefix_length = prefix->length;
2054		length += prefix_length;
2055		labels += prefix->labels;
2056	}
2057	if (copy_suffix) {
2058		length += suffix->length;
2059		labels += suffix->labels;
2060	}
2061	if (length > DNS_NAME_MAXWIRE) {
2062		MAKE_EMPTY(name);
2063		return (DNS_R_NAMETOOLONG);
2064	}
2065	if (length > nrem) {
2066		MAKE_EMPTY(name);
2067		return (ISC_R_NOSPACE);
2068	}
2069
2070	if (copy_suffix) {
2071		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2072			absolute = ISC_TRUE;
2073		if (suffix == name && suffix->buffer == target)
2074			memmove(ndata + prefix_length, suffix->ndata,
2075				suffix->length);
2076		else
2077			memcpy(ndata + prefix_length, suffix->ndata,
2078			       suffix->length);
2079	}
2080
2081	/*
2082	 * If 'prefix' and 'name' are the same object, and the object has
2083	 * a dedicated buffer, and we're using it, then we don't have to
2084	 * copy anything.
2085	 */
2086	if (copy_prefix && (prefix != name || prefix->buffer != target))
2087		memcpy(ndata, prefix->ndata, prefix_length);
2088
2089	name->ndata = ndata;
2090	name->labels = labels;
2091	name->length = length;
2092	if (absolute)
2093		name->attributes = DNS_NAMEATTR_ABSOLUTE;
2094	else
2095		name->attributes = 0;
2096
2097	if (name->labels > 0 && name->offsets != NULL) {
2098		INIT_OFFSETS(name, offsets, odata);
2099		set_offsets(name, offsets, NULL);
2100	}
2101
2102	isc_buffer_add(target, name->length);
2103
2104	return (ISC_R_SUCCESS);
2105}
2106
2107void
2108dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2109	       dns_name_t *prefix, dns_name_t *suffix)
2110
2111{
2112	unsigned int splitlabel;
2113
2114	REQUIRE(VALID_NAME(name));
2115	REQUIRE(suffixlabels > 0);
2116	REQUIRE(suffixlabels < name->labels);
2117	REQUIRE(prefix != NULL || suffix != NULL);
2118	REQUIRE(prefix == NULL ||
2119		(VALID_NAME(prefix) &&
2120		 prefix->buffer != NULL &&
2121		 BINDABLE(prefix)));
2122	REQUIRE(suffix == NULL ||
2123		(VALID_NAME(suffix) &&
2124		 suffix->buffer != NULL &&
2125		 BINDABLE(suffix)));
2126
2127	splitlabel = name->labels - suffixlabels;
2128
2129	if (prefix != NULL)
2130		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2131
2132	if (suffix != NULL)
2133		dns_name_getlabelsequence(name, splitlabel,
2134					  suffixlabels, suffix);
2135
2136	return;
2137}
2138
2139isc_result_t
2140dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2141	     dns_name_t *target)
2142{
2143	/*
2144	 * Make 'target' a dynamically allocated copy of 'source'.
2145	 */
2146
2147	REQUIRE(VALID_NAME(source));
2148	REQUIRE(source->length > 0);
2149	REQUIRE(VALID_NAME(target));
2150	REQUIRE(BINDABLE(target));
2151
2152	/*
2153	 * Make 'target' empty in case of failure.
2154	 */
2155	MAKE_EMPTY(target);
2156
2157	target->ndata = isc_mem_get(mctx, source->length);
2158	if (target->ndata == NULL)
2159		return (ISC_R_NOMEMORY);
2160
2161	memcpy(target->ndata, source->ndata, source->length);
2162
2163	target->length = source->length;
2164	target->labels = source->labels;
2165	target->attributes = DNS_NAMEATTR_DYNAMIC;
2166	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2167		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2168	if (target->offsets != NULL) {
2169		if (source->offsets != NULL)
2170			memcpy(target->offsets, source->offsets,
2171			       source->labels);
2172		else
2173			set_offsets(target, target->offsets, NULL);
2174	}
2175
2176	return (ISC_R_SUCCESS);
2177}
2178
2179isc_result_t
2180dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2181			dns_name_t *target)
2182{
2183	/*
2184	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2185	 * 'target' will also have a dynamically allocated offsets table.
2186	 */
2187
2188	REQUIRE(VALID_NAME(source));
2189	REQUIRE(source->length > 0);
2190	REQUIRE(VALID_NAME(target));
2191	REQUIRE(BINDABLE(target));
2192	REQUIRE(target->offsets == NULL);
2193
2194	/*
2195	 * Make 'target' empty in case of failure.
2196	 */
2197	MAKE_EMPTY(target);
2198
2199	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2200	if (target->ndata == NULL)
2201		return (ISC_R_NOMEMORY);
2202
2203	memcpy(target->ndata, source->ndata, source->length);
2204
2205	target->length = source->length;
2206	target->labels = source->labels;
2207	target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2208		DNS_NAMEATTR_READONLY;
2209	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2210		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2211	target->offsets = target->ndata + source->length;
2212	if (source->offsets != NULL)
2213		memcpy(target->offsets, source->offsets, source->labels);
2214	else
2215		set_offsets(target, target->offsets, NULL);
2216
2217	return (ISC_R_SUCCESS);
2218}
2219
2220void
2221dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2222	size_t size;
2223
2224	/*
2225	 * Free 'name'.
2226	 */
2227
2228	REQUIRE(VALID_NAME(name));
2229	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2230
2231	size = name->length;
2232	if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2233		size += name->labels;
2234	isc_mem_put(mctx, name->ndata, size);
2235	dns_name_invalidate(name);
2236}
2237
2238isc_result_t
2239dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2240	dns_name_t downname;
2241	unsigned char data[256];
2242	isc_buffer_t buffer;
2243	isc_result_t result;
2244	isc_region_t r;
2245
2246	/*
2247	 * Send 'name' in DNSSEC canonical form to 'digest'.
2248	 */
2249
2250	REQUIRE(VALID_NAME(name));
2251	REQUIRE(digest != NULL);
2252
2253#if defined(__clang__)  && \
2254       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2255	memset(&downname, 0, sizeof(downname));
2256#endif
2257	DNS_NAME_INIT(&downname, NULL);
2258
2259	isc_buffer_init(&buffer, data, sizeof(data));
2260
2261	result = dns_name_downcase(name, &downname, &buffer);
2262	if (result != ISC_R_SUCCESS)
2263		return (result);
2264
2265	isc_buffer_usedregion(&buffer, &r);
2266
2267	return ((digest)(arg, &r));
2268}
2269
2270isc_boolean_t
2271dns_name_dynamic(dns_name_t *name) {
2272	REQUIRE(VALID_NAME(name));
2273
2274	/*
2275	 * Returns whether there is dynamic memory associated with this name.
2276	 */
2277
2278	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2279		ISC_TRUE : ISC_FALSE);
2280}
2281
2282isc_result_t
2283dns_name_print(dns_name_t *name, FILE *stream) {
2284	isc_result_t result;
2285	isc_buffer_t b;
2286	isc_region_t r;
2287	char t[1024];
2288
2289	/*
2290	 * Print 'name' on 'stream'.
2291	 */
2292
2293	REQUIRE(VALID_NAME(name));
2294
2295	isc_buffer_init(&b, t, sizeof(t));
2296	result = dns_name_totext(name, ISC_FALSE, &b);
2297	if (result != ISC_R_SUCCESS)
2298		return (result);
2299	isc_buffer_usedregion(&b, &r);
2300	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2301
2302	return (ISC_R_SUCCESS);
2303}
2304
2305isc_result_t
2306dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2307#ifdef ISC_PLATFORM_USETHREADS
2308	isc_result_t result;
2309	dns_name_totextfilter_t *mem;
2310	int res;
2311
2312	result = totext_filter_proc_key_init();
2313	if (result != ISC_R_SUCCESS)
2314		return (result);
2315
2316	/*
2317	 * If we already have been here set / clear as appropriate.
2318	 * Otherwise allocate memory.
2319	 */
2320	mem = isc_thread_key_getspecific(totext_filter_proc_key);
2321	if (mem != NULL && proc != NULL) {
2322		*mem = proc;
2323		return (ISC_R_SUCCESS);
2324	}
2325	if (proc == NULL) {
2326		isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2327		res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2328		if (res != 0)
2329			result = ISC_R_UNEXPECTED;
2330		return (result);
2331	}
2332
2333	mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2334	if (mem == NULL)
2335		return (ISC_R_NOMEMORY);
2336	*mem = proc;
2337	if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2338		isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2339		result = ISC_R_UNEXPECTED;
2340	}
2341	return (result);
2342#else
2343	totext_filter_proc = proc;
2344	return (ISC_R_SUCCESS);
2345#endif
2346}
2347
2348void
2349dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2350	isc_result_t result;
2351	isc_buffer_t buf;
2352
2353	REQUIRE(size > 0);
2354
2355	/*
2356	 * Leave room for null termination after buffer.
2357	 */
2358	isc_buffer_init(&buf, cp, size - 1);
2359	result = dns_name_totext(name, ISC_TRUE, &buf);
2360	if (result == ISC_R_SUCCESS) {
2361		/*
2362		 * Null terminate.
2363		 */
2364		isc_region_t r;
2365		isc_buffer_usedregion(&buf, &r);
2366		((char *) r.base)[r.length] = '\0';
2367
2368	} else
2369		snprintf(cp, size, "<unknown>");
2370}
2371
2372/*
2373 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2374 * memory.
2375 */
2376isc_result_t
2377dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2378	isc_result_t result;
2379	isc_buffer_t buf;
2380	isc_region_t reg;
2381	char *p, txt[DNS_NAME_FORMATSIZE];
2382
2383	REQUIRE(VALID_NAME(name));
2384	REQUIRE(target != NULL && *target == NULL);
2385
2386	isc_buffer_init(&buf, txt, sizeof(txt));
2387	result = dns_name_totext(name, ISC_FALSE, &buf);
2388	if (result != ISC_R_SUCCESS)
2389		return (result);
2390
2391	isc_buffer_usedregion(&buf, &reg);
2392	p = isc_mem_allocate(mctx, reg.length + 1);
2393	memcpy(p, (char *) reg.base, (int) reg.length);
2394	p[reg.length] = '\0';
2395
2396	*target = p;
2397	return (ISC_R_SUCCESS);
2398}
2399
2400/*
2401 * dns_name_fromstring() -- convert directly from a string to a name,
2402 * allocating memory as needed
2403 */
2404isc_result_t
2405dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2406		    isc_mem_t *mctx)
2407{
2408	return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2409}
2410
2411isc_result_t
2412dns_name_fromstring2(dns_name_t *target, const char *src,
2413		     const dns_name_t *origin, unsigned int options,
2414		     isc_mem_t *mctx)
2415{
2416	isc_result_t result;
2417	isc_buffer_t buf;
2418	dns_fixedname_t fn;
2419	dns_name_t *name;
2420
2421	REQUIRE(src != NULL);
2422
2423	isc_buffer_constinit(&buf, src, strlen(src));
2424	isc_buffer_add(&buf, strlen(src));
2425	if (BINDABLE(target) && target->buffer != NULL)
2426		name = target;
2427	else {
2428		dns_fixedname_init(&fn);
2429		name = dns_fixedname_name(&fn);
2430	}
2431
2432	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2433	if (result != ISC_R_SUCCESS)
2434		return (result);
2435
2436	if (name != target)
2437		result = dns_name_dupwithoffsets(name, mctx, target);
2438	return (result);
2439}
2440
2441isc_result_t
2442dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2443	unsigned char *ndata;
2444
2445	/*
2446	 * Make dest a copy of source.
2447	 */
2448
2449	REQUIRE(VALID_NAME(source));
2450	REQUIRE(VALID_NAME(dest));
2451	REQUIRE(target != NULL || dest->buffer != NULL);
2452
2453	if (target == NULL) {
2454		target = dest->buffer;
2455		isc_buffer_clear(dest->buffer);
2456	}
2457
2458	REQUIRE(BINDABLE(dest));
2459
2460	/*
2461	 * Set up.
2462	 */
2463	if (target->length - target->used < source->length)
2464		return (ISC_R_NOSPACE);
2465
2466	ndata = (unsigned char *)target->base + target->used;
2467	dest->ndata = target->base;
2468
2469	memcpy(ndata, source->ndata, source->length);
2470
2471	dest->ndata = ndata;
2472	dest->labels = source->labels;
2473	dest->length = source->length;
2474	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2475		dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2476	else
2477		dest->attributes = 0;
2478
2479	if (dest->labels > 0 && dest->offsets != NULL) {
2480		if (source->offsets != NULL)
2481			memcpy(dest->offsets, source->offsets, source->labels);
2482		else
2483			set_offsets(dest, dest->offsets, NULL);
2484	}
2485
2486	isc_buffer_add(target, dest->length);
2487
2488	return (ISC_R_SUCCESS);
2489}
2490
2491void
2492dns_name_destroy(void) {
2493#ifdef ISC_PLATFORM_USETHREADS
2494	RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2495				  == ISC_R_SUCCESS);
2496
2497	LOCK(&thread_key_mutex);
2498	if (thread_key_initialized) {
2499		isc_mem_detach(&thread_key_mctx);
2500		isc_thread_key_delete(totext_filter_proc_key);
2501		thread_key_initialized = 0;
2502	}
2503	UNLOCK(&thread_key_mutex);
2504
2505#endif
2506}
2507