name.c revision 254402
1/* 2 * Copyright (C) 2004-2012 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 SETUP_OFFSETS(name1, offsets1, odata1); 582 SETUP_OFFSETS(name2, offsets2, odata2); 583 584 nlabels = 0; 585 l1 = name1->labels; 586 l2 = name2->labels; 587 if (l2 > l1) { 588 l = l1; 589 ldiff = 0 - (l2 - l1); 590 } else { 591 l = l2; 592 ldiff = l1 - l2; 593 } 594 595 while (l > 0) { 596 l--; 597 l1--; 598 l2--; 599 label1 = &name1->ndata[offsets1[l1]]; 600 label2 = &name2->ndata[offsets2[l2]]; 601 count1 = *label1++; 602 count2 = *label2++; 603 604 /* 605 * We dropped bitstring labels, and we don't support any 606 * other extended label types. 607 */ 608 INSIST(count1 <= 63 && count2 <= 63); 609 610 cdiff = (int)count1 - (int)count2; 611 if (cdiff < 0) 612 count = count1; 613 else 614 count = count2; 615 616 while (count > 0) { 617 chdiff = (int)maptolower[*label1] - 618 (int)maptolower[*label2]; 619 if (chdiff != 0) { 620 *orderp = chdiff; 621 goto done; 622 } 623 count--; 624 label1++; 625 label2++; 626 } 627 if (cdiff != 0) { 628 *orderp = cdiff; 629 goto done; 630 } 631 nlabels++; 632 } 633 634 *orderp = ldiff; 635 if (ldiff < 0) 636 namereln = dns_namereln_contains; 637 else if (ldiff > 0) 638 namereln = dns_namereln_subdomain; 639 else 640 namereln = dns_namereln_equal; 641 642 done: 643 *nlabelsp = nlabels; 644 645 if (nlabels > 0 && namereln == dns_namereln_none) 646 namereln = dns_namereln_commonancestor; 647 648 return (namereln); 649} 650 651int 652dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) { 653 int order; 654 unsigned int nlabels; 655 656 /* 657 * Determine the relative ordering under the DNSSEC order relation of 658 * 'name1' and 'name2'. 659 * 660 * Note: It makes no sense for one of the names to be relative and the 661 * other absolute. If both names are relative, then to be meaningfully 662 * compared the caller must ensure that they are both relative to the 663 * same domain. 664 */ 665 666 (void)dns_name_fullcompare(name1, name2, &order, &nlabels); 667 668 return (order); 669} 670 671isc_boolean_t 672dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) { 673 unsigned int l, count; 674 unsigned char c; 675 unsigned char *label1, *label2; 676 677 /* 678 * Are 'name1' and 'name2' equal? 679 * 680 * Note: It makes no sense for one of the names to be relative and the 681 * other absolute. If both names are relative, then to be meaningfully 682 * compared the caller must ensure that they are both relative to the 683 * same domain. 684 */ 685 686 REQUIRE(VALID_NAME(name1)); 687 REQUIRE(VALID_NAME(name2)); 688 /* 689 * Either name1 is absolute and name2 is absolute, or neither is. 690 */ 691 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 692 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 693 694 if (name1->length != name2->length) 695 return (ISC_FALSE); 696 697 l = name1->labels; 698 699 if (l != name2->labels) 700 return (ISC_FALSE); 701 702 label1 = name1->ndata; 703 label2 = name2->ndata; 704 while (l > 0) { 705 l--; 706 count = *label1++; 707 if (count != *label2++) 708 return (ISC_FALSE); 709 710 INSIST(count <= 63); /* no bitstring support */ 711 712 while (count > 0) { 713 count--; 714 c = maptolower[*label1++]; 715 if (c != maptolower[*label2++]) 716 return (ISC_FALSE); 717 } 718 } 719 720 return (ISC_TRUE); 721} 722 723isc_boolean_t 724dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) { 725 726 /* 727 * Are 'name1' and 'name2' equal? 728 * 729 * Note: It makes no sense for one of the names to be relative and the 730 * other absolute. If both names are relative, then to be meaningfully 731 * compared the caller must ensure that they are both relative to the 732 * same domain. 733 */ 734 735 REQUIRE(VALID_NAME(name1)); 736 REQUIRE(VALID_NAME(name2)); 737 /* 738 * Either name1 is absolute and name2 is absolute, or neither is. 739 */ 740 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 741 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 742 743 if (name1->length != name2->length) 744 return (ISC_FALSE); 745 746 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) 747 return (ISC_FALSE); 748 749 return (ISC_TRUE); 750} 751 752int 753dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) { 754 unsigned int l1, l2, l, count1, count2, count; 755 unsigned char c1, c2; 756 unsigned char *label1, *label2; 757 758 /* 759 * Compare two absolute names as rdata. 760 */ 761 762 REQUIRE(VALID_NAME(name1)); 763 REQUIRE(name1->labels > 0); 764 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 765 REQUIRE(VALID_NAME(name2)); 766 REQUIRE(name2->labels > 0); 767 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 768 769 l1 = name1->labels; 770 l2 = name2->labels; 771 772 l = (l1 < l2) ? l1 : l2; 773 774 label1 = name1->ndata; 775 label2 = name2->ndata; 776 while (l > 0) { 777 l--; 778 count1 = *label1++; 779 count2 = *label2++; 780 781 /* no bitstring support */ 782 INSIST(count1 <= 63 && count2 <= 63); 783 784 if (count1 != count2) 785 return ((count1 < count2) ? -1 : 1); 786 count = count1; 787 while (count > 0) { 788 count--; 789 c1 = maptolower[*label1++]; 790 c2 = maptolower[*label2++]; 791 if (c1 < c2) 792 return (-1); 793 else if (c1 > c2) 794 return (1); 795 } 796 } 797 798 /* 799 * If one name had more labels than the other, their common 800 * prefix must have been different because the shorter name 801 * ended with the root label and the longer one can't have 802 * a root label in the middle of it. Therefore, if we get 803 * to this point, the lengths must be equal. 804 */ 805 INSIST(l1 == l2); 806 807 return (0); 808} 809 810isc_boolean_t 811dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) { 812 int order; 813 unsigned int nlabels; 814 dns_namereln_t namereln; 815 816 /* 817 * Is 'name1' a subdomain of 'name2'? 818 * 819 * Note: It makes no sense for one of the names to be relative and the 820 * other absolute. If both names are relative, then to be meaningfully 821 * compared the caller must ensure that they are both relative to the 822 * same domain. 823 */ 824 825 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); 826 if (namereln == dns_namereln_subdomain || 827 namereln == dns_namereln_equal) 828 return (ISC_TRUE); 829 830 return (ISC_FALSE); 831} 832 833isc_boolean_t 834dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) { 835 int order; 836 unsigned int nlabels, labels; 837 dns_name_t tname; 838 839 REQUIRE(VALID_NAME(name)); 840 REQUIRE(name->labels > 0); 841 REQUIRE(VALID_NAME(wname)); 842 labels = wname->labels; 843 REQUIRE(labels > 0); 844 REQUIRE(dns_name_iswildcard(wname)); 845 846#if defined(__clang__) && \ 847 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)) 848 memset(&tname, 0, sizeof(tname)); 849#endif 850 DNS_NAME_INIT(&tname, NULL); 851 dns_name_getlabelsequence(wname, 1, labels - 1, &tname); 852 if (dns_name_fullcompare(name, &tname, &order, &nlabels) == 853 dns_namereln_subdomain) 854 return (ISC_TRUE); 855 return (ISC_FALSE); 856} 857 858unsigned int 859dns_name_countlabels(const dns_name_t *name) { 860 /* 861 * How many labels does 'name' have? 862 */ 863 864 REQUIRE(VALID_NAME(name)); 865 866 ENSURE(name->labels <= 128); 867 868 return (name->labels); 869} 870 871void 872dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) { 873 unsigned char *offsets; 874 dns_offsets_t odata; 875 876 /* 877 * Make 'label' refer to the 'n'th least significant label of 'name'. 878 */ 879 880 REQUIRE(VALID_NAME(name)); 881 REQUIRE(name->labels > 0); 882 REQUIRE(n < name->labels); 883 REQUIRE(label != NULL); 884 885 SETUP_OFFSETS(name, offsets, odata); 886 887 label->base = &name->ndata[offsets[n]]; 888 if (n == name->labels - 1) 889 label->length = name->length - offsets[n]; 890 else 891 label->length = offsets[n + 1] - offsets[n]; 892} 893 894void 895dns_name_getlabelsequence(const dns_name_t *source, 896 unsigned int first, unsigned int n, 897 dns_name_t *target) 898{ 899 unsigned char *offsets; 900 dns_offsets_t odata; 901 unsigned int firstoffset, endoffset; 902 903 /* 904 * Make 'target' refer to the 'n' labels including and following 905 * 'first' in 'source'. 906 */ 907 908 REQUIRE(VALID_NAME(source)); 909 REQUIRE(VALID_NAME(target)); 910 REQUIRE(first <= source->labels); 911 REQUIRE(n <= source->labels - first); /* note first+n could overflow */ 912 REQUIRE(BINDABLE(target)); 913 914 SETUP_OFFSETS(source, offsets, odata); 915 916 if (first == source->labels) 917 firstoffset = source->length; 918 else 919 firstoffset = offsets[first]; 920 921 if (first + n == source->labels) 922 endoffset = source->length; 923 else 924 endoffset = offsets[first + n]; 925 926 target->ndata = &source->ndata[firstoffset]; 927 target->length = endoffset - firstoffset; 928 929 if (first + n == source->labels && n > 0 && 930 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 931 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 932 else 933 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 934 935 target->labels = n; 936 937 /* 938 * If source and target are the same, and we're making target 939 * a prefix of source, the offsets table is correct already 940 * so we don't need to call set_offsets(). 941 */ 942 if (target->offsets != NULL && 943 (target != source || first != 0)) 944 set_offsets(target, target->offsets, NULL); 945} 946 947void 948dns_name_clone(const dns_name_t *source, dns_name_t *target) { 949 950 /* 951 * Make 'target' refer to the same name as 'source'. 952 */ 953 954 REQUIRE(VALID_NAME(source)); 955 REQUIRE(VALID_NAME(target)); 956 REQUIRE(BINDABLE(target)); 957 958 target->ndata = source->ndata; 959 target->length = source->length; 960 target->labels = source->labels; 961 target->attributes = source->attributes & 962 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC | 963 DNS_NAMEATTR_DYNOFFSETS); 964 if (target->offsets != NULL && source->labels > 0) { 965 if (source->offsets != NULL) 966 memcpy(target->offsets, source->offsets, 967 source->labels); 968 else 969 set_offsets(target, target->offsets, NULL); 970 } 971} 972 973void 974dns_name_fromregion(dns_name_t *name, const isc_region_t *r) { 975 unsigned char *offsets; 976 dns_offsets_t odata; 977 unsigned int len; 978 isc_region_t r2; 979 980 /* 981 * Make 'name' refer to region 'r'. 982 */ 983 984 REQUIRE(VALID_NAME(name)); 985 REQUIRE(r != NULL); 986 REQUIRE(BINDABLE(name)); 987 988 INIT_OFFSETS(name, offsets, odata); 989 990 if (name->buffer != NULL) { 991 isc_buffer_clear(name->buffer); 992 isc_buffer_availableregion(name->buffer, &r2); 993 len = (r->length < r2.length) ? r->length : r2.length; 994 if (len > DNS_NAME_MAXWIRE) 995 len = DNS_NAME_MAXWIRE; 996 memcpy(r2.base, r->base, len); 997 name->ndata = r2.base; 998 name->length = len; 999 } else { 1000 name->ndata = r->base; 1001 name->length = (r->length <= DNS_NAME_MAXWIRE) ? 1002 r->length : DNS_NAME_MAXWIRE; 1003 } 1004 1005 if (r->length > 0) 1006 set_offsets(name, offsets, name); 1007 else { 1008 name->labels = 0; 1009 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1010 } 1011 1012 if (name->buffer != NULL) 1013 isc_buffer_add(name->buffer, name->length); 1014} 1015 1016void 1017dns_name_toregion(dns_name_t *name, isc_region_t *r) { 1018 /* 1019 * Make 'r' refer to 'name'. 1020 */ 1021 1022 REQUIRE(VALID_NAME(name)); 1023 REQUIRE(r != NULL); 1024 1025 DNS_NAME_TOREGION(name, r); 1026} 1027 1028isc_result_t 1029dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, 1030 const dns_name_t *origin, unsigned int options, 1031 isc_buffer_t *target) 1032{ 1033 unsigned char *ndata, *label = NULL; 1034 char *tdata; 1035 char c; 1036 ft_state state; 1037 unsigned int value = 0, count = 0; 1038 unsigned int n1 = 0, n2 = 0; 1039 unsigned int tlen, nrem, nused, digits = 0, labels, tused; 1040 isc_boolean_t done; 1041 unsigned char *offsets; 1042 dns_offsets_t odata; 1043 isc_boolean_t downcase; 1044 1045 /* 1046 * Convert the textual representation of a DNS name at source 1047 * into uncompressed wire form stored in target. 1048 * 1049 * Notes: 1050 * Relative domain names will have 'origin' appended to them 1051 * unless 'origin' is NULL, in which case relative domain names 1052 * will remain relative. 1053 */ 1054 1055 REQUIRE(VALID_NAME(name)); 1056 REQUIRE(ISC_BUFFER_VALID(source)); 1057 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1058 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1059 1060 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 1061 1062 if (target == NULL && name->buffer != NULL) { 1063 target = name->buffer; 1064 isc_buffer_clear(target); 1065 } 1066 1067 REQUIRE(BINDABLE(name)); 1068 1069 INIT_OFFSETS(name, offsets, odata); 1070 offsets[0] = 0; 1071 1072 /* 1073 * Make 'name' empty in case of failure. 1074 */ 1075 MAKE_EMPTY(name); 1076 1077 /* 1078 * Set up the state machine. 1079 */ 1080 tdata = (char *)source->base + source->current; 1081 tlen = isc_buffer_remaininglength(source); 1082 tused = 0; 1083 ndata = isc_buffer_used(target); 1084 nrem = isc_buffer_availablelength(target); 1085 if (nrem > 255) 1086 nrem = 255; 1087 nused = 0; 1088 labels = 0; 1089 done = ISC_FALSE; 1090 state = ft_init; 1091 1092 while (nrem > 0 && tlen > 0 && !done) { 1093 c = *tdata++; 1094 tlen--; 1095 tused++; 1096 1097 switch (state) { 1098 case ft_init: 1099 /* 1100 * Is this the root name? 1101 */ 1102 if (c == '.') { 1103 if (tlen != 0) 1104 return (DNS_R_EMPTYLABEL); 1105 labels++; 1106 *ndata++ = 0; 1107 nrem--; 1108 nused++; 1109 done = ISC_TRUE; 1110 break; 1111 } 1112 if (c == '@' && tlen == 0) { 1113 state = ft_at; 1114 break; 1115 } 1116 1117 /* FALLTHROUGH */ 1118 case ft_start: 1119 label = ndata; 1120 ndata++; 1121 nrem--; 1122 nused++; 1123 count = 0; 1124 if (c == '\\') { 1125 state = ft_initialescape; 1126 break; 1127 } 1128 state = ft_ordinary; 1129 if (nrem == 0) 1130 return (ISC_R_NOSPACE); 1131 /* FALLTHROUGH */ 1132 case ft_ordinary: 1133 if (c == '.') { 1134 if (count == 0) 1135 return (DNS_R_EMPTYLABEL); 1136 *label = count; 1137 labels++; 1138 INSIST(labels <= 127); 1139 offsets[labels] = nused; 1140 if (tlen == 0) { 1141 labels++; 1142 *ndata++ = 0; 1143 nrem--; 1144 nused++; 1145 done = ISC_TRUE; 1146 } 1147 state = ft_start; 1148 } else if (c == '\\') { 1149 state = ft_escape; 1150 } else { 1151 if (count >= 63) 1152 return (DNS_R_LABELTOOLONG); 1153 count++; 1154 CONVERTTOASCII(c); 1155 if (downcase) 1156 c = maptolower[(int)c]; 1157 *ndata++ = c; 1158 nrem--; 1159 nused++; 1160 } 1161 break; 1162 case ft_initialescape: 1163 if (c == '[') { 1164 /* 1165 * This looks like a bitstring label, which 1166 * was deprecated. Intentionally drop it. 1167 */ 1168 return (DNS_R_BADLABELTYPE); 1169 } 1170 state = ft_escape; 1171 POST(state); 1172 /* FALLTHROUGH */ 1173 case ft_escape: 1174 if (!isdigit(c & 0xff)) { 1175 if (count >= 63) 1176 return (DNS_R_LABELTOOLONG); 1177 count++; 1178 CONVERTTOASCII(c); 1179 if (downcase) 1180 c = maptolower[(int)c]; 1181 *ndata++ = c; 1182 nrem--; 1183 nused++; 1184 state = ft_ordinary; 1185 break; 1186 } 1187 digits = 0; 1188 value = 0; 1189 state = ft_escdecimal; 1190 /* FALLTHROUGH */ 1191 case ft_escdecimal: 1192 if (!isdigit(c & 0xff)) 1193 return (DNS_R_BADESCAPE); 1194 value *= 10; 1195 value += digitvalue[(int)c]; 1196 digits++; 1197 if (digits == 3) { 1198 if (value > 255) 1199 return (DNS_R_BADESCAPE); 1200 if (count >= 63) 1201 return (DNS_R_LABELTOOLONG); 1202 count++; 1203 if (downcase) 1204 value = maptolower[value]; 1205 *ndata++ = value; 1206 nrem--; 1207 nused++; 1208 state = ft_ordinary; 1209 } 1210 break; 1211 default: 1212 FATAL_ERROR(__FILE__, __LINE__, 1213 "Unexpected state %d", state); 1214 /* Does not return. */ 1215 } 1216 } 1217 1218 if (!done) { 1219 if (nrem == 0) 1220 return (ISC_R_NOSPACE); 1221 INSIST(tlen == 0); 1222 if (state != ft_ordinary && state != ft_at) 1223 return (ISC_R_UNEXPECTEDEND); 1224 if (state == ft_ordinary) { 1225 INSIST(count != 0); 1226 *label = count; 1227 labels++; 1228 INSIST(labels <= 127); 1229 offsets[labels] = nused; 1230 } 1231 if (origin != NULL) { 1232 if (nrem < origin->length) 1233 return (ISC_R_NOSPACE); 1234 label = origin->ndata; 1235 n1 = origin->length; 1236 nrem -= n1; 1237 POST(nrem); 1238 while (n1 > 0) { 1239 n2 = *label++; 1240 INSIST(n2 <= 63); /* no bitstring support */ 1241 *ndata++ = n2; 1242 n1 -= n2 + 1; 1243 nused += n2 + 1; 1244 while (n2 > 0) { 1245 c = *label++; 1246 if (downcase) 1247 c = maptolower[(int)c]; 1248 *ndata++ = c; 1249 n2--; 1250 } 1251 labels++; 1252 if (n1 > 0) { 1253 INSIST(labels <= 127); 1254 offsets[labels] = nused; 1255 } 1256 } 1257 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1258 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1259 } 1260 } else 1261 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1262 1263 name->ndata = (unsigned char *)target->base + target->used; 1264 name->labels = labels; 1265 name->length = nused; 1266 1267 isc_buffer_forward(source, tused); 1268 isc_buffer_add(target, name->length); 1269 1270 return (ISC_R_SUCCESS); 1271} 1272 1273#ifdef ISC_PLATFORM_USETHREADS 1274static void 1275free_specific(void *arg) { 1276 dns_name_totextfilter_t *mem = arg; 1277 isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); 1278 /* Stop use being called again. */ 1279 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL); 1280} 1281 1282static void 1283thread_key_mutex_init(void) { 1284 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS); 1285} 1286 1287static isc_result_t 1288totext_filter_proc_key_init(void) { 1289 isc_result_t result; 1290 1291 /* 1292 * We need the call to isc_once_do() to support profiled mutex 1293 * otherwise thread_key_mutex could be initialized at compile time. 1294 */ 1295 result = isc_once_do(&once, thread_key_mutex_init); 1296 if (result != ISC_R_SUCCESS) 1297 return (result); 1298 1299 if (!thread_key_initialized) { 1300 LOCK(&thread_key_mutex); 1301 if (thread_key_mctx == NULL) 1302 result = isc_mem_create2(0, 0, &thread_key_mctx, 0); 1303 if (result != ISC_R_SUCCESS) 1304 goto unlock; 1305 isc_mem_setname(thread_key_mctx, "threadkey", NULL); 1306 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE); 1307 1308 if (!thread_key_initialized && 1309 isc_thread_key_create(&totext_filter_proc_key, 1310 free_specific) != 0) { 1311 result = ISC_R_FAILURE; 1312 isc_mem_detach(&thread_key_mctx); 1313 } else 1314 thread_key_initialized = 1; 1315 unlock: 1316 UNLOCK(&thread_key_mutex); 1317 } 1318 return (result); 1319} 1320#endif 1321 1322isc_result_t 1323dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, 1324 isc_buffer_t *target) 1325{ 1326 unsigned int options = DNS_NAME_MASTERFILE; 1327 1328 if (omit_final_dot) 1329 options |= DNS_NAME_OMITFINALDOT; 1330 return (dns_name_totext2(name, options, target)); 1331} 1332 1333isc_result_t 1334dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) { 1335 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target)); 1336} 1337 1338isc_result_t 1339dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target) 1340{ 1341 unsigned char *ndata; 1342 char *tdata; 1343 unsigned int nlen, tlen; 1344 unsigned char c; 1345 unsigned int trem, count; 1346 unsigned int labels; 1347 isc_boolean_t saw_root = ISC_FALSE; 1348 unsigned int oused = target->used; 1349#ifdef ISC_PLATFORM_USETHREADS 1350 dns_name_totextfilter_t *mem; 1351 dns_name_totextfilter_t totext_filter_proc = NULL; 1352 isc_result_t result; 1353#endif 1354 isc_boolean_t omit_final_dot = 1355 ISC_TF(options & DNS_NAME_OMITFINALDOT); 1356 1357 /* 1358 * This function assumes the name is in proper uncompressed 1359 * wire format. 1360 */ 1361 REQUIRE(VALID_NAME(name)); 1362 REQUIRE(ISC_BUFFER_VALID(target)); 1363 1364#ifdef ISC_PLATFORM_USETHREADS 1365 result = totext_filter_proc_key_init(); 1366 if (result != ISC_R_SUCCESS) 1367 return (result); 1368#endif 1369 ndata = name->ndata; 1370 nlen = name->length; 1371 labels = name->labels; 1372 tdata = isc_buffer_used(target); 1373 tlen = isc_buffer_availablelength(target); 1374 1375 trem = tlen; 1376 1377 if (labels == 0 && nlen == 0) { 1378 /* 1379 * Special handling for an empty name. 1380 */ 1381 if (trem == 0) 1382 return (ISC_R_NOSPACE); 1383 1384 /* 1385 * The names of these booleans are misleading in this case. 1386 * This empty name is not necessarily from the root node of 1387 * the DNS root zone, nor is a final dot going to be included. 1388 * They need to be set this way, though, to keep the "@" 1389 * from being trounced. 1390 */ 1391 saw_root = ISC_TRUE; 1392 omit_final_dot = ISC_FALSE; 1393 *tdata++ = '@'; 1394 trem--; 1395 1396 /* 1397 * Skip the while() loop. 1398 */ 1399 nlen = 0; 1400 } else if (nlen == 1 && labels == 1 && *ndata == '\0') { 1401 /* 1402 * Special handling for the root label. 1403 */ 1404 if (trem == 0) 1405 return (ISC_R_NOSPACE); 1406 1407 saw_root = ISC_TRUE; 1408 omit_final_dot = ISC_FALSE; 1409 *tdata++ = '.'; 1410 trem--; 1411 1412 /* 1413 * Skip the while() loop. 1414 */ 1415 nlen = 0; 1416 } 1417 1418 while (labels > 0 && nlen > 0 && trem > 0) { 1419 labels--; 1420 count = *ndata++; 1421 nlen--; 1422 if (count == 0) { 1423 saw_root = ISC_TRUE; 1424 break; 1425 } 1426 if (count < 64) { 1427 INSIST(nlen >= count); 1428 while (count > 0) { 1429 c = *ndata; 1430 switch (c) { 1431 /* Special modifiers in zone files. */ 1432 case 0x40: /* '@' */ 1433 case 0x24: /* '$' */ 1434 if ((options & DNS_NAME_MASTERFILE) == 0) 1435 goto no_escape; 1436 /* FALLTHROUGH */ 1437 case 0x22: /* '"' */ 1438 case 0x28: /* '(' */ 1439 case 0x29: /* ')' */ 1440 case 0x2E: /* '.' */ 1441 case 0x3B: /* ';' */ 1442 case 0x5C: /* '\\' */ 1443 if (trem < 2) 1444 return (ISC_R_NOSPACE); 1445 *tdata++ = '\\'; 1446 CONVERTFROMASCII(c); 1447 *tdata++ = c; 1448 ndata++; 1449 trem -= 2; 1450 nlen--; 1451 break; 1452 no_escape: 1453 default: 1454 if (c > 0x20 && c < 0x7f) { 1455 if (trem == 0) 1456 return (ISC_R_NOSPACE); 1457 CONVERTFROMASCII(c); 1458 *tdata++ = c; 1459 ndata++; 1460 trem--; 1461 nlen--; 1462 } else { 1463 if (trem < 4) 1464 return (ISC_R_NOSPACE); 1465 *tdata++ = 0x5c; 1466 *tdata++ = 0x30 + 1467 ((c / 100) % 10); 1468 *tdata++ = 0x30 + 1469 ((c / 10) % 10); 1470 *tdata++ = 0x30 + (c % 10); 1471 trem -= 4; 1472 ndata++; 1473 nlen--; 1474 } 1475 } 1476 count--; 1477 } 1478 } else { 1479 FATAL_ERROR(__FILE__, __LINE__, 1480 "Unexpected label type %02x", count); 1481 /* NOTREACHED */ 1482 } 1483 1484 /* 1485 * The following assumes names are absolute. If not, we 1486 * fix things up later. Note that this means that in some 1487 * cases one more byte of text buffer is required than is 1488 * needed in the final output. 1489 */ 1490 if (trem == 0) 1491 return (ISC_R_NOSPACE); 1492 *tdata++ = '.'; 1493 trem--; 1494 } 1495 1496 if (nlen != 0 && trem == 0) 1497 return (ISC_R_NOSPACE); 1498 1499 if (!saw_root || omit_final_dot) 1500 trem++; 1501 1502 isc_buffer_add(target, tlen - trem); 1503 1504#ifdef ISC_PLATFORM_USETHREADS 1505 mem = isc_thread_key_getspecific(totext_filter_proc_key); 1506 if (mem != NULL) 1507 totext_filter_proc = *mem; 1508#endif 1509 if (totext_filter_proc != NULL) 1510 return ((*totext_filter_proc)(target, oused, saw_root)); 1511 1512 return (ISC_R_SUCCESS); 1513} 1514 1515isc_result_t 1516dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot, 1517 isc_buffer_t *target) 1518{ 1519 unsigned char *ndata; 1520 char *tdata; 1521 unsigned int nlen, tlen; 1522 unsigned char c; 1523 unsigned int trem, count; 1524 unsigned int labels; 1525 1526 /* 1527 * This function assumes the name is in proper uncompressed 1528 * wire format. 1529 */ 1530 REQUIRE(VALID_NAME(name)); 1531 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 1532 REQUIRE(ISC_BUFFER_VALID(target)); 1533 1534 ndata = name->ndata; 1535 nlen = name->length; 1536 labels = name->labels; 1537 tdata = isc_buffer_used(target); 1538 tlen = isc_buffer_availablelength(target); 1539 1540 trem = tlen; 1541 1542 if (nlen == 1 && labels == 1 && *ndata == '\0') { 1543 /* 1544 * Special handling for the root label. 1545 */ 1546 if (trem == 0) 1547 return (ISC_R_NOSPACE); 1548 1549 omit_final_dot = ISC_FALSE; 1550 *tdata++ = '.'; 1551 trem--; 1552 1553 /* 1554 * Skip the while() loop. 1555 */ 1556 nlen = 0; 1557 } 1558 1559 while (labels > 0 && nlen > 0 && trem > 0) { 1560 labels--; 1561 count = *ndata++; 1562 nlen--; 1563 if (count == 0) 1564 break; 1565 if (count < 64) { 1566 INSIST(nlen >= count); 1567 while (count > 0) { 1568 c = *ndata; 1569 if ((c >= 0x30 && c <= 0x39) || /* digit */ 1570 (c >= 0x41 && c <= 0x5A) || /* uppercase */ 1571 (c >= 0x61 && c <= 0x7A) || /* lowercase */ 1572 c == 0x2D || /* hyphen */ 1573 c == 0x5F) /* underscore */ 1574 { 1575 if (trem == 0) 1576 return (ISC_R_NOSPACE); 1577 /* downcase */ 1578 if (c >= 0x41 && c <= 0x5A) 1579 c += 0x20; 1580 CONVERTFROMASCII(c); 1581 *tdata++ = c; 1582 ndata++; 1583 trem--; 1584 nlen--; 1585 } else { 1586 if (trem < 3) 1587 return (ISC_R_NOSPACE); 1588 sprintf(tdata, "%%%02X", c); 1589 tdata += 3; 1590 trem -= 3; 1591 ndata++; 1592 nlen--; 1593 } 1594 count--; 1595 } 1596 } else { 1597 FATAL_ERROR(__FILE__, __LINE__, 1598 "Unexpected label type %02x", count); 1599 /* NOTREACHED */ 1600 } 1601 1602 /* 1603 * The following assumes names are absolute. If not, we 1604 * fix things up later. Note that this means that in some 1605 * cases one more byte of text buffer is required than is 1606 * needed in the final output. 1607 */ 1608 if (trem == 0) 1609 return (ISC_R_NOSPACE); 1610 *tdata++ = '.'; 1611 trem--; 1612 } 1613 1614 if (nlen != 0 && trem == 0) 1615 return (ISC_R_NOSPACE); 1616 1617 if (omit_final_dot) 1618 trem++; 1619 1620 isc_buffer_add(target, tlen - trem); 1621 1622 return (ISC_R_SUCCESS); 1623} 1624 1625isc_result_t 1626dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) { 1627 unsigned char *sndata, *ndata; 1628 unsigned int nlen, count, labels; 1629 isc_buffer_t buffer; 1630 1631 /* 1632 * Downcase 'source'. 1633 */ 1634 1635 REQUIRE(VALID_NAME(source)); 1636 REQUIRE(VALID_NAME(name)); 1637 if (source == name) { 1638 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0); 1639 isc_buffer_init(&buffer, source->ndata, source->length); 1640 target = &buffer; 1641 ndata = source->ndata; 1642 } else { 1643 REQUIRE(BINDABLE(name)); 1644 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1645 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1646 if (target == NULL) { 1647 target = name->buffer; 1648 isc_buffer_clear(name->buffer); 1649 } 1650 ndata = (unsigned char *)target->base + target->used; 1651 name->ndata = ndata; 1652 } 1653 1654 sndata = source->ndata; 1655 nlen = source->length; 1656 labels = source->labels; 1657 1658 if (nlen > (target->length - target->used)) { 1659 MAKE_EMPTY(name); 1660 return (ISC_R_NOSPACE); 1661 } 1662 1663 while (labels > 0 && nlen > 0) { 1664 labels--; 1665 count = *sndata++; 1666 *ndata++ = count; 1667 nlen--; 1668 if (count < 64) { 1669 INSIST(nlen >= count); 1670 while (count > 0) { 1671 *ndata++ = maptolower[(*sndata++)]; 1672 nlen--; 1673 count--; 1674 } 1675 } else { 1676 FATAL_ERROR(__FILE__, __LINE__, 1677 "Unexpected label type %02x", count); 1678 /* Does not return. */ 1679 } 1680 } 1681 1682 if (source != name) { 1683 name->labels = source->labels; 1684 name->length = source->length; 1685 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1686 name->attributes = DNS_NAMEATTR_ABSOLUTE; 1687 else 1688 name->attributes = 0; 1689 if (name->labels > 0 && name->offsets != NULL) 1690 set_offsets(name, name->offsets, NULL); 1691 } 1692 1693 isc_buffer_add(target, name->length); 1694 1695 return (ISC_R_SUCCESS); 1696} 1697 1698static void 1699set_offsets(const dns_name_t *name, unsigned char *offsets, 1700 dns_name_t *set_name) 1701{ 1702 unsigned int offset, count, length, nlabels; 1703 unsigned char *ndata; 1704 isc_boolean_t absolute; 1705 1706 ndata = name->ndata; 1707 length = name->length; 1708 offset = 0; 1709 nlabels = 0; 1710 absolute = ISC_FALSE; 1711 while (offset != length) { 1712 INSIST(nlabels < 128); 1713 offsets[nlabels++] = offset; 1714 count = *ndata++; 1715 offset++; 1716 INSIST(count <= 63); 1717 offset += count; 1718 ndata += count; 1719 INSIST(offset <= length); 1720 if (count == 0) { 1721 absolute = ISC_TRUE; 1722 break; 1723 } 1724 } 1725 if (set_name != NULL) { 1726 INSIST(set_name == name); 1727 1728 set_name->labels = nlabels; 1729 set_name->length = offset; 1730 if (absolute) 1731 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1732 else 1733 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1734 } 1735 INSIST(nlabels == name->labels); 1736 INSIST(offset == name->length); 1737} 1738 1739isc_result_t 1740dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, 1741 dns_decompress_t *dctx, unsigned int options, 1742 isc_buffer_t *target) 1743{ 1744 unsigned char *cdata, *ndata; 1745 unsigned int cused; /* Bytes of compressed name data used */ 1746 unsigned int nused, labels, n, nmax; 1747 unsigned int current, new_current, biggest_pointer; 1748 isc_boolean_t done; 1749 fw_state state = fw_start; 1750 unsigned int c; 1751 unsigned char *offsets; 1752 dns_offsets_t odata; 1753 isc_boolean_t downcase; 1754 isc_boolean_t seen_pointer; 1755 1756 /* 1757 * Copy the possibly-compressed name at source into target, 1758 * decompressing it. Loop prevention is performed by checking 1759 * the new pointer against biggest_pointer. 1760 */ 1761 1762 REQUIRE(VALID_NAME(name)); 1763 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1764 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1765 1766 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 1767 1768 if (target == NULL && name->buffer != NULL) { 1769 target = name->buffer; 1770 isc_buffer_clear(target); 1771 } 1772 1773 REQUIRE(dctx != NULL); 1774 REQUIRE(BINDABLE(name)); 1775 1776 INIT_OFFSETS(name, offsets, odata); 1777 1778 /* 1779 * Make 'name' empty in case of failure. 1780 */ 1781 MAKE_EMPTY(name); 1782 1783 /* 1784 * Initialize things to make the compiler happy; they're not required. 1785 */ 1786 n = 0; 1787 new_current = 0; 1788 1789 /* 1790 * Set up. 1791 */ 1792 labels = 0; 1793 done = ISC_FALSE; 1794 1795 ndata = isc_buffer_used(target); 1796 nused = 0; 1797 seen_pointer = ISC_FALSE; 1798 1799 /* 1800 * Find the maximum number of uncompressed target name 1801 * bytes we are willing to generate. This is the smaller 1802 * of the available target buffer length and the 1803 * maximum legal domain name length (255). 1804 */ 1805 nmax = isc_buffer_availablelength(target); 1806 if (nmax > DNS_NAME_MAXWIRE) 1807 nmax = DNS_NAME_MAXWIRE; 1808 1809 cdata = isc_buffer_current(source); 1810 cused = 0; 1811 1812 current = source->current; 1813 biggest_pointer = current; 1814 1815 /* 1816 * Note: The following code is not optimized for speed, but 1817 * rather for correctness. Speed will be addressed in the future. 1818 */ 1819 1820 while (current < source->active && !done) { 1821 c = *cdata++; 1822 current++; 1823 if (!seen_pointer) 1824 cused++; 1825 1826 switch (state) { 1827 case fw_start: 1828 if (c < 64) { 1829 offsets[labels] = nused; 1830 labels++; 1831 if (nused + c + 1 > nmax) 1832 goto full; 1833 nused += c + 1; 1834 *ndata++ = c; 1835 if (c == 0) 1836 done = ISC_TRUE; 1837 n = c; 1838 state = fw_ordinary; 1839 } else if (c >= 128 && c < 192) { 1840 /* 1841 * 14 bit local compression pointer. 1842 * Local compression is no longer an 1843 * IETF draft. 1844 */ 1845 return (DNS_R_BADLABELTYPE); 1846 } else if (c >= 192) { 1847 /* 1848 * Ordinary 14-bit pointer. 1849 */ 1850 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 1851 0) 1852 return (DNS_R_DISALLOWED); 1853 new_current = c & 0x3F; 1854 n = 1; 1855 state = fw_newcurrent; 1856 } else 1857 return (DNS_R_BADLABELTYPE); 1858 break; 1859 case fw_ordinary: 1860 if (downcase) 1861 c = maptolower[c]; 1862 /* FALLTHROUGH */ 1863 case fw_copy: 1864 *ndata++ = c; 1865 n--; 1866 if (n == 0) 1867 state = fw_start; 1868 break; 1869 case fw_newcurrent: 1870 new_current *= 256; 1871 new_current += c; 1872 n--; 1873 if (n != 0) 1874 break; 1875 if (new_current >= biggest_pointer) 1876 return (DNS_R_BADPOINTER); 1877 biggest_pointer = new_current; 1878 current = new_current; 1879 cdata = (unsigned char *)source->base + current; 1880 seen_pointer = ISC_TRUE; 1881 state = fw_start; 1882 break; 1883 default: 1884 FATAL_ERROR(__FILE__, __LINE__, 1885 "Unknown state %d", state); 1886 /* Does not return. */ 1887 } 1888 } 1889 1890 if (!done) 1891 return (ISC_R_UNEXPECTEDEND); 1892 1893 name->ndata = (unsigned char *)target->base + target->used; 1894 name->labels = labels; 1895 name->length = nused; 1896 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1897 1898 isc_buffer_forward(source, cused); 1899 isc_buffer_add(target, name->length); 1900 1901 return (ISC_R_SUCCESS); 1902 1903 full: 1904 if (nmax == DNS_NAME_MAXWIRE) 1905 /* 1906 * The name did not fit even though we had a buffer 1907 * big enough to fit a maximum-length name. 1908 */ 1909 return (DNS_R_NAMETOOLONG); 1910 else 1911 /* 1912 * The name might fit if only the caller could give us a 1913 * big enough buffer. 1914 */ 1915 return (ISC_R_NOSPACE); 1916} 1917 1918isc_result_t 1919dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, 1920 isc_buffer_t *target) 1921{ 1922 unsigned int methods; 1923 isc_uint16_t offset; 1924 dns_name_t gp; /* Global compression prefix */ 1925 isc_boolean_t gf; /* Global compression target found */ 1926 isc_uint16_t go; /* Global compression offset */ 1927 dns_offsets_t clo; 1928 dns_name_t clname; 1929 1930 /* 1931 * Convert 'name' into wire format, compressing it as specified by the 1932 * compression context 'cctx', and storing the result in 'target'. 1933 */ 1934 1935 REQUIRE(VALID_NAME(name)); 1936 REQUIRE(cctx != NULL); 1937 REQUIRE(ISC_BUFFER_VALID(target)); 1938 1939 /* 1940 * If 'name' doesn't have an offsets table, make a clone which 1941 * has one. 1942 */ 1943 if (name->offsets == NULL) { 1944#if defined(__clang__) && \ 1945 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)) 1946 memset(&clname, 0, sizeof(clname)); 1947#endif 1948 DNS_NAME_INIT(&clname, clo); 1949 dns_name_clone(name, &clname); 1950 name = &clname; 1951 } 1952 DNS_NAME_INIT(&gp, NULL); 1953 1954 offset = target->used; /*XXX*/ 1955 1956 methods = dns_compress_getmethods(cctx); 1957 1958 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 && 1959 (methods & DNS_COMPRESS_GLOBAL14) != 0) 1960 gf = dns_compress_findglobal(cctx, name, &gp, &go); 1961 else 1962 gf = ISC_FALSE; 1963 1964 /* 1965 * If the offset is too high for 14 bit global compression, we're 1966 * out of luck. 1967 */ 1968 if (gf && go >= 0x4000) 1969 gf = ISC_FALSE; 1970 1971 /* 1972 * Will the compression pointer reduce the message size? 1973 */ 1974 if (gf && (gp.length + 2) >= name->length) 1975 gf = ISC_FALSE; 1976 1977 if (gf) { 1978 if (target->length - target->used < gp.length) 1979 return (ISC_R_NOSPACE); 1980 (void)memcpy((unsigned char *)target->base + target->used, 1981 gp.ndata, (size_t)gp.length); 1982 isc_buffer_add(target, gp.length); 1983 go |= 0xc000; 1984 if (target->length - target->used < 2) 1985 return (ISC_R_NOSPACE); 1986 isc_buffer_putuint16(target, go); 1987 if (gp.length != 0) 1988 dns_compress_add(cctx, name, &gp, offset); 1989 } else { 1990 if (target->length - target->used < name->length) 1991 return (ISC_R_NOSPACE); 1992 (void)memcpy((unsigned char *)target->base + target->used, 1993 name->ndata, (size_t)name->length); 1994 isc_buffer_add(target, name->length); 1995 dns_compress_add(cctx, name, name, offset); 1996 } 1997 return (ISC_R_SUCCESS); 1998} 1999 2000isc_result_t 2001dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, 2002 isc_buffer_t *target) 2003{ 2004 unsigned char *ndata, *offsets; 2005 unsigned int nrem, labels, prefix_length, length; 2006 isc_boolean_t copy_prefix = ISC_TRUE; 2007 isc_boolean_t copy_suffix = ISC_TRUE; 2008 isc_boolean_t absolute = ISC_FALSE; 2009 dns_name_t tmp_name; 2010 dns_offsets_t odata; 2011 2012 /* 2013 * Concatenate 'prefix' and 'suffix'. 2014 */ 2015 2016 REQUIRE(prefix == NULL || VALID_NAME(prefix)); 2017 REQUIRE(suffix == NULL || VALID_NAME(suffix)); 2018 REQUIRE(name == NULL || VALID_NAME(name)); 2019 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 2020 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer))); 2021 if (prefix == NULL || prefix->labels == 0) 2022 copy_prefix = ISC_FALSE; 2023 if (suffix == NULL || suffix->labels == 0) 2024 copy_suffix = ISC_FALSE; 2025 if (copy_prefix && 2026 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 2027 absolute = ISC_TRUE; 2028 REQUIRE(!copy_suffix); 2029 } 2030 if (name == NULL) { 2031 DNS_NAME_INIT(&tmp_name, odata); 2032 name = &tmp_name; 2033 } 2034 if (target == NULL) { 2035 INSIST(name->buffer != NULL); 2036 target = name->buffer; 2037 isc_buffer_clear(name->buffer); 2038 } 2039 2040 REQUIRE(BINDABLE(name)); 2041 2042 /* 2043 * Set up. 2044 */ 2045 nrem = target->length - target->used; 2046 ndata = (unsigned char *)target->base + target->used; 2047 if (nrem > DNS_NAME_MAXWIRE) 2048 nrem = DNS_NAME_MAXWIRE; 2049 length = 0; 2050 prefix_length = 0; 2051 labels = 0; 2052 if (copy_prefix) { 2053 prefix_length = prefix->length; 2054 length += prefix_length; 2055 labels += prefix->labels; 2056 } 2057 if (copy_suffix) { 2058 length += suffix->length; 2059 labels += suffix->labels; 2060 } 2061 if (length > DNS_NAME_MAXWIRE) { 2062 MAKE_EMPTY(name); 2063 return (DNS_R_NAMETOOLONG); 2064 } 2065 if (length > nrem) { 2066 MAKE_EMPTY(name); 2067 return (ISC_R_NOSPACE); 2068 } 2069 2070 if (copy_suffix) { 2071 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2072 absolute = ISC_TRUE; 2073 if (suffix == name && suffix->buffer == target) 2074 memmove(ndata + prefix_length, suffix->ndata, 2075 suffix->length); 2076 else 2077 memcpy(ndata + prefix_length, suffix->ndata, 2078 suffix->length); 2079 } 2080 2081 /* 2082 * If 'prefix' and 'name' are the same object, and the object has 2083 * a dedicated buffer, and we're using it, then we don't have to 2084 * copy anything. 2085 */ 2086 if (copy_prefix && (prefix != name || prefix->buffer != target)) 2087 memcpy(ndata, prefix->ndata, prefix_length); 2088 2089 name->ndata = ndata; 2090 name->labels = labels; 2091 name->length = length; 2092 if (absolute) 2093 name->attributes = DNS_NAMEATTR_ABSOLUTE; 2094 else 2095 name->attributes = 0; 2096 2097 if (name->labels > 0 && name->offsets != NULL) { 2098 INIT_OFFSETS(name, offsets, odata); 2099 set_offsets(name, offsets, NULL); 2100 } 2101 2102 isc_buffer_add(target, name->length); 2103 2104 return (ISC_R_SUCCESS); 2105} 2106 2107void 2108dns_name_split(dns_name_t *name, unsigned int suffixlabels, 2109 dns_name_t *prefix, dns_name_t *suffix) 2110 2111{ 2112 unsigned int splitlabel; 2113 2114 REQUIRE(VALID_NAME(name)); 2115 REQUIRE(suffixlabels > 0); 2116 REQUIRE(suffixlabels < name->labels); 2117 REQUIRE(prefix != NULL || suffix != NULL); 2118 REQUIRE(prefix == NULL || 2119 (VALID_NAME(prefix) && 2120 prefix->buffer != NULL && 2121 BINDABLE(prefix))); 2122 REQUIRE(suffix == NULL || 2123 (VALID_NAME(suffix) && 2124 suffix->buffer != NULL && 2125 BINDABLE(suffix))); 2126 2127 splitlabel = name->labels - suffixlabels; 2128 2129 if (prefix != NULL) 2130 dns_name_getlabelsequence(name, 0, splitlabel, prefix); 2131 2132 if (suffix != NULL) 2133 dns_name_getlabelsequence(name, splitlabel, 2134 suffixlabels, suffix); 2135 2136 return; 2137} 2138 2139isc_result_t 2140dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, 2141 dns_name_t *target) 2142{ 2143 /* 2144 * Make 'target' a dynamically allocated copy of 'source'. 2145 */ 2146 2147 REQUIRE(VALID_NAME(source)); 2148 REQUIRE(source->length > 0); 2149 REQUIRE(VALID_NAME(target)); 2150 REQUIRE(BINDABLE(target)); 2151 2152 /* 2153 * Make 'target' empty in case of failure. 2154 */ 2155 MAKE_EMPTY(target); 2156 2157 target->ndata = isc_mem_get(mctx, source->length); 2158 if (target->ndata == NULL) 2159 return (ISC_R_NOMEMORY); 2160 2161 memcpy(target->ndata, source->ndata, source->length); 2162 2163 target->length = source->length; 2164 target->labels = source->labels; 2165 target->attributes = DNS_NAMEATTR_DYNAMIC; 2166 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2167 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 2168 if (target->offsets != NULL) { 2169 if (source->offsets != NULL) 2170 memcpy(target->offsets, source->offsets, 2171 source->labels); 2172 else 2173 set_offsets(target, target->offsets, NULL); 2174 } 2175 2176 return (ISC_R_SUCCESS); 2177} 2178 2179isc_result_t 2180dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx, 2181 dns_name_t *target) 2182{ 2183 /* 2184 * Make 'target' a read-only dynamically allocated copy of 'source'. 2185 * 'target' will also have a dynamically allocated offsets table. 2186 */ 2187 2188 REQUIRE(VALID_NAME(source)); 2189 REQUIRE(source->length > 0); 2190 REQUIRE(VALID_NAME(target)); 2191 REQUIRE(BINDABLE(target)); 2192 REQUIRE(target->offsets == NULL); 2193 2194 /* 2195 * Make 'target' empty in case of failure. 2196 */ 2197 MAKE_EMPTY(target); 2198 2199 target->ndata = isc_mem_get(mctx, source->length + source->labels); 2200 if (target->ndata == NULL) 2201 return (ISC_R_NOMEMORY); 2202 2203 memcpy(target->ndata, source->ndata, source->length); 2204 2205 target->length = source->length; 2206 target->labels = source->labels; 2207 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS | 2208 DNS_NAMEATTR_READONLY; 2209 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2210 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 2211 target->offsets = target->ndata + source->length; 2212 if (source->offsets != NULL) 2213 memcpy(target->offsets, source->offsets, source->labels); 2214 else 2215 set_offsets(target, target->offsets, NULL); 2216 2217 return (ISC_R_SUCCESS); 2218} 2219 2220void 2221dns_name_free(dns_name_t *name, isc_mem_t *mctx) { 2222 size_t size; 2223 2224 /* 2225 * Free 'name'. 2226 */ 2227 2228 REQUIRE(VALID_NAME(name)); 2229 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0); 2230 2231 size = name->length; 2232 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) 2233 size += name->labels; 2234 isc_mem_put(mctx, name->ndata, size); 2235 dns_name_invalidate(name); 2236} 2237 2238isc_result_t 2239dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) { 2240 dns_name_t downname; 2241 unsigned char data[256]; 2242 isc_buffer_t buffer; 2243 isc_result_t result; 2244 isc_region_t r; 2245 2246 /* 2247 * Send 'name' in DNSSEC canonical form to 'digest'. 2248 */ 2249 2250 REQUIRE(VALID_NAME(name)); 2251 REQUIRE(digest != NULL); 2252 2253#if defined(__clang__) && \ 2254 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)) 2255 memset(&downname, 0, sizeof(downname)); 2256#endif 2257 DNS_NAME_INIT(&downname, NULL); 2258 2259 isc_buffer_init(&buffer, data, sizeof(data)); 2260 2261 result = dns_name_downcase(name, &downname, &buffer); 2262 if (result != ISC_R_SUCCESS) 2263 return (result); 2264 2265 isc_buffer_usedregion(&buffer, &r); 2266 2267 return ((digest)(arg, &r)); 2268} 2269 2270isc_boolean_t 2271dns_name_dynamic(dns_name_t *name) { 2272 REQUIRE(VALID_NAME(name)); 2273 2274 /* 2275 * Returns whether there is dynamic memory associated with this name. 2276 */ 2277 2278 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? 2279 ISC_TRUE : ISC_FALSE); 2280} 2281 2282isc_result_t 2283dns_name_print(dns_name_t *name, FILE *stream) { 2284 isc_result_t result; 2285 isc_buffer_t b; 2286 isc_region_t r; 2287 char t[1024]; 2288 2289 /* 2290 * Print 'name' on 'stream'. 2291 */ 2292 2293 REQUIRE(VALID_NAME(name)); 2294 2295 isc_buffer_init(&b, t, sizeof(t)); 2296 result = dns_name_totext(name, ISC_FALSE, &b); 2297 if (result != ISC_R_SUCCESS) 2298 return (result); 2299 isc_buffer_usedregion(&b, &r); 2300 fprintf(stream, "%.*s", (int)r.length, (char *)r.base); 2301 2302 return (ISC_R_SUCCESS); 2303} 2304 2305isc_result_t 2306dns_name_settotextfilter(dns_name_totextfilter_t proc) { 2307#ifdef ISC_PLATFORM_USETHREADS 2308 isc_result_t result; 2309 dns_name_totextfilter_t *mem; 2310 int res; 2311 2312 result = totext_filter_proc_key_init(); 2313 if (result != ISC_R_SUCCESS) 2314 return (result); 2315 2316 /* 2317 * If we already have been here set / clear as appropriate. 2318 * Otherwise allocate memory. 2319 */ 2320 mem = isc_thread_key_getspecific(totext_filter_proc_key); 2321 if (mem != NULL && proc != NULL) { 2322 *mem = proc; 2323 return (ISC_R_SUCCESS); 2324 } 2325 if (proc == NULL) { 2326 isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); 2327 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL); 2328 if (res != 0) 2329 result = ISC_R_UNEXPECTED; 2330 return (result); 2331 } 2332 2333 mem = isc_mem_get(thread_key_mctx, sizeof(*mem)); 2334 if (mem == NULL) 2335 return (ISC_R_NOMEMORY); 2336 *mem = proc; 2337 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) { 2338 isc_mem_put(thread_key_mctx, mem, sizeof(*mem)); 2339 result = ISC_R_UNEXPECTED; 2340 } 2341 return (result); 2342#else 2343 totext_filter_proc = proc; 2344 return (ISC_R_SUCCESS); 2345#endif 2346} 2347 2348void 2349dns_name_format(dns_name_t *name, char *cp, unsigned int size) { 2350 isc_result_t result; 2351 isc_buffer_t buf; 2352 2353 REQUIRE(size > 0); 2354 2355 /* 2356 * Leave room for null termination after buffer. 2357 */ 2358 isc_buffer_init(&buf, cp, size - 1); 2359 result = dns_name_totext(name, ISC_TRUE, &buf); 2360 if (result == ISC_R_SUCCESS) { 2361 /* 2362 * Null terminate. 2363 */ 2364 isc_region_t r; 2365 isc_buffer_usedregion(&buf, &r); 2366 ((char *) r.base)[r.length] = '\0'; 2367 2368 } else 2369 snprintf(cp, size, "<unknown>"); 2370} 2371 2372/* 2373 * dns_name_tostring() -- similar to dns_name_format() but allocates its own 2374 * memory. 2375 */ 2376isc_result_t 2377dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) { 2378 isc_result_t result; 2379 isc_buffer_t buf; 2380 isc_region_t reg; 2381 char *p, txt[DNS_NAME_FORMATSIZE]; 2382 2383 REQUIRE(VALID_NAME(name)); 2384 REQUIRE(target != NULL && *target == NULL); 2385 2386 isc_buffer_init(&buf, txt, sizeof(txt)); 2387 result = dns_name_totext(name, ISC_FALSE, &buf); 2388 if (result != ISC_R_SUCCESS) 2389 return (result); 2390 2391 isc_buffer_usedregion(&buf, ®); 2392 p = isc_mem_allocate(mctx, reg.length + 1); 2393 memcpy(p, (char *) reg.base, (int) reg.length); 2394 p[reg.length] = '\0'; 2395 2396 *target = p; 2397 return (ISC_R_SUCCESS); 2398} 2399 2400/* 2401 * dns_name_fromstring() -- convert directly from a string to a name, 2402 * allocating memory as needed 2403 */ 2404isc_result_t 2405dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options, 2406 isc_mem_t *mctx) 2407{ 2408 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx)); 2409} 2410 2411isc_result_t 2412dns_name_fromstring2(dns_name_t *target, const char *src, 2413 const dns_name_t *origin, unsigned int options, 2414 isc_mem_t *mctx) 2415{ 2416 isc_result_t result; 2417 isc_buffer_t buf; 2418 dns_fixedname_t fn; 2419 dns_name_t *name; 2420 2421 REQUIRE(src != NULL); 2422 2423 isc_buffer_constinit(&buf, src, strlen(src)); 2424 isc_buffer_add(&buf, strlen(src)); 2425 if (BINDABLE(target) && target->buffer != NULL) 2426 name = target; 2427 else { 2428 dns_fixedname_init(&fn); 2429 name = dns_fixedname_name(&fn); 2430 } 2431 2432 result = dns_name_fromtext(name, &buf, origin, options, NULL); 2433 if (result != ISC_R_SUCCESS) 2434 return (result); 2435 2436 if (name != target) 2437 result = dns_name_dupwithoffsets(name, mctx, target); 2438 return (result); 2439} 2440 2441isc_result_t 2442dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { 2443 unsigned char *ndata; 2444 2445 /* 2446 * Make dest a copy of source. 2447 */ 2448 2449 REQUIRE(VALID_NAME(source)); 2450 REQUIRE(VALID_NAME(dest)); 2451 REQUIRE(target != NULL || dest->buffer != NULL); 2452 2453 if (target == NULL) { 2454 target = dest->buffer; 2455 isc_buffer_clear(dest->buffer); 2456 } 2457 2458 REQUIRE(BINDABLE(dest)); 2459 2460 /* 2461 * Set up. 2462 */ 2463 if (target->length - target->used < source->length) 2464 return (ISC_R_NOSPACE); 2465 2466 ndata = (unsigned char *)target->base + target->used; 2467 dest->ndata = target->base; 2468 2469 memcpy(ndata, source->ndata, source->length); 2470 2471 dest->ndata = ndata; 2472 dest->labels = source->labels; 2473 dest->length = source->length; 2474 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2475 dest->attributes = DNS_NAMEATTR_ABSOLUTE; 2476 else 2477 dest->attributes = 0; 2478 2479 if (dest->labels > 0 && dest->offsets != NULL) { 2480 if (source->offsets != NULL) 2481 memcpy(dest->offsets, source->offsets, source->labels); 2482 else 2483 set_offsets(dest, dest->offsets, NULL); 2484 } 2485 2486 isc_buffer_add(target, dest->length); 2487 2488 return (ISC_R_SUCCESS); 2489} 2490 2491void 2492dns_name_destroy(void) { 2493#ifdef ISC_PLATFORM_USETHREADS 2494 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init) 2495 == ISC_R_SUCCESS); 2496 2497 LOCK(&thread_key_mutex); 2498 if (thread_key_initialized) { 2499 isc_mem_detach(&thread_key_mctx); 2500 isc_thread_key_delete(totext_filter_proc_key); 2501 thread_key_initialized = 0; 2502 } 2503 UNLOCK(&thread_key_mutex); 2504 2505#endif 2506} 2507