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