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