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