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