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