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