1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <ctype.h>
15 #include <inttypes.h>
16 #include <stdbool.h>
17 #include <stdlib.h>
18 
19 #include <isc/buffer.h>
20 #include <isc/hash.h>
21 #include <isc/mem.h>
22 #include <isc/once.h>
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/result.h>
26 #include <isc/string.h>
27 #include <isc/thread.h>
28 #include <isc/util.h>
29 
30 #include <dns/compress.h>
31 #include <dns/fixedname.h>
32 #include <dns/name.h>
33 
34 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
35 
36 typedef enum {
37 	ft_init = 0,
38 	ft_start,
39 	ft_ordinary,
40 	ft_initialescape,
41 	ft_escape,
42 	ft_escdecimal,
43 	ft_at
44 } ft_state;
45 
46 typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state;
47 
48 static char digitvalue[256] = {
49 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
50 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
51 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
52 	0,  1,	2,  3,	4,  5,	6,  7,	8,  9,	-1, -1, -1, -1, -1, -1, /*64*/
53 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
54 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
55 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
56 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
57 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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, /*256*/
65 };
66 
67 static unsigned char maptolower[] = {
68 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
69 	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
70 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
71 	0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
72 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
73 	0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
74 	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
75 	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
76 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
77 	0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
78 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
79 	0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
80 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
81 	0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
82 	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
83 	0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
84 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
85 	0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
86 	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
87 	0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
88 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
89 	0xfc, 0xfd, 0xfe, 0xff
90 };
91 
92 #define CONVERTTOASCII(c)
93 #define CONVERTFROMASCII(c)
94 
95 #define INIT_OFFSETS(name, var, default_offsets) \
96 	if ((name)->offsets != NULL)             \
97 		var = (name)->offsets;           \
98 	else                                     \
99 		var = (default_offsets);
100 
101 #define SETUP_OFFSETS(name, var, default_offsets) \
102 	if ((name)->offsets != NULL) {            \
103 		var = (name)->offsets;            \
104 	} else {                                  \
105 		var = (default_offsets);          \
106 		set_offsets(name, var, NULL);     \
107 	}
108 
109 /*%
110  * Note:  If additional attributes are added that should not be set for
111  *	  empty names, MAKE_EMPTY() must be changed so it clears them.
112  */
113 #define MAKE_EMPTY(name)                                    \
114 	do {                                                \
115 		name->ndata = NULL;                         \
116 		name->length = 0;                           \
117 		name->labels = 0;                           \
118 		name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
119 	} while (0);
120 
121 /*%
122  * A name is "bindable" if it can be set to point to a new value, i.e.
123  * name->ndata and name->length may be changed.
124  */
125 #define BINDABLE(name)       \
126 	((name->attributes & \
127 	  (DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC)) == 0)
128 
129 /*%
130  * Note that the name data must be a char array, not a string
131  * literal, to avoid compiler warnings about discarding
132  * the const attribute of a string.
133  */
134 static unsigned char root_ndata[] = { "" };
135 static unsigned char root_offsets[] = { 0 };
136 
137 static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets);
138 const dns_name_t *dns_rootname = &root;
139 
140 static unsigned char wild_ndata[] = { "\001*" };
141 static unsigned char wild_offsets[] = { 0 };
142 
143 static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata,
144 							wild_offsets);
145 
146 const dns_name_t *dns_wildcardname = &wild;
147 
148 /*
149  * dns_name_t to text post-conversion procedure.
150  */
151 static thread_local dns_name_totextfilter_t *totext_filter_proc = NULL;
152 
153 static void
154 set_offsets(const dns_name_t *name, unsigned char *offsets,
155 	    dns_name_t *set_name);
156 
157 void
dns_name_init(dns_name_t * name,unsigned char * offsets)158 dns_name_init(dns_name_t *name, unsigned char *offsets) {
159 	/*
160 	 * Initialize 'name'.
161 	 */
162 	DNS_NAME_INIT(name, offsets);
163 }
164 
165 void
dns_name_reset(dns_name_t * name)166 dns_name_reset(dns_name_t *name) {
167 	REQUIRE(VALID_NAME(name));
168 	REQUIRE(BINDABLE(name));
169 
170 	DNS_NAME_RESET(name);
171 }
172 
173 void
dns_name_invalidate(dns_name_t * name)174 dns_name_invalidate(dns_name_t *name) {
175 	/*
176 	 * Make 'name' invalid.
177 	 */
178 
179 	REQUIRE(VALID_NAME(name));
180 
181 	name->magic = 0;
182 	name->ndata = NULL;
183 	name->length = 0;
184 	name->labels = 0;
185 	name->attributes = 0;
186 	name->offsets = NULL;
187 	name->buffer = NULL;
188 	ISC_LINK_INIT(name, link);
189 }
190 
191 bool
dns_name_isvalid(const dns_name_t * name)192 dns_name_isvalid(const dns_name_t *name) {
193 	unsigned char *ndata, *offsets;
194 	unsigned int offset, count, length, nlabels;
195 
196 	if (!VALID_NAME(name)) {
197 		return (false);
198 	}
199 
200 	if (name->length > 255U || name->labels > 127U) {
201 		return (false);
202 	}
203 
204 	ndata = name->ndata;
205 	length = name->length;
206 	offsets = name->offsets;
207 	offset = 0;
208 	nlabels = 0;
209 
210 	while (offset != length) {
211 		count = *ndata;
212 		if (count > 63U) {
213 			return (false);
214 		}
215 		if (offsets != NULL && offsets[nlabels] != offset) {
216 			return (false);
217 		}
218 
219 		nlabels++;
220 		offset += count + 1;
221 		ndata += count + 1;
222 		if (offset > length) {
223 			return (false);
224 		}
225 
226 		if (count == 0) {
227 			break;
228 		}
229 	}
230 
231 	if (nlabels != name->labels || offset != name->length) {
232 		return (false);
233 	}
234 
235 	return (true);
236 }
237 
238 void
dns_name_setbuffer(dns_name_t * name,isc_buffer_t * buffer)239 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
240 	/*
241 	 * Dedicate a buffer for use with 'name'.
242 	 */
243 
244 	REQUIRE(VALID_NAME(name));
245 	REQUIRE((buffer != NULL && name->buffer == NULL) || (buffer == NULL));
246 
247 	name->buffer = buffer;
248 }
249 
250 bool
dns_name_hasbuffer(const dns_name_t * name)251 dns_name_hasbuffer(const dns_name_t *name) {
252 	/*
253 	 * Does 'name' have a dedicated buffer?
254 	 */
255 
256 	REQUIRE(VALID_NAME(name));
257 
258 	if (name->buffer != NULL) {
259 		return (true);
260 	}
261 
262 	return (false);
263 }
264 
265 bool
dns_name_isabsolute(const dns_name_t * name)266 dns_name_isabsolute(const dns_name_t *name) {
267 	/*
268 	 * Does 'name' end in the root label?
269 	 */
270 
271 	REQUIRE(VALID_NAME(name));
272 
273 	if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
274 		return (true);
275 	}
276 	return (false);
277 }
278 
279 #define hyphenchar(c) ((c) == 0x2d)
280 #define asterchar(c)  ((c) == 0x2a)
281 #define alphachar(c) \
282 	(((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a))
283 #define digitchar(c)  ((c) >= 0x30 && (c) <= 0x39)
284 #define borderchar(c) (alphachar(c) || digitchar(c))
285 #define middlechar(c) (borderchar(c) || hyphenchar(c))
286 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
287 
288 bool
dns_name_ismailbox(const dns_name_t * name)289 dns_name_ismailbox(const dns_name_t *name) {
290 	unsigned char *ndata, ch;
291 	unsigned int n;
292 	bool first;
293 
294 	REQUIRE(VALID_NAME(name));
295 	REQUIRE(name->labels > 0);
296 	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
297 
298 	/*
299 	 * Root label.
300 	 */
301 	if (name->length == 1) {
302 		return (true);
303 	}
304 
305 	ndata = name->ndata;
306 	n = *ndata++;
307 	INSIST(n <= 63);
308 	while (n--) {
309 		ch = *ndata++;
310 		if (!domainchar(ch)) {
311 			return (false);
312 		}
313 	}
314 
315 	if (ndata == name->ndata + name->length) {
316 		return (false);
317 	}
318 
319 	/*
320 	 * RFC952/RFC1123 hostname.
321 	 */
322 	while (ndata < (name->ndata + name->length)) {
323 		n = *ndata++;
324 		INSIST(n <= 63);
325 		first = true;
326 		while (n--) {
327 			ch = *ndata++;
328 			if (first || n == 0) {
329 				if (!borderchar(ch)) {
330 					return (false);
331 				}
332 			} else {
333 				if (!middlechar(ch)) {
334 					return (false);
335 				}
336 			}
337 			first = false;
338 		}
339 	}
340 	return (true);
341 }
342 
343 bool
dns_name_ishostname(const dns_name_t * name,bool wildcard)344 dns_name_ishostname(const dns_name_t *name, bool wildcard) {
345 	unsigned char *ndata, ch;
346 	unsigned int n;
347 	bool first;
348 
349 	REQUIRE(VALID_NAME(name));
350 	REQUIRE(name->labels > 0);
351 	REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
352 
353 	/*
354 	 * Root label.
355 	 */
356 	if (name->length == 1) {
357 		return (true);
358 	}
359 
360 	/*
361 	 * Skip wildcard if this is a ownername.
362 	 */
363 	ndata = name->ndata;
364 	if (wildcard && ndata[0] == 1 && ndata[1] == '*') {
365 		ndata += 2;
366 	}
367 
368 	/*
369 	 * RFC952/RFC1123 hostname.
370 	 */
371 	while (ndata < (name->ndata + name->length)) {
372 		n = *ndata++;
373 		INSIST(n <= 63);
374 		first = true;
375 		while (n--) {
376 			ch = *ndata++;
377 			if (first || n == 0) {
378 				if (!borderchar(ch)) {
379 					return (false);
380 				}
381 			} else {
382 				if (!middlechar(ch)) {
383 					return (false);
384 				}
385 			}
386 			first = false;
387 		}
388 	}
389 	return (true);
390 }
391 
392 bool
dns_name_iswildcard(const dns_name_t * name)393 dns_name_iswildcard(const dns_name_t *name) {
394 	unsigned char *ndata;
395 
396 	/*
397 	 * Is 'name' a wildcard name?
398 	 */
399 
400 	REQUIRE(VALID_NAME(name));
401 	REQUIRE(name->labels > 0);
402 
403 	if (name->length >= 2) {
404 		ndata = name->ndata;
405 		if (ndata[0] == 1 && ndata[1] == '*') {
406 			return (true);
407 		}
408 	}
409 
410 	return (false);
411 }
412 
413 bool
dns_name_internalwildcard(const dns_name_t * name)414 dns_name_internalwildcard(const dns_name_t *name) {
415 	unsigned char *ndata;
416 	unsigned int count;
417 	unsigned int label;
418 
419 	/*
420 	 * Does 'name' contain a internal wildcard?
421 	 */
422 
423 	REQUIRE(VALID_NAME(name));
424 	REQUIRE(name->labels > 0);
425 
426 	/*
427 	 * Skip first label.
428 	 */
429 	ndata = name->ndata;
430 	count = *ndata++;
431 	INSIST(count <= 63);
432 	ndata += count;
433 	label = 1;
434 	/*
435 	 * Check all but the last of the remaining labels.
436 	 */
437 	while (label + 1 < name->labels) {
438 		count = *ndata++;
439 		INSIST(count <= 63);
440 		if (count == 1 && *ndata == '*') {
441 			return (true);
442 		}
443 		ndata += count;
444 		label++;
445 	}
446 	return (false);
447 }
448 
449 unsigned int
dns_name_hash(const dns_name_t * name,bool case_sensitive)450 dns_name_hash(const dns_name_t *name, bool case_sensitive) {
451 	unsigned int length;
452 
453 	/*
454 	 * Provide a hash value for 'name'.
455 	 */
456 	REQUIRE(VALID_NAME(name));
457 
458 	if (name->labels == 0) {
459 		return (0);
460 	}
461 
462 	length = name->length;
463 	if (length > 16) {
464 		length = 16;
465 	}
466 
467 	/* High bits are more random. */
468 	return (isc_hash32(name->ndata, length, case_sensitive));
469 }
470 
471 unsigned int
dns_name_fullhash(const dns_name_t * name,bool case_sensitive)472 dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
473 	/*
474 	 * Provide a hash value for 'name'.
475 	 */
476 	REQUIRE(VALID_NAME(name));
477 
478 	if (name->labels == 0) {
479 		return (0);
480 	}
481 
482 	/* High bits are more random. */
483 	return (isc_hash32(name->ndata, name->length, case_sensitive));
484 }
485 
486 dns_namereln_t
dns_name_fullcompare(const dns_name_t * name1,const dns_name_t * name2,int * orderp,unsigned int * nlabelsp)487 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
488 		     int *orderp, unsigned int *nlabelsp) {
489 	unsigned int l1, l2, l, count1, count2, count, nlabels;
490 	int cdiff, ldiff, chdiff;
491 	unsigned char *label1, *label2;
492 	unsigned char *offsets1, *offsets2;
493 	dns_offsets_t odata1, odata2;
494 	dns_namereln_t namereln = dns_namereln_none;
495 
496 	/*
497 	 * Determine the relative ordering under the DNSSEC order relation of
498 	 * 'name1' and 'name2', and also determine the hierarchical
499 	 * relationship of the names.
500 	 *
501 	 * Note: It makes no sense for one of the names to be relative and the
502 	 * other absolute.  If both names are relative, then to be meaningfully
503 	 * compared the caller must ensure that they are both relative to the
504 	 * same domain.
505 	 */
506 
507 	REQUIRE(VALID_NAME(name1));
508 	REQUIRE(VALID_NAME(name2));
509 	REQUIRE(orderp != NULL);
510 	REQUIRE(nlabelsp != NULL);
511 	/*
512 	 * Either name1 is absolute and name2 is absolute, or neither is.
513 	 */
514 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
515 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
516 
517 	if (ISC_UNLIKELY(name1 == name2)) {
518 		*orderp = 0;
519 		*nlabelsp = name1->labels;
520 		return (dns_namereln_equal);
521 	}
522 
523 	SETUP_OFFSETS(name1, offsets1, odata1);
524 	SETUP_OFFSETS(name2, offsets2, odata2);
525 
526 	nlabels = 0;
527 	l1 = name1->labels;
528 	l2 = name2->labels;
529 	if (l2 > l1) {
530 		l = l1;
531 		ldiff = 0 - (l2 - l1);
532 	} else {
533 		l = l2;
534 		ldiff = l1 - l2;
535 	}
536 
537 	offsets1 += l1;
538 	offsets2 += l2;
539 
540 	while (ISC_LIKELY(l > 0)) {
541 		l--;
542 		offsets1--;
543 		offsets2--;
544 		label1 = &name1->ndata[*offsets1];
545 		label2 = &name2->ndata[*offsets2];
546 		count1 = *label1++;
547 		count2 = *label2++;
548 
549 		/*
550 		 * We dropped bitstring labels, and we don't support any
551 		 * other extended label types.
552 		 */
553 		INSIST(count1 <= 63 && count2 <= 63);
554 
555 		cdiff = (int)count1 - (int)count2;
556 		if (cdiff < 0) {
557 			count = count1;
558 		} else {
559 			count = count2;
560 		}
561 
562 		/* Loop unrolled for performance */
563 		while (ISC_LIKELY(count > 3)) {
564 			chdiff = (int)maptolower[label1[0]] -
565 				 (int)maptolower[label2[0]];
566 			if (chdiff != 0) {
567 				*orderp = chdiff;
568 				goto done;
569 			}
570 			chdiff = (int)maptolower[label1[1]] -
571 				 (int)maptolower[label2[1]];
572 			if (chdiff != 0) {
573 				*orderp = chdiff;
574 				goto done;
575 			}
576 			chdiff = (int)maptolower[label1[2]] -
577 				 (int)maptolower[label2[2]];
578 			if (chdiff != 0) {
579 				*orderp = chdiff;
580 				goto done;
581 			}
582 			chdiff = (int)maptolower[label1[3]] -
583 				 (int)maptolower[label2[3]];
584 			if (chdiff != 0) {
585 				*orderp = chdiff;
586 				goto done;
587 			}
588 			count -= 4;
589 			label1 += 4;
590 			label2 += 4;
591 		}
592 		while (ISC_LIKELY(count-- > 0)) {
593 			chdiff = (int)maptolower[*label1++] -
594 				 (int)maptolower[*label2++];
595 			if (chdiff != 0) {
596 				*orderp = chdiff;
597 				goto done;
598 			}
599 		}
600 		if (cdiff != 0) {
601 			*orderp = cdiff;
602 			goto done;
603 		}
604 		nlabels++;
605 	}
606 
607 	*orderp = ldiff;
608 	if (ldiff < 0) {
609 		namereln = dns_namereln_contains;
610 	} else if (ldiff > 0) {
611 		namereln = dns_namereln_subdomain;
612 	} else {
613 		namereln = dns_namereln_equal;
614 	}
615 	*nlabelsp = nlabels;
616 	return (namereln);
617 
618 done:
619 	*nlabelsp = nlabels;
620 	if (nlabels > 0) {
621 		namereln = dns_namereln_commonancestor;
622 	}
623 
624 	return (namereln);
625 }
626 
627 int
dns_name_compare(const dns_name_t * name1,const dns_name_t * name2)628 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
629 	int order;
630 	unsigned int nlabels;
631 
632 	/*
633 	 * Determine the relative ordering under the DNSSEC order relation of
634 	 * 'name1' and 'name2'.
635 	 *
636 	 * Note: It makes no sense for one of the names to be relative and the
637 	 * other absolute.  If both names are relative, then to be meaningfully
638 	 * compared the caller must ensure that they are both relative to the
639 	 * same domain.
640 	 */
641 
642 	(void)dns_name_fullcompare(name1, name2, &order, &nlabels);
643 
644 	return (order);
645 }
646 
647 bool
dns_name_equal(const dns_name_t * name1,const dns_name_t * name2)648 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
649 	unsigned int l, count;
650 	unsigned char c;
651 	unsigned char *label1, *label2;
652 
653 	/*
654 	 * Are 'name1' and 'name2' equal?
655 	 *
656 	 * Note: It makes no sense for one of the names to be relative and the
657 	 * other absolute.  If both names are relative, then to be meaningfully
658 	 * compared the caller must ensure that they are both relative to the
659 	 * same domain.
660 	 */
661 
662 	REQUIRE(VALID_NAME(name1));
663 	REQUIRE(VALID_NAME(name2));
664 	/*
665 	 * Either name1 is absolute and name2 is absolute, or neither is.
666 	 */
667 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
668 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
669 
670 	if (ISC_UNLIKELY(name1 == name2)) {
671 		return (true);
672 	}
673 
674 	if (name1->length != name2->length) {
675 		return (false);
676 	}
677 
678 	l = name1->labels;
679 
680 	if (l != name2->labels) {
681 		return (false);
682 	}
683 
684 	label1 = name1->ndata;
685 	label2 = name2->ndata;
686 	while (ISC_LIKELY(l-- > 0)) {
687 		count = *label1++;
688 		if (count != *label2++) {
689 			return (false);
690 		}
691 
692 		INSIST(count <= 63); /* no bitstring support */
693 
694 		/* Loop unrolled for performance */
695 		while (ISC_LIKELY(count > 3)) {
696 			c = maptolower[label1[0]];
697 			if (c != maptolower[label2[0]]) {
698 				return (false);
699 			}
700 			c = maptolower[label1[1]];
701 			if (c != maptolower[label2[1]]) {
702 				return (false);
703 			}
704 			c = maptolower[label1[2]];
705 			if (c != maptolower[label2[2]]) {
706 				return (false);
707 			}
708 			c = maptolower[label1[3]];
709 			if (c != maptolower[label2[3]]) {
710 				return (false);
711 			}
712 			count -= 4;
713 			label1 += 4;
714 			label2 += 4;
715 		}
716 		while (ISC_LIKELY(count-- > 0)) {
717 			c = maptolower[*label1++];
718 			if (c != maptolower[*label2++]) {
719 				return (false);
720 			}
721 		}
722 	}
723 
724 	return (true);
725 }
726 
727 bool
dns_name_caseequal(const dns_name_t * name1,const dns_name_t * name2)728 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
729 	/*
730 	 * Are 'name1' and 'name2' equal?
731 	 *
732 	 * Note: It makes no sense for one of the names to be relative and the
733 	 * other absolute.  If both names are relative, then to be meaningfully
734 	 * compared the caller must ensure that they are both relative to the
735 	 * same domain.
736 	 */
737 
738 	REQUIRE(VALID_NAME(name1));
739 	REQUIRE(VALID_NAME(name2));
740 	/*
741 	 * Either name1 is absolute and name2 is absolute, or neither is.
742 	 */
743 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
744 		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
745 
746 	if (name1->length != name2->length) {
747 		return (false);
748 	}
749 
750 	if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
751 		return (false);
752 	}
753 
754 	return (true);
755 }
756 
757 int
dns_name_rdatacompare(const dns_name_t * name1,const dns_name_t * name2)758 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
759 	unsigned int l1, l2, l, count1, count2, count;
760 	unsigned char c1, c2;
761 	unsigned char *label1, *label2;
762 
763 	/*
764 	 * Compare two absolute names as rdata.
765 	 */
766 
767 	REQUIRE(VALID_NAME(name1));
768 	REQUIRE(name1->labels > 0);
769 	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
770 	REQUIRE(VALID_NAME(name2));
771 	REQUIRE(name2->labels > 0);
772 	REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
773 
774 	l1 = name1->labels;
775 	l2 = name2->labels;
776 
777 	l = (l1 < l2) ? l1 : l2;
778 
779 	label1 = name1->ndata;
780 	label2 = name2->ndata;
781 	while (l > 0) {
782 		l--;
783 		count1 = *label1++;
784 		count2 = *label2++;
785 
786 		/* no bitstring support */
787 		INSIST(count1 <= 63 && count2 <= 63);
788 
789 		if (count1 != count2) {
790 			return ((count1 < count2) ? -1 : 1);
791 		}
792 		count = count1;
793 		while (count > 0) {
794 			count--;
795 			c1 = maptolower[*label1++];
796 			c2 = maptolower[*label2++];
797 			if (c1 < c2) {
798 				return (-1);
799 			} else if (c1 > c2) {
800 				return (1);
801 			}
802 		}
803 	}
804 
805 	/*
806 	 * If one name had more labels than the other, their common
807 	 * prefix must have been different because the shorter name
808 	 * ended with the root label and the longer one can't have
809 	 * a root label in the middle of it.  Therefore, if we get
810 	 * to this point, the lengths must be equal.
811 	 */
812 	INSIST(l1 == l2);
813 
814 	return (0);
815 }
816 
817 bool
dns_name_issubdomain(const dns_name_t * name1,const dns_name_t * name2)818 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
819 	int order;
820 	unsigned int nlabels;
821 	dns_namereln_t namereln;
822 
823 	/*
824 	 * Is 'name1' a subdomain of 'name2'?
825 	 *
826 	 * Note: It makes no sense for one of the names to be relative and the
827 	 * other absolute.  If both names are relative, then to be meaningfully
828 	 * compared the caller must ensure that they are both relative to the
829 	 * same domain.
830 	 */
831 
832 	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
833 	if (namereln == dns_namereln_subdomain ||
834 	    namereln == dns_namereln_equal) {
835 		return (true);
836 	}
837 
838 	return (false);
839 }
840 
841 bool
dns_name_matcheswildcard(const dns_name_t * name,const dns_name_t * wname)842 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
843 	int order;
844 	unsigned int nlabels, labels;
845 	dns_name_t tname;
846 
847 	REQUIRE(VALID_NAME(name));
848 	REQUIRE(name->labels > 0);
849 	REQUIRE(VALID_NAME(wname));
850 	labels = wname->labels;
851 	REQUIRE(labels > 0);
852 	REQUIRE(dns_name_iswildcard(wname));
853 
854 #if defined(__clang__) && \
855 	(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
856 	memset(&tname, 0, sizeof(tname));
857 #endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
858 	* 3                                                                    \
859 	* && __clang_minor__ < 2)) */
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 						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 			/* NOTREACHED */
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 			/* NOTREACHED */
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 					return (DNS_R_DISALLOWED);
1862 				}
1863 				new_current = c & 0x3F;
1864 				state = fw_newcurrent;
1865 			} else {
1866 				return (DNS_R_BADLABELTYPE);
1867 			}
1868 			break;
1869 		case fw_ordinary:
1870 			if (downcase) {
1871 				c = maptolower[c];
1872 			}
1873 			*ndata++ = c;
1874 			n--;
1875 			if (n == 0) {
1876 				state = fw_start;
1877 			}
1878 			break;
1879 		case fw_newcurrent:
1880 			new_current *= 256;
1881 			new_current += c;
1882 			if (new_current >= biggest_pointer) {
1883 				return (DNS_R_BADPOINTER);
1884 			}
1885 			biggest_pointer = new_current;
1886 			current = new_current;
1887 			cdata = (unsigned char *)source->base + current;
1888 			seen_pointer = true;
1889 			state = fw_start;
1890 			break;
1891 		default:
1892 			FATAL_ERROR(__FILE__, __LINE__, "Unknown state %d",
1893 				    state);
1894 			/* Does not return. */
1895 		}
1896 	}
1897 
1898 	if (!done) {
1899 		return (ISC_R_UNEXPECTEDEND);
1900 	}
1901 
1902 	name->ndata = (unsigned char *)target->base + target->used;
1903 	name->labels = labels;
1904 	name->length = nused;
1905 	name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1906 
1907 	isc_buffer_forward(source, cused);
1908 	isc_buffer_add(target, name->length);
1909 
1910 	return (ISC_R_SUCCESS);
1911 
1912 full:
1913 	if (nmax == DNS_NAME_MAXWIRE) {
1914 		/*
1915 		 * The name did not fit even though we had a buffer
1916 		 * big enough to fit a maximum-length name.
1917 		 */
1918 		return (DNS_R_NAMETOOLONG);
1919 	} else {
1920 		/*
1921 		 * The name might fit if only the caller could give us a
1922 		 * big enough buffer.
1923 		 */
1924 		return (ISC_R_NOSPACE);
1925 	}
1926 }
1927 
1928 isc_result_t
dns_name_towire(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target)1929 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1930 		isc_buffer_t *target) {
1931 	return (dns_name_towire2(name, cctx, target, NULL));
1932 }
1933 
1934 isc_result_t
dns_name_towire2(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target,uint16_t * comp_offsetp)1935 dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
1936 		 isc_buffer_t *target, uint16_t *comp_offsetp) {
1937 	unsigned int methods;
1938 	uint16_t offset;
1939 	dns_name_t gp; /* Global compression prefix */
1940 	bool gf;       /* Global compression target found */
1941 	uint16_t go;   /* Global compression offset */
1942 	dns_offsets_t clo;
1943 	dns_name_t clname;
1944 
1945 	/*
1946 	 * Convert 'name' into wire format, compressing it as specified by the
1947 	 * compression context 'cctx', and storing the result in 'target'.
1948 	 */
1949 
1950 	REQUIRE(VALID_NAME(name));
1951 	REQUIRE(cctx != NULL);
1952 	REQUIRE(ISC_BUFFER_VALID(target));
1953 
1954 	/*
1955 	 * If this exact name was already rendered before, and the
1956 	 * offset of the previously rendered name is passed to us, write
1957 	 * a compression pointer directly.
1958 	 */
1959 	methods = dns_compress_getmethods(cctx);
1960 	if (comp_offsetp != NULL && *comp_offsetp < 0x4000 &&
1961 	    (name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1962 	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1963 	{
1964 		if (ISC_UNLIKELY(target->length - target->used < 2)) {
1965 			return (ISC_R_NOSPACE);
1966 		}
1967 		offset = *comp_offsetp;
1968 		offset |= 0xc000;
1969 		isc_buffer_putuint16(target, offset);
1970 		return (ISC_R_SUCCESS);
1971 	}
1972 
1973 	/*
1974 	 * If 'name' doesn't have an offsets table, make a clone which
1975 	 * has one.
1976 	 */
1977 	if (name->offsets == NULL) {
1978 #if defined(__clang__) && \
1979 	(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1980 		memset(&clname, 0, sizeof(clname));
1981 #endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
1982 	* 3                                                                    \
1983 	* && __clang_minor__ < 2)) */
1984 		DNS_NAME_INIT(&clname, clo);
1985 		dns_name_clone(name, &clname);
1986 		name = &clname;
1987 	}
1988 	DNS_NAME_INIT(&gp, NULL);
1989 
1990 	offset = target->used; /*XXX*/
1991 
1992 	if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1993 	    (methods & DNS_COMPRESS_GLOBAL14) != 0)
1994 	{
1995 		gf = dns_compress_findglobal(cctx, name, &gp, &go);
1996 	} else {
1997 		gf = false;
1998 	}
1999 
2000 	/*
2001 	 * If the offset is too high for 14 bit global compression, we're
2002 	 * out of luck.
2003 	 */
2004 	if (gf && ISC_UNLIKELY(go >= 0x4000)) {
2005 		gf = false;
2006 	}
2007 
2008 	/*
2009 	 * Will the compression pointer reduce the message size?
2010 	 */
2011 	if (gf && (gp.length + 2) >= name->length) {
2012 		gf = false;
2013 	}
2014 
2015 	if (gf) {
2016 		if (ISC_UNLIKELY(target->length - target->used < gp.length)) {
2017 			return (ISC_R_NOSPACE);
2018 		}
2019 		if (gp.length != 0) {
2020 			unsigned char *base = target->base;
2021 			(void)memmove(base + target->used, gp.ndata,
2022 				      (size_t)gp.length);
2023 		}
2024 		isc_buffer_add(target, gp.length);
2025 		if (ISC_UNLIKELY(target->length - target->used < 2)) {
2026 			return (ISC_R_NOSPACE);
2027 		}
2028 		isc_buffer_putuint16(target, go | 0xc000);
2029 		if (gp.length != 0) {
2030 			dns_compress_add(cctx, name, &gp, offset);
2031 			if (comp_offsetp != NULL) {
2032 				*comp_offsetp = offset;
2033 			}
2034 		} else if (comp_offsetp != NULL) {
2035 			*comp_offsetp = go;
2036 		}
2037 	} else {
2038 		if (ISC_UNLIKELY(target->length - target->used < name->length))
2039 		{
2040 			return (ISC_R_NOSPACE);
2041 		}
2042 		if (name->length != 0) {
2043 			unsigned char *base = target->base;
2044 			(void)memmove(base + target->used, name->ndata,
2045 				      (size_t)name->length);
2046 		}
2047 		isc_buffer_add(target, name->length);
2048 		dns_compress_add(cctx, name, name, offset);
2049 		if (comp_offsetp != NULL) {
2050 			*comp_offsetp = offset;
2051 		}
2052 	}
2053 
2054 	return (ISC_R_SUCCESS);
2055 }
2056 
2057 isc_result_t
dns_name_concatenate(const dns_name_t * prefix,const dns_name_t * suffix,dns_name_t * name,isc_buffer_t * target)2058 dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
2059 		     dns_name_t *name, isc_buffer_t *target) {
2060 	unsigned char *ndata, *offsets;
2061 	unsigned int nrem, labels, prefix_length, length;
2062 	bool copy_prefix = true;
2063 	bool copy_suffix = true;
2064 	bool absolute = false;
2065 	dns_name_t tmp_name;
2066 	dns_offsets_t odata;
2067 
2068 	/*
2069 	 * Concatenate 'prefix' and 'suffix'.
2070 	 */
2071 
2072 	REQUIRE(prefix == NULL || VALID_NAME(prefix));
2073 	REQUIRE(suffix == NULL || VALID_NAME(suffix));
2074 	REQUIRE(name == NULL || VALID_NAME(name));
2075 	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2076 		(target == NULL && name != NULL &&
2077 		 ISC_BUFFER_VALID(name->buffer)));
2078 	if (prefix == NULL || prefix->labels == 0) {
2079 		copy_prefix = false;
2080 	}
2081 	if (suffix == NULL || suffix->labels == 0) {
2082 		copy_suffix = false;
2083 	}
2084 	if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2085 		absolute = true;
2086 		REQUIRE(!copy_suffix);
2087 	}
2088 	if (name == NULL) {
2089 		DNS_NAME_INIT(&tmp_name, odata);
2090 		name = &tmp_name;
2091 	}
2092 	if (target == NULL) {
2093 		INSIST(name->buffer != NULL);
2094 		target = name->buffer;
2095 		isc_buffer_clear(name->buffer);
2096 	}
2097 
2098 	REQUIRE(BINDABLE(name));
2099 
2100 	/*
2101 	 * Set up.
2102 	 */
2103 	nrem = target->length - target->used;
2104 	ndata = (unsigned char *)target->base + target->used;
2105 	if (nrem > DNS_NAME_MAXWIRE) {
2106 		nrem = DNS_NAME_MAXWIRE;
2107 	}
2108 	length = 0;
2109 	prefix_length = 0;
2110 	labels = 0;
2111 	if (copy_prefix) {
2112 		prefix_length = prefix->length;
2113 		length += prefix_length;
2114 		labels += prefix->labels;
2115 	}
2116 	if (copy_suffix) {
2117 		length += suffix->length;
2118 		labels += suffix->labels;
2119 	}
2120 	if (length > DNS_NAME_MAXWIRE) {
2121 		MAKE_EMPTY(name);
2122 		return (DNS_R_NAMETOOLONG);
2123 	}
2124 	if (length > nrem) {
2125 		MAKE_EMPTY(name);
2126 		return (ISC_R_NOSPACE);
2127 	}
2128 
2129 	if (copy_suffix) {
2130 		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2131 			absolute = true;
2132 		}
2133 		memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2134 	}
2135 
2136 	/*
2137 	 * If 'prefix' and 'name' are the same object, and the object has
2138 	 * a dedicated buffer, and we're using it, then we don't have to
2139 	 * copy anything.
2140 	 */
2141 	if (copy_prefix && (prefix != name || prefix->buffer != target)) {
2142 		memmove(ndata, prefix->ndata, prefix_length);
2143 	}
2144 
2145 	name->ndata = ndata;
2146 	name->labels = labels;
2147 	name->length = length;
2148 	if (absolute) {
2149 		name->attributes = DNS_NAMEATTR_ABSOLUTE;
2150 	} else {
2151 		name->attributes = 0;
2152 	}
2153 
2154 	if (name->labels > 0 && name->offsets != NULL) {
2155 		INIT_OFFSETS(name, offsets, odata);
2156 		set_offsets(name, offsets, NULL);
2157 	}
2158 
2159 	isc_buffer_add(target, name->length);
2160 
2161 	return (ISC_R_SUCCESS);
2162 }
2163 
2164 void
dns_name_split(const dns_name_t * name,unsigned int suffixlabels,dns_name_t * prefix,dns_name_t * suffix)2165 dns_name_split(const dns_name_t *name, unsigned int suffixlabels,
2166 	       dns_name_t *prefix, dns_name_t *suffix)
2167 
2168 {
2169 	unsigned int splitlabel;
2170 
2171 	REQUIRE(VALID_NAME(name));
2172 	REQUIRE(suffixlabels > 0);
2173 	REQUIRE(suffixlabels <= name->labels);
2174 	REQUIRE(prefix != NULL || suffix != NULL);
2175 	REQUIRE(prefix == NULL || (VALID_NAME(prefix) && BINDABLE(prefix)));
2176 	REQUIRE(suffix == NULL || (VALID_NAME(suffix) && BINDABLE(suffix)));
2177 
2178 	splitlabel = name->labels - suffixlabels;
2179 
2180 	if (prefix != NULL) {
2181 		dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2182 	}
2183 
2184 	if (suffix != NULL) {
2185 		dns_name_getlabelsequence(name, splitlabel, suffixlabels,
2186 					  suffix);
2187 	}
2188 
2189 	return;
2190 }
2191 
2192 void
dns_name_dup(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)2193 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
2194 	/*
2195 	 * Make 'target' a dynamically allocated copy of 'source'.
2196 	 */
2197 
2198 	REQUIRE(VALID_NAME(source));
2199 	REQUIRE(source->length > 0);
2200 	REQUIRE(VALID_NAME(target));
2201 	REQUIRE(BINDABLE(target));
2202 
2203 	/*
2204 	 * Make 'target' empty in case of failure.
2205 	 */
2206 	MAKE_EMPTY(target);
2207 
2208 	target->ndata = isc_mem_get(mctx, source->length);
2209 
2210 	memmove(target->ndata, source->ndata, source->length);
2211 
2212 	target->length = source->length;
2213 	target->labels = source->labels;
2214 	target->attributes = DNS_NAMEATTR_DYNAMIC;
2215 	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2216 		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2217 	}
2218 	if (target->offsets != NULL) {
2219 		if (source->offsets != NULL) {
2220 			memmove(target->offsets, source->offsets,
2221 				source->labels);
2222 		} else {
2223 			set_offsets(target, target->offsets, NULL);
2224 		}
2225 	}
2226 }
2227 
2228 isc_result_t
dns_name_dupwithoffsets(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)2229 dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx,
2230 			dns_name_t *target) {
2231 	/*
2232 	 * Make 'target' a read-only dynamically allocated copy of 'source'.
2233 	 * 'target' will also have a dynamically allocated offsets table.
2234 	 */
2235 
2236 	REQUIRE(VALID_NAME(source));
2237 	REQUIRE(source->length > 0);
2238 	REQUIRE(VALID_NAME(target));
2239 	REQUIRE(BINDABLE(target));
2240 	REQUIRE(target->offsets == NULL);
2241 
2242 	/*
2243 	 * Make 'target' empty in case of failure.
2244 	 */
2245 	MAKE_EMPTY(target);
2246 
2247 	target->ndata = isc_mem_get(mctx, source->length + source->labels);
2248 
2249 	memmove(target->ndata, source->ndata, source->length);
2250 
2251 	target->length = source->length;
2252 	target->labels = source->labels;
2253 	target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2254 			     DNS_NAMEATTR_READONLY;
2255 	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2256 		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2257 	}
2258 	target->offsets = target->ndata + source->length;
2259 	if (source->offsets != NULL) {
2260 		memmove(target->offsets, source->offsets, source->labels);
2261 	} else {
2262 		set_offsets(target, target->offsets, NULL);
2263 	}
2264 
2265 	return (ISC_R_SUCCESS);
2266 }
2267 
2268 void
dns_name_free(dns_name_t * name,isc_mem_t * mctx)2269 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2270 	size_t size;
2271 
2272 	/*
2273 	 * Free 'name'.
2274 	 */
2275 
2276 	REQUIRE(VALID_NAME(name));
2277 	REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2278 
2279 	size = name->length;
2280 	if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) {
2281 		size += name->labels;
2282 	}
2283 	isc_mem_put(mctx, name->ndata, size);
2284 	dns_name_invalidate(name);
2285 }
2286 
2287 isc_result_t
dns_name_digest(const dns_name_t * name,dns_digestfunc_t digest,void * arg)2288 dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2289 	dns_name_t downname;
2290 	unsigned char data[256];
2291 	isc_buffer_t buffer;
2292 	isc_result_t result;
2293 	isc_region_t r;
2294 
2295 	/*
2296 	 * Send 'name' in DNSSEC canonical form to 'digest'.
2297 	 */
2298 
2299 	REQUIRE(VALID_NAME(name));
2300 	REQUIRE(digest != NULL);
2301 
2302 #if defined(__clang__) && \
2303 	(__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2304 	memset(&downname, 0, sizeof(downname));
2305 #endif /* if defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == \
2306 	* 3                                                                    \
2307 	* && __clang_minor__ < 2)) */
2308 	DNS_NAME_INIT(&downname, NULL);
2309 
2310 	isc_buffer_init(&buffer, data, sizeof(data));
2311 
2312 	result = dns_name_downcase(name, &downname, &buffer);
2313 	if (result != ISC_R_SUCCESS) {
2314 		return (result);
2315 	}
2316 
2317 	isc_buffer_usedregion(&buffer, &r);
2318 
2319 	return ((digest)(arg, &r));
2320 }
2321 
2322 bool
dns_name_dynamic(const dns_name_t * name)2323 dns_name_dynamic(const dns_name_t *name) {
2324 	REQUIRE(VALID_NAME(name));
2325 
2326 	/*
2327 	 * Returns whether there is dynamic memory associated with this name.
2328 	 */
2329 
2330 	return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? true : false);
2331 }
2332 
2333 isc_result_t
dns_name_print(const dns_name_t * name,FILE * stream)2334 dns_name_print(const dns_name_t *name, FILE *stream) {
2335 	isc_result_t result;
2336 	isc_buffer_t b;
2337 	isc_region_t r;
2338 	char t[1024];
2339 
2340 	/*
2341 	 * Print 'name' on 'stream'.
2342 	 */
2343 
2344 	REQUIRE(VALID_NAME(name));
2345 
2346 	isc_buffer_init(&b, t, sizeof(t));
2347 	result = dns_name_totext(name, false, &b);
2348 	if (result != ISC_R_SUCCESS) {
2349 		return (result);
2350 	}
2351 	isc_buffer_usedregion(&b, &r);
2352 	fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2353 
2354 	return (ISC_R_SUCCESS);
2355 }
2356 
2357 isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t * proc)2358 dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
2359 	/*
2360 	 * If we already have been here set / clear as appropriate.
2361 	 */
2362 	if (totext_filter_proc != NULL && proc != NULL) {
2363 		if (totext_filter_proc == proc) {
2364 			return (ISC_R_SUCCESS);
2365 		}
2366 	}
2367 	if (proc == NULL && totext_filter_proc != NULL) {
2368 		totext_filter_proc = NULL;
2369 		return (ISC_R_SUCCESS);
2370 	}
2371 
2372 	totext_filter_proc = proc;
2373 
2374 	return (ISC_R_SUCCESS);
2375 }
2376 
2377 void
dns_name_format(const dns_name_t * name,char * cp,unsigned int size)2378 dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
2379 	isc_result_t result;
2380 	isc_buffer_t buf;
2381 
2382 	REQUIRE(size > 0);
2383 
2384 	/*
2385 	 * Leave room for null termination after buffer.
2386 	 */
2387 	isc_buffer_init(&buf, cp, size - 1);
2388 	result = dns_name_totext(name, true, &buf);
2389 	if (result == ISC_R_SUCCESS) {
2390 		isc_buffer_putuint8(&buf, (uint8_t)'\0');
2391 	} else {
2392 		snprintf(cp, size, "<unknown>");
2393 	}
2394 }
2395 
2396 /*
2397  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2398  * memory.
2399  */
2400 isc_result_t
dns_name_tostring(const dns_name_t * name,char ** target,isc_mem_t * mctx)2401 dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
2402 	isc_result_t result;
2403 	isc_buffer_t buf;
2404 	isc_region_t reg;
2405 	char *p, txt[DNS_NAME_FORMATSIZE];
2406 
2407 	REQUIRE(VALID_NAME(name));
2408 	REQUIRE(target != NULL && *target == NULL);
2409 
2410 	isc_buffer_init(&buf, txt, sizeof(txt));
2411 	result = dns_name_totext(name, false, &buf);
2412 	if (result != ISC_R_SUCCESS) {
2413 		return (result);
2414 	}
2415 
2416 	isc_buffer_usedregion(&buf, &reg);
2417 	p = isc_mem_allocate(mctx, reg.length + 1);
2418 	memmove(p, (char *)reg.base, (int)reg.length);
2419 	p[reg.length] = '\0';
2420 
2421 	*target = p;
2422 	return (ISC_R_SUCCESS);
2423 }
2424 
2425 /*
2426  * dns_name_fromstring() -- convert directly from a string to a name,
2427  * allocating memory as needed
2428  */
2429 isc_result_t
dns_name_fromstring(dns_name_t * target,const char * src,unsigned int options,isc_mem_t * mctx)2430 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2431 		    isc_mem_t *mctx) {
2432 	return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2433 }
2434 
2435 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)2436 dns_name_fromstring2(dns_name_t *target, const char *src,
2437 		     const dns_name_t *origin, unsigned int options,
2438 		     isc_mem_t *mctx) {
2439 	isc_result_t result;
2440 	isc_buffer_t buf;
2441 	dns_fixedname_t fn;
2442 	dns_name_t *name;
2443 
2444 	REQUIRE(src != NULL);
2445 
2446 	isc_buffer_constinit(&buf, src, strlen(src));
2447 	isc_buffer_add(&buf, strlen(src));
2448 	if (BINDABLE(target) && target->buffer != NULL) {
2449 		name = target;
2450 	} else {
2451 		name = dns_fixedname_initname(&fn);
2452 	}
2453 
2454 	result = dns_name_fromtext(name, &buf, origin, options, NULL);
2455 	if (result != ISC_R_SUCCESS) {
2456 		return (result);
2457 	}
2458 
2459 	if (name != target) {
2460 		result = dns_name_dupwithoffsets(name, mctx, target);
2461 	}
2462 	return (result);
2463 }
2464 
2465 void
dns_name_copy(const dns_name_t * source,dns_name_t * dest)2466 dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
2467 	isc_buffer_t *target = NULL;
2468 	unsigned char *ndata = NULL;
2469 
2470 	REQUIRE(VALID_NAME(source));
2471 	REQUIRE(VALID_NAME(dest));
2472 	REQUIRE(BINDABLE(dest));
2473 
2474 	target = dest->buffer;
2475 
2476 	REQUIRE(target != NULL);
2477 	REQUIRE(target->length >= source->length);
2478 
2479 	isc_buffer_clear(target);
2480 
2481 	ndata = (unsigned char *)target->base;
2482 	dest->ndata = target->base;
2483 
2484 	if (source->length != 0) {
2485 		memmove(ndata, source->ndata, source->length);
2486 	}
2487 
2488 	dest->ndata = ndata;
2489 	dest->labels = source->labels;
2490 	dest->length = source->length;
2491 	if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2492 		dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2493 	} else {
2494 		dest->attributes = 0;
2495 	}
2496 
2497 	if (dest->labels > 0 && dest->offsets != NULL) {
2498 		if (source->offsets != NULL && source->labels != 0) {
2499 			memmove(dest->offsets, source->offsets, source->labels);
2500 		} else {
2501 			set_offsets(dest, dest->offsets, NULL);
2502 		}
2503 	}
2504 
2505 	isc_buffer_add(target, dest->length);
2506 }
2507 
2508 /*
2509  * Service Discovery Prefixes RFC 6763.
2510  */
2511 static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
2512 static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
2513 static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
2514 static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
2515 static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
2516 static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
2517 static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
2518 static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
2519 static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
2520 static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
2521 
2522 static dns_name_t const dns_sd[] = {
2523 	DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
2524 	DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
2525 	DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
2526 	DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
2527 	DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
2528 };
2529 
2530 bool
dns_name_isdnssd(const dns_name_t * name)2531 dns_name_isdnssd(const dns_name_t *name) {
2532 	size_t i;
2533 	dns_name_t prefix;
2534 
2535 	if (dns_name_countlabels(name) > 3U) {
2536 		dns_name_init(&prefix, NULL);
2537 		dns_name_getlabelsequence(name, 0, 3, &prefix);
2538 		for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
2539 			if (dns_name_equal(&prefix, &dns_sd[i])) {
2540 				return (true);
2541 			}
2542 		}
2543 	}
2544 
2545 	return (false);
2546 }
2547 
2548 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
2549 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
2550 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
2551 
2552 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
2553 
2554 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
2555 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
2556 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
2557 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
2558 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
2559 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
2560 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
2561 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
2562 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
2563 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
2564 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
2565 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
2566 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
2567 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
2568 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
2569 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
2570 
2571 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
2572 
2573 static dns_name_t const rfc1918names[] = {
2574 	DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
2575 	DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
2576 	DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
2577 	DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
2578 	DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
2579 	DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
2580 	DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
2581 	DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
2582 	DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
2583 	DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
2584 	DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
2585 	DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
2586 	DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
2587 	DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
2588 	DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
2589 	DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
2590 	DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
2591 	DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
2592 };
2593 
2594 bool
dns_name_isrfc1918(const dns_name_t * name)2595 dns_name_isrfc1918(const dns_name_t *name) {
2596 	size_t i;
2597 
2598 	for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
2599 		if (dns_name_issubdomain(name, &rfc1918names[i])) {
2600 			return (true);
2601 		}
2602 	}
2603 	return (false);
2604 }
2605 
2606 static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
2607 static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
2608 static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
2609 
2610 static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
2611 				       DNS_NAME_INITABSOLUTE(ip6fd,
2612 							     ulaoffsets) };
2613 
2614 bool
dns_name_isula(const dns_name_t * name)2615 dns_name_isula(const dns_name_t *name) {
2616 	size_t i;
2617 
2618 	for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
2619 		if (dns_name_issubdomain(name, &ulanames[i])) {
2620 			return (true);
2621 		}
2622 	}
2623 	return (false);
2624 }
2625 
2626 /*
2627  * Use a simple table as we don't want all the locale stuff
2628  * associated with ishexdigit().
2629  */
2630 const char ishex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2631 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2632 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2633 			  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2634 			  0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2635 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2636 			  0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2637 			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2638 
2639 bool
dns_name_istat(const dns_name_t * name)2640 dns_name_istat(const dns_name_t *name) {
2641 	unsigned char len;
2642 	const unsigned char *ndata;
2643 
2644 	REQUIRE(VALID_NAME(name));
2645 
2646 	if (name->labels < 1) {
2647 		return (false);
2648 	}
2649 
2650 	ndata = name->ndata;
2651 	len = ndata[0];
2652 	INSIST(len <= name->length);
2653 	ndata++;
2654 
2655 	/*
2656 	 * Is there at least one trust anchor reported and is the
2657 	 * label length consistent with a trust-anchor-telemetry label.
2658 	 */
2659 	if ((len < 8) || (len - 3) % 5 != 0) {
2660 		return (false);
2661 	}
2662 
2663 	if (ndata[0] != '_' || maptolower[ndata[1]] != 't' ||
2664 	    maptolower[ndata[2]] != 'a')
2665 	{
2666 		return (false);
2667 	}
2668 	ndata += 3;
2669 	len -= 3;
2670 
2671 	while (len > 0) {
2672 		INSIST(len >= 5);
2673 		if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] ||
2674 		    !ishex[ndata[3]] || !ishex[ndata[4]])
2675 		{
2676 			return (false);
2677 		}
2678 		ndata += 5;
2679 		len -= 5;
2680 	}
2681 	return (true);
2682 }
2683