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