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, ®);
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