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