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