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