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