1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* $Id: name.c,v 1.13 2020/02/25 05:00:42 jsg Exp $ */ 18 19 /*! \file */ 20 #include <ctype.h> 21 #include <stdlib.h> 22 #include <isc/buffer.h> 23 #include <isc/hash.h> 24 25 #include <string.h> 26 #include <isc/util.h> 27 28 #include <dns/compress.h> 29 #include <dns/fixedname.h> 30 #include <dns/name.h> 31 #include <dns/result.h> 32 33 typedef enum { 34 ft_init = 0, 35 ft_start, 36 ft_ordinary, 37 ft_initialescape, 38 ft_escape, 39 ft_escdecimal, 40 ft_at 41 } ft_state; 42 43 typedef enum { 44 fw_start = 0, 45 fw_ordinary, 46 fw_newcurrent 47 } fw_state; 48 49 static char digitvalue[256] = { 50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 53 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 54 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 56 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 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, /*256*/ 66 }; 67 68 static unsigned char maptolower[] = { 69 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 70 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 71 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 72 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 73 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 74 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 75 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 76 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 77 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 78 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 79 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 80 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 81 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 82 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 83 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 84 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 85 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 86 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 87 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 88 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 89 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 90 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 91 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 92 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 93 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 94 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 95 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 96 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 97 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 98 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 99 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 100 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff 101 }; 102 103 #define CONVERTTOASCII(c) 104 #define CONVERTFROMASCII(c) 105 106 #define INIT_OFFSETS(name, var, default_offsets) \ 107 if ((name)->offsets != NULL) \ 108 var = (name)->offsets; \ 109 else \ 110 var = (default_offsets); 111 112 #define SETUP_OFFSETS(name, var, default_offsets) \ 113 if ((name)->offsets != NULL) \ 114 var = (name)->offsets; \ 115 else { \ 116 var = (default_offsets); \ 117 set_offsets(name, var, NULL); \ 118 } 119 120 /*% 121 * Note: If additional attributes are added that should not be set for 122 * empty names, MAKE_EMPTY() must be changed so it clears them. 123 */ 124 #define MAKE_EMPTY(name) \ 125 do { \ 126 name->ndata = NULL; \ 127 name->length = 0; \ 128 name->labels = 0; \ 129 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \ 130 } while (0); 131 132 /*% 133 * A name is "bindable" if it can be set to point to a new value, i.e. 134 * name->ndata and name->length may be changed. 135 */ 136 #define BINDABLE(name) \ 137 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \ 138 == 0) 139 140 /*% 141 * Note that the name data must be a char array, not a string 142 * literal, to avoid compiler warnings about discarding 143 * the const attribute of a string. 144 */ 145 static unsigned char root_ndata[] = { "" }; 146 static unsigned char root_offsets[] = { 0 }; 147 148 static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets); 149 150 /* XXXDCL make const? */ 151 dns_name_t *dns_rootname = &root; 152 153 static void 154 set_offsets(const dns_name_t *name, unsigned char *offsets, 155 dns_name_t *set_name); 156 157 void 158 dns_name_init(dns_name_t *name, unsigned char *offsets) { 159 /* 160 * Initialize 'name'. 161 */ 162 name->ndata = NULL; 163 name->length = 0; 164 name->labels = 0; 165 name->attributes = 0; 166 name->offsets = offsets; 167 name->buffer = NULL; 168 ISC_LINK_INIT(name, link); 169 ISC_LIST_INIT(name->list); 170 171 } 172 173 void 174 dns_name_reset(dns_name_t *name) { 175 REQUIRE(BINDABLE(name)); 176 177 name->ndata = NULL; 178 name->length = 0; 179 name->labels = 0; 180 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 181 if (name->buffer != NULL) 182 isc_buffer_clear(name->buffer); 183 } 184 185 void 186 dns_name_invalidate(dns_name_t *name) { 187 /* 188 * Make 'name' invalid. 189 */ 190 191 name->ndata = NULL; 192 name->length = 0; 193 name->labels = 0; 194 name->attributes = 0; 195 name->offsets = NULL; 196 name->buffer = NULL; 197 ISC_LINK_INIT(name, link); 198 } 199 200 void 201 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) { 202 /* 203 * Dedicate a buffer for use with 'name'. 204 */ 205 206 REQUIRE((buffer != NULL && name->buffer == NULL) || 207 (buffer == NULL)); 208 209 name->buffer = buffer; 210 } 211 212 isc_boolean_t 213 dns_name_isabsolute(const dns_name_t *name) { 214 215 /* 216 * Does 'name' end in the root label? 217 */ 218 219 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 220 return (ISC_TRUE); 221 return (ISC_FALSE); 222 } 223 224 unsigned int 225 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) { 226 unsigned int length; 227 228 /* 229 * Provide a hash value for 'name'. 230 */ 231 232 if (name->labels == 0) 233 return (0); 234 235 length = name->length; 236 if (length > 16) 237 length = 16; 238 239 return (isc_hash_function_reverse(name->ndata, length, 240 case_sensitive, NULL)); 241 } 242 243 dns_namereln_t 244 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, 245 int *orderp, unsigned int *nlabelsp) 246 { 247 unsigned int l1, l2, l, count1, count2, count, nlabels; 248 int cdiff, ldiff, chdiff; 249 unsigned char *label1, *label2; 250 unsigned char *offsets1, *offsets2; 251 dns_offsets_t odata1, odata2; 252 dns_namereln_t namereln = dns_namereln_none; 253 254 /* 255 * Determine the relative ordering under the DNSSEC order relation of 256 * 'name1' and 'name2', and also determine the hierarchical 257 * relationship of the names. 258 * 259 * Note: It makes no sense for one of the names to be relative and the 260 * other absolute. If both names are relative, then to be meaningfully 261 * compared the caller must ensure that they are both relative to the 262 * same domain. 263 */ 264 265 REQUIRE(orderp != NULL); 266 REQUIRE(nlabelsp != NULL); 267 /* 268 * Either name1 is absolute and name2 is absolute, or neither is. 269 */ 270 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 271 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 272 273 if (name1 == name2) { 274 *orderp = 0; 275 *nlabelsp = name1->labels; 276 return (dns_namereln_equal); 277 } 278 279 SETUP_OFFSETS(name1, offsets1, odata1); 280 SETUP_OFFSETS(name2, offsets2, odata2); 281 282 nlabels = 0; 283 l1 = name1->labels; 284 l2 = name2->labels; 285 if (l2 > l1) { 286 l = l1; 287 ldiff = 0 - (l2 - l1); 288 } else { 289 l = l2; 290 ldiff = l1 - l2; 291 } 292 293 offsets1 += l1; 294 offsets2 += l2; 295 296 while (l > 0) { 297 l--; 298 offsets1--; 299 offsets2--; 300 label1 = &name1->ndata[*offsets1]; 301 label2 = &name2->ndata[*offsets2]; 302 count1 = *label1++; 303 count2 = *label2++; 304 305 /* 306 * We dropped bitstring labels, and we don't support any 307 * other extended label types. 308 */ 309 INSIST(count1 <= 63 && count2 <= 63); 310 311 cdiff = (int)count1 - (int)count2; 312 if (cdiff < 0) 313 count = count1; 314 else 315 count = count2; 316 317 /* Loop unrolled for performance */ 318 while (count > 3) { 319 chdiff = (int)maptolower[label1[0]] - 320 (int)maptolower[label2[0]]; 321 if (chdiff != 0) { 322 *orderp = chdiff; 323 goto done; 324 } 325 chdiff = (int)maptolower[label1[1]] - 326 (int)maptolower[label2[1]]; 327 if (chdiff != 0) { 328 *orderp = chdiff; 329 goto done; 330 } 331 chdiff = (int)maptolower[label1[2]] - 332 (int)maptolower[label2[2]]; 333 if (chdiff != 0) { 334 *orderp = chdiff; 335 goto done; 336 } 337 chdiff = (int)maptolower[label1[3]] - 338 (int)maptolower[label2[3]]; 339 if (chdiff != 0) { 340 *orderp = chdiff; 341 goto done; 342 } 343 count -= 4; 344 label1 += 4; 345 label2 += 4; 346 } 347 while (count-- > 0) { 348 chdiff = (int)maptolower[*label1++] - 349 (int)maptolower[*label2++]; 350 if (chdiff != 0) { 351 *orderp = chdiff; 352 goto done; 353 } 354 } 355 if (cdiff != 0) { 356 *orderp = cdiff; 357 goto done; 358 } 359 nlabels++; 360 } 361 362 *orderp = ldiff; 363 if (ldiff < 0) 364 namereln = dns_namereln_contains; 365 else if (ldiff > 0) 366 namereln = dns_namereln_subdomain; 367 else 368 namereln = dns_namereln_equal; 369 *nlabelsp = nlabels; 370 return (namereln); 371 372 done: 373 *nlabelsp = nlabels; 374 if (nlabels > 0) 375 namereln = dns_namereln_commonancestor; 376 377 return (namereln); 378 } 379 380 int 381 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) { 382 int order; 383 unsigned int nlabels; 384 385 /* 386 * Determine the relative ordering under the DNSSEC order relation of 387 * 'name1' and 'name2'. 388 * 389 * Note: It makes no sense for one of the names to be relative and the 390 * other absolute. If both names are relative, then to be meaningfully 391 * compared the caller must ensure that they are both relative to the 392 * same domain. 393 */ 394 395 (void)dns_name_fullcompare(name1, name2, &order, &nlabels); 396 397 return (order); 398 } 399 400 isc_boolean_t 401 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) { 402 unsigned int l, count; 403 unsigned char c; 404 unsigned char *label1, *label2; 405 406 /* 407 * Are 'name1' and 'name2' equal? 408 * 409 * Note: It makes no sense for one of the names to be relative and the 410 * other absolute. If both names are relative, then to be meaningfully 411 * compared the caller must ensure that they are both relative to the 412 * same domain. 413 */ 414 415 /* 416 * Either name1 is absolute and name2 is absolute, or neither is. 417 */ 418 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 419 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 420 421 if (name1 == name2) 422 return (ISC_TRUE); 423 424 if (name1->length != name2->length) 425 return (ISC_FALSE); 426 427 l = name1->labels; 428 429 if (l != name2->labels) 430 return (ISC_FALSE); 431 432 label1 = name1->ndata; 433 label2 = name2->ndata; 434 while (l-- > 0) { 435 count = *label1++; 436 if (count != *label2++) 437 return (ISC_FALSE); 438 439 INSIST(count <= 63); /* no bitstring support */ 440 441 /* Loop unrolled for performance */ 442 while (count > 3) { 443 c = maptolower[label1[0]]; 444 if (c != maptolower[label2[0]]) 445 return (ISC_FALSE); 446 c = maptolower[label1[1]]; 447 if (c != maptolower[label2[1]]) 448 return (ISC_FALSE); 449 c = maptolower[label1[2]]; 450 if (c != maptolower[label2[2]]) 451 return (ISC_FALSE); 452 c = maptolower[label1[3]]; 453 if (c != maptolower[label2[3]]) 454 return (ISC_FALSE); 455 count -= 4; 456 label1 += 4; 457 label2 += 4; 458 } 459 while (count-- > 0) { 460 c = maptolower[*label1++]; 461 if (c != maptolower[*label2++]) 462 return (ISC_FALSE); 463 } 464 } 465 466 return (ISC_TRUE); 467 } 468 469 isc_boolean_t 470 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) { 471 472 /* 473 * Are 'name1' and 'name2' equal? 474 * 475 * Note: It makes no sense for one of the names to be relative and the 476 * other absolute. If both names are relative, then to be meaningfully 477 * compared the caller must ensure that they are both relative to the 478 * same domain. 479 */ 480 481 /* 482 * Either name1 is absolute and name2 is absolute, or neither is. 483 */ 484 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 485 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 486 487 if (name1->length != name2->length) 488 return (ISC_FALSE); 489 490 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) 491 return (ISC_FALSE); 492 493 return (ISC_TRUE); 494 } 495 496 isc_boolean_t 497 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) { 498 int order; 499 unsigned int nlabels; 500 dns_namereln_t namereln; 501 502 /* 503 * Is 'name1' a subdomain of 'name2'? 504 * 505 * Note: It makes no sense for one of the names to be relative and the 506 * other absolute. If both names are relative, then to be meaningfully 507 * compared the caller must ensure that they are both relative to the 508 * same domain. 509 */ 510 511 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); 512 if (namereln == dns_namereln_subdomain || 513 namereln == dns_namereln_equal) 514 return (ISC_TRUE); 515 516 return (ISC_FALSE); 517 } 518 519 unsigned int 520 dns_name_countlabels(const dns_name_t *name) { 521 /* 522 * How many labels does 'name' have? 523 */ 524 525 ENSURE(name->labels <= 128); 526 527 return (name->labels); 528 } 529 530 void 531 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) { 532 unsigned char *offsets; 533 dns_offsets_t odata; 534 535 /* 536 * Make 'label' refer to the 'n'th least significant label of 'name'. 537 */ 538 539 REQUIRE(name->labels > 0); 540 REQUIRE(n < name->labels); 541 REQUIRE(label != NULL); 542 543 SETUP_OFFSETS(name, offsets, odata); 544 545 label->base = &name->ndata[offsets[n]]; 546 if (n == name->labels - 1) 547 label->length = name->length - offsets[n]; 548 else 549 label->length = offsets[n + 1] - offsets[n]; 550 } 551 552 void 553 dns_name_getlabelsequence(const dns_name_t *source, 554 unsigned int first, unsigned int n, 555 dns_name_t *target) 556 { 557 unsigned char *offsets; 558 dns_offsets_t odata; 559 unsigned int firstoffset, endoffset; 560 561 /* 562 * Make 'target' refer to the 'n' labels including and following 563 * 'first' in 'source'. 564 */ 565 566 REQUIRE(first <= source->labels); 567 REQUIRE(n <= source->labels - first); /* note first+n could overflow */ 568 REQUIRE(BINDABLE(target)); 569 570 SETUP_OFFSETS(source, offsets, odata); 571 572 if (first == source->labels) 573 firstoffset = source->length; 574 else 575 firstoffset = offsets[first]; 576 577 if (first + n == source->labels) 578 endoffset = source->length; 579 else 580 endoffset = offsets[first + n]; 581 582 target->ndata = &source->ndata[firstoffset]; 583 target->length = endoffset - firstoffset; 584 585 if (first + n == source->labels && n > 0 && 586 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 587 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 588 else 589 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 590 591 target->labels = n; 592 593 /* 594 * If source and target are the same, and we're making target 595 * a prefix of source, the offsets table is correct already 596 * so we don't need to call set_offsets(). 597 */ 598 if (target->offsets != NULL && 599 (target != source || first != 0)) 600 set_offsets(target, target->offsets, NULL); 601 } 602 603 void 604 dns_name_clone(const dns_name_t *source, dns_name_t *target) { 605 606 /* 607 * Make 'target' refer to the same name as 'source'. 608 */ 609 610 REQUIRE(BINDABLE(target)); 611 612 target->ndata = source->ndata; 613 target->length = source->length; 614 target->labels = source->labels; 615 target->attributes = source->attributes & 616 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC | 617 DNS_NAMEATTR_DYNOFFSETS); 618 if (target->offsets != NULL && source->labels > 0) { 619 if (source->offsets != NULL) 620 memmove(target->offsets, source->offsets, 621 source->labels); 622 else 623 set_offsets(target, target->offsets, NULL); 624 } 625 } 626 627 void 628 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) { 629 unsigned char *offsets; 630 dns_offsets_t odata; 631 unsigned int len; 632 isc_region_t r2; 633 634 /* 635 * Make 'name' refer to region 'r'. 636 */ 637 638 REQUIRE(r != NULL); 639 REQUIRE(BINDABLE(name)); 640 641 INIT_OFFSETS(name, offsets, odata); 642 643 if (name->buffer != NULL) { 644 isc_buffer_clear(name->buffer); 645 isc_buffer_availableregion(name->buffer, &r2); 646 len = (r->length < r2.length) ? r->length : r2.length; 647 if (len > DNS_NAME_MAXWIRE) 648 len = DNS_NAME_MAXWIRE; 649 if (len != 0) 650 memmove(r2.base, r->base, len); 651 name->ndata = r2.base; 652 name->length = len; 653 } else { 654 name->ndata = r->base; 655 name->length = (r->length <= DNS_NAME_MAXWIRE) ? 656 r->length : DNS_NAME_MAXWIRE; 657 } 658 659 if (r->length > 0) 660 set_offsets(name, offsets, name); 661 else { 662 name->labels = 0; 663 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 664 } 665 666 if (name->buffer != NULL) 667 isc_buffer_add(name->buffer, name->length); 668 } 669 670 void 671 dns_name_toregion(dns_name_t *name, isc_region_t *r) { 672 /* 673 * Make 'r' refer to 'name'. 674 */ 675 676 REQUIRE(r != NULL); 677 678 r->base = name->ndata; 679 r->length = name->length; 680 } 681 682 isc_result_t 683 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, 684 const dns_name_t *origin, unsigned int options, 685 isc_buffer_t *target) 686 { 687 unsigned char *ndata, *label = NULL; 688 char *tdata; 689 char c; 690 ft_state state; 691 unsigned int value = 0, count = 0; 692 unsigned int n1 = 0, n2 = 0; 693 unsigned int tlen, nrem, nused, digits = 0, labels, tused; 694 isc_boolean_t done; 695 unsigned char *offsets; 696 dns_offsets_t odata; 697 isc_boolean_t downcase; 698 699 /* 700 * Convert the textual representation of a DNS name at source 701 * into uncompressed wire form stored in target. 702 * 703 * Notes: 704 * Relative domain names will have 'origin' appended to them 705 * unless 'origin' is NULL, in which case relative domain names 706 * will remain relative. 707 */ 708 709 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 710 711 if (target == NULL && name->buffer != NULL) { 712 target = name->buffer; 713 isc_buffer_clear(target); 714 } 715 716 REQUIRE(BINDABLE(name)); 717 718 INIT_OFFSETS(name, offsets, odata); 719 offsets[0] = 0; 720 721 /* 722 * Make 'name' empty in case of failure. 723 */ 724 MAKE_EMPTY(name); 725 726 /* 727 * Set up the state machine. 728 */ 729 tdata = (char *)source->base + source->current; 730 tlen = isc_buffer_remaininglength(source); 731 tused = 0; 732 ndata = isc_buffer_used(target); 733 nrem = isc_buffer_availablelength(target); 734 if (nrem > 255) 735 nrem = 255; 736 nused = 0; 737 labels = 0; 738 done = ISC_FALSE; 739 state = ft_init; 740 741 while (nrem > 0 && tlen > 0 && !done) { 742 c = *tdata++; 743 tlen--; 744 tused++; 745 746 switch (state) { 747 case ft_init: 748 /* 749 * Is this the root name? 750 */ 751 if (c == '.') { 752 if (tlen != 0) 753 return (DNS_R_EMPTYLABEL); 754 labels++; 755 *ndata++ = 0; 756 nrem--; 757 nused++; 758 done = ISC_TRUE; 759 break; 760 } 761 if (c == '@' && tlen == 0) { 762 state = ft_at; 763 break; 764 } 765 766 /* FALLTHROUGH */ 767 case ft_start: 768 label = ndata; 769 ndata++; 770 nrem--; 771 nused++; 772 count = 0; 773 if (c == '\\') { 774 state = ft_initialescape; 775 break; 776 } 777 state = ft_ordinary; 778 if (nrem == 0) 779 return (ISC_R_NOSPACE); 780 /* FALLTHROUGH */ 781 case ft_ordinary: 782 if (c == '.') { 783 if (count == 0) 784 return (DNS_R_EMPTYLABEL); 785 *label = count; 786 labels++; 787 INSIST(labels <= 127); 788 offsets[labels] = nused; 789 if (tlen == 0) { 790 labels++; 791 *ndata++ = 0; 792 nrem--; 793 nused++; 794 done = ISC_TRUE; 795 } 796 state = ft_start; 797 } else if (c == '\\') { 798 state = ft_escape; 799 } else { 800 if (count >= 63) 801 return (DNS_R_LABELTOOLONG); 802 count++; 803 CONVERTTOASCII(c); 804 if (downcase) 805 c = maptolower[c & 0xff]; 806 *ndata++ = c; 807 nrem--; 808 nused++; 809 } 810 break; 811 case ft_initialescape: 812 if (c == '[') { 813 /* 814 * This looks like a bitstring label, which 815 * was deprecated. Intentionally drop it. 816 */ 817 return (DNS_R_BADLABELTYPE); 818 } 819 state = ft_escape; 820 POST(state); 821 /* FALLTHROUGH */ 822 case ft_escape: 823 if (!isdigit(c & 0xff)) { 824 if (count >= 63) 825 return (DNS_R_LABELTOOLONG); 826 count++; 827 CONVERTTOASCII(c); 828 if (downcase) 829 c = maptolower[c & 0xff]; 830 *ndata++ = c; 831 nrem--; 832 nused++; 833 state = ft_ordinary; 834 break; 835 } 836 digits = 0; 837 value = 0; 838 state = ft_escdecimal; 839 /* FALLTHROUGH */ 840 case ft_escdecimal: 841 if (!isdigit(c & 0xff)) 842 return (DNS_R_BADESCAPE); 843 value *= 10; 844 value += digitvalue[c & 0xff]; 845 digits++; 846 if (digits == 3) { 847 if (value > 255) 848 return (DNS_R_BADESCAPE); 849 if (count >= 63) 850 return (DNS_R_LABELTOOLONG); 851 count++; 852 if (downcase) 853 value = maptolower[value]; 854 *ndata++ = value; 855 nrem--; 856 nused++; 857 state = ft_ordinary; 858 } 859 break; 860 default: 861 FATAL_ERROR(__FILE__, __LINE__, 862 "Unexpected state %d", state); 863 /* Does not return. */ 864 } 865 } 866 867 if (!done) { 868 if (nrem == 0) 869 return (ISC_R_NOSPACE); 870 INSIST(tlen == 0); 871 if (state != ft_ordinary && state != ft_at) 872 return (ISC_R_UNEXPECTEDEND); 873 if (state == ft_ordinary) { 874 INSIST(count != 0); 875 *label = count; 876 labels++; 877 INSIST(labels <= 127); 878 offsets[labels] = nused; 879 } 880 if (origin != NULL) { 881 if (nrem < origin->length) 882 return (ISC_R_NOSPACE); 883 label = origin->ndata; 884 n1 = origin->length; 885 nrem -= n1; 886 POST(nrem); 887 while (n1 > 0) { 888 n2 = *label++; 889 INSIST(n2 <= 63); /* no bitstring support */ 890 *ndata++ = n2; 891 n1 -= n2 + 1; 892 nused += n2 + 1; 893 while (n2 > 0) { 894 c = *label++; 895 if (downcase) 896 c = maptolower[c & 0xff]; 897 *ndata++ = c; 898 n2--; 899 } 900 labels++; 901 if (n1 > 0) { 902 INSIST(labels <= 127); 903 offsets[labels] = nused; 904 } 905 } 906 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 907 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 908 } 909 } else 910 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 911 912 name->ndata = (unsigned char *)target->base + target->used; 913 name->labels = labels; 914 name->length = nused; 915 916 isc_buffer_forward(source, tused); 917 isc_buffer_add(target, name->length); 918 919 return (ISC_R_SUCCESS); 920 } 921 922 isc_result_t 923 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, 924 isc_buffer_t *target) 925 { 926 unsigned int options = DNS_NAME_MASTERFILE; 927 928 if (omit_final_dot) 929 options |= DNS_NAME_OMITFINALDOT; 930 return (dns_name_totext2(name, options, target)); 931 } 932 933 isc_result_t 934 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target) 935 { 936 unsigned char *ndata; 937 char *tdata; 938 unsigned int nlen, tlen; 939 unsigned char c; 940 unsigned int trem, count; 941 unsigned int labels; 942 isc_boolean_t saw_root = ISC_FALSE; 943 isc_boolean_t omit_final_dot = 944 ISC_TF(options & DNS_NAME_OMITFINALDOT); 945 946 /* 947 * This function assumes the name is in proper uncompressed 948 * wire format. 949 */ 950 951 ndata = name->ndata; 952 nlen = name->length; 953 labels = name->labels; 954 tdata = isc_buffer_used(target); 955 tlen = isc_buffer_availablelength(target); 956 957 trem = tlen; 958 959 if (labels == 0 && nlen == 0) { 960 /* 961 * Special handling for an empty name. 962 */ 963 if (trem == 0) 964 return (ISC_R_NOSPACE); 965 966 /* 967 * The names of these booleans are misleading in this case. 968 * This empty name is not necessarily from the root node of 969 * the DNS root zone, nor is a final dot going to be included. 970 * They need to be set this way, though, to keep the "@" 971 * from being trounced. 972 */ 973 saw_root = ISC_TRUE; 974 omit_final_dot = ISC_FALSE; 975 *tdata++ = '@'; 976 trem--; 977 978 /* 979 * Skip the while() loop. 980 */ 981 nlen = 0; 982 } else if (nlen == 1 && labels == 1 && *ndata == '\0') { 983 /* 984 * Special handling for the root label. 985 */ 986 if (trem == 0) 987 return (ISC_R_NOSPACE); 988 989 saw_root = ISC_TRUE; 990 omit_final_dot = ISC_FALSE; 991 *tdata++ = '.'; 992 trem--; 993 994 /* 995 * Skip the while() loop. 996 */ 997 nlen = 0; 998 } 999 1000 while (labels > 0 && nlen > 0 && trem > 0) { 1001 labels--; 1002 count = *ndata++; 1003 nlen--; 1004 if (count == 0) { 1005 saw_root = ISC_TRUE; 1006 break; 1007 } 1008 if (count < 64) { 1009 INSIST(nlen >= count); 1010 while (count > 0) { 1011 c = *ndata; 1012 switch (c) { 1013 /* Special modifiers in zone files. */ 1014 case 0x40: /* '@' */ 1015 case 0x24: /* '$' */ 1016 if ((options & DNS_NAME_MASTERFILE) == 0) 1017 goto no_escape; 1018 /* FALLTHROUGH */ 1019 case 0x22: /* '"' */ 1020 case 0x28: /* '(' */ 1021 case 0x29: /* ')' */ 1022 case 0x2E: /* '.' */ 1023 case 0x3B: /* ';' */ 1024 case 0x5C: /* '\\' */ 1025 if (trem < 2) 1026 return (ISC_R_NOSPACE); 1027 *tdata++ = '\\'; 1028 CONVERTFROMASCII(c); 1029 *tdata++ = c; 1030 ndata++; 1031 trem -= 2; 1032 nlen--; 1033 break; 1034 no_escape: 1035 default: 1036 if (c > 0x20 && c < 0x7f) { 1037 if (trem == 0) 1038 return (ISC_R_NOSPACE); 1039 CONVERTFROMASCII(c); 1040 *tdata++ = c; 1041 ndata++; 1042 trem--; 1043 nlen--; 1044 } else { 1045 if (trem < 4) 1046 return (ISC_R_NOSPACE); 1047 *tdata++ = 0x5c; 1048 *tdata++ = 0x30 + 1049 ((c / 100) % 10); 1050 *tdata++ = 0x30 + 1051 ((c / 10) % 10); 1052 *tdata++ = 0x30 + (c % 10); 1053 trem -= 4; 1054 ndata++; 1055 nlen--; 1056 } 1057 } 1058 count--; 1059 } 1060 } else { 1061 FATAL_ERROR(__FILE__, __LINE__, 1062 "Unexpected label type %02x", count); 1063 /* NOTREACHED */ 1064 } 1065 1066 /* 1067 * The following assumes names are absolute. If not, we 1068 * fix things up later. Note that this means that in some 1069 * cases one more byte of text buffer is required than is 1070 * needed in the final output. 1071 */ 1072 if (trem == 0) 1073 return (ISC_R_NOSPACE); 1074 *tdata++ = '.'; 1075 trem--; 1076 } 1077 1078 if (nlen != 0 && trem == 0) 1079 return (ISC_R_NOSPACE); 1080 1081 if (!saw_root || omit_final_dot) 1082 trem++; 1083 1084 isc_buffer_add(target, tlen - trem); 1085 1086 return (ISC_R_SUCCESS); 1087 } 1088 1089 isc_result_t 1090 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) { 1091 unsigned char *sndata, *ndata; 1092 unsigned int nlen, count, labels; 1093 isc_buffer_t buffer; 1094 1095 /* 1096 * Downcase 'source'. 1097 */ 1098 1099 if (source == name) { 1100 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0); 1101 isc_buffer_init(&buffer, source->ndata, source->length); 1102 target = &buffer; 1103 ndata = source->ndata; 1104 } else { 1105 REQUIRE(BINDABLE(name)); 1106 if (target == NULL) { 1107 target = name->buffer; 1108 isc_buffer_clear(name->buffer); 1109 } 1110 ndata = (unsigned char *)target->base + target->used; 1111 name->ndata = ndata; 1112 } 1113 1114 sndata = source->ndata; 1115 nlen = source->length; 1116 labels = source->labels; 1117 1118 if (nlen > (target->length - target->used)) { 1119 MAKE_EMPTY(name); 1120 return (ISC_R_NOSPACE); 1121 } 1122 1123 while (labels > 0 && nlen > 0) { 1124 labels--; 1125 count = *sndata++; 1126 *ndata++ = count; 1127 nlen--; 1128 if (count < 64) { 1129 INSIST(nlen >= count); 1130 while (count > 0) { 1131 *ndata++ = maptolower[(*sndata++)]; 1132 nlen--; 1133 count--; 1134 } 1135 } else { 1136 FATAL_ERROR(__FILE__, __LINE__, 1137 "Unexpected label type %02x", count); 1138 /* Does not return. */ 1139 } 1140 } 1141 1142 if (source != name) { 1143 name->labels = source->labels; 1144 name->length = source->length; 1145 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1146 name->attributes = DNS_NAMEATTR_ABSOLUTE; 1147 else 1148 name->attributes = 0; 1149 if (name->labels > 0 && name->offsets != NULL) 1150 set_offsets(name, name->offsets, NULL); 1151 } 1152 1153 isc_buffer_add(target, name->length); 1154 1155 return (ISC_R_SUCCESS); 1156 } 1157 1158 static void 1159 set_offsets(const dns_name_t *name, unsigned char *offsets, 1160 dns_name_t *set_name) 1161 { 1162 unsigned int offset, count, length, nlabels; 1163 unsigned char *ndata; 1164 isc_boolean_t absolute; 1165 1166 ndata = name->ndata; 1167 length = name->length; 1168 offset = 0; 1169 nlabels = 0; 1170 absolute = ISC_FALSE; 1171 while (offset != length) { 1172 INSIST(nlabels < 128); 1173 offsets[nlabels++] = offset; 1174 count = *ndata++; 1175 offset++; 1176 INSIST(count <= 63); 1177 offset += count; 1178 ndata += count; 1179 INSIST(offset <= length); 1180 if (count == 0) { 1181 absolute = ISC_TRUE; 1182 break; 1183 } 1184 } 1185 if (set_name != NULL) { 1186 INSIST(set_name == name); 1187 1188 set_name->labels = nlabels; 1189 set_name->length = offset; 1190 if (absolute) 1191 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1192 else 1193 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1194 } 1195 INSIST(nlabels == name->labels); 1196 INSIST(offset == name->length); 1197 } 1198 1199 isc_result_t 1200 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, 1201 dns_decompress_t *dctx, unsigned int options, 1202 isc_buffer_t *target) 1203 { 1204 unsigned char *cdata, *ndata; 1205 unsigned int cused; /* Bytes of compressed name data used */ 1206 unsigned int nused, labels, n, nmax; 1207 unsigned int current, new_current, biggest_pointer; 1208 isc_boolean_t done; 1209 fw_state state = fw_start; 1210 unsigned int c; 1211 unsigned char *offsets; 1212 dns_offsets_t odata; 1213 isc_boolean_t downcase; 1214 isc_boolean_t seen_pointer; 1215 1216 /* 1217 * Copy the possibly-compressed name at source into target, 1218 * decompressing it. Loop prevention is performed by checking 1219 * the new pointer against biggest_pointer. 1220 */ 1221 1222 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 1223 1224 if (target == NULL && name->buffer != NULL) { 1225 target = name->buffer; 1226 isc_buffer_clear(target); 1227 } 1228 1229 REQUIRE(dctx != NULL); 1230 REQUIRE(BINDABLE(name)); 1231 1232 INIT_OFFSETS(name, offsets, odata); 1233 1234 /* 1235 * Make 'name' empty in case of failure. 1236 */ 1237 MAKE_EMPTY(name); 1238 1239 /* 1240 * Initialize things to make the compiler happy; they're not required. 1241 */ 1242 n = 0; 1243 new_current = 0; 1244 1245 /* 1246 * Set up. 1247 */ 1248 labels = 0; 1249 done = ISC_FALSE; 1250 1251 ndata = isc_buffer_used(target); 1252 nused = 0; 1253 seen_pointer = ISC_FALSE; 1254 1255 /* 1256 * Find the maximum number of uncompressed target name 1257 * bytes we are willing to generate. This is the smaller 1258 * of the available target buffer length and the 1259 * maximum legal domain name length (255). 1260 */ 1261 nmax = isc_buffer_availablelength(target); 1262 if (nmax > DNS_NAME_MAXWIRE) 1263 nmax = DNS_NAME_MAXWIRE; 1264 1265 cdata = isc_buffer_current(source); 1266 cused = 0; 1267 1268 current = source->current; 1269 biggest_pointer = current; 1270 1271 /* 1272 * Note: The following code is not optimized for speed, but 1273 * rather for correctness. Speed will be addressed in the future. 1274 */ 1275 1276 while (current < source->active && !done) { 1277 c = *cdata++; 1278 current++; 1279 if (!seen_pointer) 1280 cused++; 1281 1282 switch (state) { 1283 case fw_start: 1284 if (c < 64) { 1285 offsets[labels] = nused; 1286 labels++; 1287 if (nused + c + 1 > nmax) 1288 goto full; 1289 nused += c + 1; 1290 *ndata++ = c; 1291 if (c == 0) 1292 done = ISC_TRUE; 1293 n = c; 1294 state = fw_ordinary; 1295 } else if (c >= 128 && c < 192) { 1296 /* 1297 * 14 bit local compression pointer. 1298 * Local compression is no longer an 1299 * IETF draft. 1300 */ 1301 return (DNS_R_BADLABELTYPE); 1302 } else if (c >= 192) { 1303 /* 1304 * Ordinary 14-bit pointer. 1305 */ 1306 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 1307 0) 1308 return (DNS_R_DISALLOWED); 1309 new_current = c & 0x3F; 1310 state = fw_newcurrent; 1311 } else 1312 return (DNS_R_BADLABELTYPE); 1313 break; 1314 case fw_ordinary: 1315 if (downcase) 1316 c = maptolower[c]; 1317 *ndata++ = c; 1318 n--; 1319 if (n == 0) 1320 state = fw_start; 1321 break; 1322 case fw_newcurrent: 1323 new_current *= 256; 1324 new_current += c; 1325 if (new_current >= biggest_pointer) 1326 return (DNS_R_BADPOINTER); 1327 biggest_pointer = new_current; 1328 current = new_current; 1329 cdata = (unsigned char *)source->base + current; 1330 seen_pointer = ISC_TRUE; 1331 state = fw_start; 1332 break; 1333 default: 1334 FATAL_ERROR(__FILE__, __LINE__, 1335 "Unknown state %d", state); 1336 /* Does not return. */ 1337 } 1338 } 1339 1340 if (!done) 1341 return (ISC_R_UNEXPECTEDEND); 1342 1343 name->ndata = (unsigned char *)target->base + target->used; 1344 name->labels = labels; 1345 name->length = nused; 1346 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1347 1348 isc_buffer_forward(source, cused); 1349 isc_buffer_add(target, name->length); 1350 1351 return (ISC_R_SUCCESS); 1352 1353 full: 1354 if (nmax == DNS_NAME_MAXWIRE) 1355 /* 1356 * The name did not fit even though we had a buffer 1357 * big enough to fit a maximum-length name. 1358 */ 1359 return (DNS_R_NAMETOOLONG); 1360 else 1361 /* 1362 * The name might fit if only the caller could give us a 1363 * big enough buffer. 1364 */ 1365 return (ISC_R_NOSPACE); 1366 } 1367 1368 isc_result_t 1369 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, 1370 isc_buffer_t *target) 1371 { 1372 unsigned int methods; 1373 uint16_t offset; 1374 dns_name_t gp; /* Global compression prefix */ 1375 isc_boolean_t gf; /* Global compression target found */ 1376 uint16_t go; /* Global compression offset */ 1377 dns_offsets_t clo; 1378 dns_name_t clname; 1379 1380 /* 1381 * Convert 'name' into wire format, compressing it as specified by the 1382 * compression context 'cctx', and storing the result in 'target'. 1383 */ 1384 1385 REQUIRE(cctx != NULL); 1386 1387 /* 1388 * If 'name' doesn't have an offsets table, make a clone which 1389 * has one. 1390 */ 1391 if (name->offsets == NULL) { 1392 dns_name_init(&clname, clo); 1393 dns_name_clone(name, &clname); 1394 name = &clname; 1395 } 1396 dns_name_init(&gp, NULL); 1397 1398 offset = target->used; /*XXX*/ 1399 1400 methods = dns_compress_getmethods(cctx); 1401 1402 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 && 1403 (methods & DNS_COMPRESS_GLOBAL14) != 0) 1404 gf = dns_compress_findglobal(cctx, name, &gp, &go); 1405 else 1406 gf = ISC_FALSE; 1407 1408 /* 1409 * If the offset is too high for 14 bit global compression, we're 1410 * out of luck. 1411 */ 1412 if (gf && go >= 0x4000) 1413 gf = ISC_FALSE; 1414 1415 /* 1416 * Will the compression pointer reduce the message size? 1417 */ 1418 if (gf && (gp.length + 2) >= name->length) 1419 gf = ISC_FALSE; 1420 1421 if (gf) { 1422 if (target->length - target->used < gp.length) 1423 return (ISC_R_NOSPACE); 1424 if (gp.length != 0) { 1425 unsigned char *base = target->base; 1426 (void)memmove(base + target->used, gp.ndata, 1427 (size_t)gp.length); 1428 } 1429 isc_buffer_add(target, gp.length); 1430 go |= 0xc000; 1431 if (target->length - target->used < 2) 1432 return (ISC_R_NOSPACE); 1433 isc_buffer_putuint16(target, go); 1434 if (gp.length != 0) 1435 dns_compress_add(cctx, name, &gp, offset); 1436 } else { 1437 if (target->length - target->used < name->length) 1438 return (ISC_R_NOSPACE); 1439 if (name->length != 0) { 1440 unsigned char *base = target->base; 1441 (void)memmove(base + target->used, name->ndata, 1442 (size_t)name->length); 1443 } 1444 isc_buffer_add(target, name->length); 1445 dns_compress_add(cctx, name, name, offset); 1446 } 1447 return (ISC_R_SUCCESS); 1448 } 1449 1450 isc_result_t 1451 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, 1452 isc_buffer_t *target) 1453 { 1454 unsigned char *ndata, *offsets; 1455 unsigned int nrem, labels, prefix_length, length; 1456 isc_boolean_t copy_prefix = ISC_TRUE; 1457 isc_boolean_t copy_suffix = ISC_TRUE; 1458 isc_boolean_t absolute = ISC_FALSE; 1459 dns_name_t tmp_name; 1460 dns_offsets_t odata; 1461 1462 /* 1463 * Concatenate 'prefix' and 'suffix'. 1464 */ 1465 1466 if (prefix == NULL || prefix->labels == 0) 1467 copy_prefix = ISC_FALSE; 1468 if (suffix == NULL || suffix->labels == 0) 1469 copy_suffix = ISC_FALSE; 1470 if (copy_prefix && 1471 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 1472 absolute = ISC_TRUE; 1473 REQUIRE(!copy_suffix); 1474 } 1475 if (name == NULL) { 1476 dns_name_init(&tmp_name, odata); 1477 name = &tmp_name; 1478 } 1479 if (target == NULL) { 1480 INSIST(name->buffer != NULL); 1481 target = name->buffer; 1482 isc_buffer_clear(name->buffer); 1483 } 1484 1485 REQUIRE(BINDABLE(name)); 1486 1487 /* 1488 * Set up. 1489 */ 1490 nrem = target->length - target->used; 1491 ndata = (unsigned char *)target->base + target->used; 1492 if (nrem > DNS_NAME_MAXWIRE) 1493 nrem = DNS_NAME_MAXWIRE; 1494 length = 0; 1495 prefix_length = 0; 1496 labels = 0; 1497 if (copy_prefix) { 1498 prefix_length = prefix->length; 1499 length += prefix_length; 1500 labels += prefix->labels; 1501 } 1502 if (copy_suffix) { 1503 length += suffix->length; 1504 labels += suffix->labels; 1505 } 1506 if (length > DNS_NAME_MAXWIRE) { 1507 MAKE_EMPTY(name); 1508 return (DNS_R_NAMETOOLONG); 1509 } 1510 if (length > nrem) { 1511 MAKE_EMPTY(name); 1512 return (ISC_R_NOSPACE); 1513 } 1514 1515 if (copy_suffix) { 1516 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1517 absolute = ISC_TRUE; 1518 memmove(ndata + prefix_length, suffix->ndata, suffix->length); 1519 } 1520 1521 /* 1522 * If 'prefix' and 'name' are the same object, and the object has 1523 * a dedicated buffer, and we're using it, then we don't have to 1524 * copy anything. 1525 */ 1526 if (copy_prefix && (prefix != name || prefix->buffer != target)) 1527 memmove(ndata, prefix->ndata, prefix_length); 1528 1529 name->ndata = ndata; 1530 name->labels = labels; 1531 name->length = length; 1532 if (absolute) 1533 name->attributes = DNS_NAMEATTR_ABSOLUTE; 1534 else 1535 name->attributes = 0; 1536 1537 if (name->labels > 0 && name->offsets != NULL) { 1538 INIT_OFFSETS(name, offsets, odata); 1539 set_offsets(name, offsets, NULL); 1540 } 1541 1542 isc_buffer_add(target, name->length); 1543 1544 return (ISC_R_SUCCESS); 1545 } 1546 1547 isc_result_t 1548 dns_name_dup(const dns_name_t *source, 1549 dns_name_t *target) 1550 { 1551 /* 1552 * Make 'target' a dynamically allocated copy of 'source'. 1553 */ 1554 1555 REQUIRE(source->length > 0); 1556 REQUIRE(BINDABLE(target)); 1557 1558 /* 1559 * Make 'target' empty in case of failure. 1560 */ 1561 MAKE_EMPTY(target); 1562 1563 target->ndata = malloc(source->length); 1564 if (target->ndata == NULL) 1565 return (ISC_R_NOMEMORY); 1566 1567 memmove(target->ndata, source->ndata, source->length); 1568 1569 target->length = source->length; 1570 target->labels = source->labels; 1571 target->attributes = DNS_NAMEATTR_DYNAMIC; 1572 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1573 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 1574 if (target->offsets != NULL) { 1575 if (source->offsets != NULL) 1576 memmove(target->offsets, source->offsets, 1577 source->labels); 1578 else 1579 set_offsets(target, target->offsets, NULL); 1580 } 1581 1582 return (ISC_R_SUCCESS); 1583 } 1584 1585 isc_result_t 1586 dns_name_dupwithoffsets(dns_name_t *source, 1587 dns_name_t *target) 1588 { 1589 /* 1590 * Make 'target' a read-only dynamically allocated copy of 'source'. 1591 * 'target' will also have a dynamically allocated offsets table. 1592 */ 1593 1594 REQUIRE(source->length > 0); 1595 REQUIRE(BINDABLE(target)); 1596 REQUIRE(target->offsets == NULL); 1597 1598 /* 1599 * Make 'target' empty in case of failure. 1600 */ 1601 MAKE_EMPTY(target); 1602 1603 target->ndata = malloc(source->length + source->labels); 1604 if (target->ndata == NULL) 1605 return (ISC_R_NOMEMORY); 1606 1607 memmove(target->ndata, source->ndata, source->length); 1608 1609 target->length = source->length; 1610 target->labels = source->labels; 1611 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS | 1612 DNS_NAMEATTR_READONLY; 1613 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1614 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 1615 target->offsets = target->ndata + source->length; 1616 if (source->offsets != NULL) 1617 memmove(target->offsets, source->offsets, source->labels); 1618 else 1619 set_offsets(target, target->offsets, NULL); 1620 1621 return (ISC_R_SUCCESS); 1622 } 1623 1624 void 1625 dns_name_free(dns_name_t *name) { 1626 /* 1627 * Free 'name'. 1628 */ 1629 1630 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0); 1631 1632 free(name->ndata); 1633 dns_name_invalidate(name); 1634 } 1635 1636 isc_boolean_t 1637 dns_name_dynamic(dns_name_t *name) { 1638 1639 /* 1640 * Returns whether there is dynamic memory associated with this name. 1641 */ 1642 1643 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? 1644 ISC_TRUE : ISC_FALSE); 1645 } 1646 1647 void 1648 dns_name_format(dns_name_t *name, char *cp, unsigned int size) { 1649 isc_result_t result; 1650 isc_buffer_t buf; 1651 1652 REQUIRE(size > 0); 1653 1654 /* 1655 * Leave room for null termination after buffer. 1656 */ 1657 isc_buffer_init(&buf, cp, size - 1); 1658 result = dns_name_totext(name, ISC_TRUE, &buf); 1659 if (result == ISC_R_SUCCESS) { 1660 /* 1661 * Null terminate. 1662 */ 1663 isc_region_t r; 1664 isc_buffer_usedregion(&buf, &r); 1665 ((char *) r.base)[r.length] = '\0'; 1666 1667 } else 1668 snprintf(cp, size, "<unknown>"); 1669 } 1670 1671 /* 1672 * dns_name_fromstring() -- convert directly from a string to a name, 1673 * allocating memory as needed 1674 */ 1675 isc_result_t 1676 dns_name_fromstring2(dns_name_t *target, const char *src, 1677 const dns_name_t *origin, unsigned int options) 1678 { 1679 isc_result_t result; 1680 isc_buffer_t buf; 1681 dns_fixedname_t fn; 1682 dns_name_t *name; 1683 1684 REQUIRE(src != NULL); 1685 1686 isc_buffer_init(&buf, (void *)src, strlen(src)); 1687 isc_buffer_add(&buf, strlen(src)); 1688 if (BINDABLE(target) && target->buffer != NULL) 1689 name = target; 1690 else { 1691 dns_fixedname_init(&fn); 1692 name = dns_fixedname_name(&fn); 1693 } 1694 1695 result = dns_name_fromtext(name, &buf, origin, options, NULL); 1696 if (result != ISC_R_SUCCESS) 1697 return (result); 1698 1699 if (name != target) 1700 result = dns_name_dupwithoffsets(name, target); 1701 return (result); 1702 } 1703 1704 isc_result_t 1705 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { 1706 unsigned char *ndata; 1707 1708 /* 1709 * Make dest a copy of source. 1710 */ 1711 1712 REQUIRE(target != NULL || dest->buffer != NULL); 1713 1714 if (target == NULL) { 1715 target = dest->buffer; 1716 isc_buffer_clear(dest->buffer); 1717 } 1718 1719 REQUIRE(BINDABLE(dest)); 1720 1721 /* 1722 * Set up. 1723 */ 1724 if (target->length - target->used < source->length) 1725 return (ISC_R_NOSPACE); 1726 1727 ndata = (unsigned char *)target->base + target->used; 1728 dest->ndata = target->base; 1729 1730 if (source->length != 0) 1731 memmove(ndata, source->ndata, source->length); 1732 1733 dest->ndata = ndata; 1734 dest->labels = source->labels; 1735 dest->length = source->length; 1736 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1737 dest->attributes = DNS_NAMEATTR_ABSOLUTE; 1738 else 1739 dest->attributes = 0; 1740 1741 if (dest->labels > 0 && dest->offsets != NULL) { 1742 if (source->offsets != NULL) 1743 memmove(dest->offsets, source->offsets, source->labels); 1744 else 1745 set_offsets(dest, dest->offsets, NULL); 1746 } 1747 1748 isc_buffer_add(target, dest->length); 1749 1750 return (ISC_R_SUCCESS); 1751 } 1752