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