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