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