1 /* $NetBSD: name.c,v 1.12 2023/01/25 21:43:30 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 }
194
195 bool
dns_name_isvalid(const dns_name_t * name)196 dns_name_isvalid(const dns_name_t *name) {
197 unsigned char *ndata, *offsets;
198 unsigned int offset, count, length, nlabels;
199
200 if (!VALID_NAME(name)) {
201 return (false);
202 }
203
204 if (name->length > 255U || name->labels > 127U) {
205 return (false);
206 }
207
208 ndata = name->ndata;
209 length = name->length;
210 offsets = name->offsets;
211 offset = 0;
212 nlabels = 0;
213
214 while (offset != length) {
215 count = *ndata;
216 if (count > 63U) {
217 return (false);
218 }
219 if (offsets != NULL && offsets[nlabels] != offset) {
220 return (false);
221 }
222
223 nlabels++;
224 offset += count + 1;
225 ndata += count + 1;
226 if (offset > length) {
227 return (false);
228 }
229
230 if (count == 0) {
231 break;
232 }
233 }
234
235 if (nlabels != name->labels || offset != name->length) {
236 return (false);
237 }
238
239 return (true);
240 }
241
242 void
dns_name_setbuffer(dns_name_t * name,isc_buffer_t * buffer)243 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
244 /*
245 * Dedicate a buffer for use with 'name'.
246 */
247
248 REQUIRE(VALID_NAME(name));
249 REQUIRE((buffer != NULL && name->buffer == NULL) || (buffer == NULL));
250
251 name->buffer = buffer;
252 }
253
254 bool
dns_name_hasbuffer(const dns_name_t * name)255 dns_name_hasbuffer(const dns_name_t *name) {
256 /*
257 * Does 'name' have a dedicated buffer?
258 */
259
260 REQUIRE(VALID_NAME(name));
261
262 if (name->buffer != NULL) {
263 return (true);
264 }
265
266 return (false);
267 }
268
269 bool
dns_name_isabsolute(const dns_name_t * name)270 dns_name_isabsolute(const dns_name_t *name) {
271 /*
272 * Does 'name' end in the root label?
273 */
274
275 REQUIRE(VALID_NAME(name));
276
277 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
278 return (true);
279 }
280 return (false);
281 }
282
283 #define hyphenchar(c) ((c) == 0x2d)
284 #define asterchar(c) ((c) == 0x2a)
285 #define alphachar(c) \
286 (((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a))
287 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
288 #define borderchar(c) (alphachar(c) || digitchar(c))
289 #define middlechar(c) (borderchar(c) || hyphenchar(c))
290 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
291
292 bool
dns_name_ismailbox(const dns_name_t * name)293 dns_name_ismailbox(const dns_name_t *name) {
294 unsigned char *ndata, ch;
295 unsigned int n;
296 bool first;
297
298 REQUIRE(VALID_NAME(name));
299 REQUIRE(name->labels > 0);
300 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
301
302 /*
303 * Root label.
304 */
305 if (name->length == 1) {
306 return (true);
307 }
308
309 ndata = name->ndata;
310 n = *ndata++;
311 INSIST(n <= 63);
312 while (n--) {
313 ch = *ndata++;
314 if (!domainchar(ch)) {
315 return (false);
316 }
317 }
318
319 if (ndata == name->ndata + name->length) {
320 return (false);
321 }
322
323 /*
324 * RFC952/RFC1123 hostname.
325 */
326 while (ndata < (name->ndata + name->length)) {
327 n = *ndata++;
328 INSIST(n <= 63);
329 first = true;
330 while (n--) {
331 ch = *ndata++;
332 if (first || n == 0) {
333 if (!borderchar(ch)) {
334 return (false);
335 }
336 } else {
337 if (!middlechar(ch)) {
338 return (false);
339 }
340 }
341 first = false;
342 }
343 }
344 return (true);
345 }
346
347 bool
dns_name_ishostname(const dns_name_t * name,bool wildcard)348 dns_name_ishostname(const dns_name_t *name, bool wildcard) {
349 unsigned char *ndata, ch;
350 unsigned int n;
351 bool first;
352
353 REQUIRE(VALID_NAME(name));
354 REQUIRE(name->labels > 0);
355 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
356
357 /*
358 * Root label.
359 */
360 if (name->length == 1) {
361 return (true);
362 }
363
364 /*
365 * Skip wildcard if this is a ownername.
366 */
367 ndata = name->ndata;
368 if (wildcard && ndata[0] == 1 && ndata[1] == '*') {
369 ndata += 2;
370 }
371
372 /*
373 * RFC292/RFC1123 hostname.
374 */
375 while (ndata < (name->ndata + name->length)) {
376 n = *ndata++;
377 INSIST(n <= 63);
378 first = true;
379 while (n--) {
380 ch = *ndata++;
381 if (first || n == 0) {
382 if (!borderchar(ch)) {
383 return (false);
384 }
385 } else {
386 if (!middlechar(ch)) {
387 return (false);
388 }
389 }
390 first = false;
391 }
392 }
393 return (true);
394 }
395
396 bool
dns_name_iswildcard(const dns_name_t * name)397 dns_name_iswildcard(const dns_name_t *name) {
398 unsigned char *ndata;
399
400 /*
401 * Is 'name' a wildcard name?
402 */
403
404 REQUIRE(VALID_NAME(name));
405 REQUIRE(name->labels > 0);
406
407 if (name->length >= 2) {
408 ndata = name->ndata;
409 if (ndata[0] == 1 && ndata[1] == '*') {
410 return (true);
411 }
412 }
413
414 return (false);
415 }
416
417 bool
dns_name_internalwildcard(const dns_name_t * name)418 dns_name_internalwildcard(const dns_name_t *name) {
419 unsigned char *ndata;
420 unsigned int count;
421 unsigned int label;
422
423 /*
424 * Does 'name' contain a internal wildcard?
425 */
426
427 REQUIRE(VALID_NAME(name));
428 REQUIRE(name->labels > 0);
429
430 /*
431 * Skip first label.
432 */
433 ndata = name->ndata;
434 count = *ndata++;
435 INSIST(count <= 63);
436 ndata += count;
437 label = 1;
438 /*
439 * Check all but the last of the remaining labels.
440 */
441 while (label + 1 < name->labels) {
442 count = *ndata++;
443 INSIST(count <= 63);
444 if (count == 1 && *ndata == '*') {
445 return (true);
446 }
447 ndata += count;
448 label++;
449 }
450 return (false);
451 }
452
453 unsigned int
dns_name_hash(const dns_name_t * name,bool case_sensitive)454 dns_name_hash(const dns_name_t *name, bool case_sensitive) {
455 unsigned int length;
456
457 /*
458 * Provide a hash value for 'name'.
459 */
460 REQUIRE(VALID_NAME(name));
461
462 if (name->labels == 0) {
463 return (0);
464 }
465
466 length = name->length;
467 if (length > 16) {
468 length = 16;
469 }
470
471 /* High bits are more random. */
472 return (isc_hash32(name->ndata, length, case_sensitive));
473 }
474
475 unsigned int
dns_name_fullhash(const dns_name_t * name,bool case_sensitive)476 dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
477 /*
478 * Provide a hash value for 'name'.
479 */
480 REQUIRE(VALID_NAME(name));
481
482 if (name->labels == 0) {
483 return (0);
484 }
485
486 /* High bits are more random. */
487 return (isc_hash32(name->ndata, name->length, case_sensitive));
488 }
489
490 dns_namereln_t
dns_name_fullcompare(const dns_name_t * name1,const dns_name_t * name2,int * orderp,unsigned int * nlabelsp)491 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
492 int *orderp, unsigned int *nlabelsp) {
493 unsigned int l1, l2, l, count1, count2, count, nlabels;
494 int cdiff, ldiff, chdiff;
495 unsigned char *label1, *label2;
496 unsigned char *offsets1, *offsets2;
497 dns_offsets_t odata1, odata2;
498 dns_namereln_t namereln = dns_namereln_none;
499
500 /*
501 * Determine the relative ordering under the DNSSEC order relation of
502 * 'name1' and 'name2', and also determine the hierarchical
503 * relationship of the names.
504 *
505 * Note: It makes no sense for one of the names to be relative and the
506 * other absolute. If both names are relative, then to be meaningfully
507 * compared the caller must ensure that they are both relative to the
508 * same domain.
509 */
510
511 REQUIRE(VALID_NAME(name1));
512 REQUIRE(VALID_NAME(name2));
513 REQUIRE(orderp != NULL);
514 REQUIRE(nlabelsp != NULL);
515 /*
516 * Either name1 is absolute and name2 is absolute, or neither is.
517 */
518 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
519 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
520
521 if (ISC_UNLIKELY(name1 == name2)) {
522 *orderp = 0;
523 *nlabelsp = name1->labels;
524 return (dns_namereln_equal);
525 }
526
527 SETUP_OFFSETS(name1, offsets1, odata1);
528 SETUP_OFFSETS(name2, offsets2, odata2);
529
530 nlabels = 0;
531 l1 = name1->labels;
532 l2 = name2->labels;
533 if (l2 > l1) {
534 l = l1;
535 ldiff = 0 - (l2 - l1);
536 } else {
537 l = l2;
538 ldiff = l1 - l2;
539 }
540
541 offsets1 += l1;
542 offsets2 += l2;
543
544 while (ISC_LIKELY(l > 0)) {
545 l--;
546 offsets1--;
547 offsets2--;
548 label1 = &name1->ndata[*offsets1];
549 label2 = &name2->ndata[*offsets2];
550 count1 = *label1++;
551 count2 = *label2++;
552
553 /*
554 * We dropped bitstring labels, and we don't support any
555 * other extended label types.
556 */
557 INSIST(count1 <= 63 && count2 <= 63);
558
559 cdiff = (int)count1 - (int)count2;
560 if (cdiff < 0) {
561 count = count1;
562 } else {
563 count = count2;
564 }
565
566 /* Loop unrolled for performance */
567 while (ISC_LIKELY(count > 3)) {
568 chdiff = (int)maptolower[label1[0]] -
569 (int)maptolower[label2[0]];
570 if (chdiff != 0) {
571 *orderp = chdiff;
572 goto done;
573 }
574 chdiff = (int)maptolower[label1[1]] -
575 (int)maptolower[label2[1]];
576 if (chdiff != 0) {
577 *orderp = chdiff;
578 goto done;
579 }
580 chdiff = (int)maptolower[label1[2]] -
581 (int)maptolower[label2[2]];
582 if (chdiff != 0) {
583 *orderp = chdiff;
584 goto done;
585 }
586 chdiff = (int)maptolower[label1[3]] -
587 (int)maptolower[label2[3]];
588 if (chdiff != 0) {
589 *orderp = chdiff;
590 goto done;
591 }
592 count -= 4;
593 label1 += 4;
594 label2 += 4;
595 }
596 while (ISC_LIKELY(count-- > 0)) {
597 chdiff = (int)maptolower[*label1++] -
598 (int)maptolower[*label2++];
599 if (chdiff != 0) {
600 *orderp = chdiff;
601 goto done;
602 }
603 }
604 if (cdiff != 0) {
605 *orderp = cdiff;
606 goto done;
607 }
608 nlabels++;
609 }
610
611 *orderp = ldiff;
612 if (ldiff < 0) {
613 namereln = dns_namereln_contains;
614 } else if (ldiff > 0) {
615 namereln = dns_namereln_subdomain;
616 } else {
617 namereln = dns_namereln_equal;
618 }
619 *nlabelsp = nlabels;
620 return (namereln);
621
622 done:
623 *nlabelsp = nlabels;
624 if (nlabels > 0) {
625 namereln = dns_namereln_commonancestor;
626 }
627
628 return (namereln);
629 }
630
631 int
dns_name_compare(const dns_name_t * name1,const dns_name_t * name2)632 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
633 int order;
634 unsigned int nlabels;
635
636 /*
637 * Determine the relative ordering under the DNSSEC order relation of
638 * 'name1' and 'name2'.
639 *
640 * Note: It makes no sense for one of the names to be relative and the
641 * other absolute. If both names are relative, then to be meaningfully
642 * compared the caller must ensure that they are both relative to the
643 * same domain.
644 */
645
646 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
647
648 return (order);
649 }
650
651 bool
dns_name_equal(const dns_name_t * name1,const dns_name_t * name2)652 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
653 unsigned int l, count;
654 unsigned char c;
655 unsigned char *label1, *label2;
656
657 /*
658 * Are 'name1' and 'name2' equal?
659 *
660 * Note: It makes no sense for one of the names to be relative and the
661 * other absolute. If both names are relative, then to be meaningfully
662 * compared the caller must ensure that they are both relative to the
663 * same domain.
664 */
665
666 REQUIRE(VALID_NAME(name1));
667 REQUIRE(VALID_NAME(name2));
668 /*
669 * Either name1 is absolute and name2 is absolute, or neither is.
670 */
671 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
672 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
673
674 if (ISC_UNLIKELY(name1 == name2)) {
675 return (true);
676 }
677
678 if (name1->length != name2->length) {
679 return (false);
680 }
681
682 l = name1->labels;
683
684 if (l != name2->labels) {
685 return (false);
686 }
687
688 label1 = name1->ndata;
689 label2 = name2->ndata;
690 while (ISC_LIKELY(l-- > 0)) {
691 count = *label1++;
692 if (count != *label2++) {
693 return (false);
694 }
695
696 INSIST(count <= 63); /* no bitstring support */
697
698 /* Loop unrolled for performance */
699 while (ISC_LIKELY(count > 3)) {
700 c = maptolower[label1[0]];
701 if (c != maptolower[label2[0]]) {
702 return (false);
703 }
704 c = maptolower[label1[1]];
705 if (c != maptolower[label2[1]]) {
706 return (false);
707 }
708 c = maptolower[label1[2]];
709 if (c != maptolower[label2[2]]) {
710 return (false);
711 }
712 c = maptolower[label1[3]];
713 if (c != maptolower[label2[3]]) {
714 return (false);
715 }
716 count -= 4;
717 label1 += 4;
718 label2 += 4;
719 }
720 while (ISC_LIKELY(count-- > 0)) {
721 c = maptolower[*label1++];
722 if (c != maptolower[*label2++]) {
723 return (false);
724 }
725 }
726 }
727
728 return (true);
729 }
730
731 bool
dns_name_caseequal(const dns_name_t * name1,const dns_name_t * name2)732 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
733 /*
734 * Are 'name1' and 'name2' equal?
735 *
736 * Note: It makes no sense for one of the names to be relative and the
737 * other absolute. If both names are relative, then to be meaningfully
738 * compared the caller must ensure that they are both relative to the
739 * same domain.
740 */
741
742 REQUIRE(VALID_NAME(name1));
743 REQUIRE(VALID_NAME(name2));
744 /*
745 * Either name1 is absolute and name2 is absolute, or neither is.
746 */
747 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
748 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
749
750 if (name1->length != name2->length) {
751 return (false);
752 }
753
754 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
755 return (false);
756 }
757
758 return (true);
759 }
760
761 int
dns_name_rdatacompare(const dns_name_t * name1,const dns_name_t * name2)762 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
763 unsigned int l1, l2, l, count1, count2, count;
764 unsigned char c1, c2;
765 unsigned char *label1, *label2;
766
767 /*
768 * Compare two absolute names as rdata.
769 */
770
771 REQUIRE(VALID_NAME(name1));
772 REQUIRE(name1->labels > 0);
773 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
774 REQUIRE(VALID_NAME(name2));
775 REQUIRE(name2->labels > 0);
776 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
777
778 l1 = name1->labels;
779 l2 = name2->labels;
780
781 l = (l1 < l2) ? l1 : l2;
782
783 label1 = name1->ndata;
784 label2 = name2->ndata;
785 while (l > 0) {
786 l--;
787 count1 = *label1++;
788 count2 = *label2++;
789
790 /* no bitstring support */
791 INSIST(count1 <= 63 && count2 <= 63);
792
793 if (count1 != count2) {
794 return ((count1 < count2) ? -1 : 1);
795 }
796 count = count1;
797 while (count > 0) {
798 count--;
799 c1 = maptolower[*label1++];
800 c2 = maptolower[*label2++];
801 if (c1 < c2) {
802 return (-1);
803 } else if (c1 > c2) {
804 return (1);
805 }
806 }
807 }
808
809 /*
810 * If one name had more labels than the other, their common
811 * prefix must have been different because the shorter name
812 * ended with the root label and the longer one can't have
813 * a root label in the middle of it. Therefore, if we get
814 * to this point, the lengths must be equal.
815 */
816 INSIST(l1 == l2);
817
818 return (0);
819 }
820
821 bool
dns_name_issubdomain(const dns_name_t * name1,const dns_name_t * name2)822 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
823 int order;
824 unsigned int nlabels;
825 dns_namereln_t namereln;
826
827 /*
828 * Is 'name1' a subdomain of 'name2'?
829 *
830 * Note: It makes no sense for one of the names to be relative and the
831 * other absolute. If both names are relative, then to be meaningfully
832 * compared the caller must ensure that they are both relative to the
833 * same domain.
834 */
835
836 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
837 if (namereln == dns_namereln_subdomain ||
838 namereln == dns_namereln_equal)
839 {
840 return (true);
841 }
842
843 return (false);
844 }
845
846 bool
dns_name_matcheswildcard(const dns_name_t * name,const dns_name_t * wname)847 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
848 int order;
849 unsigned int nlabels, labels;
850 dns_name_t tname;
851
852 REQUIRE(VALID_NAME(name));
853 REQUIRE(name->labels > 0);
854 REQUIRE(VALID_NAME(wname));
855 labels = wname->labels;
856 REQUIRE(labels > 0);
857 REQUIRE(dns_name_iswildcard(wname));
858
859 DNS_NAME_INIT(&tname, NULL);
860 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
861 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
862 dns_namereln_subdomain)
863 {
864 return (true);
865 }
866 return (false);
867 }
868
869 unsigned int
dns_name_countlabels(const dns_name_t * name)870 dns_name_countlabels(const dns_name_t *name) {
871 /*
872 * How many labels does 'name' have?
873 */
874
875 REQUIRE(VALID_NAME(name));
876
877 ENSURE(name->labels <= 128);
878
879 return (name->labels);
880 }
881
882 void
dns_name_getlabel(const dns_name_t * name,unsigned int n,dns_label_t * label)883 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
884 unsigned char *offsets;
885 dns_offsets_t odata;
886
887 /*
888 * Make 'label' refer to the 'n'th least significant label of 'name'.
889 */
890
891 REQUIRE(VALID_NAME(name));
892 REQUIRE(name->labels > 0);
893 REQUIRE(n < name->labels);
894 REQUIRE(label != NULL);
895
896 SETUP_OFFSETS(name, offsets, odata);
897
898 label->base = &name->ndata[offsets[n]];
899 if (n == name->labels - 1) {
900 label->length = name->length - offsets[n];
901 } else {
902 label->length = offsets[n + 1] - offsets[n];
903 }
904 }
905
906 void
dns_name_getlabelsequence(const dns_name_t * source,unsigned int first,unsigned int n,dns_name_t * target)907 dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
908 unsigned int n, dns_name_t *target) {
909 unsigned char *p, l;
910 unsigned int firstoffset, endoffset;
911 unsigned int i;
912
913 /*
914 * Make 'target' refer to the 'n' labels including and following
915 * 'first' in 'source'.
916 */
917
918 REQUIRE(VALID_NAME(source));
919 REQUIRE(VALID_NAME(target));
920 REQUIRE(first <= source->labels);
921 REQUIRE(n <= source->labels - first); /* note first+n could overflow */
922 REQUIRE(BINDABLE(target));
923
924 p = source->ndata;
925 if (ISC_UNLIKELY(first == source->labels)) {
926 firstoffset = source->length;
927 } else {
928 for (i = 0; i < first; i++) {
929 l = *p;
930 p += l + 1;
931 }
932 firstoffset = (unsigned int)(p - source->ndata);
933 }
934
935 if (ISC_LIKELY(first + n == source->labels)) {
936 endoffset = source->length;
937 } else {
938 for (i = 0; i < n; i++) {
939 l = *p;
940 p += l + 1;
941 }
942 endoffset = (unsigned int)(p - source->ndata);
943 }
944
945 target->ndata = &source->ndata[firstoffset];
946 target->length = endoffset - firstoffset;
947
948 if (first + n == source->labels && n > 0 &&
949 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
950 {
951 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
952 } else {
953 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
954 }
955
956 target->labels = n;
957
958 /*
959 * If source and target are the same, and we're making target
960 * a prefix of source, the offsets table is correct already
961 * so we don't need to call set_offsets().
962 */
963 if (target->offsets != NULL && (target != source || first != 0)) {
964 set_offsets(target, target->offsets, NULL);
965 }
966 }
967
968 void
dns_name_clone(const dns_name_t * source,dns_name_t * target)969 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
970 /*
971 * Make 'target' refer to the same name as 'source'.
972 */
973
974 REQUIRE(VALID_NAME(source));
975 REQUIRE(VALID_NAME(target));
976 REQUIRE(BINDABLE(target));
977
978 target->ndata = source->ndata;
979 target->length = source->length;
980 target->labels = source->labels;
981 target->attributes = source->attributes &
982 (unsigned int)~(DNS_NAMEATTR_READONLY |
983 DNS_NAMEATTR_DYNAMIC |
984 DNS_NAMEATTR_DYNOFFSETS);
985 if (target->offsets != NULL && source->labels > 0) {
986 if (source->offsets != NULL) {
987 memmove(target->offsets, source->offsets,
988 source->labels);
989 } else {
990 set_offsets(target, target->offsets, NULL);
991 }
992 }
993 }
994
995 void
dns_name_fromregion(dns_name_t * name,const isc_region_t * r)996 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
997 unsigned char *offsets;
998 dns_offsets_t odata;
999 unsigned int len;
1000 isc_region_t r2;
1001
1002 /*
1003 * Make 'name' refer to region 'r'.
1004 */
1005
1006 REQUIRE(VALID_NAME(name));
1007 REQUIRE(r != NULL);
1008 REQUIRE(BINDABLE(name));
1009
1010 INIT_OFFSETS(name, offsets, odata);
1011
1012 if (name->buffer != NULL) {
1013 isc_buffer_clear(name->buffer);
1014 isc_buffer_availableregion(name->buffer, &r2);
1015 len = (r->length < r2.length) ? r->length : r2.length;
1016 if (len > DNS_NAME_MAXWIRE) {
1017 len = DNS_NAME_MAXWIRE;
1018 }
1019 if (len != 0) {
1020 memmove(r2.base, r->base, len);
1021 }
1022 name->ndata = r2.base;
1023 name->length = len;
1024 } else {
1025 name->ndata = r->base;
1026 name->length = (r->length <= DNS_NAME_MAXWIRE)
1027 ? r->length
1028 : DNS_NAME_MAXWIRE;
1029 }
1030
1031 if (r->length > 0) {
1032 set_offsets(name, offsets, name);
1033 } else {
1034 name->labels = 0;
1035 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1036 }
1037
1038 if (name->buffer != NULL) {
1039 isc_buffer_add(name->buffer, name->length);
1040 }
1041 }
1042
1043 void
dns_name_toregion(const dns_name_t * name,isc_region_t * r)1044 dns_name_toregion(const dns_name_t *name, isc_region_t *r) {
1045 /*
1046 * Make 'r' refer to 'name'.
1047 */
1048
1049 REQUIRE(VALID_NAME(name));
1050 REQUIRE(r != NULL);
1051
1052 DNS_NAME_TOREGION(name, r);
1053 }
1054
1055 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)1056 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1057 const dns_name_t *origin, unsigned int options,
1058 isc_buffer_t *target) {
1059 unsigned char *ndata, *label = NULL;
1060 char *tdata;
1061 char c;
1062 ft_state state;
1063 unsigned int value = 0, count = 0;
1064 unsigned int n1 = 0, n2 = 0;
1065 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1066 bool done;
1067 unsigned char *offsets;
1068 dns_offsets_t odata;
1069 bool downcase;
1070
1071 /*
1072 * Convert the textual representation of a DNS name at source
1073 * into uncompressed wire form stored in target.
1074 *
1075 * Notes:
1076 * Relative domain names will have 'origin' appended to them
1077 * unless 'origin' is NULL, in which case relative domain names
1078 * will remain relative.
1079 */
1080
1081 REQUIRE(VALID_NAME(name));
1082 REQUIRE(ISC_BUFFER_VALID(source));
1083 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1084 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1085
1086 downcase = ((options & DNS_NAME_DOWNCASE) != 0);
1087
1088 if (target == NULL && name->buffer != NULL) {
1089 target = name->buffer;
1090 isc_buffer_clear(target);
1091 }
1092
1093 REQUIRE(BINDABLE(name));
1094
1095 INIT_OFFSETS(name, offsets, odata);
1096 offsets[0] = 0;
1097
1098 /*
1099 * Make 'name' empty in case of failure.
1100 */
1101 MAKE_EMPTY(name);
1102
1103 /*
1104 * Set up the state machine.
1105 */
1106 tdata = (char *)source->base + source->current;
1107 tlen = isc_buffer_remaininglength(source);
1108 tused = 0;
1109 ndata = isc_buffer_used(target);
1110 nrem = isc_buffer_availablelength(target);
1111 if (nrem > 255) {
1112 nrem = 255;
1113 }
1114 nused = 0;
1115 labels = 0;
1116 done = false;
1117 state = ft_init;
1118
1119 while (nrem > 0 && tlen > 0 && !done) {
1120 c = *tdata++;
1121 tlen--;
1122 tused++;
1123
1124 switch (state) {
1125 case ft_init:
1126 /*
1127 * Is this the root name?
1128 */
1129 if (c == '.') {
1130 if (tlen != 0) {
1131 return (DNS_R_EMPTYLABEL);
1132 }
1133 labels++;
1134 *ndata++ = 0;
1135 nrem--;
1136 nused++;
1137 done = true;
1138 break;
1139 }
1140 if (c == '@' && tlen == 0) {
1141 state = ft_at;
1142 break;
1143 }
1144
1145 FALLTHROUGH;
1146 case ft_start:
1147 label = ndata;
1148 ndata++;
1149 nrem--;
1150 nused++;
1151 count = 0;
1152 if (c == '\\') {
1153 state = ft_initialescape;
1154 break;
1155 }
1156 state = ft_ordinary;
1157 if (nrem == 0) {
1158 return (ISC_R_NOSPACE);
1159 }
1160 FALLTHROUGH;
1161 case ft_ordinary:
1162 if (c == '.') {
1163 if (count == 0) {
1164 return (DNS_R_EMPTYLABEL);
1165 }
1166 *label = count;
1167 labels++;
1168 INSIST(labels <= 127);
1169 offsets[labels] = nused;
1170 if (tlen == 0) {
1171 labels++;
1172 *ndata++ = 0;
1173 nrem--;
1174 nused++;
1175 done = true;
1176 }
1177 state = ft_start;
1178 } else if (c == '\\') {
1179 state = ft_escape;
1180 } else {
1181 if (count >= 63) {
1182 return (DNS_R_LABELTOOLONG);
1183 }
1184 count++;
1185 CONVERTTOASCII(c);
1186 if (downcase) {
1187 c = maptolower[c & 0xff];
1188 }
1189 *ndata++ = c;
1190 nrem--;
1191 nused++;
1192 }
1193 break;
1194 case ft_initialescape:
1195 if (c == '[') {
1196 /*
1197 * This looks like a bitstring label, which
1198 * was deprecated. Intentionally drop it.
1199 */
1200 return (DNS_R_BADLABELTYPE);
1201 }
1202 state = ft_escape;
1203 POST(state);
1204 FALLTHROUGH;
1205 case ft_escape:
1206 if (!isdigit((unsigned char)c)) {
1207 if (count >= 63) {
1208 return (DNS_R_LABELTOOLONG);
1209 }
1210 count++;
1211 CONVERTTOASCII(c);
1212 if (downcase) {
1213 c = maptolower[c & 0xff];
1214 }
1215 *ndata++ = c;
1216 nrem--;
1217 nused++;
1218 state = ft_ordinary;
1219 break;
1220 }
1221 digits = 0;
1222 value = 0;
1223 state = ft_escdecimal;
1224 FALLTHROUGH;
1225 case ft_escdecimal:
1226 if (!isdigit((unsigned char)c)) {
1227 return (DNS_R_BADESCAPE);
1228 }
1229 value *= 10;
1230 value += digitvalue[c & 0xff];
1231 digits++;
1232 if (digits == 3) {
1233 if (value > 255) {
1234 return (DNS_R_BADESCAPE);
1235 }
1236 if (count >= 63) {
1237 return (DNS_R_LABELTOOLONG);
1238 }
1239 count++;
1240 if (downcase) {
1241 value = maptolower[value];
1242 }
1243 *ndata++ = value;
1244 nrem--;
1245 nused++;
1246 state = ft_ordinary;
1247 }
1248 break;
1249 default:
1250 FATAL_ERROR(__FILE__, __LINE__, "Unexpected state %d",
1251 state);
1252 /* Does not return. */
1253 }
1254 }
1255
1256 if (!done) {
1257 if (nrem == 0) {
1258 return (ISC_R_NOSPACE);
1259 }
1260 INSIST(tlen == 0);
1261 if (state != ft_ordinary && state != ft_at) {
1262 return (ISC_R_UNEXPECTEDEND);
1263 }
1264 if (state == ft_ordinary) {
1265 INSIST(count != 0);
1266 INSIST(label != NULL);
1267 *label = count;
1268 labels++;
1269 INSIST(labels <= 127);
1270 offsets[labels] = nused;
1271 }
1272 if (origin != NULL) {
1273 if (nrem < origin->length) {
1274 return (ISC_R_NOSPACE);
1275 }
1276 label = origin->ndata;
1277 n1 = origin->length;
1278 nrem -= n1;
1279 POST(nrem);
1280 while (n1 > 0) {
1281 n2 = *label++;
1282 INSIST(n2 <= 63); /* no bitstring support */
1283 *ndata++ = n2;
1284 n1 -= n2 + 1;
1285 nused += n2 + 1;
1286 while (n2 > 0) {
1287 c = *label++;
1288 if (downcase) {
1289 c = maptolower[c & 0xff];
1290 }
1291 *ndata++ = c;
1292 n2--;
1293 }
1294 labels++;
1295 if (n1 > 0) {
1296 INSIST(labels <= 127);
1297 offsets[labels] = nused;
1298 }
1299 }
1300 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1301 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1302 }
1303 }
1304 } else {
1305 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1306 }
1307
1308 name->ndata = (unsigned char *)target->base + target->used;
1309 name->labels = labels;
1310 name->length = nused;
1311
1312 isc_buffer_forward(source, tused);
1313 isc_buffer_add(target, name->length);
1314
1315 return (ISC_R_SUCCESS);
1316 }
1317
1318 isc_result_t
dns_name_totext(const dns_name_t * name,bool omit_final_dot,isc_buffer_t * target)1319 dns_name_totext(const dns_name_t *name, bool omit_final_dot,
1320 isc_buffer_t *target) {
1321 unsigned int options = DNS_NAME_MASTERFILE;
1322
1323 if (omit_final_dot) {
1324 options |= DNS_NAME_OMITFINALDOT;
1325 }
1326 return (dns_name_totext2(name, options, target));
1327 }
1328
1329 isc_result_t
dns_name_toprincipal(const dns_name_t * name,isc_buffer_t * target)1330 dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) {
1331 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1332 }
1333
1334 isc_result_t
dns_name_totext2(const dns_name_t * name,unsigned int options,isc_buffer_t * target)1335 dns_name_totext2(const dns_name_t *name, unsigned int options,
1336 isc_buffer_t *target) {
1337 unsigned char *ndata;
1338 char *tdata;
1339 unsigned int nlen, tlen;
1340 unsigned char c;
1341 unsigned int trem, count;
1342 unsigned int labels;
1343 bool saw_root = false;
1344 unsigned int oused;
1345 bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
1346
1347 /*
1348 * This function assumes the name is in proper uncompressed
1349 * wire format.
1350 */
1351 REQUIRE(VALID_NAME(name));
1352 REQUIRE(ISC_BUFFER_VALID(target));
1353
1354 oused = target->used;
1355
1356 ndata = name->ndata;
1357 nlen = name->length;
1358 labels = name->labels;
1359 tdata = isc_buffer_used(target);
1360 tlen = isc_buffer_availablelength(target);
1361
1362 trem = tlen;
1363
1364 if (labels == 0 && nlen == 0) {
1365 /*
1366 * Special handling for an empty name.
1367 */
1368 if (trem == 0) {
1369 return (ISC_R_NOSPACE);
1370 }
1371
1372 /*
1373 * The names of these booleans are misleading in this case.
1374 * This empty name is not necessarily from the root node of
1375 * the DNS root zone, nor is a final dot going to be included.
1376 * They need to be set this way, though, to keep the "@"
1377 * from being trounced.
1378 */
1379 saw_root = true;
1380 omit_final_dot = false;
1381 *tdata++ = '@';
1382 trem--;
1383
1384 /*
1385 * Skip the while() loop.
1386 */
1387 nlen = 0;
1388 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1389 /*
1390 * Special handling for the root label.
1391 */
1392 if (trem == 0) {
1393 return (ISC_R_NOSPACE);
1394 }
1395
1396 saw_root = true;
1397 omit_final_dot = false;
1398 *tdata++ = '.';
1399 trem--;
1400
1401 /*
1402 * Skip the while() loop.
1403 */
1404 nlen = 0;
1405 }
1406
1407 while (labels > 0 && nlen > 0 && trem > 0) {
1408 labels--;
1409 count = *ndata++;
1410 nlen--;
1411 if (count == 0) {
1412 saw_root = true;
1413 break;
1414 }
1415 if (count < 64) {
1416 INSIST(nlen >= count);
1417 while (count > 0) {
1418 c = *ndata;
1419 switch (c) {
1420 /* Special modifiers in zone files. */
1421 case 0x40: /* '@' */
1422 case 0x24: /* '$' */
1423 if ((options & DNS_NAME_MASTERFILE) ==
1424 0)
1425 {
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 UNREACHABLE();
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 UNREACHABLE();
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 {
1862 return (DNS_R_DISALLOWED);
1863 }
1864 new_current = c & 0x3F;
1865 state = fw_newcurrent;
1866 } else {
1867 return (DNS_R_BADLABELTYPE);
1868 }
1869 break;
1870 case fw_ordinary:
1871 if (downcase) {
1872 c = maptolower[c];
1873 }
1874 *ndata++ = c;
1875 n--;
1876 if (n == 0) {
1877 state = fw_start;
1878 }
1879 break;
1880 case fw_newcurrent:
1881 new_current *= 256;
1882 new_current += c;
1883 if (new_current >= biggest_pointer) {
1884 return (DNS_R_BADPOINTER);
1885 }
1886 biggest_pointer = new_current;
1887 current = new_current;
1888 cdata = (unsigned char *)source->base + current;
1889 seen_pointer = true;
1890 state = fw_start;
1891 break;
1892 default:
1893 FATAL_ERROR(__FILE__, __LINE__, "Unknown state %d",
1894 state);
1895 /* Does not return. */
1896 }
1897 }
1898
1899 if (!done) {
1900 return (ISC_R_UNEXPECTEDEND);
1901 }
1902
1903 name->ndata = (unsigned char *)target->base + target->used;
1904 name->labels = labels;
1905 name->length = nused;
1906 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1907
1908 isc_buffer_forward(source, cused);
1909 isc_buffer_add(target, name->length);
1910
1911 return (ISC_R_SUCCESS);
1912
1913 full:
1914 if (nmax == DNS_NAME_MAXWIRE) {
1915 /*
1916 * The name did not fit even though we had a buffer
1917 * big enough to fit a maximum-length name.
1918 */
1919 return (DNS_R_NAMETOOLONG);
1920 } else {
1921 /*
1922 * The name might fit if only the caller could give us a
1923 * big enough buffer.
1924 */
1925 return (ISC_R_NOSPACE);
1926 }
1927 }
1928
1929 isc_result_t
dns_name_towire(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target)1930 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1931 isc_buffer_t *target) {
1932 return (dns_name_towire2(name, cctx, target, NULL));
1933 }
1934
1935 isc_result_t
dns_name_towire2(const dns_name_t * name,dns_compress_t * cctx,isc_buffer_t * target,uint16_t * comp_offsetp)1936 dns_name_towire2(const dns_name_t *name, dns_compress_t *cctx,
1937 isc_buffer_t *target, uint16_t *comp_offsetp) {
1938 unsigned int methods;
1939 uint16_t offset;
1940 dns_name_t gp; /* Global compression prefix */
1941 bool gf; /* Global compression target found */
1942 uint16_t go; /* Global compression offset */
1943 dns_offsets_t clo;
1944 dns_name_t clname;
1945
1946 /*
1947 * Convert 'name' into wire format, compressing it as specified by the
1948 * compression context 'cctx', and storing the result in 'target'.
1949 */
1950
1951 REQUIRE(VALID_NAME(name));
1952 REQUIRE(cctx != NULL);
1953 REQUIRE(ISC_BUFFER_VALID(target));
1954
1955 /*
1956 * If this exact name was already rendered before, and the
1957 * offset of the previously rendered name is passed to us, write
1958 * a compression pointer directly.
1959 */
1960 methods = dns_compress_getmethods(cctx);
1961 if (comp_offsetp != NULL && *comp_offsetp < 0x4000 &&
1962 (name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1963 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1964 {
1965 if (ISC_UNLIKELY(target->length - target->used < 2)) {
1966 return (ISC_R_NOSPACE);
1967 }
1968 offset = *comp_offsetp;
1969 offset |= 0xc000;
1970 isc_buffer_putuint16(target, offset);
1971 return (ISC_R_SUCCESS);
1972 }
1973
1974 /*
1975 * If 'name' doesn't have an offsets table, make a clone which
1976 * has one.
1977 */
1978 if (name->offsets == NULL) {
1979 DNS_NAME_INIT(&clname, clo);
1980 dns_name_clone(name, &clname);
1981 name = &clname;
1982 }
1983 DNS_NAME_INIT(&gp, NULL);
1984
1985 offset = target->used; /*XXX*/
1986
1987 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1988 (methods & DNS_COMPRESS_GLOBAL14) != 0)
1989 {
1990 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1991 } else {
1992 gf = false;
1993 }
1994
1995 /*
1996 * If the offset is too high for 14 bit global compression, we're
1997 * out of luck.
1998 */
1999 if (gf && ISC_UNLIKELY(go >= 0x4000)) {
2000 gf = false;
2001 }
2002
2003 /*
2004 * Will the compression pointer reduce the message size?
2005 */
2006 if (gf && (gp.length + 2) >= name->length) {
2007 gf = false;
2008 }
2009
2010 if (gf) {
2011 if (ISC_UNLIKELY(target->length - target->used < gp.length)) {
2012 return (ISC_R_NOSPACE);
2013 }
2014 if (gp.length != 0) {
2015 unsigned char *base = target->base;
2016 (void)memmove(base + target->used, gp.ndata,
2017 (size_t)gp.length);
2018 }
2019 isc_buffer_add(target, gp.length);
2020 if (ISC_UNLIKELY(target->length - target->used < 2)) {
2021 return (ISC_R_NOSPACE);
2022 }
2023 isc_buffer_putuint16(target, go | 0xc000);
2024 if (gp.length != 0) {
2025 dns_compress_add(cctx, name, &gp, offset);
2026 if (comp_offsetp != NULL) {
2027 *comp_offsetp = offset;
2028 }
2029 } else if (comp_offsetp != NULL) {
2030 *comp_offsetp = go;
2031 }
2032 } else {
2033 if (ISC_UNLIKELY(target->length - target->used < name->length))
2034 {
2035 return (ISC_R_NOSPACE);
2036 }
2037 if (name->length != 0) {
2038 unsigned char *base = target->base;
2039 (void)memmove(base + target->used, name->ndata,
2040 (size_t)name->length);
2041 }
2042 isc_buffer_add(target, name->length);
2043 dns_compress_add(cctx, name, name, offset);
2044 if (comp_offsetp != NULL) {
2045 *comp_offsetp = offset;
2046 }
2047 }
2048
2049 return (ISC_R_SUCCESS);
2050 }
2051
2052 isc_result_t
dns_name_concatenate(const dns_name_t * prefix,const dns_name_t * suffix,dns_name_t * name,isc_buffer_t * target)2053 dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
2054 dns_name_t *name, isc_buffer_t *target) {
2055 unsigned char *ndata, *offsets;
2056 unsigned int nrem, labels, prefix_length, length;
2057 bool copy_prefix = true;
2058 bool copy_suffix = true;
2059 bool absolute = false;
2060 dns_name_t tmp_name;
2061 dns_offsets_t odata;
2062
2063 /*
2064 * Concatenate 'prefix' and 'suffix'.
2065 */
2066
2067 REQUIRE(prefix == NULL || VALID_NAME(prefix));
2068 REQUIRE(suffix == NULL || VALID_NAME(suffix));
2069 REQUIRE(name == NULL || VALID_NAME(name));
2070 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2071 (target == NULL && name != NULL &&
2072 ISC_BUFFER_VALID(name->buffer)));
2073 if (prefix == NULL || prefix->labels == 0) {
2074 copy_prefix = false;
2075 }
2076 if (suffix == NULL || suffix->labels == 0) {
2077 copy_suffix = false;
2078 }
2079 if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2080 absolute = true;
2081 REQUIRE(!copy_suffix);
2082 }
2083 if (name == NULL) {
2084 DNS_NAME_INIT(&tmp_name, odata);
2085 name = &tmp_name;
2086 }
2087 if (target == NULL) {
2088 INSIST(name->buffer != NULL);
2089 target = name->buffer;
2090 isc_buffer_clear(name->buffer);
2091 }
2092
2093 REQUIRE(BINDABLE(name));
2094
2095 /*
2096 * Set up.
2097 */
2098 nrem = target->length - target->used;
2099 ndata = (unsigned char *)target->base + target->used;
2100 if (nrem > DNS_NAME_MAXWIRE) {
2101 nrem = DNS_NAME_MAXWIRE;
2102 }
2103 length = 0;
2104 prefix_length = 0;
2105 labels = 0;
2106 if (copy_prefix) {
2107 prefix_length = prefix->length;
2108 length += prefix_length;
2109 labels += prefix->labels;
2110 }
2111 if (copy_suffix) {
2112 length += suffix->length;
2113 labels += suffix->labels;
2114 }
2115 if (length > DNS_NAME_MAXWIRE) {
2116 MAKE_EMPTY(name);
2117 return (DNS_R_NAMETOOLONG);
2118 }
2119 if (length > nrem) {
2120 MAKE_EMPTY(name);
2121 return (ISC_R_NOSPACE);
2122 }
2123
2124 if (copy_suffix) {
2125 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2126 absolute = true;
2127 }
2128 memmove(ndata + prefix_length, suffix->ndata, suffix->length);
2129 }
2130
2131 /*
2132 * If 'prefix' and 'name' are the same object, and the object has
2133 * a dedicated buffer, and we're using it, then we don't have to
2134 * copy anything.
2135 */
2136 if (copy_prefix && (prefix != name || prefix->buffer != target)) {
2137 memmove(ndata, prefix->ndata, prefix_length);
2138 }
2139
2140 name->ndata = ndata;
2141 name->labels = labels;
2142 name->length = length;
2143 if (absolute) {
2144 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2145 } else {
2146 name->attributes = 0;
2147 }
2148
2149 if (name->labels > 0 && name->offsets != NULL) {
2150 INIT_OFFSETS(name, offsets, odata);
2151 set_offsets(name, offsets, NULL);
2152 }
2153
2154 isc_buffer_add(target, name->length);
2155
2156 return (ISC_R_SUCCESS);
2157 }
2158
2159 void
dns_name_split(const dns_name_t * name,unsigned int suffixlabels,dns_name_t * prefix,dns_name_t * suffix)2160 dns_name_split(const dns_name_t *name, unsigned int suffixlabels,
2161 dns_name_t *prefix, dns_name_t *suffix)
2162
2163 {
2164 unsigned int splitlabel;
2165
2166 REQUIRE(VALID_NAME(name));
2167 REQUIRE(suffixlabels > 0);
2168 REQUIRE(suffixlabels <= name->labels);
2169 REQUIRE(prefix != NULL || suffix != NULL);
2170 REQUIRE(prefix == NULL || (VALID_NAME(prefix) && BINDABLE(prefix)));
2171 REQUIRE(suffix == NULL || (VALID_NAME(suffix) && BINDABLE(suffix)));
2172
2173 splitlabel = name->labels - suffixlabels;
2174
2175 if (prefix != NULL) {
2176 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2177 }
2178
2179 if (suffix != NULL) {
2180 dns_name_getlabelsequence(name, splitlabel, suffixlabels,
2181 suffix);
2182 }
2183
2184 return;
2185 }
2186
2187 void
dns_name_dup(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)2188 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
2189 /*
2190 * Make 'target' a dynamically allocated copy of 'source'.
2191 */
2192
2193 REQUIRE(VALID_NAME(source));
2194 REQUIRE(source->length > 0);
2195 REQUIRE(VALID_NAME(target));
2196 REQUIRE(BINDABLE(target));
2197
2198 /*
2199 * Make 'target' empty in case of failure.
2200 */
2201 MAKE_EMPTY(target);
2202
2203 target->ndata = isc_mem_get(mctx, source->length);
2204
2205 memmove(target->ndata, source->ndata, source->length);
2206
2207 target->length = source->length;
2208 target->labels = source->labels;
2209 target->attributes = DNS_NAMEATTR_DYNAMIC;
2210 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2211 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2212 }
2213 if (target->offsets != NULL) {
2214 if (source->offsets != NULL) {
2215 memmove(target->offsets, source->offsets,
2216 source->labels);
2217 } else {
2218 set_offsets(target, target->offsets, NULL);
2219 }
2220 }
2221 }
2222
2223 isc_result_t
dns_name_dupwithoffsets(const dns_name_t * source,isc_mem_t * mctx,dns_name_t * target)2224 dns_name_dupwithoffsets(const dns_name_t *source, isc_mem_t *mctx,
2225 dns_name_t *target) {
2226 /*
2227 * Make 'target' a read-only dynamically allocated copy of 'source'.
2228 * 'target' will also have a dynamically allocated offsets table.
2229 */
2230
2231 REQUIRE(VALID_NAME(source));
2232 REQUIRE(source->length > 0);
2233 REQUIRE(VALID_NAME(target));
2234 REQUIRE(BINDABLE(target));
2235 REQUIRE(target->offsets == NULL);
2236
2237 /*
2238 * Make 'target' empty in case of failure.
2239 */
2240 MAKE_EMPTY(target);
2241
2242 target->ndata = isc_mem_get(mctx, source->length + source->labels);
2243
2244 memmove(target->ndata, source->ndata, source->length);
2245
2246 target->length = source->length;
2247 target->labels = source->labels;
2248 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2249 DNS_NAMEATTR_READONLY;
2250 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2251 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2252 }
2253 target->offsets = target->ndata + source->length;
2254 if (source->offsets != NULL) {
2255 memmove(target->offsets, source->offsets, source->labels);
2256 } else {
2257 set_offsets(target, target->offsets, NULL);
2258 }
2259
2260 return (ISC_R_SUCCESS);
2261 }
2262
2263 void
dns_name_free(dns_name_t * name,isc_mem_t * mctx)2264 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2265 size_t size;
2266
2267 /*
2268 * Free 'name'.
2269 */
2270
2271 REQUIRE(VALID_NAME(name));
2272 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2273
2274 size = name->length;
2275 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) {
2276 size += name->labels;
2277 }
2278 isc_mem_put(mctx, name->ndata, size);
2279 dns_name_invalidate(name);
2280 }
2281
2282 isc_result_t
dns_name_digest(const dns_name_t * name,dns_digestfunc_t digest,void * arg)2283 dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2284 dns_name_t downname;
2285 unsigned char data[256];
2286 isc_buffer_t buffer;
2287 isc_result_t result;
2288 isc_region_t r;
2289
2290 /*
2291 * Send 'name' in DNSSEC canonical form to 'digest'.
2292 */
2293
2294 REQUIRE(VALID_NAME(name));
2295 REQUIRE(digest != NULL);
2296
2297 DNS_NAME_INIT(&downname, NULL);
2298
2299 isc_buffer_init(&buffer, data, sizeof(data));
2300
2301 result = dns_name_downcase(name, &downname, &buffer);
2302 if (result != ISC_R_SUCCESS) {
2303 return (result);
2304 }
2305
2306 isc_buffer_usedregion(&buffer, &r);
2307
2308 return ((digest)(arg, &r));
2309 }
2310
2311 bool
dns_name_dynamic(const dns_name_t * name)2312 dns_name_dynamic(const dns_name_t *name) {
2313 REQUIRE(VALID_NAME(name));
2314
2315 /*
2316 * Returns whether there is dynamic memory associated with this name.
2317 */
2318
2319 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? true : false);
2320 }
2321
2322 isc_result_t
dns_name_print(const dns_name_t * name,FILE * stream)2323 dns_name_print(const dns_name_t *name, FILE *stream) {
2324 isc_result_t result;
2325 isc_buffer_t b;
2326 isc_region_t r;
2327 char t[1024];
2328
2329 /*
2330 * Print 'name' on 'stream'.
2331 */
2332
2333 REQUIRE(VALID_NAME(name));
2334
2335 isc_buffer_init(&b, t, sizeof(t));
2336 result = dns_name_totext(name, false, &b);
2337 if (result != ISC_R_SUCCESS) {
2338 return (result);
2339 }
2340 isc_buffer_usedregion(&b, &r);
2341 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2342
2343 return (ISC_R_SUCCESS);
2344 }
2345
2346 isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t * proc)2347 dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
2348 /*
2349 * If we already have been here set / clear as appropriate.
2350 */
2351 if (totext_filter_proc != NULL && proc != NULL) {
2352 if (totext_filter_proc == proc) {
2353 return (ISC_R_SUCCESS);
2354 }
2355 }
2356 if (proc == NULL && totext_filter_proc != NULL) {
2357 totext_filter_proc = NULL;
2358 return (ISC_R_SUCCESS);
2359 }
2360
2361 totext_filter_proc = proc;
2362
2363 return (ISC_R_SUCCESS);
2364 }
2365
2366 void
dns_name_format(const dns_name_t * name,char * cp,unsigned int size)2367 dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
2368 isc_result_t result;
2369 isc_buffer_t buf;
2370
2371 REQUIRE(size > 0);
2372
2373 /*
2374 * Leave room for null termination after buffer.
2375 */
2376 isc_buffer_init(&buf, cp, size - 1);
2377 result = dns_name_totext(name, true, &buf);
2378 if (result == ISC_R_SUCCESS) {
2379 isc_buffer_putuint8(&buf, (uint8_t)'\0');
2380 } else {
2381 snprintf(cp, size, "<unknown>");
2382 }
2383 }
2384
2385 /*
2386 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2387 * memory.
2388 */
2389 isc_result_t
dns_name_tostring(const dns_name_t * name,char ** target,isc_mem_t * mctx)2390 dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
2391 isc_result_t result;
2392 isc_buffer_t buf;
2393 isc_region_t reg;
2394 char *p, txt[DNS_NAME_FORMATSIZE];
2395
2396 REQUIRE(VALID_NAME(name));
2397 REQUIRE(target != NULL && *target == NULL);
2398
2399 isc_buffer_init(&buf, txt, sizeof(txt));
2400 result = dns_name_totext(name, false, &buf);
2401 if (result != ISC_R_SUCCESS) {
2402 return (result);
2403 }
2404
2405 isc_buffer_usedregion(&buf, ®);
2406 p = isc_mem_allocate(mctx, reg.length + 1);
2407 memmove(p, (char *)reg.base, (int)reg.length);
2408 p[reg.length] = '\0';
2409
2410 *target = p;
2411 return (ISC_R_SUCCESS);
2412 }
2413
2414 /*
2415 * dns_name_fromstring() -- convert directly from a string to a name,
2416 * allocating memory as needed
2417 */
2418 isc_result_t
dns_name_fromstring(dns_name_t * target,const char * src,unsigned int options,isc_mem_t * mctx)2419 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2420 isc_mem_t *mctx) {
2421 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2422 }
2423
2424 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)2425 dns_name_fromstring2(dns_name_t *target, const char *src,
2426 const dns_name_t *origin, unsigned int options,
2427 isc_mem_t *mctx) {
2428 isc_result_t result;
2429 isc_buffer_t buf;
2430 dns_fixedname_t fn;
2431 dns_name_t *name;
2432
2433 REQUIRE(src != NULL);
2434
2435 isc_buffer_constinit(&buf, src, strlen(src));
2436 isc_buffer_add(&buf, strlen(src));
2437 if (BINDABLE(target) && target->buffer != NULL) {
2438 name = target;
2439 } else {
2440 name = dns_fixedname_initname(&fn);
2441 }
2442
2443 result = dns_name_fromtext(name, &buf, origin, options, NULL);
2444 if (result != ISC_R_SUCCESS) {
2445 return (result);
2446 }
2447
2448 if (name != target) {
2449 result = dns_name_dupwithoffsets(name, mctx, target);
2450 }
2451 return (result);
2452 }
2453
2454 static isc_result_t
name_copy(const dns_name_t * source,dns_name_t * dest,isc_buffer_t * target)2455 name_copy(const dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2456 unsigned char *ndata = NULL;
2457
2458 /*
2459 * Make dest a copy of source.
2460 */
2461
2462 REQUIRE(BINDABLE(dest));
2463
2464 /*
2465 * Set up.
2466 */
2467 if (target->length - target->used < source->length) {
2468 return (ISC_R_NOSPACE);
2469 }
2470
2471 ndata = (unsigned char *)target->base + target->used;
2472 dest->ndata = target->base;
2473
2474 if (source->length != 0) {
2475 memmove(ndata, source->ndata, source->length);
2476 }
2477
2478 dest->ndata = ndata;
2479 dest->labels = source->labels;
2480 dest->length = source->length;
2481 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2482 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2483 } else {
2484 dest->attributes = 0;
2485 }
2486
2487 if (dest->labels > 0 && dest->offsets != NULL) {
2488 if (source->offsets != NULL && source->labels != 0) {
2489 memmove(dest->offsets, source->offsets, source->labels);
2490 } else {
2491 set_offsets(dest, dest->offsets, NULL);
2492 }
2493 }
2494
2495 isc_buffer_add(target, dest->length);
2496
2497 return (ISC_R_SUCCESS);
2498 }
2499
2500 isc_result_t
dns_name_copy(const dns_name_t * source,dns_name_t * dest,isc_buffer_t * target)2501 dns_name_copy(const dns_name_t *source, dns_name_t *dest,
2502 isc_buffer_t *target) {
2503 REQUIRE(VALID_NAME(source));
2504 REQUIRE(VALID_NAME(dest));
2505 REQUIRE(target != NULL);
2506
2507 return (name_copy(source, dest, target));
2508 }
2509
2510 void
dns_name_copynf(const dns_name_t * source,dns_name_t * dest)2511 dns_name_copynf(const dns_name_t *source, dns_name_t *dest) {
2512 REQUIRE(VALID_NAME(source));
2513 REQUIRE(VALID_NAME(dest));
2514 REQUIRE(dest->buffer != NULL);
2515
2516 isc_buffer_clear(dest->buffer);
2517 RUNTIME_CHECK(name_copy(source, dest, dest->buffer) == ISC_R_SUCCESS);
2518 }
2519
2520 /*
2521 * Service Discovery Prefixes RFC 6763.
2522 */
2523 static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
2524 static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
2525 static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
2526 static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
2527 static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
2528 static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
2529 static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
2530 static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
2531 static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
2532 static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
2533
2534 static dns_name_t const dns_sd[] = {
2535 DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
2536 DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
2537 DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
2538 DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
2539 DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
2540 };
2541
2542 bool
dns_name_isdnssd(const dns_name_t * name)2543 dns_name_isdnssd(const dns_name_t *name) {
2544 size_t i;
2545 dns_name_t prefix;
2546
2547 if (dns_name_countlabels(name) > 3U) {
2548 dns_name_init(&prefix, NULL);
2549 dns_name_getlabelsequence(name, 0, 3, &prefix);
2550 for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
2551 if (dns_name_equal(&prefix, &dns_sd[i])) {
2552 return (true);
2553 }
2554 }
2555 }
2556
2557 return (false);
2558 }
2559
2560 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
2561 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
2562 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
2563
2564 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
2565
2566 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
2567 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
2568 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
2569 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
2570 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
2571 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
2572 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
2573 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
2574 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
2575 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
2576 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
2577 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
2578 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
2579 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
2580 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
2581 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
2582
2583 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
2584
2585 static dns_name_t const rfc1918names[] = {
2586 DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
2587 DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
2588 DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
2589 DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
2590 DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
2591 DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
2592 DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
2593 DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
2594 DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
2595 DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
2596 DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
2597 DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
2598 DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
2599 DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
2600 DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
2601 DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
2602 DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
2603 DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
2604 };
2605
2606 bool
dns_name_isrfc1918(const dns_name_t * name)2607 dns_name_isrfc1918(const dns_name_t *name) {
2608 size_t i;
2609
2610 for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
2611 if (dns_name_issubdomain(name, &rfc1918names[i])) {
2612 return (true);
2613 }
2614 }
2615 return (false);
2616 }
2617
2618 static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
2619 static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
2620 static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
2621
2622 static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
2623 DNS_NAME_INITABSOLUTE(ip6fd,
2624 ulaoffsets) };
2625
2626 bool
dns_name_isula(const dns_name_t * name)2627 dns_name_isula(const dns_name_t *name) {
2628 size_t i;
2629
2630 for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
2631 if (dns_name_issubdomain(name, &ulanames[i])) {
2632 return (true);
2633 }
2634 }
2635 return (false);
2636 }
2637
2638 /*
2639 * Use a simple table as we don't want all the locale stuff
2640 * associated with ishexdigit().
2641 */
2642 const char ishex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2643 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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2646 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2647 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2648 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2649 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2650
2651 bool
dns_name_istat(const dns_name_t * name)2652 dns_name_istat(const dns_name_t *name) {
2653 unsigned char len;
2654 const unsigned char *ndata;
2655
2656 REQUIRE(VALID_NAME(name));
2657
2658 if (name->labels < 1) {
2659 return (false);
2660 }
2661
2662 ndata = name->ndata;
2663 len = ndata[0];
2664 INSIST(len <= name->length);
2665 ndata++;
2666
2667 /*
2668 * Is there at least one trust anchor reported and is the
2669 * label length consistent with a trust-anchor-telemetry label.
2670 */
2671 if ((len < 8) || (len - 3) % 5 != 0) {
2672 return (false);
2673 }
2674
2675 if (ndata[0] != '_' || maptolower[ndata[1]] != 't' ||
2676 maptolower[ndata[2]] != 'a')
2677 {
2678 return (false);
2679 }
2680 ndata += 3;
2681 len -= 3;
2682
2683 while (len > 0) {
2684 INSIST(len >= 5);
2685 if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] ||
2686 !ishex[ndata[3]] || !ishex[ndata[4]])
2687 {
2688 return (false);
2689 }
2690 ndata += 5;
2691 len -= 5;
2692 }
2693 return (true);
2694 }
2695