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