message.c revision 267654
1/* 2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-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/* $Id$ */ 19 20/*! \file */ 21 22/*** 23 *** Imports 24 ***/ 25 26#include <config.h> 27#include <ctype.h> 28 29#include <isc/buffer.h> 30#include <isc/mem.h> 31#include <isc/print.h> 32#include <isc/string.h> /* Required for HP/UX (and others?) */ 33#include <isc/util.h> 34 35#include <dns/dnssec.h> 36#include <dns/keyvalues.h> 37#include <dns/log.h> 38#include <dns/masterdump.h> 39#include <dns/message.h> 40#include <dns/opcode.h> 41#include <dns/rdata.h> 42#include <dns/rdatalist.h> 43#include <dns/rdataset.h> 44#include <dns/rdatastruct.h> 45#include <dns/result.h> 46#include <dns/tsig.h> 47#include <dns/view.h> 48 49#ifdef SKAN_MSG_DEBUG 50static void 51hexdump(const char *msg, const char *msg2, void *base, size_t len) { 52 unsigned char *p; 53 unsigned int cnt; 54 55 p = base; 56 cnt = 0; 57 58 printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base); 59 60 while (cnt < len) { 61 if (cnt % 16 == 0) 62 printf("%p: ", p); 63 else if (cnt % 8 == 0) 64 printf(" |"); 65 printf(" %02x %c", *p, (isprint(*p) ? *p : ' ')); 66 p++; 67 cnt++; 68 69 if (cnt % 16 == 0) 70 printf("\n"); 71 } 72 73 if (cnt % 16 != 0) 74 printf("\n"); 75} 76#endif 77 78#define DNS_MESSAGE_OPCODE_MASK 0x7800U 79#define DNS_MESSAGE_OPCODE_SHIFT 11 80#define DNS_MESSAGE_RCODE_MASK 0x000fU 81#define DNS_MESSAGE_FLAG_MASK 0x8ff0U 82#define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U 83#define DNS_MESSAGE_EDNSRCODE_SHIFT 24 84#define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U 85#define DNS_MESSAGE_EDNSVERSION_SHIFT 16 86 87#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \ 88 && ((s) < DNS_SECTION_MAX)) 89#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \ 90 && ((s) < DNS_SECTION_MAX)) 91#define ADD_STRING(b, s) {if (strlen(s) >= \ 92 isc_buffer_availablelength(b)) \ 93 return(ISC_R_NOSPACE); else \ 94 isc_buffer_putstr(b, s);} 95#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \ 96 && ((s) < DNS_PSEUDOSECTION_MAX)) 97 98#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0) 99 100/*% 101 * This is the size of each individual scratchpad buffer, and the numbers 102 * of various block allocations used within the server. 103 * XXXMLG These should come from a config setting. 104 */ 105#define SCRATCHPAD_SIZE 512 106#define NAME_COUNT 8 107#define OFFSET_COUNT 4 108#define RDATA_COUNT 8 109#define RDATALIST_COUNT 8 110#define RDATASET_COUNT RDATALIST_COUNT 111 112/*% 113 * Text representation of the different items, for message_totext 114 * functions. 115 */ 116static const char *sectiontext[] = { 117 "QUESTION", 118 "ANSWER", 119 "AUTHORITY", 120 "ADDITIONAL" 121}; 122 123static const char *updsectiontext[] = { 124 "ZONE", 125 "PREREQUISITE", 126 "UPDATE", 127 "ADDITIONAL" 128}; 129 130static const char *opcodetext[] = { 131 "QUERY", 132 "IQUERY", 133 "STATUS", 134 "RESERVED3", 135 "NOTIFY", 136 "UPDATE", 137 "RESERVED6", 138 "RESERVED7", 139 "RESERVED8", 140 "RESERVED9", 141 "RESERVED10", 142 "RESERVED11", 143 "RESERVED12", 144 "RESERVED13", 145 "RESERVED14", 146 "RESERVED15" 147}; 148 149static const char *rcodetext[] = { 150 "NOERROR", 151 "FORMERR", 152 "SERVFAIL", 153 "NXDOMAIN", 154 "NOTIMP", 155 "REFUSED", 156 "YXDOMAIN", 157 "YXRRSET", 158 "NXRRSET", 159 "NOTAUTH", 160 "NOTZONE", 161 "RESERVED11", 162 "RESERVED12", 163 "RESERVED13", 164 "RESERVED14", 165 "RESERVED15", 166 "BADVERS" 167}; 168 169 170/*% 171 * "helper" type, which consists of a block of some type, and is linkable. 172 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer 173 * size, or the allocated elements will not be aligned correctly. 174 */ 175struct dns_msgblock { 176 unsigned int count; 177 unsigned int remaining; 178 ISC_LINK(dns_msgblock_t) link; 179}; /* dynamically sized */ 180 181static inline dns_msgblock_t * 182msgblock_allocate(isc_mem_t *, unsigned int, unsigned int); 183 184#define msgblock_get(block, type) \ 185 ((type *)msgblock_internalget(block, sizeof(type))) 186 187static inline void * 188msgblock_internalget(dns_msgblock_t *, unsigned int); 189 190static inline void 191msgblock_reset(dns_msgblock_t *); 192 193static inline void 194msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int); 195 196/* 197 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory 198 * is free, return NULL. 199 */ 200static inline dns_msgblock_t * 201msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type, 202 unsigned int count) 203{ 204 dns_msgblock_t *block; 205 unsigned int length; 206 207 length = sizeof(dns_msgblock_t) + (sizeof_type * count); 208 209 block = isc_mem_get(mctx, length); 210 if (block == NULL) 211 return (NULL); 212 213 block->count = count; 214 block->remaining = count; 215 216 ISC_LINK_INIT(block, link); 217 218 return (block); 219} 220 221/* 222 * Return an element from the msgblock. If no more are available, return 223 * NULL. 224 */ 225static inline void * 226msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) { 227 void *ptr; 228 229 if (block == NULL || block->remaining == 0) 230 return (NULL); 231 232 block->remaining--; 233 234 ptr = (((unsigned char *)block) 235 + sizeof(dns_msgblock_t) 236 + (sizeof_type * block->remaining)); 237 238 return (ptr); 239} 240 241static inline void 242msgblock_reset(dns_msgblock_t *block) { 243 block->remaining = block->count; 244} 245 246/* 247 * Release memory associated with a message block. 248 */ 249static inline void 250msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type) 251{ 252 unsigned int length; 253 254 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count); 255 256 isc_mem_put(mctx, block, length); 257} 258 259/* 260 * Allocate a new dynamic buffer, and attach it to this message as the 261 * "current" buffer. (which is always the last on the list, for our 262 * uses) 263 */ 264static inline isc_result_t 265newbuffer(dns_message_t *msg, unsigned int size) { 266 isc_result_t result; 267 isc_buffer_t *dynbuf; 268 269 dynbuf = NULL; 270 result = isc_buffer_allocate(msg->mctx, &dynbuf, size); 271 if (result != ISC_R_SUCCESS) 272 return (ISC_R_NOMEMORY); 273 274 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link); 275 return (ISC_R_SUCCESS); 276} 277 278static inline isc_buffer_t * 279currentbuffer(dns_message_t *msg) { 280 isc_buffer_t *dynbuf; 281 282 dynbuf = ISC_LIST_TAIL(msg->scratchpad); 283 INSIST(dynbuf != NULL); 284 285 return (dynbuf); 286} 287 288static inline void 289releaserdata(dns_message_t *msg, dns_rdata_t *rdata) { 290 ISC_LIST_PREPEND(msg->freerdata, rdata, link); 291} 292 293static inline dns_rdata_t * 294newrdata(dns_message_t *msg) { 295 dns_msgblock_t *msgblock; 296 dns_rdata_t *rdata; 297 298 rdata = ISC_LIST_HEAD(msg->freerdata); 299 if (rdata != NULL) { 300 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 301 return (rdata); 302 } 303 304 msgblock = ISC_LIST_TAIL(msg->rdatas); 305 rdata = msgblock_get(msgblock, dns_rdata_t); 306 if (rdata == NULL) { 307 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t), 308 RDATA_COUNT); 309 if (msgblock == NULL) 310 return (NULL); 311 312 ISC_LIST_APPEND(msg->rdatas, msgblock, link); 313 314 rdata = msgblock_get(msgblock, dns_rdata_t); 315 } 316 317 dns_rdata_init(rdata); 318 return (rdata); 319} 320 321static inline void 322releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) { 323 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link); 324} 325 326static inline dns_rdatalist_t * 327newrdatalist(dns_message_t *msg) { 328 dns_msgblock_t *msgblock; 329 dns_rdatalist_t *rdatalist; 330 331 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 332 if (rdatalist != NULL) { 333 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 334 return (rdatalist); 335 } 336 337 msgblock = ISC_LIST_TAIL(msg->rdatalists); 338 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 339 if (rdatalist == NULL) { 340 msgblock = msgblock_allocate(msg->mctx, 341 sizeof(dns_rdatalist_t), 342 RDATALIST_COUNT); 343 if (msgblock == NULL) 344 return (NULL); 345 346 ISC_LIST_APPEND(msg->rdatalists, msgblock, link); 347 348 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 349 } 350 351 return (rdatalist); 352} 353 354static inline dns_offsets_t * 355newoffsets(dns_message_t *msg) { 356 dns_msgblock_t *msgblock; 357 dns_offsets_t *offsets; 358 359 msgblock = ISC_LIST_TAIL(msg->offsets); 360 offsets = msgblock_get(msgblock, dns_offsets_t); 361 if (offsets == NULL) { 362 msgblock = msgblock_allocate(msg->mctx, 363 sizeof(dns_offsets_t), 364 OFFSET_COUNT); 365 if (msgblock == NULL) 366 return (NULL); 367 368 ISC_LIST_APPEND(msg->offsets, msgblock, link); 369 370 offsets = msgblock_get(msgblock, dns_offsets_t); 371 } 372 373 return (offsets); 374} 375 376static inline void 377msginitheader(dns_message_t *m) { 378 m->id = 0; 379 m->flags = 0; 380 m->rcode = 0; 381 m->opcode = 0; 382 m->rdclass = 0; 383} 384 385static inline void 386msginitprivate(dns_message_t *m) { 387 unsigned int i; 388 389 for (i = 0; i < DNS_SECTION_MAX; i++) { 390 m->cursors[i] = NULL; 391 m->counts[i] = 0; 392 } 393 m->opt = NULL; 394 m->sig0 = NULL; 395 m->sig0name = NULL; 396 m->tsig = NULL; 397 m->tsigname = NULL; 398 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ 399 m->opt_reserved = 0; 400 m->sig_reserved = 0; 401 m->reserved = 0; 402 m->buffer = NULL; 403} 404 405static inline void 406msginittsig(dns_message_t *m) { 407 m->tsigstatus = dns_rcode_noerror; 408 m->querytsigstatus = dns_rcode_noerror; 409 m->tsigkey = NULL; 410 m->tsigctx = NULL; 411 m->sigstart = -1; 412 m->sig0key = NULL; 413 m->sig0status = dns_rcode_noerror; 414 m->timeadjust = 0; 415} 416 417/* 418 * Init elements to default state. Used both when allocating a new element 419 * and when resetting one. 420 */ 421static inline void 422msginit(dns_message_t *m) { 423 msginitheader(m); 424 msginitprivate(m); 425 msginittsig(m); 426 m->header_ok = 0; 427 m->question_ok = 0; 428 m->tcp_continuation = 0; 429 m->verified_sig = 0; 430 m->verify_attempted = 0; 431 m->order = NULL; 432 m->order_arg = NULL; 433 m->query.base = NULL; 434 m->query.length = 0; 435 m->free_query = 0; 436 m->saved.base = NULL; 437 m->saved.length = 0; 438 m->free_saved = 0; 439 m->querytsig = NULL; 440} 441 442static inline void 443msgresetnames(dns_message_t *msg, unsigned int first_section) { 444 unsigned int i; 445 dns_name_t *name, *next_name; 446 dns_rdataset_t *rds, *next_rds; 447 448 /* 449 * Clean up name lists by calling the rdataset disassociate function. 450 */ 451 for (i = first_section; i < DNS_SECTION_MAX; i++) { 452 name = ISC_LIST_HEAD(msg->sections[i]); 453 while (name != NULL) { 454 next_name = ISC_LIST_NEXT(name, link); 455 ISC_LIST_UNLINK(msg->sections[i], name, link); 456 457 rds = ISC_LIST_HEAD(name->list); 458 while (rds != NULL) { 459 next_rds = ISC_LIST_NEXT(rds, link); 460 ISC_LIST_UNLINK(name->list, rds, link); 461 462 INSIST(dns_rdataset_isassociated(rds)); 463 dns_rdataset_disassociate(rds); 464 isc_mempool_put(msg->rdspool, rds); 465 rds = next_rds; 466 } 467 if (dns_name_dynamic(name)) 468 dns_name_free(name, msg->mctx); 469 isc_mempool_put(msg->namepool, name); 470 name = next_name; 471 } 472 } 473} 474 475static void 476msgresetopt(dns_message_t *msg) 477{ 478 if (msg->opt != NULL) { 479 if (msg->opt_reserved > 0) { 480 dns_message_renderrelease(msg, msg->opt_reserved); 481 msg->opt_reserved = 0; 482 } 483 INSIST(dns_rdataset_isassociated(msg->opt)); 484 dns_rdataset_disassociate(msg->opt); 485 isc_mempool_put(msg->rdspool, msg->opt); 486 msg->opt = NULL; 487 } 488} 489 490static void 491msgresetsigs(dns_message_t *msg, isc_boolean_t replying) { 492 if (msg->sig_reserved > 0) { 493 dns_message_renderrelease(msg, msg->sig_reserved); 494 msg->sig_reserved = 0; 495 } 496 if (msg->tsig != NULL) { 497 INSIST(dns_rdataset_isassociated(msg->tsig)); 498 INSIST(msg->namepool != NULL); 499 if (replying) { 500 INSIST(msg->querytsig == NULL); 501 msg->querytsig = msg->tsig; 502 } else { 503 dns_rdataset_disassociate(msg->tsig); 504 isc_mempool_put(msg->rdspool, msg->tsig); 505 if (msg->querytsig != NULL) { 506 dns_rdataset_disassociate(msg->querytsig); 507 isc_mempool_put(msg->rdspool, msg->querytsig); 508 } 509 } 510 if (dns_name_dynamic(msg->tsigname)) 511 dns_name_free(msg->tsigname, msg->mctx); 512 isc_mempool_put(msg->namepool, msg->tsigname); 513 msg->tsig = NULL; 514 msg->tsigname = NULL; 515 } else if (msg->querytsig != NULL && !replying) { 516 dns_rdataset_disassociate(msg->querytsig); 517 isc_mempool_put(msg->rdspool, msg->querytsig); 518 msg->querytsig = NULL; 519 } 520 if (msg->sig0 != NULL) { 521 INSIST(dns_rdataset_isassociated(msg->sig0)); 522 dns_rdataset_disassociate(msg->sig0); 523 isc_mempool_put(msg->rdspool, msg->sig0); 524 if (msg->sig0name != NULL) { 525 if (dns_name_dynamic(msg->sig0name)) 526 dns_name_free(msg->sig0name, msg->mctx); 527 isc_mempool_put(msg->namepool, msg->sig0name); 528 } 529 msg->sig0 = NULL; 530 msg->sig0name = NULL; 531 } 532} 533 534/* 535 * Free all but one (or everything) for this message. This is used by 536 * both dns_message_reset() and dns_message_destroy(). 537 */ 538static void 539msgreset(dns_message_t *msg, isc_boolean_t everything) { 540 dns_msgblock_t *msgblock, *next_msgblock; 541 isc_buffer_t *dynbuf, *next_dynbuf; 542 dns_rdata_t *rdata; 543 dns_rdatalist_t *rdatalist; 544 545 msgresetnames(msg, 0); 546 msgresetopt(msg); 547 msgresetsigs(msg, ISC_FALSE); 548 549 /* 550 * Clean up linked lists. 551 */ 552 553 /* 554 * Run through the free lists, and just unlink anything found there. 555 * The memory isn't lost since these are part of message blocks we 556 * have allocated. 557 */ 558 rdata = ISC_LIST_HEAD(msg->freerdata); 559 while (rdata != NULL) { 560 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 561 rdata = ISC_LIST_HEAD(msg->freerdata); 562 } 563 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 564 while (rdatalist != NULL) { 565 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 566 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 567 } 568 569 dynbuf = ISC_LIST_HEAD(msg->scratchpad); 570 INSIST(dynbuf != NULL); 571 if (!everything) { 572 isc_buffer_clear(dynbuf); 573 dynbuf = ISC_LIST_NEXT(dynbuf, link); 574 } 575 while (dynbuf != NULL) { 576 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 577 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link); 578 isc_buffer_free(&dynbuf); 579 dynbuf = next_dynbuf; 580 } 581 582 msgblock = ISC_LIST_HEAD(msg->rdatas); 583 if (!everything && msgblock != NULL) { 584 msgblock_reset(msgblock); 585 msgblock = ISC_LIST_NEXT(msgblock, link); 586 } 587 while (msgblock != NULL) { 588 next_msgblock = ISC_LIST_NEXT(msgblock, link); 589 ISC_LIST_UNLINK(msg->rdatas, msgblock, link); 590 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t)); 591 msgblock = next_msgblock; 592 } 593 594 /* 595 * rdatalists could be empty. 596 */ 597 598 msgblock = ISC_LIST_HEAD(msg->rdatalists); 599 if (!everything && msgblock != NULL) { 600 msgblock_reset(msgblock); 601 msgblock = ISC_LIST_NEXT(msgblock, link); 602 } 603 while (msgblock != NULL) { 604 next_msgblock = ISC_LIST_NEXT(msgblock, link); 605 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link); 606 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t)); 607 msgblock = next_msgblock; 608 } 609 610 msgblock = ISC_LIST_HEAD(msg->offsets); 611 if (!everything && msgblock != NULL) { 612 msgblock_reset(msgblock); 613 msgblock = ISC_LIST_NEXT(msgblock, link); 614 } 615 while (msgblock != NULL) { 616 next_msgblock = ISC_LIST_NEXT(msgblock, link); 617 ISC_LIST_UNLINK(msg->offsets, msgblock, link); 618 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t)); 619 msgblock = next_msgblock; 620 } 621 622 if (msg->tsigkey != NULL) { 623 dns_tsigkey_detach(&msg->tsigkey); 624 msg->tsigkey = NULL; 625 } 626 627 if (msg->tsigctx != NULL) 628 dst_context_destroy(&msg->tsigctx); 629 630 if (msg->query.base != NULL) { 631 if (msg->free_query != 0) 632 isc_mem_put(msg->mctx, msg->query.base, 633 msg->query.length); 634 msg->query.base = NULL; 635 msg->query.length = 0; 636 } 637 638 if (msg->saved.base != NULL) { 639 if (msg->free_saved != 0) 640 isc_mem_put(msg->mctx, msg->saved.base, 641 msg->saved.length); 642 msg->saved.base = NULL; 643 msg->saved.length = 0; 644 } 645 646 /* 647 * cleanup the buffer cleanup list 648 */ 649 dynbuf = ISC_LIST_HEAD(msg->cleanup); 650 while (dynbuf != NULL) { 651 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 652 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link); 653 isc_buffer_free(&dynbuf); 654 dynbuf = next_dynbuf; 655 } 656 657 /* 658 * Set other bits to normal default values. 659 */ 660 if (!everything) 661 msginit(msg); 662 663 ENSURE(isc_mempool_getallocated(msg->namepool) == 0); 664 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0); 665} 666 667static unsigned int 668spacefortsig(dns_tsigkey_t *key, int otherlen) { 669 isc_region_t r1, r2; 670 unsigned int x; 671 isc_result_t result; 672 673 /* 674 * The space required for an TSIG record is: 675 * 676 * n1 bytes for the name 677 * 2 bytes for the type 678 * 2 bytes for the class 679 * 4 bytes for the ttl 680 * 2 bytes for the rdlength 681 * n2 bytes for the algorithm name 682 * 6 bytes for the time signed 683 * 2 bytes for the fudge 684 * 2 bytes for the MAC size 685 * x bytes for the MAC 686 * 2 bytes for the original id 687 * 2 bytes for the error 688 * 2 bytes for the other data length 689 * y bytes for the other data (at most) 690 * --------------------------------- 691 * 26 + n1 + n2 + x + y bytes 692 */ 693 694 dns_name_toregion(&key->name, &r1); 695 dns_name_toregion(key->algorithm, &r2); 696 if (key->key == NULL) 697 x = 0; 698 else { 699 result = dst_key_sigsize(key->key, &x); 700 if (result != ISC_R_SUCCESS) 701 x = 0; 702 } 703 return (26 + r1.length + r2.length + x + otherlen); 704} 705 706isc_result_t 707dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) 708{ 709 dns_message_t *m; 710 isc_result_t result; 711 isc_buffer_t *dynbuf; 712 unsigned int i; 713 714 REQUIRE(mctx != NULL); 715 REQUIRE(msgp != NULL); 716 REQUIRE(*msgp == NULL); 717 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 718 || intent == DNS_MESSAGE_INTENTRENDER); 719 720 m = isc_mem_get(mctx, sizeof(dns_message_t)); 721 if (m == NULL) 722 return (ISC_R_NOMEMORY); 723 724 /* 725 * No allocations until further notice. Just initialize all lists 726 * and other members that are freed in the cleanup phase here. 727 */ 728 729 m->magic = DNS_MESSAGE_MAGIC; 730 m->from_to_wire = intent; 731 msginit(m); 732 733 for (i = 0; i < DNS_SECTION_MAX; i++) 734 ISC_LIST_INIT(m->sections[i]); 735 736 m->mctx = NULL; 737 isc_mem_attach(mctx, &m->mctx); 738 739 ISC_LIST_INIT(m->scratchpad); 740 ISC_LIST_INIT(m->cleanup); 741 m->namepool = NULL; 742 m->rdspool = NULL; 743 ISC_LIST_INIT(m->rdatas); 744 ISC_LIST_INIT(m->rdatalists); 745 ISC_LIST_INIT(m->offsets); 746 ISC_LIST_INIT(m->freerdata); 747 ISC_LIST_INIT(m->freerdatalist); 748 749 /* 750 * Ok, it is safe to allocate (and then "goto cleanup" if failure) 751 */ 752 753 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool); 754 if (result != ISC_R_SUCCESS) 755 goto cleanup; 756 isc_mempool_setfreemax(m->namepool, NAME_COUNT); 757 isc_mempool_setname(m->namepool, "msg:names"); 758 759 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), 760 &m->rdspool); 761 if (result != ISC_R_SUCCESS) 762 goto cleanup; 763 isc_mempool_setfreemax(m->rdspool, NAME_COUNT); 764 isc_mempool_setname(m->rdspool, "msg:rdataset"); 765 766 dynbuf = NULL; 767 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE); 768 if (result != ISC_R_SUCCESS) 769 goto cleanup; 770 ISC_LIST_APPEND(m->scratchpad, dynbuf, link); 771 772 m->cctx = NULL; 773 774 *msgp = m; 775 return (ISC_R_SUCCESS); 776 777 /* 778 * Cleanup for error returns. 779 */ 780 cleanup: 781 dynbuf = ISC_LIST_HEAD(m->scratchpad); 782 if (dynbuf != NULL) { 783 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); 784 isc_buffer_free(&dynbuf); 785 } 786 if (m->namepool != NULL) 787 isc_mempool_destroy(&m->namepool); 788 if (m->rdspool != NULL) 789 isc_mempool_destroy(&m->rdspool); 790 m->magic = 0; 791 isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t)); 792 793 return (ISC_R_NOMEMORY); 794} 795 796void 797dns_message_reset(dns_message_t *msg, unsigned int intent) { 798 REQUIRE(DNS_MESSAGE_VALID(msg)); 799 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 800 || intent == DNS_MESSAGE_INTENTRENDER); 801 802 msgreset(msg, ISC_FALSE); 803 msg->from_to_wire = intent; 804} 805 806void 807dns_message_destroy(dns_message_t **msgp) { 808 dns_message_t *msg; 809 810 REQUIRE(msgp != NULL); 811 REQUIRE(DNS_MESSAGE_VALID(*msgp)); 812 813 msg = *msgp; 814 *msgp = NULL; 815 816 msgreset(msg, ISC_TRUE); 817 isc_mempool_destroy(&msg->namepool); 818 isc_mempool_destroy(&msg->rdspool); 819 msg->magic = 0; 820 isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t)); 821} 822 823static isc_result_t 824findname(dns_name_t **foundname, dns_name_t *target, 825 dns_namelist_t *section) 826{ 827 dns_name_t *curr; 828 829 for (curr = ISC_LIST_TAIL(*section); 830 curr != NULL; 831 curr = ISC_LIST_PREV(curr, link)) { 832 if (dns_name_equal(curr, target)) { 833 if (foundname != NULL) 834 *foundname = curr; 835 return (ISC_R_SUCCESS); 836 } 837 } 838 839 return (ISC_R_NOTFOUND); 840} 841 842isc_result_t 843dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, 844 dns_rdatatype_t type, dns_rdatatype_t covers, 845 dns_rdataset_t **rdataset) 846{ 847 dns_rdataset_t *curr; 848 849 if (rdataset != NULL) { 850 REQUIRE(*rdataset == NULL); 851 } 852 853 for (curr = ISC_LIST_TAIL(name->list); 854 curr != NULL; 855 curr = ISC_LIST_PREV(curr, link)) { 856 if (curr->rdclass == rdclass && 857 curr->type == type && curr->covers == covers) { 858 if (rdataset != NULL) 859 *rdataset = curr; 860 return (ISC_R_SUCCESS); 861 } 862 } 863 864 return (ISC_R_NOTFOUND); 865} 866 867isc_result_t 868dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, 869 dns_rdatatype_t covers, dns_rdataset_t **rdataset) 870{ 871 dns_rdataset_t *curr; 872 873 REQUIRE(name != NULL); 874 if (rdataset != NULL) { 875 REQUIRE(*rdataset == NULL); 876 } 877 878 for (curr = ISC_LIST_TAIL(name->list); 879 curr != NULL; 880 curr = ISC_LIST_PREV(curr, link)) { 881 if (curr->type == type && curr->covers == covers) { 882 if (rdataset != NULL) 883 *rdataset = curr; 884 return (ISC_R_SUCCESS); 885 } 886 } 887 888 return (ISC_R_NOTFOUND); 889} 890 891/* 892 * Read a name from buffer "source". 893 */ 894static isc_result_t 895getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, 896 dns_decompress_t *dctx) 897{ 898 isc_buffer_t *scratch; 899 isc_result_t result; 900 unsigned int tries; 901 902 scratch = currentbuffer(msg); 903 904 /* 905 * First try: use current buffer. 906 * Second try: allocate a new buffer and use that. 907 */ 908 tries = 0; 909 while (tries < 2) { 910 result = dns_name_fromwire(name, source, dctx, ISC_FALSE, 911 scratch); 912 913 if (result == ISC_R_NOSPACE) { 914 tries++; 915 916 result = newbuffer(msg, SCRATCHPAD_SIZE); 917 if (result != ISC_R_SUCCESS) 918 return (result); 919 920 scratch = currentbuffer(msg); 921 dns_name_reset(name); 922 } else { 923 return (result); 924 } 925 } 926 927 INSIST(0); /* Cannot get here... */ 928 return (ISC_R_UNEXPECTED); 929} 930 931static isc_result_t 932getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 933 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, 934 unsigned int rdatalen, dns_rdata_t *rdata) 935{ 936 isc_buffer_t *scratch; 937 isc_result_t result; 938 unsigned int tries; 939 unsigned int trysize; 940 941 scratch = currentbuffer(msg); 942 943 isc_buffer_setactive(source, rdatalen); 944 945 /* 946 * First try: use current buffer. 947 * Second try: allocate a new buffer of size 948 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) 949 * (the data will fit if it was not more than 50% compressed) 950 * Subsequent tries: double buffer size on each try. 951 */ 952 tries = 0; 953 trysize = 0; 954 /* XXX possibly change this to a while (tries < 2) loop */ 955 for (;;) { 956 result = dns_rdata_fromwire(rdata, rdclass, rdtype, 957 source, dctx, 0, 958 scratch); 959 960 if (result == ISC_R_NOSPACE) { 961 if (tries == 0) { 962 trysize = 2 * rdatalen; 963 if (trysize < SCRATCHPAD_SIZE) 964 trysize = SCRATCHPAD_SIZE; 965 } else { 966 INSIST(trysize != 0); 967 if (trysize >= 65535) 968 return (ISC_R_NOSPACE); 969 /* XXX DNS_R_RRTOOLONG? */ 970 trysize *= 2; 971 } 972 tries++; 973 result = newbuffer(msg, trysize); 974 if (result != ISC_R_SUCCESS) 975 return (result); 976 977 scratch = currentbuffer(msg); 978 } else { 979 return (result); 980 } 981 } 982} 983 984#define DO_FORMERR \ 985 do { \ 986 if (best_effort) \ 987 seen_problem = ISC_TRUE; \ 988 else { \ 989 result = DNS_R_FORMERR; \ 990 goto cleanup; \ 991 } \ 992 } while (0) 993 994static isc_result_t 995getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 996 unsigned int options) 997{ 998 isc_region_t r; 999 unsigned int count; 1000 dns_name_t *name; 1001 dns_name_t *name2; 1002 dns_offsets_t *offsets; 1003 dns_rdataset_t *rdataset; 1004 dns_rdatalist_t *rdatalist; 1005 isc_result_t result; 1006 dns_rdatatype_t rdtype; 1007 dns_rdataclass_t rdclass; 1008 dns_namelist_t *section; 1009 isc_boolean_t free_name; 1010 isc_boolean_t best_effort; 1011 isc_boolean_t seen_problem; 1012 1013 section = &msg->sections[DNS_SECTION_QUESTION]; 1014 1015 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1016 seen_problem = ISC_FALSE; 1017 1018 name = NULL; 1019 rdataset = NULL; 1020 rdatalist = NULL; 1021 1022 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { 1023 name = isc_mempool_get(msg->namepool); 1024 if (name == NULL) 1025 return (ISC_R_NOMEMORY); 1026 free_name = ISC_TRUE; 1027 1028 offsets = newoffsets(msg); 1029 if (offsets == NULL) { 1030 result = ISC_R_NOMEMORY; 1031 goto cleanup; 1032 } 1033 dns_name_init(name, *offsets); 1034 1035 /* 1036 * Parse the name out of this packet. 1037 */ 1038 isc_buffer_remainingregion(source, &r); 1039 isc_buffer_setactive(source, r.length); 1040 result = getname(name, source, msg, dctx); 1041 if (result != ISC_R_SUCCESS) 1042 goto cleanup; 1043 1044 /* 1045 * Run through the section, looking to see if this name 1046 * is already there. If it is found, put back the allocated 1047 * name since we no longer need it, and set our name pointer 1048 * to point to the name we found. 1049 */ 1050 result = findname(&name2, name, section); 1051 1052 /* 1053 * If it is the first name in the section, accept it. 1054 * 1055 * If it is not, but is not the same as the name already 1056 * in the question section, append to the section. Note that 1057 * here in the question section this is illegal, so return 1058 * FORMERR. In the future, check the opcode to see if 1059 * this should be legal or not. In either case we no longer 1060 * need this name pointer. 1061 */ 1062 if (result != ISC_R_SUCCESS) { 1063 if (!ISC_LIST_EMPTY(*section)) 1064 DO_FORMERR; 1065 ISC_LIST_APPEND(*section, name, link); 1066 free_name = ISC_FALSE; 1067 } else { 1068 isc_mempool_put(msg->namepool, name); 1069 name = name2; 1070 name2 = NULL; 1071 free_name = ISC_FALSE; 1072 } 1073 1074 /* 1075 * Get type and class. 1076 */ 1077 isc_buffer_remainingregion(source, &r); 1078 if (r.length < 4) { 1079 result = ISC_R_UNEXPECTEDEND; 1080 goto cleanup; 1081 } 1082 rdtype = isc_buffer_getuint16(source); 1083 rdclass = isc_buffer_getuint16(source); 1084 1085 /* 1086 * If this class is different than the one we already read, 1087 * this is an error. 1088 */ 1089 if (msg->state == DNS_SECTION_ANY) { 1090 msg->state = DNS_SECTION_QUESTION; 1091 msg->rdclass = rdclass; 1092 } else if (msg->rdclass != rdclass) 1093 DO_FORMERR; 1094 1095 /* 1096 * Can't ask the same question twice. 1097 */ 1098 result = dns_message_find(name, rdclass, rdtype, 0, NULL); 1099 if (result == ISC_R_SUCCESS) 1100 DO_FORMERR; 1101 1102 /* 1103 * Allocate a new rdatalist. 1104 */ 1105 rdatalist = newrdatalist(msg); 1106 if (rdatalist == NULL) { 1107 result = ISC_R_NOMEMORY; 1108 goto cleanup; 1109 } 1110 rdataset = isc_mempool_get(msg->rdspool); 1111 if (rdataset == NULL) { 1112 result = ISC_R_NOMEMORY; 1113 goto cleanup; 1114 } 1115 1116 /* 1117 * Convert rdatalist to rdataset, and attach the latter to 1118 * the name. 1119 */ 1120 rdatalist->type = rdtype; 1121 rdatalist->covers = 0; 1122 rdatalist->rdclass = rdclass; 1123 rdatalist->ttl = 0; 1124 ISC_LIST_INIT(rdatalist->rdata); 1125 1126 dns_rdataset_init(rdataset); 1127 result = dns_rdatalist_tordataset(rdatalist, rdataset); 1128 if (result != ISC_R_SUCCESS) 1129 goto cleanup; 1130 1131 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 1132 1133 ISC_LIST_APPEND(name->list, rdataset, link); 1134 rdataset = NULL; 1135 } 1136 1137 if (seen_problem) 1138 return (DNS_R_RECOVERABLE); 1139 return (ISC_R_SUCCESS); 1140 1141 cleanup: 1142 if (rdataset != NULL) { 1143 INSIST(!dns_rdataset_isassociated(rdataset)); 1144 isc_mempool_put(msg->rdspool, rdataset); 1145 } 1146#if 0 1147 if (rdatalist != NULL) 1148 isc_mempool_put(msg->rdlpool, rdatalist); 1149#endif 1150 if (free_name) 1151 isc_mempool_put(msg->namepool, name); 1152 1153 return (result); 1154} 1155 1156static isc_boolean_t 1157update(dns_section_t section, dns_rdataclass_t rdclass) { 1158 if (section == DNS_SECTION_PREREQUISITE) 1159 return (ISC_TF(rdclass == dns_rdataclass_any || 1160 rdclass == dns_rdataclass_none)); 1161 if (section == DNS_SECTION_UPDATE) 1162 return (ISC_TF(rdclass == dns_rdataclass_any)); 1163 return (ISC_FALSE); 1164} 1165 1166static isc_result_t 1167getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 1168 dns_section_t sectionid, unsigned int options) 1169{ 1170 isc_region_t r; 1171 unsigned int count, rdatalen; 1172 dns_name_t *name; 1173 dns_name_t *name2; 1174 dns_offsets_t *offsets; 1175 dns_rdataset_t *rdataset; 1176 dns_rdatalist_t *rdatalist; 1177 isc_result_t result; 1178 dns_rdatatype_t rdtype, covers; 1179 dns_rdataclass_t rdclass; 1180 dns_rdata_t *rdata; 1181 dns_ttl_t ttl; 1182 dns_namelist_t *section; 1183 isc_boolean_t free_name, free_rdataset; 1184 isc_boolean_t preserve_order, best_effort, seen_problem; 1185 isc_boolean_t issigzero; 1186 1187 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER); 1188 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1189 seen_problem = ISC_FALSE; 1190 1191 for (count = 0; count < msg->counts[sectionid]; count++) { 1192 int recstart = source->current; 1193 isc_boolean_t skip_name_search, skip_type_search; 1194 1195 section = &msg->sections[sectionid]; 1196 1197 skip_name_search = ISC_FALSE; 1198 skip_type_search = ISC_FALSE; 1199 free_rdataset = ISC_FALSE; 1200 1201 name = isc_mempool_get(msg->namepool); 1202 if (name == NULL) 1203 return (ISC_R_NOMEMORY); 1204 free_name = ISC_TRUE; 1205 1206 offsets = newoffsets(msg); 1207 if (offsets == NULL) { 1208 result = ISC_R_NOMEMORY; 1209 goto cleanup; 1210 } 1211 dns_name_init(name, *offsets); 1212 1213 /* 1214 * Parse the name out of this packet. 1215 */ 1216 isc_buffer_remainingregion(source, &r); 1217 isc_buffer_setactive(source, r.length); 1218 result = getname(name, source, msg, dctx); 1219 if (result != ISC_R_SUCCESS) 1220 goto cleanup; 1221 1222 /* 1223 * Get type, class, ttl, and rdatalen. Verify that at least 1224 * rdatalen bytes remain. (Some of this is deferred to 1225 * later.) 1226 */ 1227 isc_buffer_remainingregion(source, &r); 1228 if (r.length < 2 + 2 + 4 + 2) { 1229 result = ISC_R_UNEXPECTEDEND; 1230 goto cleanup; 1231 } 1232 rdtype = isc_buffer_getuint16(source); 1233 rdclass = isc_buffer_getuint16(source); 1234 1235 /* 1236 * If there was no question section, we may not yet have 1237 * established a class. Do so now. 1238 */ 1239 if (msg->state == DNS_SECTION_ANY && 1240 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ 1241 rdtype != dns_rdatatype_tsig && /* class is ANY */ 1242 rdtype != dns_rdatatype_tkey) { /* class is undefined */ 1243 msg->rdclass = rdclass; 1244 msg->state = DNS_SECTION_QUESTION; 1245 } 1246 1247 /* 1248 * If this class is different than the one in the question 1249 * section, bail. 1250 */ 1251 if (msg->opcode != dns_opcode_update 1252 && rdtype != dns_rdatatype_tsig 1253 && rdtype != dns_rdatatype_opt 1254 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ 1255 && rdtype != dns_rdatatype_sig /* SIG(0) */ 1256 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ 1257 && msg->rdclass != dns_rdataclass_any 1258 && msg->rdclass != rdclass) 1259 DO_FORMERR; 1260 1261 /* 1262 * Special type handling for TSIG, OPT, and TKEY. 1263 */ 1264 if (rdtype == dns_rdatatype_tsig) { 1265 /* 1266 * If it is a tsig, verify that it is in the 1267 * additional data section. 1268 */ 1269 if (sectionid != DNS_SECTION_ADDITIONAL || 1270 rdclass != dns_rdataclass_any || 1271 count != msg->counts[sectionid] - 1) 1272 DO_FORMERR; 1273 msg->sigstart = recstart; 1274 skip_name_search = ISC_TRUE; 1275 skip_type_search = ISC_TRUE; 1276 } else if (rdtype == dns_rdatatype_opt) { 1277 /* 1278 * The name of an OPT record must be ".", it 1279 * must be in the additional data section, and 1280 * it must be the first OPT we've seen. 1281 */ 1282 if (!dns_name_equal(dns_rootname, name) || 1283 msg->opt != NULL) 1284 DO_FORMERR; 1285 skip_name_search = ISC_TRUE; 1286 skip_type_search = ISC_TRUE; 1287 } else if (rdtype == dns_rdatatype_tkey) { 1288 /* 1289 * A TKEY must be in the additional section if this 1290 * is a query, and the answer section if this is a 1291 * response. Unless it's a Win2000 client. 1292 * 1293 * Its class is ignored. 1294 */ 1295 dns_section_t tkeysection; 1296 1297 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) 1298 tkeysection = DNS_SECTION_ADDITIONAL; 1299 else 1300 tkeysection = DNS_SECTION_ANSWER; 1301 if (sectionid != tkeysection && 1302 sectionid != DNS_SECTION_ANSWER) 1303 DO_FORMERR; 1304 } 1305 1306 /* 1307 * ... now get ttl and rdatalen, and check buffer. 1308 */ 1309 ttl = isc_buffer_getuint32(source); 1310 rdatalen = isc_buffer_getuint16(source); 1311 r.length -= (2 + 2 + 4 + 2); 1312 if (r.length < rdatalen) { 1313 result = ISC_R_UNEXPECTEDEND; 1314 goto cleanup; 1315 } 1316 1317 /* 1318 * Read the rdata from the wire format. Interpret the 1319 * rdata according to its actual class, even if it had a 1320 * DynDNS meta-class in the packet (unless this is a TSIG). 1321 * Then put the meta-class back into the finished rdata. 1322 */ 1323 rdata = newrdata(msg); 1324 if (rdata == NULL) { 1325 result = ISC_R_NOMEMORY; 1326 goto cleanup; 1327 } 1328 if (msg->opcode == dns_opcode_update && 1329 update(sectionid, rdclass)) { 1330 if (rdatalen != 0) { 1331 result = DNS_R_FORMERR; 1332 goto cleanup; 1333 } 1334 /* 1335 * When the rdata is empty, the data pointer is 1336 * never dereferenced, but it must still be non-NULL. 1337 * Casting 1 rather than "" avoids warnings about 1338 * discarding the const attribute of a string, 1339 * for compilers that would warn about such things. 1340 */ 1341 rdata->data = (unsigned char *)1; 1342 rdata->length = 0; 1343 rdata->rdclass = rdclass; 1344 rdata->type = rdtype; 1345 rdata->flags = DNS_RDATA_UPDATE; 1346 result = ISC_R_SUCCESS; 1347 } else if (rdclass == dns_rdataclass_none && 1348 msg->opcode == dns_opcode_update && 1349 sectionid == DNS_SECTION_UPDATE) { 1350 result = getrdata(source, msg, dctx, msg->rdclass, 1351 rdtype, rdatalen, rdata); 1352 } else 1353 result = getrdata(source, msg, dctx, rdclass, 1354 rdtype, rdatalen, rdata); 1355 if (result != ISC_R_SUCCESS) 1356 goto cleanup; 1357 rdata->rdclass = rdclass; 1358 issigzero = ISC_FALSE; 1359 if (rdtype == dns_rdatatype_rrsig && 1360 rdata->flags == 0) { 1361 covers = dns_rdata_covers(rdata); 1362 if (covers == 0) 1363 DO_FORMERR; 1364 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1365 rdata->flags == 0) { 1366 covers = dns_rdata_covers(rdata); 1367 if (covers == 0) { 1368 if (sectionid != DNS_SECTION_ADDITIONAL || 1369 count != msg->counts[sectionid] - 1) 1370 DO_FORMERR; 1371 msg->sigstart = recstart; 1372 skip_name_search = ISC_TRUE; 1373 skip_type_search = ISC_TRUE; 1374 issigzero = ISC_TRUE; 1375 } 1376 } else 1377 covers = 0; 1378 1379 /* 1380 * If we are doing a dynamic update or this is a meta-type, 1381 * don't bother searching for a name, just append this one 1382 * to the end of the message. 1383 */ 1384 if (preserve_order || msg->opcode == dns_opcode_update || 1385 skip_name_search) { 1386 if (rdtype != dns_rdatatype_opt && 1387 rdtype != dns_rdatatype_tsig && 1388 !issigzero) 1389 { 1390 ISC_LIST_APPEND(*section, name, link); 1391 free_name = ISC_FALSE; 1392 } 1393 } else { 1394 /* 1395 * Run through the section, looking to see if this name 1396 * is already there. If it is found, put back the 1397 * allocated name since we no longer need it, and set 1398 * our name pointer to point to the name we found. 1399 */ 1400 result = findname(&name2, name, section); 1401 1402 /* 1403 * If it is a new name, append to the section. 1404 */ 1405 if (result == ISC_R_SUCCESS) { 1406 isc_mempool_put(msg->namepool, name); 1407 name = name2; 1408 } else { 1409 ISC_LIST_APPEND(*section, name, link); 1410 } 1411 free_name = ISC_FALSE; 1412 } 1413 1414 /* 1415 * Search name for the particular type and class. 1416 * Skip this stage if in update mode or this is a meta-type. 1417 */ 1418 if (preserve_order || msg->opcode == dns_opcode_update || 1419 skip_type_search) 1420 result = ISC_R_NOTFOUND; 1421 else { 1422 /* 1423 * If this is a type that can only occur in 1424 * the question section, fail. 1425 */ 1426 if (dns_rdatatype_questiononly(rdtype)) 1427 DO_FORMERR; 1428 1429 rdataset = NULL; 1430 result = dns_message_find(name, rdclass, rdtype, 1431 covers, &rdataset); 1432 } 1433 1434 /* 1435 * If we found an rdataset that matches, we need to 1436 * append this rdata to that set. If we did not, we need 1437 * to create a new rdatalist, store the important bits there, 1438 * convert it to an rdataset, and link the latter to the name. 1439 * Yuck. When appending, make certain that the type isn't 1440 * a singleton type, such as SOA or CNAME. 1441 * 1442 * Note that this check will be bypassed when preserving order, 1443 * the opcode is an update, or the type search is skipped. 1444 */ 1445 if (result == ISC_R_SUCCESS) { 1446 if (dns_rdatatype_issingleton(rdtype)) { 1447 dns_rdata_t *first; 1448 dns_rdatalist_fromrdataset(rdataset, 1449 &rdatalist); 1450 first = ISC_LIST_HEAD(rdatalist->rdata); 1451 INSIST(first != NULL); 1452 if (dns_rdata_compare(rdata, first) != 0) 1453 DO_FORMERR; 1454 } 1455 } 1456 1457 if (result == ISC_R_NOTFOUND) { 1458 rdataset = isc_mempool_get(msg->rdspool); 1459 if (rdataset == NULL) { 1460 result = ISC_R_NOMEMORY; 1461 goto cleanup; 1462 } 1463 free_rdataset = ISC_TRUE; 1464 1465 rdatalist = newrdatalist(msg); 1466 if (rdatalist == NULL) { 1467 result = ISC_R_NOMEMORY; 1468 goto cleanup; 1469 } 1470 1471 rdatalist->type = rdtype; 1472 rdatalist->covers = covers; 1473 rdatalist->rdclass = rdclass; 1474 rdatalist->ttl = ttl; 1475 ISC_LIST_INIT(rdatalist->rdata); 1476 1477 dns_rdataset_init(rdataset); 1478 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, 1479 rdataset) 1480 == ISC_R_SUCCESS); 1481 1482 if (rdtype != dns_rdatatype_opt && 1483 rdtype != dns_rdatatype_tsig && 1484 !issigzero) 1485 { 1486 ISC_LIST_APPEND(name->list, rdataset, link); 1487 free_rdataset = ISC_FALSE; 1488 } 1489 } 1490 1491 /* 1492 * Minimize TTLs. 1493 * 1494 * Section 5.2 of RFC2181 says we should drop 1495 * nonauthoritative rrsets where the TTLs differ, but we 1496 * currently treat them the as if they were authoritative and 1497 * minimize them. 1498 */ 1499 if (ttl != rdataset->ttl) { 1500 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1501 if (ttl < rdataset->ttl) 1502 rdataset->ttl = ttl; 1503 } 1504 1505 /* Append this rdata to the rdataset. */ 1506 dns_rdatalist_fromrdataset(rdataset, &rdatalist); 1507 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1508 1509 /* 1510 * If this is an OPT record, remember it. Also, set 1511 * the extended rcode. Note that msg->opt will only be set 1512 * if best-effort parsing is enabled. 1513 */ 1514 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { 1515 dns_rcode_t ercode; 1516 1517 msg->opt = rdataset; 1518 rdataset = NULL; 1519 free_rdataset = ISC_FALSE; 1520 ercode = (dns_rcode_t) 1521 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) 1522 >> 20); 1523 msg->rcode |= ercode; 1524 isc_mempool_put(msg->namepool, name); 1525 free_name = ISC_FALSE; 1526 } 1527 1528 /* 1529 * If this is an SIG(0) or TSIG record, remember it. Note 1530 * that msg->sig0 or msg->tsig will only be set if best-effort 1531 * parsing is enabled. 1532 */ 1533 if (issigzero && msg->sig0 == NULL) { 1534 msg->sig0 = rdataset; 1535 msg->sig0name = name; 1536 rdataset = NULL; 1537 free_rdataset = ISC_FALSE; 1538 free_name = ISC_FALSE; 1539 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) { 1540 msg->tsig = rdataset; 1541 msg->tsigname = name; 1542 /* Windows doesn't like TSIG names to be compressed. */ 1543 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1544 rdataset = NULL; 1545 free_rdataset = ISC_FALSE; 1546 free_name = ISC_FALSE; 1547 } 1548 1549 if (seen_problem) { 1550 if (free_name) 1551 isc_mempool_put(msg->namepool, name); 1552 if (free_rdataset) 1553 isc_mempool_put(msg->rdspool, rdataset); 1554 free_name = free_rdataset = ISC_FALSE; 1555 } 1556 INSIST(free_name == ISC_FALSE); 1557 INSIST(free_rdataset == ISC_FALSE); 1558 } 1559 1560 if (seen_problem) 1561 return (DNS_R_RECOVERABLE); 1562 return (ISC_R_SUCCESS); 1563 1564 cleanup: 1565 if (free_name) 1566 isc_mempool_put(msg->namepool, name); 1567 if (free_rdataset) 1568 isc_mempool_put(msg->rdspool, rdataset); 1569 1570 return (result); 1571} 1572 1573isc_result_t 1574dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1575 unsigned int options) 1576{ 1577 isc_region_t r; 1578 dns_decompress_t dctx; 1579 isc_result_t ret; 1580 isc_uint16_t tmpflags; 1581 isc_buffer_t origsource; 1582 isc_boolean_t seen_problem; 1583 isc_boolean_t ignore_tc; 1584 1585 REQUIRE(DNS_MESSAGE_VALID(msg)); 1586 REQUIRE(source != NULL); 1587 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1588 1589 seen_problem = ISC_FALSE; 1590 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); 1591 1592 origsource = *source; 1593 1594 msg->header_ok = 0; 1595 msg->question_ok = 0; 1596 1597 isc_buffer_remainingregion(source, &r); 1598 if (r.length < DNS_MESSAGE_HEADERLEN) 1599 return (ISC_R_UNEXPECTEDEND); 1600 1601 msg->id = isc_buffer_getuint16(source); 1602 tmpflags = isc_buffer_getuint16(source); 1603 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1604 >> DNS_MESSAGE_OPCODE_SHIFT); 1605 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1606 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1607 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1608 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1609 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1610 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1611 1612 msg->header_ok = 1; 1613 1614 /* 1615 * -1 means no EDNS. 1616 */ 1617 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1618 1619 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1620 1621 ret = getquestions(source, msg, &dctx, options); 1622 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1623 goto truncated; 1624 if (ret == DNS_R_RECOVERABLE) { 1625 seen_problem = ISC_TRUE; 1626 ret = ISC_R_SUCCESS; 1627 } 1628 if (ret != ISC_R_SUCCESS) 1629 return (ret); 1630 msg->question_ok = 1; 1631 1632 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1633 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1634 goto truncated; 1635 if (ret == DNS_R_RECOVERABLE) { 1636 seen_problem = ISC_TRUE; 1637 ret = ISC_R_SUCCESS; 1638 } 1639 if (ret != ISC_R_SUCCESS) 1640 return (ret); 1641 1642 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1643 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1644 goto truncated; 1645 if (ret == DNS_R_RECOVERABLE) { 1646 seen_problem = ISC_TRUE; 1647 ret = ISC_R_SUCCESS; 1648 } 1649 if (ret != ISC_R_SUCCESS) 1650 return (ret); 1651 1652 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1653 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1654 goto truncated; 1655 if (ret == DNS_R_RECOVERABLE) { 1656 seen_problem = ISC_TRUE; 1657 ret = ISC_R_SUCCESS; 1658 } 1659 if (ret != ISC_R_SUCCESS) 1660 return (ret); 1661 1662 isc_buffer_remainingregion(source, &r); 1663 if (r.length != 0) { 1664 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1665 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1666 "message has %u byte(s) of trailing garbage", 1667 r.length); 1668 } 1669 1670 truncated: 1671 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) 1672 isc_buffer_usedregion(&origsource, &msg->saved); 1673 else { 1674 msg->saved.length = isc_buffer_usedlength(&origsource); 1675 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1676 if (msg->saved.base == NULL) 1677 return (ISC_R_NOMEMORY); 1678 memmove(msg->saved.base, isc_buffer_base(&origsource), 1679 msg->saved.length); 1680 msg->free_saved = 1; 1681 } 1682 1683 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1684 return (DNS_R_RECOVERABLE); 1685 if (seen_problem == ISC_TRUE) 1686 return (DNS_R_RECOVERABLE); 1687 return (ISC_R_SUCCESS); 1688} 1689 1690isc_result_t 1691dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1692 isc_buffer_t *buffer) 1693{ 1694 isc_region_t r; 1695 1696 REQUIRE(DNS_MESSAGE_VALID(msg)); 1697 REQUIRE(buffer != NULL); 1698 REQUIRE(msg->buffer == NULL); 1699 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1700 1701 msg->cctx = cctx; 1702 1703 /* 1704 * Erase the contents of this buffer. 1705 */ 1706 isc_buffer_clear(buffer); 1707 1708 /* 1709 * Make certain there is enough for at least the header in this 1710 * buffer. 1711 */ 1712 isc_buffer_availableregion(buffer, &r); 1713 if (r.length < DNS_MESSAGE_HEADERLEN) 1714 return (ISC_R_NOSPACE); 1715 1716 if (r.length < msg->reserved) 1717 return (ISC_R_NOSPACE); 1718 1719 /* 1720 * Reserve enough space for the header in this buffer. 1721 */ 1722 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1723 1724 msg->buffer = buffer; 1725 1726 return (ISC_R_SUCCESS); 1727} 1728 1729isc_result_t 1730dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1731 isc_region_t r, rn; 1732 1733 REQUIRE(DNS_MESSAGE_VALID(msg)); 1734 REQUIRE(buffer != NULL); 1735 REQUIRE(msg->buffer != NULL); 1736 1737 /* 1738 * Ensure that the new buffer is empty, and has enough space to 1739 * hold the current contents. 1740 */ 1741 isc_buffer_clear(buffer); 1742 1743 isc_buffer_availableregion(buffer, &rn); 1744 isc_buffer_usedregion(msg->buffer, &r); 1745 REQUIRE(rn.length > r.length); 1746 1747 /* 1748 * Copy the contents from the old to the new buffer. 1749 */ 1750 isc_buffer_add(buffer, r.length); 1751 memmove(rn.base, r.base, r.length); 1752 1753 msg->buffer = buffer; 1754 1755 return (ISC_R_SUCCESS); 1756} 1757 1758void 1759dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1760 REQUIRE(DNS_MESSAGE_VALID(msg)); 1761 REQUIRE(space <= msg->reserved); 1762 1763 msg->reserved -= space; 1764} 1765 1766isc_result_t 1767dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1768 isc_region_t r; 1769 1770 REQUIRE(DNS_MESSAGE_VALID(msg)); 1771 1772 if (msg->buffer != NULL) { 1773 isc_buffer_availableregion(msg->buffer, &r); 1774 if (r.length < (space + msg->reserved)) 1775 return (ISC_R_NOSPACE); 1776 } 1777 1778 msg->reserved += space; 1779 1780 return (ISC_R_SUCCESS); 1781} 1782 1783static inline isc_boolean_t 1784wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1785 int pass_needed; 1786 1787 /* 1788 * If we are not rendering class IN, this ordering is bogus. 1789 */ 1790 if (rds->rdclass != dns_rdataclass_in) 1791 return (ISC_FALSE); 1792 1793 switch (rds->type) { 1794 case dns_rdatatype_a: 1795 case dns_rdatatype_aaaa: 1796 if (preferred_glue == rds->type) 1797 pass_needed = 4; 1798 else 1799 pass_needed = 3; 1800 break; 1801 case dns_rdatatype_rrsig: 1802 case dns_rdatatype_dnskey: 1803 pass_needed = 2; 1804 break; 1805 default: 1806 pass_needed = 1; 1807 } 1808 1809 if (pass_needed >= pass) 1810 return (ISC_FALSE); 1811 1812 return (ISC_TRUE); 1813} 1814 1815#ifdef ALLOW_FILTER_AAAA_ON_V4 1816/* 1817 * Decide whether to not answer with an AAAA record and its RRSIG 1818 */ 1819static inline isc_boolean_t 1820norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) 1821{ 1822 switch (rdataset->type) { 1823 case dns_rdatatype_aaaa: 1824 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0) 1825 return (ISC_FALSE); 1826 break; 1827 1828 case dns_rdatatype_rrsig: 1829 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || 1830 rdataset->covers != dns_rdatatype_aaaa) 1831 return (ISC_FALSE); 1832 break; 1833 1834 default: 1835 return (ISC_FALSE); 1836 } 1837 1838 if (rdataset->rdclass != dns_rdataclass_in) 1839 return (ISC_FALSE); 1840 1841 return (ISC_TRUE); 1842} 1843 1844#endif 1845isc_result_t 1846dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1847 unsigned int options) 1848{ 1849 dns_namelist_t *section; 1850 dns_name_t *name, *next_name; 1851 dns_rdataset_t *rdataset, *next_rdataset; 1852 unsigned int count, total; 1853 isc_result_t result; 1854 isc_buffer_t st; /* for rollbacks */ 1855 int pass; 1856 isc_boolean_t partial = ISC_FALSE; 1857 unsigned int rd_options; 1858 dns_rdatatype_t preferred_glue = 0; 1859 1860 REQUIRE(DNS_MESSAGE_VALID(msg)); 1861 REQUIRE(msg->buffer != NULL); 1862 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1863 1864 section = &msg->sections[sectionid]; 1865 1866 if ((sectionid == DNS_SECTION_ADDITIONAL) 1867 && (options & DNS_MESSAGERENDER_ORDERED) == 0) { 1868 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1869 preferred_glue = dns_rdatatype_a; 1870 pass = 4; 1871 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1872 preferred_glue = dns_rdatatype_aaaa; 1873 pass = 4; 1874 } else 1875 pass = 3; 1876 } else 1877 pass = 1; 1878 1879 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) 1880 rd_options = 0; 1881 else 1882 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1883 1884 /* 1885 * Shrink the space in the buffer by the reserved amount. 1886 */ 1887 msg->buffer->length -= msg->reserved; 1888 1889 total = 0; 1890 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) 1891 partial = ISC_TRUE; 1892 1893 /* 1894 * Render required glue first. Set TC if it won't fit. 1895 */ 1896 name = ISC_LIST_HEAD(*section); 1897 if (name != NULL) { 1898 rdataset = ISC_LIST_HEAD(name->list); 1899 if (rdataset != NULL && 1900 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && 1901 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { 1902 const void *order_arg = msg->order_arg; 1903 st = *(msg->buffer); 1904 count = 0; 1905 if (partial) 1906 result = dns_rdataset_towirepartial(rdataset, 1907 name, 1908 msg->cctx, 1909 msg->buffer, 1910 msg->order, 1911 order_arg, 1912 rd_options, 1913 &count, 1914 NULL); 1915 else 1916 result = dns_rdataset_towiresorted(rdataset, 1917 name, 1918 msg->cctx, 1919 msg->buffer, 1920 msg->order, 1921 order_arg, 1922 rd_options, 1923 &count); 1924 total += count; 1925 if (partial && result == ISC_R_NOSPACE) { 1926 msg->flags |= DNS_MESSAGEFLAG_TC; 1927 msg->buffer->length += msg->reserved; 1928 msg->counts[sectionid] += total; 1929 return (result); 1930 } 1931 if (result == ISC_R_NOSPACE) 1932 msg->flags |= DNS_MESSAGEFLAG_TC; 1933 if (result != ISC_R_SUCCESS) { 1934 INSIST(st.used < 65536); 1935 dns_compress_rollback(msg->cctx, 1936 (isc_uint16_t)st.used); 1937 *(msg->buffer) = st; /* rollback */ 1938 msg->buffer->length += msg->reserved; 1939 msg->counts[sectionid] += total; 1940 return (result); 1941 } 1942 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 1943 } 1944 } 1945 1946 do { 1947 name = ISC_LIST_HEAD(*section); 1948 if (name == NULL) { 1949 msg->buffer->length += msg->reserved; 1950 msg->counts[sectionid] += total; 1951 return (ISC_R_SUCCESS); 1952 } 1953 1954 while (name != NULL) { 1955 next_name = ISC_LIST_NEXT(name, link); 1956 1957 rdataset = ISC_LIST_HEAD(name->list); 1958 while (rdataset != NULL) { 1959 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1960 1961 if ((rdataset->attributes & 1962 DNS_RDATASETATTR_RENDERED) != 0) 1963 goto next; 1964 1965 if (((options & DNS_MESSAGERENDER_ORDERED) 1966 == 0) 1967 && (sectionid == DNS_SECTION_ADDITIONAL) 1968 && wrong_priority(rdataset, pass, 1969 preferred_glue)) 1970 goto next; 1971 1972#ifdef ALLOW_FILTER_AAAA_ON_V4 1973 /* 1974 * Suppress AAAAs if asked and we are 1975 * not doing DNSSEC or are breaking DNSSEC. 1976 * Say so in the AD bit if we break DNSSEC. 1977 */ 1978 if (norender_rdataset(rdataset, options) && 1979 sectionid != DNS_SECTION_QUESTION) { 1980 if (sectionid == DNS_SECTION_ANSWER || 1981 sectionid == DNS_SECTION_AUTHORITY) 1982 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1983 if (OPTOUT(rdataset)) 1984 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1985 goto next; 1986 } 1987 1988#endif 1989 st = *(msg->buffer); 1990 1991 count = 0; 1992 if (partial) 1993 result = dns_rdataset_towirepartial( 1994 rdataset, 1995 name, 1996 msg->cctx, 1997 msg->buffer, 1998 msg->order, 1999 msg->order_arg, 2000 rd_options, 2001 &count, 2002 NULL); 2003 else 2004 result = dns_rdataset_towiresorted( 2005 rdataset, 2006 name, 2007 msg->cctx, 2008 msg->buffer, 2009 msg->order, 2010 msg->order_arg, 2011 rd_options, 2012 &count); 2013 2014 total += count; 2015 2016 /* 2017 * If out of space, record stats on what we 2018 * rendered so far, and return that status. 2019 * 2020 * XXXMLG Need to change this when 2021 * dns_rdataset_towire() can render partial 2022 * sets starting at some arbitrary point in the 2023 * set. This will include setting a bit in the 2024 * rdataset to indicate that a partial 2025 * rendering was done, and some state saved 2026 * somewhere (probably in the message struct) 2027 * to indicate where to continue from. 2028 */ 2029 if (partial && result == ISC_R_NOSPACE) { 2030 msg->buffer->length += msg->reserved; 2031 msg->counts[sectionid] += total; 2032 return (result); 2033 } 2034 if (result != ISC_R_SUCCESS) { 2035 INSIST(st.used < 65536); 2036 dns_compress_rollback(msg->cctx, 2037 (isc_uint16_t)st.used); 2038 *(msg->buffer) = st; /* rollback */ 2039 msg->buffer->length += msg->reserved; 2040 msg->counts[sectionid] += total; 2041 return (result); 2042 } 2043 2044 /* 2045 * If we have rendered non-validated data, 2046 * ensure that the AD bit is not set. 2047 */ 2048 if (rdataset->trust != dns_trust_secure && 2049 (sectionid == DNS_SECTION_ANSWER || 2050 sectionid == DNS_SECTION_AUTHORITY)) 2051 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2052 if (OPTOUT(rdataset)) 2053 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2054 2055 rdataset->attributes |= 2056 DNS_RDATASETATTR_RENDERED; 2057 2058 next: 2059 rdataset = next_rdataset; 2060 } 2061 2062 name = next_name; 2063 } 2064 } while (--pass != 0); 2065 2066 msg->buffer->length += msg->reserved; 2067 msg->counts[sectionid] += total; 2068 2069 return (ISC_R_SUCCESS); 2070} 2071 2072void 2073dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 2074 isc_uint16_t tmp; 2075 isc_region_t r; 2076 2077 REQUIRE(DNS_MESSAGE_VALID(msg)); 2078 REQUIRE(target != NULL); 2079 2080 isc_buffer_availableregion(target, &r); 2081 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 2082 2083 isc_buffer_putuint16(target, msg->id); 2084 2085 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 2086 & DNS_MESSAGE_OPCODE_MASK); 2087 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 2088 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 2089 2090 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 2091 msg->counts[DNS_SECTION_ANSWER] < 65536 && 2092 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 2093 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 2094 2095 isc_buffer_putuint16(target, tmp); 2096 isc_buffer_putuint16(target, 2097 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2098 isc_buffer_putuint16(target, 2099 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2100 isc_buffer_putuint16(target, 2101 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2102 isc_buffer_putuint16(target, 2103 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2104} 2105 2106isc_result_t 2107dns_message_renderend(dns_message_t *msg) { 2108 isc_buffer_t tmpbuf; 2109 isc_region_t r; 2110 int result; 2111 unsigned int count; 2112 2113 REQUIRE(DNS_MESSAGE_VALID(msg)); 2114 REQUIRE(msg->buffer != NULL); 2115 2116 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2117 /* 2118 * We have an extended rcode but are not using EDNS. 2119 */ 2120 return (DNS_R_FORMERR); 2121 } 2122 2123 /* 2124 * If we're adding a OPT, TSIG or SIG(0) to a truncated message, 2125 * clear all rdatasets from the message except for the question 2126 * before adding the OPT, TSIG or SIG(0). If the question doesn't 2127 * fit, don't include it. 2128 */ 2129 if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) && 2130 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2131 { 2132 isc_buffer_t *buf; 2133 2134 msgresetnames(msg, DNS_SECTION_ANSWER); 2135 buf = msg->buffer; 2136 dns_message_renderreset(msg); 2137 msg->buffer = buf; 2138 isc_buffer_clear(msg->buffer); 2139 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2140 dns_compress_rollback(msg->cctx, 0); 2141 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2142 0); 2143 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 2144 return (result); 2145 } 2146 2147 /* 2148 * If we've got an OPT record, render it. 2149 */ 2150 if (msg->opt != NULL) { 2151 dns_message_renderrelease(msg, msg->opt_reserved); 2152 msg->opt_reserved = 0; 2153 /* 2154 * Set the extended rcode. 2155 */ 2156 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2157 msg->opt->ttl |= ((msg->rcode << 20) & 2158 DNS_MESSAGE_EDNSRCODE_MASK); 2159 /* 2160 * Render. 2161 */ 2162 count = 0; 2163 result = dns_rdataset_towire(msg->opt, dns_rootname, 2164 msg->cctx, msg->buffer, 0, 2165 &count); 2166 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2167 if (result != ISC_R_SUCCESS) 2168 return (result); 2169 } 2170 2171 /* 2172 * If we're adding a TSIG record, generate and render it. 2173 */ 2174 if (msg->tsigkey != NULL) { 2175 dns_message_renderrelease(msg, msg->sig_reserved); 2176 msg->sig_reserved = 0; 2177 result = dns_tsig_sign(msg); 2178 if (result != ISC_R_SUCCESS) 2179 return (result); 2180 count = 0; 2181 result = dns_rdataset_towire(msg->tsig, msg->tsigname, 2182 msg->cctx, msg->buffer, 0, 2183 &count); 2184 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2185 if (result != ISC_R_SUCCESS) 2186 return (result); 2187 } 2188 2189 /* 2190 * If we're adding a SIG(0) record, generate and render it. 2191 */ 2192 if (msg->sig0key != NULL) { 2193 dns_message_renderrelease(msg, msg->sig_reserved); 2194 msg->sig_reserved = 0; 2195 result = dns_dnssec_signmessage(msg, msg->sig0key); 2196 if (result != ISC_R_SUCCESS) 2197 return (result); 2198 count = 0; 2199 /* 2200 * Note: dns_rootname is used here, not msg->sig0name, since 2201 * the owner name of a SIG(0) is irrelevant, and will not 2202 * be set in a message being rendered. 2203 */ 2204 result = dns_rdataset_towire(msg->sig0, dns_rootname, 2205 msg->cctx, msg->buffer, 0, 2206 &count); 2207 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2208 if (result != ISC_R_SUCCESS) 2209 return (result); 2210 } 2211 2212 isc_buffer_usedregion(msg->buffer, &r); 2213 isc_buffer_init(&tmpbuf, r.base, r.length); 2214 2215 dns_message_renderheader(msg, &tmpbuf); 2216 2217 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2218 2219 return (ISC_R_SUCCESS); 2220} 2221 2222void 2223dns_message_renderreset(dns_message_t *msg) { 2224 unsigned int i; 2225 dns_name_t *name; 2226 dns_rdataset_t *rds; 2227 2228 /* 2229 * Reset the message so that it may be rendered again. 2230 */ 2231 2232 REQUIRE(DNS_MESSAGE_VALID(msg)); 2233 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2234 2235 msg->buffer = NULL; 2236 2237 for (i = 0; i < DNS_SECTION_MAX; i++) { 2238 msg->cursors[i] = NULL; 2239 msg->counts[i] = 0; 2240 for (name = ISC_LIST_HEAD(msg->sections[i]); 2241 name != NULL; 2242 name = ISC_LIST_NEXT(name, link)) { 2243 for (rds = ISC_LIST_HEAD(name->list); 2244 rds != NULL; 2245 rds = ISC_LIST_NEXT(rds, link)) { 2246 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2247 } 2248 } 2249 } 2250 if (msg->tsigname != NULL) 2251 dns_message_puttempname(msg, &msg->tsigname); 2252 if (msg->tsig != NULL) { 2253 dns_rdataset_disassociate(msg->tsig); 2254 dns_message_puttemprdataset(msg, &msg->tsig); 2255 } 2256 if (msg->sig0 != NULL) { 2257 dns_rdataset_disassociate(msg->sig0); 2258 dns_message_puttemprdataset(msg, &msg->sig0); 2259 } 2260} 2261 2262isc_result_t 2263dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2264 REQUIRE(DNS_MESSAGE_VALID(msg)); 2265 REQUIRE(VALID_NAMED_SECTION(section)); 2266 2267 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2268 2269 if (msg->cursors[section] == NULL) 2270 return (ISC_R_NOMORE); 2271 2272 return (ISC_R_SUCCESS); 2273} 2274 2275isc_result_t 2276dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2277 REQUIRE(DNS_MESSAGE_VALID(msg)); 2278 REQUIRE(VALID_NAMED_SECTION(section)); 2279 REQUIRE(msg->cursors[section] != NULL); 2280 2281 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2282 2283 if (msg->cursors[section] == NULL) 2284 return (ISC_R_NOMORE); 2285 2286 return (ISC_R_SUCCESS); 2287} 2288 2289void 2290dns_message_currentname(dns_message_t *msg, dns_section_t section, 2291 dns_name_t **name) 2292{ 2293 REQUIRE(DNS_MESSAGE_VALID(msg)); 2294 REQUIRE(VALID_NAMED_SECTION(section)); 2295 REQUIRE(name != NULL && *name == NULL); 2296 REQUIRE(msg->cursors[section] != NULL); 2297 2298 *name = msg->cursors[section]; 2299} 2300 2301isc_result_t 2302dns_message_findname(dns_message_t *msg, dns_section_t section, 2303 dns_name_t *target, dns_rdatatype_t type, 2304 dns_rdatatype_t covers, dns_name_t **name, 2305 dns_rdataset_t **rdataset) 2306{ 2307 dns_name_t *foundname; 2308 isc_result_t result; 2309 2310 /* 2311 * XXX These requirements are probably too intensive, especially 2312 * where things can be NULL, but as they are they ensure that if 2313 * something is NON-NULL, indicating that the caller expects it 2314 * to be filled in, that we can in fact fill it in. 2315 */ 2316 REQUIRE(msg != NULL); 2317 REQUIRE(VALID_SECTION(section)); 2318 REQUIRE(target != NULL); 2319 if (name != NULL) 2320 REQUIRE(*name == NULL); 2321 if (type == dns_rdatatype_any) { 2322 REQUIRE(rdataset == NULL); 2323 } else { 2324 if (rdataset != NULL) 2325 REQUIRE(*rdataset == NULL); 2326 } 2327 2328 result = findname(&foundname, target, 2329 &msg->sections[section]); 2330 2331 if (result == ISC_R_NOTFOUND) 2332 return (DNS_R_NXDOMAIN); 2333 else if (result != ISC_R_SUCCESS) 2334 return (result); 2335 2336 if (name != NULL) 2337 *name = foundname; 2338 2339 /* 2340 * And now look for the type. 2341 */ 2342 if (type == dns_rdatatype_any) 2343 return (ISC_R_SUCCESS); 2344 2345 result = dns_message_findtype(foundname, type, covers, rdataset); 2346 if (result == ISC_R_NOTFOUND) 2347 return (DNS_R_NXRRSET); 2348 2349 return (result); 2350} 2351 2352void 2353dns_message_movename(dns_message_t *msg, dns_name_t *name, 2354 dns_section_t fromsection, 2355 dns_section_t tosection) 2356{ 2357 REQUIRE(msg != NULL); 2358 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2359 REQUIRE(name != NULL); 2360 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2361 REQUIRE(VALID_NAMED_SECTION(tosection)); 2362 2363 /* 2364 * Unlink the name from the old section 2365 */ 2366 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2367 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2368} 2369 2370void 2371dns_message_addname(dns_message_t *msg, dns_name_t *name, 2372 dns_section_t section) 2373{ 2374 REQUIRE(msg != NULL); 2375 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2376 REQUIRE(name != NULL); 2377 REQUIRE(VALID_NAMED_SECTION(section)); 2378 2379 ISC_LIST_APPEND(msg->sections[section], name, link); 2380} 2381 2382void 2383dns_message_removename(dns_message_t *msg, dns_name_t *name, 2384 dns_section_t section) 2385{ 2386 REQUIRE(msg != NULL); 2387 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2388 REQUIRE(name != NULL); 2389 REQUIRE(VALID_NAMED_SECTION(section)); 2390 2391 ISC_LIST_UNLINK(msg->sections[section], name, link); 2392} 2393 2394isc_result_t 2395dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2396 REQUIRE(DNS_MESSAGE_VALID(msg)); 2397 REQUIRE(item != NULL && *item == NULL); 2398 2399 *item = isc_mempool_get(msg->namepool); 2400 if (*item == NULL) 2401 return (ISC_R_NOMEMORY); 2402 dns_name_init(*item, NULL); 2403 2404 return (ISC_R_SUCCESS); 2405} 2406 2407isc_result_t 2408dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { 2409 REQUIRE(DNS_MESSAGE_VALID(msg)); 2410 REQUIRE(item != NULL && *item == NULL); 2411 2412 *item = newoffsets(msg); 2413 if (*item == NULL) 2414 return (ISC_R_NOMEMORY); 2415 2416 return (ISC_R_SUCCESS); 2417} 2418 2419isc_result_t 2420dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2421 REQUIRE(DNS_MESSAGE_VALID(msg)); 2422 REQUIRE(item != NULL && *item == NULL); 2423 2424 *item = newrdata(msg); 2425 if (*item == NULL) 2426 return (ISC_R_NOMEMORY); 2427 2428 return (ISC_R_SUCCESS); 2429} 2430 2431isc_result_t 2432dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2433 REQUIRE(DNS_MESSAGE_VALID(msg)); 2434 REQUIRE(item != NULL && *item == NULL); 2435 2436 *item = isc_mempool_get(msg->rdspool); 2437 if (*item == NULL) 2438 return (ISC_R_NOMEMORY); 2439 2440 dns_rdataset_init(*item); 2441 2442 return (ISC_R_SUCCESS); 2443} 2444 2445isc_result_t 2446dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2447 REQUIRE(DNS_MESSAGE_VALID(msg)); 2448 REQUIRE(item != NULL && *item == NULL); 2449 2450 *item = newrdatalist(msg); 2451 if (*item == NULL) 2452 return (ISC_R_NOMEMORY); 2453 2454 return (ISC_R_SUCCESS); 2455} 2456 2457void 2458dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2459 REQUIRE(DNS_MESSAGE_VALID(msg)); 2460 REQUIRE(item != NULL && *item != NULL); 2461 2462 if (dns_name_dynamic(*item)) 2463 dns_name_free(*item, msg->mctx); 2464 isc_mempool_put(msg->namepool, *item); 2465 *item = NULL; 2466} 2467 2468void 2469dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2470 REQUIRE(DNS_MESSAGE_VALID(msg)); 2471 REQUIRE(item != NULL && *item != NULL); 2472 2473 releaserdata(msg, *item); 2474 *item = NULL; 2475} 2476 2477void 2478dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2479 REQUIRE(DNS_MESSAGE_VALID(msg)); 2480 REQUIRE(item != NULL && *item != NULL); 2481 2482 REQUIRE(!dns_rdataset_isassociated(*item)); 2483 isc_mempool_put(msg->rdspool, *item); 2484 *item = NULL; 2485} 2486 2487void 2488dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2489 REQUIRE(DNS_MESSAGE_VALID(msg)); 2490 REQUIRE(item != NULL && *item != NULL); 2491 2492 releaserdatalist(msg, *item); 2493 *item = NULL; 2494} 2495 2496isc_result_t 2497dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2498 unsigned int *flagsp) 2499{ 2500 isc_region_t r; 2501 isc_buffer_t buffer; 2502 dns_messageid_t id; 2503 unsigned int flags; 2504 2505 REQUIRE(source != NULL); 2506 2507 buffer = *source; 2508 2509 isc_buffer_remainingregion(&buffer, &r); 2510 if (r.length < DNS_MESSAGE_HEADERLEN) 2511 return (ISC_R_UNEXPECTEDEND); 2512 2513 id = isc_buffer_getuint16(&buffer); 2514 flags = isc_buffer_getuint16(&buffer); 2515 flags &= DNS_MESSAGE_FLAG_MASK; 2516 2517 if (flagsp != NULL) 2518 *flagsp = flags; 2519 if (idp != NULL) 2520 *idp = id; 2521 2522 return (ISC_R_SUCCESS); 2523} 2524 2525isc_result_t 2526dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { 2527 unsigned int clear_after; 2528 isc_result_t result; 2529 2530 REQUIRE(DNS_MESSAGE_VALID(msg)); 2531 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2532 2533 if (!msg->header_ok) 2534 return (DNS_R_FORMERR); 2535 if (msg->opcode != dns_opcode_query && 2536 msg->opcode != dns_opcode_notify) 2537 want_question_section = ISC_FALSE; 2538 if (msg->opcode == dns_opcode_update) 2539 clear_after = DNS_SECTION_PREREQUISITE; 2540 else if (want_question_section) { 2541 if (!msg->question_ok) 2542 return (DNS_R_FORMERR); 2543 clear_after = DNS_SECTION_ANSWER; 2544 } else 2545 clear_after = DNS_SECTION_QUESTION; 2546 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2547 msgresetnames(msg, clear_after); 2548 msgresetopt(msg); 2549 msgresetsigs(msg, ISC_TRUE); 2550 msginitprivate(msg); 2551 /* 2552 * We now clear most flags and then set QR, ensuring that the 2553 * reply's flags will be in a reasonable state. 2554 */ 2555 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2556 msg->flags |= DNS_MESSAGEFLAG_QR; 2557 2558 /* 2559 * This saves the query TSIG status, if the query was signed, and 2560 * reserves space in the reply for the TSIG. 2561 */ 2562 if (msg->tsigkey != NULL) { 2563 unsigned int otherlen = 0; 2564 msg->querytsigstatus = msg->tsigstatus; 2565 msg->tsigstatus = dns_rcode_noerror; 2566 if (msg->querytsigstatus == dns_tsigerror_badtime) 2567 otherlen = 6; 2568 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2569 result = dns_message_renderreserve(msg, msg->sig_reserved); 2570 if (result != ISC_R_SUCCESS) { 2571 msg->sig_reserved = 0; 2572 return (result); 2573 } 2574 } 2575 if (msg->saved.base != NULL) { 2576 msg->query.base = msg->saved.base; 2577 msg->query.length = msg->saved.length; 2578 msg->free_query = msg->free_saved; 2579 msg->saved.base = NULL; 2580 msg->saved.length = 0; 2581 msg->free_saved = 0; 2582 } 2583 2584 return (ISC_R_SUCCESS); 2585} 2586 2587dns_rdataset_t * 2588dns_message_getopt(dns_message_t *msg) { 2589 2590 /* 2591 * Get the OPT record for 'msg'. 2592 */ 2593 2594 REQUIRE(DNS_MESSAGE_VALID(msg)); 2595 2596 return (msg->opt); 2597} 2598 2599isc_result_t 2600dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2601 isc_result_t result; 2602 dns_rdata_t rdata = DNS_RDATA_INIT; 2603 2604 /* 2605 * Set the OPT record for 'msg'. 2606 */ 2607 2608 /* 2609 * The space required for an OPT record is: 2610 * 2611 * 1 byte for the name 2612 * 2 bytes for the type 2613 * 2 bytes for the class 2614 * 4 bytes for the ttl 2615 * 2 bytes for the rdata length 2616 * --------------------------------- 2617 * 11 bytes 2618 * 2619 * plus the length of the rdata. 2620 */ 2621 2622 REQUIRE(DNS_MESSAGE_VALID(msg)); 2623 REQUIRE(opt->type == dns_rdatatype_opt); 2624 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2625 REQUIRE(msg->state == DNS_SECTION_ANY); 2626 2627 msgresetopt(msg); 2628 2629 result = dns_rdataset_first(opt); 2630 if (result != ISC_R_SUCCESS) 2631 goto cleanup; 2632 dns_rdataset_current(opt, &rdata); 2633 msg->opt_reserved = 11 + rdata.length; 2634 result = dns_message_renderreserve(msg, msg->opt_reserved); 2635 if (result != ISC_R_SUCCESS) { 2636 msg->opt_reserved = 0; 2637 goto cleanup; 2638 } 2639 2640 msg->opt = opt; 2641 2642 return (ISC_R_SUCCESS); 2643 2644 cleanup: 2645 dns_rdataset_disassociate(opt); 2646 dns_message_puttemprdataset(msg, &opt); 2647 return (result); 2648} 2649 2650dns_rdataset_t * 2651dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2652 2653 /* 2654 * Get the TSIG record and owner for 'msg'. 2655 */ 2656 2657 REQUIRE(DNS_MESSAGE_VALID(msg)); 2658 REQUIRE(owner == NULL || *owner == NULL); 2659 2660 if (owner != NULL) 2661 *owner = msg->tsigname; 2662 return (msg->tsig); 2663} 2664 2665isc_result_t 2666dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2667 isc_result_t result; 2668 2669 /* 2670 * Set the TSIG key for 'msg' 2671 */ 2672 2673 REQUIRE(DNS_MESSAGE_VALID(msg)); 2674 REQUIRE(msg->state == DNS_SECTION_ANY); 2675 2676 if (key == NULL && msg->tsigkey != NULL) { 2677 if (msg->sig_reserved != 0) { 2678 dns_message_renderrelease(msg, msg->sig_reserved); 2679 msg->sig_reserved = 0; 2680 } 2681 dns_tsigkey_detach(&msg->tsigkey); 2682 } 2683 if (key != NULL) { 2684 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2685 dns_tsigkey_attach(key, &msg->tsigkey); 2686 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2687 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2688 result = dns_message_renderreserve(msg, 2689 msg->sig_reserved); 2690 if (result != ISC_R_SUCCESS) { 2691 dns_tsigkey_detach(&msg->tsigkey); 2692 msg->sig_reserved = 0; 2693 return (result); 2694 } 2695 } 2696 } 2697 return (ISC_R_SUCCESS); 2698} 2699 2700dns_tsigkey_t * 2701dns_message_gettsigkey(dns_message_t *msg) { 2702 2703 /* 2704 * Get the TSIG key for 'msg' 2705 */ 2706 2707 REQUIRE(DNS_MESSAGE_VALID(msg)); 2708 2709 return (msg->tsigkey); 2710} 2711 2712isc_result_t 2713dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2714 dns_rdata_t *rdata = NULL; 2715 dns_rdatalist_t *list = NULL; 2716 dns_rdataset_t *set = NULL; 2717 isc_buffer_t *buf = NULL; 2718 isc_region_t r; 2719 isc_result_t result; 2720 2721 REQUIRE(DNS_MESSAGE_VALID(msg)); 2722 REQUIRE(msg->querytsig == NULL); 2723 2724 if (querytsig == NULL) 2725 return (ISC_R_SUCCESS); 2726 2727 result = dns_message_gettemprdata(msg, &rdata); 2728 if (result != ISC_R_SUCCESS) 2729 goto cleanup; 2730 2731 result = dns_message_gettemprdatalist(msg, &list); 2732 if (result != ISC_R_SUCCESS) 2733 goto cleanup; 2734 result = dns_message_gettemprdataset(msg, &set); 2735 if (result != ISC_R_SUCCESS) 2736 goto cleanup; 2737 2738 isc_buffer_usedregion(querytsig, &r); 2739 result = isc_buffer_allocate(msg->mctx, &buf, r.length); 2740 if (result != ISC_R_SUCCESS) 2741 goto cleanup; 2742 isc_buffer_putmem(buf, r.base, r.length); 2743 isc_buffer_usedregion(buf, &r); 2744 dns_rdata_init(rdata); 2745 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2746 dns_message_takebuffer(msg, &buf); 2747 ISC_LIST_INIT(list->rdata); 2748 ISC_LIST_APPEND(list->rdata, rdata, link); 2749 result = dns_rdatalist_tordataset(list, set); 2750 if (result != ISC_R_SUCCESS) 2751 goto cleanup; 2752 2753 msg->querytsig = set; 2754 2755 return (result); 2756 2757 cleanup: 2758 if (rdata != NULL) 2759 dns_message_puttemprdata(msg, &rdata); 2760 if (list != NULL) 2761 dns_message_puttemprdatalist(msg, &list); 2762 if (set != NULL) 2763 dns_message_puttemprdataset(msg, &set); 2764 return (ISC_R_NOMEMORY); 2765} 2766 2767isc_result_t 2768dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2769 isc_buffer_t **querytsig) { 2770 isc_result_t result; 2771 dns_rdata_t rdata = DNS_RDATA_INIT; 2772 isc_region_t r; 2773 2774 REQUIRE(DNS_MESSAGE_VALID(msg)); 2775 REQUIRE(mctx != NULL); 2776 REQUIRE(querytsig != NULL && *querytsig == NULL); 2777 2778 if (msg->tsig == NULL) 2779 return (ISC_R_SUCCESS); 2780 2781 result = dns_rdataset_first(msg->tsig); 2782 if (result != ISC_R_SUCCESS) 2783 return (result); 2784 dns_rdataset_current(msg->tsig, &rdata); 2785 dns_rdata_toregion(&rdata, &r); 2786 2787 result = isc_buffer_allocate(mctx, querytsig, r.length); 2788 if (result != ISC_R_SUCCESS) 2789 return (result); 2790 isc_buffer_putmem(*querytsig, r.base, r.length); 2791 return (ISC_R_SUCCESS); 2792} 2793 2794dns_rdataset_t * 2795dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2796 2797 /* 2798 * Get the SIG(0) record for 'msg'. 2799 */ 2800 2801 REQUIRE(DNS_MESSAGE_VALID(msg)); 2802 REQUIRE(owner == NULL || *owner == NULL); 2803 2804 if (msg->sig0 != NULL && owner != NULL) { 2805 /* If dns_message_getsig0 is called on a rendered message 2806 * after the SIG(0) has been applied, we need to return the 2807 * root name, not NULL. 2808 */ 2809 if (msg->sig0name == NULL) 2810 *owner = dns_rootname; 2811 else 2812 *owner = msg->sig0name; 2813 } 2814 return (msg->sig0); 2815} 2816 2817isc_result_t 2818dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2819 isc_region_t r; 2820 unsigned int x; 2821 isc_result_t result; 2822 2823 /* 2824 * Set the SIG(0) key for 'msg' 2825 */ 2826 2827 /* 2828 * The space required for an SIG(0) record is: 2829 * 2830 * 1 byte for the name 2831 * 2 bytes for the type 2832 * 2 bytes for the class 2833 * 4 bytes for the ttl 2834 * 2 bytes for the type covered 2835 * 1 byte for the algorithm 2836 * 1 bytes for the labels 2837 * 4 bytes for the original ttl 2838 * 4 bytes for the signature expiration 2839 * 4 bytes for the signature inception 2840 * 2 bytes for the key tag 2841 * n bytes for the signer's name 2842 * x bytes for the signature 2843 * --------------------------------- 2844 * 27 + n + x bytes 2845 */ 2846 REQUIRE(DNS_MESSAGE_VALID(msg)); 2847 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2848 REQUIRE(msg->state == DNS_SECTION_ANY); 2849 2850 if (key != NULL) { 2851 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 2852 dns_name_toregion(dst_key_name(key), &r); 2853 result = dst_key_sigsize(key, &x); 2854 if (result != ISC_R_SUCCESS) { 2855 msg->sig_reserved = 0; 2856 return (result); 2857 } 2858 msg->sig_reserved = 27 + r.length + x; 2859 result = dns_message_renderreserve(msg, msg->sig_reserved); 2860 if (result != ISC_R_SUCCESS) { 2861 msg->sig_reserved = 0; 2862 return (result); 2863 } 2864 msg->sig0key = key; 2865 } 2866 return (ISC_R_SUCCESS); 2867} 2868 2869dst_key_t * 2870dns_message_getsig0key(dns_message_t *msg) { 2871 2872 /* 2873 * Get the SIG(0) key for 'msg' 2874 */ 2875 2876 REQUIRE(DNS_MESSAGE_VALID(msg)); 2877 2878 return (msg->sig0key); 2879} 2880 2881void 2882dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2883 REQUIRE(DNS_MESSAGE_VALID(msg)); 2884 REQUIRE(buffer != NULL); 2885 REQUIRE(ISC_BUFFER_VALID(*buffer)); 2886 2887 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2888 *buffer = NULL; 2889} 2890 2891isc_result_t 2892dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 2893 isc_result_t result = ISC_R_SUCCESS; 2894 dns_rdata_t rdata = DNS_RDATA_INIT; 2895 2896 REQUIRE(DNS_MESSAGE_VALID(msg)); 2897 REQUIRE(signer != NULL); 2898 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 2899 2900 if (msg->tsig == NULL && msg->sig0 == NULL) 2901 return (ISC_R_NOTFOUND); 2902 2903 if (msg->verify_attempted == 0) 2904 return (DNS_R_NOTVERIFIEDYET); 2905 2906 if (!dns_name_hasbuffer(signer)) { 2907 isc_buffer_t *dynbuf = NULL; 2908 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 2909 if (result != ISC_R_SUCCESS) 2910 return (result); 2911 dns_name_setbuffer(signer, dynbuf); 2912 dns_message_takebuffer(msg, &dynbuf); 2913 } 2914 2915 if (msg->sig0 != NULL) { 2916 dns_rdata_sig_t sig; 2917 2918 result = dns_rdataset_first(msg->sig0); 2919 INSIST(result == ISC_R_SUCCESS); 2920 dns_rdataset_current(msg->sig0, &rdata); 2921 2922 result = dns_rdata_tostruct(&rdata, &sig, NULL); 2923 if (result != ISC_R_SUCCESS) 2924 return (result); 2925 2926 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) 2927 result = ISC_R_SUCCESS; 2928 else 2929 result = DNS_R_SIGINVALID; 2930 dns_name_clone(&sig.signer, signer); 2931 dns_rdata_freestruct(&sig); 2932 } else { 2933 dns_name_t *identity; 2934 dns_rdata_any_tsig_t tsig; 2935 2936 result = dns_rdataset_first(msg->tsig); 2937 INSIST(result == ISC_R_SUCCESS); 2938 dns_rdataset_current(msg->tsig, &rdata); 2939 2940 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2941 INSIST(result == ISC_R_SUCCESS); 2942 if (msg->tsigstatus != dns_rcode_noerror) 2943 result = DNS_R_TSIGVERIFYFAILURE; 2944 else if (tsig.error != dns_rcode_noerror) 2945 result = DNS_R_TSIGERRORSET; 2946 else 2947 result = ISC_R_SUCCESS; 2948 dns_rdata_freestruct(&tsig); 2949 2950 if (msg->tsigkey == NULL) { 2951 /* 2952 * If msg->tsigstatus & tsig.error are both 2953 * dns_rcode_noerror, the message must have been 2954 * verified, which means msg->tsigkey will be 2955 * non-NULL. 2956 */ 2957 INSIST(result != ISC_R_SUCCESS); 2958 } else { 2959 identity = dns_tsigkey_identity(msg->tsigkey); 2960 if (identity == NULL) { 2961 if (result == ISC_R_SUCCESS) 2962 result = DNS_R_NOIDENTITY; 2963 identity = &msg->tsigkey->name; 2964 } 2965 dns_name_clone(identity, signer); 2966 } 2967 } 2968 2969 return (result); 2970} 2971 2972void 2973dns_message_resetsig(dns_message_t *msg) { 2974 REQUIRE(DNS_MESSAGE_VALID(msg)); 2975 msg->verified_sig = 0; 2976 msg->verify_attempted = 0; 2977 msg->tsigstatus = dns_rcode_noerror; 2978 msg->sig0status = dns_rcode_noerror; 2979 msg->timeadjust = 0; 2980 if (msg->tsigkey != NULL) { 2981 dns_tsigkey_detach(&msg->tsigkey); 2982 msg->tsigkey = NULL; 2983 } 2984} 2985 2986isc_result_t 2987dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 2988 dns_message_resetsig(msg); 2989 return (dns_message_checksig(msg, view)); 2990} 2991 2992#ifdef SKAN_MSG_DEBUG 2993void 2994dns_message_dumpsig(dns_message_t *msg, char *txt1) { 2995 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 2996 dns_rdata_any_tsig_t querytsig; 2997 isc_result_t result; 2998 2999 if (msg->tsig != NULL) { 3000 result = dns_rdataset_first(msg->tsig); 3001 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3002 dns_rdataset_current(msg->tsig, &querytsigrdata); 3003 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 3004 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3005 hexdump(txt1, "TSIG", querytsig.signature, 3006 querytsig.siglen); 3007 } 3008 3009 if (msg->querytsig != NULL) { 3010 result = dns_rdataset_first(msg->querytsig); 3011 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3012 dns_rdataset_current(msg->querytsig, &querytsigrdata); 3013 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 3014 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3015 hexdump(txt1, "QUERYTSIG", querytsig.signature, 3016 querytsig.siglen); 3017 } 3018} 3019#endif 3020 3021isc_result_t 3022dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 3023 isc_buffer_t b, msgb; 3024 3025 REQUIRE(DNS_MESSAGE_VALID(msg)); 3026 3027 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) 3028 return (ISC_R_SUCCESS); 3029 3030 INSIST(msg->saved.base != NULL); 3031 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 3032 isc_buffer_add(&msgb, msg->saved.length); 3033 if (msg->tsigkey != NULL || msg->tsig != NULL) { 3034#ifdef SKAN_MSG_DEBUG 3035 dns_message_dumpsig(msg, "dns_message_checksig#1"); 3036#endif 3037 if (view != NULL) 3038 return (dns_view_checksig(view, &msgb, msg)); 3039 else 3040 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 3041 } else { 3042 dns_rdata_t rdata = DNS_RDATA_INIT; 3043 dns_rdata_sig_t sig; 3044 dns_rdataset_t keyset; 3045 isc_result_t result; 3046 3047 result = dns_rdataset_first(msg->sig0); 3048 INSIST(result == ISC_R_SUCCESS); 3049 dns_rdataset_current(msg->sig0, &rdata); 3050 3051 /* 3052 * This can occur when the message is a dynamic update, since 3053 * the rdata length checking is relaxed. This should not 3054 * happen in a well-formed message, since the SIG(0) is only 3055 * looked for in the additional section, and the dynamic update 3056 * meta-records are in the prerequisite and update sections. 3057 */ 3058 if (rdata.length == 0) 3059 return (ISC_R_UNEXPECTEDEND); 3060 3061 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 3062 if (result != ISC_R_SUCCESS) 3063 return (result); 3064 3065 dns_rdataset_init(&keyset); 3066 if (view == NULL) 3067 return (DNS_R_KEYUNAUTHORIZED); 3068 result = dns_view_simplefind(view, &sig.signer, 3069 dns_rdatatype_key /* SIG(0) */, 3070 0, 0, ISC_FALSE, &keyset, NULL); 3071 3072 if (result != ISC_R_SUCCESS) { 3073 /* XXXBEW Should possibly create a fetch here */ 3074 result = DNS_R_KEYUNAUTHORIZED; 3075 goto freesig; 3076 } else if (keyset.trust < dns_trust_secure) { 3077 /* XXXBEW Should call a validator here */ 3078 result = DNS_R_KEYUNAUTHORIZED; 3079 goto freesig; 3080 } 3081 result = dns_rdataset_first(&keyset); 3082 INSIST(result == ISC_R_SUCCESS); 3083 for (; 3084 result == ISC_R_SUCCESS; 3085 result = dns_rdataset_next(&keyset)) 3086 { 3087 dst_key_t *key = NULL; 3088 3089 dns_rdata_reset(&rdata); 3090 dns_rdataset_current(&keyset, &rdata); 3091 isc_buffer_init(&b, rdata.data, rdata.length); 3092 isc_buffer_add(&b, rdata.length); 3093 3094 result = dst_key_fromdns(&sig.signer, rdata.rdclass, 3095 &b, view->mctx, &key); 3096 if (result != ISC_R_SUCCESS) 3097 continue; 3098 if (dst_key_alg(key) != sig.algorithm || 3099 dst_key_id(key) != sig.keyid || 3100 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 3101 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 3102 { 3103 dst_key_free(&key); 3104 continue; 3105 } 3106 result = dns_dnssec_verifymessage(&msgb, msg, key); 3107 dst_key_free(&key); 3108 if (result == ISC_R_SUCCESS) 3109 break; 3110 } 3111 if (result == ISC_R_NOMORE) 3112 result = DNS_R_KEYUNAUTHORIZED; 3113 3114 freesig: 3115 if (dns_rdataset_isassociated(&keyset)) 3116 dns_rdataset_disassociate(&keyset); 3117 dns_rdata_freestruct(&sig); 3118 return (result); 3119 } 3120} 3121 3122isc_result_t 3123dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 3124 const dns_master_style_t *style, 3125 dns_messagetextflag_t flags, 3126 isc_buffer_t *target) { 3127 dns_name_t *name, empty_name; 3128 dns_rdataset_t *rdataset; 3129 isc_result_t result; 3130 isc_boolean_t seensoa = ISC_FALSE; 3131 3132 REQUIRE(DNS_MESSAGE_VALID(msg)); 3133 REQUIRE(target != NULL); 3134 REQUIRE(VALID_SECTION(section)); 3135 3136 if (ISC_LIST_EMPTY(msg->sections[section])) 3137 return (ISC_R_SUCCESS); 3138 3139 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3140 ADD_STRING(target, ";; "); 3141 if (msg->opcode != dns_opcode_update) { 3142 ADD_STRING(target, sectiontext[section]); 3143 } else { 3144 ADD_STRING(target, updsectiontext[section]); 3145 } 3146 ADD_STRING(target, " SECTION:\n"); 3147 } 3148 3149 dns_name_init(&empty_name, NULL); 3150 result = dns_message_firstname(msg, section); 3151 if (result != ISC_R_SUCCESS) { 3152 return (result); 3153 } 3154 do { 3155 name = NULL; 3156 dns_message_currentname(msg, section, &name); 3157 for (rdataset = ISC_LIST_HEAD(name->list); 3158 rdataset != NULL; 3159 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3160 if (section == DNS_SECTION_ANSWER && 3161 rdataset->type == dns_rdatatype_soa) { 3162 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0) 3163 continue; 3164 if (seensoa && 3165 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0) 3166 continue; 3167 seensoa = ISC_TRUE; 3168 } 3169 if (section == DNS_SECTION_QUESTION) { 3170 ADD_STRING(target, ";"); 3171 result = dns_master_questiontotext(name, 3172 rdataset, 3173 style, 3174 target); 3175 } else { 3176 result = dns_master_rdatasettotext(name, 3177 rdataset, 3178 style, 3179 target); 3180 } 3181 if (result != ISC_R_SUCCESS) 3182 return (result); 3183 } 3184 result = dns_message_nextname(msg, section); 3185 } while (result == ISC_R_SUCCESS); 3186 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3187 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3188 ADD_STRING(target, "\n"); 3189 if (result == ISC_R_NOMORE) 3190 result = ISC_R_SUCCESS; 3191 return (result); 3192} 3193 3194isc_result_t 3195dns_message_pseudosectiontotext(dns_message_t *msg, 3196 dns_pseudosection_t section, 3197 const dns_master_style_t *style, 3198 dns_messagetextflag_t flags, 3199 isc_buffer_t *target) { 3200 dns_rdataset_t *ps = NULL; 3201 dns_name_t *name = NULL; 3202 isc_result_t result; 3203 char buf[sizeof("1234567890")]; 3204 isc_uint32_t mbz; 3205 dns_rdata_t rdata; 3206 isc_buffer_t optbuf; 3207 isc_uint16_t optcode, optlen; 3208 unsigned char *optdata; 3209 3210 REQUIRE(DNS_MESSAGE_VALID(msg)); 3211 REQUIRE(target != NULL); 3212 REQUIRE(VALID_PSEUDOSECTION(section)); 3213 3214 switch (section) { 3215 case DNS_PSEUDOSECTION_OPT: 3216 ps = dns_message_getopt(msg); 3217 if (ps == NULL) 3218 return (ISC_R_SUCCESS); 3219 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3220 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3221 ADD_STRING(target, "; EDNS: version: "); 3222 snprintf(buf, sizeof(buf), "%u", 3223 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3224 ADD_STRING(target, buf); 3225 ADD_STRING(target, ", flags:"); 3226 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 3227 ADD_STRING(target, " do"); 3228 mbz = ps->ttl & 0xffff; 3229 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 3230 if (mbz != 0) { 3231 ADD_STRING(target, "; MBZ: "); 3232 snprintf(buf, sizeof(buf), "%.4x ", mbz); 3233 ADD_STRING(target, buf); 3234 ADD_STRING(target, ", udp: "); 3235 } else 3236 ADD_STRING(target, "; udp: "); 3237 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3238 ADD_STRING(target, buf); 3239 3240 result = dns_rdataset_first(ps); 3241 if (result != ISC_R_SUCCESS) 3242 return (ISC_R_SUCCESS); 3243 3244 /* Print EDNS info, if any */ 3245 dns_rdata_init(&rdata); 3246 dns_rdataset_current(ps, &rdata); 3247 3248 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3249 isc_buffer_add(&optbuf, rdata.length); 3250 while (isc_buffer_remaininglength(&optbuf) != 0) { 3251 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 3252 optcode = isc_buffer_getuint16(&optbuf); 3253 optlen = isc_buffer_getuint16(&optbuf); 3254 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 3255 3256 if (optcode == DNS_OPT_NSID) { 3257 ADD_STRING(target, "; NSID"); 3258 } else { 3259 ADD_STRING(target, "; OPT="); 3260 sprintf(buf, "%u", optcode); 3261 ADD_STRING(target, buf); 3262 } 3263 3264 if (optlen != 0) { 3265 int i; 3266 ADD_STRING(target, ": "); 3267 3268 optdata = isc_buffer_current(&optbuf); 3269 for (i = 0; i < optlen; i++) { 3270 sprintf(buf, "%02x ", optdata[i]); 3271 ADD_STRING(target, buf); 3272 } 3273 for (i = 0; i < optlen; i++) { 3274 ADD_STRING(target, " ("); 3275 if (isprint(optdata[i])) 3276 isc_buffer_putmem(target, 3277 &optdata[i], 3278 1); 3279 else 3280 isc_buffer_putstr(target, "."); 3281 ADD_STRING(target, ")"); 3282 } 3283 isc_buffer_forward(&optbuf, optlen); 3284 } 3285 ADD_STRING(target, "\n"); 3286 } 3287 return (ISC_R_SUCCESS); 3288 case DNS_PSEUDOSECTION_TSIG: 3289 ps = dns_message_gettsig(msg, &name); 3290 if (ps == NULL) 3291 return (ISC_R_SUCCESS); 3292 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3293 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 3294 result = dns_master_rdatasettotext(name, ps, style, target); 3295 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3296 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3297 ADD_STRING(target, "\n"); 3298 return (result); 3299 case DNS_PSEUDOSECTION_SIG0: 3300 ps = dns_message_getsig0(msg, &name); 3301 if (ps == NULL) 3302 return (ISC_R_SUCCESS); 3303 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3304 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 3305 result = dns_master_rdatasettotext(name, ps, style, target); 3306 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3307 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3308 ADD_STRING(target, "\n"); 3309 return (result); 3310 } 3311 return (ISC_R_UNEXPECTED); 3312} 3313 3314isc_result_t 3315dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 3316 dns_messagetextflag_t flags, isc_buffer_t *target) { 3317 char buf[sizeof("1234567890")]; 3318 isc_result_t result; 3319 3320 REQUIRE(DNS_MESSAGE_VALID(msg)); 3321 REQUIRE(target != NULL); 3322 3323 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { 3324 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 3325 ADD_STRING(target, opcodetext[msg->opcode]); 3326 ADD_STRING(target, ", status: "); 3327 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 3328 ADD_STRING(target, rcodetext[msg->rcode]); 3329 } else { 3330 snprintf(buf, sizeof(buf), "%4u", msg->rcode); 3331 ADD_STRING(target, buf); 3332 } 3333 ADD_STRING(target, ", id: "); 3334 snprintf(buf, sizeof(buf), "%6u", msg->id); 3335 ADD_STRING(target, buf); 3336 ADD_STRING(target, "\n;; flags:"); 3337 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 3338 ADD_STRING(target, " qr"); 3339 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 3340 ADD_STRING(target, " aa"); 3341 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 3342 ADD_STRING(target, " tc"); 3343 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 3344 ADD_STRING(target, " rd"); 3345 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 3346 ADD_STRING(target, " ra"); 3347 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 3348 ADD_STRING(target, " ad"); 3349 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 3350 ADD_STRING(target, " cd"); 3351 /* 3352 * The final unnamed flag must be zero. 3353 */ 3354 if ((msg->flags & 0x0040U) != 0) 3355 ADD_STRING(target, "; MBZ: 0x4"); 3356 if (msg->opcode != dns_opcode_update) { 3357 ADD_STRING(target, "; QUESTION: "); 3358 } else { 3359 ADD_STRING(target, "; ZONE: "); 3360 } 3361 snprintf(buf, sizeof(buf), "%1u", 3362 msg->counts[DNS_SECTION_QUESTION]); 3363 ADD_STRING(target, buf); 3364 if (msg->opcode != dns_opcode_update) { 3365 ADD_STRING(target, ", ANSWER: "); 3366 } else { 3367 ADD_STRING(target, ", PREREQ: "); 3368 } 3369 snprintf(buf, sizeof(buf), "%1u", 3370 msg->counts[DNS_SECTION_ANSWER]); 3371 ADD_STRING(target, buf); 3372 if (msg->opcode != dns_opcode_update) { 3373 ADD_STRING(target, ", AUTHORITY: "); 3374 } else { 3375 ADD_STRING(target, ", UPDATE: "); 3376 } 3377 snprintf(buf, sizeof(buf), "%1u", 3378 msg->counts[DNS_SECTION_AUTHORITY]); 3379 ADD_STRING(target, buf); 3380 ADD_STRING(target, ", ADDITIONAL: "); 3381 snprintf(buf, sizeof(buf), "%1u", 3382 msg->counts[DNS_SECTION_ADDITIONAL]); 3383 ADD_STRING(target, buf); 3384 ADD_STRING(target, "\n"); 3385 } 3386 result = dns_message_pseudosectiontotext(msg, 3387 DNS_PSEUDOSECTION_OPT, 3388 style, flags, target); 3389 if (result != ISC_R_SUCCESS) 3390 return (result); 3391 3392 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, 3393 style, flags, target); 3394 if (result != ISC_R_SUCCESS) 3395 return (result); 3396 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, 3397 style, flags, target); 3398 if (result != ISC_R_SUCCESS) 3399 return (result); 3400 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, 3401 style, flags, target); 3402 if (result != ISC_R_SUCCESS) 3403 return (result); 3404 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, 3405 style, flags, target); 3406 if (result != ISC_R_SUCCESS) 3407 return (result); 3408 3409 result = dns_message_pseudosectiontotext(msg, 3410 DNS_PSEUDOSECTION_TSIG, 3411 style, flags, target); 3412 if (result != ISC_R_SUCCESS) 3413 return (result); 3414 3415 result = dns_message_pseudosectiontotext(msg, 3416 DNS_PSEUDOSECTION_SIG0, 3417 style, flags, target); 3418 if (result != ISC_R_SUCCESS) 3419 return (result); 3420 3421 return (ISC_R_SUCCESS); 3422} 3423 3424isc_region_t * 3425dns_message_getrawmessage(dns_message_t *msg) { 3426 REQUIRE(DNS_MESSAGE_VALID(msg)); 3427 return (&msg->saved); 3428} 3429 3430void 3431dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 3432 const void *order_arg) 3433{ 3434 REQUIRE(DNS_MESSAGE_VALID(msg)); 3435 msg->order = order; 3436 msg->order_arg = order_arg; 3437} 3438 3439void 3440dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 3441 REQUIRE(DNS_MESSAGE_VALID(msg)); 3442 msg->timeadjust = timeadjust; 3443} 3444 3445int 3446dns_message_gettimeadjust(dns_message_t *msg) { 3447 REQUIRE(DNS_MESSAGE_VALID(msg)); 3448 return (msg->timeadjust); 3449} 3450 3451isc_result_t 3452dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 3453 3454 REQUIRE(opcode < 16); 3455 3456 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) 3457 return (ISC_R_NOSPACE); 3458 isc_buffer_putstr(target, opcodetext[opcode]); 3459 return (ISC_R_SUCCESS); 3460} 3461 3462isc_result_t 3463dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, 3464 unsigned int version, isc_uint16_t udpsize, 3465 unsigned int flags, dns_ednsopt_t *ednsopts, size_t count) 3466{ 3467 dns_rdataset_t *rdataset = NULL; 3468 dns_rdatalist_t *rdatalist = NULL; 3469 dns_rdata_t *rdata = NULL; 3470 isc_result_t result; 3471 unsigned int len = 0, i; 3472 3473 REQUIRE(DNS_MESSAGE_VALID(message)); 3474 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL); 3475 3476 result = dns_message_gettemprdatalist(message, &rdatalist); 3477 if (result != ISC_R_SUCCESS) 3478 return (result); 3479 result = dns_message_gettemprdata(message, &rdata); 3480 if (result != ISC_R_SUCCESS) 3481 goto cleanup; 3482 result = dns_message_gettemprdataset(message, &rdataset); 3483 if (result != ISC_R_SUCCESS) 3484 goto cleanup; 3485 dns_rdataset_init(rdataset); 3486 3487 rdatalist->type = dns_rdatatype_opt; 3488 rdatalist->covers = 0; 3489 3490 /* 3491 * Set Maximum UDP buffer size. 3492 */ 3493 rdatalist->rdclass = udpsize; 3494 3495 /* 3496 * Set EXTENDED-RCODE and Z to 0. 3497 */ 3498 rdatalist->ttl = (version << 16); 3499 rdatalist->ttl |= (flags & 0xffff); 3500 3501 /* 3502 * Set EDNS options if applicable 3503 */ 3504 if (count != 0U) { 3505 isc_buffer_t *buf = NULL; 3506 for (i = 0; i < count; i++) 3507 len += ednsopts[i].length + 4; 3508 3509 if (len > 0xffffU) { 3510 result = ISC_R_NOSPACE; 3511 goto cleanup; 3512 } 3513 3514 result = isc_buffer_allocate(message->mctx, &buf, len); 3515 if (result != ISC_R_SUCCESS) 3516 goto cleanup; 3517 3518 for (i = 0; i < count; i++) { 3519 isc_buffer_putuint16(buf, ednsopts[i].code); 3520 isc_buffer_putuint16(buf, ednsopts[i].length); 3521 isc_buffer_putmem(buf, ednsopts[i].value, 3522 ednsopts[i].length); 3523 } 3524 rdata->data = isc_buffer_base(buf); 3525 rdata->length = len; 3526 dns_message_takebuffer(message, &buf); 3527 } else { 3528 rdata->data = NULL; 3529 rdata->length = 0; 3530 } 3531 3532 rdata->rdclass = rdatalist->rdclass; 3533 rdata->type = rdatalist->type; 3534 rdata->flags = 0; 3535 3536 ISC_LIST_INIT(rdatalist->rdata); 3537 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 3538 result = dns_rdatalist_tordataset(rdatalist, rdataset); 3539 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3540 3541 *rdatasetp = rdataset; 3542 return (ISC_R_SUCCESS); 3543 3544 cleanup: 3545 if (rdata != NULL) 3546 dns_message_puttemprdata(message, &rdata); 3547 if (rdataset != NULL) 3548 dns_message_puttemprdataset(message, &rdataset); 3549 if (rdatalist != NULL) 3550 dns_message_puttemprdatalist(message, &rdatalist); 3551 return (result); 3552} 3553