1/*	$NetBSD: name.c,v 1.14 2024/02/21 22:52:07 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/result.h>
30#include <isc/string.h>
31#include <isc/thread.h>
32#include <isc/util.h>
33
34#include <dns/compress.h>
35#include <dns/fixedname.h>
36#include <dns/name.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);
142const 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
150const dns_name_t *dns_wildcardname = &wild;
151
152/*
153 * dns_name_t to text post-conversion procedure.
154 */
155static 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	 * RFC952/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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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("Unexpected state %d", state);
1252			/* Does not return. */
1253		}
1254	}
1255
1256	if (!done) {
1257		if (nrem == 0) {
1258			return (ISC_R_NOSPACE);
1259		}
1260		INSIST(tlen == 0);
1261		if (state != ft_ordinary && state != ft_at) {
1262			return (ISC_R_UNEXPECTEDEND);
1263		}
1264		if (state == ft_ordinary) {
1265			INSIST(count != 0);
1266			INSIST(label != NULL);
1267			*label = count;
1268			labels++;
1269			INSIST(labels <= 127);
1270			offsets[labels] = nused;
1271		}
1272		if (origin != NULL) {
1273			if (nrem < origin->length) {
1274				return (ISC_R_NOSPACE);
1275			}
1276			label = origin->ndata;
1277			n1 = origin->length;
1278			nrem -= n1;
1279			POST(nrem);
1280			while (n1 > 0) {
1281				n2 = *label++;
1282				INSIST(n2 <= 63); /* no bitstring support */
1283				*ndata++ = n2;
1284				n1 -= n2 + 1;
1285				nused += n2 + 1;
1286				while (n2 > 0) {
1287					c = *label++;
1288					if (downcase) {
1289						c = maptolower[c & 0xff];
1290					}
1291					*ndata++ = c;
1292					n2--;
1293				}
1294				labels++;
1295				if (n1 > 0) {
1296					INSIST(labels <= 127);
1297					offsets[labels] = nused;
1298				}
1299			}
1300			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1301				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1302			}
1303		}
1304	} else {
1305		name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1306	}
1307
1308	name->ndata = (unsigned char *)target->base + target->used;
1309	name->labels = labels;
1310	name->length = nused;
1311
1312	isc_buffer_forward(source, tused);
1313	isc_buffer_add(target, name->length);
1314
1315	return (ISC_R_SUCCESS);
1316}
1317
1318isc_result_t
1319dns_name_totext(const dns_name_t *name, bool omit_final_dot,
1320		isc_buffer_t *target) {
1321	unsigned int options = DNS_NAME_MASTERFILE;
1322
1323	if (omit_final_dot) {
1324		options |= DNS_NAME_OMITFINALDOT;
1325	}
1326	return (dns_name_totext2(name, options, target));
1327}
1328
1329isc_result_t
1330dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) {
1331	return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1332}
1333
1334isc_result_t
1335dns_name_totext2(const dns_name_t *name, unsigned int options,
1336		 isc_buffer_t *target) {
1337	unsigned char *ndata;
1338	char *tdata;
1339	unsigned int nlen, tlen;
1340	unsigned char c;
1341	unsigned int trem, count;
1342	unsigned int labels;
1343	bool saw_root = false;
1344	unsigned int oused;
1345	bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
1346
1347	/*
1348	 * This function assumes the name is in proper uncompressed
1349	 * wire format.
1350	 */
1351	REQUIRE(VALID_NAME(name));
1352	REQUIRE(ISC_BUFFER_VALID(target));
1353
1354	oused = target->used;
1355
1356	ndata = name->ndata;
1357	nlen = name->length;
1358	labels = name->labels;
1359	tdata = isc_buffer_used(target);
1360	tlen = isc_buffer_availablelength(target);
1361
1362	trem = tlen;
1363
1364	if (labels == 0 && nlen == 0) {
1365		/*
1366		 * Special handling for an empty name.
1367		 */
1368		if (trem == 0) {
1369			return (ISC_R_NOSPACE);
1370		}
1371
1372		/*
1373		 * The names of these booleans are misleading in this case.
1374		 * This empty name is not necessarily from the root node of
1375		 * the DNS root zone, nor is a final dot going to be included.
1376		 * They need to be set this way, though, to keep the "@"
1377		 * from being trounced.
1378		 */
1379		saw_root = true;
1380		omit_final_dot = false;
1381		*tdata++ = '@';
1382		trem--;
1383
1384		/*
1385		 * Skip the while() loop.
1386		 */
1387		nlen = 0;
1388	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1389		/*
1390		 * Special handling for the root label.
1391		 */
1392		if (trem == 0) {
1393			return (ISC_R_NOSPACE);
1394		}
1395
1396		saw_root = true;
1397		omit_final_dot = false;
1398		*tdata++ = '.';
1399		trem--;
1400
1401		/*
1402		 * Skip the while() loop.
1403		 */
1404		nlen = 0;
1405	}
1406
1407	while (labels > 0 && nlen > 0 && trem > 0) {
1408		labels--;
1409		count = *ndata++;
1410		nlen--;
1411		if (count == 0) {
1412			saw_root = true;
1413			break;
1414		}
1415		if (count < 64) {
1416			INSIST(nlen >= count);
1417			while (count > 0) {
1418				c = *ndata;
1419				switch (c) {
1420				/* Special modifiers in zone files. */
1421				case 0x40: /* '@' */
1422				case 0x24: /* '$' */
1423					if ((options & DNS_NAME_MASTERFILE) ==
1424					    0)
1425					{
1426						goto no_escape;
1427					}
1428					FALLTHROUGH;
1429				case 0x22: /* '"' */
1430				case 0x28: /* '(' */
1431				case 0x29: /* ')' */
1432				case 0x2E: /* '.' */
1433				case 0x3B: /* ';' */
1434				case 0x5C: /* '\\' */
1435					if (trem < 2) {
1436						return (ISC_R_NOSPACE);
1437					}
1438					*tdata++ = '\\';
1439					CONVERTFROMASCII(c);
1440					*tdata++ = c;
1441					ndata++;
1442					trem -= 2;
1443					nlen--;
1444					break;
1445				no_escape:
1446				default:
1447					if (c > 0x20 && c < 0x7f) {
1448						if (trem == 0) {
1449							return (ISC_R_NOSPACE);
1450						}
1451						CONVERTFROMASCII(c);
1452						*tdata++ = c;
1453						ndata++;
1454						trem--;
1455						nlen--;
1456					} else {
1457						if (trem < 4) {
1458							return (ISC_R_NOSPACE);
1459						}
1460						*tdata++ = 0x5c;
1461						*tdata++ = 0x30 +
1462							   ((c / 100) % 10);
1463						*tdata++ = 0x30 +
1464							   ((c / 10) % 10);
1465						*tdata++ = 0x30 + (c % 10);
1466						trem -= 4;
1467						ndata++;
1468						nlen--;
1469					}
1470				}
1471				count--;
1472			}
1473		} else {
1474			FATAL_ERROR("Unexpected label type %02x", count);
1475			UNREACHABLE();
1476		}
1477
1478		/*
1479		 * The following assumes names are absolute.  If not, we
1480		 * fix things up later.  Note that this means that in some
1481		 * cases one more byte of text buffer is required than is
1482		 * needed in the final output.
1483		 */
1484		if (trem == 0) {
1485			return (ISC_R_NOSPACE);
1486		}
1487		*tdata++ = '.';
1488		trem--;
1489	}
1490
1491	if (nlen != 0 && trem == 0) {
1492		return (ISC_R_NOSPACE);
1493	}
1494
1495	if (!saw_root || omit_final_dot) {
1496		trem++;
1497		tdata--;
1498	}
1499	if (trem > 0) {
1500		*tdata = 0;
1501	}
1502	isc_buffer_add(target, tlen - trem);
1503
1504	if (totext_filter_proc != NULL) {
1505		return ((totext_filter_proc)(target, oused));
1506	}
1507
1508	return (ISC_R_SUCCESS);
1509}
1510
1511isc_result_t
1512dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot,
1513			isc_buffer_t *target) {
1514	unsigned char *ndata;
1515	char *tdata;
1516	unsigned int nlen, tlen;
1517	unsigned char c;
1518	unsigned int trem, count;
1519	unsigned int labels;
1520
1521	/*
1522	 * This function assumes the name is in proper uncompressed
1523	 * wire format.
1524	 */
1525	REQUIRE(VALID_NAME(name));
1526	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1527	REQUIRE(ISC_BUFFER_VALID(target));
1528
1529	ndata = name->ndata;
1530	nlen = name->length;
1531	labels = name->labels;
1532	tdata = isc_buffer_used(target);
1533	tlen = isc_buffer_availablelength(target);
1534
1535	trem = tlen;
1536
1537	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1538		/*
1539		 * Special handling for the root label.
1540		 */
1541		if (trem == 0) {
1542			return (ISC_R_NOSPACE);
1543		}
1544
1545		omit_final_dot = false;
1546		*tdata++ = '.';
1547		trem--;
1548
1549		/*
1550		 * Skip the while() loop.
1551		 */
1552		nlen = 0;
1553	}
1554
1555	while (labels > 0 && nlen > 0 && trem > 0) {
1556		labels--;
1557		count = *ndata++;
1558		nlen--;
1559		if (count == 0) {
1560			break;
1561		}
1562		if (count < 64) {
1563			INSIST(nlen >= count);
1564			while (count > 0) {
1565				c = *ndata;
1566				if ((c >= 0x30 && c <= 0x39) || /* digit */
1567				    (c >= 0x41 && c <= 0x5A) || /* uppercase */
1568				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
1569				    c == 0x2D ||		/* hyphen */
1570				    c == 0x5F)			/* underscore */
1571				{
1572					if (trem == 0) {
1573						return (ISC_R_NOSPACE);
1574					}
1575					/* downcase */
1576					if (c >= 0x41 && c <= 0x5A) {
1577						c += 0x20;
1578					}
1579					CONVERTFROMASCII(c);
1580					*tdata++ = c;
1581					ndata++;
1582					trem--;
1583					nlen--;
1584				} else {
1585					if (trem < 4) {
1586						return (ISC_R_NOSPACE);
1587					}
1588					snprintf(tdata, trem, "%%%02X", c);
1589					tdata += 3;
1590					trem -= 3;
1591					ndata++;
1592					nlen--;
1593				}
1594				count--;
1595			}
1596		} else {
1597			FATAL_ERROR("Unexpected label type %02x", count);
1598			UNREACHABLE();
1599		}
1600
1601		/*
1602		 * The following assumes names are absolute.  If not, we
1603		 * fix things up later.  Note that this means that in some
1604		 * cases one more byte of text buffer is required than is
1605		 * needed in the final output.
1606		 */
1607		if (trem == 0) {
1608			return (ISC_R_NOSPACE);
1609		}
1610		*tdata++ = '.';
1611		trem--;
1612	}
1613
1614	if (nlen != 0 && trem == 0) {
1615		return (ISC_R_NOSPACE);
1616	}
1617
1618	if (omit_final_dot) {
1619		trem++;
1620	}
1621
1622	isc_buffer_add(target, tlen - trem);
1623
1624	return (ISC_R_SUCCESS);
1625}
1626
1627isc_result_t
1628dns_name_downcase(const dns_name_t *source, dns_name_t *name,
1629		  isc_buffer_t *target) {
1630	unsigned char *sndata, *ndata;
1631	unsigned int nlen, count, labels;
1632	isc_buffer_t buffer;
1633
1634	/*
1635	 * Downcase 'source'.
1636	 */
1637
1638	REQUIRE(VALID_NAME(source));
1639	REQUIRE(VALID_NAME(name));
1640	if (source == name) {
1641		REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1642		isc_buffer_init(&buffer, source->ndata, source->length);
1643		target = &buffer;
1644		ndata = source->ndata;
1645	} else {
1646		REQUIRE(BINDABLE(name));
1647		REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1648			(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1649		if (target == NULL) {
1650			target = name->buffer;
1651			isc_buffer_clear(name->buffer);
1652		}
1653		ndata = (unsigned char *)target->base + target->used;
1654		name->ndata = ndata;
1655	}
1656
1657	sndata = source->ndata;
1658	nlen = source->length;
1659	labels = source->labels;
1660
1661	if (nlen > (target->length - target->used)) {
1662		MAKE_EMPTY(name);
1663		return (ISC_R_NOSPACE);
1664	}
1665
1666	while (labels > 0 && nlen > 0) {
1667		labels--;
1668		count = *sndata++;
1669		*ndata++ = count;
1670		nlen--;
1671		if (count < 64) {
1672			INSIST(nlen >= count);
1673			while (count > 0) {
1674				*ndata++ = maptolower[(*sndata++)];
1675				nlen--;
1676				count--;
1677			}
1678		} else {
1679			FATAL_ERROR("Unexpected label type %02x", count);
1680			/* Does not return. */
1681		}
1682	}
1683
1684	if (source != name) {
1685		name->labels = source->labels;
1686		name->length = source->length;
1687		if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1688			name->attributes = DNS_NAMEATTR_ABSOLUTE;
1689		} else {
1690			name->attributes = 0;
1691		}
1692		if (name->labels > 0 && name->offsets != NULL) {
1693			set_offsets(name, name->offsets, NULL);
1694		}
1695	}
1696
1697	isc_buffer_add(target, name->length);
1698
1699	return (ISC_R_SUCCESS);
1700}
1701
1702static void
1703set_offsets(const dns_name_t *name, unsigned char *offsets,
1704	    dns_name_t *set_name) {
1705	unsigned int offset, count, length, nlabels;
1706	unsigned char *ndata;
1707	bool absolute;
1708
1709	ndata = name->ndata;
1710	length = name->length;
1711	offset = 0;
1712	nlabels = 0;
1713	absolute = false;
1714	while (offset != length) {
1715		INSIST(nlabels < 128);
1716		offsets[nlabels++] = offset;
1717		count = *ndata;
1718		INSIST(count <= 63);
1719		offset += count + 1;
1720		ndata += count + 1;
1721		INSIST(offset <= length);
1722		if (count == 0) {
1723			absolute = true;
1724			break;
1725		}
1726	}
1727	if (set_name != NULL) {
1728		INSIST(set_name == name);
1729
1730		set_name->labels = nlabels;
1731		set_name->length = offset;
1732		if (absolute) {
1733			set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1734		} else {
1735			set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1736		}
1737	}
1738	INSIST(nlabels == name->labels);
1739	INSIST(offset == name->length);
1740}
1741
1742isc_result_t
1743dns_name_fromwire(dns_name_t *const name, isc_buffer_t *const source,
1744		  dns_decompress_t *const dctx, unsigned int options,
1745		  isc_buffer_t *target) {
1746	/*
1747	 * Copy the name at source into target, decompressing it.
1748	 *
1749	 *	*** WARNING ***
1750	 *
1751	 * dns_name_fromwire() deals with raw network data. An error in this
1752	 * routine could result in the failure or hijacking of the server.
1753	 *
1754	 * The description of name compression in RFC 1035 section 4.1.4 is
1755	 * subtle wrt certain edge cases. The first important sentence is:
1756	 *
1757	 * > In this scheme, an entire domain name or a list of labels at the
1758	 * > end of a domain name is replaced with a pointer to a prior
1759	 * > occurance of the same name.
1760	 *
1761	 * The key word is "prior". This says that compression pointers must
1762	 * point strictly earlier in the message (before our "marker" variable),
1763	 * which is enough to prevent DoS attacks due to compression loops.
1764	 *
1765	 * The next important sentence is:
1766	 *
1767	 * > If a domain name is contained in a part of the message subject to a
1768	 * > length field (such as the RDATA section of an RR), and compression
1769	 * > is used, the length of the compressed name is used in the length
1770	 * > calculation, rather than the length of the expanded name.
1771	 *
1772	 * When decompressing, this means that the amount of the source buffer
1773	 * that we consumed (which is checked wrt the container's length field)
1774	 * is the length of the compressed name. A compressed name is defined as
1775	 * a sequence of labels ending with the root label or a compression
1776	 * pointer, that is, the segment of the name that dns_name_fromwire()
1777	 * examines first.
1778	 *
1779	 * This matters when handling names that play dirty tricks, like:
1780	 *
1781	 *	+---+---+---+---+---+---+
1782	 *	| 4 | 1 |'a'|192| 0 | 0 |
1783	 *	+---+---+---+---+---+---+
1784	 *
1785	 * We start at octet 1. There is an ordinary single character label "a",
1786	 * followed by a compression pointer that refers back to octet zero.
1787	 * Here there is a label of length 4, which weirdly re-uses the octets
1788	 * we already examined as the data for the label. It is followed by the
1789	 * root label,
1790	 *
1791	 * The specification says that the compressed name ends after the first
1792	 * zero octet (after the compression pointer) not the second zero octet,
1793	 * even though the second octet is later in the message. This shows the
1794	 * correct way to set our "consumed" variable.
1795	 */
1796
1797	REQUIRE((options & DNS_NAME_DOWNCASE) == 0);
1798	REQUIRE(VALID_NAME(name));
1799	REQUIRE(BINDABLE(name));
1800	REQUIRE(dctx != NULL);
1801	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1802		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1803
1804	if (target == NULL && name->buffer != NULL) {
1805		target = name->buffer;
1806		isc_buffer_clear(target);
1807	}
1808
1809	uint8_t *const name_buf = isc_buffer_used(target);
1810	const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
1811					  isc_buffer_availablelength(target));
1812	uint32_t name_len = 0;
1813	MAKE_EMPTY(name); /* in case of failure */
1814
1815	dns_offsets_t odata;
1816	uint8_t *offsets = NULL;
1817	uint32_t labels = 0;
1818	INIT_OFFSETS(name, offsets, odata);
1819
1820	/*
1821	 * After chasing a compression pointer, these variables refer to the
1822	 * source buffer as follows:
1823	 *
1824	 * sb --- mr --- cr --- st --- cd --- sm
1825	 *
1826	 * sb = source_buf (const)
1827	 * mr = marker
1828	 * cr = cursor
1829	 * st = start (const)
1830	 * cd = consumed
1831	 * sm = source_max (const)
1832	 *
1833	 * The marker hops backwards for each pointer.
1834	 * The cursor steps forwards for each label.
1835	 * The amount of the source we consumed is set once.
1836	 */
1837	const uint8_t *const source_buf = isc_buffer_base(source);
1838	const uint8_t *const source_max = isc_buffer_used(source);
1839	const uint8_t *const start = isc_buffer_current(source);
1840	const uint8_t *marker = start;
1841	const uint8_t *cursor = start;
1842	const uint8_t *consumed = NULL;
1843
1844	/*
1845	 * One iteration per label.
1846	 */
1847	while (cursor < source_max) {
1848		const uint8_t label_len = *cursor++;
1849		if (label_len < 64) {
1850			/*
1851			 * Normal label: record its offset, and check bounds on
1852			 * the name length, which also ensures we don't overrun
1853			 * the offsets array. Don't touch any source bytes yet!
1854			 * The source bounds check will happen when we loop.
1855			 */
1856			offsets[labels++] = name_len;
1857			/* and then a step to the ri-i-i-i-i-ight */
1858			cursor += label_len;
1859			name_len += label_len + 1;
1860			if (name_len > name_max) {
1861				return (name_max == DNS_NAME_MAXWIRE
1862						? DNS_R_NAMETOOLONG
1863						: ISC_R_NOSPACE);
1864			} else if (label_len == 0) {
1865				goto root_label;
1866			}
1867		} else if (label_len < 192) {
1868			return (DNS_R_BADLABELTYPE);
1869		} else if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 0) {
1870			return (DNS_R_DISALLOWED);
1871		} else if (cursor < source_max) {
1872			/*
1873			 * Compression pointer. Ensure it does not loop.
1874			 *
1875			 * Copy multiple labels in one go, to make the most of
1876			 * memmove() performance. Start at the marker and finish
1877			 * just before the pointer's hi+lo bytes, before the
1878			 * cursor. Bounds were already checked.
1879			 */
1880			const uint32_t hi = label_len & 0x3F;
1881			const uint32_t lo = *cursor++;
1882			const uint8_t *pointer = source_buf + (256 * hi + lo);
1883			if (pointer >= marker) {
1884				return (DNS_R_BADPOINTER);
1885			}
1886			const uint32_t copy_len = (cursor - 2) - marker;
1887			uint8_t *const dest = name_buf + name_len - copy_len;
1888			memmove(dest, marker, copy_len);
1889			consumed = consumed != NULL ? consumed : cursor;
1890			/* it's just a jump to the left */
1891			cursor = marker = pointer;
1892		}
1893	}
1894	return (ISC_R_UNEXPECTEDEND);
1895root_label:;
1896	/*
1897	 * Copy labels almost like we do for compression pointers,
1898	 * from the marker up to and including the root label.
1899	 */
1900	const uint32_t copy_len = cursor - marker;
1901	memmove(name_buf + name_len - copy_len, marker, copy_len);
1902	consumed = consumed != NULL ? consumed : cursor;
1903	isc_buffer_forward(source, consumed - start);
1904
1905	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1906	name->ndata = name_buf;
1907	name->labels = labels;
1908	name->length = name_len;
1909	isc_buffer_add(target, name_len);
1910
1911	return (ISC_R_SUCCESS);
1912}
1913
1914isc_result_t
1915dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1916		isc_buffer_t *target) {
1917	return (dns_name_towire2(name, cctx, target, NULL));
1918}
1919
1920isc_result_t
1921dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
1922		 isc_buffer_t *target, uint16_t *comp_offsetp) {
1923	unsigned int methods;
1924	uint16_t offset;
1925	dns_name_t gp; /* Global compression prefix */
1926	bool gf;       /* Global compression target found */
1927	uint16_t go;   /* Global compression offset */
1928	dns_offsets_t clo;
1929	dns_name_t clname;
1930
1931	/*
1932	 * Convert 'name' into wire format, compressing it as specified by the
1933	 * compression context 'cctx', and storing the result in 'target'.
1934	 */
1935
1936	REQUIRE(VALID_NAME(name));
1937	REQUIRE(cctx != NULL);
1938	REQUIRE(ISC_BUFFER_VALID(target));
1939
1940	/*
1941	 * If this exact name was already rendered before, and the
1942	 * offset of the previously rendered name is passed to us, write
1943	 * a compression pointer directly.
1944	 */
1945	methods = dns_compress_getmethods(cctx);
1946	if (comp_offsetp != NULL && *comp_offsetp < 0x4000 &&
1947	    (name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1948	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1949	{
1950		if (target->length - target->used < 2) {
1951			return (ISC_R_NOSPACE);
1952		}
1953		offset = *comp_offsetp;
1954		offset |= 0xc000;
1955		isc_buffer_putuint16(target, offset);
1956		return (ISC_R_SUCCESS);
1957	}
1958
1959	/*
1960	 * If 'name' doesn't have an offsets table, make a clone which
1961	 * has one.
1962	 */
1963	if (name->offsets == NULL) {
1964		DNS_NAME_INIT(&clname, clo);
1965		dns_name_clone(name, &clname);
1966		name = &clname;
1967	}
1968	DNS_NAME_INIT(&gp, NULL);
1969
1970	offset = target->used; /*XXX*/
1971
1972	if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1973	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1974	{
1975		gf = dns_compress_findglobal(cctx, name, &gp, &go);
1976	} else {
1977		gf = false;
1978	}
1979
1980	/*
1981	 * If the offset is too high for 14 bit global compression, we're
1982	 * out of luck.
1983	 */
1984	if (gf && go >= 0x4000) {
1985		gf = false;
1986	}
1987
1988	/*
1989	 * Will the compression pointer reduce the message size?
1990	 */
1991	if (gf && (gp.length + 2) >= name->length) {
1992		gf = false;
1993	}
1994
1995	if (gf) {
1996		if (target->length - target->used < gp.length) {
1997			return (ISC_R_NOSPACE);
1998		}
1999		if (gp.length != 0) {
2000			unsigned char *base = target->base;
2001			(void)memmove(base + target->used, gp.ndata,
2002				      (size_t)gp.length);
2003		}
2004		isc_buffer_add(target, gp.length);
2005		if (target->length - target->used < 2) {
2006			return (ISC_R_NOSPACE);
2007		}
2008		isc_buffer_putuint16(target, go | 0xc000);
2009		if (gp.length != 0) {
2010			dns_compress_add(cctx, name, &gp, offset);
2011			if (comp_offsetp != NULL) {
2012				*comp_offsetp = offset;
2013			}
2014		} else if (comp_offsetp != NULL) {
2015			*comp_offsetp = go;
2016		}
2017	} else {
2018		if (target->length - target->used < name->length) {
2019			return (ISC_R_NOSPACE);
2020		}
2021		if (name->length != 0) {
2022			unsigned char *base = target->base;
2023			(void)memmove(base + target->used, name->ndata,
2024				      (size_t)name->length);
2025		}
2026		isc_buffer_add(target, name->length);
2027		dns_compress_add(cctx, name, name, offset);
2028		if (comp_offsetp != NULL) {
2029			*comp_offsetp = offset;
2030		}
2031	}
2032
2033	return (ISC_R_SUCCESS);
2034}
2035
2036isc_result_t
2037dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
2038		     dns_name_t *name, isc_buffer_t *target) {
2039	unsigned char *ndata, *offsets;
2040	unsigned int nrem, labels, prefix_length, length;
2041	bool copy_prefix = true;
2042	bool copy_suffix = true;
2043	bool absolute = false;
2044	dns_name_t tmp_name;
2045	dns_offsets_t odata;
2046
2047	/*
2048	 * Concatenate 'prefix' and 'suffix'.
2049	 */
2050
2051	REQUIRE(prefix == NULL || VALID_NAME(prefix));
2052	REQUIRE(suffix == NULL || VALID_NAME(suffix));
2053	REQUIRE(name == NULL || VALID_NAME(name));
2054	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2055		(target == NULL && name != NULL &&
2056		 ISC_BUFFER_VALID(name->buffer)));
2057	if (prefix == NULL || prefix->labels == 0) {
2058		copy_prefix = false;
2059	}
2060	if (suffix == NULL || suffix->labels == 0) {
2061		copy_suffix = false;
2062	}
2063	if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2064		absolute = true;
2065		REQUIRE(!copy_suffix);
2066	}
2067	if (name == NULL) {
2068		DNS_NAME_INIT(&tmp_name, odata);
2069		name = &tmp_name;
2070	}
2071	if (target == NULL) {
2072		INSIST(name->buffer != NULL);
2073		target = name->buffer;
2074		isc_buffer_clear(name->buffer);
2075	}
2076
2077	REQUIRE(BINDABLE(name));
2078
2079	/*
2080	 * Set up.
2081	 */
2082	nrem = target->length - target->used;
2083	ndata = (unsigned char *)target->base + target->used;
2084	if (nrem > DNS_NAME_MAXWIRE) {
2085		nrem = DNS_NAME_MAXWIRE;
2086	}
2087	length = 0;
2088	prefix_length = 0;
2089	labels = 0;
2090	if (copy_prefix) {
2091		prefix_length = prefix->length;
2092		length += prefix_length;
2093		labels += prefix->labels;
2094	}
2095	if (copy_suffix) {
2096		length += suffix->length;
2097		labels += suffix->labels;
2098	}
2099	if (length > DNS_NAME_MAXWIRE) {
2100		MAKE_EMPTY(name);
2101		return (DNS_R_NAMETOOLONG);
2102	}
2103	if (length > nrem) {
2104		MAKE_EMPTY(name);
2105		return (ISC_R_NOSPACE);
2106	}
2107
2108	if (copy_suffix) {
2109		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2110			absolute = true;
2111		}
2112		memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2113	}
2114
2115	/*
2116	 * If 'prefix' and 'name' are the same object, and the object has
2117	 * a dedicated buffer, and we're using it, then we don't have to
2118	 * copy anything.
2119	 */
2120	if (copy_prefix && (prefix != name || prefix->buffer != target)) {
2121		memmove(ndata, prefix->ndata, prefix_length);
2122	}
2123
2124	name->ndata = ndata;
2125	name->labels = labels;
2126	name->length = length;
2127	if (absolute) {
2128		name->attributes = DNS_NAMEATTR_ABSOLUTE;
2129	} else {
2130		name->attributes = 0;
2131	}
2132
2133	if (name->labels > 0 && name->offsets != NULL) {
2134		INIT_OFFSETS(name, offsets, odata);
2135		set_offsets(name, offsets, NULL);
2136	}
2137
2138	isc_buffer_add(target, name->length);
2139
2140	return (ISC_R_SUCCESS);
2141}
2142
2143void
2144dns_name_split(const dns_name_t *name, unsigned int suffixlabels,
2145	       dns_name_t *prefix, dns_name_t *suffix)
2146
2147{
2148	unsigned int splitlabel;
2149
2150	REQUIRE(VALID_NAME(name));
2151	REQUIRE(suffixlabels > 0);
2152	REQUIRE(suffixlabels <= name->labels);
2153	REQUIRE(prefix != NULL || suffix != NULL);
2154	REQUIRE(prefix == NULL || (VALID_NAME(prefix) && BINDABLE(prefix)));
2155	REQUIRE(suffix == NULL || (VALID_NAME(suffix) && BINDABLE(suffix)));
2156
2157	splitlabel = name->labels - suffixlabels;
2158
2159	if (prefix != NULL) {
2160		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2161	}
2162
2163	if (suffix != NULL) {
2164		dns_name_getlabelsequence(name, splitlabel, suffixlabels,
2165					  suffix);
2166	}
2167
2168	return;
2169}
2170
2171void
2172dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
2173	/*
2174	 * Make 'target' a dynamically allocated copy of 'source'.
2175	 */
2176
2177	REQUIRE(VALID_NAME(source));
2178	REQUIRE(source->length > 0);
2179	REQUIRE(VALID_NAME(target));
2180	REQUIRE(BINDABLE(target));
2181
2182	/*
2183	 * Make 'target' empty in case of failure.
2184	 */
2185	MAKE_EMPTY(target);
2186
2187	target->ndata = isc_mem_get(mctx, source->length);
2188
2189	memmove(target->ndata, source->ndata, source->length);
2190
2191	target->length = source->length;
2192	target->labels = source->labels;
2193	target->attributes = DNS_NAMEATTR_DYNAMIC;
2194	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2195		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2196	}
2197	if (target->offsets != NULL) {
2198		if (source->offsets != NULL) {
2199			memmove(target->offsets, source->offsets,
2200				source->labels);
2201		} else {
2202			set_offsets(target, target->offsets, NULL);
2203		}
2204	}
2205}
2206
2207isc_result_t
2208dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx,
2209			dns_name_t *target) {
2210	/*
2211	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2212	 * 'target' will also have a dynamically allocated offsets table.
2213	 */
2214
2215	REQUIRE(VALID_NAME(source));
2216	REQUIRE(source->length > 0);
2217	REQUIRE(VALID_NAME(target));
2218	REQUIRE(BINDABLE(target));
2219	REQUIRE(target->offsets == NULL);
2220
2221	/*
2222	 * Make 'target' empty in case of failure.
2223	 */
2224	MAKE_EMPTY(target);
2225
2226	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2227
2228	memmove(target->ndata, source->ndata, source->length);
2229
2230	target->length = source->length;
2231	target->labels = source->labels;
2232	target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2233			     DNS_NAMEATTR_READONLY;
2234	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2235		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2236	}
2237	target->offsets = target->ndata + source->length;
2238	if (source->offsets != NULL) {
2239		memmove(target->offsets, source->offsets, source->labels);
2240	} else {
2241		set_offsets(target, target->offsets, NULL);
2242	}
2243
2244	return (ISC_R_SUCCESS);
2245}
2246
2247void
2248dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2249	size_t size;
2250
2251	/*
2252	 * Free 'name'.
2253	 */
2254
2255	REQUIRE(VALID_NAME(name));
2256	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2257
2258	size = name->length;
2259	if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) {
2260		size += name->labels;
2261	}
2262	isc_mem_put(mctx, name->ndata, size);
2263	dns_name_invalidate(name);
2264}
2265
2266isc_result_t
2267dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2268	dns_name_t downname;
2269	unsigned char data[256];
2270	isc_buffer_t buffer;
2271	isc_result_t result;
2272	isc_region_t r;
2273
2274	/*
2275	 * Send 'name' in DNSSEC canonical form to 'digest'.
2276	 */
2277
2278	REQUIRE(VALID_NAME(name));
2279	REQUIRE(digest != NULL);
2280
2281	DNS_NAME_INIT(&downname, NULL);
2282
2283	isc_buffer_init(&buffer, data, sizeof(data));
2284
2285	result = dns_name_downcase(name, &downname, &buffer);
2286	if (result != ISC_R_SUCCESS) {
2287		return (result);
2288	}
2289
2290	isc_buffer_usedregion(&buffer, &r);
2291
2292	return ((digest)(arg, &r));
2293}
2294
2295bool
2296dns_name_dynamic(const dns_name_t *name) {
2297	REQUIRE(VALID_NAME(name));
2298
2299	/*
2300	 * Returns whether there is dynamic memory associated with this name.
2301	 */
2302
2303	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? true : false);
2304}
2305
2306isc_result_t
2307dns_name_print(const dns_name_t *name, FILE *stream) {
2308	isc_result_t result;
2309	isc_buffer_t b;
2310	isc_region_t r;
2311	char t[1024];
2312
2313	/*
2314	 * Print 'name' on 'stream'.
2315	 */
2316
2317	REQUIRE(VALID_NAME(name));
2318
2319	isc_buffer_init(&b, t, sizeof(t));
2320	result = dns_name_totext(name, false, &b);
2321	if (result != ISC_R_SUCCESS) {
2322		return (result);
2323	}
2324	isc_buffer_usedregion(&b, &r);
2325	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2326
2327	return (ISC_R_SUCCESS);
2328}
2329
2330isc_result_t
2331dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
2332	/*
2333	 * If we already have been here set / clear as appropriate.
2334	 */
2335	if (totext_filter_proc != NULL && proc != NULL) {
2336		if (totext_filter_proc == proc) {
2337			return (ISC_R_SUCCESS);
2338		}
2339	}
2340	if (proc == NULL && totext_filter_proc != NULL) {
2341		totext_filter_proc = NULL;
2342		return (ISC_R_SUCCESS);
2343	}
2344
2345	totext_filter_proc = proc;
2346
2347	return (ISC_R_SUCCESS);
2348}
2349
2350void
2351dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
2352	isc_result_t result;
2353	isc_buffer_t buf;
2354
2355	REQUIRE(size > 0);
2356
2357	/*
2358	 * Leave room for null termination after buffer.
2359	 */
2360	isc_buffer_init(&buf, cp, size - 1);
2361	result = dns_name_totext(name, true, &buf);
2362	if (result == ISC_R_SUCCESS) {
2363		isc_buffer_putuint8(&buf, (uint8_t)'\0');
2364	} else {
2365		snprintf(cp, size, "<unknown>");
2366	}
2367}
2368
2369/*
2370 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2371 * memory.
2372 */
2373isc_result_t
2374dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
2375	isc_result_t result;
2376	isc_buffer_t buf;
2377	isc_region_t reg;
2378	char *p, txt[DNS_NAME_FORMATSIZE];
2379
2380	REQUIRE(VALID_NAME(name));
2381	REQUIRE(target != NULL && *target == NULL);
2382
2383	isc_buffer_init(&buf, txt, sizeof(txt));
2384	result = dns_name_totext(name, false, &buf);
2385	if (result != ISC_R_SUCCESS) {
2386		return (result);
2387	}
2388
2389	isc_buffer_usedregion(&buf, &reg);
2390	p = isc_mem_allocate(mctx, reg.length + 1);
2391	memmove(p, (char *)reg.base, (int)reg.length);
2392	p[reg.length] = '\0';
2393
2394	*target = p;
2395	return (ISC_R_SUCCESS);
2396}
2397
2398/*
2399 * dns_name_fromstring() -- convert directly from a string to a name,
2400 * allocating memory as needed
2401 */
2402isc_result_t
2403dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2404		    isc_mem_t *mctx) {
2405	return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2406}
2407
2408isc_result_t
2409dns_name_fromstring2(dns_name_t *target, const char *src,
2410		     const dns_name_t *origin, unsigned int options,
2411		     isc_mem_t *mctx) {
2412	isc_result_t result;
2413	isc_buffer_t buf;
2414	dns_fixedname_t fn;
2415	dns_name_t *name;
2416
2417	REQUIRE(src != NULL);
2418
2419	isc_buffer_constinit(&buf, src, strlen(src));
2420	isc_buffer_add(&buf, strlen(src));
2421	if (BINDABLE(target) && target->buffer != NULL) {
2422		name = target;
2423	} else {
2424		name = dns_fixedname_initname(&fn);
2425	}
2426
2427	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2428	if (result != ISC_R_SUCCESS) {
2429		return (result);
2430	}
2431
2432	if (name != target) {
2433		result = dns_name_dupwithoffsets(name, mctx, target);
2434	}
2435	return (result);
2436}
2437
2438void
2439dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
2440	isc_buffer_t *target = NULL;
2441	unsigned char *ndata = NULL;
2442
2443	REQUIRE(VALID_NAME(source));
2444	REQUIRE(VALID_NAME(dest));
2445	REQUIRE(BINDABLE(dest));
2446
2447	target = dest->buffer;
2448
2449	REQUIRE(target != NULL);
2450	REQUIRE(target->length >= source->length);
2451
2452	isc_buffer_clear(target);
2453
2454	ndata = (unsigned char *)target->base;
2455	dest->ndata = target->base;
2456
2457	if (source->length != 0) {
2458		memmove(ndata, source->ndata, source->length);
2459	}
2460
2461	dest->ndata = ndata;
2462	dest->labels = source->labels;
2463	dest->length = source->length;
2464	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2465		dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2466	} else {
2467		dest->attributes = 0;
2468	}
2469
2470	if (dest->labels > 0 && dest->offsets != NULL) {
2471		if (source->offsets != NULL && source->labels != 0) {
2472			memmove(dest->offsets, source->offsets, source->labels);
2473		} else {
2474			set_offsets(dest, dest->offsets, NULL);
2475		}
2476	}
2477
2478	isc_buffer_add(target, dest->length);
2479}
2480
2481/*
2482 * Service Discovery Prefixes RFC 6763.
2483 */
2484static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
2485static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
2486static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
2487static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
2488static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
2489static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
2490static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
2491static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
2492static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
2493static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
2494
2495static dns_name_t const dns_sd[] = {
2496	DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
2497	DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
2498	DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
2499	DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
2500	DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
2501};
2502
2503bool
2504dns_name_isdnssd(const dns_name_t *name) {
2505	size_t i;
2506	dns_name_t prefix;
2507
2508	if (dns_name_countlabels(name) > 3U) {
2509		dns_name_init(&prefix, NULL);
2510		dns_name_getlabelsequence(name, 0, 3, &prefix);
2511		for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
2512			if (dns_name_equal(&prefix, &dns_sd[i])) {
2513				return (true);
2514			}
2515		}
2516	}
2517
2518	return (false);
2519}
2520
2521static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
2522static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
2523static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
2524
2525static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
2526
2527static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
2528static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
2529static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
2530static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
2531static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
2532static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
2533static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
2534static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
2535static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
2536static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
2537static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
2538static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
2539static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
2540static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
2541static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
2542static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
2543
2544static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
2545
2546static dns_name_t const rfc1918names[] = {
2547	DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
2548	DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
2549	DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
2550	DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
2551	DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
2552	DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
2553	DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
2554	DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
2555	DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
2556	DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
2557	DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
2558	DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
2559	DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
2560	DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
2561	DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
2562	DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
2563	DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
2564	DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
2565};
2566
2567bool
2568dns_name_isrfc1918(const dns_name_t *name) {
2569	size_t i;
2570
2571	for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
2572		if (dns_name_issubdomain(name, &rfc1918names[i])) {
2573			return (true);
2574		}
2575	}
2576	return (false);
2577}
2578
2579static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
2580static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
2581static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
2582
2583static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
2584				       DNS_NAME_INITABSOLUTE(ip6fd,
2585							     ulaoffsets) };
2586
2587bool
2588dns_name_isula(const dns_name_t *name) {
2589	size_t i;
2590
2591	for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
2592		if (dns_name_issubdomain(name, &ulanames[i])) {
2593			return (true);
2594		}
2595	}
2596	return (false);
2597}
2598
2599/*
2600 * Use a simple table as we don't want all the locale stuff
2601 * associated with ishexdigit().
2602 */
2603const char ishex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2604			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2605			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2606			  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2607			  0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2608			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2609			  0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2610			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2611
2612bool
2613dns_name_istat(const dns_name_t *name) {
2614	unsigned char len;
2615	const unsigned char *ndata;
2616
2617	REQUIRE(VALID_NAME(name));
2618
2619	if (name->labels < 1) {
2620		return (false);
2621	}
2622
2623	ndata = name->ndata;
2624	len = ndata[0];
2625	INSIST(len <= name->length);
2626	ndata++;
2627
2628	/*
2629	 * Is there at least one trust anchor reported and is the
2630	 * label length consistent with a trust-anchor-telemetry label.
2631	 */
2632	if ((len < 8) || (len - 3) % 5 != 0) {
2633		return (false);
2634	}
2635
2636	if (ndata[0] != '_' || maptolower[ndata[1]] != 't' ||
2637	    maptolower[ndata[2]] != 'a')
2638	{
2639		return (false);
2640	}
2641	ndata += 3;
2642	len -= 3;
2643
2644	while (len > 0) {
2645		INSIST(len >= 5);
2646		if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] ||
2647		    !ishex[ndata[3]] || !ishex[ndata[4]])
2648		{
2649			return (false);
2650		}
2651		ndata += 5;
2652		len -= 5;
2653	}
2654	return (true);
2655}
2656