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