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