1 /* $NetBSD: rdata.c,v 1.9 2021/02/19 16:42:16 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 /*! \file */ 15 16 #include <ctype.h> 17 #include <inttypes.h> 18 #include <stdbool.h> 19 20 #include <isc/base64.h> 21 #include <isc/hex.h> 22 #include <isc/lex.h> 23 #include <isc/mem.h> 24 #include <isc/parseint.h> 25 #include <isc/print.h> 26 #include <isc/string.h> 27 #include <isc/util.h> 28 29 #include <dns/callbacks.h> 30 #include <dns/cert.h> 31 #include <dns/compress.h> 32 #include <dns/dsdigest.h> 33 #include <dns/enumtype.h> 34 #include <dns/keyflags.h> 35 #include <dns/keyvalues.h> 36 #include <dns/message.h> 37 #include <dns/rcode.h> 38 #include <dns/rdata.h> 39 #include <dns/rdataclass.h> 40 #include <dns/rdatastruct.h> 41 #include <dns/rdatatype.h> 42 #include <dns/result.h> 43 #include <dns/secalg.h> 44 #include <dns/secproto.h> 45 #include <dns/time.h> 46 #include <dns/ttl.h> 47 48 #define RETERR(x) \ 49 do { \ 50 isc_result_t _r = (x); \ 51 if (_r != ISC_R_SUCCESS) \ 52 return ((_r)); \ 53 } while (/*CONSTCOND*/0) 54 55 #define RETTOK(x) \ 56 do { \ 57 isc_result_t _r = (x); \ 58 if (_r != ISC_R_SUCCESS) { \ 59 isc_lex_ungettoken(lexer, &token); \ 60 return (_r); \ 61 } \ 62 } while (/*CONSTCOND*/0) 63 64 #define CHECK(op) \ 65 do { \ 66 result = (op); \ 67 if (result != ISC_R_SUCCESS) \ 68 goto cleanup; \ 69 } while (/*CONSTCOND*/0) 70 71 #define CHECKTOK(op) \ 72 do { \ 73 result = (op); \ 74 if (result != ISC_R_SUCCESS) { \ 75 isc_lex_ungettoken(lexer, &token); \ 76 goto cleanup; \ 77 } \ 78 } while (/*CONSTCOND*/0) 79 80 #define DNS_AS_STR(t) ((t).value.as_textregion.base) 81 82 #define ARGS_FROMTEXT \ 83 int rdclass, dns_rdatatype_t type, isc_lex_t *lexer, \ 84 const dns_name_t *origin, unsigned int options, \ 85 isc_buffer_t *target, dns_rdatacallbacks_t *callbacks 86 87 #define ARGS_TOTEXT \ 88 dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target 89 90 #define ARGS_FROMWIRE \ 91 int rdclass, dns_rdatatype_t type, isc_buffer_t *source, \ 92 dns_decompress_t *dctx, unsigned int options, \ 93 isc_buffer_t *target 94 95 #define ARGS_TOWIRE \ 96 dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target 97 98 #define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2 99 100 #define ARGS_FROMSTRUCT \ 101 int rdclass, dns_rdatatype_t type, void *source, isc_buffer_t *target 102 103 #define ARGS_TOSTRUCT const dns_rdata_t *rdata, void *target, isc_mem_t *mctx 104 105 #define ARGS_FREESTRUCT void *source 106 107 #define ARGS_ADDLDATA \ 108 dns_rdata_t *rdata, dns_additionaldatafunc_t add, void *arg 109 110 #define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg 111 112 #define ARGS_CHECKOWNER \ 113 const dns_name_t *name, dns_rdataclass_t rdclass, \ 114 dns_rdatatype_t type, bool wildcard 115 116 #define ARGS_CHECKNAMES \ 117 dns_rdata_t *rdata, const dns_name_t *owner, dns_name_t *bad 118 119 /*% 120 * Context structure for the totext_ functions. 121 * Contains formatting options for rdata-to-text 122 * conversion. 123 */ 124 typedef struct dns_rdata_textctx { 125 const dns_name_t *origin; /*%< Current origin, or NULL. */ 126 dns_masterstyle_flags_t flags; /*%< DNS_STYLEFLAG_* */ 127 unsigned int width; /*%< Width of rdata column. */ 128 const char *linebreak; /*%< Line break string. */ 129 } dns_rdata_textctx_t; 130 131 static isc_result_t 132 txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target); 133 134 static isc_result_t 135 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); 136 137 static isc_result_t 138 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target); 139 140 static isc_result_t 141 multitxt_totext(isc_region_t *source, isc_buffer_t *target); 142 143 static isc_result_t 144 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target); 145 146 static bool 147 name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target); 148 149 static unsigned int 150 name_length(const dns_name_t *name); 151 152 static isc_result_t 153 str_totext(const char *source, isc_buffer_t *target); 154 155 static isc_result_t 156 inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target); 157 158 static bool 159 buffer_empty(isc_buffer_t *source); 160 161 static void 162 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region); 163 164 static isc_result_t 165 uint32_tobuffer(uint32_t, isc_buffer_t *target); 166 167 static isc_result_t 168 uint16_tobuffer(uint32_t, isc_buffer_t *target); 169 170 static isc_result_t 171 uint8_tobuffer(uint32_t, isc_buffer_t *target); 172 173 static isc_result_t 174 name_tobuffer(const dns_name_t *name, isc_buffer_t *target); 175 176 static uint32_t 177 uint32_fromregion(isc_region_t *region); 178 179 static uint16_t 180 uint16_fromregion(isc_region_t *region); 181 182 static uint8_t 183 uint8_fromregion(isc_region_t *region); 184 185 static uint8_t 186 uint8_consume_fromregion(isc_region_t *region); 187 188 static isc_result_t 189 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length); 190 191 static int 192 hexvalue(char value); 193 194 static int 195 decvalue(char value); 196 197 static void 198 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...) 199 ISC_FORMAT_PRINTF(2, 3); 200 201 static void 202 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), 203 dns_rdatacallbacks_t *callbacks, const char *name, 204 unsigned long line, isc_token_t *token, isc_result_t result); 205 206 static void 207 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks); 208 209 static isc_result_t 210 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 211 isc_buffer_t *target); 212 213 static void 214 warn_badname(const dns_name_t *name, isc_lex_t *lexer, 215 dns_rdatacallbacks_t *callbacks); 216 217 static void 218 warn_badmx(isc_token_t *token, isc_lex_t *lexer, 219 dns_rdatacallbacks_t *callbacks); 220 221 static uint16_t 222 uint16_consume_fromregion(isc_region_t *region); 223 224 static isc_result_t 225 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 226 isc_buffer_t *target); 227 228 static inline isc_result_t generic_fromtext_key(ARGS_FROMTEXT); 229 230 static inline isc_result_t generic_totext_key(ARGS_TOTEXT); 231 232 static inline isc_result_t generic_fromwire_key(ARGS_FROMWIRE); 233 234 static inline isc_result_t generic_fromstruct_key(ARGS_FROMSTRUCT); 235 236 static inline isc_result_t generic_tostruct_key(ARGS_TOSTRUCT); 237 238 static inline void generic_freestruct_key(ARGS_FREESTRUCT); 239 240 static isc_result_t generic_fromtext_txt(ARGS_FROMTEXT); 241 242 static isc_result_t generic_totext_txt(ARGS_TOTEXT); 243 244 static isc_result_t generic_fromwire_txt(ARGS_FROMWIRE); 245 246 static isc_result_t generic_fromstruct_txt(ARGS_FROMSTRUCT); 247 248 static isc_result_t generic_tostruct_txt(ARGS_TOSTRUCT); 249 250 static void generic_freestruct_txt(ARGS_FREESTRUCT); 251 252 static isc_result_t 253 generic_txt_first(dns_rdata_txt_t *txt); 254 255 static isc_result_t 256 generic_txt_next(dns_rdata_txt_t *txt); 257 258 static isc_result_t 259 generic_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string); 260 261 static isc_result_t generic_totext_ds(ARGS_TOTEXT); 262 263 static isc_result_t generic_tostruct_ds(ARGS_TOSTRUCT); 264 265 static isc_result_t generic_fromtext_ds(ARGS_FROMTEXT); 266 267 static isc_result_t generic_fromwire_ds(ARGS_FROMWIRE); 268 269 static isc_result_t generic_fromstruct_ds(ARGS_FROMSTRUCT); 270 271 static isc_result_t generic_fromtext_tlsa(ARGS_FROMTEXT); 272 273 static isc_result_t generic_totext_tlsa(ARGS_TOTEXT); 274 275 static isc_result_t generic_fromwire_tlsa(ARGS_FROMWIRE); 276 277 static isc_result_t generic_fromstruct_tlsa(ARGS_FROMSTRUCT); 278 279 static isc_result_t generic_tostruct_tlsa(ARGS_TOSTRUCT); 280 281 static void generic_freestruct_tlsa(ARGS_FREESTRUCT); 282 283 /*% INT16 Size */ 284 #define NS_INT16SZ 2 285 /*% IPv6 Address Size */ 286 #define NS_LOCATORSZ 8 287 288 /* 289 * Active Directory gc._msdcs.<forest> prefix. 290 */ 291 static unsigned char gc_msdcs_data[] = "\002gc\006_msdcs"; 292 static unsigned char gc_msdcs_offset[] = { 0, 3 }; 293 294 static dns_name_t const gc_msdcs = DNS_NAME_INITNONABSOLUTE(gc_msdcs_data, 295 gc_msdcs_offset); 296 297 /*% 298 * convert presentation level address to network order binary form. 299 * \return 300 * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 301 * \note 302 * (1) does not touch `dst' unless it's returning 1. 303 */ 304 static inline int 305 locator_pton(const char *src, unsigned char *dst) { 306 static const char xdigits_l[] = "0123456789abcdef", 307 xdigits_u[] = "0123456789ABCDEF"; 308 unsigned char tmp[NS_LOCATORSZ]; 309 unsigned char *tp = tmp, *endp; 310 const char *xdigits; 311 int ch, seen_xdigits; 312 unsigned int val; 313 314 memset(tp, '\0', NS_LOCATORSZ); 315 endp = tp + NS_LOCATORSZ; 316 seen_xdigits = 0; 317 val = 0; 318 while ((ch = *src++) != '\0') { 319 const char *pch; 320 321 pch = strchr((xdigits = xdigits_l), ch); 322 if (pch == NULL) { 323 pch = strchr((xdigits = xdigits_u), ch); 324 } 325 if (pch != NULL) { 326 val <<= 4; 327 val |= (pch - xdigits); 328 if (++seen_xdigits > 4) { 329 return (0); 330 } 331 continue; 332 } 333 if (ch == ':') { 334 if (!seen_xdigits) { 335 return (0); 336 } 337 if (tp + NS_INT16SZ > endp) { 338 return (0); 339 } 340 *tp++ = (unsigned char)(val >> 8) & 0xff; 341 *tp++ = (unsigned char)val & 0xff; 342 seen_xdigits = 0; 343 val = 0; 344 continue; 345 } 346 return (0); 347 } 348 if (seen_xdigits) { 349 if (tp + NS_INT16SZ > endp) { 350 return (0); 351 } 352 *tp++ = (unsigned char)(val >> 8) & 0xff; 353 *tp++ = (unsigned char)val & 0xff; 354 } 355 if (tp != endp) { 356 return (0); 357 } 358 memmove(dst, tmp, NS_LOCATORSZ); 359 return (1); 360 } 361 362 static inline isc_result_t 363 name_duporclone(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { 364 if (mctx != NULL) { 365 dns_name_dup(source, mctx, target); 366 } else { 367 dns_name_clone(source, target); 368 } 369 return (ISC_R_SUCCESS); 370 } 371 372 static inline void * 373 mem_maybedup(isc_mem_t *mctx, void *source, size_t length) { 374 void *copy; 375 376 if (mctx == NULL) { 377 return (source); 378 } 379 copy = isc_mem_allocate(mctx, length); 380 memmove(copy, source, length); 381 382 return (copy); 383 } 384 385 static inline isc_result_t 386 typemap_fromtext(isc_lex_t *lexer, isc_buffer_t *target, bool allow_empty) { 387 isc_token_t token; 388 unsigned char bm[8 * 1024]; /* 64k bits */ 389 dns_rdatatype_t covered, max_used; 390 int octet; 391 unsigned int max_octet, newend, end; 392 int window; 393 bool first = true; 394 395 max_used = 0; 396 bm[0] = 0; 397 end = 0; 398 399 do { 400 RETERR(isc_lex_getmastertoken(lexer, &token, 401 isc_tokentype_string, true)); 402 if (token.type != isc_tokentype_string) { 403 break; 404 } 405 RETTOK(dns_rdatatype_fromtext(&covered, 406 &token.value.as_textregion)); 407 if (covered > max_used) { 408 newend = covered / 8; 409 if (newend > end) { 410 memset(&bm[end + 1], 0, newend - end); 411 end = newend; 412 } 413 max_used = covered; 414 } 415 bm[covered / 8] |= (0x80 >> (covered % 8)); 416 first = false; 417 } while (1); 418 isc_lex_ungettoken(lexer, &token); 419 if (!allow_empty && first) { 420 return (DNS_R_FORMERR); 421 } 422 423 for (window = 0; window < 256; window++) { 424 if (max_used < window * 256) { 425 break; 426 } 427 428 max_octet = max_used - (window * 256); 429 if (max_octet >= 256) { 430 max_octet = 31; 431 } else { 432 max_octet /= 8; 433 } 434 435 /* 436 * Find if we have a type in this window. 437 */ 438 for (octet = max_octet; octet >= 0; octet--) { 439 if (bm[window * 32 + octet] != 0) { 440 break; 441 } 442 } 443 if (octet < 0) { 444 continue; 445 } 446 RETERR(uint8_tobuffer(window, target)); 447 RETERR(uint8_tobuffer(octet + 1, target)); 448 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1)); 449 } 450 return (ISC_R_SUCCESS); 451 } 452 453 static inline isc_result_t 454 typemap_totext(isc_region_t *sr, dns_rdata_textctx_t *tctx, 455 isc_buffer_t *target) { 456 unsigned int i, j, k; 457 unsigned int window, len; 458 bool first = true; 459 460 for (i = 0; i < sr->length; i += len) { 461 if (tctx != NULL && 462 (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 463 RETERR(str_totext(tctx->linebreak, target)); 464 first = true; 465 } 466 INSIST(i + 2 <= sr->length); 467 window = sr->base[i]; 468 len = sr->base[i + 1]; 469 INSIST(len > 0 && len <= 32); 470 i += 2; 471 INSIST(i + len <= sr->length); 472 for (j = 0; j < len; j++) { 473 dns_rdatatype_t t; 474 if (sr->base[i + j] == 0) { 475 continue; 476 } 477 for (k = 0; k < 8; k++) { 478 if ((sr->base[i + j] & (0x80 >> k)) == 0) { 479 continue; 480 } 481 t = window * 256 + j * 8 + k; 482 if (!first) { 483 RETERR(str_totext(" ", target)); 484 } 485 first = false; 486 if (dns_rdatatype_isknown(t)) { 487 RETERR(dns_rdatatype_totext(t, target)); 488 } else { 489 char buf[sizeof("TYPE65535")]; 490 snprintf(buf, sizeof(buf), "TYPE%u", t); 491 RETERR(str_totext(buf, target)); 492 } 493 } 494 } 495 } 496 return (ISC_R_SUCCESS); 497 } 498 499 static isc_result_t 500 typemap_test(isc_region_t *sr, bool allow_empty) { 501 unsigned int window, lastwindow = 0; 502 unsigned int len; 503 bool first = true; 504 unsigned int i; 505 506 for (i = 0; i < sr->length; i += len) { 507 /* 508 * Check for overflow. 509 */ 510 if (i + 2 > sr->length) { 511 RETERR(DNS_R_FORMERR); 512 } 513 window = sr->base[i]; 514 len = sr->base[i + 1]; 515 i += 2; 516 /* 517 * Check that bitmap windows are in the correct order. 518 */ 519 if (!first && window <= lastwindow) { 520 RETERR(DNS_R_FORMERR); 521 } 522 /* 523 * Check for legal lengths. 524 */ 525 if (len < 1 || len > 32) { 526 RETERR(DNS_R_FORMERR); 527 } 528 /* 529 * Check for overflow. 530 */ 531 if (i + len > sr->length) { 532 RETERR(DNS_R_FORMERR); 533 } 534 /* 535 * The last octet of the bitmap must be non zero. 536 */ 537 if (sr->base[i + len - 1] == 0) { 538 RETERR(DNS_R_FORMERR); 539 } 540 lastwindow = window; 541 first = false; 542 } 543 if (i != sr->length) { 544 return (DNS_R_EXTRADATA); 545 } 546 if (!allow_empty && first) { 547 RETERR(DNS_R_FORMERR); 548 } 549 return (ISC_R_SUCCESS); 550 } 551 552 static const char hexdigits[] = "0123456789abcdef"; 553 static const char decdigits[] = "0123456789"; 554 555 #include "code.h" 556 557 #define META 0x0001 558 #define RESERVED 0x0002 559 560 /*** 561 *** Initialization 562 ***/ 563 564 void 565 dns_rdata_init(dns_rdata_t *rdata) { 566 REQUIRE(rdata != NULL); 567 568 rdata->data = NULL; 569 rdata->length = 0; 570 rdata->rdclass = 0; 571 rdata->type = 0; 572 rdata->flags = 0; 573 ISC_LINK_INIT(rdata, link); 574 /* ISC_LIST_INIT(rdata->list); */ 575 } 576 577 void 578 dns_rdata_reset(dns_rdata_t *rdata) { 579 REQUIRE(rdata != NULL); 580 581 REQUIRE(!ISC_LINK_LINKED(rdata, link)); 582 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 583 584 rdata->data = NULL; 585 rdata->length = 0; 586 rdata->rdclass = 0; 587 rdata->type = 0; 588 rdata->flags = 0; 589 } 590 591 /*** 592 *** 593 ***/ 594 595 void 596 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) { 597 REQUIRE(src != NULL); 598 REQUIRE(target != NULL); 599 600 REQUIRE(DNS_RDATA_INITIALIZED(target)); 601 602 REQUIRE(DNS_RDATA_VALIDFLAGS(src)); 603 REQUIRE(DNS_RDATA_VALIDFLAGS(target)); 604 605 target->data = src->data; 606 target->length = src->length; 607 target->rdclass = src->rdclass; 608 target->type = src->type; 609 target->flags = src->flags; 610 } 611 612 /*** 613 *** Comparisons 614 ***/ 615 616 int 617 dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { 618 int result = 0; 619 bool use_default = false; 620 621 REQUIRE(rdata1 != NULL); 622 REQUIRE(rdata2 != NULL); 623 REQUIRE(rdata1->length == 0 || rdata1->data != NULL); 624 REQUIRE(rdata2->length == 0 || rdata2->data != NULL); 625 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); 626 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); 627 628 if (rdata1->rdclass != rdata2->rdclass) { 629 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); 630 } 631 632 if (rdata1->type != rdata2->type) { 633 return (rdata1->type < rdata2->type ? -1 : 1); 634 } 635 636 COMPARESWITCH 637 638 if (use_default) { 639 isc_region_t r1; 640 isc_region_t r2; 641 642 dns_rdata_toregion(rdata1, &r1); 643 dns_rdata_toregion(rdata2, &r2); 644 result = isc_region_compare(&r1, &r2); 645 } 646 return (result); 647 } 648 649 int 650 dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) { 651 int result = 0; 652 bool use_default = false; 653 654 REQUIRE(rdata1 != NULL); 655 REQUIRE(rdata2 != NULL); 656 REQUIRE(rdata1->length == 0 || rdata1->data != NULL); 657 REQUIRE(rdata2->length == 0 || rdata2->data != NULL); 658 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1)); 659 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2)); 660 661 if (rdata1->rdclass != rdata2->rdclass) { 662 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1); 663 } 664 665 if (rdata1->type != rdata2->type) { 666 return (rdata1->type < rdata2->type ? -1 : 1); 667 } 668 669 CASECOMPARESWITCH 670 671 if (use_default) { 672 isc_region_t r1; 673 isc_region_t r2; 674 675 dns_rdata_toregion(rdata1, &r1); 676 dns_rdata_toregion(rdata2, &r2); 677 result = isc_region_compare(&r1, &r2); 678 } 679 return (result); 680 } 681 682 /*** 683 *** Conversions 684 ***/ 685 686 void 687 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 688 dns_rdatatype_t type, isc_region_t *r) { 689 REQUIRE(rdata != NULL); 690 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 691 REQUIRE(r != NULL); 692 693 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 694 695 rdata->data = r->base; 696 rdata->length = r->length; 697 rdata->rdclass = rdclass; 698 rdata->type = type; 699 rdata->flags = 0; 700 } 701 702 void 703 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) { 704 REQUIRE(rdata != NULL); 705 REQUIRE(r != NULL); 706 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 707 708 r->base = rdata->data; 709 r->length = rdata->length; 710 } 711 712 isc_result_t 713 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 714 dns_rdatatype_t type, isc_buffer_t *source, 715 dns_decompress_t *dctx, unsigned int options, 716 isc_buffer_t *target) { 717 isc_result_t result = ISC_R_NOTIMPLEMENTED; 718 isc_region_t region; 719 isc_buffer_t ss; 720 isc_buffer_t st; 721 bool use_default = false; 722 uint32_t activelength; 723 unsigned int length; 724 725 REQUIRE(dctx != NULL); 726 if (rdata != NULL) { 727 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 728 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 729 } 730 REQUIRE(source != NULL); 731 REQUIRE(target != NULL); 732 733 if (type == 0) { 734 return (DNS_R_FORMERR); 735 } 736 737 ss = *source; 738 st = *target; 739 740 activelength = isc_buffer_activelength(source); 741 INSIST(activelength < 65536); 742 743 FROMWIRESWITCH 744 745 if (use_default) { 746 if (activelength > isc_buffer_availablelength(target)) { 747 result = ISC_R_NOSPACE; 748 } else { 749 isc_buffer_putmem(target, isc_buffer_current(source), 750 activelength); 751 isc_buffer_forward(source, activelength); 752 result = ISC_R_SUCCESS; 753 } 754 } 755 756 /* 757 * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH 758 * as we cannot transmit it. 759 */ 760 length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 761 if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 762 result = DNS_R_FORMERR; 763 } 764 765 /* 766 * We should have consumed all of our buffer. 767 */ 768 if (result == ISC_R_SUCCESS && !buffer_empty(source)) { 769 result = DNS_R_EXTRADATA; 770 } 771 772 if (rdata != NULL && result == ISC_R_SUCCESS) { 773 region.base = isc_buffer_used(&st); 774 region.length = length; 775 dns_rdata_fromregion(rdata, rdclass, type, ®ion); 776 } 777 778 if (result != ISC_R_SUCCESS) { 779 *source = ss; 780 *target = st; 781 } 782 return (result); 783 } 784 785 isc_result_t 786 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, 787 isc_buffer_t *target) { 788 isc_result_t result = ISC_R_NOTIMPLEMENTED; 789 bool use_default = false; 790 isc_region_t tr; 791 isc_buffer_t st; 792 793 REQUIRE(rdata != NULL); 794 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 795 796 /* 797 * Some DynDNS meta-RRs have empty rdata. 798 */ 799 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 800 INSIST(rdata->length == 0); 801 return (ISC_R_SUCCESS); 802 } 803 804 st = *target; 805 806 TOWIRESWITCH 807 808 if (use_default) { 809 isc_buffer_availableregion(target, &tr); 810 if (tr.length < rdata->length) { 811 return (ISC_R_NOSPACE); 812 } 813 memmove(tr.base, rdata->data, rdata->length); 814 isc_buffer_add(target, rdata->length); 815 return (ISC_R_SUCCESS); 816 } 817 if (result != ISC_R_SUCCESS) { 818 *target = st; 819 INSIST(target->used < 65536); 820 dns_compress_rollback(cctx, (uint16_t)target->used); 821 } 822 return (result); 823 } 824 825 /* 826 * If the binary data in 'src' is valid uncompressed wire format 827 * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS 828 * and copy the validated rdata to 'dest'. Otherwise return an error. 829 */ 830 static isc_result_t 831 rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, 832 dns_rdatatype_t type) { 833 dns_decompress_t dctx; 834 isc_result_t result; 835 836 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); 837 isc_buffer_setactive(src, isc_buffer_usedlength(src)); 838 result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest); 839 dns_decompress_invalidate(&dctx); 840 841 return (result); 842 } 843 844 static isc_result_t 845 unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type, 846 isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target) { 847 isc_result_t result; 848 isc_buffer_t *buf = NULL; 849 isc_token_t token; 850 851 if (type == 0 || dns_rdatatype_ismeta(type)) { 852 return (DNS_R_METATYPE); 853 } 854 855 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 856 false)); 857 if (token.value.as_ulong > 65535U) { 858 return (ISC_R_RANGE); 859 } 860 isc_buffer_allocate(mctx, &buf, token.value.as_ulong); 861 862 if (token.value.as_ulong != 0U) { 863 result = isc_hex_tobuffer(lexer, buf, 864 (unsigned int)token.value.as_ulong); 865 if (result != ISC_R_SUCCESS) { 866 goto failure; 867 } 868 if (isc_buffer_usedlength(buf) != token.value.as_ulong) { 869 result = ISC_R_UNEXPECTEDEND; 870 goto failure; 871 } 872 } 873 874 if (dns_rdatatype_isknown(type)) { 875 result = rdata_validate(buf, target, rdclass, type); 876 } else { 877 isc_region_t r; 878 isc_buffer_usedregion(buf, &r); 879 result = isc_buffer_copyregion(target, &r); 880 } 881 if (result != ISC_R_SUCCESS) { 882 goto failure; 883 } 884 885 isc_buffer_free(&buf); 886 return (ISC_R_SUCCESS); 887 888 failure: 889 isc_buffer_free(&buf); 890 return (result); 891 } 892 893 isc_result_t 894 dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 895 dns_rdatatype_t type, isc_lex_t *lexer, 896 const dns_name_t *origin, unsigned int options, 897 isc_mem_t *mctx, isc_buffer_t *target, 898 dns_rdatacallbacks_t *callbacks) { 899 isc_result_t result = ISC_R_NOTIMPLEMENTED; 900 isc_region_t region; 901 isc_buffer_t st; 902 isc_token_t token; 903 unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | 904 ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; 905 char *name; 906 unsigned long line; 907 void (*callback)(dns_rdatacallbacks_t *, const char *, ...); 908 isc_result_t tresult; 909 unsigned int length; 910 bool unknown; 911 912 REQUIRE(origin == NULL || dns_name_isabsolute(origin)); 913 if (rdata != NULL) { 914 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 915 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 916 } 917 if (callbacks != NULL) { 918 REQUIRE(callbacks->warn != NULL); 919 REQUIRE(callbacks->error != NULL); 920 } 921 922 st = *target; 923 924 if (callbacks != NULL) { 925 callback = callbacks->error; 926 } else { 927 callback = default_fromtext_callback; 928 } 929 930 result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 931 true); 932 if (result != ISC_R_SUCCESS) { 933 name = isc_lex_getsourcename(lexer); 934 line = isc_lex_getsourceline(lexer); 935 fromtext_error(callback, callbacks, name, line, NULL, result); 936 return (result); 937 } 938 939 unknown = false; 940 if (token.type == isc_tokentype_string && 941 strcmp(DNS_AS_STR(token), "\\#") == 0) { 942 /* 943 * If this is a TXT record '\#' could be a escaped '#'. 944 * Look to see if the next token is a number and if so 945 * treat it as a unknown record format. 946 */ 947 if (type == dns_rdatatype_txt) { 948 result = isc_lex_getmastertoken( 949 lexer, &token, isc_tokentype_number, false); 950 if (result == ISC_R_SUCCESS) { 951 isc_lex_ungettoken(lexer, &token); 952 } 953 } 954 955 if (result == ISC_R_SUCCESS) { 956 unknown = true; 957 result = unknown_fromtext(rdclass, type, lexer, mctx, 958 target); 959 } else { 960 options |= DNS_RDATA_UNKNOWNESCAPE; 961 } 962 } else { 963 isc_lex_ungettoken(lexer, &token); 964 } 965 966 if (!unknown) { 967 FROMTEXTSWITCH 968 969 /* 970 * Consume to end of line / file. 971 * If not at end of line initially set error code. 972 * Call callback via fromtext_error once if there was an error. 973 */ 974 } 975 do { 976 name = isc_lex_getsourcename(lexer); 977 line = isc_lex_getsourceline(lexer); 978 tresult = isc_lex_gettoken(lexer, lexoptions, &token); 979 if (tresult != ISC_R_SUCCESS) { 980 if (result == ISC_R_SUCCESS) { 981 result = tresult; 982 } 983 if (callback != NULL) { 984 fromtext_error(callback, callbacks, name, line, 985 NULL, result); 986 } 987 break; 988 } else if (token.type != isc_tokentype_eol && 989 token.type != isc_tokentype_eof) { 990 if (result == ISC_R_SUCCESS) { 991 result = DNS_R_EXTRATOKEN; 992 } 993 if (callback != NULL) { 994 fromtext_error(callback, callbacks, name, line, 995 &token, result); 996 callback = NULL; 997 } 998 } else if (result != ISC_R_SUCCESS && callback != NULL) { 999 fromtext_error(callback, callbacks, name, line, &token, 1000 result); 1001 break; 1002 } else { 1003 if (token.type == isc_tokentype_eof) { 1004 fromtext_warneof(lexer, callbacks); 1005 } 1006 break; 1007 } 1008 } while (1); 1009 1010 length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 1011 if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 1012 result = ISC_R_NOSPACE; 1013 } 1014 1015 if (rdata != NULL && result == ISC_R_SUCCESS) { 1016 region.base = isc_buffer_used(&st); 1017 region.length = length; 1018 dns_rdata_fromregion(rdata, rdclass, type, ®ion); 1019 } 1020 if (result != ISC_R_SUCCESS) { 1021 *target = st; 1022 } 1023 return (result); 1024 } 1025 1026 static isc_result_t 1027 unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 1028 isc_buffer_t *target) { 1029 isc_result_t result; 1030 char buf[sizeof("65535")]; 1031 isc_region_t sr; 1032 1033 strlcpy(buf, "\\# ", sizeof(buf)); 1034 result = str_totext(buf, target); 1035 if (result != ISC_R_SUCCESS) { 1036 return (result); 1037 } 1038 1039 dns_rdata_toregion(rdata, &sr); 1040 INSIST(sr.length < 65536); 1041 snprintf(buf, sizeof(buf), "%u", sr.length); 1042 result = str_totext(buf, target); 1043 if (result != ISC_R_SUCCESS) { 1044 return (result); 1045 } 1046 1047 if (sr.length != 0U) { 1048 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 1049 result = str_totext(" ( ", target); 1050 } else { 1051 result = str_totext(" ", target); 1052 } 1053 1054 if (result != ISC_R_SUCCESS) { 1055 return (result); 1056 } 1057 1058 if (tctx->width == 0) { /* No splitting */ 1059 result = isc_hex_totext(&sr, 0, "", target); 1060 } else { 1061 result = isc_hex_totext(&sr, tctx->width - 2, 1062 tctx->linebreak, target); 1063 } 1064 if (result == ISC_R_SUCCESS && 1065 (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 1066 result = str_totext(" )", target); 1067 } 1068 } 1069 return (result); 1070 } 1071 1072 static isc_result_t 1073 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 1074 isc_buffer_t *target) { 1075 isc_result_t result = ISC_R_NOTIMPLEMENTED; 1076 bool use_default = false; 1077 unsigned int cur; 1078 1079 REQUIRE(rdata != NULL); 1080 REQUIRE(tctx->origin == NULL || dns_name_isabsolute(tctx->origin)); 1081 1082 /* 1083 * Some DynDNS meta-RRs have empty rdata. 1084 */ 1085 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 1086 INSIST(rdata->length == 0); 1087 return (ISC_R_SUCCESS); 1088 } 1089 1090 if ((tctx->flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0) { 1091 return (unknown_totext(rdata, tctx, target)); 1092 } 1093 1094 cur = isc_buffer_usedlength(target); 1095 1096 TOTEXTSWITCH 1097 1098 if (use_default || (result == ISC_R_NOTIMPLEMENTED)) { 1099 unsigned int u = isc_buffer_usedlength(target); 1100 1101 INSIST(u >= cur); 1102 isc_buffer_subtract(target, u - cur); 1103 result = unknown_totext(rdata, tctx, target); 1104 } 1105 1106 return (result); 1107 } 1108 1109 isc_result_t 1110 dns_rdata_totext(dns_rdata_t *rdata, const dns_name_t *origin, 1111 isc_buffer_t *target) { 1112 dns_rdata_textctx_t tctx; 1113 1114 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1115 1116 /* 1117 * Set up formatting options for single-line output. 1118 */ 1119 tctx.origin = origin; 1120 tctx.flags = 0; 1121 tctx.width = 60; 1122 tctx.linebreak = " "; 1123 return (rdata_totext(rdata, &tctx, target)); 1124 } 1125 1126 isc_result_t 1127 dns_rdata_tofmttext(dns_rdata_t *rdata, const dns_name_t *origin, 1128 dns_masterstyle_flags_t flags, unsigned int width, 1129 unsigned int split_width, const char *linebreak, 1130 isc_buffer_t *target) { 1131 dns_rdata_textctx_t tctx; 1132 1133 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1134 1135 /* 1136 * Set up formatting options for formatted output. 1137 */ 1138 tctx.origin = origin; 1139 tctx.flags = flags; 1140 if (split_width == 0xffffffff) { 1141 tctx.width = width; 1142 } else { 1143 tctx.width = split_width; 1144 } 1145 1146 if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) { 1147 tctx.linebreak = linebreak; 1148 } else { 1149 if (split_width == 0xffffffff) { 1150 tctx.width = 60; /* Used for hex word length only. */ 1151 } 1152 tctx.linebreak = " "; 1153 } 1154 return (rdata_totext(rdata, &tctx, target)); 1155 } 1156 1157 isc_result_t 1158 dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass, 1159 dns_rdatatype_t type, void *source, isc_buffer_t *target) { 1160 isc_result_t result = ISC_R_NOTIMPLEMENTED; 1161 isc_buffer_t st; 1162 isc_region_t region; 1163 bool use_default = false; 1164 unsigned int length; 1165 1166 REQUIRE(source != NULL); 1167 if (rdata != NULL) { 1168 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 1169 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1170 } 1171 1172 st = *target; 1173 1174 FROMSTRUCTSWITCH 1175 1176 if (use_default) { 1177 (void)NULL; 1178 } 1179 1180 length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st); 1181 if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH) { 1182 result = ISC_R_NOSPACE; 1183 } 1184 1185 if (rdata != NULL && result == ISC_R_SUCCESS) { 1186 region.base = isc_buffer_used(&st); 1187 region.length = length; 1188 dns_rdata_fromregion(rdata, rdclass, type, ®ion); 1189 } 1190 if (result != ISC_R_SUCCESS) { 1191 *target = st; 1192 } 1193 return (result); 1194 } 1195 1196 isc_result_t 1197 dns_rdata_tostruct(const dns_rdata_t *rdata, void *target, isc_mem_t *mctx) { 1198 isc_result_t result = ISC_R_NOTIMPLEMENTED; 1199 bool use_default = false; 1200 1201 REQUIRE(rdata != NULL); 1202 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1203 1204 TOSTRUCTSWITCH 1205 1206 if (use_default) { 1207 (void)NULL; 1208 } 1209 1210 return (result); 1211 } 1212 1213 void 1214 dns_rdata_freestruct(void *source) { 1215 dns_rdatacommon_t *common = source; 1216 REQUIRE(common != NULL); 1217 1218 FREESTRUCTSWITCH 1219 } 1220 1221 isc_result_t 1222 dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add, 1223 void *arg) { 1224 isc_result_t result = ISC_R_NOTIMPLEMENTED; 1225 bool use_default = false; 1226 1227 /* 1228 * Call 'add' for each name and type from 'rdata' which is subject to 1229 * additional section processing. 1230 */ 1231 1232 REQUIRE(rdata != NULL); 1233 REQUIRE(add != NULL); 1234 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1235 1236 ADDITIONALDATASWITCH 1237 1238 /* No additional processing for unknown types */ 1239 if (use_default) { 1240 result = ISC_R_SUCCESS; 1241 } 1242 1243 return (result); 1244 } 1245 1246 isc_result_t 1247 dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) { 1248 isc_result_t result = ISC_R_NOTIMPLEMENTED; 1249 bool use_default = false; 1250 isc_region_t r; 1251 1252 /* 1253 * Send 'rdata' in DNSSEC canonical form to 'digest'. 1254 */ 1255 1256 REQUIRE(rdata != NULL); 1257 REQUIRE(digest != NULL); 1258 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); 1259 1260 DIGESTSWITCH 1261 1262 if (use_default) { 1263 dns_rdata_toregion(rdata, &r); 1264 result = (digest)(arg, &r); 1265 } 1266 1267 return (result); 1268 } 1269 1270 bool 1271 dns_rdata_checkowner(const dns_name_t *name, dns_rdataclass_t rdclass, 1272 dns_rdatatype_t type, bool wildcard) { 1273 bool result; 1274 1275 CHECKOWNERSWITCH 1276 return (result); 1277 } 1278 1279 bool 1280 dns_rdata_checknames(dns_rdata_t *rdata, const dns_name_t *owner, 1281 dns_name_t *bad) { 1282 bool result; 1283 1284 CHECKNAMESSWITCH 1285 return (result); 1286 } 1287 1288 unsigned int 1289 dns_rdatatype_attributes(dns_rdatatype_t type) { 1290 RDATATYPE_ATTRIBUTE_SW 1291 if (type >= (dns_rdatatype_t)128 && type <= (dns_rdatatype_t)255) { 1292 return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META); 1293 } 1294 return (DNS_RDATATYPEATTR_UNKNOWN); 1295 } 1296 1297 isc_result_t 1298 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { 1299 unsigned int hash; 1300 unsigned int n; 1301 unsigned char a, b; 1302 1303 n = source->length; 1304 1305 if (n == 0) { 1306 return (DNS_R_UNKNOWN); 1307 } 1308 1309 a = tolower((unsigned char)source->base[0]); 1310 b = tolower((unsigned char)source->base[n - 1]); 1311 1312 hash = ((a + n) * b) % 256; 1313 1314 /* 1315 * This switch block is inlined via \#define, and will use "return" 1316 * to return a result to the caller if it is a valid (known) 1317 * rdatatype name. 1318 */ 1319 RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep); 1320 1321 if (source->length > 4 && source->length < (4 + sizeof("65000")) && 1322 strncasecmp("type", source->base, 4) == 0) 1323 { 1324 char buf[sizeof("65000")]; 1325 char *endp; 1326 unsigned int val; 1327 1328 /* 1329 * source->base is not required to be NUL terminated. 1330 * Copy up to remaining bytes and NUL terminate. 1331 */ 1332 snprintf(buf, sizeof(buf), "%.*s", (int)(source->length - 4), 1333 source->base + 4); 1334 val = strtoul(buf, &endp, 10); 1335 if (*endp == '\0' && val <= 0xffff) { 1336 *typep = (dns_rdatatype_t)val; 1337 return (ISC_R_SUCCESS); 1338 } 1339 } 1340 1341 return (DNS_R_UNKNOWN); 1342 } 1343 1344 isc_result_t 1345 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { 1346 RDATATYPE_TOTEXT_SW 1347 1348 return (dns_rdatatype_tounknowntext(type, target)); 1349 } 1350 1351 isc_result_t 1352 dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target) { 1353 char buf[sizeof("TYPE65535")]; 1354 1355 snprintf(buf, sizeof(buf), "TYPE%u", type); 1356 return (str_totext(buf, target)); 1357 } 1358 1359 void 1360 dns_rdatatype_format(dns_rdatatype_t rdtype, char *array, unsigned int size) { 1361 isc_result_t result; 1362 isc_buffer_t buf; 1363 1364 if (size == 0U) { 1365 return; 1366 } 1367 1368 isc_buffer_init(&buf, array, size); 1369 result = dns_rdatatype_totext(rdtype, &buf); 1370 /* 1371 * Null terminate. 1372 */ 1373 if (result == ISC_R_SUCCESS) { 1374 if (isc_buffer_availablelength(&buf) >= 1) { 1375 isc_buffer_putuint8(&buf, 0); 1376 } else { 1377 result = ISC_R_NOSPACE; 1378 } 1379 } 1380 if (result != ISC_R_SUCCESS) { 1381 strlcpy(array, "<unknown>", size); 1382 } 1383 } 1384 1385 /* 1386 * Private function. 1387 */ 1388 1389 static unsigned int 1390 name_length(const dns_name_t *name) { 1391 return (name->length); 1392 } 1393 1394 static isc_result_t 1395 txt_totext(isc_region_t *source, bool quote, isc_buffer_t *target) { 1396 unsigned int tl; 1397 unsigned int n; 1398 unsigned char *sp; 1399 char *tp; 1400 isc_region_t region; 1401 1402 isc_buffer_availableregion(target, ®ion); 1403 sp = source->base; 1404 tp = (char *)region.base; 1405 tl = region.length; 1406 1407 n = *sp++; 1408 1409 REQUIRE(n + 1 <= source->length); 1410 if (n == 0U) { 1411 REQUIRE(quote); 1412 } 1413 1414 if (quote) { 1415 if (tl < 1) { 1416 return (ISC_R_NOSPACE); 1417 } 1418 *tp++ = '"'; 1419 tl--; 1420 } 1421 while (n--) { 1422 /* 1423 * \DDD space (0x20) if not quoting. 1424 */ 1425 if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) { 1426 if (tl < 4) { 1427 return (ISC_R_NOSPACE); 1428 } 1429 *tp++ = 0x5c; 1430 *tp++ = 0x30 + ((*sp / 100) % 10); 1431 *tp++ = 0x30 + ((*sp / 10) % 10); 1432 *tp++ = 0x30 + (*sp % 10); 1433 sp++; 1434 tl -= 4; 1435 continue; 1436 } 1437 /* 1438 * Escape double quote and backslash. If we are not 1439 * enclosing the string in double quotes also escape 1440 * at sign and semicolon. 1441 */ 1442 if (*sp == 0x22 || *sp == 0x5c || 1443 (!quote && (*sp == 0x40 || *sp == 0x3b))) { 1444 if (tl < 2) { 1445 return (ISC_R_NOSPACE); 1446 } 1447 *tp++ = '\\'; 1448 tl--; 1449 } 1450 if (tl < 1) { 1451 return (ISC_R_NOSPACE); 1452 } 1453 *tp++ = *sp++; 1454 tl--; 1455 } 1456 if (quote) { 1457 if (tl < 1) { 1458 return (ISC_R_NOSPACE); 1459 } 1460 *tp++ = '"'; 1461 tl--; 1462 POST(tl); 1463 } 1464 isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 1465 isc_region_consume(source, *source->base + 1); 1466 return (ISC_R_SUCCESS); 1467 } 1468 1469 static isc_result_t 1470 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { 1471 isc_region_t tregion; 1472 bool escape; 1473 unsigned int n, nrem; 1474 char *s; 1475 unsigned char *t; 1476 int d; 1477 int c; 1478 1479 isc_buffer_availableregion(target, &tregion); 1480 s = source->base; 1481 n = source->length; 1482 t = tregion.base; 1483 nrem = tregion.length; 1484 escape = false; 1485 if (nrem < 1) { 1486 return (ISC_R_NOSPACE); 1487 } 1488 /* 1489 * Length byte. 1490 */ 1491 nrem--; 1492 t++; 1493 /* 1494 * Maximum text string length. 1495 */ 1496 if (nrem > 255) { 1497 nrem = 255; 1498 } 1499 while (n-- != 0) { 1500 c = (*s++) & 0xff; 1501 if (escape && (d = decvalue((char)c)) != -1) { 1502 c = d; 1503 if (n == 0) { 1504 return (DNS_R_SYNTAX); 1505 } 1506 n--; 1507 if ((d = decvalue(*s++)) != -1) { 1508 c = c * 10 + d; 1509 } else { 1510 return (DNS_R_SYNTAX); 1511 } 1512 if (n == 0) { 1513 return (DNS_R_SYNTAX); 1514 } 1515 n--; 1516 if ((d = decvalue(*s++)) != -1) { 1517 c = c * 10 + d; 1518 } else { 1519 return (DNS_R_SYNTAX); 1520 } 1521 if (c > 255) { 1522 return (DNS_R_SYNTAX); 1523 } 1524 } else if (!escape && c == '\\') { 1525 escape = true; 1526 continue; 1527 } 1528 escape = false; 1529 if (nrem == 0) { 1530 return ((tregion.length <= 256U) ? ISC_R_NOSPACE 1531 : DNS_R_SYNTAX); 1532 } 1533 *t++ = c; 1534 nrem--; 1535 } 1536 if (escape) { 1537 return (DNS_R_SYNTAX); 1538 } 1539 *tregion.base = (unsigned char)(t - tregion.base - 1); 1540 isc_buffer_add(target, *tregion.base + 1); 1541 return (ISC_R_SUCCESS); 1542 } 1543 1544 static isc_result_t 1545 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { 1546 unsigned int n; 1547 isc_region_t sregion; 1548 isc_region_t tregion; 1549 1550 isc_buffer_activeregion(source, &sregion); 1551 if (sregion.length == 0) { 1552 return (ISC_R_UNEXPECTEDEND); 1553 } 1554 n = *sregion.base + 1; 1555 if (n > sregion.length) { 1556 return (ISC_R_UNEXPECTEDEND); 1557 } 1558 1559 isc_buffer_availableregion(target, &tregion); 1560 if (n > tregion.length) { 1561 return (ISC_R_NOSPACE); 1562 } 1563 1564 if (tregion.base != sregion.base) { 1565 memmove(tregion.base, sregion.base, n); 1566 } 1567 isc_buffer_forward(source, n); 1568 isc_buffer_add(target, n); 1569 return (ISC_R_SUCCESS); 1570 } 1571 1572 /* 1573 * Conversion of TXT-like rdata fields without length limits. 1574 */ 1575 static isc_result_t 1576 multitxt_totext(isc_region_t *source, isc_buffer_t *target) { 1577 unsigned int tl; 1578 unsigned int n0, n; 1579 unsigned char *sp; 1580 char *tp; 1581 isc_region_t region; 1582 1583 isc_buffer_availableregion(target, ®ion); 1584 sp = source->base; 1585 tp = (char *)region.base; 1586 tl = region.length; 1587 1588 if (tl < 1) { 1589 return (ISC_R_NOSPACE); 1590 } 1591 *tp++ = '"'; 1592 tl--; 1593 do { 1594 n = source->length; 1595 n0 = source->length - 1; 1596 1597 while (n--) { 1598 if (*sp < 0x20 || *sp >= 0x7f) { 1599 if (tl < 4) { 1600 return (ISC_R_NOSPACE); 1601 } 1602 *tp++ = 0x5c; 1603 *tp++ = 0x30 + ((*sp / 100) % 10); 1604 *tp++ = 0x30 + ((*sp / 10) % 10); 1605 *tp++ = 0x30 + (*sp % 10); 1606 sp++; 1607 tl -= 4; 1608 continue; 1609 } 1610 /* double quote, backslash */ 1611 if (*sp == 0x22 || *sp == 0x5c) { 1612 if (tl < 2) { 1613 return (ISC_R_NOSPACE); 1614 } 1615 *tp++ = '\\'; 1616 tl--; 1617 } 1618 if (tl < 1) { 1619 return (ISC_R_NOSPACE); 1620 } 1621 *tp++ = *sp++; 1622 tl--; 1623 } 1624 isc_region_consume(source, n0 + 1); 1625 } while (source->length != 0); 1626 if (tl < 1) { 1627 return (ISC_R_NOSPACE); 1628 } 1629 *tp++ = '"'; 1630 tl--; 1631 POST(tl); 1632 isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); 1633 return (ISC_R_SUCCESS); 1634 } 1635 1636 static isc_result_t 1637 multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { 1638 isc_region_t tregion; 1639 bool escape; 1640 unsigned int n, nrem; 1641 char *s; 1642 unsigned char *t0, *t; 1643 int d; 1644 int c; 1645 1646 s = source->base; 1647 n = source->length; 1648 escape = false; 1649 1650 do { 1651 isc_buffer_availableregion(target, &tregion); 1652 t0 = t = tregion.base; 1653 nrem = tregion.length; 1654 if (nrem < 1) { 1655 return (ISC_R_NOSPACE); 1656 } 1657 1658 while (n != 0) { 1659 --n; 1660 c = (*s++) & 0xff; 1661 if (escape && (d = decvalue((char)c)) != -1) { 1662 c = d; 1663 if (n == 0) { 1664 return (DNS_R_SYNTAX); 1665 } 1666 n--; 1667 if ((d = decvalue(*s++)) != -1) { 1668 c = c * 10 + d; 1669 } else { 1670 return (DNS_R_SYNTAX); 1671 } 1672 if (n == 0) { 1673 return (DNS_R_SYNTAX); 1674 } 1675 n--; 1676 if ((d = decvalue(*s++)) != -1) { 1677 c = c * 10 + d; 1678 } else { 1679 return (DNS_R_SYNTAX); 1680 } 1681 if (c > 255) { 1682 return (DNS_R_SYNTAX); 1683 } 1684 } else if (!escape && c == '\\') { 1685 escape = true; 1686 continue; 1687 } 1688 escape = false; 1689 *t++ = c; 1690 nrem--; 1691 if (nrem == 0) { 1692 break; 1693 } 1694 } 1695 if (escape) { 1696 return (DNS_R_SYNTAX); 1697 } 1698 1699 isc_buffer_add(target, (unsigned int)(t - t0)); 1700 } while (n != 0); 1701 return (ISC_R_SUCCESS); 1702 } 1703 1704 static bool 1705 name_prefix(dns_name_t *name, const dns_name_t *origin, dns_name_t *target) { 1706 int l1, l2; 1707 1708 if (origin == NULL) { 1709 goto return_false; 1710 } 1711 1712 if (dns_name_compare(origin, dns_rootname) == 0) { 1713 goto return_false; 1714 } 1715 1716 if (!dns_name_issubdomain(name, origin)) { 1717 goto return_false; 1718 } 1719 1720 l1 = dns_name_countlabels(name); 1721 l2 = dns_name_countlabels(origin); 1722 1723 if (l1 == l2) { 1724 goto return_false; 1725 } 1726 1727 /* Master files should be case preserving. */ 1728 dns_name_getlabelsequence(name, l1 - l2, l2, target); 1729 if (!dns_name_caseequal(origin, target)) { 1730 goto return_false; 1731 } 1732 1733 dns_name_getlabelsequence(name, 0, l1 - l2, target); 1734 return (true); 1735 1736 return_false: 1737 *target = *name; 1738 return (false); 1739 } 1740 1741 static isc_result_t 1742 str_totext(const char *source, isc_buffer_t *target) { 1743 unsigned int l; 1744 isc_region_t region; 1745 1746 isc_buffer_availableregion(target, ®ion); 1747 l = strlen(source); 1748 1749 if (l > region.length) { 1750 return (ISC_R_NOSPACE); 1751 } 1752 1753 memmove(region.base, source, l); 1754 isc_buffer_add(target, l); 1755 return (ISC_R_SUCCESS); 1756 } 1757 1758 static isc_result_t 1759 inet_totext(int af, uint32_t flags, isc_region_t *src, isc_buffer_t *target) { 1760 char tmpbuf[64]; 1761 1762 /* Note - inet_ntop doesn't do size checking on its input. */ 1763 if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL) { 1764 return (ISC_R_NOSPACE); 1765 } 1766 if (strlen(tmpbuf) > isc_buffer_availablelength(target)) { 1767 return (ISC_R_NOSPACE); 1768 } 1769 isc_buffer_putstr(target, tmpbuf); 1770 1771 /* 1772 * An IPv6 address ending in "::" breaks YAML 1773 * parsing, so append 0 in that case. 1774 */ 1775 if (af == AF_INET6 && (flags & DNS_STYLEFLAG_YAML) != 0) { 1776 isc_region_t tr; 1777 isc_buffer_usedregion(target, &tr); 1778 if (tr.base[tr.length - 1] == ':') { 1779 if (isc_buffer_availablelength(target) == 0) { 1780 return (ISC_R_NOSPACE); 1781 } 1782 isc_buffer_putmem(target, (const unsigned char *)"0", 1783 1); 1784 } 1785 } 1786 1787 return (ISC_R_SUCCESS); 1788 } 1789 1790 static bool 1791 buffer_empty(isc_buffer_t *source) { 1792 return ((source->current == source->active) ? true : false); 1793 } 1794 1795 static void 1796 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) { 1797 isc_buffer_init(buffer, region->base, region->length); 1798 isc_buffer_add(buffer, region->length); 1799 isc_buffer_setactive(buffer, region->length); 1800 } 1801 1802 static isc_result_t 1803 uint32_tobuffer(uint32_t value, isc_buffer_t *target) { 1804 isc_region_t region; 1805 1806 isc_buffer_availableregion(target, ®ion); 1807 if (region.length < 4) { 1808 return (ISC_R_NOSPACE); 1809 } 1810 isc_buffer_putuint32(target, value); 1811 return (ISC_R_SUCCESS); 1812 } 1813 1814 static isc_result_t 1815 uint16_tobuffer(uint32_t value, isc_buffer_t *target) { 1816 isc_region_t region; 1817 1818 if (value > 0xffff) { 1819 return (ISC_R_RANGE); 1820 } 1821 isc_buffer_availableregion(target, ®ion); 1822 if (region.length < 2) { 1823 return (ISC_R_NOSPACE); 1824 } 1825 isc_buffer_putuint16(target, (uint16_t)value); 1826 return (ISC_R_SUCCESS); 1827 } 1828 1829 static isc_result_t 1830 uint8_tobuffer(uint32_t value, isc_buffer_t *target) { 1831 isc_region_t region; 1832 1833 if (value > 0xff) { 1834 return (ISC_R_RANGE); 1835 } 1836 isc_buffer_availableregion(target, ®ion); 1837 if (region.length < 1) { 1838 return (ISC_R_NOSPACE); 1839 } 1840 isc_buffer_putuint8(target, (uint8_t)value); 1841 return (ISC_R_SUCCESS); 1842 } 1843 1844 static isc_result_t 1845 name_tobuffer(const dns_name_t *name, isc_buffer_t *target) { 1846 isc_region_t r; 1847 dns_name_toregion(name, &r); 1848 return (isc_buffer_copyregion(target, &r)); 1849 } 1850 1851 static uint32_t 1852 uint32_fromregion(isc_region_t *region) { 1853 uint32_t value; 1854 1855 REQUIRE(region->length >= 4); 1856 value = (uint32_t)region->base[0] << 24; 1857 value |= (uint32_t)region->base[1] << 16; 1858 value |= (uint32_t)region->base[2] << 8; 1859 value |= (uint32_t)region->base[3]; 1860 return (value); 1861 } 1862 1863 static uint16_t 1864 uint16_consume_fromregion(isc_region_t *region) { 1865 uint16_t r = uint16_fromregion(region); 1866 1867 isc_region_consume(region, 2); 1868 return (r); 1869 } 1870 1871 static uint16_t 1872 uint16_fromregion(isc_region_t *region) { 1873 REQUIRE(region->length >= 2); 1874 1875 return ((region->base[0] << 8) | region->base[1]); 1876 } 1877 1878 static uint8_t 1879 uint8_fromregion(isc_region_t *region) { 1880 REQUIRE(region->length >= 1); 1881 1882 return (region->base[0]); 1883 } 1884 1885 static uint8_t 1886 uint8_consume_fromregion(isc_region_t *region) { 1887 uint8_t r = uint8_fromregion(region); 1888 1889 isc_region_consume(region, 1); 1890 return (r); 1891 } 1892 1893 static isc_result_t 1894 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) { 1895 isc_region_t tr; 1896 1897 if (length == 0U) { 1898 return (ISC_R_SUCCESS); 1899 } 1900 1901 isc_buffer_availableregion(target, &tr); 1902 if (length > tr.length) { 1903 return (ISC_R_NOSPACE); 1904 } 1905 if (tr.base != base) { 1906 memmove(tr.base, base, length); 1907 } 1908 isc_buffer_add(target, length); 1909 return (ISC_R_SUCCESS); 1910 } 1911 1912 static int 1913 hexvalue(char value) { 1914 const char *s; 1915 unsigned char c; 1916 1917 c = (unsigned char)value; 1918 1919 if (!isascii(c)) { 1920 return (-1); 1921 } 1922 if (isupper(c)) { 1923 c = tolower(c); 1924 } 1925 if ((s = strchr(hexdigits, c)) == NULL) { 1926 return (-1); 1927 } 1928 return ((int)(s - hexdigits)); 1929 } 1930 1931 static int 1932 decvalue(char value) { 1933 const char *s; 1934 1935 /* 1936 * isascii() is valid for full range of int values, no need to 1937 * mask or cast. 1938 */ 1939 if (!isascii(value)) { 1940 return (-1); 1941 } 1942 if ((s = strchr(decdigits, value)) == NULL) { 1943 return (-1); 1944 } 1945 return ((int)(s - decdigits)); 1946 } 1947 1948 static void 1949 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, 1950 ...) { 1951 va_list ap; 1952 1953 UNUSED(callbacks); 1954 1955 va_start(ap, fmt); 1956 vfprintf(stderr, fmt, ap); 1957 va_end(ap); 1958 fprintf(stderr, "\n"); 1959 } 1960 1961 static void 1962 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) { 1963 if (isc_lex_isfile(lexer) && callbacks != NULL) { 1964 const char *name = isc_lex_getsourcename(lexer); 1965 if (name == NULL) { 1966 name = "UNKNOWN"; 1967 } 1968 (*callbacks->warn)(callbacks, 1969 "%s:%lu: file does not end with newline", 1970 name, isc_lex_getsourceline(lexer)); 1971 } 1972 } 1973 1974 static void 1975 warn_badmx(isc_token_t *token, isc_lex_t *lexer, 1976 dns_rdatacallbacks_t *callbacks) { 1977 const char *file; 1978 unsigned long line; 1979 1980 if (lexer != NULL) { 1981 file = isc_lex_getsourcename(lexer); 1982 line = isc_lex_getsourceline(lexer); 1983 (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s", file, 1984 line, DNS_AS_STR(*token), 1985 dns_result_totext(DNS_R_MXISADDRESS)); 1986 } 1987 } 1988 1989 static void 1990 warn_badname(const dns_name_t *name, isc_lex_t *lexer, 1991 dns_rdatacallbacks_t *callbacks) { 1992 const char *file; 1993 unsigned long line; 1994 char namebuf[DNS_NAME_FORMATSIZE]; 1995 1996 if (lexer != NULL) { 1997 file = isc_lex_getsourcename(lexer); 1998 line = isc_lex_getsourceline(lexer); 1999 dns_name_format(name, namebuf, sizeof(namebuf)); 2000 (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s", file, 2001 line, namebuf, 2002 dns_result_totext(DNS_R_BADNAME)); 2003 } 2004 } 2005 2006 static void 2007 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...), 2008 dns_rdatacallbacks_t *callbacks, const char *name, 2009 unsigned long line, isc_token_t *token, isc_result_t result) { 2010 if (name == NULL) { 2011 name = "UNKNOWN"; 2012 } 2013 2014 if (token != NULL) { 2015 switch (token->type) { 2016 case isc_tokentype_eol: 2017 (*callback)(callbacks, "%s: %s:%lu: near eol: %s", 2018 "dns_rdata_fromtext", name, line, 2019 dns_result_totext(result)); 2020 break; 2021 case isc_tokentype_eof: 2022 (*callback)(callbacks, "%s: %s:%lu: near eof: %s", 2023 "dns_rdata_fromtext", name, line, 2024 dns_result_totext(result)); 2025 break; 2026 case isc_tokentype_number: 2027 (*callback)(callbacks, "%s: %s:%lu: near %lu: %s", 2028 "dns_rdata_fromtext", name, line, 2029 token->value.as_ulong, 2030 dns_result_totext(result)); 2031 break; 2032 case isc_tokentype_string: 2033 case isc_tokentype_qstring: 2034 (*callback)(callbacks, "%s: %s:%lu: near '%s': %s", 2035 "dns_rdata_fromtext", name, line, 2036 DNS_AS_STR(*token), 2037 dns_result_totext(result)); 2038 break; 2039 default: 2040 (*callback)(callbacks, "%s: %s:%lu: %s", 2041 "dns_rdata_fromtext", name, line, 2042 dns_result_totext(result)); 2043 break; 2044 } 2045 } else { 2046 (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s", name, 2047 line, dns_result_totext(result)); 2048 } 2049 } 2050 2051 dns_rdatatype_t 2052 dns_rdata_covers(dns_rdata_t *rdata) { 2053 if (rdata->type == dns_rdatatype_rrsig) { 2054 return (covers_rrsig(rdata)); 2055 } 2056 return (covers_sig(rdata)); 2057 } 2058 2059 bool 2060 dns_rdatatype_ismeta(dns_rdatatype_t type) { 2061 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0) { 2062 return (true); 2063 } 2064 return (false); 2065 } 2066 2067 bool 2068 dns_rdatatype_issingleton(dns_rdatatype_t type) { 2069 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON) != 0) 2070 { 2071 return (true); 2072 } 2073 return (false); 2074 } 2075 2076 bool 2077 dns_rdatatype_notquestion(dns_rdatatype_t type) { 2078 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION) != 2079 0) { 2080 return (true); 2081 } 2082 return (false); 2083 } 2084 2085 bool 2086 dns_rdatatype_questiononly(dns_rdatatype_t type) { 2087 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY) != 2088 0) { 2089 return (true); 2090 } 2091 return (false); 2092 } 2093 2094 bool 2095 dns_rdatatype_atcname(dns_rdatatype_t type) { 2096 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATCNAME) != 0) { 2097 return (true); 2098 } 2099 return (false); 2100 } 2101 2102 bool 2103 dns_rdatatype_atparent(dns_rdatatype_t type) { 2104 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0) 2105 { 2106 return (true); 2107 } 2108 return (false); 2109 } 2110 2111 bool 2112 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) { 2113 if (rdclass == dns_rdataclass_reserved0 || 2114 rdclass == dns_rdataclass_none || rdclass == dns_rdataclass_any) 2115 { 2116 return (true); 2117 } 2118 2119 return (false); /* Assume it is not a meta class. */ 2120 } 2121 2122 bool 2123 dns_rdatatype_isdnssec(dns_rdatatype_t type) { 2124 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0) { 2125 return (true); 2126 } 2127 return (false); 2128 } 2129 2130 bool 2131 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) { 2132 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH) != 2133 0) { 2134 return (true); 2135 } 2136 return (false); 2137 } 2138 2139 bool 2140 dns_rdatatype_isknown(dns_rdatatype_t type) { 2141 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN) == 0) { 2142 return (true); 2143 } 2144 return (false); 2145 } 2146 2147 void 2148 dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) { 2149 REQUIRE(rdata != NULL); 2150 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2151 2152 rdata->data = NULL; 2153 rdata->length = 0; 2154 rdata->flags = DNS_RDATA_UPDATE; 2155 rdata->type = type; 2156 rdata->rdclass = dns_rdataclass_any; 2157 } 2158 2159 void 2160 dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) { 2161 REQUIRE(rdata != NULL); 2162 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2163 2164 rdata->data = NULL; 2165 rdata->length = 0; 2166 rdata->flags = DNS_RDATA_UPDATE; 2167 rdata->type = type; 2168 rdata->rdclass = dns_rdataclass_none; 2169 } 2170 2171 void 2172 dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) { 2173 REQUIRE(rdata != NULL); 2174 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2175 2176 rdata->data = NULL; 2177 rdata->length = 0; 2178 rdata->flags = DNS_RDATA_UPDATE; 2179 rdata->type = type; 2180 rdata->rdclass = dns_rdataclass_any; 2181 } 2182 2183 void 2184 dns_rdata_makedelete(dns_rdata_t *rdata) { 2185 REQUIRE(rdata != NULL); 2186 2187 rdata->rdclass = dns_rdataclass_none; 2188 } 2189 2190 const char * 2191 dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) { 2192 REQUIRE(rdata != NULL); 2193 REQUIRE(DNS_RDATA_INITIALIZED(rdata)); 2194 2195 switch (section) { 2196 case DNS_SECTION_PREREQUISITE: 2197 switch (rdata->rdclass) { 2198 case dns_rdataclass_none: 2199 switch (rdata->type) { 2200 case dns_rdatatype_any: 2201 return ("domain doesn't exist"); 2202 default: 2203 return ("rrset doesn't exist"); 2204 } 2205 case dns_rdataclass_any: 2206 switch (rdata->type) { 2207 case dns_rdatatype_any: 2208 return ("domain exists"); 2209 default: 2210 return ("rrset exists (value independent)"); 2211 } 2212 default: 2213 return ("rrset exists (value dependent)"); 2214 } 2215 case DNS_SECTION_UPDATE: 2216 switch (rdata->rdclass) { 2217 case dns_rdataclass_none: 2218 return ("delete"); 2219 case dns_rdataclass_any: 2220 switch (rdata->type) { 2221 case dns_rdatatype_any: 2222 return ("delete all rrsets"); 2223 default: 2224 return ("delete rrset"); 2225 } 2226 default: 2227 return ("add"); 2228 } 2229 } 2230 return ("invalid"); 2231 } 2232