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