xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/dns/name.c (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
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
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 	INSIST(name->ht == NULL);
194 }
195 
196 bool
dns_name_isvalid(const dns_name_t * name)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
dns_name_setbuffer(dns_name_t * name,isc_buffer_t * buffer)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
dns_name_hasbuffer(const dns_name_t * name)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
dns_name_isabsolute(const dns_name_t * name)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
dns_name_ismailbox(const dns_name_t * name)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
dns_name_ishostname(const dns_name_t * name,bool wildcard)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
dns_name_iswildcard(const dns_name_t * name)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
dns_name_internalwildcard(const dns_name_t * name)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
dns_name_hash(const dns_name_t * name,bool case_sensitive)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
dns_name_fullhash(const dns_name_t * name,bool case_sensitive)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
dns_name_fullcompare(const dns_name_t * name1,const dns_name_t * name2,int * orderp,unsigned int * nlabelsp)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
dns_name_compare(const dns_name_t * name1,const dns_name_t * name2)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
dns_name_equal(const dns_name_t * name1,const dns_name_t * name2)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
dns_name_caseequal(const dns_name_t * name1,const dns_name_t * name2)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
dns_name_rdatacompare(const dns_name_t * name1,const dns_name_t * name2)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
dns_name_issubdomain(const dns_name_t * name1,const dns_name_t * name2)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
dns_name_matcheswildcard(const dns_name_t * name,const dns_name_t * wname)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
dns_name_countlabels(const dns_name_t * name)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
dns_name_getlabel(const dns_name_t * name,unsigned int n,dns_label_t * label)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
dns_name_getlabelsequence(const dns_name_t * source,unsigned int first,unsigned int n,dns_name_t * target)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
dns_name_clone(const dns_name_t * source,dns_name_t * target)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
dns_name_fromregion(dns_name_t * name,const isc_region_t * r)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
dns_name_toregion(const dns_name_t * name,isc_region_t * r)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
dns_name_fromtext(dns_name_t * name,isc_buffer_t * source,const dns_name_t * origin,unsigned int options,isc_buffer_t * target)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
dns_name_totext(const dns_name_t * name,bool omit_final_dot,isc_buffer_t * target)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
dns_name_toprincipal(const dns_name_t * name,isc_buffer_t * target)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
dns_name_totext2(const dns_name_t * name,unsigned int options,isc_buffer_t * target)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
dns_name_tofilenametext(const dns_name_t * name,bool omit_final_dot,isc_buffer_t * target)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
dns_name_downcase(const dns_name_t * source,dns_name_t * name,isc_buffer_t * target)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
set_offsets(const dns_name_t * name,unsigned char * offsets,dns_name_t * set_name)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
dns_name_fromwire(dns_name_t * name,isc_buffer_t * source,dns_decompress_t * dctx,unsigned int options,isc_buffer_t * target)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
dns_name_towire(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target)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
dns_name_towire2(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target,uint16_t * comp_offsetp)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
dns_name_concatenate(const dns_name_t * prefix,const dns_name_t * suffix,dns_name_t * name,isc_buffer_t * target)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
dns_name_split(const dns_name_t * name,unsigned int suffixlabels,dns_name_t * prefix,dns_name_t * suffix)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
dns_name_dup(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)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
dns_name_dupwithoffsets(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)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
dns_name_free(dns_name_t * name,isc_mem_t * mctx)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
dns_name_digest(const dns_name_t * name,dns_digestfunc_t digest,void * arg)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
dns_name_dynamic(const dns_name_t * name)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
dns_name_print(const dns_name_t * name,FILE * stream)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
dns_name_settotextfilter(dns_name_totextfilter_t * proc)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
dns_name_format(const dns_name_t * name,char * cp,unsigned int size)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
dns_name_tostring(const dns_name_t * name,char ** target,isc_mem_t * mctx)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
dns_name_fromstring(dns_name_t * target,const char * src,unsigned int options,isc_mem_t * mctx)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
dns_name_fromstring2(dns_name_t * target,const char * src,const dns_name_t * origin,unsigned int options,isc_mem_t * mctx)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
name_copy(const dns_name_t * source,dns_name_t * dest,isc_buffer_t * target)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
dns_name_copy(const dns_name_t * source,dns_name_t * dest,isc_buffer_t * target)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
dns_name_copynf(const dns_name_t * source,dns_name_t * dest)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
dns_name_isdnssd(const dns_name_t * name)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
dns_name_isrfc1918(const dns_name_t * name)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
dns_name_isula(const dns_name_t * name)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
dns_name_istat(const dns_name_t * name)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