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