name.c revision 135446
140875Smsmith/*
240875Smsmith * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
340875Smsmith * Copyright (C) 1998-2003  Internet Software Consortium.
440875Smsmith *
540875Smsmith * Permission to use, copy, modify, and distribute this software for any
640875Smsmith * purpose with or without fee is hereby granted, provided that the above
740875Smsmith * copyright notice and this permission notice appear in all copies.
840875Smsmith *
940875Smsmith * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
1040875Smsmith * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1140875Smsmith * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
1240875Smsmith * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1340875Smsmith * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
1440875Smsmith * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1540875Smsmith * PERFORMANCE OF THIS SOFTWARE.
1640875Smsmith */
1740875Smsmith
1840875Smsmith/* $Id: name.c,v 1.127.2.7.2.11 2004/09/01 05:19:59 marka Exp $ */
1940875Smsmith
2040875Smsmith#include <config.h>
2140875Smsmith
2240875Smsmith#include <ctype.h>
2340875Smsmith
2440875Smsmith#include <isc/buffer.h>
2540875Smsmith#include <isc/hash.h>
2641254Spaul#include <isc/mem.h>
2740834Smsmith#include <isc/print.h>
2840834Smsmith#include <isc/string.h>
2940834Smsmith#include <isc/util.h>
3040834Smsmith
3140834Smsmith#include <dns/compress.h>
3240834Smsmith#include <dns/name.h>
3340834Smsmith#include <dns/result.h>
3440834Smsmith
3540834Smsmith#define VALID_NAME(n)	ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
3640834Smsmith
3740834Smsmithtypedef enum {
3840834Smsmith	ft_init = 0,
3940834Smsmith	ft_start,
4040834Smsmith	ft_ordinary,
4140834Smsmith	ft_initialescape,
4240834Smsmith	ft_escape,
4340834Smsmith	ft_escdecimal,
4440834Smsmith	ft_at
4540834Smsmith} ft_state;
4640834Smsmith
4740834Smsmithtypedef enum {
4840834Smsmith	fw_start = 0,
4940834Smsmith	fw_ordinary,
5040834Smsmith	fw_copy,
5140834Smsmith	fw_newcurrent
5240834Smsmith} fw_state;
5340834Smsmith
5440835Smsmithstatic char digitvalue[256] = {
5540834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
5640834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
5740834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
5840834Smsmith	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
5940834Smsmith	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
6040834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
6140834Smsmith	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
6240834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
6340835Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6440834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6540834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6640834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6740834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6840834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
6940834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
7040834Smsmith	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
7140834Smsmith};
7240834Smsmith
7340834Smsmithstatic unsigned char maptolower[] = {
7440834Smsmith	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
7540834Smsmith	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
7640834Smsmith	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
7740834Smsmith	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
7840834Smsmith	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
7940834Smsmith	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
8040834Smsmith	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
8140834Smsmith	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
8240834Smsmith	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
8340834Smsmith	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
8440834Smsmith	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
8540834Smsmith	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
8640834Smsmith	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
8740834Smsmith	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
8840834Smsmith	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
8940834Smsmith	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
9040834Smsmith	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
9140834Smsmith	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
9240834Smsmith	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
9340834Smsmith	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
9440834Smsmith	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
9540834Smsmith	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
9640834Smsmith	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
9740834Smsmith	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
9840834Smsmith	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
9940834Smsmith	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
10040834Smsmith	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
10141254Spaul	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
10240835Smsmith	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
10341254Spaul	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
10441254Spaul	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
10540834Smsmith	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
10640834Smsmith};
10740834Smsmith
10840834Smsmith#define CONVERTTOASCII(c)
10940834Smsmith#define CONVERTFROMASCII(c)
11040834Smsmith
11140834Smsmith#define INIT_OFFSETS(name, var, default) \
11240834Smsmith	if (name->offsets != NULL) \
11340834Smsmith		var = name->offsets; \
11440834Smsmith	else \
11540834Smsmith		var = default;
11640834Smsmith
11740834Smsmith#define SETUP_OFFSETS(name, var, default) \
11840834Smsmith	if (name->offsets != NULL) \
11940834Smsmith		var = name->offsets; \
12040834Smsmith	else { \
12140834Smsmith		var = default; \
12240834Smsmith		set_offsets(name, var, NULL); \
12340834Smsmith	}
12440834Smsmith
12540834Smsmith/*
12640834Smsmith * Note:  If additional attributes are added that should not be set for
12740834Smsmith *	  empty names, MAKE_EMPTY() must be changed so it clears them.
12840834Smsmith */
12940834Smsmith#define MAKE_EMPTY(name) \
13040834Smsmithdo { \
13140834Smsmith	name->ndata = NULL; \
13240834Smsmith	name->length = 0; \
13340834Smsmith	name->labels = 0; \
13440834Smsmith	name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
13540834Smsmith} while (0);
13640834Smsmith
13740834Smsmith/*
13840834Smsmith * A name is "bindable" if it can be set to point to a new value, i.e.
13940834Smsmith * name->ndata and name->length may be changed.
14040834Smsmith */
14140834Smsmith#define BINDABLE(name) \
14240834Smsmith	((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
14340834Smsmith	 == 0)
14440834Smsmith
14540834Smsmith/*
14640834Smsmith * Note that the name data must be a char array, not a string
14740834Smsmith * literal, to avoid compiler warnings about discarding
14840834Smsmith * the const attribute of a string.
14940834Smsmith */
15040834Smsmithstatic unsigned char root_ndata[] = { '\0' };
15140834Smsmithstatic unsigned char root_offsets[] = { 0 };
15240834Smsmith
15340834Smsmithstatic dns_name_t root =
15440834Smsmith{
15540834Smsmith	DNS_NAME_MAGIC,
15640834Smsmith	root_ndata, 1, 1,
15740834Smsmith	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
15840834Smsmith	root_offsets, NULL,
15940834Smsmith	{(void *)-1, (void *)-1},
16040834Smsmith	{NULL, NULL}
16140834Smsmith};
16240834Smsmith
16340834Smsmith/* XXXDCL make const? */
16440834SmsmithLIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
16540834Smsmith
16640834Smsmithstatic unsigned char wild_ndata[] = { '\001', '*' };
16740834Smsmithstatic unsigned char wild_offsets[] = { 0 };
16840834Smsmith
16940834Smsmithstatic dns_name_t wild =
17040834Smsmith{
17140834Smsmith	DNS_NAME_MAGIC,
17240834Smsmith	wild_ndata, 2, 1,
17340834Smsmith	DNS_NAMEATTR_READONLY,
17440834Smsmith	wild_offsets, NULL,
17540834Smsmith	{(void *)-1, (void *)-1},
17640834Smsmith	{NULL, NULL}
17740834Smsmith};
17840834Smsmith
17940834Smsmith/* XXXDCL make const? */
18040834SmsmithLIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
18140834Smsmith
18240834Smsmithunsigned int
18340834Smsmithdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
18440834Smsmith
18540834Smsmithstatic void
18640834Smsmithset_offsets(const dns_name_t *name, unsigned char *offsets,
18740834Smsmith	    dns_name_t *set_name);
18840834Smsmith
18940834Smsmithvoid
19040834Smsmithdns_name_init(dns_name_t *name, unsigned char *offsets) {
19140835Smsmith	/*
19240835Smsmith	 * Initialize 'name'.
19340834Smsmith	 */
19440834Smsmith	DNS_NAME_INIT(name, offsets);
19540834Smsmith}
19640834Smsmith
19740834Smsmithvoid
19840835Smsmithdns_name_reset(dns_name_t *name) {
19940834Smsmith	REQUIRE(VALID_NAME(name));
20040834Smsmith	REQUIRE(BINDABLE(name));
20140835Smsmith
20240835Smsmith	DNS_NAME_RESET(name);
20340834Smsmith}
20440834Smsmith
20540835Smsmithvoid
20640834Smsmithdns_name_invalidate(dns_name_t *name) {
20740834Smsmith	/*
20840834Smsmith	 * Make 'name' invalid.
20940834Smsmith	 */
21040834Smsmith
21140835Smsmith	REQUIRE(VALID_NAME(name));
21240835Smsmith
21340834Smsmith	name->magic = 0;
21440835Smsmith	name->ndata = NULL;
21540834Smsmith	name->length = 0;
21640834Smsmith	name->labels = 0;
21740835Smsmith	name->attributes = 0;
21840834Smsmith	name->offsets = NULL;
21940834Smsmith	name->buffer = NULL;
22040834Smsmith	ISC_LINK_INIT(name, link);
22140835Smsmith}
22240834Smsmith
22340834Smsmithvoid
22440834Smsmithdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
22540834Smsmith	/*
22640835Smsmith	 * Dedicate a buffer for use with 'name'.
22740834Smsmith	 */
22840834Smsmith
22940834Smsmith	REQUIRE(VALID_NAME(name));
23040834Smsmith	REQUIRE((buffer != NULL && name->buffer == NULL) ||
23140834Smsmith		(buffer == NULL));
23240834Smsmith
23340834Smsmith	name->buffer = buffer;
23440834Smsmith}
23540834Smsmith
23640834Smsmithisc_boolean_t
23740834Smsmithdns_name_hasbuffer(const dns_name_t *name) {
23840834Smsmith	/*
23940834Smsmith	 * Does 'name' have a dedicated buffer?
24040834Smsmith	 */
24140834Smsmith
24240834Smsmith	REQUIRE(VALID_NAME(name));
24340834Smsmith
24440834Smsmith	if (name->buffer != NULL)
24540834Smsmith		return (ISC_TRUE);
24640834Smsmith
24740834Smsmith	return (ISC_FALSE);
24840834Smsmith}
24940834Smsmith
25040834Smsmithisc_boolean_t
25140834Smsmithdns_name_isabsolute(const dns_name_t *name) {
25240834Smsmith
25340834Smsmith	/*
25440834Smsmith	 * Does 'name' end in the root label?
25540835Smsmith	 */
25640834Smsmith
25740834Smsmith	REQUIRE(VALID_NAME(name));
25840834Smsmith
25940834Smsmith	if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
26040834Smsmith		return (ISC_TRUE);
26140834Smsmith	return (ISC_FALSE);
26240834Smsmith}
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, kind;
949	unsigned int value, count, tbcount, bitlength, maxlength;
950	unsigned int n1, n2, vlen, 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	vlen = 0;
989	label = NULL;
990	digits = 0;
991	value = 0;
992	count = 0;
993	tbcount = 0;
994	bitlength = 0;
995	maxlength = 0;
996	kind = ft_init;
997
998	/*
999	 * Make 'name' empty in case of failure.
1000	 */
1001	MAKE_EMPTY(name);
1002
1003	/*
1004	 * Set up the state machine.
1005	 */
1006	tdata = (char *)source->base + source->current;
1007	tlen = isc_buffer_remaininglength(source);
1008	tused = 0;
1009	ndata = isc_buffer_used(target);
1010	nrem = isc_buffer_availablelength(target);
1011	if (nrem > 255)
1012		nrem = 255;
1013	nused = 0;
1014	labels = 0;
1015	done = ISC_FALSE;
1016	state = ft_init;
1017
1018	while (nrem > 0 && tlen > 0 && !done) {
1019		c = *tdata++;
1020		tlen--;
1021		tused++;
1022
1023		switch (state) {
1024		case ft_init:
1025			/*
1026			 * Is this the root name?
1027			 */
1028			if (c == '.') {
1029				if (tlen != 0)
1030					return (DNS_R_EMPTYLABEL);
1031				labels++;
1032				*ndata++ = 0;
1033				nrem--;
1034				nused++;
1035				done = ISC_TRUE;
1036				break;
1037			}
1038			if (c == '@' && tlen == 0) {
1039				state = ft_at;
1040				break;
1041			}
1042
1043			/* FALLTHROUGH */
1044		case ft_start:
1045			label = ndata;
1046			ndata++;
1047			nrem--;
1048			nused++;
1049			count = 0;
1050			if (c == '\\') {
1051				state = ft_initialescape;
1052				break;
1053			}
1054			kind = ft_ordinary;
1055			state = ft_ordinary;
1056			if (nrem == 0)
1057				return (ISC_R_NOSPACE);
1058			/* FALLTHROUGH */
1059		case ft_ordinary:
1060			if (c == '.') {
1061				if (count == 0)
1062					return (DNS_R_EMPTYLABEL);
1063				*label = count;
1064				labels++;
1065				INSIST(labels <= 127);
1066				offsets[labels] = nused;
1067				if (tlen == 0) {
1068					labels++;
1069					*ndata++ = 0;
1070					nrem--;
1071					nused++;
1072					done = ISC_TRUE;
1073				}
1074				state = ft_start;
1075			} else if (c == '\\') {
1076				state = ft_escape;
1077			} else {
1078				if (count >= 63)
1079					return (DNS_R_LABELTOOLONG);
1080				count++;
1081				CONVERTTOASCII(c);
1082				if (downcase)
1083					c = maptolower[(int)c];
1084				*ndata++ = c;
1085				nrem--;
1086				nused++;
1087			}
1088			break;
1089		case ft_initialescape:
1090			if (c == '[') {
1091				/*
1092				 * This looks like a bitstring label, which
1093				 * was deprecated.  Intentionally drop it.
1094				 */
1095				return (DNS_R_BADLABELTYPE);
1096			}
1097			kind = ft_ordinary;
1098			state = ft_escape;
1099			/* FALLTHROUGH */
1100		case ft_escape:
1101			if (!isdigit(c & 0xff)) {
1102				if (count >= 63)
1103					return (DNS_R_LABELTOOLONG);
1104				count++;
1105				CONVERTTOASCII(c);
1106				if (downcase)
1107					c = maptolower[(int)c];
1108				*ndata++ = c;
1109				nrem--;
1110				nused++;
1111				state = ft_ordinary;
1112				break;
1113			}
1114			digits = 0;
1115			value = 0;
1116			state = ft_escdecimal;
1117			/* FALLTHROUGH */
1118		case ft_escdecimal:
1119			if (!isdigit(c & 0xff))
1120				return (DNS_R_BADESCAPE);
1121			value *= 10;
1122			value += digitvalue[(int)c];
1123			digits++;
1124			if (digits == 3) {
1125				if (value > 255)
1126					return (DNS_R_BADESCAPE);
1127				if (count >= 63)
1128					return (DNS_R_LABELTOOLONG);
1129				count++;
1130				if (downcase)
1131					value = maptolower[value];
1132				*ndata++ = value;
1133				nrem--;
1134				nused++;
1135				state = ft_ordinary;
1136			}
1137			break;
1138		default:
1139			FATAL_ERROR(__FILE__, __LINE__,
1140				    "Unexpected state %d", state);
1141			/* Does not return. */
1142		}
1143	}
1144
1145	if (!done) {
1146		if (nrem == 0)
1147			return (ISC_R_NOSPACE);
1148		INSIST(tlen == 0);
1149		if (state != ft_ordinary && state != ft_at)
1150			return (ISC_R_UNEXPECTEDEND);
1151		if (state == ft_ordinary) {
1152			INSIST(count != 0);
1153			*label = count;
1154			labels++;
1155			INSIST(labels <= 127);
1156			offsets[labels] = nused;
1157		}
1158		if (origin != NULL) {
1159			if (nrem < origin->length)
1160				return (ISC_R_NOSPACE);
1161			label = origin->ndata;
1162			n1 = origin->length;
1163			nrem -= n1;
1164			while (n1 > 0) {
1165				n2 = *label++;
1166				INSIST(n2 <= 63); /* no bitstring support */
1167				*ndata++ = n2;
1168				n1 -= n2 + 1;
1169				nused += n2 + 1;
1170				while (n2 > 0) {
1171					c = *label++;
1172					if (downcase)
1173						c = maptolower[(int)c];
1174					*ndata++ = c;
1175					n2--;
1176				}
1177				labels++;
1178				if (n1 > 0) {
1179					INSIST(labels <= 127);
1180					offsets[labels] = nused;
1181				}
1182			}
1183			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1184				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1185		}
1186	} else
1187		name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1188
1189	name->ndata = (unsigned char *)target->base + target->used;
1190	name->labels = labels;
1191	name->length = nused;
1192
1193	isc_buffer_forward(source, tused);
1194	isc_buffer_add(target, name->length);
1195
1196	return (ISC_R_SUCCESS);
1197}
1198
1199isc_result_t
1200dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1201		isc_buffer_t *target)
1202{
1203	unsigned char *ndata;
1204	char *tdata;
1205	unsigned int nlen, tlen;
1206	unsigned char c;
1207	unsigned int trem, count;
1208	unsigned int labels;
1209	isc_boolean_t saw_root = ISC_FALSE;
1210
1211	/*
1212	 * This function assumes the name is in proper uncompressed
1213	 * wire format.
1214	 */
1215	REQUIRE(VALID_NAME(name));
1216	REQUIRE(ISC_BUFFER_VALID(target));
1217
1218	ndata = name->ndata;
1219	nlen = name->length;
1220	labels = name->labels;
1221	tdata = isc_buffer_used(target);
1222	tlen = isc_buffer_availablelength(target);
1223
1224	trem = tlen;
1225
1226	if (labels == 0 && nlen == 0) {
1227		/*
1228		 * Special handling for an empty name.
1229		 */
1230		if (trem == 0)
1231			return (ISC_R_NOSPACE);
1232
1233		/*
1234		 * The names of these booleans are misleading in this case.
1235		 * This empty name is not necessarily from the root node of
1236		 * the DNS root zone, nor is a final dot going to be included.
1237		 * They need to be set this way, though, to keep the "@"
1238		 * from being trounced.
1239		 */
1240		saw_root = ISC_TRUE;
1241		omit_final_dot = ISC_FALSE;
1242		*tdata++ = '@';
1243		trem--;
1244
1245		/*
1246		 * Skip the while() loop.
1247		 */
1248		nlen = 0;
1249	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1250		/*
1251		 * Special handling for the root label.
1252		 */
1253		if (trem == 0)
1254			return (ISC_R_NOSPACE);
1255
1256		saw_root = ISC_TRUE;
1257		omit_final_dot = ISC_FALSE;
1258		*tdata++ = '.';
1259		trem--;
1260
1261		/*
1262		 * Skip the while() loop.
1263		 */
1264		nlen = 0;
1265	}
1266
1267	while (labels > 0 && nlen > 0 && trem > 0) {
1268		labels--;
1269		count = *ndata++;
1270		nlen--;
1271		if (count == 0) {
1272			saw_root = ISC_TRUE;
1273			break;
1274		}
1275		if (count < 64) {
1276			INSIST(nlen >= count);
1277			while (count > 0) {
1278				c = *ndata;
1279				switch (c) {
1280				case 0x22: /* '"' */
1281				case 0x28: /* '(' */
1282				case 0x29: /* ')' */
1283				case 0x2E: /* '.' */
1284				case 0x3B: /* ';' */
1285				case 0x5C: /* '\\' */
1286				/* Special modifiers in zone files. */
1287				case 0x40: /* '@' */
1288				case 0x24: /* '$' */
1289					if (trem < 2)
1290						return (ISC_R_NOSPACE);
1291					*tdata++ = '\\';
1292					CONVERTFROMASCII(c);
1293					*tdata++ = c;
1294					ndata++;
1295					trem -= 2;
1296					nlen--;
1297					break;
1298				default:
1299					if (c > 0x20 && c < 0x7f) {
1300						if (trem == 0)
1301							return (ISC_R_NOSPACE);
1302						CONVERTFROMASCII(c);
1303						*tdata++ = c;
1304						ndata++;
1305						trem--;
1306						nlen--;
1307					} else {
1308						char buf[5];
1309						if (trem < 4)
1310							return (ISC_R_NOSPACE);
1311						snprintf(buf, sizeof(buf),
1312							 "\\%03u", c);
1313						memcpy(tdata, buf, 4);
1314						tdata += 4;
1315						trem -= 4;
1316						ndata++;
1317						nlen--;
1318					}
1319				}
1320				count--;
1321			}
1322		} else {
1323			FATAL_ERROR(__FILE__, __LINE__,
1324				    "Unexpected label type %02x", count);
1325			/* NOTREACHED */
1326		}
1327
1328		/*
1329		 * The following assumes names are absolute.  If not, we
1330		 * fix things up later.  Note that this means that in some
1331		 * cases one more byte of text buffer is required than is
1332		 * needed in the final output.
1333		 */
1334		if (trem == 0)
1335			return (ISC_R_NOSPACE);
1336		*tdata++ = '.';
1337		trem--;
1338	}
1339
1340	if (nlen != 0 && trem == 0)
1341		return (ISC_R_NOSPACE);
1342
1343	if (!saw_root || omit_final_dot)
1344		trem++;
1345
1346	isc_buffer_add(target, tlen - trem);
1347
1348	return (ISC_R_SUCCESS);
1349}
1350
1351isc_result_t
1352dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1353			isc_buffer_t *target)
1354{
1355	unsigned char *ndata;
1356	char *tdata;
1357	unsigned int nlen, tlen;
1358	unsigned char c;
1359	unsigned int trem, count;
1360	unsigned int labels;
1361
1362	/*
1363	 * This function assumes the name is in proper uncompressed
1364	 * wire format.
1365	 */
1366	REQUIRE(VALID_NAME(name));
1367	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1368	REQUIRE(ISC_BUFFER_VALID(target));
1369
1370	ndata = name->ndata;
1371	nlen = name->length;
1372	labels = name->labels;
1373	tdata = isc_buffer_used(target);
1374	tlen = isc_buffer_availablelength(target);
1375
1376	trem = tlen;
1377
1378	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1379		/*
1380		 * Special handling for the root label.
1381		 */
1382		if (trem == 0)
1383			return (ISC_R_NOSPACE);
1384
1385		omit_final_dot = ISC_FALSE;
1386		*tdata++ = '.';
1387		trem--;
1388
1389		/*
1390		 * Skip the while() loop.
1391		 */
1392		nlen = 0;
1393	}
1394
1395	while (labels > 0 && nlen > 0 && trem > 0) {
1396		labels--;
1397		count = *ndata++;
1398		nlen--;
1399		if (count == 0)
1400			break;
1401		if (count < 64) {
1402			INSIST(nlen >= count);
1403			while (count > 0) {
1404				c = *ndata;
1405				if ((c >= 0x30 && c <= 0x39) || /* digit */
1406				    (c >= 0x41 && c <= 0x5A) ||	/* uppercase */
1407				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
1408				    c == 0x2D ||		/* hyphen */
1409				    c == 0x5F)			/* underscore */
1410				{
1411					if (trem == 0)
1412						return (ISC_R_NOSPACE);
1413					/* downcase */
1414					if (c >= 0x41 && c <= 0x5A)
1415						c += 0x20;
1416					CONVERTFROMASCII(c);
1417					*tdata++ = c;
1418					ndata++;
1419					trem--;
1420					nlen--;
1421				} else {
1422					if (trem < 3)
1423						return (ISC_R_NOSPACE);
1424					sprintf(tdata, "%%%02X", c);
1425					tdata += 3;
1426					trem -= 3;
1427					ndata++;
1428					nlen--;
1429				}
1430				count--;
1431			}
1432		} else {
1433			FATAL_ERROR(__FILE__, __LINE__,
1434				    "Unexpected label type %02x", count);
1435			/* NOTREACHED */
1436		}
1437
1438		/*
1439		 * The following assumes names are absolute.  If not, we
1440		 * fix things up later.  Note that this means that in some
1441		 * cases one more byte of text buffer is required than is
1442		 * needed in the final output.
1443		 */
1444		if (trem == 0)
1445			return (ISC_R_NOSPACE);
1446		*tdata++ = '.';
1447		trem--;
1448	}
1449
1450	if (nlen != 0 && trem == 0)
1451		return (ISC_R_NOSPACE);
1452
1453	if (omit_final_dot)
1454		trem++;
1455
1456	isc_buffer_add(target, tlen - trem);
1457
1458	return (ISC_R_SUCCESS);
1459}
1460
1461isc_result_t
1462dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1463	unsigned char *sndata, *ndata;
1464	unsigned int nlen, count, labels;
1465	isc_buffer_t buffer;
1466
1467	/*
1468	 * Downcase 'source'.
1469	 */
1470
1471	REQUIRE(VALID_NAME(source));
1472	REQUIRE(VALID_NAME(name));
1473	if (source == name) {
1474		REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1475		isc_buffer_init(&buffer, source->ndata, source->length);
1476		target = &buffer;
1477		ndata = source->ndata;
1478	} else {
1479		REQUIRE(BINDABLE(name));
1480		REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1481			(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1482		if (target == NULL) {
1483			target = name->buffer;
1484			isc_buffer_clear(name->buffer);
1485		}
1486		ndata = (unsigned char *)target->base + target->used;
1487		name->ndata = ndata;
1488	}
1489
1490	sndata = source->ndata;
1491	nlen = source->length;
1492	labels = source->labels;
1493
1494	if (nlen > (target->length - target->used)) {
1495		MAKE_EMPTY(name);
1496		return (ISC_R_NOSPACE);
1497	}
1498
1499	while (labels > 0 && nlen > 0) {
1500		labels--;
1501		count = *sndata++;
1502		*ndata++ = count;
1503		nlen--;
1504		if (count < 64) {
1505			INSIST(nlen >= count);
1506			while (count > 0) {
1507				*ndata++ = maptolower[(*sndata++)];
1508				nlen--;
1509				count--;
1510			}
1511		} else {
1512			FATAL_ERROR(__FILE__, __LINE__,
1513				    "Unexpected label type %02x", count);
1514			/* Does not return. */
1515		}
1516	}
1517
1518	if (source != name) {
1519		name->labels = source->labels;
1520		name->length = source->length;
1521		if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1522			name->attributes = DNS_NAMEATTR_ABSOLUTE;
1523		else
1524			name->attributes = 0;
1525		if (name->labels > 0 && name->offsets != NULL)
1526			set_offsets(name, name->offsets, NULL);
1527	}
1528
1529	isc_buffer_add(target, name->length);
1530
1531	return (ISC_R_SUCCESS);
1532}
1533
1534static void
1535set_offsets(const dns_name_t *name, unsigned char *offsets,
1536	    dns_name_t *set_name)
1537{
1538	unsigned int offset, count, length, nlabels;
1539	unsigned char *ndata;
1540	isc_boolean_t absolute;
1541
1542	ndata = name->ndata;
1543	length = name->length;
1544	offset = 0;
1545	nlabels = 0;
1546	absolute = ISC_FALSE;
1547	while (offset != length) {
1548		INSIST(nlabels < 128);
1549		offsets[nlabels++] = offset;
1550		count = *ndata++;
1551		offset++;
1552		INSIST(count <= 63);
1553		offset += count;
1554		ndata += count;
1555		INSIST(offset <= length);
1556		if (count == 0) {
1557			absolute = ISC_TRUE;
1558			break;
1559		}
1560	}
1561	if (set_name != NULL) {
1562		INSIST(set_name == name);
1563
1564		set_name->labels = nlabels;
1565		set_name->length = offset;
1566		if (absolute)
1567			set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1568		else
1569			set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1570	}
1571	INSIST(nlabels == name->labels);
1572	INSIST(offset == name->length);
1573}
1574
1575isc_result_t
1576dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1577		  dns_decompress_t *dctx, unsigned int options,
1578		  isc_buffer_t *target)
1579{
1580	unsigned char *cdata, *ndata;
1581	unsigned int cused; /* Bytes of compressed name data used */
1582	unsigned int hops,  nused, labels, n, nmax;
1583	unsigned int current, new_current, biggest_pointer;
1584	isc_boolean_t done;
1585	fw_state state = fw_start;
1586	unsigned int c;
1587	unsigned char *offsets;
1588	dns_offsets_t odata;
1589	isc_boolean_t downcase;
1590
1591	/*
1592	 * Copy the possibly-compressed name at source into target,
1593	 * decompressing it.
1594	 */
1595
1596	REQUIRE(VALID_NAME(name));
1597	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1598		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1599
1600	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1601
1602	if (target == NULL && name->buffer != NULL) {
1603		target = name->buffer;
1604		isc_buffer_clear(target);
1605	}
1606
1607	REQUIRE(dctx != NULL);
1608	REQUIRE(BINDABLE(name));
1609
1610	INIT_OFFSETS(name, offsets, odata);
1611
1612	/*
1613	 * Make 'name' empty in case of failure.
1614	 */
1615	MAKE_EMPTY(name);
1616
1617	/*
1618	 * Initialize things to make the compiler happy; they're not required.
1619	 */
1620	n = 0;
1621	new_current = 0;
1622
1623	/*
1624	 * Set up.
1625	 */
1626	labels = 0;
1627	hops = 0;
1628	done = ISC_FALSE;
1629
1630	ndata = isc_buffer_used(target);
1631	nused = 0;
1632
1633	/*
1634	 * Find the maximum number of uncompressed target name
1635	 * bytes we are willing to generate.  This is the smaller
1636	 * of the available target buffer length and the
1637	 * maximum legal domain name length (255).
1638	 */
1639	nmax = isc_buffer_availablelength(target);
1640	if (nmax > DNS_NAME_MAXWIRE)
1641		nmax = DNS_NAME_MAXWIRE;
1642
1643	cdata = isc_buffer_current(source);
1644	cused = 0;
1645
1646	current = source->current;
1647	biggest_pointer = current;
1648
1649	/*
1650	 * Note:  The following code is not optimized for speed, but
1651	 * rather for correctness.  Speed will be addressed in the future.
1652	 */
1653
1654	while (current < source->active && !done) {
1655		c = *cdata++;
1656		current++;
1657		if (hops == 0)
1658			cused++;
1659
1660		switch (state) {
1661		case fw_start:
1662			if (c < 64) {
1663				offsets[labels] = nused;
1664				labels++;
1665				if (nused + c + 1 > nmax)
1666					goto full;
1667				nused += c + 1;
1668				*ndata++ = c;
1669				if (c == 0)
1670					done = ISC_TRUE;
1671				n = c;
1672				state = fw_ordinary;
1673			} else if (c >= 128 && c < 192) {
1674				/*
1675				 * 14 bit local compression pointer.
1676				 * Local compression is no longer an
1677				 * IETF draft.
1678				 */
1679				return (DNS_R_BADLABELTYPE);
1680			} else if (c >= 192) {
1681				/*
1682				 * Ordinary 14-bit pointer.
1683				 */
1684				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1685				    0)
1686					return (DNS_R_DISALLOWED);
1687				new_current = c & 0x3F;
1688				n = 1;
1689				state = fw_newcurrent;
1690			} else
1691				return (DNS_R_BADLABELTYPE);
1692			break;
1693		case fw_ordinary:
1694			if (downcase)
1695				c = maptolower[c];
1696			/* FALLTHROUGH */
1697		case fw_copy:
1698			*ndata++ = c;
1699			n--;
1700			if (n == 0)
1701				state = fw_start;
1702			break;
1703		case fw_newcurrent:
1704			new_current *= 256;
1705			new_current += c;
1706			n--;
1707			if (n != 0)
1708				break;
1709			if (new_current >= biggest_pointer)
1710				return (DNS_R_BADPOINTER);
1711			biggest_pointer = new_current;
1712			current = new_current;
1713			cdata = (unsigned char *)source->base +
1714				current;
1715			hops++;
1716			if (hops > DNS_POINTER_MAXHOPS)
1717				return (DNS_R_TOOMANYHOPS);
1718			state = fw_start;
1719			break;
1720		default:
1721			FATAL_ERROR(__FILE__, __LINE__,
1722				    "Unknown state %d", state);
1723			/* Does not return. */
1724		}
1725	}
1726
1727	if (!done)
1728		return (ISC_R_UNEXPECTEDEND);
1729
1730	name->ndata = (unsigned char *)target->base + target->used;
1731	name->labels = labels;
1732	name->length = nused;
1733	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1734
1735	isc_buffer_forward(source, cused);
1736	isc_buffer_add(target, name->length);
1737
1738	return (ISC_R_SUCCESS);
1739
1740 full:
1741	if (nmax == DNS_NAME_MAXWIRE)
1742		/*
1743		 * The name did not fit even though we had a buffer
1744		 * big enough to fit a maximum-length name.
1745		 */
1746		return (DNS_R_NAMETOOLONG);
1747	else
1748		/*
1749		 * The name might fit if only the caller could give us a
1750		 * big enough buffer.
1751		 */
1752		return (ISC_R_NOSPACE);
1753
1754}
1755
1756isc_result_t
1757dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
1758	unsigned int methods;
1759	isc_uint16_t offset;
1760	dns_name_t gp;	/* Global compression prefix */
1761	isc_boolean_t gf;	/* Global compression target found */
1762	isc_uint16_t go;	/* Global compression offset */
1763	dns_offsets_t clo;
1764	dns_name_t clname;
1765
1766	/*
1767	 * Convert 'name' into wire format, compressing it as specified by the
1768	 * compression context 'cctx', and storing the result in 'target'.
1769	 */
1770
1771	REQUIRE(VALID_NAME(name));
1772	REQUIRE(cctx != NULL);
1773	REQUIRE(ISC_BUFFER_VALID(target));
1774
1775	/*
1776	 * If 'name' doesn't have an offsets table, make a clone which
1777	 * has one.
1778	 */
1779	if (name->offsets == NULL) {
1780		DNS_NAME_INIT(&clname, clo);
1781		dns_name_clone(name, &clname);
1782		name = &clname;
1783	}
1784	DNS_NAME_INIT(&gp, NULL);
1785
1786	offset = target->used;	/*XXX*/
1787
1788	methods = dns_compress_getmethods(cctx);
1789
1790	if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
1791		gf = dns_compress_findglobal(cctx, name, &gp, &go);
1792	else
1793		gf = ISC_FALSE;
1794
1795	/*
1796	 * If the offset is too high for 14 bit global compression, we're
1797	 * out of luck.
1798	 */
1799	if (gf && go >= 0x4000)
1800		gf = ISC_FALSE;
1801
1802	/*
1803	 * Will the compression pointer reduce the message size?
1804	 */
1805	if (gf && (gp.length + 2) >= name->length)
1806		gf = ISC_FALSE;
1807
1808	if (gf) {
1809		if (target->length - target->used < gp.length)
1810			return (ISC_R_NOSPACE);
1811		(void)memcpy((unsigned char *)target->base + target->used,
1812			     gp.ndata, (size_t)gp.length);
1813		isc_buffer_add(target, gp.length);
1814		go |= 0xc000;
1815		if (target->length - target->used < 2)
1816			return (ISC_R_NOSPACE);
1817		isc_buffer_putuint16(target, go);
1818		if (gp.length != 0)
1819			dns_compress_add(cctx, name, &gp, offset);
1820	} else {
1821		if (target->length - target->used < name->length)
1822			return (ISC_R_NOSPACE);
1823		(void)memcpy((unsigned char *)target->base + target->used,
1824			     name->ndata, (size_t)name->length);
1825		isc_buffer_add(target, name->length);
1826		dns_compress_add(cctx, name, name, offset);
1827	}
1828	return (ISC_R_SUCCESS);
1829}
1830
1831isc_result_t
1832dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1833		     isc_buffer_t *target)
1834{
1835	unsigned char *ndata, *offsets;
1836	unsigned int nrem, labels, prefix_length, length;
1837	isc_boolean_t copy_prefix = ISC_TRUE;
1838	isc_boolean_t copy_suffix = ISC_TRUE;
1839	isc_boolean_t absolute = ISC_FALSE;
1840	dns_name_t tmp_name;
1841	dns_offsets_t odata;
1842
1843	/*
1844	 * Concatenate 'prefix' and 'suffix'.
1845	 */
1846
1847	REQUIRE(prefix == NULL || VALID_NAME(prefix));
1848	REQUIRE(suffix == NULL || VALID_NAME(suffix));
1849	REQUIRE(name == NULL || VALID_NAME(name));
1850	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1851		(target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1852	if (prefix == NULL || prefix->labels == 0)
1853		copy_prefix = ISC_FALSE;
1854	if (suffix == NULL || suffix->labels == 0)
1855		copy_suffix = ISC_FALSE;
1856	if (copy_prefix &&
1857	    (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1858		absolute = ISC_TRUE;
1859		REQUIRE(!copy_suffix);
1860	}
1861	if (name == NULL) {
1862		DNS_NAME_INIT(&tmp_name, odata);
1863		name = &tmp_name;
1864	}
1865	if (target == NULL) {
1866		INSIST(name->buffer != NULL);
1867		target = name->buffer;
1868		isc_buffer_clear(name->buffer);
1869	}
1870
1871	REQUIRE(BINDABLE(name));
1872
1873	/*
1874	 * Set up.
1875	 */
1876	nrem = target->length - target->used;
1877	ndata = (unsigned char *)target->base + target->used;
1878	if (nrem > DNS_NAME_MAXWIRE)
1879		nrem = DNS_NAME_MAXWIRE;
1880	length = 0;
1881	prefix_length = 0;
1882	labels = 0;
1883	if (copy_prefix) {
1884		prefix_length = prefix->length;
1885		length += prefix_length;
1886		labels += prefix->labels;
1887	}
1888	if (copy_suffix) {
1889		length += suffix->length;
1890		labels += suffix->labels;
1891	}
1892	if (length > DNS_NAME_MAXWIRE) {
1893		MAKE_EMPTY(name);
1894		return (DNS_R_NAMETOOLONG);
1895	}
1896	if (length > nrem) {
1897		MAKE_EMPTY(name);
1898		return (ISC_R_NOSPACE);
1899	}
1900
1901	if (copy_suffix) {
1902		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1903			absolute = ISC_TRUE;
1904		if (suffix == name && suffix->buffer == target)
1905			memmove(ndata + prefix_length, suffix->ndata,
1906				suffix->length);
1907		else
1908			memcpy(ndata + prefix_length, suffix->ndata,
1909			       suffix->length);
1910	}
1911
1912	/*
1913	 * If 'prefix' and 'name' are the same object, and the object has
1914	 * a dedicated buffer, and we're using it, then we don't have to
1915	 * copy anything.
1916	 */
1917	if (copy_prefix && (prefix != name || prefix->buffer != target))
1918		memcpy(ndata, prefix->ndata, prefix_length);
1919
1920	name->ndata = ndata;
1921	name->labels = labels;
1922	name->length = length;
1923	if (absolute)
1924		name->attributes = DNS_NAMEATTR_ABSOLUTE;
1925	else
1926		name->attributes = 0;
1927
1928	if (name->labels > 0 && name->offsets != NULL) {
1929		INIT_OFFSETS(name, offsets, odata);
1930		set_offsets(name, offsets, NULL);
1931	}
1932
1933	isc_buffer_add(target, name->length);
1934
1935	return (ISC_R_SUCCESS);
1936}
1937
1938void
1939dns_name_split(dns_name_t *name, unsigned int suffixlabels,
1940	       dns_name_t *prefix, dns_name_t *suffix)
1941
1942{
1943	unsigned int splitlabel;
1944
1945	REQUIRE(VALID_NAME(name));
1946	REQUIRE(suffixlabels > 0);
1947	REQUIRE(suffixlabels < name->labels);
1948	REQUIRE(prefix != NULL || suffix != NULL);
1949	REQUIRE(prefix == NULL ||
1950		(VALID_NAME(prefix) &&
1951		 prefix->buffer != NULL &&
1952		 BINDABLE(prefix)));
1953	REQUIRE(suffix == NULL ||
1954		(VALID_NAME(suffix) &&
1955		 suffix->buffer != NULL &&
1956		 BINDABLE(suffix)));
1957
1958	splitlabel = name->labels - suffixlabels;
1959
1960	if (prefix != NULL)
1961		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
1962
1963	if (suffix != NULL)
1964		dns_name_getlabelsequence(name, splitlabel,
1965					  suffixlabels, suffix);
1966
1967	return;
1968}
1969
1970isc_result_t
1971dns_name_dup(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
1972	/*
1973	 * Make 'target' a dynamically allocated copy of 'source'.
1974	 */
1975
1976	REQUIRE(VALID_NAME(source));
1977	REQUIRE(source->length > 0);
1978	REQUIRE(VALID_NAME(target));
1979	REQUIRE(BINDABLE(target));
1980
1981	/*
1982	 * Make 'target' empty in case of failure.
1983	 */
1984	MAKE_EMPTY(target);
1985
1986	target->ndata = isc_mem_get(mctx, source->length);
1987	if (target->ndata == NULL)
1988		return (ISC_R_NOMEMORY);
1989
1990	memcpy(target->ndata, source->ndata, source->length);
1991
1992	target->length = source->length;
1993	target->labels = source->labels;
1994	target->attributes = DNS_NAMEATTR_DYNAMIC;
1995	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1996		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
1997	if (target->offsets != NULL) {
1998		if (source->offsets != NULL)
1999			memcpy(target->offsets, source->offsets,
2000			       source->labels);
2001		else
2002			set_offsets(target, target->offsets, NULL);
2003	}
2004
2005	return (ISC_R_SUCCESS);
2006}
2007
2008isc_result_t
2009dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2010			dns_name_t *target)
2011{
2012	/*
2013	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2014	 * 'target' will also have a dynamically allocated offsets table.
2015	 */
2016
2017	REQUIRE(VALID_NAME(source));
2018	REQUIRE(source->length > 0);
2019	REQUIRE(VALID_NAME(target));
2020	REQUIRE(BINDABLE(target));
2021	REQUIRE(target->offsets == NULL);
2022
2023	/*
2024	 * Make 'target' empty in case of failure.
2025	 */
2026	MAKE_EMPTY(target);
2027
2028	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2029	if (target->ndata == NULL)
2030		return (ISC_R_NOMEMORY);
2031
2032	memcpy(target->ndata, source->ndata, source->length);
2033
2034	target->length = source->length;
2035	target->labels = source->labels;
2036	target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2037		DNS_NAMEATTR_READONLY;
2038	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2039		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2040	target->offsets = target->ndata + source->length;
2041	if (source->offsets != NULL)
2042		memcpy(target->offsets, source->offsets, source->labels);
2043	else
2044		set_offsets(target, target->offsets, NULL);
2045
2046	return (ISC_R_SUCCESS);
2047}
2048
2049void
2050dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2051	size_t size;
2052
2053	/*
2054	 * Free 'name'.
2055	 */
2056
2057	REQUIRE(VALID_NAME(name));
2058	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2059
2060	size = name->length;
2061	if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2062		size += name->labels;
2063	isc_mem_put(mctx, name->ndata, size);
2064	dns_name_invalidate(name);
2065}
2066
2067isc_result_t
2068dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2069	dns_name_t downname;
2070	unsigned char data[256];
2071	isc_buffer_t buffer;
2072	isc_result_t result;
2073	isc_region_t r;
2074
2075	/*
2076	 * Send 'name' in DNSSEC canonical form to 'digest'.
2077	 */
2078
2079	REQUIRE(VALID_NAME(name));
2080	REQUIRE(digest != NULL);
2081
2082	DNS_NAME_INIT(&downname, NULL);
2083	isc_buffer_init(&buffer, data, sizeof(data));
2084
2085	result = dns_name_downcase(name, &downname, &buffer);
2086	if (result != ISC_R_SUCCESS)
2087		return (result);
2088
2089	isc_buffer_usedregion(&buffer, &r);
2090
2091	return ((digest)(arg, &r));
2092}
2093
2094isc_boolean_t
2095dns_name_dynamic(dns_name_t *name) {
2096	REQUIRE(VALID_NAME(name));
2097
2098	/*
2099	 * Returns whether there is dynamic memory associated with this name.
2100	 */
2101
2102	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2103		ISC_TRUE : ISC_FALSE);
2104}
2105
2106isc_result_t
2107dns_name_print(dns_name_t *name, FILE *stream) {
2108	isc_result_t result;
2109	isc_buffer_t b;
2110	isc_region_t r;
2111	char t[1024];
2112
2113	/*
2114	 * Print 'name' on 'stream'.
2115	 */
2116
2117	REQUIRE(VALID_NAME(name));
2118
2119	isc_buffer_init(&b, t, sizeof(t));
2120	result = dns_name_totext(name, ISC_FALSE, &b);
2121	if (result != ISC_R_SUCCESS)
2122		return (result);
2123	isc_buffer_usedregion(&b, &r);
2124	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2125
2126	return (ISC_R_SUCCESS);
2127}
2128
2129void
2130dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2131	isc_result_t result;
2132	isc_buffer_t buf;
2133
2134	REQUIRE(size > 0);
2135
2136	/*
2137	 * Leave room for null termination after buffer.
2138	 */
2139	isc_buffer_init(&buf, cp, size - 1);
2140	result = dns_name_totext(name, ISC_TRUE, &buf);
2141	if (result == ISC_R_SUCCESS) {
2142		/*
2143		 * Null terminate.
2144		 */
2145		isc_region_t r;
2146		isc_buffer_usedregion(&buf, &r);
2147		((char *) r.base)[r.length] = '\0';
2148
2149	} else
2150		snprintf(cp, size, "<unknown>");
2151}
2152
2153isc_result_t
2154dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2155	unsigned char *ndata;
2156
2157	/*
2158	 * Make dest a copy of source.
2159	 */
2160
2161	REQUIRE(VALID_NAME(source));
2162	REQUIRE(VALID_NAME(dest));
2163	REQUIRE(target != NULL || dest->buffer != NULL);
2164
2165	if (target == NULL) {
2166		target = dest->buffer;
2167		isc_buffer_clear(dest->buffer);
2168	}
2169
2170	REQUIRE(BINDABLE(dest));
2171
2172	/*
2173	 * Set up.
2174	 */
2175	if (target->length - target->used < source->length)
2176		return (ISC_R_NOSPACE);
2177
2178	ndata = (unsigned char *)target->base + target->used;
2179	dest->ndata = target->base;
2180
2181	memcpy(ndata, source->ndata, source->length);
2182
2183	dest->ndata = ndata;
2184	dest->labels = source->labels;
2185	dest->length = source->length;
2186	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2187		dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2188	else
2189		dest->attributes = 0;
2190
2191	if (dest->labels > 0 && dest->offsets != NULL) {
2192		if (source->offsets != NULL)
2193			memcpy(dest->offsets, source->offsets, source->labels);
2194		else
2195			set_offsets(dest, dest->offsets, NULL);
2196	}
2197
2198	isc_buffer_add(target, dest->length);
2199
2200	return (ISC_R_SUCCESS);
2201}
2202
2203