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 40typedef 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 50typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state; 51 52static 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 71static 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 */ 138static unsigned char root_ndata[] = { "" }; 139static unsigned char root_offsets[] = { 0 }; 140 141static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets); 142LIBDNS_EXTERNAL_DATA const dns_name_t *dns_rootname = &root; 143 144static unsigned char wild_ndata[] = { "\001*" }; 145static unsigned char wild_offsets[] = { 0 }; 146 147static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata, 148 wild_offsets); 149 150LIBDNS_EXTERNAL_DATA const dns_name_t *dns_wildcardname = &wild; 151 152/* 153 * dns_name_t to text post-conversion procedure. 154 */ 155ISC_THREAD_LOCAL dns_name_totextfilter_t *totext_filter_proc = NULL; 156 157static void 158set_offsets(const dns_name_t *name, unsigned char *offsets, 159 dns_name_t *set_name); 160 161void 162dns_name_init(dns_name_t *name, unsigned char *offsets) { 163 /* 164 * Initialize 'name'. 165 */ 166 DNS_NAME_INIT(name, offsets); 167} 168 169void 170dns_name_reset(dns_name_t *name) { 171 REQUIRE(VALID_NAME(name)); 172 REQUIRE(BINDABLE(name)); 173 174 DNS_NAME_RESET(name); 175} 176 177void 178dns_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 196bool 197dns_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 243void 244dns_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 255bool 256dns_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 270bool 271dns_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 293bool 294dns_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 348bool 349dns_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 397bool 398dns_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 418bool 419dns_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 454unsigned int 455dns_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 476unsigned int 477dns_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 491dns_namereln_t 492dns_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 623done: 624 *nlabelsp = nlabels; 625 if (nlabels > 0) { 626 namereln = dns_namereln_commonancestor; 627 } 628 629 return (namereln); 630} 631 632int 633dns_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 652bool 653dns_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 732bool 733dns_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 762int 763dns_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 822bool 823dns_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 847bool 848dns_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 870unsigned int 871dns_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 883void 884dns_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 907void 908dns_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 969void 970dns_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 996void 997dns_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 1044void 1045dns_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 1056isc_result_t 1057dns_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 1319isc_result_t 1320dns_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 1330isc_result_t 1331dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) { 1332 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target)); 1333} 1334 1335isc_result_t 1336dns_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 1513isc_result_t 1514dns_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 1630isc_result_t 1631dns_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 1706static void 1707set_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 1746isc_result_t 1747dns_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 1914full: 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 1930isc_result_t 1931dns_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 1936isc_result_t 1937dns_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 2053isc_result_t 2054dns_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 2160void 2161dns_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 2188void 2189dns_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 2224isc_result_t 2225dns_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 2264void 2265dns_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 2283isc_result_t 2284dns_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 2312bool 2313dns_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 2323isc_result_t 2324dns_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 2347isc_result_t 2348dns_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 2367void 2368dns_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 */ 2390isc_result_t 2391dns_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 */ 2419isc_result_t 2420dns_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 2425isc_result_t 2426dns_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 2455static isc_result_t 2456name_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 2501isc_result_t 2502dns_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 2511void 2512dns_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 */ 2524static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp"; 2525static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 }; 2526static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp"; 2527static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2528static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp"; 2529static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 }; 2530static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp"; 2531static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2532static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp"; 2533static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 }; 2534 2535static 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 2543bool 2544dns_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 2561static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 }; 2562static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 }; 2563static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 }; 2564 2565static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA"; 2566 2567static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA"; 2568static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA"; 2569static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA"; 2570static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA"; 2571static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA"; 2572static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA"; 2573static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA"; 2574static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA"; 2575static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA"; 2576static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA"; 2577static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA"; 2578static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA"; 2579static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA"; 2580static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA"; 2581static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA"; 2582static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA"; 2583 2584static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA"; 2585 2586static 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 2607bool 2608dns_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 2619static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 }; 2620static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA"; 2621static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA"; 2622 2623static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets), 2624 DNS_NAME_INITABSOLUTE(ip6fd, 2625 ulaoffsets) }; 2626 2627bool 2628dns_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 */ 2643const 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 2652bool 2653dns_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