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