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