name.c revision 267654
1/*
2 * Copyright (C) 2004-2014  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	if (name1 == name2) {
582		*orderp = 0;
583		return (dns_namereln_equal);
584	}
585
586	SETUP_OFFSETS(name1, offsets1, odata1);
587	SETUP_OFFSETS(name2, offsets2, odata2);
588
589	nlabels = 0;
590	l1 = name1->labels;
591	l2 = name2->labels;
592	if (l2 > l1) {
593		l = l1;
594		ldiff = 0 - (l2 - l1);
595	} else {
596		l = l2;
597		ldiff = l1 - l2;
598	}
599
600	while (l > 0) {
601		l--;
602		l1--;
603		l2--;
604		label1 = &name1->ndata[offsets1[l1]];
605		label2 = &name2->ndata[offsets2[l2]];
606		count1 = *label1++;
607		count2 = *label2++;
608
609		/*
610		 * We dropped bitstring labels, and we don't support any
611		 * other extended label types.
612		 */
613		INSIST(count1 <= 63 && count2 <= 63);
614
615		cdiff = (int)count1 - (int)count2;
616		if (cdiff < 0)
617			count = count1;
618		else
619			count = count2;
620
621		while (count > 0) {
622			chdiff = (int)maptolower[*label1] -
623			    (int)maptolower[*label2];
624			if (chdiff != 0) {
625				*orderp = chdiff;
626				goto done;
627			}
628			count--;
629			label1++;
630			label2++;
631		}
632		if (cdiff != 0) {
633			*orderp = cdiff;
634			goto done;
635		}
636		nlabels++;
637	}
638
639	*orderp = ldiff;
640	if (ldiff < 0)
641		namereln = dns_namereln_contains;
642	else if (ldiff > 0)
643		namereln = dns_namereln_subdomain;
644	else
645		namereln = dns_namereln_equal;
646
647 done:
648	*nlabelsp = nlabels;
649
650	if (nlabels > 0 && namereln == dns_namereln_none)
651		namereln = dns_namereln_commonancestor;
652
653	return (namereln);
654}
655
656int
657dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
658	int order;
659	unsigned int nlabels;
660
661	/*
662	 * Determine the relative ordering under the DNSSEC order relation of
663	 * 'name1' and 'name2'.
664	 *
665	 * Note: It makes no sense for one of the names to be relative and the
666	 * other absolute.  If both names are relative, then to be meaningfully
667	 * compared the caller must ensure that they are both relative to the
668	 * same domain.
669	 */
670
671	(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
672
673	return (order);
674}
675
676isc_boolean_t
677dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
678	unsigned int l, count;
679	unsigned char c;
680	unsigned char *label1, *label2;
681
682	/*
683	 * Are 'name1' and 'name2' equal?
684	 *
685	 * Note: It makes no sense for one of the names to be relative and the
686	 * other absolute.  If both names are relative, then to be meaningfully
687	 * compared the caller must ensure that they are both relative to the
688	 * same domain.
689	 */
690
691	REQUIRE(VALID_NAME(name1));
692	REQUIRE(VALID_NAME(name2));
693	/*
694	 * Either name1 is absolute and name2 is absolute, or neither is.
695	 */
696	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
697		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
698
699	if (name1 == name2)
700		return (ISC_TRUE);
701
702	if (name1->length != name2->length)
703		return (ISC_FALSE);
704
705	l = name1->labels;
706
707	if (l != name2->labels)
708		return (ISC_FALSE);
709
710	label1 = name1->ndata;
711	label2 = name2->ndata;
712	while (l > 0) {
713		l--;
714		count = *label1++;
715		if (count != *label2++)
716			return (ISC_FALSE);
717
718		INSIST(count <= 63); /* no bitstring support */
719
720		while (count > 0) {
721			count--;
722			c = maptolower[*label1++];
723			if (c != maptolower[*label2++])
724				return (ISC_FALSE);
725		}
726	}
727
728	return (ISC_TRUE);
729}
730
731isc_boolean_t
732dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
733
734	/*
735	 * Are 'name1' and 'name2' equal?
736	 *
737	 * Note: It makes no sense for one of the names to be relative and the
738	 * other absolute.  If both names are relative, then to be meaningfully
739	 * compared the caller must ensure that they are both relative to the
740	 * same domain.
741	 */
742
743	REQUIRE(VALID_NAME(name1));
744	REQUIRE(VALID_NAME(name2));
745	/*
746	 * Either name1 is absolute and name2 is absolute, or neither is.
747	 */
748	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
749		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
750
751	if (name1->length != name2->length)
752		return (ISC_FALSE);
753
754	if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
755		return (ISC_FALSE);
756
757	return (ISC_TRUE);
758}
759
760int
761dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
762	unsigned int l1, l2, l, count1, count2, count;
763	unsigned char c1, c2;
764	unsigned char *label1, *label2;
765
766	/*
767	 * Compare two absolute names as rdata.
768	 */
769
770	REQUIRE(VALID_NAME(name1));
771	REQUIRE(name1->labels > 0);
772	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
773	REQUIRE(VALID_NAME(name2));
774	REQUIRE(name2->labels > 0);
775	REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
776
777	l1 = name1->labels;
778	l2 = name2->labels;
779
780	l = (l1 < l2) ? l1 : l2;
781
782	label1 = name1->ndata;
783	label2 = name2->ndata;
784	while (l > 0) {
785		l--;
786		count1 = *label1++;
787		count2 = *label2++;
788
789		/* no bitstring support */
790		INSIST(count1 <= 63 && count2 <= 63);
791
792		if (count1 != count2)
793			return ((count1 < count2) ? -1 : 1);
794		count = count1;
795		while (count > 0) {
796			count--;
797			c1 = maptolower[*label1++];
798			c2 = maptolower[*label2++];
799			if (c1 < c2)
800				return (-1);
801			else if (c1 > c2)
802				return (1);
803		}
804	}
805
806	/*
807	 * If one name had more labels than the other, their common
808	 * prefix must have been different because the shorter name
809	 * ended with the root label and the longer one can't have
810	 * a root label in the middle of it.  Therefore, if we get
811	 * to this point, the lengths must be equal.
812	 */
813	INSIST(l1 == l2);
814
815	return (0);
816}
817
818isc_boolean_t
819dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
820	int order;
821	unsigned int nlabels;
822	dns_namereln_t namereln;
823
824	/*
825	 * Is 'name1' a subdomain of 'name2'?
826	 *
827	 * Note: It makes no sense for one of the names to be relative and the
828	 * other absolute.  If both names are relative, then to be meaningfully
829	 * compared the caller must ensure that they are both relative to the
830	 * same domain.
831	 */
832
833	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
834	if (namereln == dns_namereln_subdomain ||
835	    namereln == dns_namereln_equal)
836		return (ISC_TRUE);
837
838	return (ISC_FALSE);
839}
840
841isc_boolean_t
842dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
843	int order;
844	unsigned int nlabels, labels;
845	dns_name_t tname;
846
847	REQUIRE(VALID_NAME(name));
848	REQUIRE(name->labels > 0);
849	REQUIRE(VALID_NAME(wname));
850	labels = wname->labels;
851	REQUIRE(labels > 0);
852	REQUIRE(dns_name_iswildcard(wname));
853
854#if defined(__clang__)  && \
855       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
856	memset(&tname, 0, sizeof(tname));
857#endif
858	DNS_NAME_INIT(&tname, NULL);
859	dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
860	if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
861	    dns_namereln_subdomain)
862		return (ISC_TRUE);
863	return (ISC_FALSE);
864}
865
866unsigned int
867dns_name_countlabels(const dns_name_t *name) {
868	/*
869	 * How many labels does 'name' have?
870	 */
871
872	REQUIRE(VALID_NAME(name));
873
874	ENSURE(name->labels <= 128);
875
876	return (name->labels);
877}
878
879void
880dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
881	unsigned char *offsets;
882	dns_offsets_t odata;
883
884	/*
885	 * Make 'label' refer to the 'n'th least significant label of 'name'.
886	 */
887
888	REQUIRE(VALID_NAME(name));
889	REQUIRE(name->labels > 0);
890	REQUIRE(n < name->labels);
891	REQUIRE(label != NULL);
892
893	SETUP_OFFSETS(name, offsets, odata);
894
895	label->base = &name->ndata[offsets[n]];
896	if (n == name->labels - 1)
897		label->length = name->length - offsets[n];
898	else
899		label->length = offsets[n + 1] - offsets[n];
900}
901
902void
903dns_name_getlabelsequence(const dns_name_t *source,
904			  unsigned int first, unsigned int n,
905			  dns_name_t *target)
906{
907	unsigned char *offsets;
908	dns_offsets_t odata;
909	unsigned int firstoffset, endoffset;
910
911	/*
912	 * Make 'target' refer to the 'n' labels including and following
913	 * 'first' in 'source'.
914	 */
915
916	REQUIRE(VALID_NAME(source));
917	REQUIRE(VALID_NAME(target));
918	REQUIRE(first <= source->labels);
919	REQUIRE(n <= source->labels - first); /* note first+n could overflow */
920	REQUIRE(BINDABLE(target));
921
922	SETUP_OFFSETS(source, offsets, odata);
923
924	if (first == source->labels)
925		firstoffset = source->length;
926	else
927		firstoffset = offsets[first];
928
929	if (first + n == source->labels)
930		endoffset = source->length;
931	else
932		endoffset = offsets[first + n];
933
934	target->ndata = &source->ndata[firstoffset];
935	target->length = endoffset - firstoffset;
936
937	if (first + n == source->labels && n > 0 &&
938	    (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
939		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
940	else
941		target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
942
943	target->labels = n;
944
945	/*
946	 * If source and target are the same, and we're making target
947	 * a prefix of source, the offsets table is correct already
948	 * so we don't need to call set_offsets().
949	 */
950	if (target->offsets != NULL &&
951	    (target != source || first != 0))
952		set_offsets(target, target->offsets, NULL);
953}
954
955void
956dns_name_clone(const dns_name_t *source, dns_name_t *target) {
957
958	/*
959	 * Make 'target' refer to the same name as 'source'.
960	 */
961
962	REQUIRE(VALID_NAME(source));
963	REQUIRE(VALID_NAME(target));
964	REQUIRE(BINDABLE(target));
965
966	target->ndata = source->ndata;
967	target->length = source->length;
968	target->labels = source->labels;
969	target->attributes = source->attributes &
970		(unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
971				DNS_NAMEATTR_DYNOFFSETS);
972	if (target->offsets != NULL && source->labels > 0) {
973		if (source->offsets != NULL)
974			memmove(target->offsets, source->offsets,
975				source->labels);
976		else
977			set_offsets(target, target->offsets, NULL);
978	}
979}
980
981void
982dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
983	unsigned char *offsets;
984	dns_offsets_t odata;
985	unsigned int len;
986	isc_region_t r2;
987
988	/*
989	 * Make 'name' refer to region 'r'.
990	 */
991
992	REQUIRE(VALID_NAME(name));
993	REQUIRE(r != NULL);
994	REQUIRE(BINDABLE(name));
995
996	INIT_OFFSETS(name, offsets, odata);
997
998	if (name->buffer != NULL) {
999		isc_buffer_clear(name->buffer);
1000		isc_buffer_availableregion(name->buffer, &r2);
1001		len = (r->length < r2.length) ? r->length : r2.length;
1002		if (len > DNS_NAME_MAXWIRE)
1003			len = DNS_NAME_MAXWIRE;
1004		memmove(r2.base, r->base, len);
1005		name->ndata = r2.base;
1006		name->length = len;
1007	} else {
1008		name->ndata = r->base;
1009		name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1010			r->length : DNS_NAME_MAXWIRE;
1011	}
1012
1013	if (r->length > 0)
1014		set_offsets(name, offsets, name);
1015	else {
1016		name->labels = 0;
1017		name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1018	}
1019
1020	if (name->buffer != NULL)
1021		isc_buffer_add(name->buffer, name->length);
1022}
1023
1024void
1025dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1026	/*
1027	 * Make 'r' refer to 'name'.
1028	 */
1029
1030	REQUIRE(VALID_NAME(name));
1031	REQUIRE(r != NULL);
1032
1033	DNS_NAME_TOREGION(name, r);
1034}
1035
1036isc_result_t
1037dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1038		  const dns_name_t *origin, unsigned int options,
1039		  isc_buffer_t *target)
1040{
1041	unsigned char *ndata, *label = NULL;
1042	char *tdata;
1043	char c;
1044	ft_state state;
1045	unsigned int value = 0, count = 0;
1046	unsigned int n1 = 0, n2 = 0;
1047	unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1048	isc_boolean_t done;
1049	unsigned char *offsets;
1050	dns_offsets_t odata;
1051	isc_boolean_t downcase;
1052
1053	/*
1054	 * Convert the textual representation of a DNS name at source
1055	 * into uncompressed wire form stored in target.
1056	 *
1057	 * Notes:
1058	 *	Relative domain names will have 'origin' appended to them
1059	 *	unless 'origin' is NULL, in which case relative domain names
1060	 *	will remain relative.
1061	 */
1062
1063	REQUIRE(VALID_NAME(name));
1064	REQUIRE(ISC_BUFFER_VALID(source));
1065	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1066		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1067
1068	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1069
1070	if (target == NULL && name->buffer != NULL) {
1071		target = name->buffer;
1072		isc_buffer_clear(target);
1073	}
1074
1075	REQUIRE(BINDABLE(name));
1076
1077	INIT_OFFSETS(name, offsets, odata);
1078	offsets[0] = 0;
1079
1080	/*
1081	 * Make 'name' empty in case of failure.
1082	 */
1083	MAKE_EMPTY(name);
1084
1085	/*
1086	 * Set up the state machine.
1087	 */
1088	tdata = (char *)source->base + source->current;
1089	tlen = isc_buffer_remaininglength(source);
1090	tused = 0;
1091	ndata = isc_buffer_used(target);
1092	nrem = isc_buffer_availablelength(target);
1093	if (nrem > 255)
1094		nrem = 255;
1095	nused = 0;
1096	labels = 0;
1097	done = ISC_FALSE;
1098	state = ft_init;
1099
1100	while (nrem > 0 && tlen > 0 && !done) {
1101		c = *tdata++;
1102		tlen--;
1103		tused++;
1104
1105		switch (state) {
1106		case ft_init:
1107			/*
1108			 * Is this the root name?
1109			 */
1110			if (c == '.') {
1111				if (tlen != 0)
1112					return (DNS_R_EMPTYLABEL);
1113				labels++;
1114				*ndata++ = 0;
1115				nrem--;
1116				nused++;
1117				done = ISC_TRUE;
1118				break;
1119			}
1120			if (c == '@' && tlen == 0) {
1121				state = ft_at;
1122				break;
1123			}
1124
1125			/* FALLTHROUGH */
1126		case ft_start:
1127			label = ndata;
1128			ndata++;
1129			nrem--;
1130			nused++;
1131			count = 0;
1132			if (c == '\\') {
1133				state = ft_initialescape;
1134				break;
1135			}
1136			state = ft_ordinary;
1137			if (nrem == 0)
1138				return (ISC_R_NOSPACE);
1139			/* FALLTHROUGH */
1140		case ft_ordinary:
1141			if (c == '.') {
1142				if (count == 0)
1143					return (DNS_R_EMPTYLABEL);
1144				*label = count;
1145				labels++;
1146				INSIST(labels <= 127);
1147				offsets[labels] = nused;
1148				if (tlen == 0) {
1149					labels++;
1150					*ndata++ = 0;
1151					nrem--;
1152					nused++;
1153					done = ISC_TRUE;
1154				}
1155				state = ft_start;
1156			} else if (c == '\\') {
1157				state = ft_escape;
1158			} else {
1159				if (count >= 63)
1160					return (DNS_R_LABELTOOLONG);
1161				count++;
1162				CONVERTTOASCII(c);
1163				if (downcase)
1164					c = maptolower[(int)c];
1165				*ndata++ = c;
1166				nrem--;
1167				nused++;
1168			}
1169			break;
1170		case ft_initialescape:
1171			if (c == '[') {
1172				/*
1173				 * This looks like a bitstring label, which
1174				 * was deprecated.  Intentionally drop it.
1175				 */
1176				return (DNS_R_BADLABELTYPE);
1177			}
1178			state = ft_escape;
1179			POST(state);
1180			/* FALLTHROUGH */
1181		case ft_escape:
1182			if (!isdigit(c & 0xff)) {
1183				if (count >= 63)
1184					return (DNS_R_LABELTOOLONG);
1185				count++;
1186				CONVERTTOASCII(c);
1187				if (downcase)
1188					c = maptolower[(int)c];
1189				*ndata++ = c;
1190				nrem--;
1191				nused++;
1192				state = ft_ordinary;
1193				break;
1194			}
1195			digits = 0;
1196			value = 0;
1197			state = ft_escdecimal;
1198			/* FALLTHROUGH */
1199		case ft_escdecimal:
1200			if (!isdigit(c & 0xff))
1201				return (DNS_R_BADESCAPE);
1202			value *= 10;
1203			value += digitvalue[(int)c];
1204			digits++;
1205			if (digits == 3) {
1206				if (value > 255)
1207					return (DNS_R_BADESCAPE);
1208				if (count >= 63)
1209					return (DNS_R_LABELTOOLONG);
1210				count++;
1211				if (downcase)
1212					value = maptolower[value];
1213				*ndata++ = value;
1214				nrem--;
1215				nused++;
1216				state = ft_ordinary;
1217			}
1218			break;
1219		default:
1220			FATAL_ERROR(__FILE__, __LINE__,
1221				    "Unexpected state %d", state);
1222			/* Does not return. */
1223		}
1224	}
1225
1226	if (!done) {
1227		if (nrem == 0)
1228			return (ISC_R_NOSPACE);
1229		INSIST(tlen == 0);
1230		if (state != ft_ordinary && state != ft_at)
1231			return (ISC_R_UNEXPECTEDEND);
1232		if (state == ft_ordinary) {
1233			INSIST(count != 0);
1234			*label = count;
1235			labels++;
1236			INSIST(labels <= 127);
1237			offsets[labels] = nused;
1238		}
1239		if (origin != NULL) {
1240			if (nrem < origin->length)
1241				return (ISC_R_NOSPACE);
1242			label = origin->ndata;
1243			n1 = origin->length;
1244			nrem -= n1;
1245			POST(nrem);
1246			while (n1 > 0) {
1247				n2 = *label++;
1248				INSIST(n2 <= 63); /* no bitstring support */
1249				*ndata++ = n2;
1250				n1 -= n2 + 1;
1251				nused += n2 + 1;
1252				while (n2 > 0) {
1253					c = *label++;
1254					if (downcase)
1255						c = maptolower[(int)c];
1256					*ndata++ = c;
1257					n2--;
1258				}
1259				labels++;
1260				if (n1 > 0) {
1261					INSIST(labels <= 127);
1262					offsets[labels] = nused;
1263				}
1264			}
1265			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1266				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1267		}
1268	} else
1269		name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1270
1271	name->ndata = (unsigned char *)target->base + target->used;
1272	name->labels = labels;
1273	name->length = nused;
1274
1275	isc_buffer_forward(source, tused);
1276	isc_buffer_add(target, name->length);
1277
1278	return (ISC_R_SUCCESS);
1279}
1280
1281#ifdef ISC_PLATFORM_USETHREADS
1282static void
1283free_specific(void *arg) {
1284	dns_name_totextfilter_t *mem = arg;
1285	isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1286	/* Stop use being called again. */
1287	(void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1288}
1289
1290static void
1291thread_key_mutex_init(void) {
1292	RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1293}
1294
1295static isc_result_t
1296totext_filter_proc_key_init(void) {
1297	isc_result_t result;
1298
1299	/*
1300	 * We need the call to isc_once_do() to support profiled mutex
1301	 * otherwise thread_key_mutex could be initialized at compile time.
1302	 */
1303	result = isc_once_do(&once, thread_key_mutex_init);
1304	if (result != ISC_R_SUCCESS)
1305		return (result);
1306
1307	if (!thread_key_initialized) {
1308		LOCK(&thread_key_mutex);
1309		if (thread_key_mctx == NULL)
1310			result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1311		if (result != ISC_R_SUCCESS)
1312			goto unlock;
1313		isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1314		isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1315
1316		if (!thread_key_initialized &&
1317		     isc_thread_key_create(&totext_filter_proc_key,
1318					   free_specific) != 0) {
1319			result = ISC_R_FAILURE;
1320			isc_mem_detach(&thread_key_mctx);
1321		} else
1322			thread_key_initialized = 1;
1323 unlock:
1324		UNLOCK(&thread_key_mutex);
1325	}
1326	return (result);
1327}
1328#endif
1329
1330isc_result_t
1331dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1332		isc_buffer_t *target)
1333{
1334	unsigned int options = DNS_NAME_MASTERFILE;
1335
1336	if (omit_final_dot)
1337		options |= DNS_NAME_OMITFINALDOT;
1338	return (dns_name_totext2(name, options, target));
1339}
1340
1341isc_result_t
1342dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1343	return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1344}
1345
1346isc_result_t
1347dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1348{
1349	unsigned char *ndata;
1350	char *tdata;
1351	unsigned int nlen, tlen;
1352	unsigned char c;
1353	unsigned int trem, count;
1354	unsigned int labels;
1355	isc_boolean_t saw_root = ISC_FALSE;
1356	unsigned int oused = target->used;
1357#ifdef ISC_PLATFORM_USETHREADS
1358	dns_name_totextfilter_t *mem;
1359	dns_name_totextfilter_t totext_filter_proc = NULL;
1360	isc_result_t result;
1361#endif
1362	isc_boolean_t omit_final_dot =
1363		ISC_TF(options & DNS_NAME_OMITFINALDOT);
1364
1365	/*
1366	 * This function assumes the name is in proper uncompressed
1367	 * wire format.
1368	 */
1369	REQUIRE(VALID_NAME(name));
1370	REQUIRE(ISC_BUFFER_VALID(target));
1371
1372#ifdef ISC_PLATFORM_USETHREADS
1373	result = totext_filter_proc_key_init();
1374	if (result != ISC_R_SUCCESS)
1375		return (result);
1376#endif
1377	ndata = name->ndata;
1378	nlen = name->length;
1379	labels = name->labels;
1380	tdata = isc_buffer_used(target);
1381	tlen = isc_buffer_availablelength(target);
1382
1383	trem = tlen;
1384
1385	if (labels == 0 && nlen == 0) {
1386		/*
1387		 * Special handling for an empty name.
1388		 */
1389		if (trem == 0)
1390			return (ISC_R_NOSPACE);
1391
1392		/*
1393		 * The names of these booleans are misleading in this case.
1394		 * This empty name is not necessarily from the root node of
1395		 * the DNS root zone, nor is a final dot going to be included.
1396		 * They need to be set this way, though, to keep the "@"
1397		 * from being trounced.
1398		 */
1399		saw_root = ISC_TRUE;
1400		omit_final_dot = ISC_FALSE;
1401		*tdata++ = '@';
1402		trem--;
1403
1404		/*
1405		 * Skip the while() loop.
1406		 */
1407		nlen = 0;
1408	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1409		/*
1410		 * Special handling for the root label.
1411		 */
1412		if (trem == 0)
1413			return (ISC_R_NOSPACE);
1414
1415		saw_root = ISC_TRUE;
1416		omit_final_dot = ISC_FALSE;
1417		*tdata++ = '.';
1418		trem--;
1419
1420		/*
1421		 * Skip the while() loop.
1422		 */
1423		nlen = 0;
1424	}
1425
1426	while (labels > 0 && nlen > 0 && trem > 0) {
1427		labels--;
1428		count = *ndata++;
1429		nlen--;
1430		if (count == 0) {
1431			saw_root = ISC_TRUE;
1432			break;
1433		}
1434		if (count < 64) {
1435			INSIST(nlen >= count);
1436			while (count > 0) {
1437				c = *ndata;
1438				switch (c) {
1439				/* Special modifiers in zone files. */
1440				case 0x40: /* '@' */
1441				case 0x24: /* '$' */
1442					if ((options & DNS_NAME_MASTERFILE) == 0)
1443						goto no_escape;
1444					/* FALLTHROUGH */
1445				case 0x22: /* '"' */
1446				case 0x28: /* '(' */
1447				case 0x29: /* ')' */
1448				case 0x2E: /* '.' */
1449				case 0x3B: /* ';' */
1450				case 0x5C: /* '\\' */
1451					if (trem < 2)
1452						return (ISC_R_NOSPACE);
1453					*tdata++ = '\\';
1454					CONVERTFROMASCII(c);
1455					*tdata++ = c;
1456					ndata++;
1457					trem -= 2;
1458					nlen--;
1459					break;
1460				no_escape:
1461				default:
1462					if (c > 0x20 && c < 0x7f) {
1463						if (trem == 0)
1464							return (ISC_R_NOSPACE);
1465						CONVERTFROMASCII(c);
1466						*tdata++ = c;
1467						ndata++;
1468						trem--;
1469						nlen--;
1470					} else {
1471						if (trem < 4)
1472							return (ISC_R_NOSPACE);
1473						*tdata++ = 0x5c;
1474						*tdata++ = 0x30 +
1475							   ((c / 100) % 10);
1476						*tdata++ = 0x30 +
1477							   ((c / 10) % 10);
1478						*tdata++ = 0x30 + (c % 10);
1479						trem -= 4;
1480						ndata++;
1481						nlen--;
1482					}
1483				}
1484				count--;
1485			}
1486		} else {
1487			FATAL_ERROR(__FILE__, __LINE__,
1488				    "Unexpected label type %02x", count);
1489			/* NOTREACHED */
1490		}
1491
1492		/*
1493		 * The following assumes names are absolute.  If not, we
1494		 * fix things up later.  Note that this means that in some
1495		 * cases one more byte of text buffer is required than is
1496		 * needed in the final output.
1497		 */
1498		if (trem == 0)
1499			return (ISC_R_NOSPACE);
1500		*tdata++ = '.';
1501		trem--;
1502	}
1503
1504	if (nlen != 0 && trem == 0)
1505		return (ISC_R_NOSPACE);
1506
1507	if (!saw_root || omit_final_dot)
1508		trem++;
1509
1510	isc_buffer_add(target, tlen - trem);
1511
1512#ifdef ISC_PLATFORM_USETHREADS
1513	mem = isc_thread_key_getspecific(totext_filter_proc_key);
1514	if (mem != NULL)
1515		totext_filter_proc = *mem;
1516#endif
1517	if (totext_filter_proc != NULL)
1518		return ((*totext_filter_proc)(target, oused, saw_root));
1519
1520	return (ISC_R_SUCCESS);
1521}
1522
1523isc_result_t
1524dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1525			isc_buffer_t *target)
1526{
1527	unsigned char *ndata;
1528	char *tdata;
1529	unsigned int nlen, tlen;
1530	unsigned char c;
1531	unsigned int trem, count;
1532	unsigned int labels;
1533
1534	/*
1535	 * This function assumes the name is in proper uncompressed
1536	 * wire format.
1537	 */
1538	REQUIRE(VALID_NAME(name));
1539	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1540	REQUIRE(ISC_BUFFER_VALID(target));
1541
1542	ndata = name->ndata;
1543	nlen = name->length;
1544	labels = name->labels;
1545	tdata = isc_buffer_used(target);
1546	tlen = isc_buffer_availablelength(target);
1547
1548	trem = tlen;
1549
1550	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1551		/*
1552		 * Special handling for the root label.
1553		 */
1554		if (trem == 0)
1555			return (ISC_R_NOSPACE);
1556
1557		omit_final_dot = ISC_FALSE;
1558		*tdata++ = '.';
1559		trem--;
1560
1561		/*
1562		 * Skip the while() loop.
1563		 */
1564		nlen = 0;
1565	}
1566
1567	while (labels > 0 && nlen > 0 && trem > 0) {
1568		labels--;
1569		count = *ndata++;
1570		nlen--;
1571		if (count == 0)
1572			break;
1573		if (count < 64) {
1574			INSIST(nlen >= count);
1575			while (count > 0) {
1576				c = *ndata;
1577				if ((c >= 0x30 && c <= 0x39) || /* digit */
1578				    (c >= 0x41 && c <= 0x5A) ||	/* uppercase */
1579				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
1580				    c == 0x2D ||		/* hyphen */
1581				    c == 0x5F)			/* underscore */
1582				{
1583					if (trem == 0)
1584						return (ISC_R_NOSPACE);
1585					/* downcase */
1586					if (c >= 0x41 && c <= 0x5A)
1587						c += 0x20;
1588					CONVERTFROMASCII(c);
1589					*tdata++ = c;
1590					ndata++;
1591					trem--;
1592					nlen--;
1593				} else {
1594					if (trem < 3)
1595						return (ISC_R_NOSPACE);
1596					sprintf(tdata, "%%%02X", c);
1597					tdata += 3;
1598					trem -= 3;
1599					ndata++;
1600					nlen--;
1601				}
1602				count--;
1603			}
1604		} else {
1605			FATAL_ERROR(__FILE__, __LINE__,
1606				    "Unexpected label type %02x", count);
1607			/* NOTREACHED */
1608		}
1609
1610		/*
1611		 * The following assumes names are absolute.  If not, we
1612		 * fix things up later.  Note that this means that in some
1613		 * cases one more byte of text buffer is required than is
1614		 * needed in the final output.
1615		 */
1616		if (trem == 0)
1617			return (ISC_R_NOSPACE);
1618		*tdata++ = '.';
1619		trem--;
1620	}
1621
1622	if (nlen != 0 && trem == 0)
1623		return (ISC_R_NOSPACE);
1624
1625	if (omit_final_dot)
1626		trem++;
1627
1628	isc_buffer_add(target, tlen - trem);
1629
1630	return (ISC_R_SUCCESS);
1631}
1632
1633isc_result_t
1634dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1635	unsigned char *sndata, *ndata;
1636	unsigned int nlen, count, labels;
1637	isc_buffer_t buffer;
1638
1639	/*
1640	 * Downcase 'source'.
1641	 */
1642
1643	REQUIRE(VALID_NAME(source));
1644	REQUIRE(VALID_NAME(name));
1645	if (source == name) {
1646		REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1647		isc_buffer_init(&buffer, source->ndata, source->length);
1648		target = &buffer;
1649		ndata = source->ndata;
1650	} else {
1651		REQUIRE(BINDABLE(name));
1652		REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1653			(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1654		if (target == NULL) {
1655			target = name->buffer;
1656			isc_buffer_clear(name->buffer);
1657		}
1658		ndata = (unsigned char *)target->base + target->used;
1659		name->ndata = ndata;
1660	}
1661
1662	sndata = source->ndata;
1663	nlen = source->length;
1664	labels = source->labels;
1665
1666	if (nlen > (target->length - target->used)) {
1667		MAKE_EMPTY(name);
1668		return (ISC_R_NOSPACE);
1669	}
1670
1671	while (labels > 0 && nlen > 0) {
1672		labels--;
1673		count = *sndata++;
1674		*ndata++ = count;
1675		nlen--;
1676		if (count < 64) {
1677			INSIST(nlen >= count);
1678			while (count > 0) {
1679				*ndata++ = maptolower[(*sndata++)];
1680				nlen--;
1681				count--;
1682			}
1683		} else {
1684			FATAL_ERROR(__FILE__, __LINE__,
1685				    "Unexpected label type %02x", count);
1686			/* Does not return. */
1687		}
1688	}
1689
1690	if (source != name) {
1691		name->labels = source->labels;
1692		name->length = source->length;
1693		if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1694			name->attributes = DNS_NAMEATTR_ABSOLUTE;
1695		else
1696			name->attributes = 0;
1697		if (name->labels > 0 && name->offsets != NULL)
1698			set_offsets(name, name->offsets, NULL);
1699	}
1700
1701	isc_buffer_add(target, name->length);
1702
1703	return (ISC_R_SUCCESS);
1704}
1705
1706static void
1707set_offsets(const dns_name_t *name, unsigned char *offsets,
1708	    dns_name_t *set_name)
1709{
1710	unsigned int offset, count, length, nlabels;
1711	unsigned char *ndata;
1712	isc_boolean_t absolute;
1713
1714	ndata = name->ndata;
1715	length = name->length;
1716	offset = 0;
1717	nlabels = 0;
1718	absolute = ISC_FALSE;
1719	while (offset != length) {
1720		INSIST(nlabels < 128);
1721		offsets[nlabels++] = offset;
1722		count = *ndata++;
1723		offset++;
1724		INSIST(count <= 63);
1725		offset += count;
1726		ndata += count;
1727		INSIST(offset <= length);
1728		if (count == 0) {
1729			absolute = ISC_TRUE;
1730			break;
1731		}
1732	}
1733	if (set_name != NULL) {
1734		INSIST(set_name == name);
1735
1736		set_name->labels = nlabels;
1737		set_name->length = offset;
1738		if (absolute)
1739			set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1740		else
1741			set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1742	}
1743	INSIST(nlabels == name->labels);
1744	INSIST(offset == name->length);
1745}
1746
1747isc_result_t
1748dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1749		  dns_decompress_t *dctx, unsigned int options,
1750		  isc_buffer_t *target)
1751{
1752	unsigned char *cdata, *ndata;
1753	unsigned int cused; /* Bytes of compressed name data used */
1754	unsigned int nused, labels, n, nmax;
1755	unsigned int current, new_current, biggest_pointer;
1756	isc_boolean_t done;
1757	fw_state state = fw_start;
1758	unsigned int c;
1759	unsigned char *offsets;
1760	dns_offsets_t odata;
1761	isc_boolean_t downcase;
1762	isc_boolean_t seen_pointer;
1763
1764	/*
1765	 * Copy the possibly-compressed name at source into target,
1766	 * decompressing it.  Loop prevention is performed by checking
1767	 * the new pointer against biggest_pointer.
1768	 */
1769
1770	REQUIRE(VALID_NAME(name));
1771	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1772		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1773
1774	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1775
1776	if (target == NULL && name->buffer != NULL) {
1777		target = name->buffer;
1778		isc_buffer_clear(target);
1779	}
1780
1781	REQUIRE(dctx != NULL);
1782	REQUIRE(BINDABLE(name));
1783
1784	INIT_OFFSETS(name, offsets, odata);
1785
1786	/*
1787	 * Make 'name' empty in case of failure.
1788	 */
1789	MAKE_EMPTY(name);
1790
1791	/*
1792	 * Initialize things to make the compiler happy; they're not required.
1793	 */
1794	n = 0;
1795	new_current = 0;
1796
1797	/*
1798	 * Set up.
1799	 */
1800	labels = 0;
1801	done = ISC_FALSE;
1802
1803	ndata = isc_buffer_used(target);
1804	nused = 0;
1805	seen_pointer = ISC_FALSE;
1806
1807	/*
1808	 * Find the maximum number of uncompressed target name
1809	 * bytes we are willing to generate.  This is the smaller
1810	 * of the available target buffer length and the
1811	 * maximum legal domain name length (255).
1812	 */
1813	nmax = isc_buffer_availablelength(target);
1814	if (nmax > DNS_NAME_MAXWIRE)
1815		nmax = DNS_NAME_MAXWIRE;
1816
1817	cdata = isc_buffer_current(source);
1818	cused = 0;
1819
1820	current = source->current;
1821	biggest_pointer = current;
1822
1823	/*
1824	 * Note:  The following code is not optimized for speed, but
1825	 * rather for correctness.  Speed will be addressed in the future.
1826	 */
1827
1828	while (current < source->active && !done) {
1829		c = *cdata++;
1830		current++;
1831		if (!seen_pointer)
1832			cused++;
1833
1834		switch (state) {
1835		case fw_start:
1836			if (c < 64) {
1837				offsets[labels] = nused;
1838				labels++;
1839				if (nused + c + 1 > nmax)
1840					goto full;
1841				nused += c + 1;
1842				*ndata++ = c;
1843				if (c == 0)
1844					done = ISC_TRUE;
1845				n = c;
1846				state = fw_ordinary;
1847			} else if (c >= 128 && c < 192) {
1848				/*
1849				 * 14 bit local compression pointer.
1850				 * Local compression is no longer an
1851				 * IETF draft.
1852				 */
1853				return (DNS_R_BADLABELTYPE);
1854			} else if (c >= 192) {
1855				/*
1856				 * Ordinary 14-bit pointer.
1857				 */
1858				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1859				    0)
1860					return (DNS_R_DISALLOWED);
1861				new_current = c & 0x3F;
1862				n = 1;
1863				state = fw_newcurrent;
1864			} else
1865				return (DNS_R_BADLABELTYPE);
1866			break;
1867		case fw_ordinary:
1868			if (downcase)
1869				c = maptolower[c];
1870			/* FALLTHROUGH */
1871		case fw_copy:
1872			*ndata++ = c;
1873			n--;
1874			if (n == 0)
1875				state = fw_start;
1876			break;
1877		case fw_newcurrent:
1878			new_current *= 256;
1879			new_current += c;
1880			n--;
1881			if (n != 0)
1882				break;
1883			if (new_current >= biggest_pointer)
1884				return (DNS_R_BADPOINTER);
1885			biggest_pointer = new_current;
1886			current = new_current;
1887			cdata = (unsigned char *)source->base + current;
1888			seen_pointer = ISC_TRUE;
1889			state = fw_start;
1890			break;
1891		default:
1892			FATAL_ERROR(__FILE__, __LINE__,
1893				    "Unknown state %d", state);
1894			/* Does not return. */
1895		}
1896	}
1897
1898	if (!done)
1899		return (ISC_R_UNEXPECTEDEND);
1900
1901	name->ndata = (unsigned char *)target->base + target->used;
1902	name->labels = labels;
1903	name->length = nused;
1904	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1905
1906	isc_buffer_forward(source, cused);
1907	isc_buffer_add(target, name->length);
1908
1909	return (ISC_R_SUCCESS);
1910
1911 full:
1912	if (nmax == DNS_NAME_MAXWIRE)
1913		/*
1914		 * The name did not fit even though we had a buffer
1915		 * big enough to fit a maximum-length name.
1916		 */
1917		return (DNS_R_NAMETOOLONG);
1918	else
1919		/*
1920		 * The name might fit if only the caller could give us a
1921		 * big enough buffer.
1922		 */
1923		return (ISC_R_NOSPACE);
1924}
1925
1926isc_result_t
1927dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1928		isc_buffer_t *target)
1929{
1930	unsigned int methods;
1931	isc_uint16_t offset;
1932	dns_name_t gp;	/* Global compression prefix */
1933	isc_boolean_t gf;	/* Global compression target found */
1934	isc_uint16_t go;	/* Global compression offset */
1935	dns_offsets_t clo;
1936	dns_name_t clname;
1937
1938	/*
1939	 * Convert 'name' into wire format, compressing it as specified by the
1940	 * compression context 'cctx', and storing the result in 'target'.
1941	 */
1942
1943	REQUIRE(VALID_NAME(name));
1944	REQUIRE(cctx != NULL);
1945	REQUIRE(ISC_BUFFER_VALID(target));
1946
1947	/*
1948	 * If 'name' doesn't have an offsets table, make a clone which
1949	 * has one.
1950	 */
1951	if (name->offsets == NULL) {
1952#if defined(__clang__)  && \
1953       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1954		memset(&clname, 0, sizeof(clname));
1955#endif
1956		DNS_NAME_INIT(&clname, clo);
1957		dns_name_clone(name, &clname);
1958		name = &clname;
1959	}
1960	DNS_NAME_INIT(&gp, NULL);
1961
1962	offset = target->used;	/*XXX*/
1963
1964	methods = dns_compress_getmethods(cctx);
1965
1966	if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1967	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1968		gf = dns_compress_findglobal(cctx, name, &gp, &go);
1969	else
1970		gf = ISC_FALSE;
1971
1972	/*
1973	 * If the offset is too high for 14 bit global compression, we're
1974	 * out of luck.
1975	 */
1976	if (gf && go >= 0x4000)
1977		gf = ISC_FALSE;
1978
1979	/*
1980	 * Will the compression pointer reduce the message size?
1981	 */
1982	if (gf && (gp.length + 2) >= name->length)
1983		gf = ISC_FALSE;
1984
1985	if (gf) {
1986		if (target->length - target->used < gp.length)
1987			return (ISC_R_NOSPACE);
1988		(void)memmove((unsigned char *)target->base + target->used,
1989			      gp.ndata, (size_t)gp.length);
1990		isc_buffer_add(target, gp.length);
1991		go |= 0xc000;
1992		if (target->length - target->used < 2)
1993			return (ISC_R_NOSPACE);
1994		isc_buffer_putuint16(target, go);
1995		if (gp.length != 0)
1996			dns_compress_add(cctx, name, &gp, offset);
1997	} else {
1998		if (target->length - target->used < name->length)
1999			return (ISC_R_NOSPACE);
2000		(void)memmove((unsigned char *)target->base + target->used,
2001			      name->ndata, (size_t)name->length);
2002		isc_buffer_add(target, name->length);
2003		dns_compress_add(cctx, name, name, offset);
2004	}
2005	return (ISC_R_SUCCESS);
2006}
2007
2008isc_result_t
2009dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2010		     isc_buffer_t *target)
2011{
2012	unsigned char *ndata, *offsets;
2013	unsigned int nrem, labels, prefix_length, length;
2014	isc_boolean_t copy_prefix = ISC_TRUE;
2015	isc_boolean_t copy_suffix = ISC_TRUE;
2016	isc_boolean_t absolute = ISC_FALSE;
2017	dns_name_t tmp_name;
2018	dns_offsets_t odata;
2019
2020	/*
2021	 * Concatenate 'prefix' and 'suffix'.
2022	 */
2023
2024	REQUIRE(prefix == NULL || VALID_NAME(prefix));
2025	REQUIRE(suffix == NULL || VALID_NAME(suffix));
2026	REQUIRE(name == NULL || VALID_NAME(name));
2027	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2028		(target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2029	if (prefix == NULL || prefix->labels == 0)
2030		copy_prefix = ISC_FALSE;
2031	if (suffix == NULL || suffix->labels == 0)
2032		copy_suffix = ISC_FALSE;
2033	if (copy_prefix &&
2034	    (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2035		absolute = ISC_TRUE;
2036		REQUIRE(!copy_suffix);
2037	}
2038	if (name == NULL) {
2039		DNS_NAME_INIT(&tmp_name, odata);
2040		name = &tmp_name;
2041	}
2042	if (target == NULL) {
2043		INSIST(name->buffer != NULL);
2044		target = name->buffer;
2045		isc_buffer_clear(name->buffer);
2046	}
2047
2048	REQUIRE(BINDABLE(name));
2049
2050	/*
2051	 * Set up.
2052	 */
2053	nrem = target->length - target->used;
2054	ndata = (unsigned char *)target->base + target->used;
2055	if (nrem > DNS_NAME_MAXWIRE)
2056		nrem = DNS_NAME_MAXWIRE;
2057	length = 0;
2058	prefix_length = 0;
2059	labels = 0;
2060	if (copy_prefix) {
2061		prefix_length = prefix->length;
2062		length += prefix_length;
2063		labels += prefix->labels;
2064	}
2065	if (copy_suffix) {
2066		length += suffix->length;
2067		labels += suffix->labels;
2068	}
2069	if (length > DNS_NAME_MAXWIRE) {
2070		MAKE_EMPTY(name);
2071		return (DNS_R_NAMETOOLONG);
2072	}
2073	if (length > nrem) {
2074		MAKE_EMPTY(name);
2075		return (ISC_R_NOSPACE);
2076	}
2077
2078	if (copy_suffix) {
2079		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2080			absolute = ISC_TRUE;
2081		memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2082	}
2083
2084	/*
2085	 * If 'prefix' and 'name' are the same object, and the object has
2086	 * a dedicated buffer, and we're using it, then we don't have to
2087	 * copy anything.
2088	 */
2089	if (copy_prefix && (prefix != name || prefix->buffer != target))
2090		memmove(ndata, prefix->ndata, prefix_length);
2091
2092	name->ndata = ndata;
2093	name->labels = labels;
2094	name->length = length;
2095	if (absolute)
2096		name->attributes = DNS_NAMEATTR_ABSOLUTE;
2097	else
2098		name->attributes = 0;
2099
2100	if (name->labels > 0 && name->offsets != NULL) {
2101		INIT_OFFSETS(name, offsets, odata);
2102		set_offsets(name, offsets, NULL);
2103	}
2104
2105	isc_buffer_add(target, name->length);
2106
2107	return (ISC_R_SUCCESS);
2108}
2109
2110void
2111dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2112	       dns_name_t *prefix, dns_name_t *suffix)
2113
2114{
2115	unsigned int splitlabel;
2116
2117	REQUIRE(VALID_NAME(name));
2118	REQUIRE(suffixlabels > 0);
2119	REQUIRE(suffixlabels < name->labels);
2120	REQUIRE(prefix != NULL || suffix != NULL);
2121	REQUIRE(prefix == NULL ||
2122		(VALID_NAME(prefix) &&
2123		 prefix->buffer != NULL &&
2124		 BINDABLE(prefix)));
2125	REQUIRE(suffix == NULL ||
2126		(VALID_NAME(suffix) &&
2127		 suffix->buffer != NULL &&
2128		 BINDABLE(suffix)));
2129
2130	splitlabel = name->labels - suffixlabels;
2131
2132	if (prefix != NULL)
2133		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2134
2135	if (suffix != NULL)
2136		dns_name_getlabelsequence(name, splitlabel,
2137					  suffixlabels, suffix);
2138
2139	return;
2140}
2141
2142isc_result_t
2143dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2144	     dns_name_t *target)
2145{
2146	/*
2147	 * Make 'target' a dynamically allocated copy of 'source'.
2148	 */
2149
2150	REQUIRE(VALID_NAME(source));
2151	REQUIRE(source->length > 0);
2152	REQUIRE(VALID_NAME(target));
2153	REQUIRE(BINDABLE(target));
2154
2155	/*
2156	 * Make 'target' empty in case of failure.
2157	 */
2158	MAKE_EMPTY(target);
2159
2160	target->ndata = isc_mem_get(mctx, source->length);
2161	if (target->ndata == NULL)
2162		return (ISC_R_NOMEMORY);
2163
2164	memmove(target->ndata, source->ndata, source->length);
2165
2166	target->length = source->length;
2167	target->labels = source->labels;
2168	target->attributes = DNS_NAMEATTR_DYNAMIC;
2169	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2170		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2171	if (target->offsets != NULL) {
2172		if (source->offsets != NULL)
2173			memmove(target->offsets, source->offsets,
2174				source->labels);
2175		else
2176			set_offsets(target, target->offsets, NULL);
2177	}
2178
2179	return (ISC_R_SUCCESS);
2180}
2181
2182isc_result_t
2183dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2184			dns_name_t *target)
2185{
2186	/*
2187	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2188	 * 'target' will also have a dynamically allocated offsets table.
2189	 */
2190
2191	REQUIRE(VALID_NAME(source));
2192	REQUIRE(source->length > 0);
2193	REQUIRE(VALID_NAME(target));
2194	REQUIRE(BINDABLE(target));
2195	REQUIRE(target->offsets == NULL);
2196
2197	/*
2198	 * Make 'target' empty in case of failure.
2199	 */
2200	MAKE_EMPTY(target);
2201
2202	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2203	if (target->ndata == NULL)
2204		return (ISC_R_NOMEMORY);
2205
2206	memmove(target->ndata, source->ndata, source->length);
2207
2208	target->length = source->length;
2209	target->labels = source->labels;
2210	target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2211		DNS_NAMEATTR_READONLY;
2212	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2213		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2214	target->offsets = target->ndata + source->length;
2215	if (source->offsets != NULL)
2216		memmove(target->offsets, source->offsets, source->labels);
2217	else
2218		set_offsets(target, target->offsets, NULL);
2219
2220	return (ISC_R_SUCCESS);
2221}
2222
2223void
2224dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2225	size_t size;
2226
2227	/*
2228	 * Free 'name'.
2229	 */
2230
2231	REQUIRE(VALID_NAME(name));
2232	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2233
2234	size = name->length;
2235	if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2236		size += name->labels;
2237	isc_mem_put(mctx, name->ndata, size);
2238	dns_name_invalidate(name);
2239}
2240
2241isc_result_t
2242dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2243	dns_name_t downname;
2244	unsigned char data[256];
2245	isc_buffer_t buffer;
2246	isc_result_t result;
2247	isc_region_t r;
2248
2249	/*
2250	 * Send 'name' in DNSSEC canonical form to 'digest'.
2251	 */
2252
2253	REQUIRE(VALID_NAME(name));
2254	REQUIRE(digest != NULL);
2255
2256#if defined(__clang__)  && \
2257       ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2258	memset(&downname, 0, sizeof(downname));
2259#endif
2260	DNS_NAME_INIT(&downname, NULL);
2261
2262	isc_buffer_init(&buffer, data, sizeof(data));
2263
2264	result = dns_name_downcase(name, &downname, &buffer);
2265	if (result != ISC_R_SUCCESS)
2266		return (result);
2267
2268	isc_buffer_usedregion(&buffer, &r);
2269
2270	return ((digest)(arg, &r));
2271}
2272
2273isc_boolean_t
2274dns_name_dynamic(dns_name_t *name) {
2275	REQUIRE(VALID_NAME(name));
2276
2277	/*
2278	 * Returns whether there is dynamic memory associated with this name.
2279	 */
2280
2281	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2282		ISC_TRUE : ISC_FALSE);
2283}
2284
2285isc_result_t
2286dns_name_print(dns_name_t *name, FILE *stream) {
2287	isc_result_t result;
2288	isc_buffer_t b;
2289	isc_region_t r;
2290	char t[1024];
2291
2292	/*
2293	 * Print 'name' on 'stream'.
2294	 */
2295
2296	REQUIRE(VALID_NAME(name));
2297
2298	isc_buffer_init(&b, t, sizeof(t));
2299	result = dns_name_totext(name, ISC_FALSE, &b);
2300	if (result != ISC_R_SUCCESS)
2301		return (result);
2302	isc_buffer_usedregion(&b, &r);
2303	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2304
2305	return (ISC_R_SUCCESS);
2306}
2307
2308isc_result_t
2309dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2310#ifdef ISC_PLATFORM_USETHREADS
2311	isc_result_t result;
2312	dns_name_totextfilter_t *mem;
2313	int res;
2314
2315	result = totext_filter_proc_key_init();
2316	if (result != ISC_R_SUCCESS)
2317		return (result);
2318
2319	/*
2320	 * If we already have been here set / clear as appropriate.
2321	 * Otherwise allocate memory.
2322	 */
2323	mem = isc_thread_key_getspecific(totext_filter_proc_key);
2324	if (mem != NULL && proc != NULL) {
2325		*mem = proc;
2326		return (ISC_R_SUCCESS);
2327	}
2328	if (proc == NULL) {
2329		isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2330		res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2331		if (res != 0)
2332			result = ISC_R_UNEXPECTED;
2333		return (result);
2334	}
2335
2336	mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2337	if (mem == NULL)
2338		return (ISC_R_NOMEMORY);
2339	*mem = proc;
2340	if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2341		isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2342		result = ISC_R_UNEXPECTED;
2343	}
2344	return (result);
2345#else
2346	totext_filter_proc = proc;
2347	return (ISC_R_SUCCESS);
2348#endif
2349}
2350
2351void
2352dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2353	isc_result_t result;
2354	isc_buffer_t buf;
2355
2356	REQUIRE(size > 0);
2357
2358	/*
2359	 * Leave room for null termination after buffer.
2360	 */
2361	isc_buffer_init(&buf, cp, size - 1);
2362	result = dns_name_totext(name, ISC_TRUE, &buf);
2363	if (result == ISC_R_SUCCESS) {
2364		/*
2365		 * Null terminate.
2366		 */
2367		isc_region_t r;
2368		isc_buffer_usedregion(&buf, &r);
2369		((char *) r.base)[r.length] = '\0';
2370
2371	} else
2372		snprintf(cp, size, "<unknown>");
2373}
2374
2375/*
2376 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2377 * memory.
2378 */
2379isc_result_t
2380dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2381	isc_result_t result;
2382	isc_buffer_t buf;
2383	isc_region_t reg;
2384	char *p, txt[DNS_NAME_FORMATSIZE];
2385
2386	REQUIRE(VALID_NAME(name));
2387	REQUIRE(target != NULL && *target == NULL);
2388
2389	isc_buffer_init(&buf, txt, sizeof(txt));
2390	result = dns_name_totext(name, ISC_FALSE, &buf);
2391	if (result != ISC_R_SUCCESS)
2392		return (result);
2393
2394	isc_buffer_usedregion(&buf, &reg);
2395	p = isc_mem_allocate(mctx, reg.length + 1);
2396	memmove(p, (char *) reg.base, (int) reg.length);
2397	p[reg.length] = '\0';
2398
2399	*target = p;
2400	return (ISC_R_SUCCESS);
2401}
2402
2403/*
2404 * dns_name_fromstring() -- convert directly from a string to a name,
2405 * allocating memory as needed
2406 */
2407isc_result_t
2408dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2409		    isc_mem_t *mctx)
2410{
2411	return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2412}
2413
2414isc_result_t
2415dns_name_fromstring2(dns_name_t *target, const char *src,
2416		     const dns_name_t *origin, unsigned int options,
2417		     isc_mem_t *mctx)
2418{
2419	isc_result_t result;
2420	isc_buffer_t buf;
2421	dns_fixedname_t fn;
2422	dns_name_t *name;
2423
2424	REQUIRE(src != NULL);
2425
2426	isc_buffer_constinit(&buf, src, strlen(src));
2427	isc_buffer_add(&buf, strlen(src));
2428	if (BINDABLE(target) && target->buffer != NULL)
2429		name = target;
2430	else {
2431		dns_fixedname_init(&fn);
2432		name = dns_fixedname_name(&fn);
2433	}
2434
2435	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2436	if (result != ISC_R_SUCCESS)
2437		return (result);
2438
2439	if (name != target)
2440		result = dns_name_dupwithoffsets(name, mctx, target);
2441	return (result);
2442}
2443
2444isc_result_t
2445dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2446	unsigned char *ndata;
2447
2448	/*
2449	 * Make dest a copy of source.
2450	 */
2451
2452	REQUIRE(VALID_NAME(source));
2453	REQUIRE(VALID_NAME(dest));
2454	REQUIRE(target != NULL || dest->buffer != NULL);
2455
2456	if (target == NULL) {
2457		target = dest->buffer;
2458		isc_buffer_clear(dest->buffer);
2459	}
2460
2461	REQUIRE(BINDABLE(dest));
2462
2463	/*
2464	 * Set up.
2465	 */
2466	if (target->length - target->used < source->length)
2467		return (ISC_R_NOSPACE);
2468
2469	ndata = (unsigned char *)target->base + target->used;
2470	dest->ndata = target->base;
2471
2472	memmove(ndata, source->ndata, source->length);
2473
2474	dest->ndata = ndata;
2475	dest->labels = source->labels;
2476	dest->length = source->length;
2477	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2478		dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2479	else
2480		dest->attributes = 0;
2481
2482	if (dest->labels > 0 && dest->offsets != NULL) {
2483		if (source->offsets != NULL)
2484			memmove(dest->offsets, source->offsets, source->labels);
2485		else
2486			set_offsets(dest, dest->offsets, NULL);
2487	}
2488
2489	isc_buffer_add(target, dest->length);
2490
2491	return (ISC_R_SUCCESS);
2492}
2493
2494void
2495dns_name_destroy(void) {
2496#ifdef ISC_PLATFORM_USETHREADS
2497	RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2498				  == ISC_R_SUCCESS);
2499
2500	LOCK(&thread_key_mutex);
2501	if (thread_key_initialized) {
2502		isc_mem_detach(&thread_key_mctx);
2503		isc_thread_key_delete(totext_filter_proc_key);
2504		thread_key_initialized = 0;
2505	}
2506	UNLOCK(&thread_key_mutex);
2507
2508#endif
2509}
2510