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