message.c revision 170222
1/* 2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and 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.10 2006/03/02 23:19:20 marka 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 1312 result = getrdata(source, msg, dctx, rdclass, 1313 rdtype, rdatalen, rdata); 1314 if (result != ISC_R_SUCCESS) 1315 goto cleanup; 1316 rdata->rdclass = rdclass; 1317 issigzero = ISC_FALSE; 1318 if (rdtype == dns_rdatatype_rrsig && 1319 rdata->flags == 0) { 1320 covers = dns_rdata_covers(rdata); 1321 if (covers == 0) 1322 DO_FORMERR; 1323 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1324 rdata->flags == 0) { 1325 covers = dns_rdata_covers(rdata); 1326 if (covers == 0) { 1327 if (sectionid != DNS_SECTION_ADDITIONAL || 1328 count != msg->counts[sectionid] - 1) 1329 DO_FORMERR; 1330 msg->sigstart = recstart; 1331 skip_name_search = ISC_TRUE; 1332 skip_type_search = ISC_TRUE; 1333 issigzero = ISC_TRUE; 1334 } 1335 } else 1336 covers = 0; 1337 1338 /* 1339 * If we are doing a dynamic update or this is a meta-type, 1340 * don't bother searching for a name, just append this one 1341 * to the end of the message. 1342 */ 1343 if (preserve_order || msg->opcode == dns_opcode_update || 1344 skip_name_search) { 1345 if (rdtype != dns_rdatatype_opt && 1346 rdtype != dns_rdatatype_tsig && 1347 !issigzero) 1348 { 1349 ISC_LIST_APPEND(*section, name, link); 1350 free_name = ISC_FALSE; 1351 } 1352 } else { 1353 /* 1354 * Run through the section, looking to see if this name 1355 * is already there. If it is found, put back the 1356 * allocated name since we no longer need it, and set 1357 * our name pointer to point to the name we found. 1358 */ 1359 result = findname(&name2, name, section); 1360 1361 /* 1362 * If it is a new name, append to the section. 1363 */ 1364 if (result == ISC_R_SUCCESS) { 1365 isc_mempool_put(msg->namepool, name); 1366 name = name2; 1367 } else { 1368 ISC_LIST_APPEND(*section, name, link); 1369 } 1370 free_name = ISC_FALSE; 1371 } 1372 1373 /* 1374 * Search name for the particular type and class. 1375 * Skip this stage if in update mode or this is a meta-type. 1376 */ 1377 if (preserve_order || msg->opcode == dns_opcode_update || 1378 skip_type_search) 1379 result = ISC_R_NOTFOUND; 1380 else { 1381 /* 1382 * If this is a type that can only occur in 1383 * the question section, fail. 1384 */ 1385 if (dns_rdatatype_questiononly(rdtype)) 1386 DO_FORMERR; 1387 1388 rdataset = NULL; 1389 result = dns_message_find(name, rdclass, rdtype, 1390 covers, &rdataset); 1391 } 1392 1393 /* 1394 * If we found an rdataset that matches, we need to 1395 * append this rdata to that set. If we did not, we need 1396 * to create a new rdatalist, store the important bits there, 1397 * convert it to an rdataset, and link the latter to the name. 1398 * Yuck. When appending, make certain that the type isn't 1399 * a singleton type, such as SOA or CNAME. 1400 * 1401 * Note that this check will be bypassed when preserving order, 1402 * the opcode is an update, or the type search is skipped. 1403 */ 1404 if (result == ISC_R_SUCCESS) { 1405 if (dns_rdatatype_issingleton(rdtype)) 1406 DO_FORMERR; 1407 } 1408 1409 if (result == ISC_R_NOTFOUND) { 1410 rdataset = isc_mempool_get(msg->rdspool); 1411 if (rdataset == NULL) { 1412 result = ISC_R_NOMEMORY; 1413 goto cleanup; 1414 } 1415 free_rdataset = ISC_TRUE; 1416 1417 rdatalist = newrdatalist(msg); 1418 if (rdatalist == NULL) { 1419 result = ISC_R_NOMEMORY; 1420 goto cleanup; 1421 } 1422 1423 rdatalist->type = rdtype; 1424 rdatalist->covers = covers; 1425 rdatalist->rdclass = rdclass; 1426 rdatalist->ttl = ttl; 1427 ISC_LIST_INIT(rdatalist->rdata); 1428 1429 dns_rdataset_init(rdataset); 1430 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, 1431 rdataset) 1432 == ISC_R_SUCCESS); 1433 1434 if (rdtype != dns_rdatatype_opt && 1435 rdtype != dns_rdatatype_tsig && 1436 !issigzero) 1437 { 1438 ISC_LIST_APPEND(name->list, rdataset, link); 1439 free_rdataset = ISC_FALSE; 1440 } 1441 } 1442 1443 /* 1444 * Minimize TTLs. 1445 * 1446 * Section 5.2 of RFC2181 says we should drop 1447 * nonauthoritative rrsets where the TTLs differ, but we 1448 * currently treat them the as if they were authoritative and 1449 * minimize them. 1450 */ 1451 if (ttl != rdataset->ttl) { 1452 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1453 if (ttl < rdataset->ttl) 1454 rdataset->ttl = ttl; 1455 } 1456 1457 /* 1458 * XXXMLG Perform a totally ugly hack here to pull 1459 * the rdatalist out of the private field in the rdataset, 1460 * and append this rdata to the rdatalist's linked list 1461 * of rdata. 1462 */ 1463 rdatalist = (dns_rdatalist_t *)(rdataset->private1); 1464 1465 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1466 1467 /* 1468 * If this is an OPT record, remember it. Also, set 1469 * the extended rcode. Note that msg->opt will only be set 1470 * if best-effort parsing is enabled. 1471 */ 1472 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { 1473 dns_rcode_t ercode; 1474 1475 msg->opt = rdataset; 1476 rdataset = NULL; 1477 free_rdataset = ISC_FALSE; 1478 ercode = (dns_rcode_t) 1479 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) 1480 >> 20); 1481 msg->rcode |= ercode; 1482 isc_mempool_put(msg->namepool, name); 1483 free_name = ISC_FALSE; 1484 } 1485 1486 /* 1487 * If this is an SIG(0) or TSIG record, remember it. Note 1488 * that msg->sig0 or msg->tsig will only be set if best-effort 1489 * parsing is enabled. 1490 */ 1491 if (issigzero && msg->sig0 == NULL) { 1492 msg->sig0 = rdataset; 1493 msg->sig0name = name; 1494 rdataset = NULL; 1495 free_rdataset = ISC_FALSE; 1496 free_name = ISC_FALSE; 1497 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) { 1498 msg->tsig = rdataset; 1499 msg->tsigname = name; 1500 rdataset = NULL; 1501 free_rdataset = ISC_FALSE; 1502 free_name = ISC_FALSE; 1503 } 1504 1505 if (seen_problem) { 1506 if (free_name) 1507 isc_mempool_put(msg->namepool, name); 1508 if (free_rdataset) 1509 isc_mempool_put(msg->rdspool, rdataset); 1510 free_name = free_rdataset = ISC_FALSE; 1511 } 1512 INSIST(free_name == ISC_FALSE); 1513 INSIST(free_rdataset == ISC_FALSE); 1514 } 1515 1516 if (seen_problem) 1517 return (DNS_R_RECOVERABLE); 1518 return (ISC_R_SUCCESS); 1519 1520 cleanup: 1521 if (free_name) 1522 isc_mempool_put(msg->namepool, name); 1523 if (free_rdataset) 1524 isc_mempool_put(msg->rdspool, rdataset); 1525 1526 return (result); 1527} 1528 1529isc_result_t 1530dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1531 unsigned int options) 1532{ 1533 isc_region_t r; 1534 dns_decompress_t dctx; 1535 isc_result_t ret; 1536 isc_uint16_t tmpflags; 1537 isc_buffer_t origsource; 1538 isc_boolean_t seen_problem; 1539 isc_boolean_t ignore_tc; 1540 1541 REQUIRE(DNS_MESSAGE_VALID(msg)); 1542 REQUIRE(source != NULL); 1543 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1544 1545 seen_problem = ISC_FALSE; 1546 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); 1547 1548 origsource = *source; 1549 1550 msg->header_ok = 0; 1551 msg->question_ok = 0; 1552 1553 isc_buffer_remainingregion(source, &r); 1554 if (r.length < DNS_MESSAGE_HEADERLEN) 1555 return (ISC_R_UNEXPECTEDEND); 1556 1557 msg->id = isc_buffer_getuint16(source); 1558 tmpflags = isc_buffer_getuint16(source); 1559 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1560 >> DNS_MESSAGE_OPCODE_SHIFT); 1561 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1562 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1563 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1564 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1565 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1566 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1567 1568 msg->header_ok = 1; 1569 1570 /* 1571 * -1 means no EDNS. 1572 */ 1573 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1574 1575 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1576 1577 ret = getquestions(source, msg, &dctx, options); 1578 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1579 goto truncated; 1580 if (ret == DNS_R_RECOVERABLE) { 1581 seen_problem = ISC_TRUE; 1582 ret = ISC_R_SUCCESS; 1583 } 1584 if (ret != ISC_R_SUCCESS) 1585 return (ret); 1586 msg->question_ok = 1; 1587 1588 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1589 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1590 goto truncated; 1591 if (ret == DNS_R_RECOVERABLE) { 1592 seen_problem = ISC_TRUE; 1593 ret = ISC_R_SUCCESS; 1594 } 1595 if (ret != ISC_R_SUCCESS) 1596 return (ret); 1597 1598 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1599 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1600 goto truncated; 1601 if (ret == DNS_R_RECOVERABLE) { 1602 seen_problem = ISC_TRUE; 1603 ret = ISC_R_SUCCESS; 1604 } 1605 if (ret != ISC_R_SUCCESS) 1606 return (ret); 1607 1608 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1609 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1610 goto truncated; 1611 if (ret == DNS_R_RECOVERABLE) { 1612 seen_problem = ISC_TRUE; 1613 ret = ISC_R_SUCCESS; 1614 } 1615 if (ret != ISC_R_SUCCESS) 1616 return (ret); 1617 1618 isc_buffer_remainingregion(source, &r); 1619 if (r.length != 0) { 1620 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1621 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1622 "message has %u byte(s) of trailing garbage", 1623 r.length); 1624 } 1625 1626 truncated: 1627 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) 1628 isc_buffer_usedregion(&origsource, &msg->saved); 1629 else { 1630 msg->saved.length = isc_buffer_usedlength(&origsource); 1631 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1632 if (msg->saved.base == NULL) 1633 return (ISC_R_NOMEMORY); 1634 memcpy(msg->saved.base, isc_buffer_base(&origsource), 1635 msg->saved.length); 1636 msg->free_saved = 1; 1637 } 1638 1639 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1640 return (DNS_R_RECOVERABLE); 1641 if (seen_problem == ISC_TRUE) 1642 return (DNS_R_RECOVERABLE); 1643 return (ISC_R_SUCCESS); 1644} 1645 1646isc_result_t 1647dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1648 isc_buffer_t *buffer) 1649{ 1650 isc_region_t r; 1651 1652 REQUIRE(DNS_MESSAGE_VALID(msg)); 1653 REQUIRE(buffer != NULL); 1654 REQUIRE(msg->buffer == NULL); 1655 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1656 1657 msg->cctx = cctx; 1658 1659 /* 1660 * Erase the contents of this buffer. 1661 */ 1662 isc_buffer_clear(buffer); 1663 1664 /* 1665 * Make certain there is enough for at least the header in this 1666 * buffer. 1667 */ 1668 isc_buffer_availableregion(buffer, &r); 1669 if (r.length < DNS_MESSAGE_HEADERLEN) 1670 return (ISC_R_NOSPACE); 1671 1672 if (r.length < msg->reserved) 1673 return (ISC_R_NOSPACE); 1674 1675 /* 1676 * Reserve enough space for the header in this buffer. 1677 */ 1678 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1679 1680 msg->buffer = buffer; 1681 1682 return (ISC_R_SUCCESS); 1683} 1684 1685isc_result_t 1686dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1687 isc_region_t r, rn; 1688 1689 REQUIRE(DNS_MESSAGE_VALID(msg)); 1690 REQUIRE(buffer != NULL); 1691 REQUIRE(msg->buffer != NULL); 1692 1693 /* 1694 * Ensure that the new buffer is empty, and has enough space to 1695 * hold the current contents. 1696 */ 1697 isc_buffer_clear(buffer); 1698 1699 isc_buffer_availableregion(buffer, &rn); 1700 isc_buffer_usedregion(msg->buffer, &r); 1701 REQUIRE(rn.length > r.length); 1702 1703 /* 1704 * Copy the contents from the old to the new buffer. 1705 */ 1706 isc_buffer_add(buffer, r.length); 1707 memcpy(rn.base, r.base, r.length); 1708 1709 msg->buffer = buffer; 1710 1711 return (ISC_R_SUCCESS); 1712} 1713 1714void 1715dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1716 REQUIRE(DNS_MESSAGE_VALID(msg)); 1717 REQUIRE(space <= msg->reserved); 1718 1719 msg->reserved -= space; 1720} 1721 1722isc_result_t 1723dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1724 isc_region_t r; 1725 1726 REQUIRE(DNS_MESSAGE_VALID(msg)); 1727 1728 if (msg->buffer != NULL) { 1729 isc_buffer_availableregion(msg->buffer, &r); 1730 if (r.length < (space + msg->reserved)) 1731 return (ISC_R_NOSPACE); 1732 } 1733 1734 msg->reserved += space; 1735 1736 return (ISC_R_SUCCESS); 1737} 1738 1739static inline isc_boolean_t 1740wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1741 int pass_needed; 1742 1743 /* 1744 * If we are not rendering class IN, this ordering is bogus. 1745 */ 1746 if (rds->rdclass != dns_rdataclass_in) 1747 return (ISC_FALSE); 1748 1749 switch (rds->type) { 1750 case dns_rdatatype_a: 1751 case dns_rdatatype_aaaa: 1752 if (preferred_glue == rds->type) 1753 pass_needed = 4; 1754 else 1755 pass_needed = 3; 1756 break; 1757 case dns_rdatatype_rrsig: 1758 case dns_rdatatype_dnskey: 1759 pass_needed = 2; 1760 break; 1761 default: 1762 pass_needed = 1; 1763 } 1764 1765 if (pass_needed >= pass) 1766 return (ISC_FALSE); 1767 1768 return (ISC_TRUE); 1769} 1770 1771isc_result_t 1772dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1773 unsigned int options) 1774{ 1775 dns_namelist_t *section; 1776 dns_name_t *name, *next_name; 1777 dns_rdataset_t *rdataset, *next_rdataset; 1778 unsigned int count, total; 1779 isc_result_t result; 1780 isc_buffer_t st; /* for rollbacks */ 1781 int pass; 1782 isc_boolean_t partial = ISC_FALSE; 1783 unsigned int rd_options; 1784 dns_rdatatype_t preferred_glue = 0; 1785 1786 REQUIRE(DNS_MESSAGE_VALID(msg)); 1787 REQUIRE(msg->buffer != NULL); 1788 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1789 1790 section = &msg->sections[sectionid]; 1791 1792 if ((sectionid == DNS_SECTION_ADDITIONAL) 1793 && (options & DNS_MESSAGERENDER_ORDERED) == 0) { 1794 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1795 preferred_glue = dns_rdatatype_a; 1796 pass = 4; 1797 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1798 preferred_glue = dns_rdatatype_aaaa; 1799 pass = 4; 1800 } else 1801 pass = 3; 1802 } else 1803 pass = 1; 1804 1805 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) 1806 rd_options = 0; 1807 else 1808 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1809 1810 /* 1811 * Shrink the space in the buffer by the reserved amount. 1812 */ 1813 msg->buffer->length -= msg->reserved; 1814 1815 total = 0; 1816 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) 1817 partial = ISC_TRUE; 1818 1819 /* 1820 * Render required glue first. Set TC if it won't fit. 1821 */ 1822 name = ISC_LIST_HEAD(*section); 1823 if (name != NULL) { 1824 rdataset = ISC_LIST_HEAD(name->list); 1825 if (rdataset != NULL && 1826 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && 1827 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { 1828 const void *order_arg = msg->order_arg; 1829 st = *(msg->buffer); 1830 count = 0; 1831 if (partial) 1832 result = dns_rdataset_towirepartial(rdataset, 1833 name, 1834 msg->cctx, 1835 msg->buffer, 1836 msg->order, 1837 order_arg, 1838 rd_options, 1839 &count, 1840 NULL); 1841 else 1842 result = dns_rdataset_towiresorted(rdataset, 1843 name, 1844 msg->cctx, 1845 msg->buffer, 1846 msg->order, 1847 order_arg, 1848 rd_options, 1849 &count); 1850 total += count; 1851 if (partial && result == ISC_R_NOSPACE) { 1852 msg->flags |= DNS_MESSAGEFLAG_TC; 1853 msg->buffer->length += msg->reserved; 1854 msg->counts[sectionid] += total; 1855 return (result); 1856 } 1857 if (result != ISC_R_SUCCESS) { 1858 INSIST(st.used < 65536); 1859 dns_compress_rollback(msg->cctx, 1860 (isc_uint16_t)st.used); 1861 *(msg->buffer) = st; /* rollback */ 1862 msg->buffer->length += msg->reserved; 1863 msg->counts[sectionid] += total; 1864 return (result); 1865 } 1866 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 1867 } 1868 } 1869 1870 do { 1871 name = ISC_LIST_HEAD(*section); 1872 if (name == NULL) { 1873 msg->buffer->length += msg->reserved; 1874 msg->counts[sectionid] += total; 1875 return (ISC_R_SUCCESS); 1876 } 1877 1878 while (name != NULL) { 1879 next_name = ISC_LIST_NEXT(name, link); 1880 1881 rdataset = ISC_LIST_HEAD(name->list); 1882 while (rdataset != NULL) { 1883 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1884 1885 if ((rdataset->attributes & 1886 DNS_RDATASETATTR_RENDERED) != 0) 1887 goto next; 1888 1889 if (((options & DNS_MESSAGERENDER_ORDERED) 1890 == 0) 1891 && (sectionid == DNS_SECTION_ADDITIONAL) 1892 && wrong_priority(rdataset, pass, 1893 preferred_glue)) 1894 goto next; 1895 1896 st = *(msg->buffer); 1897 1898 count = 0; 1899 if (partial) 1900 result = dns_rdataset_towirepartial( 1901 rdataset, 1902 name, 1903 msg->cctx, 1904 msg->buffer, 1905 msg->order, 1906 msg->order_arg, 1907 rd_options, 1908 &count, 1909 NULL); 1910 else 1911 result = dns_rdataset_towiresorted( 1912 rdataset, 1913 name, 1914 msg->cctx, 1915 msg->buffer, 1916 msg->order, 1917 msg->order_arg, 1918 rd_options, 1919 &count); 1920 1921 total += count; 1922 1923 /* 1924 * If out of space, record stats on what we 1925 * rendered so far, and return that status. 1926 * 1927 * XXXMLG Need to change this when 1928 * dns_rdataset_towire() can render partial 1929 * sets starting at some arbitary point in the 1930 * set. This will include setting a bit in the 1931 * rdataset to indicate that a partial 1932 * rendering was done, and some state saved 1933 * somewhere (probably in the message struct) 1934 * to indicate where to continue from. 1935 */ 1936 if (partial && result == ISC_R_NOSPACE) { 1937 msg->buffer->length += msg->reserved; 1938 msg->counts[sectionid] += total; 1939 return (result); 1940 } 1941 if (result != ISC_R_SUCCESS) { 1942 INSIST(st.used < 65536); 1943 dns_compress_rollback(msg->cctx, 1944 (isc_uint16_t)st.used); 1945 *(msg->buffer) = st; /* rollback */ 1946 msg->buffer->length += msg->reserved; 1947 msg->counts[sectionid] += total; 1948 return (result); 1949 } 1950 1951 /* 1952 * If we have rendered non-validated data, 1953 * ensure that the AD bit is not set. 1954 */ 1955 if (rdataset->trust != dns_trust_secure && 1956 (sectionid == DNS_SECTION_ANSWER || 1957 sectionid == DNS_SECTION_AUTHORITY)) 1958 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1959 1960 rdataset->attributes |= 1961 DNS_RDATASETATTR_RENDERED; 1962 1963 next: 1964 rdataset = next_rdataset; 1965 } 1966 1967 name = next_name; 1968 } 1969 } while (--pass != 0); 1970 1971 msg->buffer->length += msg->reserved; 1972 msg->counts[sectionid] += total; 1973 1974 return (ISC_R_SUCCESS); 1975} 1976 1977void 1978dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 1979 isc_uint16_t tmp; 1980 isc_region_t r; 1981 1982 REQUIRE(DNS_MESSAGE_VALID(msg)); 1983 REQUIRE(target != NULL); 1984 1985 isc_buffer_availableregion(target, &r); 1986 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 1987 1988 isc_buffer_putuint16(target, msg->id); 1989 1990 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 1991 & DNS_MESSAGE_OPCODE_MASK); 1992 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 1993 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 1994 1995 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 1996 msg->counts[DNS_SECTION_ANSWER] < 65536 && 1997 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 1998 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 1999 2000 isc_buffer_putuint16(target, tmp); 2001 isc_buffer_putuint16(target, 2002 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2003 isc_buffer_putuint16(target, 2004 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2005 isc_buffer_putuint16(target, 2006 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2007 isc_buffer_putuint16(target, 2008 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2009} 2010 2011isc_result_t 2012dns_message_renderend(dns_message_t *msg) { 2013 isc_buffer_t tmpbuf; 2014 isc_region_t r; 2015 int result; 2016 unsigned int count; 2017 2018 REQUIRE(DNS_MESSAGE_VALID(msg)); 2019 REQUIRE(msg->buffer != NULL); 2020 2021 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2022 /* 2023 * We have an extended rcode but are not using EDNS. 2024 */ 2025 return (DNS_R_FORMERR); 2026 } 2027 2028 /* 2029 * If we've got an OPT record, render it. 2030 */ 2031 if (msg->opt != NULL) { 2032 dns_message_renderrelease(msg, msg->opt_reserved); 2033 msg->opt_reserved = 0; 2034 /* 2035 * Set the extended rcode. 2036 */ 2037 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2038 msg->opt->ttl |= ((msg->rcode << 20) & 2039 DNS_MESSAGE_EDNSRCODE_MASK); 2040 /* 2041 * Render. 2042 */ 2043 count = 0; 2044 result = dns_rdataset_towire(msg->opt, dns_rootname, 2045 msg->cctx, msg->buffer, 0, 2046 &count); 2047 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2048 if (result != ISC_R_SUCCESS) 2049 return (result); 2050 } 2051 2052 /* 2053 * If we're adding a TSIG or SIG(0) to a truncated message, 2054 * clear all rdatasets from the message except for the question 2055 * before adding the TSIG or SIG(0). If the question doesn't fit, 2056 * don't include it. 2057 */ 2058 if ((msg->tsigkey != NULL || msg->sig0key != NULL) && 2059 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2060 { 2061 isc_buffer_t *buf; 2062 2063 msgresetnames(msg, DNS_SECTION_ANSWER); 2064 buf = msg->buffer; 2065 dns_message_renderreset(msg); 2066 msg->buffer = buf; 2067 isc_buffer_clear(msg->buffer); 2068 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2069 dns_compress_rollback(msg->cctx, 0); 2070 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2071 0); 2072 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 2073 return (result); 2074 } 2075 2076 /* 2077 * If we're adding a TSIG record, generate and render it. 2078 */ 2079 if (msg->tsigkey != NULL) { 2080 dns_message_renderrelease(msg, msg->sig_reserved); 2081 msg->sig_reserved = 0; 2082 result = dns_tsig_sign(msg); 2083 if (result != ISC_R_SUCCESS) 2084 return (result); 2085 count = 0; 2086 result = dns_rdataset_towire(msg->tsig, msg->tsigname, 2087 msg->cctx, msg->buffer, 0, 2088 &count); 2089 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2090 if (result != ISC_R_SUCCESS) 2091 return (result); 2092 } 2093 2094 /* 2095 * If we're adding a SIG(0) record, generate and render it. 2096 */ 2097 if (msg->sig0key != NULL) { 2098 dns_message_renderrelease(msg, msg->sig_reserved); 2099 msg->sig_reserved = 0; 2100 result = dns_dnssec_signmessage(msg, msg->sig0key); 2101 if (result != ISC_R_SUCCESS) 2102 return (result); 2103 count = 0; 2104 /* 2105 * Note: dns_rootname is used here, not msg->sig0name, since 2106 * the owner name of a SIG(0) is irrelevant, and will not 2107 * be set in a message being rendered. 2108 */ 2109 result = dns_rdataset_towire(msg->sig0, dns_rootname, 2110 msg->cctx, msg->buffer, 0, 2111 &count); 2112 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2113 if (result != ISC_R_SUCCESS) 2114 return (result); 2115 } 2116 2117 isc_buffer_usedregion(msg->buffer, &r); 2118 isc_buffer_init(&tmpbuf, r.base, r.length); 2119 2120 dns_message_renderheader(msg, &tmpbuf); 2121 2122 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2123 2124 return (ISC_R_SUCCESS); 2125} 2126 2127void 2128dns_message_renderreset(dns_message_t *msg) { 2129 unsigned int i; 2130 dns_name_t *name; 2131 dns_rdataset_t *rds; 2132 2133 /* 2134 * Reset the message so that it may be rendered again. 2135 */ 2136 2137 REQUIRE(DNS_MESSAGE_VALID(msg)); 2138 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2139 2140 msg->buffer = NULL; 2141 2142 for (i = 0; i < DNS_SECTION_MAX; i++) { 2143 msg->cursors[i] = NULL; 2144 msg->counts[i] = 0; 2145 for (name = ISC_LIST_HEAD(msg->sections[i]); 2146 name != NULL; 2147 name = ISC_LIST_NEXT(name, link)) { 2148 for (rds = ISC_LIST_HEAD(name->list); 2149 rds != NULL; 2150 rds = ISC_LIST_NEXT(rds, link)) { 2151 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2152 } 2153 } 2154 } 2155 if (msg->tsigname != NULL) 2156 dns_message_puttempname(msg, &msg->tsigname); 2157 if (msg->tsig != NULL) { 2158 dns_rdataset_disassociate(msg->tsig); 2159 dns_message_puttemprdataset(msg, &msg->tsig); 2160 } 2161 if (msg->sig0 != NULL) { 2162 dns_rdataset_disassociate(msg->sig0); 2163 dns_message_puttemprdataset(msg, &msg->sig0); 2164 } 2165} 2166 2167isc_result_t 2168dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2169 REQUIRE(DNS_MESSAGE_VALID(msg)); 2170 REQUIRE(VALID_NAMED_SECTION(section)); 2171 2172 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2173 2174 if (msg->cursors[section] == NULL) 2175 return (ISC_R_NOMORE); 2176 2177 return (ISC_R_SUCCESS); 2178} 2179 2180isc_result_t 2181dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2182 REQUIRE(DNS_MESSAGE_VALID(msg)); 2183 REQUIRE(VALID_NAMED_SECTION(section)); 2184 REQUIRE(msg->cursors[section] != NULL); 2185 2186 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2187 2188 if (msg->cursors[section] == NULL) 2189 return (ISC_R_NOMORE); 2190 2191 return (ISC_R_SUCCESS); 2192} 2193 2194void 2195dns_message_currentname(dns_message_t *msg, dns_section_t section, 2196 dns_name_t **name) 2197{ 2198 REQUIRE(DNS_MESSAGE_VALID(msg)); 2199 REQUIRE(VALID_NAMED_SECTION(section)); 2200 REQUIRE(name != NULL && *name == NULL); 2201 REQUIRE(msg->cursors[section] != NULL); 2202 2203 *name = msg->cursors[section]; 2204} 2205 2206isc_result_t 2207dns_message_findname(dns_message_t *msg, dns_section_t section, 2208 dns_name_t *target, dns_rdatatype_t type, 2209 dns_rdatatype_t covers, dns_name_t **name, 2210 dns_rdataset_t **rdataset) 2211{ 2212 dns_name_t *foundname; 2213 isc_result_t result; 2214 2215 /* 2216 * XXX These requirements are probably too intensive, especially 2217 * where things can be NULL, but as they are they ensure that if 2218 * something is NON-NULL, indicating that the caller expects it 2219 * to be filled in, that we can in fact fill it in. 2220 */ 2221 REQUIRE(msg != NULL); 2222 REQUIRE(VALID_SECTION(section)); 2223 REQUIRE(target != NULL); 2224 if (name != NULL) 2225 REQUIRE(*name == NULL); 2226 if (type == dns_rdatatype_any) { 2227 REQUIRE(rdataset == NULL); 2228 } else { 2229 if (rdataset != NULL) 2230 REQUIRE(*rdataset == NULL); 2231 } 2232 2233 result = findname(&foundname, target, 2234 &msg->sections[section]); 2235 2236 if (result == ISC_R_NOTFOUND) 2237 return (DNS_R_NXDOMAIN); 2238 else if (result != ISC_R_SUCCESS) 2239 return (result); 2240 2241 if (name != NULL) 2242 *name = foundname; 2243 2244 /* 2245 * And now look for the type. 2246 */ 2247 if (type == dns_rdatatype_any) 2248 return (ISC_R_SUCCESS); 2249 2250 result = dns_message_findtype(foundname, type, covers, rdataset); 2251 if (result == ISC_R_NOTFOUND) 2252 return (DNS_R_NXRRSET); 2253 2254 return (result); 2255} 2256 2257void 2258dns_message_movename(dns_message_t *msg, dns_name_t *name, 2259 dns_section_t fromsection, 2260 dns_section_t tosection) 2261{ 2262 REQUIRE(msg != NULL); 2263 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2264 REQUIRE(name != NULL); 2265 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2266 REQUIRE(VALID_NAMED_SECTION(tosection)); 2267 2268 /* 2269 * Unlink the name from the old section 2270 */ 2271 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2272 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2273} 2274 2275void 2276dns_message_addname(dns_message_t *msg, dns_name_t *name, 2277 dns_section_t section) 2278{ 2279 REQUIRE(msg != NULL); 2280 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2281 REQUIRE(name != NULL); 2282 REQUIRE(VALID_NAMED_SECTION(section)); 2283 2284 ISC_LIST_APPEND(msg->sections[section], name, link); 2285} 2286 2287void 2288dns_message_removename(dns_message_t *msg, dns_name_t *name, 2289 dns_section_t section) 2290{ 2291 REQUIRE(msg != NULL); 2292 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2293 REQUIRE(name != NULL); 2294 REQUIRE(VALID_NAMED_SECTION(section)); 2295 2296 ISC_LIST_UNLINK(msg->sections[section], name, link); 2297} 2298 2299isc_result_t 2300dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2301 REQUIRE(DNS_MESSAGE_VALID(msg)); 2302 REQUIRE(item != NULL && *item == NULL); 2303 2304 *item = isc_mempool_get(msg->namepool); 2305 if (*item == NULL) 2306 return (ISC_R_NOMEMORY); 2307 dns_name_init(*item, NULL); 2308 2309 return (ISC_R_SUCCESS); 2310} 2311 2312isc_result_t 2313dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { 2314 REQUIRE(DNS_MESSAGE_VALID(msg)); 2315 REQUIRE(item != NULL && *item == NULL); 2316 2317 *item = newoffsets(msg); 2318 if (*item == NULL) 2319 return (ISC_R_NOMEMORY); 2320 2321 return (ISC_R_SUCCESS); 2322} 2323 2324isc_result_t 2325dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2326 REQUIRE(DNS_MESSAGE_VALID(msg)); 2327 REQUIRE(item != NULL && *item == NULL); 2328 2329 *item = newrdata(msg); 2330 if (*item == NULL) 2331 return (ISC_R_NOMEMORY); 2332 2333 return (ISC_R_SUCCESS); 2334} 2335 2336isc_result_t 2337dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2338 REQUIRE(DNS_MESSAGE_VALID(msg)); 2339 REQUIRE(item != NULL && *item == NULL); 2340 2341 *item = isc_mempool_get(msg->rdspool); 2342 if (*item == NULL) 2343 return (ISC_R_NOMEMORY); 2344 2345 dns_rdataset_init(*item); 2346 2347 return (ISC_R_SUCCESS); 2348} 2349 2350isc_result_t 2351dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2352 REQUIRE(DNS_MESSAGE_VALID(msg)); 2353 REQUIRE(item != NULL && *item == NULL); 2354 2355 *item = newrdatalist(msg); 2356 if (*item == NULL) 2357 return (ISC_R_NOMEMORY); 2358 2359 return (ISC_R_SUCCESS); 2360} 2361 2362void 2363dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2364 REQUIRE(DNS_MESSAGE_VALID(msg)); 2365 REQUIRE(item != NULL && *item != NULL); 2366 2367 if (dns_name_dynamic(*item)) 2368 dns_name_free(*item, msg->mctx); 2369 isc_mempool_put(msg->namepool, *item); 2370 *item = NULL; 2371} 2372 2373void 2374dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2375 REQUIRE(DNS_MESSAGE_VALID(msg)); 2376 REQUIRE(item != NULL && *item != NULL); 2377 2378 releaserdata(msg, *item); 2379 *item = NULL; 2380} 2381 2382void 2383dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2384 REQUIRE(DNS_MESSAGE_VALID(msg)); 2385 REQUIRE(item != NULL && *item != NULL); 2386 2387 REQUIRE(!dns_rdataset_isassociated(*item)); 2388 isc_mempool_put(msg->rdspool, *item); 2389 *item = NULL; 2390} 2391 2392void 2393dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2394 REQUIRE(DNS_MESSAGE_VALID(msg)); 2395 REQUIRE(item != NULL && *item != NULL); 2396 2397 releaserdatalist(msg, *item); 2398 *item = NULL; 2399} 2400 2401isc_result_t 2402dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2403 unsigned int *flagsp) 2404{ 2405 isc_region_t r; 2406 isc_buffer_t buffer; 2407 dns_messageid_t id; 2408 unsigned int flags; 2409 2410 REQUIRE(source != NULL); 2411 2412 buffer = *source; 2413 2414 isc_buffer_remainingregion(&buffer, &r); 2415 if (r.length < DNS_MESSAGE_HEADERLEN) 2416 return (ISC_R_UNEXPECTEDEND); 2417 2418 id = isc_buffer_getuint16(&buffer); 2419 flags = isc_buffer_getuint16(&buffer); 2420 flags &= DNS_MESSAGE_FLAG_MASK; 2421 2422 if (flagsp != NULL) 2423 *flagsp = flags; 2424 if (idp != NULL) 2425 *idp = id; 2426 2427 return (ISC_R_SUCCESS); 2428} 2429 2430isc_result_t 2431dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { 2432 unsigned int first_section; 2433 isc_result_t result; 2434 2435 REQUIRE(DNS_MESSAGE_VALID(msg)); 2436 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2437 2438 if (!msg->header_ok) 2439 return (DNS_R_FORMERR); 2440 if (msg->opcode != dns_opcode_query && 2441 msg->opcode != dns_opcode_notify) 2442 want_question_section = ISC_FALSE; 2443 if (want_question_section) { 2444 if (!msg->question_ok) 2445 return (DNS_R_FORMERR); 2446 first_section = DNS_SECTION_ANSWER; 2447 } else 2448 first_section = DNS_SECTION_QUESTION; 2449 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2450 msgresetnames(msg, first_section); 2451 msgresetopt(msg); 2452 msgresetsigs(msg, ISC_TRUE); 2453 msginitprivate(msg); 2454 /* 2455 * We now clear most flags and then set QR, ensuring that the 2456 * reply's flags will be in a reasonable state. 2457 */ 2458 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2459 msg->flags |= DNS_MESSAGEFLAG_QR; 2460 2461 /* 2462 * This saves the query TSIG status, if the query was signed, and 2463 * reserves space in the reply for the TSIG. 2464 */ 2465 if (msg->tsigkey != NULL) { 2466 unsigned int otherlen = 0; 2467 msg->querytsigstatus = msg->tsigstatus; 2468 msg->tsigstatus = dns_rcode_noerror; 2469 if (msg->querytsigstatus == dns_tsigerror_badtime) 2470 otherlen = 6; 2471 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2472 result = dns_message_renderreserve(msg, msg->sig_reserved); 2473 if (result != ISC_R_SUCCESS) { 2474 msg->sig_reserved = 0; 2475 return (result); 2476 } 2477 } 2478 if (msg->saved.base != NULL) { 2479 msg->query.base = msg->saved.base; 2480 msg->query.length = msg->saved.length; 2481 msg->free_query = msg->free_saved; 2482 msg->saved.base = NULL; 2483 msg->saved.length = 0; 2484 msg->free_saved = 0; 2485 } 2486 2487 return (ISC_R_SUCCESS); 2488} 2489 2490dns_rdataset_t * 2491dns_message_getopt(dns_message_t *msg) { 2492 2493 /* 2494 * Get the OPT record for 'msg'. 2495 */ 2496 2497 REQUIRE(DNS_MESSAGE_VALID(msg)); 2498 2499 return (msg->opt); 2500} 2501 2502isc_result_t 2503dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2504 isc_result_t result; 2505 dns_rdata_t rdata = DNS_RDATA_INIT; 2506 2507 /* 2508 * Set the OPT record for 'msg'. 2509 */ 2510 2511 /* 2512 * The space required for an OPT record is: 2513 * 2514 * 1 byte for the name 2515 * 2 bytes for the type 2516 * 2 bytes for the class 2517 * 4 bytes for the ttl 2518 * 2 bytes for the rdata length 2519 * --------------------------------- 2520 * 11 bytes 2521 * 2522 * plus the length of the rdata. 2523 */ 2524 2525 REQUIRE(DNS_MESSAGE_VALID(msg)); 2526 REQUIRE(opt->type == dns_rdatatype_opt); 2527 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2528 REQUIRE(msg->state == DNS_SECTION_ANY); 2529 2530 msgresetopt(msg); 2531 2532 result = dns_rdataset_first(opt); 2533 if (result != ISC_R_SUCCESS) 2534 goto cleanup; 2535 dns_rdataset_current(opt, &rdata); 2536 msg->opt_reserved = 11 + rdata.length; 2537 result = dns_message_renderreserve(msg, msg->opt_reserved); 2538 if (result != ISC_R_SUCCESS) { 2539 msg->opt_reserved = 0; 2540 goto cleanup; 2541 } 2542 2543 msg->opt = opt; 2544 2545 return (ISC_R_SUCCESS); 2546 2547 cleanup: 2548 dns_message_puttemprdataset(msg, &opt); 2549 return (result); 2550 2551} 2552 2553dns_rdataset_t * 2554dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2555 2556 /* 2557 * Get the TSIG record and owner for 'msg'. 2558 */ 2559 2560 REQUIRE(DNS_MESSAGE_VALID(msg)); 2561 REQUIRE(owner == NULL || *owner == NULL); 2562 2563 if (owner != NULL) 2564 *owner = msg->tsigname; 2565 return (msg->tsig); 2566} 2567 2568isc_result_t 2569dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2570 isc_result_t result; 2571 2572 /* 2573 * Set the TSIG key for 'msg' 2574 */ 2575 2576 REQUIRE(DNS_MESSAGE_VALID(msg)); 2577 REQUIRE(msg->state == DNS_SECTION_ANY); 2578 2579 if (key == NULL && msg->tsigkey != NULL) { 2580 if (msg->sig_reserved != 0) { 2581 dns_message_renderrelease(msg, msg->sig_reserved); 2582 msg->sig_reserved = 0; 2583 } 2584 dns_tsigkey_detach(&msg->tsigkey); 2585 } 2586 if (key != NULL) { 2587 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2588 dns_tsigkey_attach(key, &msg->tsigkey); 2589 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2590 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2591 result = dns_message_renderreserve(msg, 2592 msg->sig_reserved); 2593 if (result != ISC_R_SUCCESS) { 2594 dns_tsigkey_detach(&msg->tsigkey); 2595 msg->sig_reserved = 0; 2596 return (result); 2597 } 2598 } 2599 } 2600 return (ISC_R_SUCCESS); 2601} 2602 2603dns_tsigkey_t * 2604dns_message_gettsigkey(dns_message_t *msg) { 2605 2606 /* 2607 * Get the TSIG key for 'msg' 2608 */ 2609 2610 REQUIRE(DNS_MESSAGE_VALID(msg)); 2611 2612 return (msg->tsigkey); 2613} 2614 2615isc_result_t 2616dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2617 dns_rdata_t *rdata = NULL; 2618 dns_rdatalist_t *list = NULL; 2619 dns_rdataset_t *set = NULL; 2620 isc_buffer_t *buf = NULL; 2621 isc_region_t r; 2622 isc_result_t result; 2623 2624 REQUIRE(DNS_MESSAGE_VALID(msg)); 2625 REQUIRE(msg->querytsig == NULL); 2626 2627 if (querytsig == NULL) 2628 return (ISC_R_SUCCESS); 2629 2630 result = dns_message_gettemprdata(msg, &rdata); 2631 if (result != ISC_R_SUCCESS) 2632 goto cleanup; 2633 2634 result = dns_message_gettemprdatalist(msg, &list); 2635 if (result != ISC_R_SUCCESS) 2636 goto cleanup; 2637 result = dns_message_gettemprdataset(msg, &set); 2638 if (result != ISC_R_SUCCESS) 2639 goto cleanup; 2640 2641 isc_buffer_usedregion(querytsig, &r); 2642 result = isc_buffer_allocate(msg->mctx, &buf, r.length); 2643 if (result != ISC_R_SUCCESS) 2644 goto cleanup; 2645 isc_buffer_putmem(buf, r.base, r.length); 2646 isc_buffer_usedregion(buf, &r); 2647 dns_rdata_init(rdata); 2648 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2649 dns_message_takebuffer(msg, &buf); 2650 ISC_LIST_INIT(list->rdata); 2651 ISC_LIST_APPEND(list->rdata, rdata, link); 2652 result = dns_rdatalist_tordataset(list, set); 2653 if (result != ISC_R_SUCCESS) 2654 goto cleanup; 2655 2656 msg->querytsig = set; 2657 2658 return (result); 2659 2660 cleanup: 2661 if (rdata != NULL) 2662 dns_message_puttemprdata(msg, &rdata); 2663 if (list != NULL) 2664 dns_message_puttemprdatalist(msg, &list); 2665 if (set != NULL) 2666 dns_message_puttemprdataset(msg, &set); 2667 return (ISC_R_NOMEMORY); 2668} 2669 2670isc_result_t 2671dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2672 isc_buffer_t **querytsig) { 2673 isc_result_t result; 2674 dns_rdata_t rdata = DNS_RDATA_INIT; 2675 isc_region_t r; 2676 2677 REQUIRE(DNS_MESSAGE_VALID(msg)); 2678 REQUIRE(mctx != NULL); 2679 REQUIRE(querytsig != NULL && *querytsig == NULL); 2680 2681 if (msg->tsig == NULL) 2682 return (ISC_R_SUCCESS); 2683 2684 result = dns_rdataset_first(msg->tsig); 2685 if (result != ISC_R_SUCCESS) 2686 return (result); 2687 dns_rdataset_current(msg->tsig, &rdata); 2688 dns_rdata_toregion(&rdata, &r); 2689 2690 result = isc_buffer_allocate(mctx, querytsig, r.length); 2691 if (result != ISC_R_SUCCESS) 2692 return (result); 2693 isc_buffer_putmem(*querytsig, r.base, r.length); 2694 return (ISC_R_SUCCESS); 2695} 2696 2697dns_rdataset_t * 2698dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2699 2700 /* 2701 * Get the SIG(0) record for 'msg'. 2702 */ 2703 2704 REQUIRE(DNS_MESSAGE_VALID(msg)); 2705 REQUIRE(owner == NULL || *owner == NULL); 2706 2707 if (msg->sig0 != NULL && owner != NULL) { 2708 /* If dns_message_getsig0 is called on a rendered message 2709 * after the SIG(0) has been applied, we need to return the 2710 * root name, not NULL. 2711 */ 2712 if (msg->sig0name == NULL) 2713 *owner = dns_rootname; 2714 else 2715 *owner = msg->sig0name; 2716 } 2717 return (msg->sig0); 2718} 2719 2720isc_result_t 2721dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2722 isc_region_t r; 2723 unsigned int x; 2724 isc_result_t result; 2725 2726 /* 2727 * Set the SIG(0) key for 'msg' 2728 */ 2729 2730 /* 2731 * The space required for an SIG(0) record is: 2732 * 2733 * 1 byte for the name 2734 * 2 bytes for the type 2735 * 2 bytes for the class 2736 * 4 bytes for the ttl 2737 * 2 bytes for the type covered 2738 * 1 byte for the algorithm 2739 * 1 bytes for the labels 2740 * 4 bytes for the original ttl 2741 * 4 bytes for the signature expiration 2742 * 4 bytes for the signature inception 2743 * 2 bytes for the key tag 2744 * n bytes for the signer's name 2745 * x bytes for the signature 2746 * --------------------------------- 2747 * 27 + n + x bytes 2748 */ 2749 REQUIRE(DNS_MESSAGE_VALID(msg)); 2750 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2751 REQUIRE(msg->state == DNS_SECTION_ANY); 2752 2753 if (key != NULL) { 2754 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 2755 dns_name_toregion(dst_key_name(key), &r); 2756 result = dst_key_sigsize(key, &x); 2757 if (result != ISC_R_SUCCESS) { 2758 msg->sig_reserved = 0; 2759 return (result); 2760 } 2761 msg->sig_reserved = 27 + r.length + x; 2762 result = dns_message_renderreserve(msg, msg->sig_reserved); 2763 if (result != ISC_R_SUCCESS) { 2764 msg->sig_reserved = 0; 2765 return (result); 2766 } 2767 msg->sig0key = key; 2768 } 2769 return (ISC_R_SUCCESS); 2770} 2771 2772dst_key_t * 2773dns_message_getsig0key(dns_message_t *msg) { 2774 2775 /* 2776 * Get the SIG(0) key for 'msg' 2777 */ 2778 2779 REQUIRE(DNS_MESSAGE_VALID(msg)); 2780 2781 return (msg->sig0key); 2782} 2783 2784void 2785dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2786 REQUIRE(DNS_MESSAGE_VALID(msg)); 2787 REQUIRE(buffer != NULL); 2788 REQUIRE(ISC_BUFFER_VALID(*buffer)); 2789 2790 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2791 *buffer = NULL; 2792} 2793 2794isc_result_t 2795dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 2796 isc_result_t result = ISC_R_SUCCESS; 2797 dns_rdata_t rdata = DNS_RDATA_INIT; 2798 2799 REQUIRE(DNS_MESSAGE_VALID(msg)); 2800 REQUIRE(signer != NULL); 2801 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 2802 2803 if (msg->tsig == NULL && msg->sig0 == NULL) 2804 return (ISC_R_NOTFOUND); 2805 2806 if (msg->verify_attempted == 0) 2807 return (DNS_R_NOTVERIFIEDYET); 2808 2809 if (!dns_name_hasbuffer(signer)) { 2810 isc_buffer_t *dynbuf = NULL; 2811 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 2812 if (result != ISC_R_SUCCESS) 2813 return (result); 2814 dns_name_setbuffer(signer, dynbuf); 2815 dns_message_takebuffer(msg, &dynbuf); 2816 } 2817 2818 if (msg->sig0 != NULL) { 2819 dns_rdata_sig_t sig; 2820 2821 result = dns_rdataset_first(msg->sig0); 2822 INSIST(result == ISC_R_SUCCESS); 2823 dns_rdataset_current(msg->sig0, &rdata); 2824 2825 result = dns_rdata_tostruct(&rdata, &sig, NULL); 2826 if (result != ISC_R_SUCCESS) 2827 return (result); 2828 2829 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) 2830 result = ISC_R_SUCCESS; 2831 else 2832 result = DNS_R_SIGINVALID; 2833 dns_name_clone(&sig.signer, signer); 2834 dns_rdata_freestruct(&sig); 2835 } else { 2836 dns_name_t *identity; 2837 dns_rdata_any_tsig_t tsig; 2838 2839 result = dns_rdataset_first(msg->tsig); 2840 INSIST(result == ISC_R_SUCCESS); 2841 dns_rdataset_current(msg->tsig, &rdata); 2842 2843 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2844 if (msg->tsigstatus != dns_rcode_noerror) 2845 result = DNS_R_TSIGVERIFYFAILURE; 2846 else if (tsig.error != dns_rcode_noerror) 2847 result = DNS_R_TSIGERRORSET; 2848 else 2849 result = ISC_R_SUCCESS; 2850 dns_rdata_freestruct(&tsig); 2851 2852 if (msg->tsigkey == NULL) { 2853 /* 2854 * If msg->tsigstatus & tsig.error are both 2855 * dns_rcode_noerror, the message must have been 2856 * verified, which means msg->tsigkey will be 2857 * non-NULL. 2858 */ 2859 INSIST(result != ISC_R_SUCCESS); 2860 } else { 2861 identity = dns_tsigkey_identity(msg->tsigkey); 2862 if (identity == NULL) { 2863 if (result == ISC_R_SUCCESS) 2864 result = DNS_R_NOIDENTITY; 2865 identity = &msg->tsigkey->name; 2866 } 2867 dns_name_clone(identity, signer); 2868 } 2869 } 2870 2871 return (result); 2872} 2873 2874void 2875dns_message_resetsig(dns_message_t *msg) { 2876 REQUIRE(DNS_MESSAGE_VALID(msg)); 2877 msg->verified_sig = 0; 2878 msg->verify_attempted = 0; 2879 msg->tsigstatus = dns_rcode_noerror; 2880 msg->sig0status = dns_rcode_noerror; 2881 msg->timeadjust = 0; 2882 if (msg->tsigkey != NULL) { 2883 dns_tsigkey_detach(&msg->tsigkey); 2884 msg->tsigkey = NULL; 2885 } 2886} 2887 2888isc_result_t 2889dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 2890 dns_message_resetsig(msg); 2891 return (dns_message_checksig(msg, view)); 2892} 2893 2894isc_result_t 2895dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 2896 isc_buffer_t b, msgb; 2897 2898 REQUIRE(DNS_MESSAGE_VALID(msg)); 2899 2900 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) 2901 return (ISC_R_SUCCESS); 2902 INSIST(msg->saved.base != NULL); 2903 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 2904 isc_buffer_add(&msgb, msg->saved.length); 2905 if (msg->tsigkey != NULL || msg->tsig != NULL) { 2906 if (view != NULL) 2907 return (dns_view_checksig(view, &msgb, msg)); 2908 else 2909 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 2910 } else { 2911 dns_rdata_t rdata = DNS_RDATA_INIT; 2912 dns_rdata_sig_t sig; 2913 dns_rdataset_t keyset; 2914 isc_result_t result; 2915 2916 result = dns_rdataset_first(msg->sig0); 2917 INSIST(result == ISC_R_SUCCESS); 2918 dns_rdataset_current(msg->sig0, &rdata); 2919 2920 /* 2921 * This can occur when the message is a dynamic update, since 2922 * the rdata length checking is relaxed. This should not 2923 * happen in a well-formed message, since the SIG(0) is only 2924 * looked for in the additional section, and the dynamic update 2925 * meta-records are in the prerequisite and update sections. 2926 */ 2927 if (rdata.length == 0) 2928 return (ISC_R_UNEXPECTEDEND); 2929 2930 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 2931 if (result != ISC_R_SUCCESS) 2932 return (result); 2933 2934 dns_rdataset_init(&keyset); 2935 if (view == NULL) 2936 return (DNS_R_KEYUNAUTHORIZED); 2937 result = dns_view_simplefind(view, &sig.signer, 2938 dns_rdatatype_key /* SIG(0) */, 2939 0, 0, ISC_FALSE, &keyset, NULL); 2940 2941 if (result != ISC_R_SUCCESS) { 2942 /* XXXBEW Should possibly create a fetch here */ 2943 result = DNS_R_KEYUNAUTHORIZED; 2944 goto freesig; 2945 } else if (keyset.trust < dns_trust_secure) { 2946 /* XXXBEW Should call a validator here */ 2947 result = DNS_R_KEYUNAUTHORIZED; 2948 goto freesig; 2949 } 2950 result = dns_rdataset_first(&keyset); 2951 INSIST(result == ISC_R_SUCCESS); 2952 for (; 2953 result == ISC_R_SUCCESS; 2954 result = dns_rdataset_next(&keyset)) 2955 { 2956 dst_key_t *key = NULL; 2957 2958 dns_rdataset_current(&keyset, &rdata); 2959 isc_buffer_init(&b, rdata.data, rdata.length); 2960 isc_buffer_add(&b, rdata.length); 2961 2962 result = dst_key_fromdns(&sig.signer, rdata.rdclass, 2963 &b, view->mctx, &key); 2964 if (result != ISC_R_SUCCESS) 2965 continue; 2966 if (dst_key_alg(key) != sig.algorithm || 2967 dst_key_id(key) != sig.keyid || 2968 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 2969 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 2970 { 2971 dst_key_free(&key); 2972 continue; 2973 } 2974 result = dns_dnssec_verifymessage(&msgb, msg, key); 2975 dst_key_free(&key); 2976 if (result == ISC_R_SUCCESS) 2977 break; 2978 } 2979 if (result == ISC_R_NOMORE) 2980 result = DNS_R_KEYUNAUTHORIZED; 2981 2982 freesig: 2983 if (dns_rdataset_isassociated(&keyset)) 2984 dns_rdataset_disassociate(&keyset); 2985 dns_rdata_freestruct(&sig); 2986 return (result); 2987 } 2988} 2989 2990isc_result_t 2991dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 2992 const dns_master_style_t *style, 2993 dns_messagetextflag_t flags, 2994 isc_buffer_t *target) { 2995 dns_name_t *name, empty_name; 2996 dns_rdataset_t *rdataset; 2997 isc_result_t result; 2998 2999 REQUIRE(DNS_MESSAGE_VALID(msg)); 3000 REQUIRE(target != NULL); 3001 REQUIRE(VALID_SECTION(section)); 3002 3003 if (ISC_LIST_EMPTY(msg->sections[section])) 3004 return (ISC_R_SUCCESS); 3005 3006 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3007 ADD_STRING(target, ";; "); 3008 if (msg->opcode != dns_opcode_update) { 3009 ADD_STRING(target, sectiontext[section]); 3010 } 3011 else { 3012 ADD_STRING(target, updsectiontext[section]); 3013 } 3014 ADD_STRING(target, " SECTION:\n"); 3015 } 3016 3017 dns_name_init(&empty_name, NULL); 3018 result = dns_message_firstname(msg, section); 3019 if (result != ISC_R_SUCCESS) { 3020 return (result); 3021 } 3022 do { 3023 name = NULL; 3024 dns_message_currentname(msg, section, &name); 3025 for (rdataset = ISC_LIST_HEAD(name->list); 3026 rdataset != NULL; 3027 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3028 if (section == DNS_SECTION_QUESTION) { 3029 ADD_STRING(target, ";"); 3030 result = dns_master_questiontotext(name, 3031 rdataset, 3032 style, 3033 target); 3034 } else { 3035 result = dns_master_rdatasettotext(name, 3036 rdataset, 3037 style, 3038 target); 3039 } 3040 if (result != ISC_R_SUCCESS) 3041 return (result); 3042 } 3043 result = dns_message_nextname(msg, section); 3044 } while (result == ISC_R_SUCCESS); 3045 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3046 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3047 ADD_STRING(target, "\n"); 3048 if (result == ISC_R_NOMORE) 3049 result = ISC_R_SUCCESS; 3050 return (result); 3051} 3052 3053isc_result_t 3054dns_message_pseudosectiontotext(dns_message_t *msg, 3055 dns_pseudosection_t section, 3056 const dns_master_style_t *style, 3057 dns_messagetextflag_t flags, 3058 isc_buffer_t *target) { 3059 dns_rdataset_t *ps = NULL; 3060 dns_name_t *name = NULL; 3061 isc_result_t result; 3062 char buf[sizeof("1234567890")]; 3063 isc_uint32_t mbz; 3064 3065 REQUIRE(DNS_MESSAGE_VALID(msg)); 3066 REQUIRE(target != NULL); 3067 REQUIRE(VALID_PSEUDOSECTION(section)); 3068 3069 switch (section) { 3070 case DNS_PSEUDOSECTION_OPT: 3071 ps = dns_message_getopt(msg); 3072 if (ps == NULL) 3073 return (ISC_R_SUCCESS); 3074 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3075 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3076 ADD_STRING(target, "; EDNS: version: "); 3077 snprintf(buf, sizeof(buf), "%u", 3078 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3079 ADD_STRING(target, buf); 3080 ADD_STRING(target, ", flags:"); 3081 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 3082 ADD_STRING(target, " do"); 3083 mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff; 3084 if (mbz != 0) { 3085 ADD_STRING(target, "; MBZ: "); 3086 snprintf(buf, sizeof(buf), "%.4x ", mbz); 3087 ADD_STRING(target, buf); 3088 ADD_STRING(target, ", udp: "); 3089 } else 3090 ADD_STRING(target, "; udp: "); 3091 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3092 ADD_STRING(target, buf); 3093 return (ISC_R_SUCCESS); 3094 case DNS_PSEUDOSECTION_TSIG: 3095 ps = dns_message_gettsig(msg, &name); 3096 if (ps == NULL) 3097 return (ISC_R_SUCCESS); 3098 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3099 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 3100 result = dns_master_rdatasettotext(name, ps, style, target); 3101 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3102 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3103 ADD_STRING(target, "\n"); 3104 return (result); 3105 case DNS_PSEUDOSECTION_SIG0: 3106 ps = dns_message_getsig0(msg, &name); 3107 if (ps == NULL) 3108 return (ISC_R_SUCCESS); 3109 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3110 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 3111 result = dns_master_rdatasettotext(name, ps, style, target); 3112 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3113 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3114 ADD_STRING(target, "\n"); 3115 return (result); 3116 } 3117 return (ISC_R_UNEXPECTED); 3118} 3119 3120isc_result_t 3121dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 3122 dns_messagetextflag_t flags, isc_buffer_t *target) { 3123 char buf[sizeof("1234567890")]; 3124 isc_result_t result; 3125 3126 REQUIRE(DNS_MESSAGE_VALID(msg)); 3127 REQUIRE(target != NULL); 3128 3129 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { 3130 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 3131 ADD_STRING(target, opcodetext[msg->opcode]); 3132 ADD_STRING(target, ", status: "); 3133 ADD_STRING(target, rcodetext[msg->rcode]); 3134 ADD_STRING(target, ", id: "); 3135 snprintf(buf, sizeof(buf), "%6u", msg->id); 3136 ADD_STRING(target, buf); 3137 ADD_STRING(target, "\n;; flags: "); 3138 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 3139 ADD_STRING(target, "qr "); 3140 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 3141 ADD_STRING(target, "aa "); 3142 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 3143 ADD_STRING(target, "tc "); 3144 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 3145 ADD_STRING(target, "rd "); 3146 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 3147 ADD_STRING(target, "ra "); 3148 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 3149 ADD_STRING(target, "ad "); 3150 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 3151 ADD_STRING(target, "cd "); 3152 if (msg->opcode != dns_opcode_update) { 3153 ADD_STRING(target, "; QUESTION: "); 3154 } else { 3155 ADD_STRING(target, "; ZONE: "); 3156 } 3157 snprintf(buf, sizeof(buf), "%1u", 3158 msg->counts[DNS_SECTION_QUESTION]); 3159 ADD_STRING(target, buf); 3160 if (msg->opcode != dns_opcode_update) { 3161 ADD_STRING(target, ", ANSWER: "); 3162 } else { 3163 ADD_STRING(target, ", PREREQ: "); 3164 } 3165 snprintf(buf, sizeof(buf), "%1u", 3166 msg->counts[DNS_SECTION_ANSWER]); 3167 ADD_STRING(target, buf); 3168 if (msg->opcode != dns_opcode_update) { 3169 ADD_STRING(target, ", AUTHORITY: "); 3170 } else { 3171 ADD_STRING(target, ", UPDATE: "); 3172 } 3173 snprintf(buf, sizeof(buf), "%1u", 3174 msg->counts[DNS_SECTION_AUTHORITY]); 3175 ADD_STRING(target, buf); 3176 ADD_STRING(target, ", ADDITIONAL: "); 3177 snprintf(buf, sizeof(buf), "%1u", 3178 msg->counts[DNS_SECTION_ADDITIONAL]); 3179 ADD_STRING(target, buf); 3180 ADD_STRING(target, "\n"); 3181 } 3182 result = dns_message_pseudosectiontotext(msg, 3183 DNS_PSEUDOSECTION_OPT, 3184 style, flags, target); 3185 if (result != ISC_R_SUCCESS) 3186 return (result); 3187 3188 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, 3189 style, flags, target); 3190 if (result != ISC_R_SUCCESS) 3191 return (result); 3192 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, 3193 style, flags, target); 3194 if (result != ISC_R_SUCCESS) 3195 return (result); 3196 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, 3197 style, flags, target); 3198 if (result != ISC_R_SUCCESS) 3199 return (result); 3200 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, 3201 style, flags, target); 3202 if (result != ISC_R_SUCCESS) 3203 return (result); 3204 3205 result = dns_message_pseudosectiontotext(msg, 3206 DNS_PSEUDOSECTION_TSIG, 3207 style, flags, target); 3208 if (result != ISC_R_SUCCESS) 3209 return (result); 3210 3211 result = dns_message_pseudosectiontotext(msg, 3212 DNS_PSEUDOSECTION_SIG0, 3213 style, flags, target); 3214 if (result != ISC_R_SUCCESS) 3215 return (result); 3216 3217 return (ISC_R_SUCCESS); 3218} 3219 3220isc_region_t * 3221dns_message_getrawmessage(dns_message_t *msg) { 3222 REQUIRE(DNS_MESSAGE_VALID(msg)); 3223 return (&msg->saved); 3224} 3225 3226void 3227dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 3228 const void *order_arg) 3229{ 3230 REQUIRE(DNS_MESSAGE_VALID(msg)); 3231 msg->order = order; 3232 msg->order_arg = order_arg; 3233} 3234 3235void 3236dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 3237 REQUIRE(DNS_MESSAGE_VALID(msg)); 3238 msg->timeadjust = timeadjust; 3239} 3240 3241int 3242dns_message_gettimeadjust(dns_message_t *msg) { 3243 REQUIRE(DNS_MESSAGE_VALID(msg)); 3244 return (msg->timeadjust); 3245} 3246 3247isc_result_t 3248dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 3249 3250 REQUIRE(opcode < 16); 3251 3252 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) 3253 return (ISC_R_NOSPACE); 3254 isc_buffer_putstr(target, opcodetext[opcode]); 3255 return (ISC_R_SUCCESS); 3256} 3257