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