message.c revision 204619
1/* 2 * Copyright (C) 2004-2009 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.3 2009/11/24 03:25:53 marka 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 rdataset = NULL; 1535 free_rdataset = ISC_FALSE; 1536 free_name = ISC_FALSE; 1537 } 1538 1539 if (seen_problem) { 1540 if (free_name) 1541 isc_mempool_put(msg->namepool, name); 1542 if (free_rdataset) 1543 isc_mempool_put(msg->rdspool, rdataset); 1544 free_name = free_rdataset = ISC_FALSE; 1545 } 1546 INSIST(free_name == ISC_FALSE); 1547 INSIST(free_rdataset == ISC_FALSE); 1548 } 1549 1550 if (seen_problem) 1551 return (DNS_R_RECOVERABLE); 1552 return (ISC_R_SUCCESS); 1553 1554 cleanup: 1555 if (free_name) 1556 isc_mempool_put(msg->namepool, name); 1557 if (free_rdataset) 1558 isc_mempool_put(msg->rdspool, rdataset); 1559 1560 return (result); 1561} 1562 1563isc_result_t 1564dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1565 unsigned int options) 1566{ 1567 isc_region_t r; 1568 dns_decompress_t dctx; 1569 isc_result_t ret; 1570 isc_uint16_t tmpflags; 1571 isc_buffer_t origsource; 1572 isc_boolean_t seen_problem; 1573 isc_boolean_t ignore_tc; 1574 1575 REQUIRE(DNS_MESSAGE_VALID(msg)); 1576 REQUIRE(source != NULL); 1577 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1578 1579 seen_problem = ISC_FALSE; 1580 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); 1581 1582 origsource = *source; 1583 1584 msg->header_ok = 0; 1585 msg->question_ok = 0; 1586 1587 isc_buffer_remainingregion(source, &r); 1588 if (r.length < DNS_MESSAGE_HEADERLEN) 1589 return (ISC_R_UNEXPECTEDEND); 1590 1591 msg->id = isc_buffer_getuint16(source); 1592 tmpflags = isc_buffer_getuint16(source); 1593 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1594 >> DNS_MESSAGE_OPCODE_SHIFT); 1595 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1596 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1597 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1598 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1599 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1600 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1601 1602 msg->header_ok = 1; 1603 1604 /* 1605 * -1 means no EDNS. 1606 */ 1607 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1608 1609 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1610 1611 ret = getquestions(source, msg, &dctx, options); 1612 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1613 goto truncated; 1614 if (ret == DNS_R_RECOVERABLE) { 1615 seen_problem = ISC_TRUE; 1616 ret = ISC_R_SUCCESS; 1617 } 1618 if (ret != ISC_R_SUCCESS) 1619 return (ret); 1620 msg->question_ok = 1; 1621 1622 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1623 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1624 goto truncated; 1625 if (ret == DNS_R_RECOVERABLE) { 1626 seen_problem = ISC_TRUE; 1627 ret = ISC_R_SUCCESS; 1628 } 1629 if (ret != ISC_R_SUCCESS) 1630 return (ret); 1631 1632 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1633 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1634 goto truncated; 1635 if (ret == DNS_R_RECOVERABLE) { 1636 seen_problem = ISC_TRUE; 1637 ret = ISC_R_SUCCESS; 1638 } 1639 if (ret != ISC_R_SUCCESS) 1640 return (ret); 1641 1642 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1643 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1644 goto truncated; 1645 if (ret == DNS_R_RECOVERABLE) { 1646 seen_problem = ISC_TRUE; 1647 ret = ISC_R_SUCCESS; 1648 } 1649 if (ret != ISC_R_SUCCESS) 1650 return (ret); 1651 1652 isc_buffer_remainingregion(source, &r); 1653 if (r.length != 0) { 1654 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1655 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1656 "message has %u byte(s) of trailing garbage", 1657 r.length); 1658 } 1659 1660 truncated: 1661 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) 1662 isc_buffer_usedregion(&origsource, &msg->saved); 1663 else { 1664 msg->saved.length = isc_buffer_usedlength(&origsource); 1665 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1666 if (msg->saved.base == NULL) 1667 return (ISC_R_NOMEMORY); 1668 memcpy(msg->saved.base, isc_buffer_base(&origsource), 1669 msg->saved.length); 1670 msg->free_saved = 1; 1671 } 1672 1673 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1674 return (DNS_R_RECOVERABLE); 1675 if (seen_problem == ISC_TRUE) 1676 return (DNS_R_RECOVERABLE); 1677 return (ISC_R_SUCCESS); 1678} 1679 1680isc_result_t 1681dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1682 isc_buffer_t *buffer) 1683{ 1684 isc_region_t r; 1685 1686 REQUIRE(DNS_MESSAGE_VALID(msg)); 1687 REQUIRE(buffer != NULL); 1688 REQUIRE(msg->buffer == NULL); 1689 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1690 1691 msg->cctx = cctx; 1692 1693 /* 1694 * Erase the contents of this buffer. 1695 */ 1696 isc_buffer_clear(buffer); 1697 1698 /* 1699 * Make certain there is enough for at least the header in this 1700 * buffer. 1701 */ 1702 isc_buffer_availableregion(buffer, &r); 1703 if (r.length < DNS_MESSAGE_HEADERLEN) 1704 return (ISC_R_NOSPACE); 1705 1706 if (r.length < msg->reserved) 1707 return (ISC_R_NOSPACE); 1708 1709 /* 1710 * Reserve enough space for the header in this buffer. 1711 */ 1712 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1713 1714 msg->buffer = buffer; 1715 1716 return (ISC_R_SUCCESS); 1717} 1718 1719isc_result_t 1720dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1721 isc_region_t r, rn; 1722 1723 REQUIRE(DNS_MESSAGE_VALID(msg)); 1724 REQUIRE(buffer != NULL); 1725 REQUIRE(msg->buffer != NULL); 1726 1727 /* 1728 * Ensure that the new buffer is empty, and has enough space to 1729 * hold the current contents. 1730 */ 1731 isc_buffer_clear(buffer); 1732 1733 isc_buffer_availableregion(buffer, &rn); 1734 isc_buffer_usedregion(msg->buffer, &r); 1735 REQUIRE(rn.length > r.length); 1736 1737 /* 1738 * Copy the contents from the old to the new buffer. 1739 */ 1740 isc_buffer_add(buffer, r.length); 1741 memcpy(rn.base, r.base, r.length); 1742 1743 msg->buffer = buffer; 1744 1745 return (ISC_R_SUCCESS); 1746} 1747 1748void 1749dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1750 REQUIRE(DNS_MESSAGE_VALID(msg)); 1751 REQUIRE(space <= msg->reserved); 1752 1753 msg->reserved -= space; 1754} 1755 1756isc_result_t 1757dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1758 isc_region_t r; 1759 1760 REQUIRE(DNS_MESSAGE_VALID(msg)); 1761 1762 if (msg->buffer != NULL) { 1763 isc_buffer_availableregion(msg->buffer, &r); 1764 if (r.length < (space + msg->reserved)) 1765 return (ISC_R_NOSPACE); 1766 } 1767 1768 msg->reserved += space; 1769 1770 return (ISC_R_SUCCESS); 1771} 1772 1773static inline isc_boolean_t 1774wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1775 int pass_needed; 1776 1777 /* 1778 * If we are not rendering class IN, this ordering is bogus. 1779 */ 1780 if (rds->rdclass != dns_rdataclass_in) 1781 return (ISC_FALSE); 1782 1783 switch (rds->type) { 1784 case dns_rdatatype_a: 1785 case dns_rdatatype_aaaa: 1786 if (preferred_glue == rds->type) 1787 pass_needed = 4; 1788 else 1789 pass_needed = 3; 1790 break; 1791 case dns_rdatatype_rrsig: 1792 case dns_rdatatype_dnskey: 1793 pass_needed = 2; 1794 break; 1795 default: 1796 pass_needed = 1; 1797 } 1798 1799 if (pass_needed >= pass) 1800 return (ISC_FALSE); 1801 1802 return (ISC_TRUE); 1803} 1804 1805isc_result_t 1806dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1807 unsigned int options) 1808{ 1809 dns_namelist_t *section; 1810 dns_name_t *name, *next_name; 1811 dns_rdataset_t *rdataset, *next_rdataset; 1812 unsigned int count, total; 1813 isc_result_t result; 1814 isc_buffer_t st; /* for rollbacks */ 1815 int pass; 1816 isc_boolean_t partial = ISC_FALSE; 1817 unsigned int rd_options; 1818 dns_rdatatype_t preferred_glue = 0; 1819 1820 REQUIRE(DNS_MESSAGE_VALID(msg)); 1821 REQUIRE(msg->buffer != NULL); 1822 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1823 1824 section = &msg->sections[sectionid]; 1825 1826 if ((sectionid == DNS_SECTION_ADDITIONAL) 1827 && (options & DNS_MESSAGERENDER_ORDERED) == 0) { 1828 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1829 preferred_glue = dns_rdatatype_a; 1830 pass = 4; 1831 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1832 preferred_glue = dns_rdatatype_aaaa; 1833 pass = 4; 1834 } else 1835 pass = 3; 1836 } else 1837 pass = 1; 1838 1839 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) 1840 rd_options = 0; 1841 else 1842 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1843 1844 /* 1845 * Shrink the space in the buffer by the reserved amount. 1846 */ 1847 msg->buffer->length -= msg->reserved; 1848 1849 total = 0; 1850 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) 1851 partial = ISC_TRUE; 1852 1853 /* 1854 * Render required glue first. Set TC if it won't fit. 1855 */ 1856 name = ISC_LIST_HEAD(*section); 1857 if (name != NULL) { 1858 rdataset = ISC_LIST_HEAD(name->list); 1859 if (rdataset != NULL && 1860 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && 1861 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { 1862 const void *order_arg = msg->order_arg; 1863 st = *(msg->buffer); 1864 count = 0; 1865 if (partial) 1866 result = dns_rdataset_towirepartial(rdataset, 1867 name, 1868 msg->cctx, 1869 msg->buffer, 1870 msg->order, 1871 order_arg, 1872 rd_options, 1873 &count, 1874 NULL); 1875 else 1876 result = dns_rdataset_towiresorted(rdataset, 1877 name, 1878 msg->cctx, 1879 msg->buffer, 1880 msg->order, 1881 order_arg, 1882 rd_options, 1883 &count); 1884 total += count; 1885 if (partial && result == ISC_R_NOSPACE) { 1886 msg->flags |= DNS_MESSAGEFLAG_TC; 1887 msg->buffer->length += msg->reserved; 1888 msg->counts[sectionid] += total; 1889 return (result); 1890 } 1891 if (result == ISC_R_NOSPACE) 1892 msg->flags |= DNS_MESSAGEFLAG_TC; 1893 if (result != ISC_R_SUCCESS) { 1894 INSIST(st.used < 65536); 1895 dns_compress_rollback(msg->cctx, 1896 (isc_uint16_t)st.used); 1897 *(msg->buffer) = st; /* rollback */ 1898 msg->buffer->length += msg->reserved; 1899 msg->counts[sectionid] += total; 1900 return (result); 1901 } 1902 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 1903 } 1904 } 1905 1906 do { 1907 name = ISC_LIST_HEAD(*section); 1908 if (name == NULL) { 1909 msg->buffer->length += msg->reserved; 1910 msg->counts[sectionid] += total; 1911 return (ISC_R_SUCCESS); 1912 } 1913 1914 while (name != NULL) { 1915 next_name = ISC_LIST_NEXT(name, link); 1916 1917 rdataset = ISC_LIST_HEAD(name->list); 1918 while (rdataset != NULL) { 1919 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1920 1921 if ((rdataset->attributes & 1922 DNS_RDATASETATTR_RENDERED) != 0) 1923 goto next; 1924 1925 if (((options & DNS_MESSAGERENDER_ORDERED) 1926 == 0) 1927 && (sectionid == DNS_SECTION_ADDITIONAL) 1928 && wrong_priority(rdataset, pass, 1929 preferred_glue)) 1930 goto next; 1931 1932 st = *(msg->buffer); 1933 1934 count = 0; 1935 if (partial) 1936 result = dns_rdataset_towirepartial( 1937 rdataset, 1938 name, 1939 msg->cctx, 1940 msg->buffer, 1941 msg->order, 1942 msg->order_arg, 1943 rd_options, 1944 &count, 1945 NULL); 1946 else 1947 result = dns_rdataset_towiresorted( 1948 rdataset, 1949 name, 1950 msg->cctx, 1951 msg->buffer, 1952 msg->order, 1953 msg->order_arg, 1954 rd_options, 1955 &count); 1956 1957 total += count; 1958 1959 /* 1960 * If out of space, record stats on what we 1961 * rendered so far, and return that status. 1962 * 1963 * XXXMLG Need to change this when 1964 * dns_rdataset_towire() can render partial 1965 * sets starting at some arbitrary point in the 1966 * set. This will include setting a bit in the 1967 * rdataset to indicate that a partial 1968 * rendering was done, and some state saved 1969 * somewhere (probably in the message struct) 1970 * to indicate where to continue from. 1971 */ 1972 if (partial && result == ISC_R_NOSPACE) { 1973 msg->buffer->length += msg->reserved; 1974 msg->counts[sectionid] += total; 1975 return (result); 1976 } 1977 if (result != ISC_R_SUCCESS) { 1978 INSIST(st.used < 65536); 1979 dns_compress_rollback(msg->cctx, 1980 (isc_uint16_t)st.used); 1981 *(msg->buffer) = st; /* rollback */ 1982 msg->buffer->length += msg->reserved; 1983 msg->counts[sectionid] += total; 1984 return (result); 1985 } 1986 1987 /* 1988 * If we have rendered non-validated data, 1989 * ensure that the AD bit is not set. 1990 */ 1991 if (rdataset->trust != dns_trust_secure && 1992 (sectionid == DNS_SECTION_ANSWER || 1993 sectionid == DNS_SECTION_AUTHORITY)) 1994 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1995 if (OPTOUT(rdataset)) 1996 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1997 1998 rdataset->attributes |= 1999 DNS_RDATASETATTR_RENDERED; 2000 2001 next: 2002 rdataset = next_rdataset; 2003 } 2004 2005 name = next_name; 2006 } 2007 } while (--pass != 0); 2008 2009 msg->buffer->length += msg->reserved; 2010 msg->counts[sectionid] += total; 2011 2012 return (ISC_R_SUCCESS); 2013} 2014 2015void 2016dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 2017 isc_uint16_t tmp; 2018 isc_region_t r; 2019 2020 REQUIRE(DNS_MESSAGE_VALID(msg)); 2021 REQUIRE(target != NULL); 2022 2023 isc_buffer_availableregion(target, &r); 2024 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 2025 2026 isc_buffer_putuint16(target, msg->id); 2027 2028 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 2029 & DNS_MESSAGE_OPCODE_MASK); 2030 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 2031 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 2032 2033 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 2034 msg->counts[DNS_SECTION_ANSWER] < 65536 && 2035 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 2036 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 2037 2038 isc_buffer_putuint16(target, tmp); 2039 isc_buffer_putuint16(target, 2040 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2041 isc_buffer_putuint16(target, 2042 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2043 isc_buffer_putuint16(target, 2044 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2045 isc_buffer_putuint16(target, 2046 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2047} 2048 2049isc_result_t 2050dns_message_renderend(dns_message_t *msg) { 2051 isc_buffer_t tmpbuf; 2052 isc_region_t r; 2053 int result; 2054 unsigned int count; 2055 2056 REQUIRE(DNS_MESSAGE_VALID(msg)); 2057 REQUIRE(msg->buffer != NULL); 2058 2059 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2060 /* 2061 * We have an extended rcode but are not using EDNS. 2062 */ 2063 return (DNS_R_FORMERR); 2064 } 2065 2066 /* 2067 * If we've got an OPT record, render it. 2068 */ 2069 if (msg->opt != NULL) { 2070 dns_message_renderrelease(msg, msg->opt_reserved); 2071 msg->opt_reserved = 0; 2072 /* 2073 * Set the extended rcode. 2074 */ 2075 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2076 msg->opt->ttl |= ((msg->rcode << 20) & 2077 DNS_MESSAGE_EDNSRCODE_MASK); 2078 /* 2079 * Render. 2080 */ 2081 count = 0; 2082 result = dns_rdataset_towire(msg->opt, dns_rootname, 2083 msg->cctx, msg->buffer, 0, 2084 &count); 2085 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2086 if (result != ISC_R_SUCCESS) 2087 return (result); 2088 } 2089 2090 /* 2091 * If we're adding a TSIG or SIG(0) to a truncated message, 2092 * clear all rdatasets from the message except for the question 2093 * before adding the TSIG or SIG(0). If the question doesn't fit, 2094 * don't include it. 2095 */ 2096 if ((msg->tsigkey != NULL || msg->sig0key != NULL) && 2097 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2098 { 2099 isc_buffer_t *buf; 2100 2101 msgresetnames(msg, DNS_SECTION_ANSWER); 2102 buf = msg->buffer; 2103 dns_message_renderreset(msg); 2104 msg->buffer = buf; 2105 isc_buffer_clear(msg->buffer); 2106 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2107 dns_compress_rollback(msg->cctx, 0); 2108 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2109 0); 2110 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 2111 return (result); 2112 } 2113 2114 /* 2115 * If we're adding a TSIG record, generate and render it. 2116 */ 2117 if (msg->tsigkey != NULL) { 2118 dns_message_renderrelease(msg, msg->sig_reserved); 2119 msg->sig_reserved = 0; 2120 result = dns_tsig_sign(msg); 2121 if (result != ISC_R_SUCCESS) 2122 return (result); 2123 count = 0; 2124 result = dns_rdataset_towire(msg->tsig, msg->tsigname, 2125 msg->cctx, msg->buffer, 0, 2126 &count); 2127 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2128 if (result != ISC_R_SUCCESS) 2129 return (result); 2130 } 2131 2132 /* 2133 * If we're adding a SIG(0) record, generate and render it. 2134 */ 2135 if (msg->sig0key != NULL) { 2136 dns_message_renderrelease(msg, msg->sig_reserved); 2137 msg->sig_reserved = 0; 2138 result = dns_dnssec_signmessage(msg, msg->sig0key); 2139 if (result != ISC_R_SUCCESS) 2140 return (result); 2141 count = 0; 2142 /* 2143 * Note: dns_rootname is used here, not msg->sig0name, since 2144 * the owner name of a SIG(0) is irrelevant, and will not 2145 * be set in a message being rendered. 2146 */ 2147 result = dns_rdataset_towire(msg->sig0, dns_rootname, 2148 msg->cctx, msg->buffer, 0, 2149 &count); 2150 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2151 if (result != ISC_R_SUCCESS) 2152 return (result); 2153 } 2154 2155 isc_buffer_usedregion(msg->buffer, &r); 2156 isc_buffer_init(&tmpbuf, r.base, r.length); 2157 2158 dns_message_renderheader(msg, &tmpbuf); 2159 2160 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2161 2162 return (ISC_R_SUCCESS); 2163} 2164 2165void 2166dns_message_renderreset(dns_message_t *msg) { 2167 unsigned int i; 2168 dns_name_t *name; 2169 dns_rdataset_t *rds; 2170 2171 /* 2172 * Reset the message so that it may be rendered again. 2173 */ 2174 2175 REQUIRE(DNS_MESSAGE_VALID(msg)); 2176 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2177 2178 msg->buffer = NULL; 2179 2180 for (i = 0; i < DNS_SECTION_MAX; i++) { 2181 msg->cursors[i] = NULL; 2182 msg->counts[i] = 0; 2183 for (name = ISC_LIST_HEAD(msg->sections[i]); 2184 name != NULL; 2185 name = ISC_LIST_NEXT(name, link)) { 2186 for (rds = ISC_LIST_HEAD(name->list); 2187 rds != NULL; 2188 rds = ISC_LIST_NEXT(rds, link)) { 2189 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2190 } 2191 } 2192 } 2193 if (msg->tsigname != NULL) 2194 dns_message_puttempname(msg, &msg->tsigname); 2195 if (msg->tsig != NULL) { 2196 dns_rdataset_disassociate(msg->tsig); 2197 dns_message_puttemprdataset(msg, &msg->tsig); 2198 } 2199 if (msg->sig0 != NULL) { 2200 dns_rdataset_disassociate(msg->sig0); 2201 dns_message_puttemprdataset(msg, &msg->sig0); 2202 } 2203} 2204 2205isc_result_t 2206dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2207 REQUIRE(DNS_MESSAGE_VALID(msg)); 2208 REQUIRE(VALID_NAMED_SECTION(section)); 2209 2210 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2211 2212 if (msg->cursors[section] == NULL) 2213 return (ISC_R_NOMORE); 2214 2215 return (ISC_R_SUCCESS); 2216} 2217 2218isc_result_t 2219dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2220 REQUIRE(DNS_MESSAGE_VALID(msg)); 2221 REQUIRE(VALID_NAMED_SECTION(section)); 2222 REQUIRE(msg->cursors[section] != NULL); 2223 2224 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2225 2226 if (msg->cursors[section] == NULL) 2227 return (ISC_R_NOMORE); 2228 2229 return (ISC_R_SUCCESS); 2230} 2231 2232void 2233dns_message_currentname(dns_message_t *msg, dns_section_t section, 2234 dns_name_t **name) 2235{ 2236 REQUIRE(DNS_MESSAGE_VALID(msg)); 2237 REQUIRE(VALID_NAMED_SECTION(section)); 2238 REQUIRE(name != NULL && *name == NULL); 2239 REQUIRE(msg->cursors[section] != NULL); 2240 2241 *name = msg->cursors[section]; 2242} 2243 2244isc_result_t 2245dns_message_findname(dns_message_t *msg, dns_section_t section, 2246 dns_name_t *target, dns_rdatatype_t type, 2247 dns_rdatatype_t covers, dns_name_t **name, 2248 dns_rdataset_t **rdataset) 2249{ 2250 dns_name_t *foundname; 2251 isc_result_t result; 2252 2253 /* 2254 * XXX These requirements are probably too intensive, especially 2255 * where things can be NULL, but as they are they ensure that if 2256 * something is NON-NULL, indicating that the caller expects it 2257 * to be filled in, that we can in fact fill it in. 2258 */ 2259 REQUIRE(msg != NULL); 2260 REQUIRE(VALID_SECTION(section)); 2261 REQUIRE(target != NULL); 2262 if (name != NULL) 2263 REQUIRE(*name == NULL); 2264 if (type == dns_rdatatype_any) { 2265 REQUIRE(rdataset == NULL); 2266 } else { 2267 if (rdataset != NULL) 2268 REQUIRE(*rdataset == NULL); 2269 } 2270 2271 result = findname(&foundname, target, 2272 &msg->sections[section]); 2273 2274 if (result == ISC_R_NOTFOUND) 2275 return (DNS_R_NXDOMAIN); 2276 else if (result != ISC_R_SUCCESS) 2277 return (result); 2278 2279 if (name != NULL) 2280 *name = foundname; 2281 2282 /* 2283 * And now look for the type. 2284 */ 2285 if (type == dns_rdatatype_any) 2286 return (ISC_R_SUCCESS); 2287 2288 result = dns_message_findtype(foundname, type, covers, rdataset); 2289 if (result == ISC_R_NOTFOUND) 2290 return (DNS_R_NXRRSET); 2291 2292 return (result); 2293} 2294 2295void 2296dns_message_movename(dns_message_t *msg, dns_name_t *name, 2297 dns_section_t fromsection, 2298 dns_section_t tosection) 2299{ 2300 REQUIRE(msg != NULL); 2301 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2302 REQUIRE(name != NULL); 2303 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2304 REQUIRE(VALID_NAMED_SECTION(tosection)); 2305 2306 /* 2307 * Unlink the name from the old section 2308 */ 2309 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2310 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2311} 2312 2313void 2314dns_message_addname(dns_message_t *msg, dns_name_t *name, 2315 dns_section_t section) 2316{ 2317 REQUIRE(msg != NULL); 2318 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2319 REQUIRE(name != NULL); 2320 REQUIRE(VALID_NAMED_SECTION(section)); 2321 2322 ISC_LIST_APPEND(msg->sections[section], name, link); 2323} 2324 2325void 2326dns_message_removename(dns_message_t *msg, dns_name_t *name, 2327 dns_section_t section) 2328{ 2329 REQUIRE(msg != NULL); 2330 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2331 REQUIRE(name != NULL); 2332 REQUIRE(VALID_NAMED_SECTION(section)); 2333 2334 ISC_LIST_UNLINK(msg->sections[section], name, link); 2335} 2336 2337isc_result_t 2338dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2339 REQUIRE(DNS_MESSAGE_VALID(msg)); 2340 REQUIRE(item != NULL && *item == NULL); 2341 2342 *item = isc_mempool_get(msg->namepool); 2343 if (*item == NULL) 2344 return (ISC_R_NOMEMORY); 2345 dns_name_init(*item, NULL); 2346 2347 return (ISC_R_SUCCESS); 2348} 2349 2350isc_result_t 2351dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { 2352 REQUIRE(DNS_MESSAGE_VALID(msg)); 2353 REQUIRE(item != NULL && *item == NULL); 2354 2355 *item = newoffsets(msg); 2356 if (*item == NULL) 2357 return (ISC_R_NOMEMORY); 2358 2359 return (ISC_R_SUCCESS); 2360} 2361 2362isc_result_t 2363dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2364 REQUIRE(DNS_MESSAGE_VALID(msg)); 2365 REQUIRE(item != NULL && *item == NULL); 2366 2367 *item = newrdata(msg); 2368 if (*item == NULL) 2369 return (ISC_R_NOMEMORY); 2370 2371 return (ISC_R_SUCCESS); 2372} 2373 2374isc_result_t 2375dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2376 REQUIRE(DNS_MESSAGE_VALID(msg)); 2377 REQUIRE(item != NULL && *item == NULL); 2378 2379 *item = isc_mempool_get(msg->rdspool); 2380 if (*item == NULL) 2381 return (ISC_R_NOMEMORY); 2382 2383 dns_rdataset_init(*item); 2384 2385 return (ISC_R_SUCCESS); 2386} 2387 2388isc_result_t 2389dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2390 REQUIRE(DNS_MESSAGE_VALID(msg)); 2391 REQUIRE(item != NULL && *item == NULL); 2392 2393 *item = newrdatalist(msg); 2394 if (*item == NULL) 2395 return (ISC_R_NOMEMORY); 2396 2397 return (ISC_R_SUCCESS); 2398} 2399 2400void 2401dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2402 REQUIRE(DNS_MESSAGE_VALID(msg)); 2403 REQUIRE(item != NULL && *item != NULL); 2404 2405 if (dns_name_dynamic(*item)) 2406 dns_name_free(*item, msg->mctx); 2407 isc_mempool_put(msg->namepool, *item); 2408 *item = NULL; 2409} 2410 2411void 2412dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2413 REQUIRE(DNS_MESSAGE_VALID(msg)); 2414 REQUIRE(item != NULL && *item != NULL); 2415 2416 releaserdata(msg, *item); 2417 *item = NULL; 2418} 2419 2420void 2421dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2422 REQUIRE(DNS_MESSAGE_VALID(msg)); 2423 REQUIRE(item != NULL && *item != NULL); 2424 2425 REQUIRE(!dns_rdataset_isassociated(*item)); 2426 isc_mempool_put(msg->rdspool, *item); 2427 *item = NULL; 2428} 2429 2430void 2431dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2432 REQUIRE(DNS_MESSAGE_VALID(msg)); 2433 REQUIRE(item != NULL && *item != NULL); 2434 2435 releaserdatalist(msg, *item); 2436 *item = NULL; 2437} 2438 2439isc_result_t 2440dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2441 unsigned int *flagsp) 2442{ 2443 isc_region_t r; 2444 isc_buffer_t buffer; 2445 dns_messageid_t id; 2446 unsigned int flags; 2447 2448 REQUIRE(source != NULL); 2449 2450 buffer = *source; 2451 2452 isc_buffer_remainingregion(&buffer, &r); 2453 if (r.length < DNS_MESSAGE_HEADERLEN) 2454 return (ISC_R_UNEXPECTEDEND); 2455 2456 id = isc_buffer_getuint16(&buffer); 2457 flags = isc_buffer_getuint16(&buffer); 2458 flags &= DNS_MESSAGE_FLAG_MASK; 2459 2460 if (flagsp != NULL) 2461 *flagsp = flags; 2462 if (idp != NULL) 2463 *idp = id; 2464 2465 return (ISC_R_SUCCESS); 2466} 2467 2468isc_result_t 2469dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { 2470 unsigned int first_section; 2471 isc_result_t result; 2472 2473 REQUIRE(DNS_MESSAGE_VALID(msg)); 2474 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2475 2476 if (!msg->header_ok) 2477 return (DNS_R_FORMERR); 2478 if (msg->opcode != dns_opcode_query && 2479 msg->opcode != dns_opcode_notify) 2480 want_question_section = ISC_FALSE; 2481 if (want_question_section) { 2482 if (!msg->question_ok) 2483 return (DNS_R_FORMERR); 2484 first_section = DNS_SECTION_ANSWER; 2485 } else 2486 first_section = DNS_SECTION_QUESTION; 2487 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2488 msgresetnames(msg, first_section); 2489 msgresetopt(msg); 2490 msgresetsigs(msg, ISC_TRUE); 2491 msginitprivate(msg); 2492 /* 2493 * We now clear most flags and then set QR, ensuring that the 2494 * reply's flags will be in a reasonable state. 2495 */ 2496 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2497 msg->flags |= DNS_MESSAGEFLAG_QR; 2498 2499 /* 2500 * This saves the query TSIG status, if the query was signed, and 2501 * reserves space in the reply for the TSIG. 2502 */ 2503 if (msg->tsigkey != NULL) { 2504 unsigned int otherlen = 0; 2505 msg->querytsigstatus = msg->tsigstatus; 2506 msg->tsigstatus = dns_rcode_noerror; 2507 if (msg->querytsigstatus == dns_tsigerror_badtime) 2508 otherlen = 6; 2509 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2510 result = dns_message_renderreserve(msg, msg->sig_reserved); 2511 if (result != ISC_R_SUCCESS) { 2512 msg->sig_reserved = 0; 2513 return (result); 2514 } 2515 } 2516 if (msg->saved.base != NULL) { 2517 msg->query.base = msg->saved.base; 2518 msg->query.length = msg->saved.length; 2519 msg->free_query = msg->free_saved; 2520 msg->saved.base = NULL; 2521 msg->saved.length = 0; 2522 msg->free_saved = 0; 2523 } 2524 2525 return (ISC_R_SUCCESS); 2526} 2527 2528dns_rdataset_t * 2529dns_message_getopt(dns_message_t *msg) { 2530 2531 /* 2532 * Get the OPT record for 'msg'. 2533 */ 2534 2535 REQUIRE(DNS_MESSAGE_VALID(msg)); 2536 2537 return (msg->opt); 2538} 2539 2540isc_result_t 2541dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2542 isc_result_t result; 2543 dns_rdata_t rdata = DNS_RDATA_INIT; 2544 2545 /* 2546 * Set the OPT record for 'msg'. 2547 */ 2548 2549 /* 2550 * The space required for an OPT record is: 2551 * 2552 * 1 byte for the name 2553 * 2 bytes for the type 2554 * 2 bytes for the class 2555 * 4 bytes for the ttl 2556 * 2 bytes for the rdata length 2557 * --------------------------------- 2558 * 11 bytes 2559 * 2560 * plus the length of the rdata. 2561 */ 2562 2563 REQUIRE(DNS_MESSAGE_VALID(msg)); 2564 REQUIRE(opt->type == dns_rdatatype_opt); 2565 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2566 REQUIRE(msg->state == DNS_SECTION_ANY); 2567 2568 msgresetopt(msg); 2569 2570 result = dns_rdataset_first(opt); 2571 if (result != ISC_R_SUCCESS) 2572 goto cleanup; 2573 dns_rdataset_current(opt, &rdata); 2574 msg->opt_reserved = 11 + rdata.length; 2575 result = dns_message_renderreserve(msg, msg->opt_reserved); 2576 if (result != ISC_R_SUCCESS) { 2577 msg->opt_reserved = 0; 2578 goto cleanup; 2579 } 2580 2581 msg->opt = opt; 2582 2583 return (ISC_R_SUCCESS); 2584 2585 cleanup: 2586 dns_message_puttemprdataset(msg, &opt); 2587 return (result); 2588 2589} 2590 2591dns_rdataset_t * 2592dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2593 2594 /* 2595 * Get the TSIG record and owner for 'msg'. 2596 */ 2597 2598 REQUIRE(DNS_MESSAGE_VALID(msg)); 2599 REQUIRE(owner == NULL || *owner == NULL); 2600 2601 if (owner != NULL) 2602 *owner = msg->tsigname; 2603 return (msg->tsig); 2604} 2605 2606isc_result_t 2607dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2608 isc_result_t result; 2609 2610 /* 2611 * Set the TSIG key for 'msg' 2612 */ 2613 2614 REQUIRE(DNS_MESSAGE_VALID(msg)); 2615 REQUIRE(msg->state == DNS_SECTION_ANY); 2616 2617 if (key == NULL && msg->tsigkey != NULL) { 2618 if (msg->sig_reserved != 0) { 2619 dns_message_renderrelease(msg, msg->sig_reserved); 2620 msg->sig_reserved = 0; 2621 } 2622 dns_tsigkey_detach(&msg->tsigkey); 2623 } 2624 if (key != NULL) { 2625 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2626 dns_tsigkey_attach(key, &msg->tsigkey); 2627 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2628 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2629 result = dns_message_renderreserve(msg, 2630 msg->sig_reserved); 2631 if (result != ISC_R_SUCCESS) { 2632 dns_tsigkey_detach(&msg->tsigkey); 2633 msg->sig_reserved = 0; 2634 return (result); 2635 } 2636 } 2637 } 2638 return (ISC_R_SUCCESS); 2639} 2640 2641dns_tsigkey_t * 2642dns_message_gettsigkey(dns_message_t *msg) { 2643 2644 /* 2645 * Get the TSIG key for 'msg' 2646 */ 2647 2648 REQUIRE(DNS_MESSAGE_VALID(msg)); 2649 2650 return (msg->tsigkey); 2651} 2652 2653isc_result_t 2654dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2655 dns_rdata_t *rdata = NULL; 2656 dns_rdatalist_t *list = NULL; 2657 dns_rdataset_t *set = NULL; 2658 isc_buffer_t *buf = NULL; 2659 isc_region_t r; 2660 isc_result_t result; 2661 2662 REQUIRE(DNS_MESSAGE_VALID(msg)); 2663 REQUIRE(msg->querytsig == NULL); 2664 2665 if (querytsig == NULL) 2666 return (ISC_R_SUCCESS); 2667 2668 result = dns_message_gettemprdata(msg, &rdata); 2669 if (result != ISC_R_SUCCESS) 2670 goto cleanup; 2671 2672 result = dns_message_gettemprdatalist(msg, &list); 2673 if (result != ISC_R_SUCCESS) 2674 goto cleanup; 2675 result = dns_message_gettemprdataset(msg, &set); 2676 if (result != ISC_R_SUCCESS) 2677 goto cleanup; 2678 2679 isc_buffer_usedregion(querytsig, &r); 2680 result = isc_buffer_allocate(msg->mctx, &buf, r.length); 2681 if (result != ISC_R_SUCCESS) 2682 goto cleanup; 2683 isc_buffer_putmem(buf, r.base, r.length); 2684 isc_buffer_usedregion(buf, &r); 2685 dns_rdata_init(rdata); 2686 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2687 dns_message_takebuffer(msg, &buf); 2688 ISC_LIST_INIT(list->rdata); 2689 ISC_LIST_APPEND(list->rdata, rdata, link); 2690 result = dns_rdatalist_tordataset(list, set); 2691 if (result != ISC_R_SUCCESS) 2692 goto cleanup; 2693 2694 msg->querytsig = set; 2695 2696 return (result); 2697 2698 cleanup: 2699 if (rdata != NULL) 2700 dns_message_puttemprdata(msg, &rdata); 2701 if (list != NULL) 2702 dns_message_puttemprdatalist(msg, &list); 2703 if (set != NULL) 2704 dns_message_puttemprdataset(msg, &set); 2705 return (ISC_R_NOMEMORY); 2706} 2707 2708isc_result_t 2709dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2710 isc_buffer_t **querytsig) { 2711 isc_result_t result; 2712 dns_rdata_t rdata = DNS_RDATA_INIT; 2713 isc_region_t r; 2714 2715 REQUIRE(DNS_MESSAGE_VALID(msg)); 2716 REQUIRE(mctx != NULL); 2717 REQUIRE(querytsig != NULL && *querytsig == NULL); 2718 2719 if (msg->tsig == NULL) 2720 return (ISC_R_SUCCESS); 2721 2722 result = dns_rdataset_first(msg->tsig); 2723 if (result != ISC_R_SUCCESS) 2724 return (result); 2725 dns_rdataset_current(msg->tsig, &rdata); 2726 dns_rdata_toregion(&rdata, &r); 2727 2728 result = isc_buffer_allocate(mctx, querytsig, r.length); 2729 if (result != ISC_R_SUCCESS) 2730 return (result); 2731 isc_buffer_putmem(*querytsig, r.base, r.length); 2732 return (ISC_R_SUCCESS); 2733} 2734 2735dns_rdataset_t * 2736dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2737 2738 /* 2739 * Get the SIG(0) record for 'msg'. 2740 */ 2741 2742 REQUIRE(DNS_MESSAGE_VALID(msg)); 2743 REQUIRE(owner == NULL || *owner == NULL); 2744 2745 if (msg->sig0 != NULL && owner != NULL) { 2746 /* If dns_message_getsig0 is called on a rendered message 2747 * after the SIG(0) has been applied, we need to return the 2748 * root name, not NULL. 2749 */ 2750 if (msg->sig0name == NULL) 2751 *owner = dns_rootname; 2752 else 2753 *owner = msg->sig0name; 2754 } 2755 return (msg->sig0); 2756} 2757 2758isc_result_t 2759dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2760 isc_region_t r; 2761 unsigned int x; 2762 isc_result_t result; 2763 2764 /* 2765 * Set the SIG(0) key for 'msg' 2766 */ 2767 2768 /* 2769 * The space required for an SIG(0) record is: 2770 * 2771 * 1 byte for the name 2772 * 2 bytes for the type 2773 * 2 bytes for the class 2774 * 4 bytes for the ttl 2775 * 2 bytes for the type covered 2776 * 1 byte for the algorithm 2777 * 1 bytes for the labels 2778 * 4 bytes for the original ttl 2779 * 4 bytes for the signature expiration 2780 * 4 bytes for the signature inception 2781 * 2 bytes for the key tag 2782 * n bytes for the signer's name 2783 * x bytes for the signature 2784 * --------------------------------- 2785 * 27 + n + x bytes 2786 */ 2787 REQUIRE(DNS_MESSAGE_VALID(msg)); 2788 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2789 REQUIRE(msg->state == DNS_SECTION_ANY); 2790 2791 if (key != NULL) { 2792 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 2793 dns_name_toregion(dst_key_name(key), &r); 2794 result = dst_key_sigsize(key, &x); 2795 if (result != ISC_R_SUCCESS) { 2796 msg->sig_reserved = 0; 2797 return (result); 2798 } 2799 msg->sig_reserved = 27 + r.length + x; 2800 result = dns_message_renderreserve(msg, msg->sig_reserved); 2801 if (result != ISC_R_SUCCESS) { 2802 msg->sig_reserved = 0; 2803 return (result); 2804 } 2805 msg->sig0key = key; 2806 } 2807 return (ISC_R_SUCCESS); 2808} 2809 2810dst_key_t * 2811dns_message_getsig0key(dns_message_t *msg) { 2812 2813 /* 2814 * Get the SIG(0) key for 'msg' 2815 */ 2816 2817 REQUIRE(DNS_MESSAGE_VALID(msg)); 2818 2819 return (msg->sig0key); 2820} 2821 2822void 2823dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2824 REQUIRE(DNS_MESSAGE_VALID(msg)); 2825 REQUIRE(buffer != NULL); 2826 REQUIRE(ISC_BUFFER_VALID(*buffer)); 2827 2828 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2829 *buffer = NULL; 2830} 2831 2832isc_result_t 2833dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 2834 isc_result_t result = ISC_R_SUCCESS; 2835 dns_rdata_t rdata = DNS_RDATA_INIT; 2836 2837 REQUIRE(DNS_MESSAGE_VALID(msg)); 2838 REQUIRE(signer != NULL); 2839 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 2840 2841 if (msg->tsig == NULL && msg->sig0 == NULL) 2842 return (ISC_R_NOTFOUND); 2843 2844 if (msg->verify_attempted == 0) 2845 return (DNS_R_NOTVERIFIEDYET); 2846 2847 if (!dns_name_hasbuffer(signer)) { 2848 isc_buffer_t *dynbuf = NULL; 2849 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 2850 if (result != ISC_R_SUCCESS) 2851 return (result); 2852 dns_name_setbuffer(signer, dynbuf); 2853 dns_message_takebuffer(msg, &dynbuf); 2854 } 2855 2856 if (msg->sig0 != NULL) { 2857 dns_rdata_sig_t sig; 2858 2859 result = dns_rdataset_first(msg->sig0); 2860 INSIST(result == ISC_R_SUCCESS); 2861 dns_rdataset_current(msg->sig0, &rdata); 2862 2863 result = dns_rdata_tostruct(&rdata, &sig, NULL); 2864 if (result != ISC_R_SUCCESS) 2865 return (result); 2866 2867 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) 2868 result = ISC_R_SUCCESS; 2869 else 2870 result = DNS_R_SIGINVALID; 2871 dns_name_clone(&sig.signer, signer); 2872 dns_rdata_freestruct(&sig); 2873 } else { 2874 dns_name_t *identity; 2875 dns_rdata_any_tsig_t tsig; 2876 2877 result = dns_rdataset_first(msg->tsig); 2878 INSIST(result == ISC_R_SUCCESS); 2879 dns_rdataset_current(msg->tsig, &rdata); 2880 2881 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2882 if (msg->tsigstatus != dns_rcode_noerror) 2883 result = DNS_R_TSIGVERIFYFAILURE; 2884 else if (tsig.error != dns_rcode_noerror) 2885 result = DNS_R_TSIGERRORSET; 2886 else 2887 result = ISC_R_SUCCESS; 2888 dns_rdata_freestruct(&tsig); 2889 2890 if (msg->tsigkey == NULL) { 2891 /* 2892 * If msg->tsigstatus & tsig.error are both 2893 * dns_rcode_noerror, the message must have been 2894 * verified, which means msg->tsigkey will be 2895 * non-NULL. 2896 */ 2897 INSIST(result != ISC_R_SUCCESS); 2898 } else { 2899 identity = dns_tsigkey_identity(msg->tsigkey); 2900 if (identity == NULL) { 2901 if (result == ISC_R_SUCCESS) 2902 result = DNS_R_NOIDENTITY; 2903 identity = &msg->tsigkey->name; 2904 } 2905 dns_name_clone(identity, signer); 2906 } 2907 } 2908 2909 return (result); 2910} 2911 2912void 2913dns_message_resetsig(dns_message_t *msg) { 2914 REQUIRE(DNS_MESSAGE_VALID(msg)); 2915 msg->verified_sig = 0; 2916 msg->verify_attempted = 0; 2917 msg->tsigstatus = dns_rcode_noerror; 2918 msg->sig0status = dns_rcode_noerror; 2919 msg->timeadjust = 0; 2920 if (msg->tsigkey != NULL) { 2921 dns_tsigkey_detach(&msg->tsigkey); 2922 msg->tsigkey = NULL; 2923 } 2924} 2925 2926isc_result_t 2927dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 2928 dns_message_resetsig(msg); 2929 return (dns_message_checksig(msg, view)); 2930} 2931 2932#ifdef SKAN_MSG_DEBUG 2933void 2934dns_message_dumpsig(dns_message_t *msg, char *txt1) { 2935 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 2936 dns_rdata_any_tsig_t querytsig; 2937 isc_result_t result; 2938 2939 if (msg->tsig != NULL) { 2940 result = dns_rdataset_first(msg->tsig); 2941 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2942 dns_rdataset_current(msg->tsig, &querytsigrdata); 2943 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 2944 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2945 hexdump(txt1, "TSIG", querytsig.signature, 2946 querytsig.siglen); 2947 } 2948 2949 if (msg->querytsig != NULL) { 2950 result = dns_rdataset_first(msg->querytsig); 2951 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2952 dns_rdataset_current(msg->querytsig, &querytsigrdata); 2953 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 2954 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2955 hexdump(txt1, "QUERYTSIG", querytsig.signature, 2956 querytsig.siglen); 2957 } 2958} 2959#endif 2960 2961isc_result_t 2962dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 2963 isc_buffer_t b, msgb; 2964 2965 REQUIRE(DNS_MESSAGE_VALID(msg)); 2966 2967 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) 2968 return (ISC_R_SUCCESS); 2969 2970 INSIST(msg->saved.base != NULL); 2971 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 2972 isc_buffer_add(&msgb, msg->saved.length); 2973 if (msg->tsigkey != NULL || msg->tsig != NULL) { 2974#ifdef SKAN_MSG_DEBUG 2975 dns_message_dumpsig(msg, "dns_message_checksig#1"); 2976#endif 2977 if (view != NULL) 2978 return (dns_view_checksig(view, &msgb, msg)); 2979 else 2980 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 2981 } else { 2982 dns_rdata_t rdata = DNS_RDATA_INIT; 2983 dns_rdata_sig_t sig; 2984 dns_rdataset_t keyset; 2985 isc_result_t result; 2986 2987 result = dns_rdataset_first(msg->sig0); 2988 INSIST(result == ISC_R_SUCCESS); 2989 dns_rdataset_current(msg->sig0, &rdata); 2990 2991 /* 2992 * This can occur when the message is a dynamic update, since 2993 * the rdata length checking is relaxed. This should not 2994 * happen in a well-formed message, since the SIG(0) is only 2995 * looked for in the additional section, and the dynamic update 2996 * meta-records are in the prerequisite and update sections. 2997 */ 2998 if (rdata.length == 0) 2999 return (ISC_R_UNEXPECTEDEND); 3000 3001 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 3002 if (result != ISC_R_SUCCESS) 3003 return (result); 3004 3005 dns_rdataset_init(&keyset); 3006 if (view == NULL) 3007 return (DNS_R_KEYUNAUTHORIZED); 3008 result = dns_view_simplefind(view, &sig.signer, 3009 dns_rdatatype_key /* SIG(0) */, 3010 0, 0, ISC_FALSE, &keyset, NULL); 3011 3012 if (result != ISC_R_SUCCESS) { 3013 /* XXXBEW Should possibly create a fetch here */ 3014 result = DNS_R_KEYUNAUTHORIZED; 3015 goto freesig; 3016 } else if (keyset.trust < dns_trust_secure) { 3017 /* XXXBEW Should call a validator here */ 3018 result = DNS_R_KEYUNAUTHORIZED; 3019 goto freesig; 3020 } 3021 result = dns_rdataset_first(&keyset); 3022 INSIST(result == ISC_R_SUCCESS); 3023 for (; 3024 result == ISC_R_SUCCESS; 3025 result = dns_rdataset_next(&keyset)) 3026 { 3027 dst_key_t *key = NULL; 3028 3029 dns_rdata_reset(&rdata); 3030 dns_rdataset_current(&keyset, &rdata); 3031 isc_buffer_init(&b, rdata.data, rdata.length); 3032 isc_buffer_add(&b, rdata.length); 3033 3034 result = dst_key_fromdns(&sig.signer, rdata.rdclass, 3035 &b, view->mctx, &key); 3036 if (result != ISC_R_SUCCESS) 3037 continue; 3038 if (dst_key_alg(key) != sig.algorithm || 3039 dst_key_id(key) != sig.keyid || 3040 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 3041 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 3042 { 3043 dst_key_free(&key); 3044 continue; 3045 } 3046 result = dns_dnssec_verifymessage(&msgb, msg, key); 3047 dst_key_free(&key); 3048 if (result == ISC_R_SUCCESS) 3049 break; 3050 } 3051 if (result == ISC_R_NOMORE) 3052 result = DNS_R_KEYUNAUTHORIZED; 3053 3054 freesig: 3055 if (dns_rdataset_isassociated(&keyset)) 3056 dns_rdataset_disassociate(&keyset); 3057 dns_rdata_freestruct(&sig); 3058 return (result); 3059 } 3060} 3061 3062isc_result_t 3063dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 3064 const dns_master_style_t *style, 3065 dns_messagetextflag_t flags, 3066 isc_buffer_t *target) { 3067 dns_name_t *name, empty_name; 3068 dns_rdataset_t *rdataset; 3069 isc_result_t result; 3070 3071 REQUIRE(DNS_MESSAGE_VALID(msg)); 3072 REQUIRE(target != NULL); 3073 REQUIRE(VALID_SECTION(section)); 3074 3075 if (ISC_LIST_EMPTY(msg->sections[section])) 3076 return (ISC_R_SUCCESS); 3077 3078 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3079 ADD_STRING(target, ";; "); 3080 if (msg->opcode != dns_opcode_update) { 3081 ADD_STRING(target, sectiontext[section]); 3082 } else { 3083 ADD_STRING(target, updsectiontext[section]); 3084 } 3085 ADD_STRING(target, " SECTION:\n"); 3086 } 3087 3088 dns_name_init(&empty_name, NULL); 3089 result = dns_message_firstname(msg, section); 3090 if (result != ISC_R_SUCCESS) { 3091 return (result); 3092 } 3093 do { 3094 name = NULL; 3095 dns_message_currentname(msg, section, &name); 3096 for (rdataset = ISC_LIST_HEAD(name->list); 3097 rdataset != NULL; 3098 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3099 if (section == DNS_SECTION_QUESTION) { 3100 ADD_STRING(target, ";"); 3101 result = dns_master_questiontotext(name, 3102 rdataset, 3103 style, 3104 target); 3105 } else { 3106 result = dns_master_rdatasettotext(name, 3107 rdataset, 3108 style, 3109 target); 3110 } 3111 if (result != ISC_R_SUCCESS) 3112 return (result); 3113 } 3114 result = dns_message_nextname(msg, section); 3115 } while (result == ISC_R_SUCCESS); 3116 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3117 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3118 ADD_STRING(target, "\n"); 3119 if (result == ISC_R_NOMORE) 3120 result = ISC_R_SUCCESS; 3121 return (result); 3122} 3123 3124isc_result_t 3125dns_message_pseudosectiontotext(dns_message_t *msg, 3126 dns_pseudosection_t section, 3127 const dns_master_style_t *style, 3128 dns_messagetextflag_t flags, 3129 isc_buffer_t *target) { 3130 dns_rdataset_t *ps = NULL; 3131 dns_name_t *name = NULL; 3132 isc_result_t result; 3133 char buf[sizeof("1234567890")]; 3134 isc_uint32_t mbz; 3135 dns_rdata_t rdata; 3136 isc_buffer_t optbuf; 3137 isc_uint16_t optcode, optlen; 3138 unsigned char *optdata; 3139 3140 REQUIRE(DNS_MESSAGE_VALID(msg)); 3141 REQUIRE(target != NULL); 3142 REQUIRE(VALID_PSEUDOSECTION(section)); 3143 3144 switch (section) { 3145 case DNS_PSEUDOSECTION_OPT: 3146 ps = dns_message_getopt(msg); 3147 if (ps == NULL) 3148 return (ISC_R_SUCCESS); 3149 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3150 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3151 ADD_STRING(target, "; EDNS: version: "); 3152 snprintf(buf, sizeof(buf), "%u", 3153 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3154 ADD_STRING(target, buf); 3155 ADD_STRING(target, ", flags:"); 3156 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 3157 ADD_STRING(target, " do"); 3158 mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff; 3159 if (mbz != 0) { 3160 ADD_STRING(target, "; MBZ: "); 3161 snprintf(buf, sizeof(buf), "%.4x ", mbz); 3162 ADD_STRING(target, buf); 3163 ADD_STRING(target, ", udp: "); 3164 } else 3165 ADD_STRING(target, "; udp: "); 3166 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3167 ADD_STRING(target, buf); 3168 3169 result = dns_rdataset_first(ps); 3170 if (result != ISC_R_SUCCESS) 3171 return (ISC_R_SUCCESS); 3172 3173 /* Print EDNS info, if any */ 3174 dns_rdata_init(&rdata); 3175 dns_rdataset_current(ps, &rdata); 3176 if (rdata.length < 4) 3177 return (ISC_R_SUCCESS); 3178 3179 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3180 isc_buffer_add(&optbuf, rdata.length); 3181 optcode = isc_buffer_getuint16(&optbuf); 3182 optlen = isc_buffer_getuint16(&optbuf); 3183 3184 if (optcode == DNS_OPT_NSID) { 3185 ADD_STRING(target, "; NSID"); 3186 } else { 3187 ADD_STRING(target, "; OPT="); 3188 sprintf(buf, "%u", optcode); 3189 ADD_STRING(target, buf); 3190 } 3191 3192 if (optlen != 0) { 3193 int i; 3194 ADD_STRING(target, ": "); 3195 3196 optdata = rdata.data + 4; 3197 for (i = 0; i < optlen; i++) { 3198 sprintf(buf, "%02x ", optdata[i]); 3199 ADD_STRING(target, buf); 3200 } 3201 for (i = 0; i < optlen; i++) { 3202 ADD_STRING(target, " ("); 3203 if (isprint(optdata[i])) 3204 isc_buffer_putmem(target, &optdata[i], 3205 1); 3206 else 3207 isc_buffer_putstr(target, "."); 3208 ADD_STRING(target, ")"); 3209 } 3210 } 3211 ADD_STRING(target, "\n"); 3212 return (ISC_R_SUCCESS); 3213 case DNS_PSEUDOSECTION_TSIG: 3214 ps = dns_message_gettsig(msg, &name); 3215 if (ps == NULL) 3216 return (ISC_R_SUCCESS); 3217 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3218 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 3219 result = dns_master_rdatasettotext(name, ps, style, target); 3220 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3221 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3222 ADD_STRING(target, "\n"); 3223 return (result); 3224 case DNS_PSEUDOSECTION_SIG0: 3225 ps = dns_message_getsig0(msg, &name); 3226 if (ps == NULL) 3227 return (ISC_R_SUCCESS); 3228 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3229 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 3230 result = dns_master_rdatasettotext(name, ps, style, target); 3231 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3232 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3233 ADD_STRING(target, "\n"); 3234 return (result); 3235 } 3236 return (ISC_R_UNEXPECTED); 3237} 3238 3239isc_result_t 3240dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 3241 dns_messagetextflag_t flags, isc_buffer_t *target) { 3242 char buf[sizeof("1234567890")]; 3243 isc_result_t result; 3244 3245 REQUIRE(DNS_MESSAGE_VALID(msg)); 3246 REQUIRE(target != NULL); 3247 3248 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { 3249 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 3250 ADD_STRING(target, opcodetext[msg->opcode]); 3251 ADD_STRING(target, ", status: "); 3252 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 3253 ADD_STRING(target, rcodetext[msg->rcode]); 3254 } else { 3255 snprintf(buf, sizeof(buf), "%4u", msg->rcode); 3256 ADD_STRING(target, buf); 3257 } 3258 ADD_STRING(target, ", id: "); 3259 snprintf(buf, sizeof(buf), "%6u", msg->id); 3260 ADD_STRING(target, buf); 3261 ADD_STRING(target, "\n;; flags: "); 3262 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 3263 ADD_STRING(target, "qr "); 3264 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 3265 ADD_STRING(target, "aa "); 3266 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 3267 ADD_STRING(target, "tc "); 3268 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 3269 ADD_STRING(target, "rd "); 3270 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 3271 ADD_STRING(target, "ra "); 3272 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 3273 ADD_STRING(target, "ad "); 3274 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 3275 ADD_STRING(target, "cd "); 3276 if (msg->opcode != dns_opcode_update) { 3277 ADD_STRING(target, "; QUESTION: "); 3278 } else { 3279 ADD_STRING(target, "; ZONE: "); 3280 } 3281 snprintf(buf, sizeof(buf), "%1u", 3282 msg->counts[DNS_SECTION_QUESTION]); 3283 ADD_STRING(target, buf); 3284 if (msg->opcode != dns_opcode_update) { 3285 ADD_STRING(target, ", ANSWER: "); 3286 } else { 3287 ADD_STRING(target, ", PREREQ: "); 3288 } 3289 snprintf(buf, sizeof(buf), "%1u", 3290 msg->counts[DNS_SECTION_ANSWER]); 3291 ADD_STRING(target, buf); 3292 if (msg->opcode != dns_opcode_update) { 3293 ADD_STRING(target, ", AUTHORITY: "); 3294 } else { 3295 ADD_STRING(target, ", UPDATE: "); 3296 } 3297 snprintf(buf, sizeof(buf), "%1u", 3298 msg->counts[DNS_SECTION_AUTHORITY]); 3299 ADD_STRING(target, buf); 3300 ADD_STRING(target, ", ADDITIONAL: "); 3301 snprintf(buf, sizeof(buf), "%1u", 3302 msg->counts[DNS_SECTION_ADDITIONAL]); 3303 ADD_STRING(target, buf); 3304 ADD_STRING(target, "\n"); 3305 } 3306 result = dns_message_pseudosectiontotext(msg, 3307 DNS_PSEUDOSECTION_OPT, 3308 style, flags, target); 3309 if (result != ISC_R_SUCCESS) 3310 return (result); 3311 3312 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, 3313 style, flags, target); 3314 if (result != ISC_R_SUCCESS) 3315 return (result); 3316 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, 3317 style, flags, target); 3318 if (result != ISC_R_SUCCESS) 3319 return (result); 3320 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, 3321 style, flags, target); 3322 if (result != ISC_R_SUCCESS) 3323 return (result); 3324 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, 3325 style, flags, target); 3326 if (result != ISC_R_SUCCESS) 3327 return (result); 3328 3329 result = dns_message_pseudosectiontotext(msg, 3330 DNS_PSEUDOSECTION_TSIG, 3331 style, flags, target); 3332 if (result != ISC_R_SUCCESS) 3333 return (result); 3334 3335 result = dns_message_pseudosectiontotext(msg, 3336 DNS_PSEUDOSECTION_SIG0, 3337 style, flags, target); 3338 if (result != ISC_R_SUCCESS) 3339 return (result); 3340 3341 return (ISC_R_SUCCESS); 3342} 3343 3344isc_region_t * 3345dns_message_getrawmessage(dns_message_t *msg) { 3346 REQUIRE(DNS_MESSAGE_VALID(msg)); 3347 return (&msg->saved); 3348} 3349 3350void 3351dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 3352 const void *order_arg) 3353{ 3354 REQUIRE(DNS_MESSAGE_VALID(msg)); 3355 msg->order = order; 3356 msg->order_arg = order_arg; 3357} 3358 3359void 3360dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 3361 REQUIRE(DNS_MESSAGE_VALID(msg)); 3362 msg->timeadjust = timeadjust; 3363} 3364 3365int 3366dns_message_gettimeadjust(dns_message_t *msg) { 3367 REQUIRE(DNS_MESSAGE_VALID(msg)); 3368 return (msg->timeadjust); 3369} 3370 3371isc_result_t 3372dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 3373 3374 REQUIRE(opcode < 16); 3375 3376 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) 3377 return (ISC_R_NOSPACE); 3378 isc_buffer_putstr(target, opcodetext[opcode]); 3379 return (ISC_R_SUCCESS); 3380} 3381