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