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