1 /* $NetBSD: message.c,v 1.14 2022/09/23 12:15:29 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 /*** 19 *** Imports 20 ***/ 21 22 #include <ctype.h> 23 #include <inttypes.h> 24 #include <stdbool.h> 25 26 #include <isc/buffer.h> 27 #include <isc/mem.h> 28 #include <isc/print.h> 29 #include <isc/string.h> /* Required for HP/UX (and others?) */ 30 #include <isc/utf8.h> 31 #include <isc/util.h> 32 33 #include <dns/dnssec.h> 34 #include <dns/keyvalues.h> 35 #include <dns/log.h> 36 #include <dns/masterdump.h> 37 #include <dns/message.h> 38 #include <dns/opcode.h> 39 #include <dns/rcode.h> 40 #include <dns/rdata.h> 41 #include <dns/rdatalist.h> 42 #include <dns/rdataset.h> 43 #include <dns/rdatastruct.h> 44 #include <dns/result.h> 45 #include <dns/tsig.h> 46 #include <dns/ttl.h> 47 #include <dns/view.h> 48 49 #ifdef SKAN_MSG_DEBUG 50 static void 51 hexdump(const char *msg, const char *msg2, void *base, size_t len) { 52 unsigned char *p; 53 unsigned int cnt; 54 55 p = base; 56 cnt = 0; 57 58 printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, (unsigned)len, base); 59 60 while (cnt < len) { 61 if (cnt % 16 == 0) { 62 printf("%p: ", p); 63 } else if (cnt % 8 == 0) { 64 printf(" |"); 65 } 66 printf(" %02x %c", *p, (isprint(*p) ? *p : ' ')); 67 p++; 68 cnt++; 69 70 if (cnt % 16 == 0) { 71 printf("\n"); 72 } 73 } 74 75 if (cnt % 16 != 0) { 76 printf("\n"); 77 } 78 } 79 #endif /* ifdef SKAN_MSG_DEBUG */ 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) \ 91 (((s) > DNS_SECTION_ANY) && ((s) < DNS_SECTION_MAX)) 92 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) && ((s) < DNS_SECTION_MAX)) 93 #define ADD_STRING(b, s) \ 94 { \ 95 if (strlen(s) >= isc_buffer_availablelength(b)) { \ 96 result = ISC_R_NOSPACE; \ 97 goto cleanup; \ 98 } else \ 99 isc_buffer_putstr(b, s); \ 100 } 101 #define VALID_PSEUDOSECTION(s) \ 102 (((s) >= DNS_PSEUDOSECTION_ANY) && ((s) < DNS_PSEUDOSECTION_MAX)) 103 104 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0) 105 106 /*% 107 * This is the size of each individual scratchpad buffer, and the numbers 108 * of various block allocations used within the server. 109 * XXXMLG These should come from a config setting. 110 */ 111 #define SCRATCHPAD_SIZE 1232 112 #define NAME_FILLCOUNT 4 113 #define NAME_FREEMAX 8 * NAME_FILLCOUNT 114 #define OFFSET_COUNT 4 115 #define RDATA_COUNT 8 116 #define RDATALIST_COUNT 8 117 #define RDATASET_FILLCOUNT 4 118 #define RDATASET_FREEMAX 8 * RDATASET_FILLCOUNT 119 120 /*% 121 * Text representation of the different items, for message_totext 122 * functions. 123 */ 124 static const char *sectiontext[] = { "QUESTION", "ANSWER", "AUTHORITY", 125 "ADDITIONAL" }; 126 127 static const char *updsectiontext[] = { "ZONE", "PREREQUISITE", "UPDATE", 128 "ADDITIONAL" }; 129 130 static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", 131 "RESERVED3", "NOTIFY", "UPDATE", 132 "RESERVED6", "RESERVED7", "RESERVED8", 133 "RESERVED9", "RESERVED10", "RESERVED11", 134 "RESERVED12", "RESERVED13", "RESERVED14", 135 "RESERVED15" }; 136 137 static const char *edetext[] = { "Other", 138 "Unsupported DNSKEY Algorithm", 139 "Unsupported DS Digest Type", 140 "Stale Answer", 141 "Forged Answer", 142 "DNSSEC Indeterminate", 143 "DNSSEC Bogus", 144 "Signature Expired", 145 "Signature Not Yet Valid", 146 "DNSKEY Missing", 147 "RRSIGs Missing", 148 "No Zone Key Bit Set", 149 "NSEC Missing", 150 "Cached Error", 151 "Not Ready", 152 "Blocked", 153 "Censored", 154 "Filtered", 155 "Prohibited", 156 "Stale NXDOMAIN Answer", 157 "Not Authoritative", 158 "Not Supported", 159 "No Reachable Authority", 160 "Network Error", 161 "Invalid Data" }; 162 163 /*% 164 * "helper" type, which consists of a block of some type, and is linkable. 165 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer 166 * size, or the allocated elements will not be aligned correctly. 167 */ 168 struct dns_msgblock { 169 unsigned int count; 170 unsigned int remaining; 171 ISC_LINK(dns_msgblock_t) link; 172 }; /* dynamically sized */ 173 174 static dns_msgblock_t * 175 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int); 176 177 #define msgblock_get(block, type) \ 178 ((type *)msgblock_internalget(block, sizeof(type))) 179 180 static void * 181 msgblock_internalget(dns_msgblock_t *, unsigned int); 182 183 static void 184 msgblock_reset(dns_msgblock_t *); 185 186 static void 187 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int); 188 189 static void 190 logfmtpacket(dns_message_t *message, const char *description, 191 const isc_sockaddr_t *address, isc_logcategory_t *category, 192 isc_logmodule_t *module, const dns_master_style_t *style, 193 int level, isc_mem_t *mctx); 194 195 /* 196 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory 197 * is free, return NULL. 198 */ 199 static dns_msgblock_t * 200 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type, 201 unsigned int count) { 202 dns_msgblock_t *block; 203 unsigned int length; 204 205 length = sizeof(dns_msgblock_t) + (sizeof_type * count); 206 207 block = isc_mem_get(mctx, length); 208 209 block->count = count; 210 block->remaining = count; 211 212 ISC_LINK_INIT(block, link); 213 214 return (block); 215 } 216 217 /* 218 * Return an element from the msgblock. If no more are available, return 219 * NULL. 220 */ 221 static void * 222 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) { 223 void *ptr; 224 225 if (block == NULL || block->remaining == 0) { 226 return (NULL); 227 } 228 229 block->remaining--; 230 231 ptr = (((unsigned char *)block) + sizeof(dns_msgblock_t) + 232 (sizeof_type * block->remaining)); 233 234 return (ptr); 235 } 236 237 static void 238 msgblock_reset(dns_msgblock_t *block) { 239 block->remaining = block->count; 240 } 241 242 /* 243 * Release memory associated with a message block. 244 */ 245 static void 246 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, 247 unsigned int sizeof_type) { 248 unsigned int length; 249 250 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count); 251 252 isc_mem_put(mctx, block, length); 253 } 254 255 /* 256 * Allocate a new dynamic buffer, and attach it to this message as the 257 * "current" buffer. (which is always the last on the list, for our 258 * uses) 259 */ 260 static isc_result_t 261 newbuffer(dns_message_t *msg, unsigned int size) { 262 isc_buffer_t *dynbuf; 263 264 dynbuf = NULL; 265 isc_buffer_allocate(msg->mctx, &dynbuf, size); 266 267 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link); 268 return (ISC_R_SUCCESS); 269 } 270 271 static isc_buffer_t * 272 currentbuffer(dns_message_t *msg) { 273 isc_buffer_t *dynbuf; 274 275 dynbuf = ISC_LIST_TAIL(msg->scratchpad); 276 INSIST(dynbuf != NULL); 277 278 return (dynbuf); 279 } 280 281 static void 282 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) { 283 ISC_LIST_PREPEND(msg->freerdata, rdata, link); 284 } 285 286 static dns_rdata_t * 287 newrdata(dns_message_t *msg) { 288 dns_msgblock_t *msgblock; 289 dns_rdata_t *rdata; 290 291 rdata = ISC_LIST_HEAD(msg->freerdata); 292 if (rdata != NULL) { 293 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 294 return (rdata); 295 } 296 297 msgblock = ISC_LIST_TAIL(msg->rdatas); 298 rdata = msgblock_get(msgblock, dns_rdata_t); 299 if (rdata == NULL) { 300 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t), 301 RDATA_COUNT); 302 if (msgblock == NULL) { 303 return (NULL); 304 } 305 306 ISC_LIST_APPEND(msg->rdatas, msgblock, link); 307 308 rdata = msgblock_get(msgblock, dns_rdata_t); 309 } 310 311 dns_rdata_init(rdata); 312 return (rdata); 313 } 314 315 static void 316 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) { 317 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link); 318 } 319 320 static dns_rdatalist_t * 321 newrdatalist(dns_message_t *msg) { 322 dns_msgblock_t *msgblock; 323 dns_rdatalist_t *rdatalist; 324 325 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 326 if (rdatalist != NULL) { 327 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 328 goto out; 329 } 330 331 msgblock = ISC_LIST_TAIL(msg->rdatalists); 332 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 333 if (rdatalist == NULL) { 334 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdatalist_t), 335 RDATALIST_COUNT); 336 if (msgblock == NULL) { 337 return (NULL); 338 } 339 340 ISC_LIST_APPEND(msg->rdatalists, msgblock, link); 341 342 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 343 } 344 out: 345 if (rdatalist != NULL) { 346 dns_rdatalist_init(rdatalist); 347 } 348 349 return (rdatalist); 350 } 351 352 static dns_offsets_t * 353 newoffsets(dns_message_t *msg) { 354 dns_msgblock_t *msgblock; 355 dns_offsets_t *offsets; 356 357 msgblock = ISC_LIST_TAIL(msg->offsets); 358 offsets = msgblock_get(msgblock, dns_offsets_t); 359 if (offsets == NULL) { 360 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_offsets_t), 361 OFFSET_COUNT); 362 if (msgblock == NULL) { 363 return (NULL); 364 } 365 366 ISC_LIST_APPEND(msg->offsets, msgblock, link); 367 368 offsets = msgblock_get(msgblock, dns_offsets_t); 369 } 370 371 return (offsets); 372 } 373 374 static void 375 msginitheader(dns_message_t *m) { 376 m->id = 0; 377 m->flags = 0; 378 m->rcode = 0; 379 m->opcode = 0; 380 m->rdclass = 0; 381 } 382 383 static void 384 msginitprivate(dns_message_t *m) { 385 unsigned int i; 386 387 for (i = 0; i < DNS_SECTION_MAX; i++) { 388 m->cursors[i] = NULL; 389 m->counts[i] = 0; 390 } 391 m->opt = NULL; 392 m->sig0 = NULL; 393 m->sig0name = NULL; 394 m->tsig = NULL; 395 m->tsigname = NULL; 396 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ 397 m->opt_reserved = 0; 398 m->sig_reserved = 0; 399 m->reserved = 0; 400 m->padding = 0; 401 m->padding_off = 0; 402 m->buffer = NULL; 403 } 404 405 static void 406 msginittsig(dns_message_t *m) { 407 m->tsigstatus = dns_rcode_noerror; 408 m->querytsigstatus = dns_rcode_noerror; 409 m->tsigkey = NULL; 410 m->tsigctx = NULL; 411 m->sigstart = -1; 412 m->sig0key = NULL; 413 m->sig0status = dns_rcode_noerror; 414 m->timeadjust = 0; 415 } 416 417 /* 418 * Init elements to default state. Used both when allocating a new element 419 * and when resetting one. 420 */ 421 static void 422 msginit(dns_message_t *m) { 423 msginitheader(m); 424 msginitprivate(m); 425 msginittsig(m); 426 m->header_ok = 0; 427 m->question_ok = 0; 428 m->tcp_continuation = 0; 429 m->verified_sig = 0; 430 m->verify_attempted = 0; 431 m->order = NULL; 432 m->order_arg.env = NULL; 433 m->order_arg.acl = NULL; 434 m->order_arg.element = NULL; 435 m->query.base = NULL; 436 m->query.length = 0; 437 m->free_query = 0; 438 m->saved.base = NULL; 439 m->saved.length = 0; 440 m->free_saved = 0; 441 m->cc_ok = 0; 442 m->cc_bad = 0; 443 m->tkey = 0; 444 m->rdclass_set = 0; 445 m->querytsig = NULL; 446 m->indent.string = "\t"; 447 m->indent.count = 0; 448 } 449 450 static void 451 msgresetnames(dns_message_t *msg, unsigned int first_section) { 452 unsigned int i; 453 dns_name_t *name, *next_name; 454 dns_rdataset_t *rds, *next_rds; 455 456 /* 457 * Clean up name lists by calling the rdataset disassociate function. 458 */ 459 for (i = first_section; i < DNS_SECTION_MAX; i++) { 460 name = ISC_LIST_HEAD(msg->sections[i]); 461 while (name != NULL) { 462 next_name = ISC_LIST_NEXT(name, link); 463 ISC_LIST_UNLINK(msg->sections[i], name, link); 464 465 rds = ISC_LIST_HEAD(name->list); 466 while (rds != NULL) { 467 next_rds = ISC_LIST_NEXT(rds, link); 468 ISC_LIST_UNLINK(name->list, rds, link); 469 470 INSIST(dns_rdataset_isassociated(rds)); 471 dns_rdataset_disassociate(rds); 472 isc_mempool_put(msg->rdspool, rds); 473 rds = next_rds; 474 } 475 dns_message_puttempname(msg, &name); 476 name = next_name; 477 } 478 } 479 } 480 481 static void 482 msgresetopt(dns_message_t *msg) { 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->cc_ok = 0; 493 msg->cc_bad = 0; 494 } 495 } 496 497 static void 498 msgresetsigs(dns_message_t *msg, bool 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 dns_message_puttempname(msg, &msg->tsigname); 518 msg->tsig = NULL; 519 } else if (msg->querytsig != NULL && !replying) { 520 dns_rdataset_disassociate(msg->querytsig); 521 isc_mempool_put(msg->rdspool, msg->querytsig); 522 msg->querytsig = NULL; 523 } 524 if (msg->sig0 != NULL) { 525 INSIST(dns_rdataset_isassociated(msg->sig0)); 526 dns_rdataset_disassociate(msg->sig0); 527 isc_mempool_put(msg->rdspool, msg->sig0); 528 if (msg->sig0name != NULL) { 529 dns_message_puttempname(msg, &msg->sig0name); 530 } 531 msg->sig0 = NULL; 532 msg->sig0name = NULL; 533 } 534 } 535 536 /* 537 * Free all but one (or everything) for this message. This is used by 538 * both dns_message_reset() and dns__message_destroy(). 539 */ 540 static void 541 msgreset(dns_message_t *msg, bool everything) { 542 dns_msgblock_t *msgblock, *next_msgblock; 543 isc_buffer_t *dynbuf, *next_dynbuf; 544 dns_rdata_t *rdata; 545 dns_rdatalist_t *rdatalist; 546 547 msgresetnames(msg, 0); 548 msgresetopt(msg); 549 msgresetsigs(msg, false); 550 551 /* 552 * Clean up linked lists. 553 */ 554 555 /* 556 * Run through the free lists, and just unlink anything found there. 557 * The memory isn't lost since these are part of message blocks we 558 * have allocated. 559 */ 560 rdata = ISC_LIST_HEAD(msg->freerdata); 561 while (rdata != NULL) { 562 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 563 rdata = ISC_LIST_HEAD(msg->freerdata); 564 } 565 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 566 while (rdatalist != NULL) { 567 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 568 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 569 } 570 571 dynbuf = ISC_LIST_HEAD(msg->scratchpad); 572 INSIST(dynbuf != NULL); 573 if (!everything) { 574 isc_buffer_clear(dynbuf); 575 dynbuf = ISC_LIST_NEXT(dynbuf, link); 576 } 577 while (dynbuf != NULL) { 578 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 579 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link); 580 isc_buffer_free(&dynbuf); 581 dynbuf = next_dynbuf; 582 } 583 584 msgblock = ISC_LIST_HEAD(msg->rdatas); 585 if (!everything && msgblock != NULL) { 586 msgblock_reset(msgblock); 587 msgblock = ISC_LIST_NEXT(msgblock, link); 588 } 589 while (msgblock != NULL) { 590 next_msgblock = ISC_LIST_NEXT(msgblock, link); 591 ISC_LIST_UNLINK(msg->rdatas, msgblock, link); 592 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t)); 593 msgblock = next_msgblock; 594 } 595 596 /* 597 * rdatalists could be empty. 598 */ 599 600 msgblock = ISC_LIST_HEAD(msg->rdatalists); 601 if (!everything && msgblock != NULL) { 602 msgblock_reset(msgblock); 603 msgblock = ISC_LIST_NEXT(msgblock, link); 604 } 605 while (msgblock != NULL) { 606 next_msgblock = ISC_LIST_NEXT(msgblock, link); 607 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link); 608 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t)); 609 msgblock = next_msgblock; 610 } 611 612 msgblock = ISC_LIST_HEAD(msg->offsets); 613 if (!everything && msgblock != NULL) { 614 msgblock_reset(msgblock); 615 msgblock = ISC_LIST_NEXT(msgblock, link); 616 } 617 while (msgblock != NULL) { 618 next_msgblock = ISC_LIST_NEXT(msgblock, link); 619 ISC_LIST_UNLINK(msg->offsets, msgblock, link); 620 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t)); 621 msgblock = next_msgblock; 622 } 623 624 if (msg->tsigkey != NULL) { 625 dns_tsigkey_detach(&msg->tsigkey); 626 msg->tsigkey = NULL; 627 } 628 629 if (msg->tsigctx != NULL) { 630 dst_context_destroy(&msg->tsigctx); 631 } 632 633 if (msg->query.base != NULL) { 634 if (msg->free_query != 0) { 635 isc_mem_put(msg->mctx, msg->query.base, 636 msg->query.length); 637 } 638 msg->query.base = NULL; 639 msg->query.length = 0; 640 } 641 642 if (msg->saved.base != NULL) { 643 if (msg->free_saved != 0) { 644 isc_mem_put(msg->mctx, msg->saved.base, 645 msg->saved.length); 646 } 647 msg->saved.base = NULL; 648 msg->saved.length = 0; 649 } 650 651 /* 652 * cleanup the buffer cleanup list 653 */ 654 dynbuf = ISC_LIST_HEAD(msg->cleanup); 655 while (dynbuf != NULL) { 656 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 657 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link); 658 isc_buffer_free(&dynbuf); 659 dynbuf = next_dynbuf; 660 } 661 662 /* 663 * Set other bits to normal default values. 664 */ 665 if (!everything) { 666 msginit(msg); 667 } 668 669 ENSURE(isc_mempool_getallocated(msg->namepool) == 0); 670 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0); 671 } 672 673 static unsigned int 674 spacefortsig(dns_tsigkey_t *key, int otherlen) { 675 isc_region_t r1, r2; 676 unsigned int x; 677 isc_result_t result; 678 679 /* 680 * The space required for an TSIG record is: 681 * 682 * n1 bytes for the name 683 * 2 bytes for the type 684 * 2 bytes for the class 685 * 4 bytes for the ttl 686 * 2 bytes for the rdlength 687 * n2 bytes for the algorithm name 688 * 6 bytes for the time signed 689 * 2 bytes for the fudge 690 * 2 bytes for the MAC size 691 * x bytes for the MAC 692 * 2 bytes for the original id 693 * 2 bytes for the error 694 * 2 bytes for the other data length 695 * y bytes for the other data (at most) 696 * --------------------------------- 697 * 26 + n1 + n2 + x + y bytes 698 */ 699 700 dns_name_toregion(&key->name, &r1); 701 dns_name_toregion(key->algorithm, &r2); 702 if (key->key == NULL) { 703 x = 0; 704 } else { 705 result = dst_key_sigsize(key->key, &x); 706 if (result != ISC_R_SUCCESS) { 707 x = 0; 708 } 709 } 710 return (26 + r1.length + r2.length + x + otherlen); 711 } 712 713 void 714 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) { 715 dns_message_t *m = NULL; 716 isc_buffer_t *dynbuf = NULL; 717 unsigned int i; 718 719 REQUIRE(mctx != NULL); 720 REQUIRE(msgp != NULL); 721 REQUIRE(*msgp == NULL); 722 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE || 723 intent == DNS_MESSAGE_INTENTRENDER); 724 725 m = isc_mem_get(mctx, sizeof(dns_message_t)); 726 *m = (dns_message_t){ .from_to_wire = intent }; 727 isc_mem_attach(mctx, &m->mctx); 728 msginit(m); 729 730 for (i = 0; i < DNS_SECTION_MAX; i++) { 731 ISC_LIST_INIT(m->sections[i]); 732 } 733 734 ISC_LIST_INIT(m->scratchpad); 735 ISC_LIST_INIT(m->cleanup); 736 ISC_LIST_INIT(m->rdatas); 737 ISC_LIST_INIT(m->rdatalists); 738 ISC_LIST_INIT(m->offsets); 739 ISC_LIST_INIT(m->freerdata); 740 ISC_LIST_INIT(m->freerdatalist); 741 742 isc_mempool_create(m->mctx, sizeof(dns_fixedname_t), &m->namepool); 743 isc_mempool_setfillcount(m->namepool, NAME_FILLCOUNT); 744 isc_mempool_setfreemax(m->namepool, NAME_FREEMAX); 745 isc_mempool_setname(m->namepool, "msg:names"); 746 747 isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), &m->rdspool); 748 isc_mempool_setfillcount(m->rdspool, RDATASET_FILLCOUNT); 749 isc_mempool_setfreemax(m->rdspool, RDATASET_FREEMAX); 750 isc_mempool_setname(m->rdspool, "msg:rdataset"); 751 752 isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE); 753 ISC_LIST_APPEND(m->scratchpad, dynbuf, link); 754 755 isc_refcount_init(&m->refcount, 1); 756 m->magic = DNS_MESSAGE_MAGIC; 757 758 *msgp = m; 759 } 760 761 void 762 dns_message_reset(dns_message_t *msg, unsigned int intent) { 763 REQUIRE(DNS_MESSAGE_VALID(msg)); 764 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE || 765 intent == DNS_MESSAGE_INTENTRENDER); 766 767 msgreset(msg, false); 768 msg->from_to_wire = intent; 769 } 770 771 static void 772 dns__message_destroy(dns_message_t *msg) { 773 REQUIRE(msg != NULL); 774 REQUIRE(DNS_MESSAGE_VALID(msg)); 775 776 msgreset(msg, true); 777 isc_mempool_destroy(&msg->namepool); 778 isc_mempool_destroy(&msg->rdspool); 779 isc_refcount_destroy(&msg->refcount); 780 msg->magic = 0; 781 isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t)); 782 } 783 784 void 785 dns_message_attach(dns_message_t *source, dns_message_t **target) { 786 REQUIRE(DNS_MESSAGE_VALID(source)); 787 788 isc_refcount_increment(&source->refcount); 789 *target = source; 790 } 791 792 void 793 dns_message_detach(dns_message_t **messagep) { 794 REQUIRE(messagep != NULL && DNS_MESSAGE_VALID(*messagep)); 795 dns_message_t *msg = *messagep; 796 *messagep = NULL; 797 798 if (isc_refcount_decrement(&msg->refcount) == 1) { 799 dns__message_destroy(msg); 800 } 801 } 802 803 static isc_result_t 804 findname(dns_name_t **foundname, const dns_name_t *target, 805 dns_namelist_t *section) { 806 dns_name_t *curr; 807 808 for (curr = ISC_LIST_TAIL(*section); curr != NULL; 809 curr = ISC_LIST_PREV(curr, link)) 810 { 811 if (dns_name_equal(curr, target)) { 812 if (foundname != NULL) { 813 *foundname = curr; 814 } 815 return (ISC_R_SUCCESS); 816 } 817 } 818 819 return (ISC_R_NOTFOUND); 820 } 821 822 isc_result_t 823 dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass, 824 dns_rdatatype_t type, dns_rdatatype_t covers, 825 dns_rdataset_t **rdataset) { 826 dns_rdataset_t *curr; 827 828 REQUIRE(name != NULL); 829 REQUIRE(rdataset == NULL || *rdataset == NULL); 830 831 for (curr = ISC_LIST_TAIL(name->list); curr != NULL; 832 curr = ISC_LIST_PREV(curr, link)) 833 { 834 if (curr->rdclass == rdclass && curr->type == type && 835 curr->covers == covers) { 836 if (rdataset != NULL) { 837 *rdataset = curr; 838 } 839 return (ISC_R_SUCCESS); 840 } 841 } 842 843 return (ISC_R_NOTFOUND); 844 } 845 846 isc_result_t 847 dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type, 848 dns_rdatatype_t covers, dns_rdataset_t **rdataset) { 849 dns_rdataset_t *curr; 850 851 REQUIRE(name != NULL); 852 REQUIRE(rdataset == NULL || *rdataset == NULL); 853 854 for (curr = ISC_LIST_TAIL(name->list); curr != NULL; 855 curr = ISC_LIST_PREV(curr, link)) 856 { 857 if (curr->type == type && curr->covers == covers) { 858 if (ISC_UNLIKELY(rdataset != NULL)) { 859 *rdataset = curr; 860 } 861 return (ISC_R_SUCCESS); 862 } 863 } 864 865 return (ISC_R_NOTFOUND); 866 } 867 868 /* 869 * Read a name from buffer "source". 870 */ 871 static isc_result_t 872 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, 873 dns_decompress_t *dctx) { 874 isc_buffer_t *scratch; 875 isc_result_t result; 876 unsigned int tries; 877 878 scratch = currentbuffer(msg); 879 880 /* 881 * First try: use current buffer. 882 * Second try: allocate a new buffer and use that. 883 */ 884 tries = 0; 885 while (tries < 2) { 886 result = dns_name_fromwire(name, source, dctx, 0, scratch); 887 888 if (result == ISC_R_NOSPACE) { 889 tries++; 890 891 result = newbuffer(msg, SCRATCHPAD_SIZE); 892 if (result != ISC_R_SUCCESS) { 893 return (result); 894 } 895 896 scratch = currentbuffer(msg); 897 dns_name_reset(name); 898 } else { 899 return (result); 900 } 901 } 902 903 UNREACHABLE(); 904 } 905 906 static isc_result_t 907 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 908 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, 909 unsigned int rdatalen, dns_rdata_t *rdata) { 910 isc_buffer_t *scratch; 911 isc_result_t result; 912 unsigned int tries; 913 unsigned int trysize; 914 915 scratch = currentbuffer(msg); 916 917 isc_buffer_setactive(source, rdatalen); 918 919 /* 920 * First try: use current buffer. 921 * Second try: allocate a new buffer of size 922 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) 923 * (the data will fit if it was not more than 50% compressed) 924 * Subsequent tries: double buffer size on each try. 925 */ 926 tries = 0; 927 trysize = 0; 928 /* XXX possibly change this to a while (tries < 2) loop */ 929 for (;;) { 930 result = dns_rdata_fromwire(rdata, rdclass, rdtype, source, 931 dctx, 0, scratch); 932 933 if (result == ISC_R_NOSPACE) { 934 if (tries == 0) { 935 trysize = 2 * rdatalen; 936 if (trysize < SCRATCHPAD_SIZE) { 937 trysize = SCRATCHPAD_SIZE; 938 } 939 } else { 940 INSIST(trysize != 0); 941 if (trysize >= 65535) { 942 return (ISC_R_NOSPACE); 943 } 944 /* XXX DNS_R_RRTOOLONG? */ 945 trysize *= 2; 946 } 947 tries++; 948 result = newbuffer(msg, trysize); 949 if (result != ISC_R_SUCCESS) { 950 return (result); 951 } 952 953 scratch = currentbuffer(msg); 954 } else { 955 return (result); 956 } 957 } 958 } 959 960 #define DO_ERROR(r) \ 961 do { \ 962 if (best_effort) { \ 963 seen_problem = true; \ 964 } else { \ 965 result = r; \ 966 goto cleanup; \ 967 } \ 968 } while (0) 969 970 static isc_result_t 971 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 972 unsigned int options) { 973 isc_region_t r; 974 unsigned int count; 975 dns_name_t *name = NULL; 976 dns_name_t *name2 = NULL; 977 dns_rdataset_t *rdataset = NULL; 978 dns_rdatalist_t *rdatalist = NULL; 979 isc_result_t result; 980 dns_rdatatype_t rdtype; 981 dns_rdataclass_t rdclass; 982 dns_namelist_t *section = &msg->sections[DNS_SECTION_QUESTION]; 983 bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); 984 bool seen_problem = false; 985 bool free_name = false; 986 987 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { 988 name = NULL; 989 result = dns_message_gettempname(msg, &name); 990 if (result != ISC_R_SUCCESS) { 991 goto cleanup; 992 } 993 name->offsets = (unsigned char *)newoffsets(msg); 994 free_name = true; 995 996 /* 997 * Parse the name out of this packet. 998 */ 999 isc_buffer_remainingregion(source, &r); 1000 isc_buffer_setactive(source, r.length); 1001 result = getname(name, source, msg, dctx); 1002 if (result != ISC_R_SUCCESS) { 1003 goto cleanup; 1004 } 1005 1006 /* 1007 * Run through the section, looking to see if this name 1008 * is already there. If it is found, put back the allocated 1009 * name since we no longer need it, and set our name pointer 1010 * to point to the name we found. 1011 */ 1012 result = findname(&name2, name, section); 1013 1014 /* 1015 * If it is the first name in the section, accept it. 1016 * 1017 * If it is not, but is not the same as the name already 1018 * in the question section, append to the section. Note that 1019 * here in the question section this is illegal, so return 1020 * FORMERR. In the future, check the opcode to see if 1021 * this should be legal or not. In either case we no longer 1022 * need this name pointer. 1023 */ 1024 if (result != ISC_R_SUCCESS) { 1025 if (!ISC_LIST_EMPTY(*section)) { 1026 DO_ERROR(DNS_R_FORMERR); 1027 } 1028 ISC_LIST_APPEND(*section, name, link); 1029 free_name = false; 1030 } else { 1031 dns_message_puttempname(msg, &name); 1032 name = name2; 1033 name2 = NULL; 1034 free_name = false; 1035 } 1036 1037 /* 1038 * Get type and class. 1039 */ 1040 isc_buffer_remainingregion(source, &r); 1041 if (r.length < 4) { 1042 result = ISC_R_UNEXPECTEDEND; 1043 goto cleanup; 1044 } 1045 rdtype = isc_buffer_getuint16(source); 1046 rdclass = isc_buffer_getuint16(source); 1047 1048 /* 1049 * If this class is different than the one we already read, 1050 * this is an error. 1051 */ 1052 if (msg->rdclass_set == 0) { 1053 msg->rdclass = rdclass; 1054 msg->rdclass_set = 1; 1055 } else if (msg->rdclass != rdclass) { 1056 DO_ERROR(DNS_R_FORMERR); 1057 } 1058 1059 /* 1060 * Is this a TKEY query? 1061 */ 1062 if (rdtype == dns_rdatatype_tkey) { 1063 msg->tkey = 1; 1064 } 1065 1066 /* 1067 * Can't ask the same question twice. 1068 */ 1069 result = dns_message_find(name, rdclass, rdtype, 0, NULL); 1070 if (result == ISC_R_SUCCESS) { 1071 DO_ERROR(DNS_R_FORMERR); 1072 } 1073 1074 /* 1075 * Allocate a new rdatalist. 1076 */ 1077 rdatalist = newrdatalist(msg); 1078 if (rdatalist == NULL) { 1079 result = ISC_R_NOMEMORY; 1080 goto cleanup; 1081 } 1082 rdataset = isc_mempool_get(msg->rdspool); 1083 if (rdataset == NULL) { 1084 result = ISC_R_NOMEMORY; 1085 goto cleanup; 1086 } 1087 1088 /* 1089 * Convert rdatalist to rdataset, and attach the latter to 1090 * the name. 1091 */ 1092 rdatalist->type = rdtype; 1093 rdatalist->rdclass = rdclass; 1094 1095 dns_rdataset_init(rdataset); 1096 result = dns_rdatalist_tordataset(rdatalist, rdataset); 1097 if (result != ISC_R_SUCCESS) { 1098 goto cleanup; 1099 } 1100 1101 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 1102 1103 ISC_LIST_APPEND(name->list, rdataset, link); 1104 rdataset = NULL; 1105 } 1106 1107 if (seen_problem) { 1108 return (DNS_R_RECOVERABLE); 1109 } 1110 return (ISC_R_SUCCESS); 1111 1112 cleanup: 1113 if (rdataset != NULL) { 1114 INSIST(!dns_rdataset_isassociated(rdataset)); 1115 isc_mempool_put(msg->rdspool, rdataset); 1116 } 1117 if (free_name) { 1118 dns_message_puttempname(msg, &name); 1119 } 1120 1121 return (result); 1122 } 1123 1124 static bool 1125 update(dns_section_t section, dns_rdataclass_t rdclass) { 1126 if (section == DNS_SECTION_PREREQUISITE) { 1127 return (rdclass == dns_rdataclass_any || 1128 rdclass == dns_rdataclass_none); 1129 } 1130 if (section == DNS_SECTION_UPDATE) { 1131 return (rdclass == dns_rdataclass_any); 1132 } 1133 return (false); 1134 } 1135 1136 /* 1137 * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have 1138 * covering RRSIGs. 1139 */ 1140 static bool 1141 auth_signed(dns_namelist_t *section) { 1142 dns_name_t *name; 1143 1144 for (name = ISC_LIST_HEAD(*section); name != NULL; 1145 name = ISC_LIST_NEXT(name, link)) 1146 { 1147 int auth_dnssec = 0, auth_rrsig = 0; 1148 dns_rdataset_t *rds; 1149 1150 for (rds = ISC_LIST_HEAD(name->list); rds != NULL; 1151 rds = ISC_LIST_NEXT(rds, link)) 1152 { 1153 switch (rds->type) { 1154 case dns_rdatatype_ds: 1155 auth_dnssec |= 0x1; 1156 break; 1157 case dns_rdatatype_nsec: 1158 auth_dnssec |= 0x2; 1159 break; 1160 case dns_rdatatype_nsec3: 1161 auth_dnssec |= 0x4; 1162 break; 1163 case dns_rdatatype_rrsig: 1164 break; 1165 default: 1166 continue; 1167 } 1168 1169 switch (rds->covers) { 1170 case dns_rdatatype_ds: 1171 auth_rrsig |= 0x1; 1172 break; 1173 case dns_rdatatype_nsec: 1174 auth_rrsig |= 0x2; 1175 break; 1176 case dns_rdatatype_nsec3: 1177 auth_rrsig |= 0x4; 1178 break; 1179 default: 1180 break; 1181 } 1182 } 1183 1184 if (auth_dnssec != auth_rrsig) { 1185 return (false); 1186 } 1187 } 1188 1189 return (true); 1190 } 1191 1192 static isc_result_t 1193 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 1194 dns_section_t sectionid, unsigned int options) { 1195 isc_region_t r; 1196 unsigned int count, rdatalen; 1197 dns_name_t *name = NULL; 1198 dns_name_t *name2 = NULL; 1199 dns_rdataset_t *rdataset = NULL; 1200 dns_rdatalist_t *rdatalist = NULL; 1201 isc_result_t result; 1202 dns_rdatatype_t rdtype, covers; 1203 dns_rdataclass_t rdclass; 1204 dns_rdata_t *rdata = NULL; 1205 dns_ttl_t ttl; 1206 dns_namelist_t *section = &msg->sections[sectionid]; 1207 bool free_name = false, free_rdataset = false, seen_problem = false; 1208 bool preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0); 1209 bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); 1210 bool isedns, issigzero, istsig; 1211 1212 for (count = 0; count < msg->counts[sectionid]; count++) { 1213 int recstart = source->current; 1214 bool skip_name_search, skip_type_search; 1215 1216 skip_name_search = false; 1217 skip_type_search = false; 1218 free_rdataset = false; 1219 isedns = false; 1220 issigzero = false; 1221 istsig = false; 1222 1223 name = NULL; 1224 result = dns_message_gettempname(msg, &name); 1225 if (result != ISC_R_SUCCESS) { 1226 goto cleanup; 1227 } 1228 name->offsets = (unsigned char *)newoffsets(msg); 1229 free_name = true; 1230 1231 /* 1232 * Parse the name out of this packet. 1233 */ 1234 isc_buffer_remainingregion(source, &r); 1235 isc_buffer_setactive(source, r.length); 1236 result = getname(name, source, msg, dctx); 1237 if (result != ISC_R_SUCCESS) { 1238 goto cleanup; 1239 } 1240 1241 /* 1242 * Get type, class, ttl, and rdatalen. Verify that at least 1243 * rdatalen bytes remain. (Some of this is deferred to 1244 * later.) 1245 */ 1246 isc_buffer_remainingregion(source, &r); 1247 if (r.length < 2 + 2 + 4 + 2) { 1248 result = ISC_R_UNEXPECTEDEND; 1249 goto cleanup; 1250 } 1251 rdtype = isc_buffer_getuint16(source); 1252 rdclass = isc_buffer_getuint16(source); 1253 1254 /* 1255 * If there was no question section, we may not yet have 1256 * established a class. Do so now. 1257 */ 1258 if (msg->rdclass_set == 0 && 1259 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ 1260 rdtype != dns_rdatatype_tsig && /* class is ANY */ 1261 rdtype != dns_rdatatype_tkey) 1262 { /* class is undefined */ 1263 msg->rdclass = rdclass; 1264 msg->rdclass_set = 1; 1265 } 1266 1267 /* 1268 * If this class is different than the one in the question 1269 * section, bail. 1270 */ 1271 if (msg->opcode != dns_opcode_update && 1272 rdtype != dns_rdatatype_tsig && 1273 rdtype != dns_rdatatype_opt && 1274 rdtype != dns_rdatatype_key && /* in a TKEY query */ 1275 rdtype != dns_rdatatype_sig && /* SIG(0) */ 1276 rdtype != dns_rdatatype_tkey && /* Win2000 TKEY */ 1277 msg->rdclass != dns_rdataclass_any && 1278 msg->rdclass != rdclass) 1279 { 1280 DO_ERROR(DNS_R_FORMERR); 1281 } 1282 1283 /* 1284 * If this is not a TKEY query/response then the KEY 1285 * record's class needs to match. 1286 */ 1287 if (msg->opcode != dns_opcode_update && !msg->tkey && 1288 rdtype == dns_rdatatype_key && 1289 msg->rdclass != dns_rdataclass_any && 1290 msg->rdclass != rdclass) 1291 { 1292 DO_ERROR(DNS_R_FORMERR); 1293 } 1294 1295 /* 1296 * Special type handling for TSIG, OPT, and TKEY. 1297 */ 1298 if (rdtype == dns_rdatatype_tsig) { 1299 /* 1300 * If it is a tsig, verify that it is in the 1301 * additional data section. 1302 */ 1303 if (sectionid != DNS_SECTION_ADDITIONAL || 1304 rdclass != dns_rdataclass_any || 1305 count != msg->counts[sectionid] - 1) 1306 { 1307 DO_ERROR(DNS_R_BADTSIG); 1308 } else { 1309 skip_name_search = true; 1310 skip_type_search = true; 1311 istsig = true; 1312 } 1313 } else if (rdtype == dns_rdatatype_opt) { 1314 /* 1315 * The name of an OPT record must be ".", it 1316 * must be in the additional data section, and 1317 * it must be the first OPT we've seen. 1318 */ 1319 if (!dns_name_equal(dns_rootname, name) || 1320 sectionid != DNS_SECTION_ADDITIONAL || 1321 msg->opt != NULL) 1322 { 1323 DO_ERROR(DNS_R_FORMERR); 1324 } else { 1325 skip_name_search = true; 1326 skip_type_search = true; 1327 isedns = true; 1328 } 1329 } else if (rdtype == dns_rdatatype_tkey) { 1330 /* 1331 * A TKEY must be in the additional section if this 1332 * is a query, and the answer section if this is a 1333 * response. Unless it's a Win2000 client. 1334 * 1335 * Its class is ignored. 1336 */ 1337 dns_section_t tkeysection; 1338 1339 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) { 1340 tkeysection = DNS_SECTION_ADDITIONAL; 1341 } else { 1342 tkeysection = DNS_SECTION_ANSWER; 1343 } 1344 if (sectionid != tkeysection && 1345 sectionid != DNS_SECTION_ANSWER) { 1346 DO_ERROR(DNS_R_FORMERR); 1347 } 1348 } 1349 1350 /* 1351 * ... now get ttl and rdatalen, and check buffer. 1352 */ 1353 ttl = isc_buffer_getuint32(source); 1354 rdatalen = isc_buffer_getuint16(source); 1355 r.length -= (2 + 2 + 4 + 2); 1356 if (r.length < rdatalen) { 1357 result = ISC_R_UNEXPECTEDEND; 1358 goto cleanup; 1359 } 1360 1361 /* 1362 * Read the rdata from the wire format. Interpret the 1363 * rdata according to its actual class, even if it had a 1364 * DynDNS meta-class in the packet (unless this is a TSIG). 1365 * Then put the meta-class back into the finished rdata. 1366 */ 1367 rdata = newrdata(msg); 1368 if (rdata == NULL) { 1369 result = ISC_R_NOMEMORY; 1370 goto cleanup; 1371 } 1372 if (msg->opcode == dns_opcode_update && 1373 update(sectionid, rdclass)) { 1374 if (rdatalen != 0) { 1375 result = DNS_R_FORMERR; 1376 goto cleanup; 1377 } 1378 /* 1379 * When the rdata is empty, the data pointer is 1380 * never dereferenced, but it must still be non-NULL. 1381 * Casting 1 rather than "" avoids warnings about 1382 * discarding the const attribute of a string, 1383 * for compilers that would warn about such things. 1384 */ 1385 rdata->data = (unsigned char *)1; 1386 rdata->length = 0; 1387 rdata->rdclass = rdclass; 1388 rdata->type = rdtype; 1389 rdata->flags = DNS_RDATA_UPDATE; 1390 result = ISC_R_SUCCESS; 1391 } else if (rdclass == dns_rdataclass_none && 1392 msg->opcode == dns_opcode_update && 1393 sectionid == DNS_SECTION_UPDATE) 1394 { 1395 result = getrdata(source, msg, dctx, msg->rdclass, 1396 rdtype, rdatalen, rdata); 1397 } else { 1398 result = getrdata(source, msg, dctx, rdclass, rdtype, 1399 rdatalen, rdata); 1400 } 1401 if (result != ISC_R_SUCCESS) { 1402 goto cleanup; 1403 } 1404 rdata->rdclass = rdclass; 1405 if (rdtype == dns_rdatatype_rrsig && rdata->flags == 0) { 1406 covers = dns_rdata_covers(rdata); 1407 if (covers == 0) { 1408 DO_ERROR(DNS_R_FORMERR); 1409 } 1410 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1411 rdata->flags == 0) { 1412 covers = dns_rdata_covers(rdata); 1413 if (covers == 0) { 1414 if (sectionid != DNS_SECTION_ADDITIONAL || 1415 count != msg->counts[sectionid] - 1) { 1416 DO_ERROR(DNS_R_BADSIG0); 1417 } else { 1418 skip_name_search = true; 1419 skip_type_search = true; 1420 issigzero = true; 1421 } 1422 } else { 1423 if (msg->rdclass != dns_rdataclass_any && 1424 msg->rdclass != rdclass) { 1425 DO_ERROR(DNS_R_FORMERR); 1426 } 1427 } 1428 } else { 1429 covers = 0; 1430 } 1431 1432 /* 1433 * Check the ownername of NSEC3 records 1434 */ 1435 if (rdtype == dns_rdatatype_nsec3 && 1436 !dns_rdata_checkowner(name, msg->rdclass, rdtype, false)) 1437 { 1438 result = DNS_R_BADOWNERNAME; 1439 goto cleanup; 1440 } 1441 1442 /* 1443 * If we are doing a dynamic update or this is a meta-type, 1444 * don't bother searching for a name, just append this one 1445 * to the end of the message. 1446 */ 1447 if (preserve_order || msg->opcode == dns_opcode_update || 1448 skip_name_search) { 1449 if (!isedns && !istsig && !issigzero) { 1450 ISC_LIST_APPEND(*section, name, link); 1451 free_name = false; 1452 } 1453 } else { 1454 /* 1455 * Run through the section, looking to see if this name 1456 * is already there. If it is found, put back the 1457 * allocated name since we no longer need it, and set 1458 * our name pointer to point to the name we found. 1459 */ 1460 result = findname(&name2, name, section); 1461 1462 /* 1463 * If it is a new name, append to the section. 1464 */ 1465 if (result == ISC_R_SUCCESS) { 1466 dns_message_puttempname(msg, &name); 1467 name = name2; 1468 } else { 1469 ISC_LIST_APPEND(*section, name, link); 1470 } 1471 free_name = false; 1472 } 1473 1474 /* 1475 * Search name for the particular type and class. 1476 * Skip this stage if in update mode or this is a meta-type. 1477 */ 1478 if (preserve_order || msg->opcode == dns_opcode_update || 1479 skip_type_search) { 1480 result = ISC_R_NOTFOUND; 1481 } else { 1482 /* 1483 * If this is a type that can only occur in 1484 * the question section, fail. 1485 */ 1486 if (dns_rdatatype_questiononly(rdtype)) { 1487 DO_ERROR(DNS_R_FORMERR); 1488 } 1489 1490 rdataset = NULL; 1491 result = dns_message_find(name, rdclass, rdtype, covers, 1492 &rdataset); 1493 } 1494 1495 /* 1496 * If we found an rdataset that matches, we need to 1497 * append this rdata to that set. If we did not, we need 1498 * to create a new rdatalist, store the important bits there, 1499 * convert it to an rdataset, and link the latter to the name. 1500 * Yuck. When appending, make certain that the type isn't 1501 * a singleton type, such as SOA or CNAME. 1502 * 1503 * Note that this check will be bypassed when preserving order, 1504 * the opcode is an update, or the type search is skipped. 1505 */ 1506 if (result == ISC_R_SUCCESS) { 1507 if (dns_rdatatype_issingleton(rdtype)) { 1508 dns_rdata_t *first; 1509 dns_rdatalist_fromrdataset(rdataset, 1510 &rdatalist); 1511 first = ISC_LIST_HEAD(rdatalist->rdata); 1512 INSIST(first != NULL); 1513 if (dns_rdata_compare(rdata, first) != 0) { 1514 DO_ERROR(DNS_R_FORMERR); 1515 } 1516 } 1517 } 1518 1519 if (result == ISC_R_NOTFOUND) { 1520 rdataset = isc_mempool_get(msg->rdspool); 1521 if (rdataset == NULL) { 1522 result = ISC_R_NOMEMORY; 1523 goto cleanup; 1524 } 1525 free_rdataset = true; 1526 1527 rdatalist = newrdatalist(msg); 1528 if (rdatalist == NULL) { 1529 result = ISC_R_NOMEMORY; 1530 goto cleanup; 1531 } 1532 1533 rdatalist->type = rdtype; 1534 rdatalist->covers = covers; 1535 rdatalist->rdclass = rdclass; 1536 rdatalist->ttl = ttl; 1537 1538 dns_rdataset_init(rdataset); 1539 RUNTIME_CHECK( 1540 dns_rdatalist_tordataset(rdatalist, rdataset) == 1541 ISC_R_SUCCESS); 1542 dns_rdataset_setownercase(rdataset, name); 1543 1544 if (!isedns && !istsig && !issigzero) { 1545 ISC_LIST_APPEND(name->list, rdataset, link); 1546 free_rdataset = false; 1547 } 1548 } 1549 1550 /* 1551 * Minimize TTLs. 1552 * 1553 * Section 5.2 of RFC2181 says we should drop 1554 * nonauthoritative rrsets where the TTLs differ, but we 1555 * currently treat them the as if they were authoritative and 1556 * minimize them. 1557 */ 1558 if (ttl != rdataset->ttl) { 1559 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1560 if (ttl < rdataset->ttl) { 1561 rdataset->ttl = ttl; 1562 } 1563 } 1564 1565 /* Append this rdata to the rdataset. */ 1566 dns_rdatalist_fromrdataset(rdataset, &rdatalist); 1567 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1568 1569 /* 1570 * If this is an OPT, SIG(0) or TSIG record, remember it. 1571 * Also, set the extended rcode for TSIG. 1572 * 1573 * Note msg->opt, msg->sig0 and msg->tsig will only be 1574 * already set if best-effort parsing is enabled otherwise 1575 * there will only be at most one of each. 1576 */ 1577 if (isedns) { 1578 dns_rcode_t ercode; 1579 1580 msg->opt = rdataset; 1581 rdataset = NULL; 1582 free_rdataset = false; 1583 ercode = (dns_rcode_t)((msg->opt->ttl & 1584 DNS_MESSAGE_EDNSRCODE_MASK) >> 1585 20); 1586 msg->rcode |= ercode; 1587 dns_message_puttempname(msg, &name); 1588 free_name = false; 1589 } else if (issigzero) { 1590 msg->sig0 = rdataset; 1591 msg->sig0name = name; 1592 msg->sigstart = recstart; 1593 rdataset = NULL; 1594 free_rdataset = false; 1595 free_name = false; 1596 } else if (istsig) { 1597 msg->tsig = rdataset; 1598 msg->tsigname = name; 1599 msg->sigstart = recstart; 1600 /* 1601 * Windows doesn't like TSIG names to be compressed. 1602 */ 1603 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1604 rdataset = NULL; 1605 free_rdataset = false; 1606 free_name = false; 1607 } 1608 1609 if (seen_problem) { 1610 if (free_name) { 1611 dns_message_puttempname(msg, &name); 1612 } 1613 if (free_rdataset) { 1614 isc_mempool_put(msg->rdspool, rdataset); 1615 } 1616 free_name = free_rdataset = false; 1617 } 1618 INSIST(!free_name); 1619 INSIST(!free_rdataset); 1620 } 1621 1622 /* 1623 * If any of DS, NSEC or NSEC3 appeared in the 1624 * authority section of a query response without 1625 * a covering RRSIG, FORMERR 1626 */ 1627 if (sectionid == DNS_SECTION_AUTHORITY && 1628 msg->opcode == dns_opcode_query && 1629 ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) && 1630 ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && !preserve_order && 1631 !auth_signed(section)) 1632 { 1633 DO_ERROR(DNS_R_FORMERR); 1634 } 1635 1636 if (seen_problem) { 1637 return (DNS_R_RECOVERABLE); 1638 } 1639 return (ISC_R_SUCCESS); 1640 1641 cleanup: 1642 if (free_name) { 1643 dns_message_puttempname(msg, &name); 1644 } 1645 if (free_rdataset) { 1646 isc_mempool_put(msg->rdspool, rdataset); 1647 } 1648 1649 return (result); 1650 } 1651 1652 isc_result_t 1653 dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1654 unsigned int options) { 1655 isc_region_t r; 1656 dns_decompress_t dctx; 1657 isc_result_t ret; 1658 uint16_t tmpflags; 1659 isc_buffer_t origsource; 1660 bool seen_problem; 1661 bool ignore_tc; 1662 1663 REQUIRE(DNS_MESSAGE_VALID(msg)); 1664 REQUIRE(source != NULL); 1665 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1666 1667 seen_problem = false; 1668 ignore_tc = ((options & DNS_MESSAGEPARSE_IGNORETRUNCATION) != 0); 1669 1670 origsource = *source; 1671 1672 msg->header_ok = 0; 1673 msg->question_ok = 0; 1674 1675 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) { 1676 isc_buffer_usedregion(&origsource, &msg->saved); 1677 } else { 1678 msg->saved.length = isc_buffer_usedlength(&origsource); 1679 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1680 memmove(msg->saved.base, isc_buffer_base(&origsource), 1681 msg->saved.length); 1682 msg->free_saved = 1; 1683 } 1684 1685 isc_buffer_remainingregion(source, &r); 1686 if (r.length < DNS_MESSAGE_HEADERLEN) { 1687 return (ISC_R_UNEXPECTEDEND); 1688 } 1689 1690 msg->id = isc_buffer_getuint16(source); 1691 tmpflags = isc_buffer_getuint16(source); 1692 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) >> 1693 DNS_MESSAGE_OPCODE_SHIFT); 1694 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1695 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1696 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1697 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1698 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1699 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1700 1701 msg->header_ok = 1; 1702 msg->state = DNS_SECTION_QUESTION; 1703 1704 /* 1705 * -1 means no EDNS. 1706 */ 1707 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1708 1709 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1710 1711 ret = getquestions(source, msg, &dctx, options); 1712 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) { 1713 goto truncated; 1714 } 1715 if (ret == DNS_R_RECOVERABLE) { 1716 seen_problem = true; 1717 ret = ISC_R_SUCCESS; 1718 } 1719 if (ret != ISC_R_SUCCESS) { 1720 return (ret); 1721 } 1722 msg->question_ok = 1; 1723 1724 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1725 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) { 1726 goto truncated; 1727 } 1728 if (ret == DNS_R_RECOVERABLE) { 1729 seen_problem = true; 1730 ret = ISC_R_SUCCESS; 1731 } 1732 if (ret != ISC_R_SUCCESS) { 1733 return (ret); 1734 } 1735 1736 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1737 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) { 1738 goto truncated; 1739 } 1740 if (ret == DNS_R_RECOVERABLE) { 1741 seen_problem = true; 1742 ret = ISC_R_SUCCESS; 1743 } 1744 if (ret != ISC_R_SUCCESS) { 1745 return (ret); 1746 } 1747 1748 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1749 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) { 1750 goto truncated; 1751 } 1752 if (ret == DNS_R_RECOVERABLE) { 1753 seen_problem = true; 1754 ret = ISC_R_SUCCESS; 1755 } 1756 if (ret != ISC_R_SUCCESS) { 1757 return (ret); 1758 } 1759 1760 isc_buffer_remainingregion(source, &r); 1761 if (r.length != 0) { 1762 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1763 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1764 "message has %u byte(s) of trailing garbage", 1765 r.length); 1766 } 1767 1768 truncated: 1769 1770 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) { 1771 return (DNS_R_RECOVERABLE); 1772 } 1773 if (seen_problem) { 1774 return (DNS_R_RECOVERABLE); 1775 } 1776 return (ISC_R_SUCCESS); 1777 } 1778 1779 isc_result_t 1780 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1781 isc_buffer_t *buffer) { 1782 isc_region_t r; 1783 1784 REQUIRE(DNS_MESSAGE_VALID(msg)); 1785 REQUIRE(buffer != NULL); 1786 REQUIRE(msg->buffer == NULL); 1787 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1788 1789 msg->cctx = cctx; 1790 1791 /* 1792 * Erase the contents of this buffer. 1793 */ 1794 isc_buffer_clear(buffer); 1795 1796 /* 1797 * Make certain there is enough for at least the header in this 1798 * buffer. 1799 */ 1800 isc_buffer_availableregion(buffer, &r); 1801 if (r.length < DNS_MESSAGE_HEADERLEN) { 1802 return (ISC_R_NOSPACE); 1803 } 1804 1805 if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved) { 1806 return (ISC_R_NOSPACE); 1807 } 1808 1809 /* 1810 * Reserve enough space for the header in this buffer. 1811 */ 1812 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1813 1814 msg->buffer = buffer; 1815 1816 return (ISC_R_SUCCESS); 1817 } 1818 1819 isc_result_t 1820 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1821 isc_region_t r, rn; 1822 1823 REQUIRE(DNS_MESSAGE_VALID(msg)); 1824 REQUIRE(buffer != NULL); 1825 REQUIRE(msg->buffer != NULL); 1826 1827 /* 1828 * Ensure that the new buffer is empty, and has enough space to 1829 * hold the current contents. 1830 */ 1831 isc_buffer_clear(buffer); 1832 1833 isc_buffer_availableregion(buffer, &rn); 1834 isc_buffer_usedregion(msg->buffer, &r); 1835 REQUIRE(rn.length > r.length); 1836 1837 /* 1838 * Copy the contents from the old to the new buffer. 1839 */ 1840 isc_buffer_add(buffer, r.length); 1841 memmove(rn.base, r.base, r.length); 1842 1843 msg->buffer = buffer; 1844 1845 return (ISC_R_SUCCESS); 1846 } 1847 1848 void 1849 dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1850 REQUIRE(DNS_MESSAGE_VALID(msg)); 1851 REQUIRE(space <= msg->reserved); 1852 1853 msg->reserved -= space; 1854 } 1855 1856 isc_result_t 1857 dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1858 isc_region_t r; 1859 1860 REQUIRE(DNS_MESSAGE_VALID(msg)); 1861 1862 if (msg->buffer != NULL) { 1863 isc_buffer_availableregion(msg->buffer, &r); 1864 if (r.length < (space + msg->reserved)) { 1865 return (ISC_R_NOSPACE); 1866 } 1867 } 1868 1869 msg->reserved += space; 1870 1871 return (ISC_R_SUCCESS); 1872 } 1873 1874 static bool 1875 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1876 int pass_needed; 1877 1878 /* 1879 * If we are not rendering class IN, this ordering is bogus. 1880 */ 1881 if (rds->rdclass != dns_rdataclass_in) { 1882 return (false); 1883 } 1884 1885 switch (rds->type) { 1886 case dns_rdatatype_a: 1887 case dns_rdatatype_aaaa: 1888 if (preferred_glue == rds->type) { 1889 pass_needed = 4; 1890 } else { 1891 pass_needed = 3; 1892 } 1893 break; 1894 case dns_rdatatype_rrsig: 1895 case dns_rdatatype_dnskey: 1896 pass_needed = 2; 1897 break; 1898 default: 1899 pass_needed = 1; 1900 } 1901 1902 if (pass_needed >= pass) { 1903 return (false); 1904 } 1905 1906 return (true); 1907 } 1908 1909 static isc_result_t 1910 renderset(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 1911 dns_compress_t *cctx, isc_buffer_t *target, unsigned int reserved, 1912 unsigned int options, unsigned int *countp) { 1913 isc_result_t result; 1914 1915 /* 1916 * Shrink the space in the buffer by the reserved amount. 1917 */ 1918 if (target->length - target->used < reserved) { 1919 return (ISC_R_NOSPACE); 1920 } 1921 1922 target->length -= reserved; 1923 result = dns_rdataset_towire(rdataset, owner_name, cctx, target, 1924 options, countp); 1925 target->length += reserved; 1926 1927 return (result); 1928 } 1929 1930 static void 1931 maybe_clear_ad(dns_message_t *msg, dns_section_t sectionid) { 1932 if (msg->counts[sectionid] == 0 && 1933 (sectionid == DNS_SECTION_ANSWER || 1934 (sectionid == DNS_SECTION_AUTHORITY && 1935 msg->counts[DNS_SECTION_ANSWER] == 0))) 1936 { 1937 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1938 } 1939 } 1940 1941 isc_result_t 1942 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1943 unsigned int options) { 1944 dns_namelist_t *section; 1945 dns_name_t *name, *next_name; 1946 dns_rdataset_t *rdataset, *next_rdataset; 1947 unsigned int count, total; 1948 isc_result_t result; 1949 isc_buffer_t st; /* for rollbacks */ 1950 int pass; 1951 bool partial = false; 1952 unsigned int rd_options; 1953 dns_rdatatype_t preferred_glue = 0; 1954 1955 REQUIRE(DNS_MESSAGE_VALID(msg)); 1956 REQUIRE(msg->buffer != NULL); 1957 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1958 1959 section = &msg->sections[sectionid]; 1960 1961 if ((sectionid == DNS_SECTION_ADDITIONAL) && 1962 (options & DNS_MESSAGERENDER_ORDERED) == 0) 1963 { 1964 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1965 preferred_glue = dns_rdatatype_a; 1966 pass = 4; 1967 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1968 preferred_glue = dns_rdatatype_aaaa; 1969 pass = 4; 1970 } else { 1971 pass = 3; 1972 } 1973 } else { 1974 pass = 1; 1975 } 1976 1977 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) { 1978 rd_options = 0; 1979 } else { 1980 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1981 } 1982 1983 /* 1984 * Shrink the space in the buffer by the reserved amount. 1985 */ 1986 if (msg->buffer->length - msg->buffer->used < msg->reserved) { 1987 return (ISC_R_NOSPACE); 1988 } 1989 msg->buffer->length -= msg->reserved; 1990 1991 total = 0; 1992 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) { 1993 partial = true; 1994 } 1995 1996 /* 1997 * Render required glue first. Set TC if it won't fit. 1998 */ 1999 name = ISC_LIST_HEAD(*section); 2000 if (name != NULL) { 2001 rdataset = ISC_LIST_HEAD(name->list); 2002 if (rdataset != NULL && 2003 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 2004 0 && 2005 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) 2006 { 2007 const void *order_arg = &msg->order_arg; 2008 st = *(msg->buffer); 2009 count = 0; 2010 if (partial) { 2011 result = dns_rdataset_towirepartial( 2012 rdataset, name, msg->cctx, msg->buffer, 2013 msg->order, order_arg, rd_options, 2014 &count, NULL); 2015 } else { 2016 result = dns_rdataset_towiresorted( 2017 rdataset, name, msg->cctx, msg->buffer, 2018 msg->order, order_arg, rd_options, 2019 &count); 2020 } 2021 total += count; 2022 if (partial && result == ISC_R_NOSPACE) { 2023 msg->flags |= DNS_MESSAGEFLAG_TC; 2024 msg->buffer->length += msg->reserved; 2025 msg->counts[sectionid] += total; 2026 return (result); 2027 } 2028 if (result == ISC_R_NOSPACE) { 2029 msg->flags |= DNS_MESSAGEFLAG_TC; 2030 } 2031 if (result != ISC_R_SUCCESS) { 2032 INSIST(st.used < 65536); 2033 dns_compress_rollback(msg->cctx, 2034 (uint16_t)st.used); 2035 *(msg->buffer) = st; /* rollback */ 2036 msg->buffer->length += msg->reserved; 2037 msg->counts[sectionid] += total; 2038 return (result); 2039 } 2040 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 2041 } 2042 } 2043 2044 do { 2045 name = ISC_LIST_HEAD(*section); 2046 if (name == NULL) { 2047 msg->buffer->length += msg->reserved; 2048 msg->counts[sectionid] += total; 2049 return (ISC_R_SUCCESS); 2050 } 2051 2052 while (name != NULL) { 2053 next_name = ISC_LIST_NEXT(name, link); 2054 2055 rdataset = ISC_LIST_HEAD(name->list); 2056 while (rdataset != NULL) { 2057 next_rdataset = ISC_LIST_NEXT(rdataset, link); 2058 2059 if ((rdataset->attributes & 2060 DNS_RDATASETATTR_RENDERED) != 0) { 2061 goto next; 2062 } 2063 2064 if (((options & DNS_MESSAGERENDER_ORDERED) == 2065 0) && 2066 (sectionid == DNS_SECTION_ADDITIONAL) && 2067 wrong_priority(rdataset, pass, 2068 preferred_glue)) 2069 { 2070 goto next; 2071 } 2072 2073 st = *(msg->buffer); 2074 2075 count = 0; 2076 if (partial) { 2077 result = dns_rdataset_towirepartial( 2078 rdataset, name, msg->cctx, 2079 msg->buffer, msg->order, 2080 &msg->order_arg, rd_options, 2081 &count, NULL); 2082 } else { 2083 result = dns_rdataset_towiresorted( 2084 rdataset, name, msg->cctx, 2085 msg->buffer, msg->order, 2086 &msg->order_arg, rd_options, 2087 &count); 2088 } 2089 2090 total += count; 2091 2092 /* 2093 * If out of space, record stats on what we 2094 * rendered so far, and return that status. 2095 * 2096 * XXXMLG Need to change this when 2097 * dns_rdataset_towire() can render partial 2098 * sets starting at some arbitrary point in the 2099 * set. This will include setting a bit in the 2100 * rdataset to indicate that a partial 2101 * rendering was done, and some state saved 2102 * somewhere (probably in the message struct) 2103 * to indicate where to continue from. 2104 */ 2105 if (partial && result == ISC_R_NOSPACE) { 2106 msg->buffer->length += msg->reserved; 2107 msg->counts[sectionid] += total; 2108 return (result); 2109 } 2110 if (result != ISC_R_SUCCESS) { 2111 INSIST(st.used < 65536); 2112 dns_compress_rollback( 2113 msg->cctx, (uint16_t)st.used); 2114 *(msg->buffer) = st; /* rollback */ 2115 msg->buffer->length += msg->reserved; 2116 msg->counts[sectionid] += total; 2117 maybe_clear_ad(msg, sectionid); 2118 return (result); 2119 } 2120 2121 /* 2122 * If we have rendered non-validated data, 2123 * ensure that the AD bit is not set. 2124 */ 2125 if (rdataset->trust != dns_trust_secure && 2126 (sectionid == DNS_SECTION_ANSWER || 2127 sectionid == DNS_SECTION_AUTHORITY)) 2128 { 2129 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2130 } 2131 if (OPTOUT(rdataset)) { 2132 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2133 } 2134 2135 rdataset->attributes |= 2136 DNS_RDATASETATTR_RENDERED; 2137 2138 next: 2139 rdataset = next_rdataset; 2140 } 2141 2142 name = next_name; 2143 } 2144 } while (--pass != 0); 2145 2146 msg->buffer->length += msg->reserved; 2147 msg->counts[sectionid] += total; 2148 2149 return (ISC_R_SUCCESS); 2150 } 2151 2152 void 2153 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 2154 uint16_t tmp; 2155 isc_region_t r; 2156 2157 REQUIRE(DNS_MESSAGE_VALID(msg)); 2158 REQUIRE(target != NULL); 2159 2160 isc_buffer_availableregion(target, &r); 2161 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 2162 2163 isc_buffer_putuint16(target, msg->id); 2164 2165 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) & 2166 DNS_MESSAGE_OPCODE_MASK); 2167 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 2168 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 2169 2170 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 2171 msg->counts[DNS_SECTION_ANSWER] < 65536 && 2172 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 2173 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 2174 2175 isc_buffer_putuint16(target, tmp); 2176 isc_buffer_putuint16(target, 2177 (uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2178 isc_buffer_putuint16(target, (uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2179 isc_buffer_putuint16(target, 2180 (uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2181 isc_buffer_putuint16(target, 2182 (uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2183 } 2184 2185 isc_result_t 2186 dns_message_renderend(dns_message_t *msg) { 2187 isc_buffer_t tmpbuf; 2188 isc_region_t r; 2189 int result; 2190 unsigned int count; 2191 2192 REQUIRE(DNS_MESSAGE_VALID(msg)); 2193 REQUIRE(msg->buffer != NULL); 2194 2195 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2196 /* 2197 * We have an extended rcode but are not using EDNS. 2198 */ 2199 return (DNS_R_FORMERR); 2200 } 2201 2202 /* 2203 * If we're adding a OPT, TSIG or SIG(0) to a truncated message, 2204 * clear all rdatasets from the message except for the question 2205 * before adding the OPT, TSIG or SIG(0). If the question doesn't 2206 * fit, don't include it. 2207 */ 2208 if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) && 2209 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2210 { 2211 isc_buffer_t *buf; 2212 2213 msgresetnames(msg, DNS_SECTION_ANSWER); 2214 buf = msg->buffer; 2215 dns_message_renderreset(msg); 2216 msg->buffer = buf; 2217 isc_buffer_clear(msg->buffer); 2218 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2219 dns_compress_rollback(msg->cctx, 0); 2220 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2221 0); 2222 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) { 2223 return (result); 2224 } 2225 } 2226 2227 /* 2228 * If we've got an OPT record, render it. 2229 */ 2230 if (msg->opt != NULL) { 2231 dns_message_renderrelease(msg, msg->opt_reserved); 2232 msg->opt_reserved = 0; 2233 /* 2234 * Set the extended rcode. Cast msg->rcode to dns_ttl_t 2235 * so that we do a unsigned shift. 2236 */ 2237 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2238 msg->opt->ttl |= (((dns_ttl_t)(msg->rcode) << 20) & 2239 DNS_MESSAGE_EDNSRCODE_MASK); 2240 /* 2241 * Render. 2242 */ 2243 count = 0; 2244 result = renderset(msg->opt, dns_rootname, msg->cctx, 2245 msg->buffer, msg->reserved, 0, &count); 2246 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2247 if (result != ISC_R_SUCCESS) { 2248 return (result); 2249 } 2250 } 2251 2252 /* 2253 * Deal with EDNS padding. 2254 * 2255 * padding_off is the length of the OPT with the 0-length PAD 2256 * at the end. 2257 */ 2258 if (msg->padding_off > 0) { 2259 unsigned char *cp = isc_buffer_used(msg->buffer); 2260 unsigned int used, remaining; 2261 uint16_t len, padsize = 0; 2262 2263 /* Check PAD */ 2264 if ((cp[-4] != 0) || (cp[-3] != DNS_OPT_PAD) || (cp[-2] != 0) || 2265 (cp[-1] != 0)) { 2266 return (ISC_R_UNEXPECTED); 2267 } 2268 2269 /* 2270 * Zero-fill the PAD to the computed size; 2271 * patch PAD length and OPT rdlength 2272 */ 2273 2274 /* Aligned used length + reserved to padding block */ 2275 used = isc_buffer_usedlength(msg->buffer); 2276 if (msg->padding != 0) { 2277 padsize = ((uint16_t)used + msg->reserved) % 2278 msg->padding; 2279 } 2280 if (padsize != 0) { 2281 padsize = msg->padding - padsize; 2282 } 2283 /* Stay below the available length */ 2284 remaining = isc_buffer_availablelength(msg->buffer); 2285 if (padsize > remaining) { 2286 padsize = remaining; 2287 } 2288 2289 isc_buffer_add(msg->buffer, padsize); 2290 memset(cp, 0, padsize); 2291 cp[-2] = (unsigned char)((padsize & 0xff00U) >> 8); 2292 cp[-1] = (unsigned char)(padsize & 0x00ffU); 2293 cp -= msg->padding_off; 2294 len = ((uint16_t)(cp[-2])) << 8; 2295 len |= ((uint16_t)(cp[-1])); 2296 len += padsize; 2297 cp[-2] = (unsigned char)((len & 0xff00U) >> 8); 2298 cp[-1] = (unsigned char)(len & 0x00ffU); 2299 } 2300 2301 /* 2302 * If we're adding a TSIG record, generate and render it. 2303 */ 2304 if (msg->tsigkey != NULL) { 2305 dns_message_renderrelease(msg, msg->sig_reserved); 2306 msg->sig_reserved = 0; 2307 result = dns_tsig_sign(msg); 2308 if (result != ISC_R_SUCCESS) { 2309 return (result); 2310 } 2311 count = 0; 2312 result = renderset(msg->tsig, msg->tsigname, msg->cctx, 2313 msg->buffer, msg->reserved, 0, &count); 2314 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2315 if (result != ISC_R_SUCCESS) { 2316 return (result); 2317 } 2318 } 2319 2320 /* 2321 * If we're adding a SIG(0) record, generate and render it. 2322 */ 2323 if (msg->sig0key != NULL) { 2324 dns_message_renderrelease(msg, msg->sig_reserved); 2325 msg->sig_reserved = 0; 2326 result = dns_dnssec_signmessage(msg, msg->sig0key); 2327 if (result != ISC_R_SUCCESS) { 2328 return (result); 2329 } 2330 count = 0; 2331 /* 2332 * Note: dns_rootname is used here, not msg->sig0name, since 2333 * the owner name of a SIG(0) is irrelevant, and will not 2334 * be set in a message being rendered. 2335 */ 2336 result = renderset(msg->sig0, dns_rootname, msg->cctx, 2337 msg->buffer, msg->reserved, 0, &count); 2338 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2339 if (result != ISC_R_SUCCESS) { 2340 return (result); 2341 } 2342 } 2343 2344 isc_buffer_usedregion(msg->buffer, &r); 2345 isc_buffer_init(&tmpbuf, r.base, r.length); 2346 2347 dns_message_renderheader(msg, &tmpbuf); 2348 2349 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2350 2351 return (ISC_R_SUCCESS); 2352 } 2353 2354 void 2355 dns_message_renderreset(dns_message_t *msg) { 2356 unsigned int i; 2357 dns_name_t *name; 2358 dns_rdataset_t *rds; 2359 2360 /* 2361 * Reset the message so that it may be rendered again. 2362 */ 2363 2364 REQUIRE(DNS_MESSAGE_VALID(msg)); 2365 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2366 2367 msg->buffer = NULL; 2368 2369 for (i = 0; i < DNS_SECTION_MAX; i++) { 2370 msg->cursors[i] = NULL; 2371 msg->counts[i] = 0; 2372 for (name = ISC_LIST_HEAD(msg->sections[i]); name != NULL; 2373 name = ISC_LIST_NEXT(name, link)) 2374 { 2375 for (rds = ISC_LIST_HEAD(name->list); rds != NULL; 2376 rds = ISC_LIST_NEXT(rds, link)) 2377 { 2378 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2379 } 2380 } 2381 } 2382 if (msg->tsigname != NULL) { 2383 dns_message_puttempname(msg, &msg->tsigname); 2384 } 2385 if (msg->tsig != NULL) { 2386 dns_rdataset_disassociate(msg->tsig); 2387 dns_message_puttemprdataset(msg, &msg->tsig); 2388 } 2389 if (msg->sig0 != NULL) { 2390 dns_rdataset_disassociate(msg->sig0); 2391 dns_message_puttemprdataset(msg, &msg->sig0); 2392 } 2393 } 2394 2395 isc_result_t 2396 dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2397 REQUIRE(DNS_MESSAGE_VALID(msg)); 2398 REQUIRE(VALID_NAMED_SECTION(section)); 2399 2400 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2401 2402 if (msg->cursors[section] == NULL) { 2403 return (ISC_R_NOMORE); 2404 } 2405 2406 return (ISC_R_SUCCESS); 2407 } 2408 2409 isc_result_t 2410 dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2411 REQUIRE(DNS_MESSAGE_VALID(msg)); 2412 REQUIRE(VALID_NAMED_SECTION(section)); 2413 REQUIRE(msg->cursors[section] != NULL); 2414 2415 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2416 2417 if (msg->cursors[section] == NULL) { 2418 return (ISC_R_NOMORE); 2419 } 2420 2421 return (ISC_R_SUCCESS); 2422 } 2423 2424 void 2425 dns_message_currentname(dns_message_t *msg, dns_section_t section, 2426 dns_name_t **name) { 2427 REQUIRE(DNS_MESSAGE_VALID(msg)); 2428 REQUIRE(VALID_NAMED_SECTION(section)); 2429 REQUIRE(name != NULL && *name == NULL); 2430 REQUIRE(msg->cursors[section] != NULL); 2431 2432 *name = msg->cursors[section]; 2433 } 2434 2435 isc_result_t 2436 dns_message_findname(dns_message_t *msg, dns_section_t section, 2437 const dns_name_t *target, dns_rdatatype_t type, 2438 dns_rdatatype_t covers, dns_name_t **name, 2439 dns_rdataset_t **rdataset) { 2440 dns_name_t *foundname; 2441 isc_result_t result; 2442 2443 /* 2444 * XXX These requirements are probably too intensive, especially 2445 * where things can be NULL, but as they are they ensure that if 2446 * something is NON-NULL, indicating that the caller expects it 2447 * to be filled in, that we can in fact fill it in. 2448 */ 2449 REQUIRE(msg != NULL); 2450 REQUIRE(VALID_SECTION(section)); 2451 REQUIRE(target != NULL); 2452 REQUIRE(name == NULL || *name == NULL); 2453 2454 if (type == dns_rdatatype_any) { 2455 REQUIRE(rdataset == NULL); 2456 } else { 2457 REQUIRE(rdataset == NULL || *rdataset == NULL); 2458 } 2459 2460 result = findname(&foundname, target, &msg->sections[section]); 2461 2462 if (result == ISC_R_NOTFOUND) { 2463 return (DNS_R_NXDOMAIN); 2464 } else if (result != ISC_R_SUCCESS) { 2465 return (result); 2466 } 2467 2468 if (name != NULL) { 2469 *name = foundname; 2470 } 2471 2472 /* 2473 * And now look for the type. 2474 */ 2475 if (ISC_UNLIKELY(type == dns_rdatatype_any)) { 2476 return (ISC_R_SUCCESS); 2477 } 2478 2479 result = dns_message_findtype(foundname, type, covers, rdataset); 2480 if (result == ISC_R_NOTFOUND) { 2481 return (DNS_R_NXRRSET); 2482 } 2483 2484 return (result); 2485 } 2486 2487 void 2488 dns_message_movename(dns_message_t *msg, dns_name_t *name, 2489 dns_section_t fromsection, dns_section_t tosection) { 2490 REQUIRE(msg != NULL); 2491 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2492 REQUIRE(name != NULL); 2493 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2494 REQUIRE(VALID_NAMED_SECTION(tosection)); 2495 2496 /* 2497 * Unlink the name from the old section 2498 */ 2499 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2500 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2501 } 2502 2503 void 2504 dns_message_addname(dns_message_t *msg, dns_name_t *name, 2505 dns_section_t section) { 2506 REQUIRE(msg != NULL); 2507 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2508 REQUIRE(name != NULL); 2509 REQUIRE(VALID_NAMED_SECTION(section)); 2510 2511 ISC_LIST_APPEND(msg->sections[section], name, link); 2512 } 2513 2514 void 2515 dns_message_removename(dns_message_t *msg, dns_name_t *name, 2516 dns_section_t section) { 2517 REQUIRE(msg != NULL); 2518 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2519 REQUIRE(name != NULL); 2520 REQUIRE(VALID_NAMED_SECTION(section)); 2521 2522 ISC_LIST_UNLINK(msg->sections[section], name, link); 2523 } 2524 2525 isc_result_t 2526 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2527 dns_fixedname_t *fn = NULL; 2528 2529 REQUIRE(DNS_MESSAGE_VALID(msg)); 2530 REQUIRE(item != NULL && *item == NULL); 2531 2532 fn = isc_mempool_get(msg->namepool); 2533 if (fn == NULL) { 2534 return (ISC_R_NOMEMORY); 2535 } 2536 *item = dns_fixedname_initname(fn); 2537 2538 return (ISC_R_SUCCESS); 2539 } 2540 2541 isc_result_t 2542 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2543 REQUIRE(DNS_MESSAGE_VALID(msg)); 2544 REQUIRE(item != NULL && *item == NULL); 2545 2546 *item = newrdata(msg); 2547 if (*item == NULL) { 2548 return (ISC_R_NOMEMORY); 2549 } 2550 2551 return (ISC_R_SUCCESS); 2552 } 2553 2554 isc_result_t 2555 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2556 REQUIRE(DNS_MESSAGE_VALID(msg)); 2557 REQUIRE(item != NULL && *item == NULL); 2558 2559 *item = isc_mempool_get(msg->rdspool); 2560 if (*item == NULL) { 2561 return (ISC_R_NOMEMORY); 2562 } 2563 2564 dns_rdataset_init(*item); 2565 return (ISC_R_SUCCESS); 2566 } 2567 2568 isc_result_t 2569 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2570 REQUIRE(DNS_MESSAGE_VALID(msg)); 2571 REQUIRE(item != NULL && *item == NULL); 2572 2573 *item = newrdatalist(msg); 2574 if (*item == NULL) { 2575 return (ISC_R_NOMEMORY); 2576 } 2577 2578 return (ISC_R_SUCCESS); 2579 } 2580 2581 void 2582 dns_message_puttempname(dns_message_t *msg, dns_name_t **itemp) { 2583 dns_name_t *item = NULL; 2584 2585 REQUIRE(DNS_MESSAGE_VALID(msg)); 2586 REQUIRE(itemp != NULL && *itemp != NULL); 2587 2588 item = *itemp; 2589 *itemp = NULL; 2590 2591 REQUIRE(!ISC_LINK_LINKED(item, link)); 2592 REQUIRE(ISC_LIST_HEAD(item->list) == NULL); 2593 2594 /* 2595 * we need to check this in case dns_name_dup() was used. 2596 */ 2597 if (dns_name_dynamic(item)) { 2598 dns_name_free(item, msg->mctx); 2599 } 2600 2601 /* 2602 * 'name' is the first field in dns_fixedname_t, so putting 2603 * back the address of name is the same as putting back 2604 * the fixedname. 2605 */ 2606 isc_mempool_put(msg->namepool, item); 2607 } 2608 2609 void 2610 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2611 REQUIRE(DNS_MESSAGE_VALID(msg)); 2612 REQUIRE(item != NULL && *item != NULL); 2613 2614 releaserdata(msg, *item); 2615 *item = NULL; 2616 } 2617 2618 void 2619 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2620 REQUIRE(DNS_MESSAGE_VALID(msg)); 2621 REQUIRE(item != NULL && *item != NULL); 2622 2623 REQUIRE(!dns_rdataset_isassociated(*item)); 2624 isc_mempool_put(msg->rdspool, *item); 2625 *item = NULL; 2626 } 2627 2628 void 2629 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2630 REQUIRE(DNS_MESSAGE_VALID(msg)); 2631 REQUIRE(item != NULL && *item != NULL); 2632 2633 releaserdatalist(msg, *item); 2634 *item = NULL; 2635 } 2636 2637 isc_result_t 2638 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2639 unsigned int *flagsp) { 2640 isc_region_t r; 2641 isc_buffer_t buffer; 2642 dns_messageid_t id; 2643 unsigned int flags; 2644 2645 REQUIRE(source != NULL); 2646 2647 buffer = *source; 2648 2649 isc_buffer_remainingregion(&buffer, &r); 2650 if (r.length < DNS_MESSAGE_HEADERLEN) { 2651 return (ISC_R_UNEXPECTEDEND); 2652 } 2653 2654 id = isc_buffer_getuint16(&buffer); 2655 flags = isc_buffer_getuint16(&buffer); 2656 flags &= DNS_MESSAGE_FLAG_MASK; 2657 2658 if (flagsp != NULL) { 2659 *flagsp = flags; 2660 } 2661 if (idp != NULL) { 2662 *idp = id; 2663 } 2664 2665 return (ISC_R_SUCCESS); 2666 } 2667 2668 isc_result_t 2669 dns_message_reply(dns_message_t *msg, bool want_question_section) { 2670 unsigned int clear_from; 2671 isc_result_t result; 2672 2673 REQUIRE(DNS_MESSAGE_VALID(msg)); 2674 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2675 2676 if (!msg->header_ok) { 2677 return (DNS_R_FORMERR); 2678 } 2679 if (msg->opcode != dns_opcode_query && msg->opcode != dns_opcode_notify) 2680 { 2681 want_question_section = false; 2682 } 2683 if (msg->opcode == dns_opcode_update) { 2684 clear_from = DNS_SECTION_PREREQUISITE; 2685 } else if (want_question_section) { 2686 if (!msg->question_ok) { 2687 return (DNS_R_FORMERR); 2688 } 2689 clear_from = DNS_SECTION_ANSWER; 2690 } else { 2691 clear_from = DNS_SECTION_QUESTION; 2692 } 2693 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2694 msgresetnames(msg, clear_from); 2695 msgresetopt(msg); 2696 msgresetsigs(msg, true); 2697 msginitprivate(msg); 2698 /* 2699 * We now clear most flags and then set QR, ensuring that the 2700 * reply's flags will be in a reasonable state. 2701 */ 2702 if (msg->opcode == dns_opcode_query) { 2703 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2704 } else { 2705 msg->flags = 0; 2706 } 2707 msg->flags |= DNS_MESSAGEFLAG_QR; 2708 2709 /* 2710 * This saves the query TSIG status, if the query was signed, and 2711 * reserves space in the reply for the TSIG. 2712 */ 2713 if (msg->tsigkey != NULL) { 2714 unsigned int otherlen = 0; 2715 msg->querytsigstatus = msg->tsigstatus; 2716 msg->tsigstatus = dns_rcode_noerror; 2717 if (msg->querytsigstatus == dns_tsigerror_badtime) { 2718 otherlen = 6; 2719 } 2720 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2721 result = dns_message_renderreserve(msg, msg->sig_reserved); 2722 if (result != ISC_R_SUCCESS) { 2723 msg->sig_reserved = 0; 2724 return (result); 2725 } 2726 } 2727 if (msg->saved.base != NULL) { 2728 msg->query.base = msg->saved.base; 2729 msg->query.length = msg->saved.length; 2730 msg->free_query = msg->free_saved; 2731 msg->saved.base = NULL; 2732 msg->saved.length = 0; 2733 msg->free_saved = 0; 2734 } 2735 2736 return (ISC_R_SUCCESS); 2737 } 2738 2739 dns_rdataset_t * 2740 dns_message_getopt(dns_message_t *msg) { 2741 /* 2742 * Get the OPT record for 'msg'. 2743 */ 2744 2745 REQUIRE(DNS_MESSAGE_VALID(msg)); 2746 2747 return (msg->opt); 2748 } 2749 2750 isc_result_t 2751 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2752 isc_result_t result; 2753 dns_rdata_t rdata = DNS_RDATA_INIT; 2754 2755 /* 2756 * Set the OPT record for 'msg'. 2757 */ 2758 2759 /* 2760 * The space required for an OPT record is: 2761 * 2762 * 1 byte for the name 2763 * 2 bytes for the type 2764 * 2 bytes for the class 2765 * 4 bytes for the ttl 2766 * 2 bytes for the rdata length 2767 * --------------------------------- 2768 * 11 bytes 2769 * 2770 * plus the length of the rdata. 2771 */ 2772 2773 REQUIRE(DNS_MESSAGE_VALID(msg)); 2774 REQUIRE(opt->type == dns_rdatatype_opt); 2775 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2776 REQUIRE(msg->state == DNS_SECTION_ANY); 2777 2778 msgresetopt(msg); 2779 2780 result = dns_rdataset_first(opt); 2781 if (result != ISC_R_SUCCESS) { 2782 goto cleanup; 2783 } 2784 dns_rdataset_current(opt, &rdata); 2785 msg->opt_reserved = 11 + rdata.length; 2786 result = dns_message_renderreserve(msg, msg->opt_reserved); 2787 if (result != ISC_R_SUCCESS) { 2788 msg->opt_reserved = 0; 2789 goto cleanup; 2790 } 2791 2792 msg->opt = opt; 2793 2794 return (ISC_R_SUCCESS); 2795 2796 cleanup: 2797 dns_rdataset_disassociate(opt); 2798 dns_message_puttemprdataset(msg, &opt); 2799 return (result); 2800 } 2801 2802 dns_rdataset_t * 2803 dns_message_gettsig(dns_message_t *msg, const dns_name_t **owner) { 2804 /* 2805 * Get the TSIG record and owner for 'msg'. 2806 */ 2807 2808 REQUIRE(DNS_MESSAGE_VALID(msg)); 2809 REQUIRE(owner == NULL || *owner == NULL); 2810 2811 if (owner != NULL) { 2812 *owner = msg->tsigname; 2813 } 2814 return (msg->tsig); 2815 } 2816 2817 isc_result_t 2818 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2819 isc_result_t result; 2820 2821 /* 2822 * Set the TSIG key for 'msg' 2823 */ 2824 2825 REQUIRE(DNS_MESSAGE_VALID(msg)); 2826 2827 if (key == NULL && msg->tsigkey != NULL) { 2828 if (msg->sig_reserved != 0) { 2829 dns_message_renderrelease(msg, msg->sig_reserved); 2830 msg->sig_reserved = 0; 2831 } 2832 dns_tsigkey_detach(&msg->tsigkey); 2833 } 2834 if (key != NULL) { 2835 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2836 dns_tsigkey_attach(key, &msg->tsigkey); 2837 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2838 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2839 result = dns_message_renderreserve(msg, 2840 msg->sig_reserved); 2841 if (result != ISC_R_SUCCESS) { 2842 dns_tsigkey_detach(&msg->tsigkey); 2843 msg->sig_reserved = 0; 2844 return (result); 2845 } 2846 } 2847 } 2848 return (ISC_R_SUCCESS); 2849 } 2850 2851 dns_tsigkey_t * 2852 dns_message_gettsigkey(dns_message_t *msg) { 2853 /* 2854 * Get the TSIG key for 'msg' 2855 */ 2856 2857 REQUIRE(DNS_MESSAGE_VALID(msg)); 2858 2859 return (msg->tsigkey); 2860 } 2861 2862 isc_result_t 2863 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2864 dns_rdata_t *rdata = NULL; 2865 dns_rdatalist_t *list = NULL; 2866 dns_rdataset_t *set = NULL; 2867 isc_buffer_t *buf = NULL; 2868 isc_region_t r; 2869 isc_result_t result; 2870 2871 REQUIRE(DNS_MESSAGE_VALID(msg)); 2872 REQUIRE(msg->querytsig == NULL); 2873 2874 if (querytsig == NULL) { 2875 return (ISC_R_SUCCESS); 2876 } 2877 2878 result = dns_message_gettemprdata(msg, &rdata); 2879 if (result != ISC_R_SUCCESS) { 2880 goto cleanup; 2881 } 2882 2883 result = dns_message_gettemprdatalist(msg, &list); 2884 if (result != ISC_R_SUCCESS) { 2885 goto cleanup; 2886 } 2887 result = dns_message_gettemprdataset(msg, &set); 2888 if (result != ISC_R_SUCCESS) { 2889 goto cleanup; 2890 } 2891 2892 isc_buffer_usedregion(querytsig, &r); 2893 isc_buffer_allocate(msg->mctx, &buf, r.length); 2894 isc_buffer_putmem(buf, r.base, r.length); 2895 isc_buffer_usedregion(buf, &r); 2896 dns_rdata_init(rdata); 2897 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2898 dns_message_takebuffer(msg, &buf); 2899 ISC_LIST_APPEND(list->rdata, rdata, link); 2900 result = dns_rdatalist_tordataset(list, set); 2901 if (result != ISC_R_SUCCESS) { 2902 goto cleanup; 2903 } 2904 2905 msg->querytsig = set; 2906 2907 return (result); 2908 2909 cleanup: 2910 if (rdata != NULL) { 2911 dns_message_puttemprdata(msg, &rdata); 2912 } 2913 if (list != NULL) { 2914 dns_message_puttemprdatalist(msg, &list); 2915 } 2916 if (set != NULL) { 2917 dns_message_puttemprdataset(msg, &set); 2918 } 2919 return (ISC_R_NOMEMORY); 2920 } 2921 2922 isc_result_t 2923 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2924 isc_buffer_t **querytsig) { 2925 isc_result_t result; 2926 dns_rdata_t rdata = DNS_RDATA_INIT; 2927 isc_region_t r; 2928 2929 REQUIRE(DNS_MESSAGE_VALID(msg)); 2930 REQUIRE(mctx != NULL); 2931 REQUIRE(querytsig != NULL && *querytsig == NULL); 2932 2933 if (msg->tsig == NULL) { 2934 return (ISC_R_SUCCESS); 2935 } 2936 2937 result = dns_rdataset_first(msg->tsig); 2938 if (result != ISC_R_SUCCESS) { 2939 return (result); 2940 } 2941 dns_rdataset_current(msg->tsig, &rdata); 2942 dns_rdata_toregion(&rdata, &r); 2943 2944 isc_buffer_allocate(mctx, querytsig, r.length); 2945 isc_buffer_putmem(*querytsig, r.base, r.length); 2946 return (ISC_R_SUCCESS); 2947 } 2948 2949 dns_rdataset_t * 2950 dns_message_getsig0(dns_message_t *msg, const dns_name_t **owner) { 2951 /* 2952 * Get the SIG(0) record for 'msg'. 2953 */ 2954 2955 REQUIRE(DNS_MESSAGE_VALID(msg)); 2956 REQUIRE(owner == NULL || *owner == NULL); 2957 2958 if (msg->sig0 != NULL && owner != NULL) { 2959 /* If dns_message_getsig0 is called on a rendered message 2960 * after the SIG(0) has been applied, we need to return the 2961 * root name, not NULL. 2962 */ 2963 if (msg->sig0name == NULL) { 2964 *owner = dns_rootname; 2965 } else { 2966 *owner = msg->sig0name; 2967 } 2968 } 2969 return (msg->sig0); 2970 } 2971 2972 isc_result_t 2973 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2974 isc_region_t r; 2975 unsigned int x; 2976 isc_result_t result; 2977 2978 /* 2979 * Set the SIG(0) key for 'msg' 2980 */ 2981 2982 /* 2983 * The space required for an SIG(0) record is: 2984 * 2985 * 1 byte for the name 2986 * 2 bytes for the type 2987 * 2 bytes for the class 2988 * 4 bytes for the ttl 2989 * 2 bytes for the type covered 2990 * 1 byte for the algorithm 2991 * 1 bytes for the labels 2992 * 4 bytes for the original ttl 2993 * 4 bytes for the signature expiration 2994 * 4 bytes for the signature inception 2995 * 2 bytes for the key tag 2996 * n bytes for the signer's name 2997 * x bytes for the signature 2998 * --------------------------------- 2999 * 27 + n + x bytes 3000 */ 3001 REQUIRE(DNS_MESSAGE_VALID(msg)); 3002 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 3003 REQUIRE(msg->state == DNS_SECTION_ANY); 3004 3005 if (key != NULL) { 3006 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 3007 dns_name_toregion(dst_key_name(key), &r); 3008 result = dst_key_sigsize(key, &x); 3009 if (result != ISC_R_SUCCESS) { 3010 msg->sig_reserved = 0; 3011 return (result); 3012 } 3013 msg->sig_reserved = 27 + r.length + x; 3014 result = dns_message_renderreserve(msg, msg->sig_reserved); 3015 if (result != ISC_R_SUCCESS) { 3016 msg->sig_reserved = 0; 3017 return (result); 3018 } 3019 msg->sig0key = key; 3020 } 3021 return (ISC_R_SUCCESS); 3022 } 3023 3024 dst_key_t * 3025 dns_message_getsig0key(dns_message_t *msg) { 3026 /* 3027 * Get the SIG(0) key for 'msg' 3028 */ 3029 3030 REQUIRE(DNS_MESSAGE_VALID(msg)); 3031 3032 return (msg->sig0key); 3033 } 3034 3035 void 3036 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 3037 REQUIRE(DNS_MESSAGE_VALID(msg)); 3038 REQUIRE(buffer != NULL); 3039 REQUIRE(ISC_BUFFER_VALID(*buffer)); 3040 3041 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 3042 *buffer = NULL; 3043 } 3044 3045 isc_result_t 3046 dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 3047 isc_result_t result = ISC_R_SUCCESS; 3048 dns_rdata_t rdata = DNS_RDATA_INIT; 3049 3050 REQUIRE(DNS_MESSAGE_VALID(msg)); 3051 REQUIRE(signer != NULL); 3052 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 3053 3054 if (msg->tsig == NULL && msg->sig0 == NULL) { 3055 return (ISC_R_NOTFOUND); 3056 } 3057 3058 if (msg->verify_attempted == 0) { 3059 return (DNS_R_NOTVERIFIEDYET); 3060 } 3061 3062 if (!dns_name_hasbuffer(signer)) { 3063 isc_buffer_t *dynbuf = NULL; 3064 isc_buffer_allocate(msg->mctx, &dynbuf, 512); 3065 dns_name_setbuffer(signer, dynbuf); 3066 dns_message_takebuffer(msg, &dynbuf); 3067 } 3068 3069 if (msg->sig0 != NULL) { 3070 dns_rdata_sig_t sig; 3071 3072 result = dns_rdataset_first(msg->sig0); 3073 INSIST(result == ISC_R_SUCCESS); 3074 dns_rdataset_current(msg->sig0, &rdata); 3075 3076 result = dns_rdata_tostruct(&rdata, &sig, NULL); 3077 if (result != ISC_R_SUCCESS) { 3078 return (result); 3079 } 3080 3081 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) { 3082 result = ISC_R_SUCCESS; 3083 } else { 3084 result = DNS_R_SIGINVALID; 3085 } 3086 dns_name_clone(&sig.signer, signer); 3087 dns_rdata_freestruct(&sig); 3088 } else { 3089 const dns_name_t *identity; 3090 dns_rdata_any_tsig_t tsig; 3091 3092 result = dns_rdataset_first(msg->tsig); 3093 INSIST(result == ISC_R_SUCCESS); 3094 dns_rdataset_current(msg->tsig, &rdata); 3095 3096 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 3097 INSIST(result == ISC_R_SUCCESS); 3098 if (msg->verified_sig && msg->tsigstatus == dns_rcode_noerror && 3099 tsig.error == dns_rcode_noerror) 3100 { 3101 result = ISC_R_SUCCESS; 3102 } else if ((!msg->verified_sig) || 3103 (msg->tsigstatus != dns_rcode_noerror)) { 3104 result = DNS_R_TSIGVERIFYFAILURE; 3105 } else { 3106 INSIST(tsig.error != dns_rcode_noerror); 3107 result = DNS_R_TSIGERRORSET; 3108 } 3109 dns_rdata_freestruct(&tsig); 3110 3111 if (msg->tsigkey == NULL) { 3112 /* 3113 * If msg->tsigstatus & tsig.error are both 3114 * dns_rcode_noerror, the message must have been 3115 * verified, which means msg->tsigkey will be 3116 * non-NULL. 3117 */ 3118 INSIST(result != ISC_R_SUCCESS); 3119 } else { 3120 identity = dns_tsigkey_identity(msg->tsigkey); 3121 if (identity == NULL) { 3122 if (result == ISC_R_SUCCESS) { 3123 result = DNS_R_NOIDENTITY; 3124 } 3125 identity = &msg->tsigkey->name; 3126 } 3127 dns_name_clone(identity, signer); 3128 } 3129 } 3130 3131 return (result); 3132 } 3133 3134 void 3135 dns_message_resetsig(dns_message_t *msg) { 3136 REQUIRE(DNS_MESSAGE_VALID(msg)); 3137 msg->verified_sig = 0; 3138 msg->verify_attempted = 0; 3139 msg->tsigstatus = dns_rcode_noerror; 3140 msg->sig0status = dns_rcode_noerror; 3141 msg->timeadjust = 0; 3142 if (msg->tsigkey != NULL) { 3143 dns_tsigkey_detach(&msg->tsigkey); 3144 msg->tsigkey = NULL; 3145 } 3146 } 3147 3148 isc_result_t 3149 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 3150 dns_message_resetsig(msg); 3151 return (dns_message_checksig(msg, view)); 3152 } 3153 3154 #ifdef SKAN_MSG_DEBUG 3155 void 3156 dns_message_dumpsig(dns_message_t *msg, char *txt1) { 3157 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 3158 dns_rdata_any_tsig_t querytsig; 3159 isc_result_t result; 3160 3161 if (msg->tsig != NULL) { 3162 result = dns_rdataset_first(msg->tsig); 3163 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3164 dns_rdataset_current(msg->tsig, &querytsigrdata); 3165 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 3166 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3167 hexdump(txt1, "TSIG", querytsig.signature, querytsig.siglen); 3168 } 3169 3170 if (msg->querytsig != NULL) { 3171 result = dns_rdataset_first(msg->querytsig); 3172 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3173 dns_rdataset_current(msg->querytsig, &querytsigrdata); 3174 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 3175 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3176 hexdump(txt1, "QUERYTSIG", querytsig.signature, 3177 querytsig.siglen); 3178 } 3179 } 3180 #endif /* ifdef SKAN_MSG_DEBUG */ 3181 3182 isc_result_t 3183 dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 3184 isc_buffer_t b, msgb; 3185 3186 REQUIRE(DNS_MESSAGE_VALID(msg)); 3187 3188 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) { 3189 return (ISC_R_SUCCESS); 3190 } 3191 3192 INSIST(msg->saved.base != NULL); 3193 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 3194 isc_buffer_add(&msgb, msg->saved.length); 3195 if (msg->tsigkey != NULL || msg->tsig != NULL) { 3196 #ifdef SKAN_MSG_DEBUG 3197 dns_message_dumpsig(msg, "dns_message_checksig#1"); 3198 #endif /* ifdef SKAN_MSG_DEBUG */ 3199 if (view != NULL) { 3200 return (dns_view_checksig(view, &msgb, msg)); 3201 } else { 3202 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 3203 } 3204 } else { 3205 dns_rdata_t rdata = DNS_RDATA_INIT; 3206 dns_rdata_sig_t sig; 3207 dns_rdataset_t keyset; 3208 isc_result_t result; 3209 3210 result = dns_rdataset_first(msg->sig0); 3211 INSIST(result == ISC_R_SUCCESS); 3212 dns_rdataset_current(msg->sig0, &rdata); 3213 3214 /* 3215 * This can occur when the message is a dynamic update, since 3216 * the rdata length checking is relaxed. This should not 3217 * happen in a well-formed message, since the SIG(0) is only 3218 * looked for in the additional section, and the dynamic update 3219 * meta-records are in the prerequisite and update sections. 3220 */ 3221 if (rdata.length == 0) { 3222 return (ISC_R_UNEXPECTEDEND); 3223 } 3224 3225 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 3226 if (result != ISC_R_SUCCESS) { 3227 return (result); 3228 } 3229 3230 dns_rdataset_init(&keyset); 3231 if (view == NULL) { 3232 return (DNS_R_KEYUNAUTHORIZED); 3233 } 3234 result = dns_view_simplefind(view, &sig.signer, 3235 dns_rdatatype_key /* SIG(0) */, 0, 3236 0, false, &keyset, NULL); 3237 3238 if (result != ISC_R_SUCCESS) { 3239 /* XXXBEW Should possibly create a fetch here */ 3240 result = DNS_R_KEYUNAUTHORIZED; 3241 goto freesig; 3242 } else if (keyset.trust < dns_trust_secure) { 3243 /* XXXBEW Should call a validator here */ 3244 result = DNS_R_KEYUNAUTHORIZED; 3245 goto freesig; 3246 } 3247 result = dns_rdataset_first(&keyset); 3248 INSIST(result == ISC_R_SUCCESS); 3249 for (; result == ISC_R_SUCCESS; 3250 result = dns_rdataset_next(&keyset)) { 3251 dst_key_t *key = NULL; 3252 3253 dns_rdata_reset(&rdata); 3254 dns_rdataset_current(&keyset, &rdata); 3255 isc_buffer_init(&b, rdata.data, rdata.length); 3256 isc_buffer_add(&b, rdata.length); 3257 3258 result = dst_key_fromdns(&sig.signer, rdata.rdclass, &b, 3259 view->mctx, &key); 3260 if (result != ISC_R_SUCCESS) { 3261 continue; 3262 } 3263 if (dst_key_alg(key) != sig.algorithm || 3264 dst_key_id(key) != sig.keyid || 3265 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 3266 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 3267 { 3268 dst_key_free(&key); 3269 continue; 3270 } 3271 result = dns_dnssec_verifymessage(&msgb, msg, key); 3272 dst_key_free(&key); 3273 if (result == ISC_R_SUCCESS) { 3274 break; 3275 } 3276 } 3277 if (result == ISC_R_NOMORE) { 3278 result = DNS_R_KEYUNAUTHORIZED; 3279 } 3280 3281 freesig: 3282 if (dns_rdataset_isassociated(&keyset)) { 3283 dns_rdataset_disassociate(&keyset); 3284 } 3285 dns_rdata_freestruct(&sig); 3286 return (result); 3287 } 3288 } 3289 3290 #define INDENT(sp) \ 3291 do { \ 3292 unsigned int __i; \ 3293 dns_masterstyle_flags_t __flags = dns_master_styleflags(sp); \ 3294 if ((__flags & DNS_STYLEFLAG_INDENT) == 0ULL && \ 3295 (__flags & DNS_STYLEFLAG_YAML) == 0ULL) \ 3296 break; \ 3297 for (__i = 0; __i < msg->indent.count; __i++) { \ 3298 ADD_STRING(target, msg->indent.string); \ 3299 } \ 3300 } while (0) 3301 3302 isc_result_t 3303 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 3304 const dns_master_style_t *style, 3305 dns_messagetextflag_t flags, isc_buffer_t *target) { 3306 dns_name_t *name, empty_name; 3307 dns_rdataset_t *rdataset; 3308 isc_result_t result = ISC_R_SUCCESS; 3309 bool seensoa = false; 3310 size_t saved_count; 3311 dns_masterstyle_flags_t sflags; 3312 3313 REQUIRE(DNS_MESSAGE_VALID(msg)); 3314 REQUIRE(target != NULL); 3315 REQUIRE(VALID_SECTION(section)); 3316 3317 saved_count = msg->indent.count; 3318 3319 if (ISC_LIST_EMPTY(msg->sections[section])) { 3320 goto cleanup; 3321 } 3322 3323 sflags = dns_master_styleflags(style); 3324 3325 INDENT(style); 3326 if ((sflags & DNS_STYLEFLAG_YAML) != 0) { 3327 if (msg->opcode != dns_opcode_update) { 3328 ADD_STRING(target, sectiontext[section]); 3329 } else { 3330 ADD_STRING(target, updsectiontext[section]); 3331 } 3332 ADD_STRING(target, "_SECTION:\n"); 3333 } else if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3334 ADD_STRING(target, ";; "); 3335 if (msg->opcode != dns_opcode_update) { 3336 ADD_STRING(target, sectiontext[section]); 3337 } else { 3338 ADD_STRING(target, updsectiontext[section]); 3339 } 3340 ADD_STRING(target, " SECTION:\n"); 3341 } 3342 3343 dns_name_init(&empty_name, NULL); 3344 result = dns_message_firstname(msg, section); 3345 if (result != ISC_R_SUCCESS) { 3346 goto cleanup; 3347 } 3348 if ((sflags & DNS_STYLEFLAG_YAML) != 0) { 3349 msg->indent.count++; 3350 } 3351 do { 3352 name = NULL; 3353 dns_message_currentname(msg, section, &name); 3354 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; 3355 rdataset = ISC_LIST_NEXT(rdataset, link)) 3356 { 3357 if (section == DNS_SECTION_ANSWER && 3358 rdataset->type == dns_rdatatype_soa) { 3359 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0) 3360 { 3361 continue; 3362 } 3363 if (seensoa && 3364 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0) { 3365 continue; 3366 } 3367 seensoa = true; 3368 } 3369 if (section == DNS_SECTION_QUESTION) { 3370 INDENT(style); 3371 if ((sflags & DNS_STYLEFLAG_YAML) != 0) { 3372 ADD_STRING(target, "- "); 3373 } else { 3374 ADD_STRING(target, ";"); 3375 } 3376 result = dns_master_questiontotext( 3377 name, rdataset, style, target); 3378 } else { 3379 result = dns_master_rdatasettotext( 3380 name, rdataset, style, &msg->indent, 3381 target); 3382 } 3383 if (result != ISC_R_SUCCESS) { 3384 goto cleanup; 3385 } 3386 } 3387 result = dns_message_nextname(msg, section); 3388 } while (result == ISC_R_SUCCESS); 3389 if ((sflags & DNS_STYLEFLAG_YAML) != 0) { 3390 msg->indent.count--; 3391 } 3392 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3393 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0 && 3394 (sflags & DNS_STYLEFLAG_YAML) == 0) 3395 { 3396 INDENT(style); 3397 ADD_STRING(target, "\n"); 3398 } 3399 if (result == ISC_R_NOMORE) { 3400 result = ISC_R_SUCCESS; 3401 } 3402 3403 cleanup: 3404 msg->indent.count = saved_count; 3405 return (result); 3406 } 3407 3408 static isc_result_t 3409 render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) { 3410 int i; 3411 char addr[16], addr_text[64]; 3412 uint16_t family; 3413 uint8_t addrlen, addrbytes, scopelen; 3414 isc_result_t result; 3415 3416 /* 3417 * Note: This routine needs to handle malformed ECS options. 3418 */ 3419 3420 if (isc_buffer_remaininglength(ecsbuf) < 4) { 3421 return (DNS_R_OPTERR); 3422 } 3423 family = isc_buffer_getuint16(ecsbuf); 3424 addrlen = isc_buffer_getuint8(ecsbuf); 3425 scopelen = isc_buffer_getuint8(ecsbuf); 3426 3427 addrbytes = (addrlen + 7) / 8; 3428 if (isc_buffer_remaininglength(ecsbuf) < addrbytes) { 3429 return (DNS_R_OPTERR); 3430 } 3431 3432 if (addrbytes > sizeof(addr)) { 3433 return (DNS_R_OPTERR); 3434 } 3435 3436 memset(addr, 0, sizeof(addr)); 3437 for (i = 0; i < addrbytes; i++) { 3438 addr[i] = isc_buffer_getuint8(ecsbuf); 3439 } 3440 3441 switch (family) { 3442 case 0: 3443 if (addrlen != 0U || scopelen != 0U) { 3444 return (DNS_R_OPTERR); 3445 } 3446 strlcpy(addr_text, "0", sizeof(addr_text)); 3447 break; 3448 case 1: 3449 if (addrlen > 32 || scopelen > 32) { 3450 return (DNS_R_OPTERR); 3451 } 3452 inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text)); 3453 break; 3454 case 2: 3455 if (addrlen > 128 || scopelen > 128) { 3456 return (DNS_R_OPTERR); 3457 } 3458 inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text)); 3459 break; 3460 default: 3461 return (DNS_R_OPTERR); 3462 } 3463 3464 ADD_STRING(target, " "); 3465 ADD_STRING(target, addr_text); 3466 snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen); 3467 ADD_STRING(target, addr_text); 3468 3469 result = ISC_R_SUCCESS; 3470 3471 cleanup: 3472 return (result); 3473 } 3474 3475 static isc_result_t 3476 render_llq(isc_buffer_t *optbuf, isc_buffer_t *target) { 3477 char buf[sizeof("18446744073709551615")]; /* 2^64-1 */ 3478 isc_result_t result = ISC_R_SUCCESS; 3479 uint32_t u; 3480 uint64_t q; 3481 3482 u = isc_buffer_getuint16(optbuf); 3483 ADD_STRING(target, " Version: "); 3484 snprintf(buf, sizeof(buf), "%u", u); 3485 ADD_STRING(target, buf); 3486 3487 u = isc_buffer_getuint16(optbuf); 3488 ADD_STRING(target, ", Opcode: "); 3489 snprintf(buf, sizeof(buf), "%u", u); 3490 ADD_STRING(target, buf); 3491 3492 u = isc_buffer_getuint16(optbuf); 3493 ADD_STRING(target, ", Error: "); 3494 snprintf(buf, sizeof(buf), "%u", u); 3495 ADD_STRING(target, buf); 3496 3497 q = isc_buffer_getuint32(optbuf); 3498 q <<= 32; 3499 q |= isc_buffer_getuint32(optbuf); 3500 ADD_STRING(target, ", Identifier: "); 3501 snprintf(buf, sizeof(buf), "%" PRIu64, q); 3502 ADD_STRING(target, buf); 3503 3504 u = isc_buffer_getuint32(optbuf); 3505 ADD_STRING(target, ", Lifetime: "); 3506 snprintf(buf, sizeof(buf), "%u", u); 3507 ADD_STRING(target, buf); 3508 cleanup: 3509 return (result); 3510 } 3511 3512 static isc_result_t 3513 dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_pseudosection_t section, 3514 const dns_master_style_t *style, 3515 dns_messagetextflag_t flags, 3516 isc_buffer_t *target) { 3517 dns_rdataset_t *ps = NULL; 3518 const dns_name_t *name = NULL; 3519 isc_result_t result = ISC_R_SUCCESS; 3520 char buf[sizeof("1234567890")]; 3521 uint32_t mbz; 3522 dns_rdata_t rdata; 3523 isc_buffer_t optbuf; 3524 uint16_t optcode, optlen; 3525 size_t saved_count; 3526 unsigned char *optdata; 3527 unsigned int indent; 3528 3529 REQUIRE(DNS_MESSAGE_VALID(msg)); 3530 REQUIRE(target != NULL); 3531 REQUIRE(VALID_PSEUDOSECTION(section)); 3532 3533 saved_count = msg->indent.count; 3534 3535 switch (section) { 3536 case DNS_PSEUDOSECTION_OPT: 3537 ps = dns_message_getopt(msg); 3538 if (ps == NULL) { 3539 goto cleanup; 3540 } 3541 3542 INDENT(style); 3543 ADD_STRING(target, "OPT_PSEUDOSECTION:\n"); 3544 msg->indent.count++; 3545 3546 INDENT(style); 3547 ADD_STRING(target, "EDNS:\n"); 3548 indent = ++msg->indent.count; 3549 3550 INDENT(style); 3551 ADD_STRING(target, "version: "); 3552 snprintf(buf, sizeof(buf), "%u", 3553 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3554 ADD_STRING(target, buf); 3555 ADD_STRING(target, "\n"); 3556 INDENT(style); 3557 ADD_STRING(target, "flags:"); 3558 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) { 3559 ADD_STRING(target, " do"); 3560 } 3561 ADD_STRING(target, "\n"); 3562 mbz = ps->ttl & 0xffff; 3563 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 3564 if (mbz != 0) { 3565 INDENT(style); 3566 ADD_STRING(target, "MBZ: "); 3567 snprintf(buf, sizeof(buf), "0x%.4x", mbz); 3568 ADD_STRING(target, buf); 3569 ADD_STRING(target, "\n"); 3570 } 3571 INDENT(style); 3572 ADD_STRING(target, "udp: "); 3573 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3574 ADD_STRING(target, buf); 3575 result = dns_rdataset_first(ps); 3576 if (result != ISC_R_SUCCESS) { 3577 result = ISC_R_SUCCESS; 3578 goto cleanup; 3579 } 3580 3581 /* 3582 * Print EDNS info, if any. 3583 * 3584 * WARNING: The option contents may be malformed as 3585 * dig +ednsopt=value:<content> does not perform validity 3586 * checking. 3587 */ 3588 dns_rdata_init(&rdata); 3589 dns_rdataset_current(ps, &rdata); 3590 3591 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3592 isc_buffer_add(&optbuf, rdata.length); 3593 while (isc_buffer_remaininglength(&optbuf) != 0) { 3594 bool extra_text = false; 3595 msg->indent.count = indent; 3596 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 3597 optcode = isc_buffer_getuint16(&optbuf); 3598 optlen = isc_buffer_getuint16(&optbuf); 3599 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 3600 3601 if (optcode == DNS_OPT_LLQ) { 3602 INDENT(style); 3603 ADD_STRING(target, "LLQ:"); 3604 if (optlen == 18U) { 3605 result = render_llq(&optbuf, target); 3606 if (result != ISC_R_SUCCESS) { 3607 goto cleanup; 3608 } 3609 ADD_STRING(target, "\n"); 3610 continue; 3611 } 3612 } else if (optcode == DNS_OPT_NSID) { 3613 INDENT(style); 3614 ADD_STRING(target, "NSID:"); 3615 } else if (optcode == DNS_OPT_COOKIE) { 3616 INDENT(style); 3617 ADD_STRING(target, "COOKIE:"); 3618 } else if (optcode == DNS_OPT_CLIENT_SUBNET) { 3619 isc_buffer_t ecsbuf; 3620 INDENT(style); 3621 ADD_STRING(target, "CLIENT-SUBNET:"); 3622 isc_buffer_init(&ecsbuf, 3623 isc_buffer_current(&optbuf), 3624 optlen); 3625 isc_buffer_add(&ecsbuf, optlen); 3626 result = render_ecs(&ecsbuf, target); 3627 if (result == ISC_R_NOSPACE) { 3628 goto cleanup; 3629 } 3630 if (result == ISC_R_SUCCESS) { 3631 isc_buffer_forward(&optbuf, optlen); 3632 ADD_STRING(target, "\n"); 3633 continue; 3634 } 3635 ADD_STRING(target, "\n"); 3636 } else if (optcode == DNS_OPT_EXPIRE) { 3637 INDENT(style); 3638 ADD_STRING(target, "EXPIRE:"); 3639 if (optlen == 4) { 3640 uint32_t secs; 3641 secs = isc_buffer_getuint32(&optbuf); 3642 snprintf(buf, sizeof(buf), " %u", secs); 3643 ADD_STRING(target, buf); 3644 ADD_STRING(target, " ("); 3645 result = dns_ttl_totext(secs, true, 3646 true, target); 3647 if (result != ISC_R_SUCCESS) { 3648 goto cleanup; 3649 } 3650 ADD_STRING(target, ")\n"); 3651 continue; 3652 } 3653 } else if (optcode == DNS_OPT_TCP_KEEPALIVE) { 3654 if (optlen == 2) { 3655 unsigned int dsecs; 3656 dsecs = isc_buffer_getuint16(&optbuf); 3657 INDENT(style); 3658 ADD_STRING(target, "TCP-KEEPALIVE: "); 3659 snprintf(buf, sizeof(buf), "%u.%u", 3660 dsecs / 10U, dsecs % 10U); 3661 ADD_STRING(target, buf); 3662 ADD_STRING(target, " secs\n"); 3663 continue; 3664 } 3665 INDENT(style); 3666 ADD_STRING(target, "TCP-KEEPALIVE:"); 3667 } else if (optcode == DNS_OPT_PAD) { 3668 INDENT(style); 3669 ADD_STRING(target, "PAD:"); 3670 } else if (optcode == DNS_OPT_KEY_TAG) { 3671 INDENT(style); 3672 ADD_STRING(target, "KEY-TAG:"); 3673 if (optlen > 0U && (optlen % 2U) == 0U) { 3674 const char *sep = ""; 3675 uint16_t id; 3676 while (optlen > 0U) { 3677 id = isc_buffer_getuint16( 3678 &optbuf); 3679 snprintf(buf, sizeof(buf), 3680 "%s %u", sep, id); 3681 ADD_STRING(target, buf); 3682 sep = ","; 3683 optlen -= 2; 3684 } 3685 ADD_STRING(target, "\n"); 3686 continue; 3687 } 3688 } else if (optcode == DNS_OPT_EDE) { 3689 INDENT(style); 3690 ADD_STRING(target, "EDE:"); 3691 if (optlen >= 2U) { 3692 uint16_t ede; 3693 ADD_STRING(target, "\n"); 3694 msg->indent.count++; 3695 INDENT(style); 3696 ADD_STRING(target, "INFO-CODE:"); 3697 ede = isc_buffer_getuint16(&optbuf); 3698 snprintf(buf, sizeof(buf), " %u", ede); 3699 ADD_STRING(target, buf); 3700 if (ede < ARRAY_SIZE(edetext)) { 3701 ADD_STRING(target, " ("); 3702 ADD_STRING(target, 3703 edetext[ede]); 3704 ADD_STRING(target, ")"); 3705 } 3706 ADD_STRING(target, "\n"); 3707 optlen -= 2; 3708 if (optlen != 0) { 3709 INDENT(style); 3710 ADD_STRING(target, 3711 "EXTRA-TEXT:"); 3712 extra_text = true; 3713 } 3714 } 3715 } else if (optcode == DNS_OPT_CLIENT_TAG) { 3716 uint16_t id; 3717 INDENT(style); 3718 ADD_STRING(target, "CLIENT-TAG:"); 3719 if (optlen == 2U) { 3720 id = isc_buffer_getuint16(&optbuf); 3721 snprintf(buf, sizeof(buf), " %u\n", id); 3722 ADD_STRING(target, buf); 3723 optlen -= 2; 3724 POST(optlen); 3725 continue; 3726 } 3727 } else if (optcode == DNS_OPT_SERVER_TAG) { 3728 uint16_t id; 3729 INDENT(style); 3730 ADD_STRING(target, "SERVER-TAG:"); 3731 if (optlen == 2U) { 3732 id = isc_buffer_getuint16(&optbuf); 3733 snprintf(buf, sizeof(buf), " %u\n", id); 3734 ADD_STRING(target, buf); 3735 optlen -= 2; 3736 POST(optlen); 3737 continue; 3738 } 3739 } else { 3740 INDENT(style); 3741 ADD_STRING(target, "OPT="); 3742 snprintf(buf, sizeof(buf), "%u:", optcode); 3743 ADD_STRING(target, buf); 3744 } 3745 3746 if (optlen != 0) { 3747 int i; 3748 bool utf8ok = false; 3749 3750 ADD_STRING(target, " "); 3751 3752 optdata = isc_buffer_current(&optbuf); 3753 if (extra_text) { 3754 utf8ok = isc_utf8_valid(optdata, 3755 optlen); 3756 } 3757 if (!utf8ok) { 3758 for (i = 0; i < optlen; i++) { 3759 const char *sep; 3760 switch (optcode) { 3761 case DNS_OPT_COOKIE: 3762 sep = ""; 3763 break; 3764 default: 3765 sep = " "; 3766 break; 3767 } 3768 snprintf(buf, sizeof(buf), 3769 "%02x%s", optdata[i], 3770 sep); 3771 ADD_STRING(target, buf); 3772 } 3773 } 3774 3775 isc_buffer_forward(&optbuf, optlen); 3776 3777 if (optcode == DNS_OPT_COOKIE) { 3778 /* 3779 * Valid server cookie? 3780 */ 3781 if (msg->cc_ok && optlen >= 16) { 3782 ADD_STRING(target, " (good)"); 3783 } 3784 /* 3785 * Server cookie is not valid but 3786 * we had our cookie echoed back. 3787 */ 3788 if (msg->cc_ok && optlen < 16) { 3789 ADD_STRING(target, " (echoed)"); 3790 } 3791 /* 3792 * We didn't get our cookie echoed 3793 * back. 3794 */ 3795 if (msg->cc_bad) { 3796 ADD_STRING(target, " (bad)"); 3797 } 3798 ADD_STRING(target, "\n"); 3799 continue; 3800 } 3801 3802 if (optcode == DNS_OPT_CLIENT_SUBNET) { 3803 ADD_STRING(target, "\n"); 3804 continue; 3805 } 3806 3807 /* 3808 * For non-COOKIE options, add a printable 3809 * version 3810 */ 3811 if (!extra_text) { 3812 ADD_STRING(target, "(\""); 3813 } else { 3814 ADD_STRING(target, "\""); 3815 } 3816 if (isc_buffer_availablelength(target) < optlen) 3817 { 3818 result = ISC_R_NOSPACE; 3819 goto cleanup; 3820 } 3821 for (i = 0; i < optlen; i++) { 3822 if (isprint(optdata[i]) || 3823 (utf8ok && optdata[i] > 127)) { 3824 isc_buffer_putmem( 3825 target, &optdata[i], 1); 3826 } else { 3827 isc_buffer_putstr(target, "."); 3828 } 3829 } 3830 if (!extra_text) { 3831 ADD_STRING(target, "\")"); 3832 } else { 3833 ADD_STRING(target, "\""); 3834 } 3835 } 3836 ADD_STRING(target, "\n"); 3837 } 3838 msg->indent.count = indent; 3839 result = ISC_R_SUCCESS; 3840 goto cleanup; 3841 case DNS_PSEUDOSECTION_TSIG: 3842 ps = dns_message_gettsig(msg, &name); 3843 if (ps == NULL) { 3844 result = ISC_R_SUCCESS; 3845 goto cleanup; 3846 } 3847 INDENT(style); 3848 ADD_STRING(target, "TSIG_PSEUDOSECTION:\n"); 3849 result = dns_master_rdatasettotext(name, ps, style, 3850 &msg->indent, target); 3851 ADD_STRING(target, "\n"); 3852 goto cleanup; 3853 case DNS_PSEUDOSECTION_SIG0: 3854 ps = dns_message_getsig0(msg, &name); 3855 if (ps == NULL) { 3856 result = ISC_R_SUCCESS; 3857 goto cleanup; 3858 } 3859 INDENT(style); 3860 ADD_STRING(target, "SIG0_PSEUDOSECTION:\n"); 3861 result = dns_master_rdatasettotext(name, ps, style, 3862 &msg->indent, target); 3863 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3864 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3865 { 3866 ADD_STRING(target, "\n"); 3867 } 3868 goto cleanup; 3869 } 3870 3871 result = ISC_R_UNEXPECTED; 3872 3873 cleanup: 3874 msg->indent.count = saved_count; 3875 return (result); 3876 } 3877 3878 isc_result_t 3879 dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section, 3880 const dns_master_style_t *style, 3881 dns_messagetextflag_t flags, 3882 isc_buffer_t *target) { 3883 dns_rdataset_t *ps = NULL; 3884 const dns_name_t *name = NULL; 3885 isc_result_t result; 3886 char buf[sizeof(" (65000 bytes)")]; 3887 uint32_t mbz; 3888 dns_rdata_t rdata; 3889 isc_buffer_t optbuf; 3890 uint16_t optcode, optlen; 3891 unsigned char *optdata; 3892 3893 REQUIRE(DNS_MESSAGE_VALID(msg)); 3894 REQUIRE(target != NULL); 3895 REQUIRE(VALID_PSEUDOSECTION(section)); 3896 3897 if ((dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) != 0) { 3898 return (dns_message_pseudosectiontoyaml(msg, section, style, 3899 flags, target)); 3900 } 3901 3902 switch (section) { 3903 case DNS_PSEUDOSECTION_OPT: 3904 ps = dns_message_getopt(msg); 3905 if (ps == NULL) { 3906 return (ISC_R_SUCCESS); 3907 } 3908 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3909 INDENT(style); 3910 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3911 } 3912 3913 INDENT(style); 3914 ADD_STRING(target, "; EDNS: version: "); 3915 snprintf(buf, sizeof(buf), "%u", 3916 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3917 ADD_STRING(target, buf); 3918 ADD_STRING(target, ", flags:"); 3919 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) { 3920 ADD_STRING(target, " do"); 3921 } 3922 mbz = ps->ttl & 0xffff; 3923 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 3924 if (mbz != 0) { 3925 ADD_STRING(target, "; MBZ: "); 3926 snprintf(buf, sizeof(buf), "0x%.4x", mbz); 3927 ADD_STRING(target, buf); 3928 ADD_STRING(target, ", udp: "); 3929 } else { 3930 ADD_STRING(target, "; udp: "); 3931 } 3932 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3933 ADD_STRING(target, buf); 3934 3935 result = dns_rdataset_first(ps); 3936 if (result != ISC_R_SUCCESS) { 3937 return (ISC_R_SUCCESS); 3938 } 3939 3940 /* 3941 * Print EDNS info, if any. 3942 * 3943 * WARNING: The option contents may be malformed as 3944 * dig +ednsopt=value:<content> does no validity 3945 * checking. 3946 */ 3947 dns_rdata_init(&rdata); 3948 dns_rdataset_current(ps, &rdata); 3949 3950 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3951 isc_buffer_add(&optbuf, rdata.length); 3952 while (isc_buffer_remaininglength(&optbuf) != 0) { 3953 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 3954 optcode = isc_buffer_getuint16(&optbuf); 3955 optlen = isc_buffer_getuint16(&optbuf); 3956 3957 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 3958 3959 INDENT(style); 3960 3961 if (optcode == DNS_OPT_LLQ) { 3962 ADD_STRING(target, "; LLQ:"); 3963 if (optlen == 18U) { 3964 result = render_llq(&optbuf, target); 3965 if (result != ISC_R_SUCCESS) { 3966 return (result); 3967 } 3968 ADD_STRING(target, "\n"); 3969 continue; 3970 } 3971 } else if (optcode == DNS_OPT_NSID) { 3972 ADD_STRING(target, "; NSID:"); 3973 } else if (optcode == DNS_OPT_COOKIE) { 3974 ADD_STRING(target, "; COOKIE:"); 3975 } else if (optcode == DNS_OPT_CLIENT_SUBNET) { 3976 isc_buffer_t ecsbuf; 3977 3978 ADD_STRING(target, "; CLIENT-SUBNET:"); 3979 isc_buffer_init(&ecsbuf, 3980 isc_buffer_current(&optbuf), 3981 optlen); 3982 isc_buffer_add(&ecsbuf, optlen); 3983 result = render_ecs(&ecsbuf, target); 3984 if (result == ISC_R_NOSPACE) { 3985 return (result); 3986 } 3987 if (result == ISC_R_SUCCESS) { 3988 isc_buffer_forward(&optbuf, optlen); 3989 ADD_STRING(target, "\n"); 3990 continue; 3991 } 3992 } else if (optcode == DNS_OPT_EXPIRE) { 3993 ADD_STRING(target, "; EXPIRE:"); 3994 if (optlen == 4) { 3995 uint32_t secs; 3996 secs = isc_buffer_getuint32(&optbuf); 3997 snprintf(buf, sizeof(buf), " %u", secs); 3998 ADD_STRING(target, buf); 3999 ADD_STRING(target, " ("); 4000 result = dns_ttl_totext(secs, true, 4001 true, target); 4002 if (result != ISC_R_SUCCESS) { 4003 return (result); 4004 } 4005 ADD_STRING(target, ")\n"); 4006 continue; 4007 } 4008 } else if (optcode == DNS_OPT_TCP_KEEPALIVE) { 4009 ADD_STRING(target, "; TCP KEEPALIVE:"); 4010 if (optlen == 2) { 4011 unsigned int dsecs; 4012 dsecs = isc_buffer_getuint16(&optbuf); 4013 snprintf(buf, sizeof(buf), " %u.%u", 4014 dsecs / 10U, dsecs % 10U); 4015 ADD_STRING(target, buf); 4016 ADD_STRING(target, " secs\n"); 4017 continue; 4018 } 4019 } else if (optcode == DNS_OPT_PAD) { 4020 ADD_STRING(target, "; PAD:"); 4021 if (optlen > 0U) { 4022 snprintf(buf, sizeof(buf), 4023 " (%u bytes)", optlen); 4024 ADD_STRING(target, buf); 4025 isc_buffer_forward(&optbuf, optlen); 4026 } 4027 ADD_STRING(target, "\n"); 4028 continue; 4029 } else if (optcode == DNS_OPT_KEY_TAG) { 4030 ADD_STRING(target, "; KEY-TAG:"); 4031 if (optlen > 0U && (optlen % 2U) == 0U) { 4032 const char *sep = ""; 4033 uint16_t id; 4034 while (optlen > 0U) { 4035 id = isc_buffer_getuint16( 4036 &optbuf); 4037 snprintf(buf, sizeof(buf), 4038 "%s %u", sep, id); 4039 ADD_STRING(target, buf); 4040 sep = ","; 4041 optlen -= 2; 4042 } 4043 ADD_STRING(target, "\n"); 4044 continue; 4045 } 4046 } else if (optcode == DNS_OPT_EDE) { 4047 ADD_STRING(target, "; EDE:"); 4048 if (optlen >= 2U) { 4049 uint16_t ede; 4050 ede = isc_buffer_getuint16(&optbuf); 4051 snprintf(buf, sizeof(buf), " %u", ede); 4052 ADD_STRING(target, buf); 4053 if (ede < ARRAY_SIZE(edetext)) { 4054 ADD_STRING(target, " ("); 4055 ADD_STRING(target, 4056 edetext[ede]); 4057 ADD_STRING(target, ")"); 4058 } 4059 optlen -= 2; 4060 if (optlen != 0) { 4061 ADD_STRING(target, ":"); 4062 } 4063 } else if (optlen == 1U) { 4064 /* Malformed */ 4065 optdata = isc_buffer_current(&optbuf); 4066 snprintf(buf, sizeof(buf), 4067 " %02x (\"%c\")\n", optdata[0], 4068 isprint(optdata[0]) 4069 ? optdata[0] 4070 : '.'); 4071 isc_buffer_forward(&optbuf, optlen); 4072 ADD_STRING(target, buf); 4073 continue; 4074 } 4075 } else if (optcode == DNS_OPT_CLIENT_TAG) { 4076 uint16_t id; 4077 ADD_STRING(target, "; CLIENT-TAG:"); 4078 if (optlen == 2U) { 4079 id = isc_buffer_getuint16(&optbuf); 4080 snprintf(buf, sizeof(buf), " %u\n", id); 4081 ADD_STRING(target, buf); 4082 optlen -= 2; 4083 POST(optlen); 4084 continue; 4085 } 4086 } else if (optcode == DNS_OPT_SERVER_TAG) { 4087 uint16_t id; 4088 ADD_STRING(target, "; SERVER-TAG:"); 4089 if (optlen == 2U) { 4090 id = isc_buffer_getuint16(&optbuf); 4091 snprintf(buf, sizeof(buf), " %u\n", id); 4092 ADD_STRING(target, buf); 4093 optlen -= 2; 4094 POST(optlen); 4095 continue; 4096 } 4097 } else { 4098 ADD_STRING(target, "; OPT="); 4099 snprintf(buf, sizeof(buf), "%u:", optcode); 4100 ADD_STRING(target, buf); 4101 } 4102 4103 if (optlen != 0) { 4104 int i; 4105 bool utf8ok = false; 4106 4107 ADD_STRING(target, " "); 4108 4109 optdata = isc_buffer_current(&optbuf); 4110 if (optcode == DNS_OPT_EDE) { 4111 utf8ok = isc_utf8_valid(optdata, 4112 optlen); 4113 } 4114 if (!utf8ok) { 4115 for (i = 0; i < optlen; i++) { 4116 const char *sep; 4117 switch (optcode) { 4118 case DNS_OPT_COOKIE: 4119 sep = ""; 4120 break; 4121 default: 4122 sep = " "; 4123 break; 4124 } 4125 snprintf(buf, sizeof(buf), 4126 "%02x%s", optdata[i], 4127 sep); 4128 ADD_STRING(target, buf); 4129 } 4130 } 4131 4132 isc_buffer_forward(&optbuf, optlen); 4133 4134 if (optcode == DNS_OPT_COOKIE) { 4135 /* 4136 * Valid server cookie? 4137 */ 4138 if (msg->cc_ok && optlen >= 16) { 4139 ADD_STRING(target, " (good)"); 4140 } 4141 /* 4142 * Server cookie is not valid but 4143 * we had our cookie echoed back. 4144 */ 4145 if (msg->cc_ok && optlen < 16) { 4146 ADD_STRING(target, " (echoed)"); 4147 } 4148 /* 4149 * We didn't get our cookie echoed 4150 * back. 4151 */ 4152 if (msg->cc_bad) { 4153 ADD_STRING(target, " (bad)"); 4154 } 4155 ADD_STRING(target, "\n"); 4156 continue; 4157 } 4158 4159 if (optcode == DNS_OPT_CLIENT_SUBNET) { 4160 ADD_STRING(target, "\n"); 4161 continue; 4162 } 4163 4164 /* 4165 * For non-COOKIE options, add a printable 4166 * version. 4167 */ 4168 if (optcode != DNS_OPT_EDE) { 4169 ADD_STRING(target, "(\""); 4170 } else { 4171 ADD_STRING(target, "("); 4172 } 4173 if (isc_buffer_availablelength(target) < optlen) 4174 { 4175 return (ISC_R_NOSPACE); 4176 } 4177 for (i = 0; i < optlen; i++) { 4178 if (isprint(optdata[i]) || 4179 (utf8ok && optdata[i] > 127)) { 4180 isc_buffer_putmem( 4181 target, &optdata[i], 1); 4182 } else { 4183 isc_buffer_putstr(target, "."); 4184 } 4185 } 4186 if (optcode != DNS_OPT_EDE) { 4187 ADD_STRING(target, "\")"); 4188 } else { 4189 ADD_STRING(target, ")"); 4190 } 4191 } 4192 ADD_STRING(target, "\n"); 4193 } 4194 return (ISC_R_SUCCESS); 4195 case DNS_PSEUDOSECTION_TSIG: 4196 ps = dns_message_gettsig(msg, &name); 4197 if (ps == NULL) { 4198 return (ISC_R_SUCCESS); 4199 } 4200 INDENT(style); 4201 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 4202 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 4203 } 4204 result = dns_master_rdatasettotext(name, ps, style, 4205 &msg->indent, target); 4206 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 4207 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 4208 { 4209 ADD_STRING(target, "\n"); 4210 } 4211 return (result); 4212 case DNS_PSEUDOSECTION_SIG0: 4213 ps = dns_message_getsig0(msg, &name); 4214 if (ps == NULL) { 4215 return (ISC_R_SUCCESS); 4216 } 4217 INDENT(style); 4218 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 4219 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 4220 } 4221 result = dns_master_rdatasettotext(name, ps, style, 4222 &msg->indent, target); 4223 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 4224 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 4225 { 4226 ADD_STRING(target, "\n"); 4227 } 4228 return (result); 4229 } 4230 result = ISC_R_UNEXPECTED; 4231 cleanup: 4232 return (result); 4233 } 4234 4235 isc_result_t 4236 dns_message_headertotext(dns_message_t *msg, const dns_master_style_t *style, 4237 dns_messagetextflag_t flags, isc_buffer_t *target) { 4238 char buf[sizeof("1234567890")]; 4239 isc_result_t result; 4240 4241 REQUIRE(DNS_MESSAGE_VALID(msg)); 4242 REQUIRE(target != NULL); 4243 4244 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) != 0) { 4245 return (ISC_R_SUCCESS); 4246 } 4247 4248 if (dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) { 4249 INDENT(style); 4250 ADD_STRING(target, "opcode: "); 4251 ADD_STRING(target, opcodetext[msg->opcode]); 4252 ADD_STRING(target, "\n"); 4253 INDENT(style); 4254 ADD_STRING(target, "status: "); 4255 result = dns_rcode_totext(msg->rcode, target); 4256 if (result != ISC_R_SUCCESS) { 4257 return (result); 4258 } 4259 ADD_STRING(target, "\n"); 4260 INDENT(style); 4261 ADD_STRING(target, "id: "); 4262 snprintf(buf, sizeof(buf), "%u", msg->id); 4263 ADD_STRING(target, buf); 4264 ADD_STRING(target, "\n"); 4265 INDENT(style); 4266 ADD_STRING(target, "flags:"); 4267 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 4268 ADD_STRING(target, " qr"); 4269 } 4270 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 4271 ADD_STRING(target, " aa"); 4272 } 4273 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 4274 ADD_STRING(target, " tc"); 4275 } 4276 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 4277 ADD_STRING(target, " rd"); 4278 } 4279 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 4280 ADD_STRING(target, " ra"); 4281 } 4282 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 4283 ADD_STRING(target, " ad"); 4284 } 4285 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 4286 ADD_STRING(target, " cd"); 4287 } 4288 ADD_STRING(target, "\n"); 4289 /* 4290 * The final unnamed flag must be zero. 4291 */ 4292 if ((msg->flags & 0x0040U) != 0) { 4293 INDENT(style); 4294 ADD_STRING(target, "MBZ: 0x4"); 4295 ADD_STRING(target, "\n"); 4296 } 4297 if (msg->opcode != dns_opcode_update) { 4298 INDENT(style); 4299 ADD_STRING(target, "QUESTION: "); 4300 } else { 4301 INDENT(style); 4302 ADD_STRING(target, "ZONE: "); 4303 } 4304 snprintf(buf, sizeof(buf), "%1u", 4305 msg->counts[DNS_SECTION_QUESTION]); 4306 ADD_STRING(target, buf); 4307 ADD_STRING(target, "\n"); 4308 if (msg->opcode != dns_opcode_update) { 4309 INDENT(style); 4310 ADD_STRING(target, "ANSWER: "); 4311 } else { 4312 INDENT(style); 4313 ADD_STRING(target, "PREREQ: "); 4314 } 4315 snprintf(buf, sizeof(buf), "%1u", 4316 msg->counts[DNS_SECTION_ANSWER]); 4317 ADD_STRING(target, buf); 4318 ADD_STRING(target, "\n"); 4319 if (msg->opcode != dns_opcode_update) { 4320 INDENT(style); 4321 ADD_STRING(target, "AUTHORITY: "); 4322 } else { 4323 INDENT(style); 4324 ADD_STRING(target, "UPDATE: "); 4325 } 4326 snprintf(buf, sizeof(buf), "%1u", 4327 msg->counts[DNS_SECTION_AUTHORITY]); 4328 ADD_STRING(target, buf); 4329 ADD_STRING(target, "\n"); 4330 INDENT(style); 4331 ADD_STRING(target, "ADDITIONAL: "); 4332 snprintf(buf, sizeof(buf), "%1u", 4333 msg->counts[DNS_SECTION_ADDITIONAL]); 4334 ADD_STRING(target, buf); 4335 ADD_STRING(target, "\n"); 4336 } else { 4337 INDENT(style); 4338 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 4339 ADD_STRING(target, opcodetext[msg->opcode]); 4340 ADD_STRING(target, ", status: "); 4341 result = dns_rcode_totext(msg->rcode, target); 4342 if (result != ISC_R_SUCCESS) { 4343 return (result); 4344 } 4345 ADD_STRING(target, ", id: "); 4346 snprintf(buf, sizeof(buf), "%6u", msg->id); 4347 ADD_STRING(target, buf); 4348 ADD_STRING(target, "\n"); 4349 INDENT(style); 4350 ADD_STRING(target, ";; flags:"); 4351 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { 4352 ADD_STRING(target, " qr"); 4353 } 4354 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { 4355 ADD_STRING(target, " aa"); 4356 } 4357 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { 4358 ADD_STRING(target, " tc"); 4359 } 4360 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { 4361 ADD_STRING(target, " rd"); 4362 } 4363 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { 4364 ADD_STRING(target, " ra"); 4365 } 4366 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { 4367 ADD_STRING(target, " ad"); 4368 } 4369 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { 4370 ADD_STRING(target, " cd"); 4371 } 4372 /* 4373 * The final unnamed flag must be zero. 4374 */ 4375 if ((msg->flags & 0x0040U) != 0) { 4376 INDENT(style); 4377 ADD_STRING(target, "; MBZ: 0x4"); 4378 } 4379 if (msg->opcode != dns_opcode_update) { 4380 INDENT(style); 4381 ADD_STRING(target, "; QUESTION: "); 4382 } else { 4383 INDENT(style); 4384 ADD_STRING(target, "; ZONE: "); 4385 } 4386 snprintf(buf, sizeof(buf), "%1u", 4387 msg->counts[DNS_SECTION_QUESTION]); 4388 ADD_STRING(target, buf); 4389 if (msg->opcode != dns_opcode_update) { 4390 ADD_STRING(target, ", ANSWER: "); 4391 } else { 4392 ADD_STRING(target, ", PREREQ: "); 4393 } 4394 snprintf(buf, sizeof(buf), "%1u", 4395 msg->counts[DNS_SECTION_ANSWER]); 4396 ADD_STRING(target, buf); 4397 if (msg->opcode != dns_opcode_update) { 4398 ADD_STRING(target, ", AUTHORITY: "); 4399 } else { 4400 ADD_STRING(target, ", UPDATE: "); 4401 } 4402 snprintf(buf, sizeof(buf), "%1u", 4403 msg->counts[DNS_SECTION_AUTHORITY]); 4404 ADD_STRING(target, buf); 4405 ADD_STRING(target, ", ADDITIONAL: "); 4406 snprintf(buf, sizeof(buf), "%1u", 4407 msg->counts[DNS_SECTION_ADDITIONAL]); 4408 ADD_STRING(target, buf); 4409 ADD_STRING(target, "\n"); 4410 } 4411 4412 cleanup: 4413 return (result); 4414 } 4415 4416 isc_result_t 4417 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 4418 dns_messagetextflag_t flags, isc_buffer_t *target) { 4419 isc_result_t result; 4420 4421 REQUIRE(DNS_MESSAGE_VALID(msg)); 4422 REQUIRE(target != NULL); 4423 4424 result = dns_message_headertotext(msg, style, flags, target); 4425 if (result != ISC_R_SUCCESS) { 4426 return (result); 4427 } 4428 4429 result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_OPT, 4430 style, flags, target); 4431 if (result != ISC_R_SUCCESS) { 4432 return (result); 4433 } 4434 4435 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, style, 4436 flags, target); 4437 if (result != ISC_R_SUCCESS) { 4438 return (result); 4439 } 4440 4441 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, style, 4442 flags, target); 4443 if (result != ISC_R_SUCCESS) { 4444 return (result); 4445 } 4446 4447 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, style, 4448 flags, target); 4449 if (result != ISC_R_SUCCESS) { 4450 return (result); 4451 } 4452 4453 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, style, 4454 flags, target); 4455 if (result != ISC_R_SUCCESS) { 4456 return (result); 4457 } 4458 4459 result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_TSIG, 4460 style, flags, target); 4461 if (result != ISC_R_SUCCESS) { 4462 return (result); 4463 } 4464 4465 result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_SIG0, 4466 style, flags, target); 4467 return (result); 4468 } 4469 4470 isc_region_t * 4471 dns_message_getrawmessage(dns_message_t *msg) { 4472 REQUIRE(DNS_MESSAGE_VALID(msg)); 4473 return (&msg->saved); 4474 } 4475 4476 void 4477 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 4478 dns_aclenv_t *env, const dns_acl_t *acl, 4479 const dns_aclelement_t *elem) { 4480 REQUIRE(DNS_MESSAGE_VALID(msg)); 4481 REQUIRE((order == NULL) == (env == NULL)); 4482 REQUIRE(env == NULL || (acl != NULL || elem != NULL)); 4483 4484 msg->order = order; 4485 msg->order_arg.env = env; 4486 msg->order_arg.acl = acl; 4487 msg->order_arg.element = elem; 4488 } 4489 4490 void 4491 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 4492 REQUIRE(DNS_MESSAGE_VALID(msg)); 4493 msg->timeadjust = timeadjust; 4494 } 4495 4496 int 4497 dns_message_gettimeadjust(dns_message_t *msg) { 4498 REQUIRE(DNS_MESSAGE_VALID(msg)); 4499 return (msg->timeadjust); 4500 } 4501 4502 isc_result_t 4503 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 4504 REQUIRE(opcode < 16); 4505 4506 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) { 4507 return (ISC_R_NOSPACE); 4508 } 4509 isc_buffer_putstr(target, opcodetext[opcode]); 4510 return (ISC_R_SUCCESS); 4511 } 4512 4513 void 4514 dns_message_logpacket(dns_message_t *message, const char *description, 4515 const isc_sockaddr_t *address, 4516 isc_logcategory_t *category, isc_logmodule_t *module, 4517 int level, isc_mem_t *mctx) { 4518 REQUIRE(address != NULL); 4519 4520 logfmtpacket(message, description, address, category, module, 4521 &dns_master_style_debug, level, mctx); 4522 } 4523 4524 void 4525 dns_message_logfmtpacket(dns_message_t *message, const char *description, 4526 const isc_sockaddr_t *address, 4527 isc_logcategory_t *category, isc_logmodule_t *module, 4528 const dns_master_style_t *style, int level, 4529 isc_mem_t *mctx) { 4530 REQUIRE(address != NULL); 4531 4532 logfmtpacket(message, description, address, category, module, style, 4533 level, mctx); 4534 } 4535 4536 static void 4537 logfmtpacket(dns_message_t *message, const char *description, 4538 const isc_sockaddr_t *address, isc_logcategory_t *category, 4539 isc_logmodule_t *module, const dns_master_style_t *style, 4540 int level, isc_mem_t *mctx) { 4541 char addrbuf[ISC_SOCKADDR_FORMATSIZE] = { 0 }; 4542 const char *newline = "\n"; 4543 const char *space = " "; 4544 isc_buffer_t buffer; 4545 char *buf = NULL; 4546 int len = 1024; 4547 isc_result_t result; 4548 4549 if (!isc_log_wouldlog(dns_lctx, level)) { 4550 return; 4551 } 4552 4553 /* 4554 * Note that these are multiline debug messages. We want a newline 4555 * to appear in the log after each message. 4556 */ 4557 4558 if (address != NULL) { 4559 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf)); 4560 } else { 4561 newline = space = ""; 4562 } 4563 4564 do { 4565 buf = isc_mem_get(mctx, len); 4566 isc_buffer_init(&buffer, buf, len); 4567 result = dns_message_totext(message, style, 0, &buffer); 4568 if (result == ISC_R_NOSPACE) { 4569 isc_mem_put(mctx, buf, len); 4570 len += 1024; 4571 } else if (result == ISC_R_SUCCESS) { 4572 isc_log_write(dns_lctx, category, module, level, 4573 "%s%s%s%s%.*s", description, space, 4574 addrbuf, newline, 4575 (int)isc_buffer_usedlength(&buffer), buf); 4576 } 4577 } while (result == ISC_R_NOSPACE); 4578 4579 if (buf != NULL) { 4580 isc_mem_put(mctx, buf, len); 4581 } 4582 } 4583 4584 isc_result_t 4585 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, 4586 unsigned int version, uint16_t udpsize, unsigned int flags, 4587 dns_ednsopt_t *ednsopts, size_t count) { 4588 dns_rdataset_t *rdataset = NULL; 4589 dns_rdatalist_t *rdatalist = NULL; 4590 dns_rdata_t *rdata = NULL; 4591 isc_result_t result; 4592 unsigned int len = 0, i; 4593 4594 REQUIRE(DNS_MESSAGE_VALID(message)); 4595 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL); 4596 4597 result = dns_message_gettemprdatalist(message, &rdatalist); 4598 if (result != ISC_R_SUCCESS) { 4599 return (result); 4600 } 4601 result = dns_message_gettemprdata(message, &rdata); 4602 if (result != ISC_R_SUCCESS) { 4603 goto cleanup; 4604 } 4605 result = dns_message_gettemprdataset(message, &rdataset); 4606 if (result != ISC_R_SUCCESS) { 4607 goto cleanup; 4608 } 4609 4610 rdatalist->type = dns_rdatatype_opt; 4611 4612 /* 4613 * Set Maximum UDP buffer size. 4614 */ 4615 rdatalist->rdclass = udpsize; 4616 4617 /* 4618 * Set EXTENDED-RCODE and Z to 0. 4619 */ 4620 rdatalist->ttl = (version << 16); 4621 rdatalist->ttl |= (flags & 0xffff); 4622 4623 /* 4624 * Set EDNS options if applicable 4625 */ 4626 if (count != 0U) { 4627 isc_buffer_t *buf = NULL; 4628 bool seenpad = false; 4629 for (i = 0; i < count; i++) { 4630 len += ednsopts[i].length + 4; 4631 } 4632 4633 if (len > 0xffffU) { 4634 result = ISC_R_NOSPACE; 4635 goto cleanup; 4636 } 4637 4638 isc_buffer_allocate(message->mctx, &buf, len); 4639 4640 for (i = 0; i < count; i++) { 4641 if (ednsopts[i].code == DNS_OPT_PAD && 4642 ednsopts[i].length == 0U && !seenpad) { 4643 seenpad = true; 4644 continue; 4645 } 4646 isc_buffer_putuint16(buf, ednsopts[i].code); 4647 isc_buffer_putuint16(buf, ednsopts[i].length); 4648 if (ednsopts[i].length != 0) { 4649 isc_buffer_putmem(buf, ednsopts[i].value, 4650 ednsopts[i].length); 4651 } 4652 } 4653 4654 /* Padding must be the final option */ 4655 if (seenpad) { 4656 isc_buffer_putuint16(buf, DNS_OPT_PAD); 4657 isc_buffer_putuint16(buf, 0); 4658 } 4659 rdata->data = isc_buffer_base(buf); 4660 rdata->length = len; 4661 dns_message_takebuffer(message, &buf); 4662 if (seenpad) { 4663 message->padding_off = len; 4664 } 4665 } else { 4666 rdata->data = NULL; 4667 rdata->length = 0; 4668 } 4669 4670 rdata->rdclass = rdatalist->rdclass; 4671 rdata->type = rdatalist->type; 4672 rdata->flags = 0; 4673 4674 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 4675 result = dns_rdatalist_tordataset(rdatalist, rdataset); 4676 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4677 4678 *rdatasetp = rdataset; 4679 return (ISC_R_SUCCESS); 4680 4681 cleanup: 4682 if (rdata != NULL) { 4683 dns_message_puttemprdata(message, &rdata); 4684 } 4685 if (rdataset != NULL) { 4686 dns_message_puttemprdataset(message, &rdataset); 4687 } 4688 if (rdatalist != NULL) { 4689 dns_message_puttemprdatalist(message, &rdatalist); 4690 } 4691 return (result); 4692 } 4693 4694 void 4695 dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) { 4696 REQUIRE(DNS_MESSAGE_VALID(msg)); 4697 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 4698 REQUIRE(msg->state == DNS_SECTION_ANY); 4699 REQUIRE(msg->rdclass_set == 0); 4700 4701 msg->rdclass = rdclass; 4702 msg->rdclass_set = 1; 4703 } 4704 4705 void 4706 dns_message_setpadding(dns_message_t *msg, uint16_t padding) { 4707 REQUIRE(DNS_MESSAGE_VALID(msg)); 4708 4709 /* Avoid silly large padding */ 4710 if (padding > 512) { 4711 padding = 512; 4712 } 4713 msg->padding = padding; 4714 } 4715 4716 void 4717 dns_message_clonebuffer(dns_message_t *msg) { 4718 REQUIRE(DNS_MESSAGE_VALID(msg)); 4719 4720 if (msg->free_saved == 0 && msg->saved.base != NULL) { 4721 msg->saved.base = 4722 memmove(isc_mem_get(msg->mctx, msg->saved.length), 4723 msg->saved.base, msg->saved.length); 4724 msg->free_saved = 1; 4725 } 4726 if (msg->free_query == 0 && msg->query.base != NULL) { 4727 msg->query.base = 4728 memmove(isc_mem_get(msg->mctx, msg->query.length), 4729 msg->query.base, msg->query.length); 4730 msg->free_query = 1; 4731 } 4732 } 4733