xref: /netbsd-src/external/mpl/bind/dist/lib/dns/name.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: name.c,v 1.15 2025/01/26 16:25:23 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/ascii.h>
24 #include <isc/buffer.h>
25 #include <isc/hash.h>
26 #include <isc/hex.h>
27 #include <isc/mem.h>
28 #include <isc/once.h>
29 #include <isc/random.h>
30 #include <isc/result.h>
31 #include <isc/string.h>
32 #include <isc/thread.h>
33 #include <isc/util.h>
34 
35 #include <dns/compress.h>
36 #include <dns/fixedname.h>
37 #include <dns/name.h>
38 
39 typedef enum {
40 	ft_init = 0,
41 	ft_start,
42 	ft_ordinary,
43 	ft_initialescape,
44 	ft_escape,
45 	ft_escdecimal,
46 	ft_at
47 } ft_state;
48 
49 #define INIT_OFFSETS(name, var, default_offsets) \
50 	if ((name)->offsets != NULL)             \
51 		var = (name)->offsets;           \
52 	else                                     \
53 		var = (default_offsets);
54 
55 #define SETUP_OFFSETS(name, var, default_offsets) \
56 	if ((name)->offsets != NULL) {            \
57 		var = (name)->offsets;            \
58 	} else {                                  \
59 		var = (default_offsets);          \
60 		set_offsets(name, var, NULL);     \
61 	}
62 
63 /*%
64  * Note:  If additional attributes are added that should not be set for
65  *	  empty names, MAKE_EMPTY() must be changed so it clears them.
66  */
67 #define MAKE_EMPTY(name)                           \
68 	do {                                       \
69 		name->ndata = NULL;                \
70 		name->length = 0;                  \
71 		name->labels = 0;                  \
72 		name->attributes.absolute = false; \
73 	} while (0);
74 
75 /*%
76  * Note that the name data must be a char array, not a string
77  * literal, to avoid compiler warnings about discarding
78  * the const attribute of a string.
79  */
80 static unsigned char root_ndata[] = { "" };
81 static unsigned char root_offsets[] = { 0 };
82 
83 static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets);
84 const dns_name_t *dns_rootname = &root;
85 
86 static unsigned char wild_ndata[] = { "\001*" };
87 static unsigned char wild_offsets[] = { 0 };
88 
89 static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata,
90 							wild_offsets);
91 
92 const dns_name_t *dns_wildcardname = &wild;
93 
94 /*
95  * dns_name_t to text post-conversion procedure.
96  */
97 static thread_local dns_name_totextfilter_t *totext_filter_proc = NULL;
98 
99 static void
100 set_offsets(const dns_name_t *name, unsigned char *offsets,
101 	    dns_name_t *set_name);
102 
103 bool
104 dns_name_isvalid(const dns_name_t *name) {
105 	unsigned char *ndata, *offsets;
106 	unsigned int offset, count, length, nlabels;
107 
108 	if (!DNS_NAME_VALID(name)) {
109 		return false;
110 	}
111 
112 	if (name->length > DNS_NAME_MAXWIRE ||
113 	    name->labels > DNS_NAME_MAXLABELS)
114 	{
115 		return false;
116 	}
117 
118 	ndata = name->ndata;
119 	length = name->length;
120 	offsets = name->offsets;
121 	offset = 0;
122 	nlabels = 0;
123 
124 	while (offset != length) {
125 		count = *ndata;
126 		if (count > DNS_NAME_LABELLEN) {
127 			return false;
128 		}
129 		if (offsets != NULL && offsets[nlabels] != offset) {
130 			return false;
131 		}
132 
133 		nlabels++;
134 		offset += count + 1;
135 		ndata += count + 1;
136 		if (offset > length) {
137 			return false;
138 		}
139 
140 		if (count == 0) {
141 			break;
142 		}
143 	}
144 
145 	if (nlabels != name->labels || offset != name->length) {
146 		return false;
147 	}
148 
149 	return true;
150 }
151 
152 bool
153 dns_name_hasbuffer(const dns_name_t *name) {
154 	/*
155 	 * Does 'name' have a dedicated buffer?
156 	 */
157 
158 	REQUIRE(DNS_NAME_VALID(name));
159 
160 	if (name->buffer != NULL) {
161 		return true;
162 	}
163 
164 	return false;
165 }
166 
167 bool
168 dns_name_isabsolute(const dns_name_t *name) {
169 	/*
170 	 * Does 'name' end in the root label?
171 	 */
172 
173 	REQUIRE(DNS_NAME_VALID(name));
174 
175 	return name->attributes.absolute;
176 }
177 
178 #define hyphenchar(c) ((c) == 0x2d)
179 #define asterchar(c)  ((c) == 0x2a)
180 #define alphachar(c) \
181 	(((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a))
182 #define digitchar(c)  ((c) >= 0x30 && (c) <= 0x39)
183 #define borderchar(c) (alphachar(c) || digitchar(c))
184 #define middlechar(c) (borderchar(c) || hyphenchar(c))
185 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
186 
187 bool
188 dns_name_ismailbox(const dns_name_t *name) {
189 	unsigned char *ndata, ch;
190 	unsigned int n;
191 	bool first;
192 
193 	REQUIRE(DNS_NAME_VALID(name));
194 	REQUIRE(name->labels > 0);
195 	REQUIRE(name->attributes.absolute);
196 
197 	/*
198 	 * Root label.
199 	 */
200 	if (name->length == 1) {
201 		return true;
202 	}
203 
204 	ndata = name->ndata;
205 	n = *ndata++;
206 	INSIST(n <= DNS_NAME_LABELLEN);
207 	while (n--) {
208 		ch = *ndata++;
209 		if (!domainchar(ch)) {
210 			return false;
211 		}
212 	}
213 
214 	if (ndata == name->ndata + name->length) {
215 		return false;
216 	}
217 
218 	/*
219 	 * RFC952/RFC1123 hostname.
220 	 */
221 	while (ndata < (name->ndata + name->length)) {
222 		n = *ndata++;
223 		INSIST(n <= DNS_NAME_LABELLEN);
224 		first = true;
225 		while (n--) {
226 			ch = *ndata++;
227 			if (first || n == 0) {
228 				if (!borderchar(ch)) {
229 					return false;
230 				}
231 			} else {
232 				if (!middlechar(ch)) {
233 					return false;
234 				}
235 			}
236 			first = false;
237 		}
238 	}
239 	return true;
240 }
241 
242 bool
243 dns_name_ishostname(const dns_name_t *name, bool wildcard) {
244 	unsigned char *ndata, ch;
245 	unsigned int n;
246 	bool first;
247 
248 	REQUIRE(DNS_NAME_VALID(name));
249 	REQUIRE(name->labels > 0);
250 	REQUIRE(name->attributes.absolute);
251 
252 	/*
253 	 * Root label.
254 	 */
255 	if (name->length == 1) {
256 		return true;
257 	}
258 
259 	/*
260 	 * Skip wildcard if this is a ownername.
261 	 */
262 	ndata = name->ndata;
263 	if (wildcard && ndata[0] == 1 && ndata[1] == '*') {
264 		ndata += 2;
265 	}
266 
267 	/*
268 	 * RFC952/RFC1123 hostname.
269 	 */
270 	while (ndata < (name->ndata + name->length)) {
271 		n = *ndata++;
272 		INSIST(n <= DNS_NAME_LABELLEN);
273 		first = true;
274 		while (n--) {
275 			ch = *ndata++;
276 			if (first || n == 0) {
277 				if (!borderchar(ch)) {
278 					return false;
279 				}
280 			} else {
281 				if (!middlechar(ch)) {
282 					return false;
283 				}
284 			}
285 			first = false;
286 		}
287 	}
288 	return true;
289 }
290 
291 bool
292 dns_name_iswildcard(const dns_name_t *name) {
293 	unsigned char *ndata;
294 
295 	/*
296 	 * Is 'name' a wildcard name?
297 	 */
298 
299 	REQUIRE(DNS_NAME_VALID(name));
300 	REQUIRE(name->labels > 0);
301 
302 	if (name->length >= 2) {
303 		ndata = name->ndata;
304 		if (ndata[0] == 1 && ndata[1] == '*') {
305 			return true;
306 		}
307 	}
308 
309 	return false;
310 }
311 
312 bool
313 dns_name_internalwildcard(const dns_name_t *name) {
314 	unsigned char *ndata;
315 	unsigned int count;
316 	unsigned int label;
317 
318 	/*
319 	 * Does 'name' contain a internal wildcard?
320 	 */
321 
322 	REQUIRE(DNS_NAME_VALID(name));
323 	REQUIRE(name->labels > 0);
324 
325 	/*
326 	 * Skip first label.
327 	 */
328 	ndata = name->ndata;
329 	count = *ndata++;
330 	INSIST(count <= DNS_NAME_LABELLEN);
331 	ndata += count;
332 	label = 1;
333 	/*
334 	 * Check all but the last of the remaining labels.
335 	 */
336 	while (label + 1 < name->labels) {
337 		count = *ndata++;
338 		INSIST(count <= DNS_NAME_LABELLEN);
339 		if (count == 1 && *ndata == '*') {
340 			return true;
341 		}
342 		ndata += count;
343 		label++;
344 	}
345 	return false;
346 }
347 
348 uint32_t
349 dns_name_hash(const dns_name_t *name) {
350 	REQUIRE(DNS_NAME_VALID(name));
351 
352 	return isc_hash32(name->ndata, name->length, false);
353 }
354 
355 dns_namereln_t
356 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
357 		     int *orderp, unsigned int *nlabelsp) {
358 	unsigned int l1, l2, l, count1, count2, count, nlabels;
359 	int cdiff, ldiff, diff;
360 	unsigned char *label1, *label2;
361 	unsigned char *offsets1, *offsets2;
362 	dns_offsets_t odata1, odata2;
363 	dns_namereln_t namereln = dns_namereln_none;
364 
365 	/*
366 	 * Determine the relative ordering under the DNSSEC order relation of
367 	 * 'name1' and 'name2', and also determine the hierarchical
368 	 * relationship of the names.
369 	 *
370 	 * Note: It makes no sense for one of the names to be relative and the
371 	 * other absolute.  If both names are relative, then to be meaningfully
372 	 * compared the caller must ensure that they are both relative to the
373 	 * same domain.
374 	 */
375 
376 	REQUIRE(DNS_NAME_VALID(name1));
377 	REQUIRE(DNS_NAME_VALID(name2));
378 	REQUIRE(orderp != NULL);
379 	REQUIRE(nlabelsp != NULL);
380 	/*
381 	 * Either name1 is absolute and name2 is absolute, or neither is.
382 	 */
383 	REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
384 
385 	if (name1 == name2) {
386 		*orderp = 0;
387 		*nlabelsp = name1->labels;
388 		return dns_namereln_equal;
389 	}
390 
391 	SETUP_OFFSETS(name1, offsets1, odata1);
392 	SETUP_OFFSETS(name2, offsets2, odata2);
393 
394 	nlabels = 0;
395 	l1 = name1->labels;
396 	l2 = name2->labels;
397 	if (l2 > l1) {
398 		l = l1;
399 		ldiff = 0 - (l2 - l1);
400 	} else {
401 		l = l2;
402 		ldiff = l1 - l2;
403 	}
404 
405 	offsets1 += l1;
406 	offsets2 += l2;
407 
408 	while (l-- > 0) {
409 		offsets1--;
410 		offsets2--;
411 		label1 = &name1->ndata[*offsets1];
412 		label2 = &name2->ndata[*offsets2];
413 		count1 = *label1++;
414 		count2 = *label2++;
415 
416 		cdiff = (int)count1 - (int)count2;
417 		if (cdiff < 0) {
418 			count = count1;
419 		} else {
420 			count = count2;
421 		}
422 
423 		diff = isc_ascii_lowercmp(label1, label2, count);
424 		if (diff != 0) {
425 			*orderp = diff;
426 			goto done;
427 		}
428 
429 		if (cdiff != 0) {
430 			*orderp = cdiff;
431 			goto done;
432 		}
433 		nlabels++;
434 	}
435 
436 	*orderp = ldiff;
437 	if (ldiff < 0) {
438 		namereln = dns_namereln_contains;
439 	} else if (ldiff > 0) {
440 		namereln = dns_namereln_subdomain;
441 	} else {
442 		namereln = dns_namereln_equal;
443 	}
444 	*nlabelsp = nlabels;
445 	return namereln;
446 
447 done:
448 	*nlabelsp = nlabels;
449 	if (nlabels > 0) {
450 		namereln = dns_namereln_commonancestor;
451 	}
452 
453 	return namereln;
454 }
455 
456 int
457 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
458 	int order;
459 	unsigned int nlabels;
460 
461 	/*
462 	 * Determine the relative ordering under the DNSSEC order relation of
463 	 * 'name1' and 'name2'.
464 	 *
465 	 * Note: It makes no sense for one of the names to be relative and the
466 	 * other absolute.  If both names are relative, then to be meaningfully
467 	 * compared the caller must ensure that they are both relative to the
468 	 * same domain.
469 	 */
470 
471 	(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
472 
473 	return order;
474 }
475 
476 bool
477 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
478 	unsigned int length;
479 
480 	/*
481 	 * Are 'name1' and 'name2' equal?
482 	 *
483 	 * Note: It makes no sense for one of the names to be relative and the
484 	 * other absolute.  If both names are relative, then to be meaningfully
485 	 * compared the caller must ensure that they are both relative to the
486 	 * same domain.
487 	 */
488 
489 	REQUIRE(DNS_NAME_VALID(name1));
490 	REQUIRE(DNS_NAME_VALID(name2));
491 	/*
492 	 * Either name1 is absolute and name2 is absolute, or neither is.
493 	 */
494 	REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
495 
496 	if (name1 == name2) {
497 		return true;
498 	}
499 
500 	length = name1->length;
501 	if (length != name2->length) {
502 		return false;
503 	}
504 
505 	/* label lengths are < 64 so tolower() does not affect them */
506 	return isc_ascii_lowerequal(name1->ndata, name2->ndata, length);
507 }
508 
509 bool
510 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
511 	/*
512 	 * Are 'name1' and 'name2' equal?
513 	 *
514 	 * Note: It makes no sense for one of the names to be relative and the
515 	 * other absolute.  If both names are relative, then to be meaningfully
516 	 * compared the caller must ensure that they are both relative to the
517 	 * same domain.
518 	 */
519 
520 	REQUIRE(DNS_NAME_VALID(name1));
521 	REQUIRE(DNS_NAME_VALID(name2));
522 	/*
523 	 * Either name1 is absolute and name2 is absolute, or neither is.
524 	 */
525 	REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
526 
527 	if (name1->length != name2->length) {
528 		return false;
529 	}
530 
531 	if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
532 		return false;
533 	}
534 
535 	return true;
536 }
537 
538 int
539 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
540 	/*
541 	 * Compare two absolute names as rdata.
542 	 */
543 
544 	REQUIRE(DNS_NAME_VALID(name1));
545 	REQUIRE(name1->labels > 0);
546 	REQUIRE(name1->attributes.absolute);
547 	REQUIRE(DNS_NAME_VALID(name2));
548 	REQUIRE(name2->labels > 0);
549 	REQUIRE(name2->attributes.absolute);
550 
551 	/* label lengths are < 64 so tolower() does not affect them */
552 	return isc_ascii_lowercmp(name1->ndata, name2->ndata,
553 				  ISC_MIN(name1->length, name2->length));
554 }
555 
556 bool
557 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
558 	int order;
559 	unsigned int nlabels;
560 	dns_namereln_t namereln;
561 
562 	/*
563 	 * Is 'name1' a subdomain of 'name2'?
564 	 *
565 	 * Note: It makes no sense for one of the names to be relative and the
566 	 * other absolute.  If both names are relative, then to be meaningfully
567 	 * compared the caller must ensure that they are both relative to the
568 	 * same domain.
569 	 */
570 
571 	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
572 	if (namereln == dns_namereln_subdomain ||
573 	    namereln == dns_namereln_equal)
574 	{
575 		return true;
576 	}
577 
578 	return false;
579 }
580 
581 bool
582 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
583 	int order;
584 	unsigned int nlabels, labels;
585 	dns_name_t tname;
586 
587 	REQUIRE(DNS_NAME_VALID(name));
588 	REQUIRE(name->labels > 0);
589 	REQUIRE(DNS_NAME_VALID(wname));
590 	labels = wname->labels;
591 	REQUIRE(labels > 0);
592 	REQUIRE(dns_name_iswildcard(wname));
593 
594 	dns_name_init(&tname, NULL);
595 	dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
596 	if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
597 	    dns_namereln_subdomain)
598 	{
599 		return true;
600 	}
601 	return false;
602 }
603 
604 void
605 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
606 	unsigned char *offsets;
607 	dns_offsets_t odata;
608 
609 	/*
610 	 * Make 'label' refer to the 'n'th least significant label of 'name'.
611 	 */
612 
613 	REQUIRE(DNS_NAME_VALID(name));
614 	REQUIRE(name->labels > 0);
615 	REQUIRE(n < name->labels);
616 	REQUIRE(label != NULL);
617 
618 	SETUP_OFFSETS(name, offsets, odata);
619 
620 	label->base = &name->ndata[offsets[n]];
621 	if (n == name->labels - 1) {
622 		label->length = name->length - offsets[n];
623 	} else {
624 		label->length = offsets[n + 1] - offsets[n];
625 	}
626 }
627 
628 void
629 dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
630 			  unsigned int n, dns_name_t *target) {
631 	unsigned char *p, l;
632 	unsigned int firstoffset, endoffset;
633 	unsigned int i;
634 
635 	/*
636 	 * Make 'target' refer to the 'n' labels including and following
637 	 * 'first' in 'source'.
638 	 */
639 
640 	REQUIRE(DNS_NAME_VALID(source));
641 	REQUIRE(DNS_NAME_VALID(target));
642 	REQUIRE(first <= source->labels);
643 	REQUIRE(n <= source->labels - first); /* note first+n could overflow */
644 	REQUIRE(DNS_NAME_BINDABLE(target));
645 
646 	p = source->ndata;
647 	if (first == source->labels) {
648 		firstoffset = source->length;
649 	} else {
650 		for (i = 0; i < first; i++) {
651 			l = *p;
652 			p += l + 1;
653 		}
654 		firstoffset = (unsigned int)(p - source->ndata);
655 	}
656 
657 	if (first + n == source->labels) {
658 		endoffset = source->length;
659 	} else {
660 		for (i = 0; i < n; i++) {
661 			l = *p;
662 			p += l + 1;
663 		}
664 		endoffset = (unsigned int)(p - source->ndata);
665 	}
666 
667 	target->ndata = &source->ndata[firstoffset];
668 	target->length = endoffset - firstoffset;
669 
670 	if (first + n == source->labels && n > 0 && source->attributes.absolute)
671 	{
672 		target->attributes.absolute = true;
673 	} else {
674 		target->attributes.absolute = false;
675 	}
676 
677 	target->labels = n;
678 
679 	/*
680 	 * If source and target are the same, and we're making target
681 	 * a prefix of source, the offsets table is correct already
682 	 * so we don't need to call set_offsets().
683 	 */
684 	if (target->offsets != NULL && (target != source || first != 0)) {
685 		set_offsets(target, target->offsets, NULL);
686 	}
687 }
688 
689 void
690 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
691 	/*
692 	 * Make 'target' refer to the same name as 'source'.
693 	 */
694 
695 	REQUIRE(DNS_NAME_VALID(source));
696 	REQUIRE(DNS_NAME_VALID(target));
697 	REQUIRE(DNS_NAME_BINDABLE(target));
698 
699 	target->ndata = source->ndata;
700 	target->length = source->length;
701 	target->labels = source->labels;
702 	target->attributes = source->attributes;
703 	target->attributes.readonly = false;
704 	target->attributes.dynamic = false;
705 	target->attributes.dynoffsets = false;
706 	if (target->offsets != NULL && source->labels > 0) {
707 		if (source->offsets != NULL) {
708 			memmove(target->offsets, source->offsets,
709 				source->labels);
710 		} else {
711 			set_offsets(target, target->offsets, NULL);
712 		}
713 	}
714 }
715 
716 void
717 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
718 	unsigned char *offsets;
719 	dns_offsets_t odata;
720 	unsigned int len;
721 	isc_region_t r2 = { .base = NULL, .length = 0 };
722 
723 	/*
724 	 * Make 'name' refer to region 'r'.
725 	 */
726 
727 	REQUIRE(DNS_NAME_VALID(name));
728 	REQUIRE(r != NULL);
729 	REQUIRE(DNS_NAME_BINDABLE(name));
730 
731 	INIT_OFFSETS(name, offsets, odata);
732 
733 	name->ndata = r->base;
734 	if (name->buffer != NULL) {
735 		isc_buffer_clear(name->buffer);
736 		isc_buffer_availableregion(name->buffer, &r2);
737 		len = (r->length < r2.length) ? r->length : r2.length;
738 		if (len > DNS_NAME_MAXWIRE) {
739 			len = DNS_NAME_MAXWIRE;
740 		}
741 		name->length = len;
742 	} else {
743 		name->length = (r->length <= DNS_NAME_MAXWIRE)
744 				       ? r->length
745 				       : DNS_NAME_MAXWIRE;
746 	}
747 
748 	if (r->length > 0) {
749 		set_offsets(name, offsets, name);
750 	} else {
751 		name->labels = 0;
752 		name->attributes.absolute = false;
753 	}
754 
755 	if (name->buffer != NULL) {
756 		/*
757 		 * name->length has been updated by set_offsets to the actual
758 		 * length of the name data so we can now copy the actual name
759 		 * data and not anything after it.
760 		 */
761 		if (name->length > 0) {
762 			memmove(r2.base, r->base, name->length);
763 		}
764 		name->ndata = r2.base;
765 		isc_buffer_add(name->buffer, name->length);
766 	}
767 }
768 
769 isc_result_t
770 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
771 		  const dns_name_t *origin, unsigned int options,
772 		  isc_buffer_t *target) {
773 	unsigned char *ndata, *label = NULL;
774 	char *tdata;
775 	char c;
776 	ft_state state;
777 	unsigned int value = 0, count = 0;
778 	unsigned int n1 = 0, n2 = 0;
779 	unsigned int tlen, nrem, nused, digits = 0, labels, tused;
780 	bool done;
781 	unsigned char *offsets;
782 	dns_offsets_t odata;
783 	bool downcase;
784 
785 	/*
786 	 * Convert the textual representation of a DNS name at source
787 	 * into uncompressed wire form stored in target.
788 	 *
789 	 * Notes:
790 	 *	Relative domain names will have 'origin' appended to them
791 	 *	unless 'origin' is NULL, in which case relative domain names
792 	 *	will remain relative.
793 	 */
794 
795 	REQUIRE(DNS_NAME_VALID(name));
796 	REQUIRE(ISC_BUFFER_VALID(source));
797 	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
798 		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
799 
800 	downcase = ((options & DNS_NAME_DOWNCASE) != 0);
801 
802 	if (target == NULL && name->buffer != NULL) {
803 		target = name->buffer;
804 		isc_buffer_clear(target);
805 	}
806 
807 	REQUIRE(DNS_NAME_BINDABLE(name));
808 
809 	INIT_OFFSETS(name, offsets, odata);
810 	offsets[0] = 0;
811 
812 	/*
813 	 * Make 'name' empty in case of failure.
814 	 */
815 	MAKE_EMPTY(name);
816 
817 	/*
818 	 * Set up the state machine.
819 	 */
820 	tdata = (char *)source->base + source->current;
821 	tlen = isc_buffer_remaininglength(source);
822 	tused = 0;
823 	ndata = isc_buffer_used(target);
824 	nrem = isc_buffer_availablelength(target);
825 	if (nrem > DNS_NAME_MAXWIRE) {
826 		nrem = DNS_NAME_MAXWIRE;
827 	}
828 	nused = 0;
829 	labels = 0;
830 	done = false;
831 	state = ft_init;
832 
833 	while (nrem > 0 && tlen > 0 && !done) {
834 		c = *tdata++;
835 		tlen--;
836 		tused++;
837 
838 		switch (state) {
839 		case ft_init:
840 			/*
841 			 * Is this the root name?
842 			 */
843 			if (c == '.') {
844 				if (tlen != 0) {
845 					return DNS_R_EMPTYLABEL;
846 				}
847 				labels++;
848 				*ndata++ = 0;
849 				nrem--;
850 				nused++;
851 				done = true;
852 				break;
853 			}
854 			if (c == '@' && tlen == 0) {
855 				state = ft_at;
856 				break;
857 			}
858 
859 			FALLTHROUGH;
860 		case ft_start:
861 			label = ndata;
862 			ndata++;
863 			nrem--;
864 			nused++;
865 			count = 0;
866 			if (c == '\\') {
867 				state = ft_initialescape;
868 				break;
869 			}
870 			state = ft_ordinary;
871 			if (nrem == 0) {
872 				return ISC_R_NOSPACE;
873 			}
874 			FALLTHROUGH;
875 		case ft_ordinary:
876 			if (c == '.') {
877 				if (count == 0) {
878 					return DNS_R_EMPTYLABEL;
879 				}
880 				*label = count;
881 				labels++;
882 				INSIST(labels < DNS_NAME_MAXLABELS);
883 				offsets[labels] = nused;
884 				if (tlen == 0) {
885 					labels++;
886 					*ndata++ = 0;
887 					nrem--;
888 					nused++;
889 					done = true;
890 				}
891 				state = ft_start;
892 			} else if (c == '\\') {
893 				state = ft_escape;
894 			} else {
895 				if (count >= DNS_NAME_LABELLEN) {
896 					return DNS_R_LABELTOOLONG;
897 				}
898 				count++;
899 				if (downcase) {
900 					c = isc_ascii_tolower(c);
901 				}
902 				*ndata++ = c;
903 				nrem--;
904 				nused++;
905 			}
906 			break;
907 		case ft_initialescape:
908 			if (c == '[') {
909 				/*
910 				 * This looks like a bitstring label, which
911 				 * was deprecated.  Intentionally drop it.
912 				 */
913 				return DNS_R_BADLABELTYPE;
914 			}
915 			state = ft_escape;
916 			POST(state);
917 			FALLTHROUGH;
918 		case ft_escape:
919 			if (!isdigit((unsigned char)c)) {
920 				if (count >= DNS_NAME_LABELLEN) {
921 					return DNS_R_LABELTOOLONG;
922 				}
923 				count++;
924 				if (downcase) {
925 					c = isc_ascii_tolower(c);
926 				}
927 				*ndata++ = c;
928 				nrem--;
929 				nused++;
930 				state = ft_ordinary;
931 				break;
932 			}
933 			digits = 0;
934 			value = 0;
935 			state = ft_escdecimal;
936 			FALLTHROUGH;
937 		case ft_escdecimal:
938 			if (!isdigit((unsigned char)c)) {
939 				return DNS_R_BADESCAPE;
940 			}
941 			value = 10 * value + c - '0';
942 			digits++;
943 			if (digits == 3) {
944 				if (value > 255) {
945 					return DNS_R_BADESCAPE;
946 				}
947 				if (count >= DNS_NAME_LABELLEN) {
948 					return DNS_R_LABELTOOLONG;
949 				}
950 				count++;
951 				if (downcase) {
952 					value = isc_ascii_tolower(value);
953 				}
954 				*ndata++ = value;
955 				nrem--;
956 				nused++;
957 				state = ft_ordinary;
958 			}
959 			break;
960 		default:
961 			FATAL_ERROR("Unexpected state %d", state);
962 			/* Does not return. */
963 		}
964 	}
965 
966 	if (!done) {
967 		if (nrem == 0) {
968 			return ISC_R_NOSPACE;
969 		}
970 		INSIST(tlen == 0);
971 		if (state != ft_ordinary && state != ft_at) {
972 			return ISC_R_UNEXPECTEDEND;
973 		}
974 		if (state == ft_ordinary) {
975 			INSIST(count != 0);
976 			INSIST(label != NULL);
977 			*label = count;
978 			labels++;
979 			INSIST(labels < DNS_NAME_MAXLABELS);
980 			offsets[labels] = nused;
981 		}
982 		if (origin != NULL) {
983 			if (nrem < origin->length) {
984 				return ISC_R_NOSPACE;
985 			}
986 			label = origin->ndata;
987 			n1 = origin->length;
988 			nrem -= n1;
989 			POST(nrem);
990 			while (n1 > 0) {
991 				n2 = *label++;
992 				INSIST(n2 <= DNS_NAME_LABELLEN);
993 				*ndata++ = n2;
994 				n1 -= n2 + 1;
995 				nused += n2 + 1;
996 				while (n2 > 0) {
997 					c = *label++;
998 					if (downcase) {
999 						c = isc_ascii_tolower(c);
1000 					}
1001 					*ndata++ = c;
1002 					n2--;
1003 				}
1004 				labels++;
1005 				if (n1 > 0) {
1006 					INSIST(labels < DNS_NAME_MAXLABELS);
1007 					offsets[labels] = nused;
1008 				}
1009 			}
1010 			if (origin->attributes.absolute) {
1011 				name->attributes.absolute = true;
1012 			}
1013 		}
1014 	} else {
1015 		name->attributes.absolute = true;
1016 	}
1017 
1018 	name->ndata = (unsigned char *)target->base + target->used;
1019 	name->labels = labels;
1020 	name->length = nused;
1021 
1022 	isc_buffer_forward(source, tused);
1023 	isc_buffer_add(target, name->length);
1024 
1025 	return ISC_R_SUCCESS;
1026 }
1027 
1028 isc_result_t
1029 dns_name_totext(const dns_name_t *name, unsigned int options,
1030 		isc_buffer_t *target) {
1031 	unsigned char *ndata;
1032 	char *tdata;
1033 	unsigned int nlen, tlen;
1034 	unsigned char c;
1035 	unsigned int trem, count;
1036 	unsigned int labels;
1037 	bool saw_root = false;
1038 	unsigned int oused;
1039 	bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
1040 
1041 	/*
1042 	 * This function assumes the name is in proper uncompressed
1043 	 * wire format.
1044 	 */
1045 	REQUIRE(DNS_NAME_VALID(name));
1046 	REQUIRE(ISC_BUFFER_VALID(target));
1047 
1048 	oused = target->used;
1049 
1050 	ndata = name->ndata;
1051 	nlen = name->length;
1052 	labels = name->labels;
1053 	tdata = isc_buffer_used(target);
1054 	tlen = isc_buffer_availablelength(target);
1055 
1056 	trem = tlen;
1057 
1058 	if (labels == 0 && nlen == 0) {
1059 		/*
1060 		 * Special handling for an empty name.
1061 		 */
1062 		if (trem == 0) {
1063 			return ISC_R_NOSPACE;
1064 		}
1065 
1066 		/*
1067 		 * The names of these booleans are misleading in this case.
1068 		 * This empty name is not necessarily from the root node of
1069 		 * the DNS root zone, nor is a final dot going to be included.
1070 		 * They need to be set this way, though, to keep the "@"
1071 		 * from being trounced.
1072 		 */
1073 		saw_root = true;
1074 		omit_final_dot = false;
1075 		*tdata++ = '@';
1076 		trem--;
1077 
1078 		/*
1079 		 * Skip the while() loop.
1080 		 */
1081 		nlen = 0;
1082 	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1083 		/*
1084 		 * Special handling for the root label.
1085 		 */
1086 		if (trem == 0) {
1087 			return ISC_R_NOSPACE;
1088 		}
1089 
1090 		saw_root = true;
1091 		omit_final_dot = false;
1092 		*tdata++ = '.';
1093 		trem--;
1094 
1095 		/*
1096 		 * Skip the while() loop.
1097 		 */
1098 		nlen = 0;
1099 	}
1100 
1101 	while (labels > 0 && nlen > 0 && trem > 0) {
1102 		labels--;
1103 		count = *ndata++;
1104 		nlen--;
1105 		if (count == 0) {
1106 			saw_root = true;
1107 			break;
1108 		}
1109 		if (count <= DNS_NAME_LABELLEN) {
1110 			INSIST(nlen >= count);
1111 			while (count > 0) {
1112 				c = *ndata;
1113 				switch (c) {
1114 				/* Special modifiers in zone files. */
1115 				case 0x40: /* '@' */
1116 				case 0x24: /* '$' */
1117 					if ((options & DNS_NAME_PRINCIPAL) != 0)
1118 					{
1119 						goto no_escape;
1120 					}
1121 					FALLTHROUGH;
1122 				case 0x22: /* '"' */
1123 				case 0x28: /* '(' */
1124 				case 0x29: /* ')' */
1125 				case 0x2E: /* '.' */
1126 				case 0x3B: /* ';' */
1127 				case 0x5C: /* '\\' */
1128 					if (trem < 2) {
1129 						return ISC_R_NOSPACE;
1130 					}
1131 					*tdata++ = '\\';
1132 					*tdata++ = c;
1133 					ndata++;
1134 					trem -= 2;
1135 					nlen--;
1136 					break;
1137 				no_escape:
1138 				default:
1139 					if (c > 0x20 && c < 0x7f) {
1140 						if (trem == 0) {
1141 							return ISC_R_NOSPACE;
1142 						}
1143 						*tdata++ = c;
1144 						ndata++;
1145 						trem--;
1146 						nlen--;
1147 					} else {
1148 						if (trem < 4) {
1149 							return ISC_R_NOSPACE;
1150 						}
1151 						*tdata++ = 0x5c;
1152 						*tdata++ = 0x30 +
1153 							   ((c / 100) % 10);
1154 						*tdata++ = 0x30 +
1155 							   ((c / 10) % 10);
1156 						*tdata++ = 0x30 + (c % 10);
1157 						trem -= 4;
1158 						ndata++;
1159 						nlen--;
1160 					}
1161 				}
1162 				count--;
1163 			}
1164 		} else {
1165 			FATAL_ERROR("Unexpected label type %02x", count);
1166 			UNREACHABLE();
1167 		}
1168 
1169 		/*
1170 		 * The following assumes names are absolute.  If not, we
1171 		 * fix things up later.  Note that this means that in some
1172 		 * cases one more byte of text buffer is required than is
1173 		 * needed in the final output.
1174 		 */
1175 		if (trem == 0) {
1176 			return ISC_R_NOSPACE;
1177 		}
1178 		*tdata++ = '.';
1179 		trem--;
1180 	}
1181 
1182 	if (nlen != 0 && trem == 0) {
1183 		return ISC_R_NOSPACE;
1184 	}
1185 
1186 	if (!saw_root || omit_final_dot) {
1187 		trem++;
1188 		tdata--;
1189 	}
1190 	if (trem > 0) {
1191 		*tdata = 0;
1192 	}
1193 	isc_buffer_add(target, tlen - trem);
1194 
1195 	if (totext_filter_proc != NULL) {
1196 		return (totext_filter_proc)(target, oused);
1197 	}
1198 
1199 	return ISC_R_SUCCESS;
1200 }
1201 
1202 isc_result_t
1203 dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot,
1204 			isc_buffer_t *target) {
1205 	unsigned char *ndata;
1206 	char *tdata;
1207 	unsigned int nlen, tlen;
1208 	unsigned char c;
1209 	unsigned int trem, count;
1210 	unsigned int labels;
1211 
1212 	/*
1213 	 * This function assumes the name is in proper uncompressed
1214 	 * wire format.
1215 	 */
1216 	REQUIRE(DNS_NAME_VALID(name));
1217 	REQUIRE(name->attributes.absolute);
1218 	REQUIRE(ISC_BUFFER_VALID(target));
1219 
1220 	ndata = name->ndata;
1221 	nlen = name->length;
1222 	labels = name->labels;
1223 	tdata = isc_buffer_used(target);
1224 	tlen = isc_buffer_availablelength(target);
1225 
1226 	trem = tlen;
1227 
1228 	if (nlen == 1 && labels == 1 && *ndata == '\0') {
1229 		/*
1230 		 * Special handling for the root label.
1231 		 */
1232 		if (trem == 0) {
1233 			return ISC_R_NOSPACE;
1234 		}
1235 
1236 		omit_final_dot = false;
1237 		*tdata++ = '.';
1238 		trem--;
1239 
1240 		/*
1241 		 * Skip the while() loop.
1242 		 */
1243 		nlen = 0;
1244 	}
1245 
1246 	while (labels > 0 && nlen > 0 && trem > 0) {
1247 		labels--;
1248 		count = *ndata++;
1249 		nlen--;
1250 		if (count == 0) {
1251 			break;
1252 		}
1253 		if (count <= DNS_NAME_LABELLEN) {
1254 			INSIST(nlen >= count);
1255 			while (count > 0) {
1256 				c = *ndata;
1257 				if ((c >= 0x30 && c <= 0x39) || /* digit */
1258 				    (c >= 0x41 && c <= 0x5A) || /* uppercase */
1259 				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
1260 				    c == 0x2D ||		/* hyphen */
1261 				    c == 0x5F)			/* underscore */
1262 				{
1263 					if (trem == 0) {
1264 						return ISC_R_NOSPACE;
1265 					}
1266 					/* downcase */
1267 					if (c >= 0x41 && c <= 0x5A) {
1268 						c += 0x20;
1269 					}
1270 					*tdata++ = c;
1271 					ndata++;
1272 					trem--;
1273 					nlen--;
1274 				} else {
1275 					if (trem < 4) {
1276 						return ISC_R_NOSPACE;
1277 					}
1278 					snprintf(tdata, trem, "%%%02X", c);
1279 					tdata += 3;
1280 					trem -= 3;
1281 					ndata++;
1282 					nlen--;
1283 				}
1284 				count--;
1285 			}
1286 		} else {
1287 			FATAL_ERROR("Unexpected label type %02x", count);
1288 			UNREACHABLE();
1289 		}
1290 
1291 		/*
1292 		 * The following assumes names are absolute.  If not, we
1293 		 * fix things up later.  Note that this means that in some
1294 		 * cases one more byte of text buffer is required than is
1295 		 * needed in the final output.
1296 		 */
1297 		if (trem == 0) {
1298 			return ISC_R_NOSPACE;
1299 		}
1300 		*tdata++ = '.';
1301 		trem--;
1302 	}
1303 
1304 	if (nlen != 0 && trem == 0) {
1305 		return ISC_R_NOSPACE;
1306 	}
1307 
1308 	if (omit_final_dot) {
1309 		trem++;
1310 	}
1311 
1312 	isc_buffer_add(target, tlen - trem);
1313 
1314 	return ISC_R_SUCCESS;
1315 }
1316 
1317 isc_result_t
1318 dns_name_downcase(const dns_name_t *source, dns_name_t *name,
1319 		  isc_buffer_t *target) {
1320 	unsigned char *ndata;
1321 	isc_buffer_t buffer;
1322 
1323 	/*
1324 	 * Downcase 'source'.
1325 	 */
1326 
1327 	REQUIRE(DNS_NAME_VALID(source));
1328 	REQUIRE(DNS_NAME_VALID(name));
1329 	if (source == name) {
1330 		REQUIRE(!name->attributes.readonly);
1331 		isc_buffer_init(&buffer, source->ndata, source->length);
1332 		target = &buffer;
1333 		ndata = source->ndata;
1334 	} else {
1335 		REQUIRE(DNS_NAME_BINDABLE(name));
1336 		REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1337 			(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1338 		if (target == NULL) {
1339 			target = name->buffer;
1340 			isc_buffer_clear(name->buffer);
1341 		}
1342 		ndata = (unsigned char *)target->base + target->used;
1343 		name->ndata = ndata;
1344 	}
1345 
1346 	if (source->length > (target->length - target->used)) {
1347 		MAKE_EMPTY(name);
1348 		return ISC_R_NOSPACE;
1349 	}
1350 
1351 	/* label lengths are < 64 so tolower() does not affect them */
1352 	isc_ascii_lowercopy(ndata, source->ndata, source->length);
1353 
1354 	if (source != name) {
1355 		name->labels = source->labels;
1356 		name->length = source->length;
1357 		name->attributes = (struct dns_name_attrs){
1358 			.absolute = source->attributes.absolute
1359 		};
1360 		if (name->labels > 0 && name->offsets != NULL) {
1361 			set_offsets(name, name->offsets, NULL);
1362 		}
1363 	}
1364 
1365 	isc_buffer_add(target, name->length);
1366 
1367 	return ISC_R_SUCCESS;
1368 }
1369 
1370 static void
1371 set_offsets(const dns_name_t *name, unsigned char *offsets,
1372 	    dns_name_t *set_name) {
1373 	unsigned int offset, count, length, nlabels;
1374 	unsigned char *ndata;
1375 	bool absolute;
1376 
1377 	ndata = name->ndata;
1378 	length = name->length;
1379 	offset = 0;
1380 	nlabels = 0;
1381 	absolute = false;
1382 	while (offset != length) {
1383 		INSIST(nlabels < DNS_NAME_MAXLABELS);
1384 		offsets[nlabels++] = offset;
1385 		count = *ndata;
1386 		INSIST(count <= DNS_NAME_LABELLEN);
1387 		offset += count + 1;
1388 		ndata += count + 1;
1389 		INSIST(offset <= length);
1390 		if (count == 0) {
1391 			absolute = true;
1392 			break;
1393 		}
1394 	}
1395 	if (set_name != NULL) {
1396 		INSIST(set_name == name);
1397 
1398 		set_name->labels = nlabels;
1399 		set_name->length = offset;
1400 		set_name->attributes.absolute = absolute;
1401 	}
1402 	INSIST(nlabels == name->labels);
1403 	INSIST(offset == name->length);
1404 }
1405 
1406 isc_result_t
1407 dns_name_fromwire(dns_name_t *const name, isc_buffer_t *const source,
1408 		  const dns_decompress_t dctx, isc_buffer_t *target) {
1409 	/*
1410 	 * Copy the name at source into target, decompressing it.
1411 	 *
1412 	 *	*** WARNING ***
1413 	 *
1414 	 * dns_name_fromwire() deals with raw network data. An error in this
1415 	 * routine could result in the failure or hijacking of the server.
1416 	 *
1417 	 * The description of name compression in RFC 1035 section 4.1.4 is
1418 	 * subtle wrt certain edge cases. The first important sentence is:
1419 	 *
1420 	 * > In this scheme, an entire domain name or a list of labels at the
1421 	 * > end of a domain name is replaced with a pointer to a prior
1422 	 * > occurance of the same name.
1423 	 *
1424 	 * The key word is "prior". This says that compression pointers must
1425 	 * point strictly earlier in the message (before our "marker" variable),
1426 	 * which is enough to prevent DoS attacks due to compression loops.
1427 	 *
1428 	 * The next important sentence is:
1429 	 *
1430 	 * > If a domain name is contained in a part of the message subject to a
1431 	 * > length field (such as the RDATA section of an RR), and compression
1432 	 * > is used, the length of the compressed name is used in the length
1433 	 * > calculation, rather than the length of the expanded name.
1434 	 *
1435 	 * When decompressing, this means that the amount of the source buffer
1436 	 * that we consumed (which is checked wrt the container's length field)
1437 	 * is the length of the compressed name. A compressed name is defined as
1438 	 * a sequence of labels ending with the root label or a compression
1439 	 * pointer, that is, the segment of the name that dns_name_fromwire()
1440 	 * examines first.
1441 	 *
1442 	 * This matters when handling names that play dirty tricks, like:
1443 	 *
1444 	 *	+---+---+---+---+---+---+
1445 	 *	| 4 | 1 |'a'|192| 0 | 0 |
1446 	 *	+---+---+---+---+---+---+
1447 	 *
1448 	 * We start at octet 1. There is an ordinary single character label "a",
1449 	 * followed by a compression pointer that refers back to octet zero.
1450 	 * Here there is a label of length 4, which weirdly re-uses the octets
1451 	 * we already examined as the data for the label. It is followed by the
1452 	 * root label,
1453 	 *
1454 	 * The specification says that the compressed name ends after the first
1455 	 * zero octet (after the compression pointer) not the second zero octet,
1456 	 * even though the second octet is later in the message. This shows the
1457 	 * correct way to set our "consumed" variable.
1458 	 */
1459 
1460 	REQUIRE(DNS_NAME_VALID(name));
1461 	REQUIRE(DNS_NAME_BINDABLE(name));
1462 	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1463 		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
1464 
1465 	if (target == NULL && name->buffer != NULL) {
1466 		target = name->buffer;
1467 		isc_buffer_clear(target);
1468 	}
1469 
1470 	uint8_t *const name_buf = isc_buffer_used(target);
1471 	const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
1472 					  isc_buffer_availablelength(target));
1473 	uint32_t name_len = 0;
1474 	MAKE_EMPTY(name); /* in case of failure */
1475 
1476 	dns_offsets_t odata;
1477 	uint8_t *offsets = NULL;
1478 	uint32_t labels = 0;
1479 	INIT_OFFSETS(name, offsets, odata);
1480 
1481 	/*
1482 	 * After chasing a compression pointer, these variables refer to the
1483 	 * source buffer as follows:
1484 	 *
1485 	 * sb --- mr --- cr --- st --- cd --- sm
1486 	 *
1487 	 * sb = source_buf (const)
1488 	 * mr = marker
1489 	 * cr = cursor
1490 	 * st = start (const)
1491 	 * cd = consumed
1492 	 * sm = source_max (const)
1493 	 *
1494 	 * The marker hops backwards for each pointer.
1495 	 * The cursor steps forwards for each label.
1496 	 * The amount of the source we consumed is set once.
1497 	 */
1498 	const uint8_t *const source_buf = isc_buffer_base(source);
1499 	const uint8_t *const source_max = isc_buffer_used(source);
1500 	const uint8_t *const start = isc_buffer_current(source);
1501 	const uint8_t *marker = start;
1502 	const uint8_t *cursor = start;
1503 	const uint8_t *consumed = NULL;
1504 
1505 	/*
1506 	 * One iteration per label.
1507 	 */
1508 	while (cursor < source_max) {
1509 		const uint8_t label_len = *cursor++;
1510 		if (label_len <= DNS_NAME_LABELLEN) {
1511 			/*
1512 			 * Normal label: record its offset, and check bounds on
1513 			 * the name length, which also ensures we don't overrun
1514 			 * the offsets array. Don't touch any source bytes yet!
1515 			 * The source bounds check will happen when we loop.
1516 			 */
1517 			offsets[labels++] = name_len;
1518 			/* and then a step to the ri-i-i-i-i-ight */
1519 			cursor += label_len;
1520 			name_len += label_len + 1;
1521 			if (name_len > name_max) {
1522 				return name_max == DNS_NAME_MAXWIRE
1523 					       ? DNS_R_NAMETOOLONG
1524 					       : ISC_R_NOSPACE;
1525 			} else if (label_len == 0) {
1526 				goto root_label;
1527 			}
1528 		} else if (label_len < 192) {
1529 			return DNS_R_BADLABELTYPE;
1530 		} else if (!dns_decompress_getpermitted(dctx)) {
1531 			return DNS_R_DISALLOWED;
1532 		} else if (cursor < source_max) {
1533 			/*
1534 			 * Compression pointer. Ensure it does not loop.
1535 			 *
1536 			 * Copy multiple labels in one go, to make the most of
1537 			 * memmove() performance. Start at the marker and finish
1538 			 * just before the pointer's hi+lo bytes, before the
1539 			 * cursor. Bounds were already checked.
1540 			 */
1541 			const uint32_t hi = label_len & 0x3F;
1542 			const uint32_t lo = *cursor++;
1543 			const uint8_t *pointer = source_buf + (256 * hi + lo);
1544 			if (pointer >= marker) {
1545 				return DNS_R_BADPOINTER;
1546 			}
1547 			const uint32_t copy_len = (cursor - 2) - marker;
1548 			uint8_t *const dest = name_buf + name_len - copy_len;
1549 			memmove(dest, marker, copy_len);
1550 			consumed = consumed != NULL ? consumed : cursor;
1551 			/* it's just a jump to the left */
1552 			cursor = marker = pointer;
1553 		}
1554 	}
1555 	return ISC_R_UNEXPECTEDEND;
1556 root_label:;
1557 	/*
1558 	 * Copy labels almost like we do for compression pointers,
1559 	 * from the marker up to and including the root label.
1560 	 */
1561 	const uint32_t copy_len = cursor - marker;
1562 	memmove(name_buf + name_len - copy_len, marker, copy_len);
1563 	consumed = consumed != NULL ? consumed : cursor;
1564 	isc_buffer_forward(source, consumed - start);
1565 
1566 	name->attributes.absolute = true;
1567 	name->ndata = name_buf;
1568 	name->labels = labels;
1569 	name->length = name_len;
1570 	isc_buffer_add(target, name_len);
1571 
1572 	return ISC_R_SUCCESS;
1573 }
1574 
1575 isc_result_t
1576 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1577 		isc_buffer_t *target, uint16_t *name_coff) {
1578 	bool compress;
1579 	dns_offsets_t clo;
1580 	dns_name_t clname;
1581 	unsigned int here;
1582 	unsigned int prefix_length;
1583 	unsigned int suffix_coff;
1584 
1585 	/*
1586 	 * Convert 'name' into wire format, compressing it as specified by the
1587 	 * compression context 'cctx', and storing the result in 'target'.
1588 	 */
1589 
1590 	REQUIRE(DNS_NAME_VALID(name));
1591 	REQUIRE(cctx != NULL);
1592 	REQUIRE(ISC_BUFFER_VALID(target));
1593 
1594 	compress = !name->attributes.nocompress &&
1595 		   dns_compress_getpermitted(cctx);
1596 
1597 	/*
1598 	 * Write a compression pointer directly if the caller passed us
1599 	 * a pointer to this name's offset that we saved previously.
1600 	 */
1601 	if (compress && name_coff != NULL && *name_coff < 0x4000) {
1602 		if (isc_buffer_availablelength(target) < 2) {
1603 			return ISC_R_NOSPACE;
1604 		}
1605 		isc_buffer_putuint16(target, *name_coff | 0xc000);
1606 		return ISC_R_SUCCESS;
1607 	}
1608 
1609 	if (name->offsets == NULL) {
1610 		dns_name_init(&clname, clo);
1611 		dns_name_clone(name, &clname);
1612 		name = &clname;
1613 	}
1614 
1615 	/*
1616 	 * Always add the name to the compression context; if compression
1617 	 * is off, reset the return values before writing the name.
1618 	 */
1619 	prefix_length = name->length;
1620 	suffix_coff = 0;
1621 	dns_compress_name(cctx, target, name, &prefix_length, &suffix_coff);
1622 	if (!compress) {
1623 		prefix_length = name->length;
1624 		suffix_coff = 0;
1625 	}
1626 
1627 	/*
1628 	 * Return this name's compression offset for use next time, provided
1629 	 * it isn't too short for compression to help (i.e. it's the root)
1630 	 */
1631 	here = isc_buffer_usedlength(target);
1632 	if (name_coff != NULL && here < 0x4000 && prefix_length > 1) {
1633 		*name_coff = (uint16_t)here;
1634 	}
1635 
1636 	if (prefix_length > 0) {
1637 		if (isc_buffer_availablelength(target) < prefix_length) {
1638 			return ISC_R_NOSPACE;
1639 		}
1640 		memmove(isc_buffer_used(target), name->ndata, prefix_length);
1641 		isc_buffer_add(target, prefix_length);
1642 	}
1643 
1644 	if (suffix_coff > 0) {
1645 		if (name_coff != NULL && prefix_length == 0) {
1646 			*name_coff = suffix_coff;
1647 		}
1648 		if (isc_buffer_availablelength(target) < 2) {
1649 			return ISC_R_NOSPACE;
1650 		}
1651 		isc_buffer_putuint16(target, suffix_coff | 0xc000);
1652 	}
1653 
1654 	return ISC_R_SUCCESS;
1655 }
1656 
1657 isc_result_t
1658 dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
1659 		     dns_name_t *name, isc_buffer_t *target) {
1660 	unsigned char *ndata, *offsets;
1661 	unsigned int nrem, labels, prefix_length, length;
1662 	bool copy_prefix = true;
1663 	bool copy_suffix = true;
1664 	bool absolute = false;
1665 	dns_name_t tmp_name;
1666 	dns_offsets_t odata;
1667 
1668 	/*
1669 	 * Concatenate 'prefix' and 'suffix'.
1670 	 */
1671 
1672 	REQUIRE(prefix == NULL || DNS_NAME_VALID(prefix));
1673 	REQUIRE(suffix == NULL || DNS_NAME_VALID(suffix));
1674 	REQUIRE(name == NULL || DNS_NAME_VALID(name));
1675 	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1676 		(target == NULL && name != NULL &&
1677 		 ISC_BUFFER_VALID(name->buffer)));
1678 	if (prefix == NULL || prefix->labels == 0) {
1679 		copy_prefix = false;
1680 	}
1681 	if (suffix == NULL || suffix->labels == 0) {
1682 		copy_suffix = false;
1683 	}
1684 	if (copy_prefix && prefix->attributes.absolute) {
1685 		absolute = true;
1686 		REQUIRE(!copy_suffix);
1687 	}
1688 	if (name == NULL) {
1689 		dns_name_init(&tmp_name, odata);
1690 		name = &tmp_name;
1691 	}
1692 	if (target == NULL) {
1693 		INSIST(name->buffer != NULL);
1694 		target = name->buffer;
1695 		isc_buffer_clear(name->buffer);
1696 	}
1697 
1698 	REQUIRE(DNS_NAME_BINDABLE(name));
1699 
1700 	/*
1701 	 * Set up.
1702 	 */
1703 	nrem = target->length - target->used;
1704 	ndata = (unsigned char *)target->base + target->used;
1705 	if (nrem > DNS_NAME_MAXWIRE) {
1706 		nrem = DNS_NAME_MAXWIRE;
1707 	}
1708 	length = 0;
1709 	prefix_length = 0;
1710 	labels = 0;
1711 	if (copy_prefix) {
1712 		prefix_length = prefix->length;
1713 		length += prefix_length;
1714 		labels += prefix->labels;
1715 	}
1716 	if (copy_suffix) {
1717 		length += suffix->length;
1718 		labels += suffix->labels;
1719 	}
1720 	if (length > DNS_NAME_MAXWIRE) {
1721 		MAKE_EMPTY(name);
1722 		return DNS_R_NAMETOOLONG;
1723 	}
1724 	if (length > nrem) {
1725 		MAKE_EMPTY(name);
1726 		return ISC_R_NOSPACE;
1727 	}
1728 
1729 	if (copy_suffix) {
1730 		if (suffix->attributes.absolute) {
1731 			absolute = true;
1732 		}
1733 		memmove(ndata + prefix_length, suffix->ndata, suffix->length);
1734 	}
1735 
1736 	/*
1737 	 * If 'prefix' and 'name' are the same object, and the object has
1738 	 * a dedicated buffer, and we're using it, then we don't have to
1739 	 * copy anything.
1740 	 */
1741 	if (copy_prefix && (prefix != name || prefix->buffer != target)) {
1742 		memmove(ndata, prefix->ndata, prefix_length);
1743 	}
1744 
1745 	name->ndata = ndata;
1746 	name->labels = labels;
1747 	name->length = length;
1748 	name->attributes.absolute = absolute;
1749 
1750 	if (name->labels > 0 && name->offsets != NULL) {
1751 		INIT_OFFSETS(name, offsets, odata);
1752 		set_offsets(name, offsets, NULL);
1753 	}
1754 
1755 	isc_buffer_add(target, name->length);
1756 
1757 	return ISC_R_SUCCESS;
1758 }
1759 
1760 void
1761 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
1762 	/*
1763 	 * Make 'target' a dynamically allocated copy of 'source'.
1764 	 */
1765 
1766 	REQUIRE(DNS_NAME_VALID(source));
1767 	REQUIRE(source->length > 0);
1768 	REQUIRE(DNS_NAME_VALID(target));
1769 	REQUIRE(DNS_NAME_BINDABLE(target));
1770 
1771 	/*
1772 	 * Make 'target' empty in case of failure.
1773 	 */
1774 	MAKE_EMPTY(target);
1775 
1776 	target->ndata = isc_mem_get(mctx, source->length);
1777 
1778 	memmove(target->ndata, source->ndata, source->length);
1779 
1780 	target->length = source->length;
1781 	target->labels = source->labels;
1782 	target->attributes = (struct dns_name_attrs){ .dynamic = true };
1783 	target->attributes.absolute = source->attributes.absolute;
1784 	if (target->offsets != NULL) {
1785 		if (source->offsets != NULL) {
1786 			memmove(target->offsets, source->offsets,
1787 				source->labels);
1788 		} else {
1789 			set_offsets(target, target->offsets, NULL);
1790 		}
1791 	}
1792 }
1793 
1794 void
1795 dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx,
1796 			dns_name_t *target) {
1797 	/*
1798 	 * Make 'target' a read-only dynamically allocated copy of 'source'.
1799 	 * 'target' will also have a dynamically allocated offsets table.
1800 	 */
1801 
1802 	REQUIRE(DNS_NAME_VALID(source));
1803 	REQUIRE(source->length > 0);
1804 	REQUIRE(DNS_NAME_VALID(target));
1805 	REQUIRE(DNS_NAME_BINDABLE(target));
1806 	REQUIRE(target->offsets == NULL);
1807 
1808 	/*
1809 	 * Make 'target' empty in case of failure.
1810 	 */
1811 	MAKE_EMPTY(target);
1812 
1813 	target->ndata = isc_mem_get(mctx, source->length + source->labels);
1814 
1815 	memmove(target->ndata, source->ndata, source->length);
1816 
1817 	target->length = source->length;
1818 	target->labels = source->labels;
1819 	target->attributes = (struct dns_name_attrs){ .dynamic = true,
1820 						      .dynoffsets = true,
1821 						      .readonly = true };
1822 	target->attributes.absolute = source->attributes.absolute;
1823 	target->offsets = target->ndata + source->length;
1824 	if (source->offsets != NULL) {
1825 		memmove(target->offsets, source->offsets, source->labels);
1826 	} else {
1827 		set_offsets(target, target->offsets, NULL);
1828 	}
1829 }
1830 
1831 void
1832 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
1833 	size_t size;
1834 
1835 	/*
1836 	 * Free 'name'.
1837 	 */
1838 
1839 	REQUIRE(DNS_NAME_VALID(name));
1840 	REQUIRE(name->attributes.dynamic);
1841 
1842 	size = name->length;
1843 	if (name->attributes.dynoffsets) {
1844 		size += name->labels;
1845 	}
1846 	isc_mem_put(mctx, name->ndata, size);
1847 	dns_name_invalidate(name);
1848 }
1849 
1850 size_t
1851 dns_name_size(const dns_name_t *name) {
1852 	size_t size;
1853 
1854 	REQUIRE(DNS_NAME_VALID(name));
1855 
1856 	if (!name->attributes.dynamic) {
1857 		return 0;
1858 	}
1859 
1860 	size = name->length;
1861 	if (name->attributes.dynoffsets) {
1862 		size += name->labels;
1863 	}
1864 
1865 	return size;
1866 }
1867 
1868 isc_result_t
1869 dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
1870 	dns_name_t downname;
1871 	unsigned char data[256];
1872 	isc_buffer_t buffer;
1873 	isc_result_t result;
1874 	isc_region_t r;
1875 
1876 	/*
1877 	 * Send 'name' in DNSSEC canonical form to 'digest'.
1878 	 */
1879 
1880 	REQUIRE(DNS_NAME_VALID(name));
1881 	REQUIRE(digest != NULL);
1882 
1883 	dns_name_init(&downname, NULL);
1884 
1885 	isc_buffer_init(&buffer, data, sizeof(data));
1886 
1887 	result = dns_name_downcase(name, &downname, &buffer);
1888 	if (result != ISC_R_SUCCESS) {
1889 		return result;
1890 	}
1891 
1892 	isc_buffer_usedregion(&buffer, &r);
1893 
1894 	return (digest)(arg, &r);
1895 }
1896 
1897 bool
1898 dns_name_dynamic(const dns_name_t *name) {
1899 	REQUIRE(DNS_NAME_VALID(name));
1900 
1901 	/*
1902 	 * Returns whether there is dynamic memory associated with this name.
1903 	 */
1904 
1905 	return name->attributes.dynamic;
1906 }
1907 
1908 isc_result_t
1909 dns_name_print(const dns_name_t *name, FILE *stream) {
1910 	isc_result_t result;
1911 	isc_buffer_t b;
1912 	isc_region_t r;
1913 	char t[1024];
1914 
1915 	/*
1916 	 * Print 'name' on 'stream'.
1917 	 */
1918 
1919 	REQUIRE(DNS_NAME_VALID(name));
1920 
1921 	isc_buffer_init(&b, t, sizeof(t));
1922 	result = dns_name_totext(name, 0, &b);
1923 	if (result != ISC_R_SUCCESS) {
1924 		return result;
1925 	}
1926 	isc_buffer_usedregion(&b, &r);
1927 	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
1928 
1929 	return ISC_R_SUCCESS;
1930 }
1931 
1932 isc_result_t
1933 dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
1934 	/*
1935 	 * If we already have been here set / clear as appropriate.
1936 	 */
1937 	if (totext_filter_proc != NULL && proc != NULL) {
1938 		if (totext_filter_proc == proc) {
1939 			return ISC_R_SUCCESS;
1940 		}
1941 	}
1942 	if (proc == NULL && totext_filter_proc != NULL) {
1943 		totext_filter_proc = NULL;
1944 		return ISC_R_SUCCESS;
1945 	}
1946 
1947 	totext_filter_proc = proc;
1948 
1949 	return ISC_R_SUCCESS;
1950 }
1951 
1952 void
1953 dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
1954 	isc_result_t result;
1955 	isc_buffer_t buf;
1956 
1957 	REQUIRE(size > 0);
1958 
1959 	/*
1960 	 * Leave room for null termination after buffer.
1961 	 */
1962 	isc_buffer_init(&buf, cp, size - 1);
1963 	result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buf);
1964 	if (result == ISC_R_SUCCESS) {
1965 		isc_buffer_putuint8(&buf, (uint8_t)'\0');
1966 	} else {
1967 		snprintf(cp, size, "<unknown>");
1968 	}
1969 }
1970 
1971 /*
1972  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
1973  * memory.
1974  */
1975 isc_result_t
1976 dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
1977 	isc_result_t result;
1978 	isc_buffer_t buf;
1979 	isc_region_t reg;
1980 	char *p, txt[DNS_NAME_FORMATSIZE];
1981 
1982 	REQUIRE(DNS_NAME_VALID(name));
1983 	REQUIRE(target != NULL && *target == NULL);
1984 
1985 	isc_buffer_init(&buf, txt, sizeof(txt));
1986 	result = dns_name_totext(name, 0, &buf);
1987 	if (result != ISC_R_SUCCESS) {
1988 		return result;
1989 	}
1990 
1991 	isc_buffer_usedregion(&buf, &reg);
1992 	p = isc_mem_allocate(mctx, reg.length + 1);
1993 	memmove(p, (char *)reg.base, (int)reg.length);
1994 	p[reg.length] = '\0';
1995 
1996 	*target = p;
1997 	return ISC_R_SUCCESS;
1998 }
1999 
2000 isc_result_t
2001 dns_name_fromstring(dns_name_t *target, const char *src,
2002 		    const dns_name_t *origin, unsigned int options,
2003 		    isc_mem_t *mctx) {
2004 	isc_result_t result;
2005 	isc_buffer_t buf;
2006 	dns_fixedname_t fn;
2007 	dns_name_t *name;
2008 
2009 	REQUIRE(src != NULL);
2010 
2011 	isc_buffer_constinit(&buf, src, strlen(src));
2012 	isc_buffer_add(&buf, strlen(src));
2013 	if (DNS_NAME_BINDABLE(target) && target->buffer != NULL) {
2014 		name = target;
2015 	} else {
2016 		name = dns_fixedname_initname(&fn);
2017 	}
2018 
2019 	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2020 	if (result != ISC_R_SUCCESS) {
2021 		return result;
2022 	}
2023 
2024 	if (name != target) {
2025 		dns_name_dupwithoffsets(name, mctx, target);
2026 	}
2027 	return result;
2028 }
2029 
2030 void
2031 dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
2032 	isc_buffer_t *target = NULL;
2033 	unsigned char *ndata = NULL;
2034 
2035 	REQUIRE(DNS_NAME_VALID(source));
2036 	REQUIRE(DNS_NAME_VALID(dest));
2037 	REQUIRE(DNS_NAME_BINDABLE(dest));
2038 
2039 	target = dest->buffer;
2040 
2041 	REQUIRE(target != NULL);
2042 	REQUIRE(target->length >= source->length);
2043 
2044 	isc_buffer_clear(target);
2045 
2046 	ndata = (unsigned char *)target->base;
2047 	dest->ndata = target->base;
2048 
2049 	if (source->length != 0) {
2050 		memmove(ndata, source->ndata, source->length);
2051 	}
2052 
2053 	dest->ndata = ndata;
2054 	dest->labels = source->labels;
2055 	dest->length = source->length;
2056 	dest->attributes.absolute = source->attributes.absolute;
2057 
2058 	if (dest->labels > 0 && dest->offsets != NULL) {
2059 		if (source->offsets != NULL && source->labels != 0) {
2060 			memmove(dest->offsets, source->offsets, source->labels);
2061 		} else {
2062 			set_offsets(dest, dest->offsets, NULL);
2063 		}
2064 	}
2065 
2066 	isc_buffer_add(target, dest->length);
2067 }
2068 
2069 /*
2070  * Service Discovery Prefixes RFC 6763.
2071  */
2072 static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
2073 static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
2074 static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
2075 static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
2076 static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
2077 static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
2078 static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
2079 static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
2080 static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
2081 static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
2082 
2083 static dns_name_t const dns_sd[] = {
2084 	DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
2085 	DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
2086 	DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
2087 	DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
2088 	DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
2089 };
2090 
2091 bool
2092 dns_name_isdnssd(const dns_name_t *name) {
2093 	size_t i;
2094 	dns_name_t prefix;
2095 
2096 	if (dns_name_countlabels(name) > 3U) {
2097 		dns_name_init(&prefix, NULL);
2098 		dns_name_getlabelsequence(name, 0, 3, &prefix);
2099 		for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
2100 			if (dns_name_equal(&prefix, &dns_sd[i])) {
2101 				return true;
2102 			}
2103 		}
2104 	}
2105 
2106 	return false;
2107 }
2108 
2109 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
2110 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
2111 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
2112 
2113 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
2114 
2115 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
2116 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
2117 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
2118 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
2119 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
2120 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
2121 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
2122 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
2123 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
2124 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
2125 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
2126 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
2127 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
2128 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
2129 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
2130 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
2131 
2132 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
2133 
2134 static dns_name_t const rfc1918names[] = {
2135 	DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
2136 	DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
2137 	DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
2138 	DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
2139 	DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
2140 	DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
2141 	DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
2142 	DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
2143 	DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
2144 	DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
2145 	DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
2146 	DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
2147 	DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
2148 	DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
2149 	DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
2150 	DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
2151 	DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
2152 	DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
2153 };
2154 
2155 bool
2156 dns_name_isrfc1918(const dns_name_t *name) {
2157 	size_t i;
2158 
2159 	for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
2160 		if (dns_name_issubdomain(name, &rfc1918names[i])) {
2161 			return true;
2162 		}
2163 	}
2164 	return false;
2165 }
2166 
2167 static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
2168 static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
2169 static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
2170 
2171 static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
2172 				       DNS_NAME_INITABSOLUTE(ip6fd,
2173 							     ulaoffsets) };
2174 
2175 bool
2176 dns_name_isula(const dns_name_t *name) {
2177 	size_t i;
2178 
2179 	for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
2180 		if (dns_name_issubdomain(name, &ulanames[i])) {
2181 			return true;
2182 		}
2183 	}
2184 	return false;
2185 }
2186 
2187 bool
2188 dns_name_istat(const dns_name_t *name) {
2189 	unsigned char len;
2190 	const unsigned char *ndata;
2191 
2192 	REQUIRE(DNS_NAME_VALID(name));
2193 
2194 	if (name->labels < 1) {
2195 		return false;
2196 	}
2197 
2198 	ndata = name->ndata;
2199 	len = ndata[0];
2200 	INSIST(len <= name->length);
2201 	ndata++;
2202 
2203 	/*
2204 	 * Is there at least one trust anchor reported and is the
2205 	 * label length consistent with a trust-anchor-telemetry label.
2206 	 */
2207 	if ((len < 8) || (len - 3) % 5 != 0) {
2208 		return false;
2209 	}
2210 
2211 	if (ndata[0] != '_' || isc_ascii_tolower(ndata[1]) != 't' ||
2212 	    isc_ascii_tolower(ndata[2]) != 'a')
2213 	{
2214 		return false;
2215 	}
2216 	ndata += 3;
2217 	len -= 3;
2218 
2219 	while (len > 0) {
2220 		INSIST(len >= 5);
2221 		if (ndata[0] != '-' || !isc_hex_char(ndata[1]) ||
2222 		    !isc_hex_char(ndata[2]) || !isc_hex_char(ndata[3]) ||
2223 		    !isc_hex_char(ndata[4]))
2224 		{
2225 			return false;
2226 		}
2227 		ndata += 5;
2228 		len -= 5;
2229 	}
2230 	return true;
2231 }
2232 
2233 bool
2234 dns_name_isdnssvcb(const dns_name_t *name) {
2235 	unsigned char len, len1;
2236 	const unsigned char *ndata;
2237 
2238 	REQUIRE(DNS_NAME_VALID(name));
2239 
2240 	if (name->labels < 1 || name->length < 5) {
2241 		return false;
2242 	}
2243 
2244 	ndata = name->ndata;
2245 	len = len1 = ndata[0];
2246 	INSIST(len <= name->length);
2247 	ndata++;
2248 
2249 	if (len < 2 || ndata[0] != '_') {
2250 		return false;
2251 	}
2252 	if (isdigit(ndata[1]) && name->labels > 1) {
2253 		char buf[sizeof("65000")];
2254 		long port;
2255 		char *endp;
2256 
2257 		/*
2258 		 * Do we have a valid _port label?
2259 		 */
2260 		if (len > 6U || (ndata[1] == '0' && len != 2)) {
2261 			return false;
2262 		}
2263 		memcpy(buf, ndata + 1, len - 1);
2264 		buf[len - 1] = 0;
2265 		port = strtol(buf, &endp, 10);
2266 		if (*endp != 0 || port < 0 || port > 0xffff) {
2267 			return false;
2268 		}
2269 
2270 		/*
2271 		 * Move to next label.
2272 		 */
2273 		ndata += len;
2274 		INSIST(len1 + 1U < name->length);
2275 		len = *ndata;
2276 		INSIST(len + len1 + 1U <= name->length);
2277 		ndata++;
2278 	}
2279 
2280 	if (len == 4U && strncasecmp((const char *)ndata, "_dns", 4) == 0) {
2281 		return true;
2282 	}
2283 
2284 	return false;
2285 }
2286