message.c revision 223812
1/* 2 * Copyright (C) 2004-2011 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: message.c,v 1.245.50.7.6.3 2011-06-21 20:13:22 each Exp $ */ 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 m->mctx = mctx; 736 737 ISC_LIST_INIT(m->scratchpad); 738 ISC_LIST_INIT(m->cleanup); 739 m->namepool = NULL; 740 m->rdspool = NULL; 741 ISC_LIST_INIT(m->rdatas); 742 ISC_LIST_INIT(m->rdatalists); 743 ISC_LIST_INIT(m->offsets); 744 ISC_LIST_INIT(m->freerdata); 745 ISC_LIST_INIT(m->freerdatalist); 746 747 /* 748 * Ok, it is safe to allocate (and then "goto cleanup" if failure) 749 */ 750 751 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool); 752 if (result != ISC_R_SUCCESS) 753 goto cleanup; 754 isc_mempool_setfreemax(m->namepool, NAME_COUNT); 755 isc_mempool_setname(m->namepool, "msg:names"); 756 757 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), 758 &m->rdspool); 759 if (result != ISC_R_SUCCESS) 760 goto cleanup; 761 isc_mempool_setfreemax(m->rdspool, NAME_COUNT); 762 isc_mempool_setname(m->rdspool, "msg:rdataset"); 763 764 dynbuf = NULL; 765 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE); 766 if (result != ISC_R_SUCCESS) 767 goto cleanup; 768 ISC_LIST_APPEND(m->scratchpad, dynbuf, link); 769 770 m->cctx = NULL; 771 772 *msgp = m; 773 return (ISC_R_SUCCESS); 774 775 /* 776 * Cleanup for error returns. 777 */ 778 cleanup: 779 dynbuf = ISC_LIST_HEAD(m->scratchpad); 780 if (dynbuf != NULL) { 781 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); 782 isc_buffer_free(&dynbuf); 783 } 784 if (m->namepool != NULL) 785 isc_mempool_destroy(&m->namepool); 786 if (m->rdspool != NULL) 787 isc_mempool_destroy(&m->rdspool); 788 m->magic = 0; 789 isc_mem_put(mctx, m, sizeof(dns_message_t)); 790 791 return (ISC_R_NOMEMORY); 792} 793 794void 795dns_message_reset(dns_message_t *msg, unsigned int intent) { 796 REQUIRE(DNS_MESSAGE_VALID(msg)); 797 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 798 || intent == DNS_MESSAGE_INTENTRENDER); 799 800 msgreset(msg, ISC_FALSE); 801 msg->from_to_wire = intent; 802} 803 804void 805dns_message_destroy(dns_message_t **msgp) { 806 dns_message_t *msg; 807 808 REQUIRE(msgp != NULL); 809 REQUIRE(DNS_MESSAGE_VALID(*msgp)); 810 811 msg = *msgp; 812 *msgp = NULL; 813 814 msgreset(msg, ISC_TRUE); 815 isc_mempool_destroy(&msg->namepool); 816 isc_mempool_destroy(&msg->rdspool); 817 msg->magic = 0; 818 isc_mem_put(msg->mctx, msg, sizeof(dns_message_t)); 819} 820 821static isc_result_t 822findname(dns_name_t **foundname, dns_name_t *target, 823 dns_namelist_t *section) 824{ 825 dns_name_t *curr; 826 827 for (curr = ISC_LIST_TAIL(*section); 828 curr != NULL; 829 curr = ISC_LIST_PREV(curr, link)) { 830 if (dns_name_equal(curr, target)) { 831 if (foundname != NULL) 832 *foundname = curr; 833 return (ISC_R_SUCCESS); 834 } 835 } 836 837 return (ISC_R_NOTFOUND); 838} 839 840isc_result_t 841dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, 842 dns_rdatatype_t type, dns_rdatatype_t covers, 843 dns_rdataset_t **rdataset) 844{ 845 dns_rdataset_t *curr; 846 847 if (rdataset != NULL) { 848 REQUIRE(*rdataset == NULL); 849 } 850 851 for (curr = ISC_LIST_TAIL(name->list); 852 curr != NULL; 853 curr = ISC_LIST_PREV(curr, link)) { 854 if (curr->rdclass == rdclass && 855 curr->type == type && curr->covers == covers) { 856 if (rdataset != NULL) 857 *rdataset = curr; 858 return (ISC_R_SUCCESS); 859 } 860 } 861 862 return (ISC_R_NOTFOUND); 863} 864 865isc_result_t 866dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, 867 dns_rdatatype_t covers, dns_rdataset_t **rdataset) 868{ 869 dns_rdataset_t *curr; 870 871 REQUIRE(name != NULL); 872 if (rdataset != NULL) { 873 REQUIRE(*rdataset == NULL); 874 } 875 876 for (curr = ISC_LIST_TAIL(name->list); 877 curr != NULL; 878 curr = ISC_LIST_PREV(curr, link)) { 879 if (curr->type == type && curr->covers == covers) { 880 if (rdataset != NULL) 881 *rdataset = curr; 882 return (ISC_R_SUCCESS); 883 } 884 } 885 886 return (ISC_R_NOTFOUND); 887} 888 889/* 890 * Read a name from buffer "source". 891 */ 892static isc_result_t 893getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, 894 dns_decompress_t *dctx) 895{ 896 isc_buffer_t *scratch; 897 isc_result_t result; 898 unsigned int tries; 899 900 scratch = currentbuffer(msg); 901 902 /* 903 * First try: use current buffer. 904 * Second try: allocate a new buffer and use that. 905 */ 906 tries = 0; 907 while (tries < 2) { 908 result = dns_name_fromwire(name, source, dctx, ISC_FALSE, 909 scratch); 910 911 if (result == ISC_R_NOSPACE) { 912 tries++; 913 914 result = newbuffer(msg, SCRATCHPAD_SIZE); 915 if (result != ISC_R_SUCCESS) 916 return (result); 917 918 scratch = currentbuffer(msg); 919 dns_name_reset(name); 920 } else { 921 return (result); 922 } 923 } 924 925 INSIST(0); /* Cannot get here... */ 926 return (ISC_R_UNEXPECTED); 927} 928 929static isc_result_t 930getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 931 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, 932 unsigned int rdatalen, dns_rdata_t *rdata) 933{ 934 isc_buffer_t *scratch; 935 isc_result_t result; 936 unsigned int tries; 937 unsigned int trysize; 938 939 scratch = currentbuffer(msg); 940 941 isc_buffer_setactive(source, rdatalen); 942 943 /* 944 * First try: use current buffer. 945 * Second try: allocate a new buffer of size 946 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) 947 * (the data will fit if it was not more than 50% compressed) 948 * Subsequent tries: double buffer size on each try. 949 */ 950 tries = 0; 951 trysize = 0; 952 /* XXX possibly change this to a while (tries < 2) loop */ 953 for (;;) { 954 result = dns_rdata_fromwire(rdata, rdclass, rdtype, 955 source, dctx, 0, 956 scratch); 957 958 if (result == ISC_R_NOSPACE) { 959 if (tries == 0) { 960 trysize = 2 * rdatalen; 961 if (trysize < SCRATCHPAD_SIZE) 962 trysize = SCRATCHPAD_SIZE; 963 } else { 964 INSIST(trysize != 0); 965 if (trysize >= 65535) 966 return (ISC_R_NOSPACE); 967 /* XXX DNS_R_RRTOOLONG? */ 968 trysize *= 2; 969 } 970 tries++; 971 result = newbuffer(msg, trysize); 972 if (result != ISC_R_SUCCESS) 973 return (result); 974 975 scratch = currentbuffer(msg); 976 } else { 977 return (result); 978 } 979 } 980} 981 982#define DO_FORMERR \ 983 do { \ 984 if (best_effort) \ 985 seen_problem = ISC_TRUE; \ 986 else { \ 987 result = DNS_R_FORMERR; \ 988 goto cleanup; \ 989 } \ 990 } while (0) 991 992static isc_result_t 993getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 994 unsigned int options) 995{ 996 isc_region_t r; 997 unsigned int count; 998 dns_name_t *name; 999 dns_name_t *name2; 1000 dns_offsets_t *offsets; 1001 dns_rdataset_t *rdataset; 1002 dns_rdatalist_t *rdatalist; 1003 isc_result_t result; 1004 dns_rdatatype_t rdtype; 1005 dns_rdataclass_t rdclass; 1006 dns_namelist_t *section; 1007 isc_boolean_t free_name; 1008 isc_boolean_t best_effort; 1009 isc_boolean_t seen_problem; 1010 1011 section = &msg->sections[DNS_SECTION_QUESTION]; 1012 1013 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1014 seen_problem = ISC_FALSE; 1015 1016 name = NULL; 1017 rdataset = NULL; 1018 rdatalist = NULL; 1019 1020 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { 1021 name = isc_mempool_get(msg->namepool); 1022 if (name == NULL) 1023 return (ISC_R_NOMEMORY); 1024 free_name = ISC_TRUE; 1025 1026 offsets = newoffsets(msg); 1027 if (offsets == NULL) { 1028 result = ISC_R_NOMEMORY; 1029 goto cleanup; 1030 } 1031 dns_name_init(name, *offsets); 1032 1033 /* 1034 * Parse the name out of this packet. 1035 */ 1036 isc_buffer_remainingregion(source, &r); 1037 isc_buffer_setactive(source, r.length); 1038 result = getname(name, source, msg, dctx); 1039 if (result != ISC_R_SUCCESS) 1040 goto cleanup; 1041 1042 /* 1043 * Run through the section, looking to see if this name 1044 * is already there. If it is found, put back the allocated 1045 * name since we no longer need it, and set our name pointer 1046 * to point to the name we found. 1047 */ 1048 result = findname(&name2, name, section); 1049 1050 /* 1051 * If it is the first name in the section, accept it. 1052 * 1053 * If it is not, but is not the same as the name already 1054 * in the question section, append to the section. Note that 1055 * here in the question section this is illegal, so return 1056 * FORMERR. In the future, check the opcode to see if 1057 * this should be legal or not. In either case we no longer 1058 * need this name pointer. 1059 */ 1060 if (result != ISC_R_SUCCESS) { 1061 if (!ISC_LIST_EMPTY(*section)) 1062 DO_FORMERR; 1063 ISC_LIST_APPEND(*section, name, link); 1064 free_name = ISC_FALSE; 1065 } else { 1066 isc_mempool_put(msg->namepool, name); 1067 name = name2; 1068 name2 = NULL; 1069 free_name = ISC_FALSE; 1070 } 1071 1072 /* 1073 * Get type and class. 1074 */ 1075 isc_buffer_remainingregion(source, &r); 1076 if (r.length < 4) { 1077 result = ISC_R_UNEXPECTEDEND; 1078 goto cleanup; 1079 } 1080 rdtype = isc_buffer_getuint16(source); 1081 rdclass = isc_buffer_getuint16(source); 1082 1083 /* 1084 * If this class is different than the one we already read, 1085 * this is an error. 1086 */ 1087 if (msg->state == DNS_SECTION_ANY) { 1088 msg->state = DNS_SECTION_QUESTION; 1089 msg->rdclass = rdclass; 1090 } else if (msg->rdclass != rdclass) 1091 DO_FORMERR; 1092 1093 /* 1094 * Can't ask the same question twice. 1095 */ 1096 result = dns_message_find(name, rdclass, rdtype, 0, NULL); 1097 if (result == ISC_R_SUCCESS) 1098 DO_FORMERR; 1099 1100 /* 1101 * Allocate a new rdatalist. 1102 */ 1103 rdatalist = newrdatalist(msg); 1104 if (rdatalist == NULL) { 1105 result = ISC_R_NOMEMORY; 1106 goto cleanup; 1107 } 1108 rdataset = isc_mempool_get(msg->rdspool); 1109 if (rdataset == NULL) { 1110 result = ISC_R_NOMEMORY; 1111 goto cleanup; 1112 } 1113 1114 /* 1115 * Convert rdatalist to rdataset, and attach the latter to 1116 * the name. 1117 */ 1118 rdatalist->type = rdtype; 1119 rdatalist->covers = 0; 1120 rdatalist->rdclass = rdclass; 1121 rdatalist->ttl = 0; 1122 ISC_LIST_INIT(rdatalist->rdata); 1123 1124 dns_rdataset_init(rdataset); 1125 result = dns_rdatalist_tordataset(rdatalist, rdataset); 1126 if (result != ISC_R_SUCCESS) 1127 goto cleanup; 1128 1129 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 1130 1131 ISC_LIST_APPEND(name->list, rdataset, link); 1132 rdataset = NULL; 1133 } 1134 1135 if (seen_problem) 1136 return (DNS_R_RECOVERABLE); 1137 return (ISC_R_SUCCESS); 1138 1139 cleanup: 1140 if (rdataset != NULL) { 1141 INSIST(!dns_rdataset_isassociated(rdataset)); 1142 isc_mempool_put(msg->rdspool, rdataset); 1143 } 1144#if 0 1145 if (rdatalist != NULL) 1146 isc_mempool_put(msg->rdlpool, rdatalist); 1147#endif 1148 if (free_name) 1149 isc_mempool_put(msg->namepool, name); 1150 1151 return (result); 1152} 1153 1154static isc_boolean_t 1155update(dns_section_t section, dns_rdataclass_t rdclass) { 1156 if (section == DNS_SECTION_PREREQUISITE) 1157 return (ISC_TF(rdclass == dns_rdataclass_any || 1158 rdclass == dns_rdataclass_none)); 1159 if (section == DNS_SECTION_UPDATE) 1160 return (ISC_TF(rdclass == dns_rdataclass_any)); 1161 return (ISC_FALSE); 1162} 1163 1164static isc_result_t 1165getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 1166 dns_section_t sectionid, unsigned int options) 1167{ 1168 isc_region_t r; 1169 unsigned int count, rdatalen; 1170 dns_name_t *name; 1171 dns_name_t *name2; 1172 dns_offsets_t *offsets; 1173 dns_rdataset_t *rdataset; 1174 dns_rdatalist_t *rdatalist; 1175 isc_result_t result; 1176 dns_rdatatype_t rdtype, covers; 1177 dns_rdataclass_t rdclass; 1178 dns_rdata_t *rdata; 1179 dns_ttl_t ttl; 1180 dns_namelist_t *section; 1181 isc_boolean_t free_name, free_rdataset; 1182 isc_boolean_t preserve_order, best_effort, seen_problem; 1183 isc_boolean_t issigzero; 1184 1185 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER); 1186 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1187 seen_problem = ISC_FALSE; 1188 1189 for (count = 0; count < msg->counts[sectionid]; count++) { 1190 int recstart = source->current; 1191 isc_boolean_t skip_name_search, skip_type_search; 1192 1193 section = &msg->sections[sectionid]; 1194 1195 skip_name_search = ISC_FALSE; 1196 skip_type_search = ISC_FALSE; 1197 free_name = ISC_FALSE; 1198 free_rdataset = ISC_FALSE; 1199 1200 name = isc_mempool_get(msg->namepool); 1201 if (name == NULL) 1202 return (ISC_R_NOMEMORY); 1203 free_name = ISC_TRUE; 1204 1205 offsets = newoffsets(msg); 1206 if (offsets == NULL) { 1207 result = ISC_R_NOMEMORY; 1208 goto cleanup; 1209 } 1210 dns_name_init(name, *offsets); 1211 1212 /* 1213 * Parse the name out of this packet. 1214 */ 1215 isc_buffer_remainingregion(source, &r); 1216 isc_buffer_setactive(source, r.length); 1217 result = getname(name, source, msg, dctx); 1218 if (result != ISC_R_SUCCESS) 1219 goto cleanup; 1220 1221 /* 1222 * Get type, class, ttl, and rdatalen. Verify that at least 1223 * rdatalen bytes remain. (Some of this is deferred to 1224 * later.) 1225 */ 1226 isc_buffer_remainingregion(source, &r); 1227 if (r.length < 2 + 2 + 4 + 2) { 1228 result = ISC_R_UNEXPECTEDEND; 1229 goto cleanup; 1230 } 1231 rdtype = isc_buffer_getuint16(source); 1232 rdclass = isc_buffer_getuint16(source); 1233 1234 /* 1235 * If there was no question section, we may not yet have 1236 * established a class. Do so now. 1237 */ 1238 if (msg->state == DNS_SECTION_ANY && 1239 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ 1240 rdtype != dns_rdatatype_tsig && /* class is ANY */ 1241 rdtype != dns_rdatatype_tkey) { /* class is undefined */ 1242 msg->rdclass = rdclass; 1243 msg->state = DNS_SECTION_QUESTION; 1244 } 1245 1246 /* 1247 * If this class is different than the one in the question 1248 * section, bail. 1249 */ 1250 if (msg->opcode != dns_opcode_update 1251 && rdtype != dns_rdatatype_tsig 1252 && rdtype != dns_rdatatype_opt 1253 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ 1254 && rdtype != dns_rdatatype_sig /* SIG(0) */ 1255 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ 1256 && msg->rdclass != dns_rdataclass_any 1257 && msg->rdclass != rdclass) 1258 DO_FORMERR; 1259 1260 /* 1261 * Special type handling for TSIG, OPT, and TKEY. 1262 */ 1263 if (rdtype == dns_rdatatype_tsig) { 1264 /* 1265 * If it is a tsig, verify that it is in the 1266 * additional data section. 1267 */ 1268 if (sectionid != DNS_SECTION_ADDITIONAL || 1269 rdclass != dns_rdataclass_any || 1270 count != msg->counts[sectionid] - 1) 1271 DO_FORMERR; 1272 msg->sigstart = recstart; 1273 skip_name_search = ISC_TRUE; 1274 skip_type_search = ISC_TRUE; 1275 } else if (rdtype == dns_rdatatype_opt) { 1276 /* 1277 * The name of an OPT record must be ".", it 1278 * must be in the additional data section, and 1279 * it must be the first OPT we've seen. 1280 */ 1281 if (!dns_name_equal(dns_rootname, name) || 1282 msg->opt != NULL) 1283 DO_FORMERR; 1284 skip_name_search = ISC_TRUE; 1285 skip_type_search = ISC_TRUE; 1286 } else if (rdtype == dns_rdatatype_tkey) { 1287 /* 1288 * A TKEY must be in the additional section if this 1289 * is a query, and the answer section if this is a 1290 * response. Unless it's a Win2000 client. 1291 * 1292 * Its class is ignored. 1293 */ 1294 dns_section_t tkeysection; 1295 1296 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) 1297 tkeysection = DNS_SECTION_ADDITIONAL; 1298 else 1299 tkeysection = DNS_SECTION_ANSWER; 1300 if (sectionid != tkeysection && 1301 sectionid != DNS_SECTION_ANSWER) 1302 DO_FORMERR; 1303 } 1304 1305 /* 1306 * ... now get ttl and rdatalen, and check buffer. 1307 */ 1308 ttl = isc_buffer_getuint32(source); 1309 rdatalen = isc_buffer_getuint16(source); 1310 r.length -= (2 + 2 + 4 + 2); 1311 if (r.length < rdatalen) { 1312 result = ISC_R_UNEXPECTEDEND; 1313 goto cleanup; 1314 } 1315 1316 /* 1317 * Read the rdata from the wire format. Interpret the 1318 * rdata according to its actual class, even if it had a 1319 * DynDNS meta-class in the packet (unless this is a TSIG). 1320 * Then put the meta-class back into the finished rdata. 1321 */ 1322 rdata = newrdata(msg); 1323 if (rdata == NULL) { 1324 result = ISC_R_NOMEMORY; 1325 goto cleanup; 1326 } 1327 if (msg->opcode == dns_opcode_update && 1328 update(sectionid, rdclass)) { 1329 if (rdatalen != 0) { 1330 result = DNS_R_FORMERR; 1331 goto cleanup; 1332 } 1333 /* 1334 * When the rdata is empty, the data pointer is 1335 * never dereferenced, but it must still be non-NULL. 1336 * Casting 1 rather than "" avoids warnings about 1337 * discarding the const attribute of a string, 1338 * for compilers that would warn about such things. 1339 */ 1340 rdata->data = (unsigned char *)1; 1341 rdata->length = 0; 1342 rdata->rdclass = rdclass; 1343 rdata->type = rdtype; 1344 rdata->flags = DNS_RDATA_UPDATE; 1345 result = ISC_R_SUCCESS; 1346 } else if (rdclass == dns_rdataclass_none && 1347 msg->opcode == dns_opcode_update && 1348 sectionid == DNS_SECTION_UPDATE) { 1349 result = getrdata(source, msg, dctx, msg->rdclass, 1350 rdtype, rdatalen, rdata); 1351 } else 1352 result = getrdata(source, msg, dctx, rdclass, 1353 rdtype, rdatalen, rdata); 1354 if (result != ISC_R_SUCCESS) 1355 goto cleanup; 1356 rdata->rdclass = rdclass; 1357 issigzero = ISC_FALSE; 1358 if (rdtype == dns_rdatatype_rrsig && 1359 rdata->flags == 0) { 1360 covers = dns_rdata_covers(rdata); 1361 if (covers == 0) 1362 DO_FORMERR; 1363 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1364 rdata->flags == 0) { 1365 covers = dns_rdata_covers(rdata); 1366 if (covers == 0) { 1367 if (sectionid != DNS_SECTION_ADDITIONAL || 1368 count != msg->counts[sectionid] - 1) 1369 DO_FORMERR; 1370 msg->sigstart = recstart; 1371 skip_name_search = ISC_TRUE; 1372 skip_type_search = ISC_TRUE; 1373 issigzero = ISC_TRUE; 1374 } 1375 } else 1376 covers = 0; 1377 1378 /* 1379 * If we are doing a dynamic update or this is a meta-type, 1380 * don't bother searching for a name, just append this one 1381 * to the end of the message. 1382 */ 1383 if (preserve_order || msg->opcode == dns_opcode_update || 1384 skip_name_search) { 1385 if (rdtype != dns_rdatatype_opt && 1386 rdtype != dns_rdatatype_tsig && 1387 !issigzero) 1388 { 1389 ISC_LIST_APPEND(*section, name, link); 1390 free_name = ISC_FALSE; 1391 } 1392 } else { 1393 /* 1394 * Run through the section, looking to see if this name 1395 * is already there. If it is found, put back the 1396 * allocated name since we no longer need it, and set 1397 * our name pointer to point to the name we found. 1398 */ 1399 result = findname(&name2, name, section); 1400 1401 /* 1402 * If it is a new name, append to the section. 1403 */ 1404 if (result == ISC_R_SUCCESS) { 1405 isc_mempool_put(msg->namepool, name); 1406 name = name2; 1407 } else { 1408 ISC_LIST_APPEND(*section, name, link); 1409 } 1410 free_name = ISC_FALSE; 1411 } 1412 1413 /* 1414 * Search name for the particular type and class. 1415 * Skip this stage if in update mode or this is a meta-type. 1416 */ 1417 if (preserve_order || msg->opcode == dns_opcode_update || 1418 skip_type_search) 1419 result = ISC_R_NOTFOUND; 1420 else { 1421 /* 1422 * If this is a type that can only occur in 1423 * the question section, fail. 1424 */ 1425 if (dns_rdatatype_questiononly(rdtype)) 1426 DO_FORMERR; 1427 1428 rdataset = NULL; 1429 result = dns_message_find(name, rdclass, rdtype, 1430 covers, &rdataset); 1431 } 1432 1433 /* 1434 * If we found an rdataset that matches, we need to 1435 * append this rdata to that set. If we did not, we need 1436 * to create a new rdatalist, store the important bits there, 1437 * convert it to an rdataset, and link the latter to the name. 1438 * Yuck. When appending, make certain that the type isn't 1439 * a singleton type, such as SOA or CNAME. 1440 * 1441 * Note that this check will be bypassed when preserving order, 1442 * the opcode is an update, or the type search is skipped. 1443 */ 1444 if (result == ISC_R_SUCCESS) { 1445 if (dns_rdatatype_issingleton(rdtype)) 1446 DO_FORMERR; 1447 } 1448 1449 if (result == ISC_R_NOTFOUND) { 1450 rdataset = isc_mempool_get(msg->rdspool); 1451 if (rdataset == NULL) { 1452 result = ISC_R_NOMEMORY; 1453 goto cleanup; 1454 } 1455 free_rdataset = ISC_TRUE; 1456 1457 rdatalist = newrdatalist(msg); 1458 if (rdatalist == NULL) { 1459 result = ISC_R_NOMEMORY; 1460 goto cleanup; 1461 } 1462 1463 rdatalist->type = rdtype; 1464 rdatalist->covers = covers; 1465 rdatalist->rdclass = rdclass; 1466 rdatalist->ttl = ttl; 1467 ISC_LIST_INIT(rdatalist->rdata); 1468 1469 dns_rdataset_init(rdataset); 1470 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, 1471 rdataset) 1472 == ISC_R_SUCCESS); 1473 1474 if (rdtype != dns_rdatatype_opt && 1475 rdtype != dns_rdatatype_tsig && 1476 !issigzero) 1477 { 1478 ISC_LIST_APPEND(name->list, rdataset, link); 1479 free_rdataset = ISC_FALSE; 1480 } 1481 } 1482 1483 /* 1484 * Minimize TTLs. 1485 * 1486 * Section 5.2 of RFC2181 says we should drop 1487 * nonauthoritative rrsets where the TTLs differ, but we 1488 * currently treat them the as if they were authoritative and 1489 * minimize them. 1490 */ 1491 if (ttl != rdataset->ttl) { 1492 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1493 if (ttl < rdataset->ttl) 1494 rdataset->ttl = ttl; 1495 } 1496 1497 /* Append this rdata to the rdataset. */ 1498 dns_rdatalist_fromrdataset(rdataset, &rdatalist); 1499 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1500 1501 /* 1502 * If this is an OPT record, remember it. Also, set 1503 * the extended rcode. Note that msg->opt will only be set 1504 * if best-effort parsing is enabled. 1505 */ 1506 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { 1507 dns_rcode_t ercode; 1508 1509 msg->opt = rdataset; 1510 rdataset = NULL; 1511 free_rdataset = ISC_FALSE; 1512 ercode = (dns_rcode_t) 1513 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) 1514 >> 20); 1515 msg->rcode |= ercode; 1516 isc_mempool_put(msg->namepool, name); 1517 free_name = ISC_FALSE; 1518 } 1519 1520 /* 1521 * If this is an SIG(0) or TSIG record, remember it. Note 1522 * that msg->sig0 or msg->tsig will only be set if best-effort 1523 * parsing is enabled. 1524 */ 1525 if (issigzero && msg->sig0 == NULL) { 1526 msg->sig0 = rdataset; 1527 msg->sig0name = name; 1528 rdataset = NULL; 1529 free_rdataset = ISC_FALSE; 1530 free_name = ISC_FALSE; 1531 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) { 1532 msg->tsig = rdataset; 1533 msg->tsigname = name; 1534 /* Windows doesn't like TSIG names to be compressed. */ 1535 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1536 rdataset = NULL; 1537 free_rdataset = ISC_FALSE; 1538 free_name = ISC_FALSE; 1539 } 1540 1541 if (seen_problem) { 1542 if (free_name) 1543 isc_mempool_put(msg->namepool, name); 1544 if (free_rdataset) 1545 isc_mempool_put(msg->rdspool, rdataset); 1546 free_name = free_rdataset = ISC_FALSE; 1547 } 1548 INSIST(free_name == ISC_FALSE); 1549 INSIST(free_rdataset == ISC_FALSE); 1550 } 1551 1552 if (seen_problem) 1553 return (DNS_R_RECOVERABLE); 1554 return (ISC_R_SUCCESS); 1555 1556 cleanup: 1557 if (free_name) 1558 isc_mempool_put(msg->namepool, name); 1559 if (free_rdataset) 1560 isc_mempool_put(msg->rdspool, rdataset); 1561 1562 return (result); 1563} 1564 1565isc_result_t 1566dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1567 unsigned int options) 1568{ 1569 isc_region_t r; 1570 dns_decompress_t dctx; 1571 isc_result_t ret; 1572 isc_uint16_t tmpflags; 1573 isc_buffer_t origsource; 1574 isc_boolean_t seen_problem; 1575 isc_boolean_t ignore_tc; 1576 1577 REQUIRE(DNS_MESSAGE_VALID(msg)); 1578 REQUIRE(source != NULL); 1579 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1580 1581 seen_problem = ISC_FALSE; 1582 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); 1583 1584 origsource = *source; 1585 1586 msg->header_ok = 0; 1587 msg->question_ok = 0; 1588 1589 isc_buffer_remainingregion(source, &r); 1590 if (r.length < DNS_MESSAGE_HEADERLEN) 1591 return (ISC_R_UNEXPECTEDEND); 1592 1593 msg->id = isc_buffer_getuint16(source); 1594 tmpflags = isc_buffer_getuint16(source); 1595 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1596 >> DNS_MESSAGE_OPCODE_SHIFT); 1597 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1598 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1599 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1600 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1601 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1602 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1603 1604 msg->header_ok = 1; 1605 1606 /* 1607 * -1 means no EDNS. 1608 */ 1609 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1610 1611 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1612 1613 ret = getquestions(source, msg, &dctx, options); 1614 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1615 goto truncated; 1616 if (ret == DNS_R_RECOVERABLE) { 1617 seen_problem = ISC_TRUE; 1618 ret = ISC_R_SUCCESS; 1619 } 1620 if (ret != ISC_R_SUCCESS) 1621 return (ret); 1622 msg->question_ok = 1; 1623 1624 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1625 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1626 goto truncated; 1627 if (ret == DNS_R_RECOVERABLE) { 1628 seen_problem = ISC_TRUE; 1629 ret = ISC_R_SUCCESS; 1630 } 1631 if (ret != ISC_R_SUCCESS) 1632 return (ret); 1633 1634 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1635 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1636 goto truncated; 1637 if (ret == DNS_R_RECOVERABLE) { 1638 seen_problem = ISC_TRUE; 1639 ret = ISC_R_SUCCESS; 1640 } 1641 if (ret != ISC_R_SUCCESS) 1642 return (ret); 1643 1644 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1645 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1646 goto truncated; 1647 if (ret == DNS_R_RECOVERABLE) { 1648 seen_problem = ISC_TRUE; 1649 ret = ISC_R_SUCCESS; 1650 } 1651 if (ret != ISC_R_SUCCESS) 1652 return (ret); 1653 1654 isc_buffer_remainingregion(source, &r); 1655 if (r.length != 0) { 1656 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1657 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1658 "message has %u byte(s) of trailing garbage", 1659 r.length); 1660 } 1661 1662 truncated: 1663 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) 1664 isc_buffer_usedregion(&origsource, &msg->saved); 1665 else { 1666 msg->saved.length = isc_buffer_usedlength(&origsource); 1667 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1668 if (msg->saved.base == NULL) 1669 return (ISC_R_NOMEMORY); 1670 memcpy(msg->saved.base, isc_buffer_base(&origsource), 1671 msg->saved.length); 1672 msg->free_saved = 1; 1673 } 1674 1675 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1676 return (DNS_R_RECOVERABLE); 1677 if (seen_problem == ISC_TRUE) 1678 return (DNS_R_RECOVERABLE); 1679 return (ISC_R_SUCCESS); 1680} 1681 1682isc_result_t 1683dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1684 isc_buffer_t *buffer) 1685{ 1686 isc_region_t r; 1687 1688 REQUIRE(DNS_MESSAGE_VALID(msg)); 1689 REQUIRE(buffer != NULL); 1690 REQUIRE(msg->buffer == NULL); 1691 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1692 1693 msg->cctx = cctx; 1694 1695 /* 1696 * Erase the contents of this buffer. 1697 */ 1698 isc_buffer_clear(buffer); 1699 1700 /* 1701 * Make certain there is enough for at least the header in this 1702 * buffer. 1703 */ 1704 isc_buffer_availableregion(buffer, &r); 1705 if (r.length < DNS_MESSAGE_HEADERLEN) 1706 return (ISC_R_NOSPACE); 1707 1708 if (r.length < msg->reserved) 1709 return (ISC_R_NOSPACE); 1710 1711 /* 1712 * Reserve enough space for the header in this buffer. 1713 */ 1714 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1715 1716 msg->buffer = buffer; 1717 1718 return (ISC_R_SUCCESS); 1719} 1720 1721isc_result_t 1722dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1723 isc_region_t r, rn; 1724 1725 REQUIRE(DNS_MESSAGE_VALID(msg)); 1726 REQUIRE(buffer != NULL); 1727 REQUIRE(msg->buffer != NULL); 1728 1729 /* 1730 * Ensure that the new buffer is empty, and has enough space to 1731 * hold the current contents. 1732 */ 1733 isc_buffer_clear(buffer); 1734 1735 isc_buffer_availableregion(buffer, &rn); 1736 isc_buffer_usedregion(msg->buffer, &r); 1737 REQUIRE(rn.length > r.length); 1738 1739 /* 1740 * Copy the contents from the old to the new buffer. 1741 */ 1742 isc_buffer_add(buffer, r.length); 1743 memcpy(rn.base, r.base, r.length); 1744 1745 msg->buffer = buffer; 1746 1747 return (ISC_R_SUCCESS); 1748} 1749 1750void 1751dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1752 REQUIRE(DNS_MESSAGE_VALID(msg)); 1753 REQUIRE(space <= msg->reserved); 1754 1755 msg->reserved -= space; 1756} 1757 1758isc_result_t 1759dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1760 isc_region_t r; 1761 1762 REQUIRE(DNS_MESSAGE_VALID(msg)); 1763 1764 if (msg->buffer != NULL) { 1765 isc_buffer_availableregion(msg->buffer, &r); 1766 if (r.length < (space + msg->reserved)) 1767 return (ISC_R_NOSPACE); 1768 } 1769 1770 msg->reserved += space; 1771 1772 return (ISC_R_SUCCESS); 1773} 1774 1775static inline isc_boolean_t 1776wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1777 int pass_needed; 1778 1779 /* 1780 * If we are not rendering class IN, this ordering is bogus. 1781 */ 1782 if (rds->rdclass != dns_rdataclass_in) 1783 return (ISC_FALSE); 1784 1785 switch (rds->type) { 1786 case dns_rdatatype_a: 1787 case dns_rdatatype_aaaa: 1788 if (preferred_glue == rds->type) 1789 pass_needed = 4; 1790 else 1791 pass_needed = 3; 1792 break; 1793 case dns_rdatatype_rrsig: 1794 case dns_rdatatype_dnskey: 1795 pass_needed = 2; 1796 break; 1797 default: 1798 pass_needed = 1; 1799 } 1800 1801 if (pass_needed >= pass) 1802 return (ISC_FALSE); 1803 1804 return (ISC_TRUE); 1805} 1806 1807isc_result_t 1808dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1809 unsigned int options) 1810{ 1811 dns_namelist_t *section; 1812 dns_name_t *name, *next_name; 1813 dns_rdataset_t *rdataset, *next_rdataset; 1814 unsigned int count, total; 1815 isc_result_t result; 1816 isc_buffer_t st; /* for rollbacks */ 1817 int pass; 1818 isc_boolean_t partial = ISC_FALSE; 1819 unsigned int rd_options; 1820 dns_rdatatype_t preferred_glue = 0; 1821 1822 REQUIRE(DNS_MESSAGE_VALID(msg)); 1823 REQUIRE(msg->buffer != NULL); 1824 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1825 1826 section = &msg->sections[sectionid]; 1827 1828 if ((sectionid == DNS_SECTION_ADDITIONAL) 1829 && (options & DNS_MESSAGERENDER_ORDERED) == 0) { 1830 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1831 preferred_glue = dns_rdatatype_a; 1832 pass = 4; 1833 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1834 preferred_glue = dns_rdatatype_aaaa; 1835 pass = 4; 1836 } else 1837 pass = 3; 1838 } else 1839 pass = 1; 1840 1841 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) 1842 rd_options = 0; 1843 else 1844 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1845 1846 /* 1847 * Shrink the space in the buffer by the reserved amount. 1848 */ 1849 msg->buffer->length -= msg->reserved; 1850 1851 total = 0; 1852 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) 1853 partial = ISC_TRUE; 1854 1855 /* 1856 * Render required glue first. Set TC if it won't fit. 1857 */ 1858 name = ISC_LIST_HEAD(*section); 1859 if (name != NULL) { 1860 rdataset = ISC_LIST_HEAD(name->list); 1861 if (rdataset != NULL && 1862 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && 1863 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { 1864 const void *order_arg = msg->order_arg; 1865 st = *(msg->buffer); 1866 count = 0; 1867 if (partial) 1868 result = dns_rdataset_towirepartial(rdataset, 1869 name, 1870 msg->cctx, 1871 msg->buffer, 1872 msg->order, 1873 order_arg, 1874 rd_options, 1875 &count, 1876 NULL); 1877 else 1878 result = dns_rdataset_towiresorted(rdataset, 1879 name, 1880 msg->cctx, 1881 msg->buffer, 1882 msg->order, 1883 order_arg, 1884 rd_options, 1885 &count); 1886 total += count; 1887 if (partial && result == ISC_R_NOSPACE) { 1888 msg->flags |= DNS_MESSAGEFLAG_TC; 1889 msg->buffer->length += msg->reserved; 1890 msg->counts[sectionid] += total; 1891 return (result); 1892 } 1893 if (result == ISC_R_NOSPACE) 1894 msg->flags |= DNS_MESSAGEFLAG_TC; 1895 if (result != ISC_R_SUCCESS) { 1896 INSIST(st.used < 65536); 1897 dns_compress_rollback(msg->cctx, 1898 (isc_uint16_t)st.used); 1899 *(msg->buffer) = st; /* rollback */ 1900 msg->buffer->length += msg->reserved; 1901 msg->counts[sectionid] += total; 1902 return (result); 1903 } 1904 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 1905 } 1906 } 1907 1908 do { 1909 name = ISC_LIST_HEAD(*section); 1910 if (name == NULL) { 1911 msg->buffer->length += msg->reserved; 1912 msg->counts[sectionid] += total; 1913 return (ISC_R_SUCCESS); 1914 } 1915 1916 while (name != NULL) { 1917 next_name = ISC_LIST_NEXT(name, link); 1918 1919 rdataset = ISC_LIST_HEAD(name->list); 1920 while (rdataset != NULL) { 1921 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1922 1923 if ((rdataset->attributes & 1924 DNS_RDATASETATTR_RENDERED) != 0) 1925 goto next; 1926 1927 if (((options & DNS_MESSAGERENDER_ORDERED) 1928 == 0) 1929 && (sectionid == DNS_SECTION_ADDITIONAL) 1930 && wrong_priority(rdataset, pass, 1931 preferred_glue)) 1932 goto next; 1933 1934 st = *(msg->buffer); 1935 1936 count = 0; 1937 if (partial) 1938 result = dns_rdataset_towirepartial( 1939 rdataset, 1940 name, 1941 msg->cctx, 1942 msg->buffer, 1943 msg->order, 1944 msg->order_arg, 1945 rd_options, 1946 &count, 1947 NULL); 1948 else 1949 result = dns_rdataset_towiresorted( 1950 rdataset, 1951 name, 1952 msg->cctx, 1953 msg->buffer, 1954 msg->order, 1955 msg->order_arg, 1956 rd_options, 1957 &count); 1958 1959 total += count; 1960 1961 /* 1962 * If out of space, record stats on what we 1963 * rendered so far, and return that status. 1964 * 1965 * XXXMLG Need to change this when 1966 * dns_rdataset_towire() can render partial 1967 * sets starting at some arbitrary point in the 1968 * set. This will include setting a bit in the 1969 * rdataset to indicate that a partial 1970 * rendering was done, and some state saved 1971 * somewhere (probably in the message struct) 1972 * to indicate where to continue from. 1973 */ 1974 if (partial && result == ISC_R_NOSPACE) { 1975 msg->buffer->length += msg->reserved; 1976 msg->counts[sectionid] += total; 1977 return (result); 1978 } 1979 if (result != ISC_R_SUCCESS) { 1980 INSIST(st.used < 65536); 1981 dns_compress_rollback(msg->cctx, 1982 (isc_uint16_t)st.used); 1983 *(msg->buffer) = st; /* rollback */ 1984 msg->buffer->length += msg->reserved; 1985 msg->counts[sectionid] += total; 1986 return (result); 1987 } 1988 1989 /* 1990 * If we have rendered non-validated data, 1991 * ensure that the AD bit is not set. 1992 */ 1993 if (rdataset->trust != dns_trust_secure && 1994 (sectionid == DNS_SECTION_ANSWER || 1995 sectionid == DNS_SECTION_AUTHORITY)) 1996 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1997 if (OPTOUT(rdataset)) 1998 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1999 2000 rdataset->attributes |= 2001 DNS_RDATASETATTR_RENDERED; 2002 2003 next: 2004 rdataset = next_rdataset; 2005 } 2006 2007 name = next_name; 2008 } 2009 } while (--pass != 0); 2010 2011 msg->buffer->length += msg->reserved; 2012 msg->counts[sectionid] += total; 2013 2014 return (ISC_R_SUCCESS); 2015} 2016 2017void 2018dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 2019 isc_uint16_t tmp; 2020 isc_region_t r; 2021 2022 REQUIRE(DNS_MESSAGE_VALID(msg)); 2023 REQUIRE(target != NULL); 2024 2025 isc_buffer_availableregion(target, &r); 2026 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 2027 2028 isc_buffer_putuint16(target, msg->id); 2029 2030 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 2031 & DNS_MESSAGE_OPCODE_MASK); 2032 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 2033 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 2034 2035 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 2036 msg->counts[DNS_SECTION_ANSWER] < 65536 && 2037 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 2038 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 2039 2040 isc_buffer_putuint16(target, tmp); 2041 isc_buffer_putuint16(target, 2042 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2043 isc_buffer_putuint16(target, 2044 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2045 isc_buffer_putuint16(target, 2046 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2047 isc_buffer_putuint16(target, 2048 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2049} 2050 2051isc_result_t 2052dns_message_renderend(dns_message_t *msg) { 2053 isc_buffer_t tmpbuf; 2054 isc_region_t r; 2055 int result; 2056 unsigned int count; 2057 2058 REQUIRE(DNS_MESSAGE_VALID(msg)); 2059 REQUIRE(msg->buffer != NULL); 2060 2061 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2062 /* 2063 * We have an extended rcode but are not using EDNS. 2064 */ 2065 return (DNS_R_FORMERR); 2066 } 2067 2068 /* 2069 * If we've got an OPT record, render it. 2070 */ 2071 if (msg->opt != NULL) { 2072 dns_message_renderrelease(msg, msg->opt_reserved); 2073 msg->opt_reserved = 0; 2074 /* 2075 * Set the extended rcode. 2076 */ 2077 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2078 msg->opt->ttl |= ((msg->rcode << 20) & 2079 DNS_MESSAGE_EDNSRCODE_MASK); 2080 /* 2081 * Render. 2082 */ 2083 count = 0; 2084 result = dns_rdataset_towire(msg->opt, dns_rootname, 2085 msg->cctx, msg->buffer, 0, 2086 &count); 2087 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2088 if (result != ISC_R_SUCCESS) 2089 return (result); 2090 } 2091 2092 /* 2093 * If we're adding a TSIG or SIG(0) to a truncated message, 2094 * clear all rdatasets from the message except for the question 2095 * before adding the TSIG or SIG(0). If the question doesn't fit, 2096 * don't include it. 2097 */ 2098 if ((msg->tsigkey != NULL || msg->sig0key != NULL) && 2099 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2100 { 2101 isc_buffer_t *buf; 2102 2103 msgresetnames(msg, DNS_SECTION_ANSWER); 2104 buf = msg->buffer; 2105 dns_message_renderreset(msg); 2106 msg->buffer = buf; 2107 isc_buffer_clear(msg->buffer); 2108 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2109 dns_compress_rollback(msg->cctx, 0); 2110 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2111 0); 2112 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 2113 return (result); 2114 } 2115 2116 /* 2117 * If we're adding a TSIG record, generate and render it. 2118 */ 2119 if (msg->tsigkey != NULL) { 2120 dns_message_renderrelease(msg, msg->sig_reserved); 2121 msg->sig_reserved = 0; 2122 result = dns_tsig_sign(msg); 2123 if (result != ISC_R_SUCCESS) 2124 return (result); 2125 count = 0; 2126 result = dns_rdataset_towire(msg->tsig, msg->tsigname, 2127 msg->cctx, msg->buffer, 0, 2128 &count); 2129 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2130 if (result != ISC_R_SUCCESS) 2131 return (result); 2132 } 2133 2134 /* 2135 * If we're adding a SIG(0) record, generate and render it. 2136 */ 2137 if (msg->sig0key != NULL) { 2138 dns_message_renderrelease(msg, msg->sig_reserved); 2139 msg->sig_reserved = 0; 2140 result = dns_dnssec_signmessage(msg, msg->sig0key); 2141 if (result != ISC_R_SUCCESS) 2142 return (result); 2143 count = 0; 2144 /* 2145 * Note: dns_rootname is used here, not msg->sig0name, since 2146 * the owner name of a SIG(0) is irrelevant, and will not 2147 * be set in a message being rendered. 2148 */ 2149 result = dns_rdataset_towire(msg->sig0, dns_rootname, 2150 msg->cctx, msg->buffer, 0, 2151 &count); 2152 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2153 if (result != ISC_R_SUCCESS) 2154 return (result); 2155 } 2156 2157 isc_buffer_usedregion(msg->buffer, &r); 2158 isc_buffer_init(&tmpbuf, r.base, r.length); 2159 2160 dns_message_renderheader(msg, &tmpbuf); 2161 2162 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2163 2164 return (ISC_R_SUCCESS); 2165} 2166 2167void 2168dns_message_renderreset(dns_message_t *msg) { 2169 unsigned int i; 2170 dns_name_t *name; 2171 dns_rdataset_t *rds; 2172 2173 /* 2174 * Reset the message so that it may be rendered again. 2175 */ 2176 2177 REQUIRE(DNS_MESSAGE_VALID(msg)); 2178 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2179 2180 msg->buffer = NULL; 2181 2182 for (i = 0; i < DNS_SECTION_MAX; i++) { 2183 msg->cursors[i] = NULL; 2184 msg->counts[i] = 0; 2185 for (name = ISC_LIST_HEAD(msg->sections[i]); 2186 name != NULL; 2187 name = ISC_LIST_NEXT(name, link)) { 2188 for (rds = ISC_LIST_HEAD(name->list); 2189 rds != NULL; 2190 rds = ISC_LIST_NEXT(rds, link)) { 2191 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2192 } 2193 } 2194 } 2195 if (msg->tsigname != NULL) 2196 dns_message_puttempname(msg, &msg->tsigname); 2197 if (msg->tsig != NULL) { 2198 dns_rdataset_disassociate(msg->tsig); 2199 dns_message_puttemprdataset(msg, &msg->tsig); 2200 } 2201 if (msg->sig0 != NULL) { 2202 dns_rdataset_disassociate(msg->sig0); 2203 dns_message_puttemprdataset(msg, &msg->sig0); 2204 } 2205} 2206 2207isc_result_t 2208dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2209 REQUIRE(DNS_MESSAGE_VALID(msg)); 2210 REQUIRE(VALID_NAMED_SECTION(section)); 2211 2212 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2213 2214 if (msg->cursors[section] == NULL) 2215 return (ISC_R_NOMORE); 2216 2217 return (ISC_R_SUCCESS); 2218} 2219 2220isc_result_t 2221dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2222 REQUIRE(DNS_MESSAGE_VALID(msg)); 2223 REQUIRE(VALID_NAMED_SECTION(section)); 2224 REQUIRE(msg->cursors[section] != NULL); 2225 2226 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2227 2228 if (msg->cursors[section] == NULL) 2229 return (ISC_R_NOMORE); 2230 2231 return (ISC_R_SUCCESS); 2232} 2233 2234void 2235dns_message_currentname(dns_message_t *msg, dns_section_t section, 2236 dns_name_t **name) 2237{ 2238 REQUIRE(DNS_MESSAGE_VALID(msg)); 2239 REQUIRE(VALID_NAMED_SECTION(section)); 2240 REQUIRE(name != NULL && *name == NULL); 2241 REQUIRE(msg->cursors[section] != NULL); 2242 2243 *name = msg->cursors[section]; 2244} 2245 2246isc_result_t 2247dns_message_findname(dns_message_t *msg, dns_section_t section, 2248 dns_name_t *target, dns_rdatatype_t type, 2249 dns_rdatatype_t covers, dns_name_t **name, 2250 dns_rdataset_t **rdataset) 2251{ 2252 dns_name_t *foundname; 2253 isc_result_t result; 2254 2255 /* 2256 * XXX These requirements are probably too intensive, especially 2257 * where things can be NULL, but as they are they ensure that if 2258 * something is NON-NULL, indicating that the caller expects it 2259 * to be filled in, that we can in fact fill it in. 2260 */ 2261 REQUIRE(msg != NULL); 2262 REQUIRE(VALID_SECTION(section)); 2263 REQUIRE(target != NULL); 2264 if (name != NULL) 2265 REQUIRE(*name == NULL); 2266 if (type == dns_rdatatype_any) { 2267 REQUIRE(rdataset == NULL); 2268 } else { 2269 if (rdataset != NULL) 2270 REQUIRE(*rdataset == NULL); 2271 } 2272 2273 result = findname(&foundname, target, 2274 &msg->sections[section]); 2275 2276 if (result == ISC_R_NOTFOUND) 2277 return (DNS_R_NXDOMAIN); 2278 else if (result != ISC_R_SUCCESS) 2279 return (result); 2280 2281 if (name != NULL) 2282 *name = foundname; 2283 2284 /* 2285 * And now look for the type. 2286 */ 2287 if (type == dns_rdatatype_any) 2288 return (ISC_R_SUCCESS); 2289 2290 result = dns_message_findtype(foundname, type, covers, rdataset); 2291 if (result == ISC_R_NOTFOUND) 2292 return (DNS_R_NXRRSET); 2293 2294 return (result); 2295} 2296 2297void 2298dns_message_movename(dns_message_t *msg, dns_name_t *name, 2299 dns_section_t fromsection, 2300 dns_section_t tosection) 2301{ 2302 REQUIRE(msg != NULL); 2303 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2304 REQUIRE(name != NULL); 2305 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2306 REQUIRE(VALID_NAMED_SECTION(tosection)); 2307 2308 /* 2309 * Unlink the name from the old section 2310 */ 2311 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2312 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2313} 2314 2315void 2316dns_message_addname(dns_message_t *msg, dns_name_t *name, 2317 dns_section_t section) 2318{ 2319 REQUIRE(msg != NULL); 2320 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2321 REQUIRE(name != NULL); 2322 REQUIRE(VALID_NAMED_SECTION(section)); 2323 2324 ISC_LIST_APPEND(msg->sections[section], name, link); 2325} 2326 2327void 2328dns_message_removename(dns_message_t *msg, dns_name_t *name, 2329 dns_section_t section) 2330{ 2331 REQUIRE(msg != NULL); 2332 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2333 REQUIRE(name != NULL); 2334 REQUIRE(VALID_NAMED_SECTION(section)); 2335 2336 ISC_LIST_UNLINK(msg->sections[section], name, link); 2337} 2338 2339isc_result_t 2340dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2341 REQUIRE(DNS_MESSAGE_VALID(msg)); 2342 REQUIRE(item != NULL && *item == NULL); 2343 2344 *item = isc_mempool_get(msg->namepool); 2345 if (*item == NULL) 2346 return (ISC_R_NOMEMORY); 2347 dns_name_init(*item, NULL); 2348 2349 return (ISC_R_SUCCESS); 2350} 2351 2352isc_result_t 2353dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { 2354 REQUIRE(DNS_MESSAGE_VALID(msg)); 2355 REQUIRE(item != NULL && *item == NULL); 2356 2357 *item = newoffsets(msg); 2358 if (*item == NULL) 2359 return (ISC_R_NOMEMORY); 2360 2361 return (ISC_R_SUCCESS); 2362} 2363 2364isc_result_t 2365dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2366 REQUIRE(DNS_MESSAGE_VALID(msg)); 2367 REQUIRE(item != NULL && *item == NULL); 2368 2369 *item = newrdata(msg); 2370 if (*item == NULL) 2371 return (ISC_R_NOMEMORY); 2372 2373 return (ISC_R_SUCCESS); 2374} 2375 2376isc_result_t 2377dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2378 REQUIRE(DNS_MESSAGE_VALID(msg)); 2379 REQUIRE(item != NULL && *item == NULL); 2380 2381 *item = isc_mempool_get(msg->rdspool); 2382 if (*item == NULL) 2383 return (ISC_R_NOMEMORY); 2384 2385 dns_rdataset_init(*item); 2386 2387 return (ISC_R_SUCCESS); 2388} 2389 2390isc_result_t 2391dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2392 REQUIRE(DNS_MESSAGE_VALID(msg)); 2393 REQUIRE(item != NULL && *item == NULL); 2394 2395 *item = newrdatalist(msg); 2396 if (*item == NULL) 2397 return (ISC_R_NOMEMORY); 2398 2399 return (ISC_R_SUCCESS); 2400} 2401 2402void 2403dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2404 REQUIRE(DNS_MESSAGE_VALID(msg)); 2405 REQUIRE(item != NULL && *item != NULL); 2406 2407 if (dns_name_dynamic(*item)) 2408 dns_name_free(*item, msg->mctx); 2409 isc_mempool_put(msg->namepool, *item); 2410 *item = NULL; 2411} 2412 2413void 2414dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2415 REQUIRE(DNS_MESSAGE_VALID(msg)); 2416 REQUIRE(item != NULL && *item != NULL); 2417 2418 releaserdata(msg, *item); 2419 *item = NULL; 2420} 2421 2422void 2423dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2424 REQUIRE(DNS_MESSAGE_VALID(msg)); 2425 REQUIRE(item != NULL && *item != NULL); 2426 2427 REQUIRE(!dns_rdataset_isassociated(*item)); 2428 isc_mempool_put(msg->rdspool, *item); 2429 *item = NULL; 2430} 2431 2432void 2433dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2434 REQUIRE(DNS_MESSAGE_VALID(msg)); 2435 REQUIRE(item != NULL && *item != NULL); 2436 2437 releaserdatalist(msg, *item); 2438 *item = NULL; 2439} 2440 2441isc_result_t 2442dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2443 unsigned int *flagsp) 2444{ 2445 isc_region_t r; 2446 isc_buffer_t buffer; 2447 dns_messageid_t id; 2448 unsigned int flags; 2449 2450 REQUIRE(source != NULL); 2451 2452 buffer = *source; 2453 2454 isc_buffer_remainingregion(&buffer, &r); 2455 if (r.length < DNS_MESSAGE_HEADERLEN) 2456 return (ISC_R_UNEXPECTEDEND); 2457 2458 id = isc_buffer_getuint16(&buffer); 2459 flags = isc_buffer_getuint16(&buffer); 2460 flags &= DNS_MESSAGE_FLAG_MASK; 2461 2462 if (flagsp != NULL) 2463 *flagsp = flags; 2464 if (idp != NULL) 2465 *idp = id; 2466 2467 return (ISC_R_SUCCESS); 2468} 2469 2470isc_result_t 2471dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { 2472 unsigned int clear_after; 2473 isc_result_t result; 2474 2475 REQUIRE(DNS_MESSAGE_VALID(msg)); 2476 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2477 2478 if (!msg->header_ok) 2479 return (DNS_R_FORMERR); 2480 if (msg->opcode != dns_opcode_query && 2481 msg->opcode != dns_opcode_notify) 2482 want_question_section = ISC_FALSE; 2483 if (msg->opcode == dns_opcode_update) 2484 clear_after = DNS_SECTION_PREREQUISITE; 2485 else if (want_question_section) { 2486 if (!msg->question_ok) 2487 return (DNS_R_FORMERR); 2488 clear_after = DNS_SECTION_ANSWER; 2489 } else 2490 clear_after = DNS_SECTION_QUESTION; 2491 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2492 msgresetnames(msg, clear_after); 2493 msgresetopt(msg); 2494 msgresetsigs(msg, ISC_TRUE); 2495 msginitprivate(msg); 2496 /* 2497 * We now clear most flags and then set QR, ensuring that the 2498 * reply's flags will be in a reasonable state. 2499 */ 2500 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2501 msg->flags |= DNS_MESSAGEFLAG_QR; 2502 2503 /* 2504 * This saves the query TSIG status, if the query was signed, and 2505 * reserves space in the reply for the TSIG. 2506 */ 2507 if (msg->tsigkey != NULL) { 2508 unsigned int otherlen = 0; 2509 msg->querytsigstatus = msg->tsigstatus; 2510 msg->tsigstatus = dns_rcode_noerror; 2511 if (msg->querytsigstatus == dns_tsigerror_badtime) 2512 otherlen = 6; 2513 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2514 result = dns_message_renderreserve(msg, msg->sig_reserved); 2515 if (result != ISC_R_SUCCESS) { 2516 msg->sig_reserved = 0; 2517 return (result); 2518 } 2519 } 2520 if (msg->saved.base != NULL) { 2521 msg->query.base = msg->saved.base; 2522 msg->query.length = msg->saved.length; 2523 msg->free_query = msg->free_saved; 2524 msg->saved.base = NULL; 2525 msg->saved.length = 0; 2526 msg->free_saved = 0; 2527 } 2528 2529 return (ISC_R_SUCCESS); 2530} 2531 2532dns_rdataset_t * 2533dns_message_getopt(dns_message_t *msg) { 2534 2535 /* 2536 * Get the OPT record for 'msg'. 2537 */ 2538 2539 REQUIRE(DNS_MESSAGE_VALID(msg)); 2540 2541 return (msg->opt); 2542} 2543 2544isc_result_t 2545dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2546 isc_result_t result; 2547 dns_rdata_t rdata = DNS_RDATA_INIT; 2548 2549 /* 2550 * Set the OPT record for 'msg'. 2551 */ 2552 2553 /* 2554 * The space required for an OPT record is: 2555 * 2556 * 1 byte for the name 2557 * 2 bytes for the type 2558 * 2 bytes for the class 2559 * 4 bytes for the ttl 2560 * 2 bytes for the rdata length 2561 * --------------------------------- 2562 * 11 bytes 2563 * 2564 * plus the length of the rdata. 2565 */ 2566 2567 REQUIRE(DNS_MESSAGE_VALID(msg)); 2568 REQUIRE(opt->type == dns_rdatatype_opt); 2569 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2570 REQUIRE(msg->state == DNS_SECTION_ANY); 2571 2572 msgresetopt(msg); 2573 2574 result = dns_rdataset_first(opt); 2575 if (result != ISC_R_SUCCESS) 2576 goto cleanup; 2577 dns_rdataset_current(opt, &rdata); 2578 msg->opt_reserved = 11 + rdata.length; 2579 result = dns_message_renderreserve(msg, msg->opt_reserved); 2580 if (result != ISC_R_SUCCESS) { 2581 msg->opt_reserved = 0; 2582 goto cleanup; 2583 } 2584 2585 msg->opt = opt; 2586 2587 return (ISC_R_SUCCESS); 2588 2589 cleanup: 2590 dns_message_puttemprdataset(msg, &opt); 2591 return (result); 2592 2593} 2594 2595dns_rdataset_t * 2596dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2597 2598 /* 2599 * Get the TSIG record and owner for 'msg'. 2600 */ 2601 2602 REQUIRE(DNS_MESSAGE_VALID(msg)); 2603 REQUIRE(owner == NULL || *owner == NULL); 2604 2605 if (owner != NULL) 2606 *owner = msg->tsigname; 2607 return (msg->tsig); 2608} 2609 2610isc_result_t 2611dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2612 isc_result_t result; 2613 2614 /* 2615 * Set the TSIG key for 'msg' 2616 */ 2617 2618 REQUIRE(DNS_MESSAGE_VALID(msg)); 2619 REQUIRE(msg->state == DNS_SECTION_ANY); 2620 2621 if (key == NULL && msg->tsigkey != NULL) { 2622 if (msg->sig_reserved != 0) { 2623 dns_message_renderrelease(msg, msg->sig_reserved); 2624 msg->sig_reserved = 0; 2625 } 2626 dns_tsigkey_detach(&msg->tsigkey); 2627 } 2628 if (key != NULL) { 2629 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2630 dns_tsigkey_attach(key, &msg->tsigkey); 2631 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2632 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2633 result = dns_message_renderreserve(msg, 2634 msg->sig_reserved); 2635 if (result != ISC_R_SUCCESS) { 2636 dns_tsigkey_detach(&msg->tsigkey); 2637 msg->sig_reserved = 0; 2638 return (result); 2639 } 2640 } 2641 } 2642 return (ISC_R_SUCCESS); 2643} 2644 2645dns_tsigkey_t * 2646dns_message_gettsigkey(dns_message_t *msg) { 2647 2648 /* 2649 * Get the TSIG key for 'msg' 2650 */ 2651 2652 REQUIRE(DNS_MESSAGE_VALID(msg)); 2653 2654 return (msg->tsigkey); 2655} 2656 2657isc_result_t 2658dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2659 dns_rdata_t *rdata = NULL; 2660 dns_rdatalist_t *list = NULL; 2661 dns_rdataset_t *set = NULL; 2662 isc_buffer_t *buf = NULL; 2663 isc_region_t r; 2664 isc_result_t result; 2665 2666 REQUIRE(DNS_MESSAGE_VALID(msg)); 2667 REQUIRE(msg->querytsig == NULL); 2668 2669 if (querytsig == NULL) 2670 return (ISC_R_SUCCESS); 2671 2672 result = dns_message_gettemprdata(msg, &rdata); 2673 if (result != ISC_R_SUCCESS) 2674 goto cleanup; 2675 2676 result = dns_message_gettemprdatalist(msg, &list); 2677 if (result != ISC_R_SUCCESS) 2678 goto cleanup; 2679 result = dns_message_gettemprdataset(msg, &set); 2680 if (result != ISC_R_SUCCESS) 2681 goto cleanup; 2682 2683 isc_buffer_usedregion(querytsig, &r); 2684 result = isc_buffer_allocate(msg->mctx, &buf, r.length); 2685 if (result != ISC_R_SUCCESS) 2686 goto cleanup; 2687 isc_buffer_putmem(buf, r.base, r.length); 2688 isc_buffer_usedregion(buf, &r); 2689 dns_rdata_init(rdata); 2690 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2691 dns_message_takebuffer(msg, &buf); 2692 ISC_LIST_INIT(list->rdata); 2693 ISC_LIST_APPEND(list->rdata, rdata, link); 2694 result = dns_rdatalist_tordataset(list, set); 2695 if (result != ISC_R_SUCCESS) 2696 goto cleanup; 2697 2698 msg->querytsig = set; 2699 2700 return (result); 2701 2702 cleanup: 2703 if (rdata != NULL) 2704 dns_message_puttemprdata(msg, &rdata); 2705 if (list != NULL) 2706 dns_message_puttemprdatalist(msg, &list); 2707 if (set != NULL) 2708 dns_message_puttemprdataset(msg, &set); 2709 return (ISC_R_NOMEMORY); 2710} 2711 2712isc_result_t 2713dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2714 isc_buffer_t **querytsig) { 2715 isc_result_t result; 2716 dns_rdata_t rdata = DNS_RDATA_INIT; 2717 isc_region_t r; 2718 2719 REQUIRE(DNS_MESSAGE_VALID(msg)); 2720 REQUIRE(mctx != NULL); 2721 REQUIRE(querytsig != NULL && *querytsig == NULL); 2722 2723 if (msg->tsig == NULL) 2724 return (ISC_R_SUCCESS); 2725 2726 result = dns_rdataset_first(msg->tsig); 2727 if (result != ISC_R_SUCCESS) 2728 return (result); 2729 dns_rdataset_current(msg->tsig, &rdata); 2730 dns_rdata_toregion(&rdata, &r); 2731 2732 result = isc_buffer_allocate(mctx, querytsig, r.length); 2733 if (result != ISC_R_SUCCESS) 2734 return (result); 2735 isc_buffer_putmem(*querytsig, r.base, r.length); 2736 return (ISC_R_SUCCESS); 2737} 2738 2739dns_rdataset_t * 2740dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2741 2742 /* 2743 * Get the SIG(0) record for 'msg'. 2744 */ 2745 2746 REQUIRE(DNS_MESSAGE_VALID(msg)); 2747 REQUIRE(owner == NULL || *owner == NULL); 2748 2749 if (msg->sig0 != NULL && owner != NULL) { 2750 /* If dns_message_getsig0 is called on a rendered message 2751 * after the SIG(0) has been applied, we need to return the 2752 * root name, not NULL. 2753 */ 2754 if (msg->sig0name == NULL) 2755 *owner = dns_rootname; 2756 else 2757 *owner = msg->sig0name; 2758 } 2759 return (msg->sig0); 2760} 2761 2762isc_result_t 2763dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2764 isc_region_t r; 2765 unsigned int x; 2766 isc_result_t result; 2767 2768 /* 2769 * Set the SIG(0) key for 'msg' 2770 */ 2771 2772 /* 2773 * The space required for an SIG(0) record is: 2774 * 2775 * 1 byte for the name 2776 * 2 bytes for the type 2777 * 2 bytes for the class 2778 * 4 bytes for the ttl 2779 * 2 bytes for the type covered 2780 * 1 byte for the algorithm 2781 * 1 bytes for the labels 2782 * 4 bytes for the original ttl 2783 * 4 bytes for the signature expiration 2784 * 4 bytes for the signature inception 2785 * 2 bytes for the key tag 2786 * n bytes for the signer's name 2787 * x bytes for the signature 2788 * --------------------------------- 2789 * 27 + n + x bytes 2790 */ 2791 REQUIRE(DNS_MESSAGE_VALID(msg)); 2792 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2793 REQUIRE(msg->state == DNS_SECTION_ANY); 2794 2795 if (key != NULL) { 2796 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 2797 dns_name_toregion(dst_key_name(key), &r); 2798 result = dst_key_sigsize(key, &x); 2799 if (result != ISC_R_SUCCESS) { 2800 msg->sig_reserved = 0; 2801 return (result); 2802 } 2803 msg->sig_reserved = 27 + r.length + x; 2804 result = dns_message_renderreserve(msg, msg->sig_reserved); 2805 if (result != ISC_R_SUCCESS) { 2806 msg->sig_reserved = 0; 2807 return (result); 2808 } 2809 msg->sig0key = key; 2810 } 2811 return (ISC_R_SUCCESS); 2812} 2813 2814dst_key_t * 2815dns_message_getsig0key(dns_message_t *msg) { 2816 2817 /* 2818 * Get the SIG(0) key for 'msg' 2819 */ 2820 2821 REQUIRE(DNS_MESSAGE_VALID(msg)); 2822 2823 return (msg->sig0key); 2824} 2825 2826void 2827dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2828 REQUIRE(DNS_MESSAGE_VALID(msg)); 2829 REQUIRE(buffer != NULL); 2830 REQUIRE(ISC_BUFFER_VALID(*buffer)); 2831 2832 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2833 *buffer = NULL; 2834} 2835 2836isc_result_t 2837dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 2838 isc_result_t result = ISC_R_SUCCESS; 2839 dns_rdata_t rdata = DNS_RDATA_INIT; 2840 2841 REQUIRE(DNS_MESSAGE_VALID(msg)); 2842 REQUIRE(signer != NULL); 2843 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 2844 2845 if (msg->tsig == NULL && msg->sig0 == NULL) 2846 return (ISC_R_NOTFOUND); 2847 2848 if (msg->verify_attempted == 0) 2849 return (DNS_R_NOTVERIFIEDYET); 2850 2851 if (!dns_name_hasbuffer(signer)) { 2852 isc_buffer_t *dynbuf = NULL; 2853 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 2854 if (result != ISC_R_SUCCESS) 2855 return (result); 2856 dns_name_setbuffer(signer, dynbuf); 2857 dns_message_takebuffer(msg, &dynbuf); 2858 } 2859 2860 if (msg->sig0 != NULL) { 2861 dns_rdata_sig_t sig; 2862 2863 result = dns_rdataset_first(msg->sig0); 2864 INSIST(result == ISC_R_SUCCESS); 2865 dns_rdataset_current(msg->sig0, &rdata); 2866 2867 result = dns_rdata_tostruct(&rdata, &sig, NULL); 2868 if (result != ISC_R_SUCCESS) 2869 return (result); 2870 2871 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) 2872 result = ISC_R_SUCCESS; 2873 else 2874 result = DNS_R_SIGINVALID; 2875 dns_name_clone(&sig.signer, signer); 2876 dns_rdata_freestruct(&sig); 2877 } else { 2878 dns_name_t *identity; 2879 dns_rdata_any_tsig_t tsig; 2880 2881 result = dns_rdataset_first(msg->tsig); 2882 INSIST(result == ISC_R_SUCCESS); 2883 dns_rdataset_current(msg->tsig, &rdata); 2884 2885 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2886 if (msg->tsigstatus != dns_rcode_noerror) 2887 result = DNS_R_TSIGVERIFYFAILURE; 2888 else if (tsig.error != dns_rcode_noerror) 2889 result = DNS_R_TSIGERRORSET; 2890 else 2891 result = ISC_R_SUCCESS; 2892 dns_rdata_freestruct(&tsig); 2893 2894 if (msg->tsigkey == NULL) { 2895 /* 2896 * If msg->tsigstatus & tsig.error are both 2897 * dns_rcode_noerror, the message must have been 2898 * verified, which means msg->tsigkey will be 2899 * non-NULL. 2900 */ 2901 INSIST(result != ISC_R_SUCCESS); 2902 } else { 2903 identity = dns_tsigkey_identity(msg->tsigkey); 2904 if (identity == NULL) { 2905 if (result == ISC_R_SUCCESS) 2906 result = DNS_R_NOIDENTITY; 2907 identity = &msg->tsigkey->name; 2908 } 2909 dns_name_clone(identity, signer); 2910 } 2911 } 2912 2913 return (result); 2914} 2915 2916void 2917dns_message_resetsig(dns_message_t *msg) { 2918 REQUIRE(DNS_MESSAGE_VALID(msg)); 2919 msg->verified_sig = 0; 2920 msg->verify_attempted = 0; 2921 msg->tsigstatus = dns_rcode_noerror; 2922 msg->sig0status = dns_rcode_noerror; 2923 msg->timeadjust = 0; 2924 if (msg->tsigkey != NULL) { 2925 dns_tsigkey_detach(&msg->tsigkey); 2926 msg->tsigkey = NULL; 2927 } 2928} 2929 2930isc_result_t 2931dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 2932 dns_message_resetsig(msg); 2933 return (dns_message_checksig(msg, view)); 2934} 2935 2936#ifdef SKAN_MSG_DEBUG 2937void 2938dns_message_dumpsig(dns_message_t *msg, char *txt1) { 2939 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 2940 dns_rdata_any_tsig_t querytsig; 2941 isc_result_t result; 2942 2943 if (msg->tsig != NULL) { 2944 result = dns_rdataset_first(msg->tsig); 2945 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2946 dns_rdataset_current(msg->tsig, &querytsigrdata); 2947 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 2948 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2949 hexdump(txt1, "TSIG", querytsig.signature, 2950 querytsig.siglen); 2951 } 2952 2953 if (msg->querytsig != NULL) { 2954 result = dns_rdataset_first(msg->querytsig); 2955 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2956 dns_rdataset_current(msg->querytsig, &querytsigrdata); 2957 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 2958 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2959 hexdump(txt1, "QUERYTSIG", querytsig.signature, 2960 querytsig.siglen); 2961 } 2962} 2963#endif 2964 2965isc_result_t 2966dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 2967 isc_buffer_t b, msgb; 2968 2969 REQUIRE(DNS_MESSAGE_VALID(msg)); 2970 2971 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) 2972 return (ISC_R_SUCCESS); 2973 2974 INSIST(msg->saved.base != NULL); 2975 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 2976 isc_buffer_add(&msgb, msg->saved.length); 2977 if (msg->tsigkey != NULL || msg->tsig != NULL) { 2978#ifdef SKAN_MSG_DEBUG 2979 dns_message_dumpsig(msg, "dns_message_checksig#1"); 2980#endif 2981 if (view != NULL) 2982 return (dns_view_checksig(view, &msgb, msg)); 2983 else 2984 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 2985 } else { 2986 dns_rdata_t rdata = DNS_RDATA_INIT; 2987 dns_rdata_sig_t sig; 2988 dns_rdataset_t keyset; 2989 isc_result_t result; 2990 2991 result = dns_rdataset_first(msg->sig0); 2992 INSIST(result == ISC_R_SUCCESS); 2993 dns_rdataset_current(msg->sig0, &rdata); 2994 2995 /* 2996 * This can occur when the message is a dynamic update, since 2997 * the rdata length checking is relaxed. This should not 2998 * happen in a well-formed message, since the SIG(0) is only 2999 * looked for in the additional section, and the dynamic update 3000 * meta-records are in the prerequisite and update sections. 3001 */ 3002 if (rdata.length == 0) 3003 return (ISC_R_UNEXPECTEDEND); 3004 3005 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 3006 if (result != ISC_R_SUCCESS) 3007 return (result); 3008 3009 dns_rdataset_init(&keyset); 3010 if (view == NULL) 3011 return (DNS_R_KEYUNAUTHORIZED); 3012 result = dns_view_simplefind(view, &sig.signer, 3013 dns_rdatatype_key /* SIG(0) */, 3014 0, 0, ISC_FALSE, &keyset, NULL); 3015 3016 if (result != ISC_R_SUCCESS) { 3017 /* XXXBEW Should possibly create a fetch here */ 3018 result = DNS_R_KEYUNAUTHORIZED; 3019 goto freesig; 3020 } else if (keyset.trust < dns_trust_secure) { 3021 /* XXXBEW Should call a validator here */ 3022 result = DNS_R_KEYUNAUTHORIZED; 3023 goto freesig; 3024 } 3025 result = dns_rdataset_first(&keyset); 3026 INSIST(result == ISC_R_SUCCESS); 3027 for (; 3028 result == ISC_R_SUCCESS; 3029 result = dns_rdataset_next(&keyset)) 3030 { 3031 dst_key_t *key = NULL; 3032 3033 dns_rdata_reset(&rdata); 3034 dns_rdataset_current(&keyset, &rdata); 3035 isc_buffer_init(&b, rdata.data, rdata.length); 3036 isc_buffer_add(&b, rdata.length); 3037 3038 result = dst_key_fromdns(&sig.signer, rdata.rdclass, 3039 &b, view->mctx, &key); 3040 if (result != ISC_R_SUCCESS) 3041 continue; 3042 if (dst_key_alg(key) != sig.algorithm || 3043 dst_key_id(key) != sig.keyid || 3044 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 3045 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 3046 { 3047 dst_key_free(&key); 3048 continue; 3049 } 3050 result = dns_dnssec_verifymessage(&msgb, msg, key); 3051 dst_key_free(&key); 3052 if (result == ISC_R_SUCCESS) 3053 break; 3054 } 3055 if (result == ISC_R_NOMORE) 3056 result = DNS_R_KEYUNAUTHORIZED; 3057 3058 freesig: 3059 if (dns_rdataset_isassociated(&keyset)) 3060 dns_rdataset_disassociate(&keyset); 3061 dns_rdata_freestruct(&sig); 3062 return (result); 3063 } 3064} 3065 3066isc_result_t 3067dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 3068 const dns_master_style_t *style, 3069 dns_messagetextflag_t flags, 3070 isc_buffer_t *target) { 3071 dns_name_t *name, empty_name; 3072 dns_rdataset_t *rdataset; 3073 isc_result_t result; 3074 3075 REQUIRE(DNS_MESSAGE_VALID(msg)); 3076 REQUIRE(target != NULL); 3077 REQUIRE(VALID_SECTION(section)); 3078 3079 if (ISC_LIST_EMPTY(msg->sections[section])) 3080 return (ISC_R_SUCCESS); 3081 3082 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3083 ADD_STRING(target, ";; "); 3084 if (msg->opcode != dns_opcode_update) { 3085 ADD_STRING(target, sectiontext[section]); 3086 } else { 3087 ADD_STRING(target, updsectiontext[section]); 3088 } 3089 ADD_STRING(target, " SECTION:\n"); 3090 } 3091 3092 dns_name_init(&empty_name, NULL); 3093 result = dns_message_firstname(msg, section); 3094 if (result != ISC_R_SUCCESS) { 3095 return (result); 3096 } 3097 do { 3098 name = NULL; 3099 dns_message_currentname(msg, section, &name); 3100 for (rdataset = ISC_LIST_HEAD(name->list); 3101 rdataset != NULL; 3102 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3103 if (section == DNS_SECTION_QUESTION) { 3104 ADD_STRING(target, ";"); 3105 result = dns_master_questiontotext(name, 3106 rdataset, 3107 style, 3108 target); 3109 } else { 3110 result = dns_master_rdatasettotext(name, 3111 rdataset, 3112 style, 3113 target); 3114 } 3115 if (result != ISC_R_SUCCESS) 3116 return (result); 3117 } 3118 result = dns_message_nextname(msg, section); 3119 } while (result == ISC_R_SUCCESS); 3120 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3121 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3122 ADD_STRING(target, "\n"); 3123 if (result == ISC_R_NOMORE) 3124 result = ISC_R_SUCCESS; 3125 return (result); 3126} 3127 3128isc_result_t 3129dns_message_pseudosectiontotext(dns_message_t *msg, 3130 dns_pseudosection_t section, 3131 const dns_master_style_t *style, 3132 dns_messagetextflag_t flags, 3133 isc_buffer_t *target) { 3134 dns_rdataset_t *ps = NULL; 3135 dns_name_t *name = NULL; 3136 isc_result_t result; 3137 char buf[sizeof("1234567890")]; 3138 isc_uint32_t mbz; 3139 dns_rdata_t rdata; 3140 isc_buffer_t optbuf; 3141 isc_uint16_t optcode, optlen; 3142 unsigned char *optdata; 3143 3144 REQUIRE(DNS_MESSAGE_VALID(msg)); 3145 REQUIRE(target != NULL); 3146 REQUIRE(VALID_PSEUDOSECTION(section)); 3147 3148 switch (section) { 3149 case DNS_PSEUDOSECTION_OPT: 3150 ps = dns_message_getopt(msg); 3151 if (ps == NULL) 3152 return (ISC_R_SUCCESS); 3153 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3154 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3155 ADD_STRING(target, "; EDNS: version: "); 3156 snprintf(buf, sizeof(buf), "%u", 3157 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3158 ADD_STRING(target, buf); 3159 ADD_STRING(target, ", flags:"); 3160 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 3161 ADD_STRING(target, " do"); 3162 mbz = ps->ttl & 0xffff; 3163 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 3164 if (mbz != 0) { 3165 ADD_STRING(target, "; MBZ: "); 3166 snprintf(buf, sizeof(buf), "%.4x ", mbz); 3167 ADD_STRING(target, buf); 3168 ADD_STRING(target, ", udp: "); 3169 } else 3170 ADD_STRING(target, "; udp: "); 3171 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3172 ADD_STRING(target, buf); 3173 3174 result = dns_rdataset_first(ps); 3175 if (result != ISC_R_SUCCESS) 3176 return (ISC_R_SUCCESS); 3177 3178 /* Print EDNS info, if any */ 3179 dns_rdata_init(&rdata); 3180 dns_rdataset_current(ps, &rdata); 3181 3182 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3183 isc_buffer_add(&optbuf, rdata.length); 3184 while (isc_buffer_remaininglength(&optbuf) != 0) { 3185 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 3186 optcode = isc_buffer_getuint16(&optbuf); 3187 optlen = isc_buffer_getuint16(&optbuf); 3188 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 3189 3190 if (optcode == DNS_OPT_NSID) { 3191 ADD_STRING(target, "; NSID"); 3192 } else { 3193 ADD_STRING(target, "; OPT="); 3194 sprintf(buf, "%u", optcode); 3195 ADD_STRING(target, buf); 3196 } 3197 3198 if (optlen != 0) { 3199 int i; 3200 ADD_STRING(target, ": "); 3201 3202 optdata = isc_buffer_current(&optbuf); 3203 for (i = 0; i < optlen; i++) { 3204 sprintf(buf, "%02x ", optdata[i]); 3205 ADD_STRING(target, buf); 3206 } 3207 for (i = 0; i < optlen; i++) { 3208 ADD_STRING(target, " ("); 3209 if (isprint(optdata[i])) 3210 isc_buffer_putmem(target, 3211 &optdata[i], 3212 1); 3213 else 3214 isc_buffer_putstr(target, "."); 3215 ADD_STRING(target, ")"); 3216 } 3217 isc_buffer_forward(&optbuf, optlen); 3218 } 3219 ADD_STRING(target, "\n"); 3220 } 3221 return (ISC_R_SUCCESS); 3222 case DNS_PSEUDOSECTION_TSIG: 3223 ps = dns_message_gettsig(msg, &name); 3224 if (ps == NULL) 3225 return (ISC_R_SUCCESS); 3226 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3227 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 3228 result = dns_master_rdatasettotext(name, ps, style, target); 3229 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3230 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3231 ADD_STRING(target, "\n"); 3232 return (result); 3233 case DNS_PSEUDOSECTION_SIG0: 3234 ps = dns_message_getsig0(msg, &name); 3235 if (ps == NULL) 3236 return (ISC_R_SUCCESS); 3237 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3238 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 3239 result = dns_master_rdatasettotext(name, ps, style, target); 3240 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3241 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3242 ADD_STRING(target, "\n"); 3243 return (result); 3244 } 3245 return (ISC_R_UNEXPECTED); 3246} 3247 3248isc_result_t 3249dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 3250 dns_messagetextflag_t flags, isc_buffer_t *target) { 3251 char buf[sizeof("1234567890")]; 3252 isc_result_t result; 3253 3254 REQUIRE(DNS_MESSAGE_VALID(msg)); 3255 REQUIRE(target != NULL); 3256 3257 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { 3258 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 3259 ADD_STRING(target, opcodetext[msg->opcode]); 3260 ADD_STRING(target, ", status: "); 3261 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 3262 ADD_STRING(target, rcodetext[msg->rcode]); 3263 } else { 3264 snprintf(buf, sizeof(buf), "%4u", msg->rcode); 3265 ADD_STRING(target, buf); 3266 } 3267 ADD_STRING(target, ", id: "); 3268 snprintf(buf, sizeof(buf), "%6u", msg->id); 3269 ADD_STRING(target, buf); 3270 ADD_STRING(target, "\n;; flags:"); 3271 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 3272 ADD_STRING(target, " qr"); 3273 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 3274 ADD_STRING(target, " aa"); 3275 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 3276 ADD_STRING(target, " tc"); 3277 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 3278 ADD_STRING(target, " rd"); 3279 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 3280 ADD_STRING(target, " ra"); 3281 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 3282 ADD_STRING(target, " ad"); 3283 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 3284 ADD_STRING(target, " cd"); 3285 /* 3286 * The final unnamed flag must be zero. 3287 */ 3288 if ((msg->flags & 0x0040U) != 0) 3289 ADD_STRING(target, "; MBZ: 0x4"); 3290 if (msg->opcode != dns_opcode_update) { 3291 ADD_STRING(target, "; QUESTION: "); 3292 } else { 3293 ADD_STRING(target, "; ZONE: "); 3294 } 3295 snprintf(buf, sizeof(buf), "%1u", 3296 msg->counts[DNS_SECTION_QUESTION]); 3297 ADD_STRING(target, buf); 3298 if (msg->opcode != dns_opcode_update) { 3299 ADD_STRING(target, ", ANSWER: "); 3300 } else { 3301 ADD_STRING(target, ", PREREQ: "); 3302 } 3303 snprintf(buf, sizeof(buf), "%1u", 3304 msg->counts[DNS_SECTION_ANSWER]); 3305 ADD_STRING(target, buf); 3306 if (msg->opcode != dns_opcode_update) { 3307 ADD_STRING(target, ", AUTHORITY: "); 3308 } else { 3309 ADD_STRING(target, ", UPDATE: "); 3310 } 3311 snprintf(buf, sizeof(buf), "%1u", 3312 msg->counts[DNS_SECTION_AUTHORITY]); 3313 ADD_STRING(target, buf); 3314 ADD_STRING(target, ", ADDITIONAL: "); 3315 snprintf(buf, sizeof(buf), "%1u", 3316 msg->counts[DNS_SECTION_ADDITIONAL]); 3317 ADD_STRING(target, buf); 3318 ADD_STRING(target, "\n"); 3319 } 3320 result = dns_message_pseudosectiontotext(msg, 3321 DNS_PSEUDOSECTION_OPT, 3322 style, flags, target); 3323 if (result != ISC_R_SUCCESS) 3324 return (result); 3325 3326 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, 3327 style, flags, target); 3328 if (result != ISC_R_SUCCESS) 3329 return (result); 3330 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, 3331 style, flags, target); 3332 if (result != ISC_R_SUCCESS) 3333 return (result); 3334 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, 3335 style, flags, target); 3336 if (result != ISC_R_SUCCESS) 3337 return (result); 3338 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, 3339 style, flags, target); 3340 if (result != ISC_R_SUCCESS) 3341 return (result); 3342 3343 result = dns_message_pseudosectiontotext(msg, 3344 DNS_PSEUDOSECTION_TSIG, 3345 style, flags, target); 3346 if (result != ISC_R_SUCCESS) 3347 return (result); 3348 3349 result = dns_message_pseudosectiontotext(msg, 3350 DNS_PSEUDOSECTION_SIG0, 3351 style, flags, target); 3352 if (result != ISC_R_SUCCESS) 3353 return (result); 3354 3355 return (ISC_R_SUCCESS); 3356} 3357 3358isc_region_t * 3359dns_message_getrawmessage(dns_message_t *msg) { 3360 REQUIRE(DNS_MESSAGE_VALID(msg)); 3361 return (&msg->saved); 3362} 3363 3364void 3365dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 3366 const void *order_arg) 3367{ 3368 REQUIRE(DNS_MESSAGE_VALID(msg)); 3369 msg->order = order; 3370 msg->order_arg = order_arg; 3371} 3372 3373void 3374dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 3375 REQUIRE(DNS_MESSAGE_VALID(msg)); 3376 msg->timeadjust = timeadjust; 3377} 3378 3379int 3380dns_message_gettimeadjust(dns_message_t *msg) { 3381 REQUIRE(DNS_MESSAGE_VALID(msg)); 3382 return (msg->timeadjust); 3383} 3384 3385isc_result_t 3386dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 3387 3388 REQUIRE(opcode < 16); 3389 3390 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) 3391 return (ISC_R_NOSPACE); 3392 isc_buffer_putstr(target, opcodetext[opcode]); 3393 return (ISC_R_SUCCESS); 3394} 3395