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