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