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