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