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