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