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