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