1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* $Id: message.c,v 1.18 2020/11/01 07:12:14 florian Exp $ */ 18 19 /*! \file */ 20 21 /*** 22 *** Imports 23 ***/ 24 25 #include <sys/socket.h> 26 #include <arpa/inet.h> 27 28 #include <ctype.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include <isc/buffer.h> 33 #include <isc/util.h> 34 35 #include <dns/log.h> 36 #include <dns/masterdump.h> 37 #include <dns/message.h> 38 #include <dns/rdata.h> 39 #include <dns/rdatalist.h> 40 #include <dns/rdataset.h> 41 #include <dns/result.h> 42 #include <dns/tsig.h> 43 #include <dns/ttl.h> 44 45 #define DNS_MESSAGE_OPCODE_MASK 0x7800U 46 #define DNS_MESSAGE_OPCODE_SHIFT 11 47 #define DNS_MESSAGE_RCODE_MASK 0x000fU 48 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U 49 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U 50 51 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \ 52 && ((s) < DNS_SECTION_MAX)) 53 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \ 54 && ((s) < DNS_SECTION_MAX)) 55 #define ADD_STRING(b, s) {if (strlen(s) >= \ 56 isc_buffer_availablelength(b)) \ 57 return(ISC_R_NOSPACE); else \ 58 isc_buffer_putstr(b, s);} 59 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \ 60 && ((s) < DNS_PSEUDOSECTION_MAX)) 61 62 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0) 63 64 /*% 65 * This is the size of each individual scratchpad buffer, and the numbers 66 * of various block allocations used within the server. 67 * XXXMLG These should come from a config setting. 68 */ 69 #define SCRATCHPAD_SIZE 512 70 #define OFFSET_COUNT 4 71 #define RDATA_COUNT 8 72 #define RDATALIST_COUNT 8 73 74 /*% 75 * Text representation of the different items, for message_totext 76 * functions. 77 */ 78 static const char *sectiontext[] = { 79 "QUESTION", 80 "ANSWER", 81 "AUTHORITY", 82 "ADDITIONAL" 83 }; 84 85 static const char *updsectiontext[] = { 86 "ZONE", 87 "PREREQUISITE", 88 "UPDATE", 89 "ADDITIONAL" 90 }; 91 92 /*% 93 * "helper" type, which consists of a block of some type, and is linkable. 94 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer 95 * size, or the allocated elements will not be aligned correctly. 96 */ 97 struct dns_msgblock { 98 unsigned int count; 99 unsigned int remaining; 100 ISC_LINK(dns_msgblock_t) link; 101 }; /* dynamically sized */ 102 103 static inline dns_msgblock_t * 104 msgblock_allocate(unsigned int, unsigned int); 105 106 #define msgblock_get(block, type) \ 107 ((type *)msgblock_internalget(block, sizeof(type))) 108 109 static inline void * 110 msgblock_internalget(dns_msgblock_t *, unsigned int); 111 112 static inline void 113 msgblock_reset(dns_msgblock_t *); 114 115 /* 116 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory 117 * is free, return NULL. 118 */ 119 static inline dns_msgblock_t * 120 msgblock_allocate(unsigned int sizeof_type, 121 unsigned int count) 122 { 123 dns_msgblock_t *block; 124 unsigned int length; 125 126 length = sizeof(dns_msgblock_t) + (sizeof_type * count); 127 128 block = malloc(length); 129 if (block == NULL) 130 return (NULL); 131 132 block->count = count; 133 block->remaining = count; 134 135 ISC_LINK_INIT(block, link); 136 137 return (block); 138 } 139 140 /* 141 * Return an element from the msgblock. If no more are available, return 142 * NULL. 143 */ 144 static inline void * 145 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) { 146 void *ptr; 147 148 if (block == NULL || block->remaining == 0) 149 return (NULL); 150 151 block->remaining--; 152 153 ptr = (((unsigned char *)block) 154 + sizeof(dns_msgblock_t) 155 + (sizeof_type * block->remaining)); 156 157 return (ptr); 158 } 159 160 static inline void 161 msgblock_reset(dns_msgblock_t *block) { 162 block->remaining = block->count; 163 } 164 165 /* 166 * Allocate a new dynamic buffer, and attach it to this message as the 167 * "current" buffer. (which is always the last on the list, for our 168 * uses) 169 */ 170 static inline isc_result_t 171 newbuffer(dns_message_t *msg, unsigned int size) { 172 isc_result_t result; 173 isc_buffer_t *dynbuf; 174 175 dynbuf = NULL; 176 result = isc_buffer_allocate(&dynbuf, size); 177 if (result != ISC_R_SUCCESS) 178 return (ISC_R_NOMEMORY); 179 180 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link); 181 return (ISC_R_SUCCESS); 182 } 183 184 static inline isc_buffer_t * 185 currentbuffer(dns_message_t *msg) { 186 isc_buffer_t *dynbuf; 187 188 dynbuf = ISC_LIST_TAIL(msg->scratchpad); 189 INSIST(dynbuf != NULL); 190 191 return (dynbuf); 192 } 193 194 static inline void 195 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) { 196 ISC_LIST_PREPEND(msg->freerdata, rdata, link); 197 } 198 199 static inline dns_rdata_t * 200 newrdata(dns_message_t *msg) { 201 dns_msgblock_t *msgblock; 202 dns_rdata_t *rdata; 203 204 rdata = ISC_LIST_HEAD(msg->freerdata); 205 if (rdata != NULL) { 206 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 207 return (rdata); 208 } 209 210 msgblock = ISC_LIST_TAIL(msg->rdatas); 211 rdata = msgblock_get(msgblock, dns_rdata_t); 212 if (rdata == NULL) { 213 msgblock = msgblock_allocate(sizeof(dns_rdata_t), RDATA_COUNT); 214 if (msgblock == NULL) 215 return (NULL); 216 217 ISC_LIST_APPEND(msg->rdatas, msgblock, link); 218 219 rdata = msgblock_get(msgblock, dns_rdata_t); 220 } 221 222 dns_rdata_init(rdata); 223 return (rdata); 224 } 225 226 static inline void 227 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) { 228 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link); 229 } 230 231 static inline dns_rdatalist_t * 232 newrdatalist(dns_message_t *msg) { 233 dns_msgblock_t *msgblock; 234 dns_rdatalist_t *rdatalist; 235 236 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 237 if (rdatalist != NULL) { 238 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 239 goto out; 240 } 241 242 msgblock = ISC_LIST_TAIL(msg->rdatalists); 243 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 244 if (rdatalist == NULL) { 245 msgblock = msgblock_allocate(sizeof(dns_rdatalist_t), 246 RDATALIST_COUNT); 247 if (msgblock == NULL) 248 return (NULL); 249 250 ISC_LIST_APPEND(msg->rdatalists, msgblock, link); 251 252 rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 253 } 254 out: 255 if (rdatalist != NULL) 256 dns_rdatalist_init(rdatalist); 257 258 return (rdatalist); 259 } 260 261 static inline dns_offsets_t * 262 newoffsets(dns_message_t *msg) { 263 dns_msgblock_t *msgblock; 264 dns_offsets_t *offsets; 265 266 msgblock = ISC_LIST_TAIL(msg->offsets); 267 offsets = msgblock_get(msgblock, dns_offsets_t); 268 if (offsets == NULL) { 269 msgblock = msgblock_allocate(sizeof(dns_offsets_t), 270 OFFSET_COUNT); 271 if (msgblock == NULL) 272 return (NULL); 273 274 ISC_LIST_APPEND(msg->offsets, msgblock, link); 275 276 offsets = msgblock_get(msgblock, dns_offsets_t); 277 } 278 279 return (offsets); 280 } 281 282 static inline void 283 msginitheader(dns_message_t *m) { 284 m->id = 0; 285 m->flags = 0; 286 m->rcode = 0; 287 m->opcode = 0; 288 m->rdclass = 0; 289 } 290 291 static inline void 292 msginitprivate(dns_message_t *m) { 293 unsigned int i; 294 295 for (i = 0; i < DNS_SECTION_MAX; i++) { 296 m->cursors[i] = NULL; 297 m->counts[i] = 0; 298 } 299 m->opt = NULL; 300 m->sig0 = NULL; 301 m->sig0name = NULL; 302 m->tsig = NULL; 303 m->tsigname = NULL; 304 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ 305 m->opt_reserved = 0; 306 m->sig_reserved = 0; 307 m->reserved = 0; 308 m->buffer = NULL; 309 } 310 311 static inline void 312 msginittsig(dns_message_t *m) { 313 m->tsigstatus = dns_rcode_noerror; 314 m->querytsigstatus = dns_rcode_noerror; 315 m->tsigkey = NULL; 316 m->tsigctx = NULL; 317 m->sigstart = -1; 318 m->sig0status = dns_rcode_noerror; 319 m->timeadjust = 0; 320 } 321 322 /* 323 * Init elements to default state. Used both when allocating a new element 324 * and when resetting one. 325 */ 326 static inline void 327 msginit(dns_message_t *m) { 328 msginitheader(m); 329 msginitprivate(m); 330 msginittsig(m); 331 m->header_ok = 0; 332 m->question_ok = 0; 333 m->tcp_continuation = 0; 334 m->verified_sig = 0; 335 m->verify_attempted = 0; 336 m->order = NULL; 337 m->order_arg = NULL; 338 m->query.base = NULL; 339 m->query.length = 0; 340 m->free_query = 0; 341 m->saved.base = NULL; 342 m->saved.length = 0; 343 m->free_saved = 0; 344 m->sitok = 0; 345 m->sitbad = 0; 346 m->tkey = 0; 347 m->rdclass_set = 0; 348 m->querytsig = NULL; 349 } 350 351 static inline void 352 msgresetnames(dns_message_t *msg, unsigned int first_section) { 353 unsigned int i; 354 dns_name_t *name, *next_name; 355 dns_rdataset_t *rds, *next_rds; 356 357 /* 358 * Clean up name lists by calling the rdataset disassociate function. 359 */ 360 for (i = first_section; i < DNS_SECTION_MAX; i++) { 361 name = ISC_LIST_HEAD(msg->sections[i]); 362 while (name != NULL) { 363 next_name = ISC_LIST_NEXT(name, link); 364 ISC_LIST_UNLINK(msg->sections[i], name, link); 365 366 rds = ISC_LIST_HEAD(name->list); 367 while (rds != NULL) { 368 next_rds = ISC_LIST_NEXT(rds, link); 369 ISC_LIST_UNLINK(name->list, rds, link); 370 371 INSIST(dns_rdataset_isassociated(rds)); 372 dns_rdataset_disassociate(rds); 373 free(rds); 374 rds = next_rds; 375 } 376 if (dns_name_dynamic(name)) 377 dns_name_free(name); 378 free(name); 379 name = next_name; 380 } 381 } 382 } 383 384 static void 385 msgresetopt(dns_message_t *msg) 386 { 387 if (msg->opt != NULL) { 388 if (msg->opt_reserved > 0) { 389 dns_message_renderrelease(msg, msg->opt_reserved); 390 msg->opt_reserved = 0; 391 } 392 INSIST(dns_rdataset_isassociated(msg->opt)); 393 dns_rdataset_disassociate(msg->opt); 394 free(msg->opt); 395 msg->opt = NULL; 396 msg->sitok = 0; 397 msg->sitbad = 0; 398 } 399 } 400 401 static void 402 msgresetsigs(dns_message_t *msg, int replying) { 403 if (msg->sig_reserved > 0) { 404 dns_message_renderrelease(msg, msg->sig_reserved); 405 msg->sig_reserved = 0; 406 } 407 if (msg->tsig != NULL) { 408 INSIST(dns_rdataset_isassociated(msg->tsig)); 409 if (replying) { 410 INSIST(msg->querytsig == NULL); 411 msg->querytsig = msg->tsig; 412 } else { 413 dns_rdataset_disassociate(msg->tsig); 414 free(msg->tsig); 415 if (msg->querytsig != NULL) { 416 dns_rdataset_disassociate(msg->querytsig); 417 free(msg->querytsig); 418 } 419 } 420 if (dns_name_dynamic(msg->tsigname)) 421 dns_name_free(msg->tsigname); 422 free(msg->tsigname); 423 msg->tsig = NULL; 424 msg->tsigname = NULL; 425 } else if (msg->querytsig != NULL && !replying) { 426 dns_rdataset_disassociate(msg->querytsig); 427 free(msg->querytsig); 428 msg->querytsig = NULL; 429 } 430 if (msg->sig0 != NULL) { 431 INSIST(dns_rdataset_isassociated(msg->sig0)); 432 dns_rdataset_disassociate(msg->sig0); 433 free(msg->sig0); 434 if (msg->sig0name != NULL) { 435 if (dns_name_dynamic(msg->sig0name)) 436 dns_name_free(msg->sig0name); 437 free(msg->sig0name); 438 } 439 msg->sig0 = NULL; 440 msg->sig0name = NULL; 441 } 442 } 443 444 /* 445 * Free all but one (or everything) for this message. This is used by 446 * both dns_message_reset() and dns_message_destroy(). 447 */ 448 static void 449 msgreset(dns_message_t *msg, int everything) { 450 dns_msgblock_t *msgblock, *next_msgblock; 451 isc_buffer_t *dynbuf, *next_dynbuf; 452 dns_rdata_t *rdata; 453 dns_rdatalist_t *rdatalist; 454 455 msgresetnames(msg, 0); 456 msgresetopt(msg); 457 msgresetsigs(msg, 0); 458 459 /* 460 * Clean up linked lists. 461 */ 462 463 /* 464 * Run through the free lists, and just unlink anything found there. 465 * The memory isn't lost since these are part of message blocks we 466 * have allocated. 467 */ 468 rdata = ISC_LIST_HEAD(msg->freerdata); 469 while (rdata != NULL) { 470 ISC_LIST_UNLINK(msg->freerdata, rdata, link); 471 rdata = ISC_LIST_HEAD(msg->freerdata); 472 } 473 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 474 while (rdatalist != NULL) { 475 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 476 rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 477 } 478 479 dynbuf = ISC_LIST_HEAD(msg->scratchpad); 480 INSIST(dynbuf != NULL); 481 if (!everything) { 482 isc_buffer_clear(dynbuf); 483 dynbuf = ISC_LIST_NEXT(dynbuf, link); 484 } 485 while (dynbuf != NULL) { 486 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 487 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link); 488 isc_buffer_free(&dynbuf); 489 dynbuf = next_dynbuf; 490 } 491 492 msgblock = ISC_LIST_HEAD(msg->rdatas); 493 if (!everything && msgblock != NULL) { 494 msgblock_reset(msgblock); 495 msgblock = ISC_LIST_NEXT(msgblock, link); 496 } 497 while (msgblock != NULL) { 498 next_msgblock = ISC_LIST_NEXT(msgblock, link); 499 ISC_LIST_UNLINK(msg->rdatas, msgblock, link); 500 free(msgblock); 501 msgblock = next_msgblock; 502 } 503 504 /* 505 * rdatalists could be empty. 506 */ 507 508 msgblock = ISC_LIST_HEAD(msg->rdatalists); 509 if (!everything && msgblock != NULL) { 510 msgblock_reset(msgblock); 511 msgblock = ISC_LIST_NEXT(msgblock, link); 512 } 513 while (msgblock != NULL) { 514 next_msgblock = ISC_LIST_NEXT(msgblock, link); 515 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link); 516 free(msgblock); 517 msgblock = next_msgblock; 518 } 519 520 msgblock = ISC_LIST_HEAD(msg->offsets); 521 if (!everything && msgblock != NULL) { 522 msgblock_reset(msgblock); 523 msgblock = ISC_LIST_NEXT(msgblock, link); 524 } 525 while (msgblock != NULL) { 526 next_msgblock = ISC_LIST_NEXT(msgblock, link); 527 ISC_LIST_UNLINK(msg->offsets, msgblock, link); 528 free(msgblock); 529 msgblock = next_msgblock; 530 } 531 532 if (msg->tsigkey != NULL) { 533 dns_tsigkey_detach(&msg->tsigkey); 534 msg->tsigkey = NULL; 535 } 536 537 if (msg->tsigctx != NULL) 538 dst_context_destroy(&msg->tsigctx); 539 540 if (msg->query.base != NULL) { 541 if (msg->free_query != 0) 542 free(msg->query.base); 543 msg->query.base = NULL; 544 msg->query.length = 0; 545 } 546 547 if (msg->saved.base != NULL) { 548 if (msg->free_saved != 0) 549 free(msg->saved.base); 550 msg->saved.base = NULL; 551 msg->saved.length = 0; 552 } 553 554 /* 555 * cleanup the buffer cleanup list 556 */ 557 dynbuf = ISC_LIST_HEAD(msg->cleanup); 558 while (dynbuf != NULL) { 559 next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 560 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link); 561 isc_buffer_free(&dynbuf); 562 dynbuf = next_dynbuf; 563 } 564 565 /* 566 * Set other bits to normal default values. 567 */ 568 if (!everything) 569 msginit(msg); 570 } 571 572 static unsigned int 573 spacefortsig(dns_tsigkey_t *key, int otherlen) { 574 isc_region_t r1, r2; 575 unsigned int x; 576 isc_result_t result; 577 578 /* 579 * The space required for an TSIG record is: 580 * 581 * n1 bytes for the name 582 * 2 bytes for the type 583 * 2 bytes for the class 584 * 4 bytes for the ttl 585 * 2 bytes for the rdlength 586 * n2 bytes for the algorithm name 587 * 6 bytes for the time signed 588 * 2 bytes for the fudge 589 * 2 bytes for the MAC size 590 * x bytes for the MAC 591 * 2 bytes for the original id 592 * 2 bytes for the error 593 * 2 bytes for the other data length 594 * y bytes for the other data (at most) 595 * --------------------------------- 596 * 26 + n1 + n2 + x + y bytes 597 */ 598 599 dns_name_toregion(&key->name, &r1); 600 dns_name_toregion(key->algorithm, &r2); 601 if (key->key == NULL) 602 x = 0; 603 else { 604 result = dst_key_sigsize(key->key, &x); 605 if (result != ISC_R_SUCCESS) 606 x = 0; 607 } 608 return (26 + r1.length + r2.length + x + otherlen); 609 } 610 611 isc_result_t 612 dns_message_create(unsigned int intent, dns_message_t **msgp) 613 { 614 dns_message_t *m; 615 isc_result_t result; 616 isc_buffer_t *dynbuf; 617 unsigned int i; 618 619 REQUIRE(msgp != NULL); 620 REQUIRE(*msgp == NULL); 621 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 622 || intent == DNS_MESSAGE_INTENTRENDER); 623 624 m = malloc(sizeof(dns_message_t)); 625 if (m == NULL) 626 return (ISC_R_NOMEMORY); 627 628 /* 629 * No allocations until further notice. Just initialize all lists 630 * and other members that are freed in the cleanup phase here. 631 */ 632 633 m->from_to_wire = intent; 634 msginit(m); 635 636 for (i = 0; i < DNS_SECTION_MAX; i++) 637 ISC_LIST_INIT(m->sections[i]); 638 639 ISC_LIST_INIT(m->scratchpad); 640 ISC_LIST_INIT(m->cleanup); 641 ISC_LIST_INIT(m->rdatas); 642 ISC_LIST_INIT(m->rdatalists); 643 ISC_LIST_INIT(m->offsets); 644 ISC_LIST_INIT(m->freerdata); 645 ISC_LIST_INIT(m->freerdatalist); 646 647 /* 648 * Ok, it is safe to allocate (and then "goto cleanup" if failure) 649 */ 650 651 dynbuf = NULL; 652 result = isc_buffer_allocate(&dynbuf, SCRATCHPAD_SIZE); 653 if (result != ISC_R_SUCCESS) 654 goto cleanup; 655 ISC_LIST_APPEND(m->scratchpad, dynbuf, link); 656 657 m->cctx = NULL; 658 659 *msgp = m; 660 return (ISC_R_SUCCESS); 661 662 /* 663 * Cleanup for error returns. 664 */ 665 cleanup: 666 dynbuf = ISC_LIST_HEAD(m->scratchpad); 667 if (dynbuf != NULL) { 668 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); 669 isc_buffer_free(&dynbuf); 670 } 671 free(m); 672 673 return (ISC_R_NOMEMORY); 674 } 675 676 void 677 dns_message_destroy(dns_message_t **msgp) { 678 dns_message_t *msg; 679 680 REQUIRE(msgp != NULL); 681 682 msg = *msgp; 683 *msgp = NULL; 684 685 msgreset(msg, 1); 686 free(msg); 687 } 688 689 static isc_result_t 690 findname(dns_name_t **foundname, dns_name_t *target, 691 dns_namelist_t *section) 692 { 693 dns_name_t *curr; 694 695 for (curr = ISC_LIST_TAIL(*section); 696 curr != NULL; 697 curr = ISC_LIST_PREV(curr, link)) { 698 if (dns_name_equal(curr, target)) { 699 if (foundname != NULL) 700 *foundname = curr; 701 return (ISC_R_SUCCESS); 702 } 703 } 704 705 return (ISC_R_NOTFOUND); 706 } 707 708 isc_result_t 709 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, 710 dns_rdatatype_t type, dns_rdatatype_t covers, 711 dns_rdataset_t **rdataset) 712 { 713 dns_rdataset_t *curr; 714 715 REQUIRE(name != NULL); 716 REQUIRE(rdataset == NULL || *rdataset == NULL); 717 718 for (curr = ISC_LIST_TAIL(name->list); 719 curr != NULL; 720 curr = ISC_LIST_PREV(curr, link)) { 721 if (curr->rdclass == rdclass && 722 curr->type == type && curr->covers == covers) { 723 if (rdataset != NULL) 724 *rdataset = curr; 725 return (ISC_R_SUCCESS); 726 } 727 } 728 729 return (ISC_R_NOTFOUND); 730 } 731 732 isc_result_t 733 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, 734 dns_rdatatype_t covers, dns_rdataset_t **rdataset) 735 { 736 dns_rdataset_t *curr; 737 738 REQUIRE(name != NULL); 739 REQUIRE(rdataset == NULL || *rdataset == NULL); 740 741 for (curr = ISC_LIST_TAIL(name->list); 742 curr != NULL; 743 curr = ISC_LIST_PREV(curr, link)) { 744 if (curr->type == type && curr->covers == covers) { 745 if (rdataset != NULL) 746 *rdataset = curr; 747 return (ISC_R_SUCCESS); 748 } 749 } 750 751 return (ISC_R_NOTFOUND); 752 } 753 754 /* 755 * Read a name from buffer "source". 756 */ 757 static isc_result_t 758 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, 759 dns_decompress_t *dctx) 760 { 761 isc_buffer_t *scratch; 762 isc_result_t result; 763 unsigned int tries; 764 765 scratch = currentbuffer(msg); 766 767 /* 768 * First try: use current buffer. 769 * Second try: allocate a new buffer and use that. 770 */ 771 tries = 0; 772 while (tries < 2) { 773 result = dns_name_fromwire(name, source, dctx, 0, 774 scratch); 775 776 if (result == ISC_R_NOSPACE) { 777 tries++; 778 779 result = newbuffer(msg, SCRATCHPAD_SIZE); 780 if (result != ISC_R_SUCCESS) 781 return (result); 782 783 scratch = currentbuffer(msg); 784 dns_name_reset(name); 785 } else { 786 return (result); 787 } 788 } 789 790 INSIST(0); /* Cannot get here... */ 791 return (ISC_R_UNEXPECTED); 792 } 793 794 static isc_result_t 795 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 796 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, 797 unsigned int rdatalen, dns_rdata_t *rdata) 798 { 799 isc_buffer_t *scratch; 800 isc_result_t result; 801 unsigned int tries; 802 unsigned int trysize; 803 804 scratch = currentbuffer(msg); 805 806 isc_buffer_setactive(source, rdatalen); 807 808 /* 809 * First try: use current buffer. 810 * Second try: allocate a new buffer of size 811 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) 812 * (the data will fit if it was not more than 50% compressed) 813 * Subsequent tries: double buffer size on each try. 814 */ 815 tries = 0; 816 trysize = 0; 817 /* XXX possibly change this to a while (tries < 2) loop */ 818 for (;;) { 819 result = dns_rdata_fromwire(rdata, rdclass, rdtype, 820 source, dctx, 0, 821 scratch); 822 823 if (result == ISC_R_NOSPACE) { 824 if (tries == 0) { 825 trysize = 2 * rdatalen; 826 if (trysize < SCRATCHPAD_SIZE) 827 trysize = SCRATCHPAD_SIZE; 828 } else { 829 INSIST(trysize != 0); 830 if (trysize >= 65535) 831 return (ISC_R_NOSPACE); 832 /* XXX DNS_R_RRTOOLONG? */ 833 trysize *= 2; 834 } 835 tries++; 836 result = newbuffer(msg, trysize); 837 if (result != ISC_R_SUCCESS) 838 return (result); 839 840 scratch = currentbuffer(msg); 841 } else { 842 return (result); 843 } 844 } 845 } 846 847 #define DO_FORMERR \ 848 do { \ 849 if (best_effort) \ 850 seen_problem = 1; \ 851 else { \ 852 result = DNS_R_FORMERR; \ 853 goto cleanup; \ 854 } \ 855 } while (0) 856 857 static isc_result_t 858 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 859 unsigned int options) 860 { 861 isc_region_t r; 862 unsigned int count; 863 dns_name_t *name; 864 dns_name_t *name2; 865 dns_offsets_t *offsets; 866 dns_rdataset_t *rdataset; 867 dns_rdatalist_t *rdatalist; 868 isc_result_t result; 869 dns_rdatatype_t rdtype; 870 dns_rdataclass_t rdclass; 871 dns_namelist_t *section; 872 int free_name; 873 int best_effort; 874 int seen_problem; 875 876 section = &msg->sections[DNS_SECTION_QUESTION]; 877 878 best_effort = options & DNS_MESSAGEPARSE_BESTEFFORT; 879 seen_problem = 0; 880 881 name = NULL; 882 rdataset = NULL; 883 rdatalist = NULL; 884 885 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { 886 name = malloc(sizeof(dns_name_t)); 887 if (name == NULL) 888 return (ISC_R_NOMEMORY); 889 free_name = 1; 890 891 offsets = newoffsets(msg); 892 if (offsets == NULL) { 893 result = ISC_R_NOMEMORY; 894 goto cleanup; 895 } 896 dns_name_init(name, *offsets); 897 898 /* 899 * Parse the name out of this packet. 900 */ 901 isc_buffer_remainingregion(source, &r); 902 isc_buffer_setactive(source, r.length); 903 result = getname(name, source, msg, dctx); 904 if (result != ISC_R_SUCCESS) 905 goto cleanup; 906 907 /* 908 * Run through the section, looking to see if this name 909 * is already there. If it is found, put back the allocated 910 * name since we no longer need it, and set our name pointer 911 * to point to the name we found. 912 */ 913 result = findname(&name2, name, section); 914 915 /* 916 * If it is the first name in the section, accept it. 917 * 918 * If it is not, but is not the same as the name already 919 * in the question section, append to the section. Note that 920 * here in the question section this is illegal, so return 921 * FORMERR. In the future, check the opcode to see if 922 * this should be legal or not. In either case we no longer 923 * need this name pointer. 924 */ 925 if (result != ISC_R_SUCCESS) { 926 if (!ISC_LIST_EMPTY(*section)) 927 DO_FORMERR; 928 ISC_LIST_APPEND(*section, name, link); 929 free_name = 0; 930 } else { 931 free(name); 932 name = name2; 933 name2 = NULL; 934 free_name = 0; 935 } 936 937 /* 938 * Get type and class. 939 */ 940 isc_buffer_remainingregion(source, &r); 941 if (r.length < 4) { 942 result = ISC_R_UNEXPECTEDEND; 943 goto cleanup; 944 } 945 rdtype = isc_buffer_getuint16(source); 946 rdclass = isc_buffer_getuint16(source); 947 948 /* 949 * If this class is different than the one we already read, 950 * this is an error. 951 */ 952 if (msg->rdclass_set == 0) { 953 msg->rdclass = rdclass; 954 msg->rdclass_set = 1; 955 } else if (msg->rdclass != rdclass) 956 DO_FORMERR; 957 958 /* 959 * Is this a TKEY query? 960 */ 961 if (rdtype == dns_rdatatype_tkey) 962 msg->tkey = 1; 963 964 /* 965 * Can't ask the same question twice. 966 */ 967 result = dns_message_find(name, rdclass, rdtype, 0, NULL); 968 if (result == ISC_R_SUCCESS) 969 DO_FORMERR; 970 971 /* 972 * Allocate a new rdatalist. 973 */ 974 rdatalist = newrdatalist(msg); 975 if (rdatalist == NULL) { 976 result = ISC_R_NOMEMORY; 977 goto cleanup; 978 } 979 rdataset = malloc(sizeof(dns_rdataset_t)); 980 if (rdataset == NULL) { 981 result = ISC_R_NOMEMORY; 982 goto cleanup; 983 } 984 985 /* 986 * Convert rdatalist to rdataset, and attach the latter to 987 * the name. 988 */ 989 rdatalist->type = rdtype; 990 rdatalist->covers = 0; 991 rdatalist->rdclass = rdclass; 992 rdatalist->ttl = 0; 993 ISC_LIST_INIT(rdatalist->rdata); 994 995 dns_rdataset_init(rdataset); 996 result = dns_rdatalist_tordataset(rdatalist, rdataset); 997 if (result != ISC_R_SUCCESS) 998 goto cleanup; 999 1000 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 1001 1002 ISC_LIST_APPEND(name->list, rdataset, link); 1003 rdataset = NULL; 1004 } 1005 1006 if (seen_problem) 1007 return (DNS_R_RECOVERABLE); 1008 return (ISC_R_SUCCESS); 1009 1010 cleanup: 1011 if (rdataset != NULL) { 1012 INSIST(!dns_rdataset_isassociated(rdataset)); 1013 free(rdataset); 1014 } 1015 if (free_name) 1016 free(name); 1017 1018 return (result); 1019 } 1020 1021 static int 1022 update(dns_section_t section, dns_rdataclass_t rdclass) { 1023 if (section == DNS_SECTION_PREREQUISITE) 1024 return (rdclass == dns_rdataclass_any || 1025 rdclass == dns_rdataclass_none); 1026 if (section == DNS_SECTION_UPDATE) 1027 return (rdclass == dns_rdataclass_any); 1028 return (0); 1029 } 1030 1031 static isc_result_t 1032 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 1033 dns_section_t sectionid, unsigned int options) 1034 { 1035 isc_region_t r; 1036 unsigned int count, rdatalen; 1037 dns_name_t *name = NULL; 1038 dns_offsets_t *offsets; 1039 dns_rdataset_t *rdataset; 1040 dns_rdatalist_t *rdatalist; 1041 isc_result_t result; 1042 dns_rdatatype_t rdtype, covers; 1043 dns_rdataclass_t rdclass; 1044 dns_rdata_t *rdata; 1045 dns_ttl_t ttl; 1046 dns_namelist_t *section; 1047 int free_name = 0, free_rdataset = 0; 1048 int best_effort, seen_problem; 1049 int issigzero; 1050 1051 best_effort = options & DNS_MESSAGEPARSE_BESTEFFORT; 1052 seen_problem = 0; 1053 1054 section = &msg->sections[sectionid]; 1055 1056 for (count = 0; count < msg->counts[sectionid]; count++) { 1057 int recstart = source->current; 1058 free_rdataset = 0; 1059 1060 name = malloc(sizeof(dns_name_t)); 1061 if (name == NULL) 1062 return (ISC_R_NOMEMORY); 1063 free_name = 1; 1064 1065 offsets = newoffsets(msg); 1066 if (offsets == NULL) { 1067 result = ISC_R_NOMEMORY; 1068 goto cleanup; 1069 } 1070 dns_name_init(name, *offsets); 1071 1072 /* 1073 * Parse the name out of this packet. 1074 */ 1075 isc_buffer_remainingregion(source, &r); 1076 isc_buffer_setactive(source, r.length); 1077 result = getname(name, source, msg, dctx); 1078 if (result != ISC_R_SUCCESS) 1079 goto cleanup; 1080 1081 /* 1082 * Get type, class, ttl, and rdatalen. Verify that at least 1083 * rdatalen bytes remain. (Some of this is deferred to 1084 * later.) 1085 */ 1086 isc_buffer_remainingregion(source, &r); 1087 if (r.length < 2 + 2 + 4 + 2) { 1088 result = ISC_R_UNEXPECTEDEND; 1089 goto cleanup; 1090 } 1091 rdtype = isc_buffer_getuint16(source); 1092 rdclass = isc_buffer_getuint16(source); 1093 1094 /* 1095 * If there was no question section, we may not yet have 1096 * established a class. Do so now. 1097 */ 1098 if (msg->rdclass_set == 0 && 1099 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ 1100 rdtype != dns_rdatatype_tsig && /* class is ANY */ 1101 rdtype != dns_rdatatype_tkey) { /* class is undefined */ 1102 msg->rdclass = rdclass; 1103 msg->rdclass_set = 1; 1104 } 1105 1106 /* 1107 * If this class is different than the one in the question 1108 * section, bail. 1109 */ 1110 if (msg->opcode != dns_opcode_update 1111 && rdtype != dns_rdatatype_tsig 1112 && rdtype != dns_rdatatype_opt 1113 && rdtype != dns_rdatatype_key /* in a TKEY query */ 1114 && rdtype != dns_rdatatype_sig /* SIG(0) */ 1115 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ 1116 && msg->rdclass != dns_rdataclass_any 1117 && msg->rdclass != rdclass) 1118 DO_FORMERR; 1119 1120 /* 1121 * If this is not a TKEY query/response then the KEY 1122 * record's class needs to match. 1123 */ 1124 if (msg->opcode != dns_opcode_update && !msg->tkey && 1125 rdtype == dns_rdatatype_key && 1126 msg->rdclass != dns_rdataclass_any && 1127 msg->rdclass != rdclass) 1128 DO_FORMERR; 1129 1130 /* 1131 * Special type handling for TSIG, OPT, and TKEY. 1132 */ 1133 if (rdtype == dns_rdatatype_tsig) { 1134 /* 1135 * If it is a tsig, verify that it is in the 1136 * additional data section. 1137 */ 1138 if (sectionid != DNS_SECTION_ADDITIONAL || 1139 rdclass != dns_rdataclass_any || 1140 count != msg->counts[sectionid] - 1) 1141 DO_FORMERR; 1142 msg->sigstart = recstart; 1143 } else if (rdtype == dns_rdatatype_opt) { 1144 /* 1145 * The name of an OPT record must be ".", it 1146 * must be in the additional data section, and 1147 * it must be the first OPT we've seen. 1148 */ 1149 if (!dns_name_equal(dns_rootname, name) || 1150 sectionid != DNS_SECTION_ADDITIONAL || 1151 msg->opt != NULL) 1152 DO_FORMERR; 1153 } else if (rdtype == dns_rdatatype_tkey) { 1154 /* 1155 * A TKEY must be in the additional section if this 1156 * is a query, and the answer section if this is a 1157 * response. Unless it's a Win2000 client. 1158 * 1159 * Its class is ignored. 1160 */ 1161 dns_section_t tkeysection; 1162 1163 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) 1164 tkeysection = DNS_SECTION_ADDITIONAL; 1165 else 1166 tkeysection = DNS_SECTION_ANSWER; 1167 if (sectionid != tkeysection && 1168 sectionid != DNS_SECTION_ANSWER) 1169 DO_FORMERR; 1170 } 1171 1172 /* 1173 * ... now get ttl and rdatalen, and check buffer. 1174 */ 1175 ttl = isc_buffer_getuint32(source); 1176 rdatalen = isc_buffer_getuint16(source); 1177 r.length -= (2 + 2 + 4 + 2); 1178 if (r.length < rdatalen) { 1179 result = ISC_R_UNEXPECTEDEND; 1180 goto cleanup; 1181 } 1182 1183 /* 1184 * Read the rdata from the wire format. Interpret the 1185 * rdata according to its actual class, even if it had a 1186 * DynDNS meta-class in the packet (unless this is a TSIG). 1187 * Then put the meta-class back into the finished rdata. 1188 */ 1189 rdata = newrdata(msg); 1190 if (rdata == NULL) { 1191 result = ISC_R_NOMEMORY; 1192 goto cleanup; 1193 } 1194 if (msg->opcode == dns_opcode_update && 1195 update(sectionid, rdclass)) { 1196 if (rdatalen != 0) { 1197 result = DNS_R_FORMERR; 1198 goto cleanup; 1199 } 1200 /* 1201 * When the rdata is empty, the data pointer is 1202 * never dereferenced, but it must still be non-NULL. 1203 * Casting 1 rather than "" avoids warnings about 1204 * discarding the const attribute of a string, 1205 * for compilers that would warn about such things. 1206 */ 1207 rdata->data = (unsigned char *)1; 1208 rdata->length = 0; 1209 rdata->rdclass = rdclass; 1210 rdata->type = rdtype; 1211 rdata->flags = DNS_RDATA_UPDATE; 1212 result = ISC_R_SUCCESS; 1213 } else if (rdclass == dns_rdataclass_none && 1214 msg->opcode == dns_opcode_update && 1215 sectionid == DNS_SECTION_UPDATE) { 1216 result = getrdata(source, msg, dctx, msg->rdclass, 1217 rdtype, rdatalen, rdata); 1218 } else 1219 result = getrdata(source, msg, dctx, rdclass, 1220 rdtype, rdatalen, rdata); 1221 if (result != ISC_R_SUCCESS) 1222 goto cleanup; 1223 rdata->rdclass = rdclass; 1224 issigzero = 0; 1225 if (rdtype == dns_rdatatype_rrsig && 1226 rdata->flags == 0) { 1227 covers = dns_rdata_covers(rdata); 1228 if (covers == 0) 1229 DO_FORMERR; 1230 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1231 rdata->flags == 0) { 1232 covers = dns_rdata_covers(rdata); 1233 if (covers == 0) { 1234 if (sectionid != DNS_SECTION_ADDITIONAL || 1235 count != msg->counts[sectionid] - 1) 1236 DO_FORMERR; 1237 msg->sigstart = recstart; 1238 issigzero = 1; 1239 } else { 1240 if (msg->rdclass != dns_rdataclass_any && 1241 msg->rdclass != rdclass) 1242 DO_FORMERR; 1243 } 1244 } else 1245 covers = 0; 1246 1247 /* 1248 * Check the ownername of NSEC3 records 1249 */ 1250 if (rdtype == dns_rdatatype_nsec3 && 1251 !dns_rdata_checkowner_nsec3(name, msg->rdclass, rdtype, 1252 0)) { 1253 result = DNS_R_BADOWNERNAME; 1254 goto cleanup; 1255 } 1256 1257 if (rdtype != dns_rdatatype_opt && 1258 rdtype != dns_rdatatype_tsig && !issigzero) { 1259 ISC_LIST_APPEND(*section, name, link); 1260 free_name = 0; 1261 } 1262 1263 rdataset = malloc(sizeof(dns_rdataset_t)); 1264 if (rdataset == NULL) { 1265 result = ISC_R_NOMEMORY; 1266 goto cleanup; 1267 } 1268 free_rdataset = 1; 1269 1270 rdatalist = newrdatalist(msg); 1271 if (rdatalist == NULL) { 1272 result = ISC_R_NOMEMORY; 1273 goto cleanup; 1274 } 1275 1276 rdatalist->type = rdtype; 1277 rdatalist->covers = covers; 1278 rdatalist->rdclass = rdclass; 1279 rdatalist->ttl = ttl; 1280 ISC_LIST_INIT(rdatalist->rdata); 1281 1282 dns_rdataset_init(rdataset); 1283 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, 1284 rdataset) 1285 == ISC_R_SUCCESS); 1286 1287 if (rdtype != dns_rdatatype_opt && 1288 rdtype != dns_rdatatype_tsig && 1289 !issigzero) 1290 { 1291 ISC_LIST_APPEND(name->list, rdataset, link); 1292 free_rdataset = 0; 1293 } 1294 1295 /* 1296 * Minimize TTLs. 1297 * 1298 * Section 5.2 of RFC2181 says we should drop 1299 * nonauthoritative rrsets where the TTLs differ, but we 1300 * currently treat them the as if they were authoritative and 1301 * minimize them. 1302 */ 1303 if (ttl != rdataset->ttl) { 1304 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1305 if (ttl < rdataset->ttl) 1306 rdataset->ttl = ttl; 1307 } 1308 1309 /* Append this rdata to the rdataset. */ 1310 dns_rdatalist_fromrdataset(rdataset, &rdatalist); 1311 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1312 1313 /* 1314 * If this is an OPT, SIG(0) or TSIG record, remember it. 1315 * Also, set the extended rcode for TSIG. 1316 * 1317 * Note msg->opt, msg->sig0 and msg->tsig will only be 1318 * already set if best-effort parsing is enabled otherwise 1319 * there will only be at most one of each. 1320 */ 1321 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { 1322 dns_rcode_t ercode; 1323 1324 msg->opt = rdataset; 1325 rdataset = NULL; 1326 free_rdataset = 0; 1327 ercode = (dns_rcode_t) 1328 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) 1329 >> 20); 1330 msg->rcode |= ercode; 1331 free(name); 1332 free_name = 0; 1333 } else if (issigzero && msg->sig0 == NULL) { 1334 msg->sig0 = rdataset; 1335 msg->sig0name = name; 1336 rdataset = NULL; 1337 free_rdataset = 0; 1338 free_name = 0; 1339 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) { 1340 msg->tsig = rdataset; 1341 msg->tsigname = name; 1342 /* Windows doesn't like TSIG names to be compressed. */ 1343 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1344 rdataset = NULL; 1345 free_rdataset = 0; 1346 free_name = 0; 1347 } 1348 1349 if (seen_problem) { 1350 if (free_name) 1351 free(name); 1352 if (free_rdataset) 1353 free(rdataset); 1354 free_name = free_rdataset = 0; 1355 } 1356 INSIST(!free_name); 1357 INSIST(!free_rdataset); 1358 } 1359 1360 if (seen_problem) 1361 return (DNS_R_RECOVERABLE); 1362 return (ISC_R_SUCCESS); 1363 1364 cleanup: 1365 if (free_name) 1366 free(name); 1367 if (free_rdataset) 1368 free(rdataset); 1369 1370 return (result); 1371 } 1372 1373 isc_result_t 1374 dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1375 unsigned int options) 1376 { 1377 isc_region_t r; 1378 dns_decompress_t dctx; 1379 isc_result_t ret; 1380 uint16_t tmpflags; 1381 isc_buffer_t origsource; 1382 int seen_problem; 1383 int ignore_tc; 1384 1385 REQUIRE(source != NULL); 1386 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1387 1388 seen_problem = 0; 1389 ignore_tc = options & DNS_MESSAGEPARSE_IGNORETRUNCATION; 1390 1391 origsource = *source; 1392 1393 msg->header_ok = 0; 1394 msg->question_ok = 0; 1395 1396 isc_buffer_remainingregion(source, &r); 1397 if (r.length < DNS_MESSAGE_HEADERLEN) 1398 return (ISC_R_UNEXPECTEDEND); 1399 1400 msg->id = isc_buffer_getuint16(source); 1401 tmpflags = isc_buffer_getuint16(source); 1402 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1403 >> DNS_MESSAGE_OPCODE_SHIFT); 1404 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1405 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1406 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1407 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1408 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1409 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1410 1411 msg->header_ok = 1; 1412 msg->state = DNS_SECTION_QUESTION; 1413 1414 /* 1415 * -1 means no EDNS. 1416 */ 1417 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1418 1419 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1420 1421 ret = getquestions(source, msg, &dctx, options); 1422 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1423 goto truncated; 1424 if (ret == DNS_R_RECOVERABLE) { 1425 seen_problem = 1; 1426 ret = ISC_R_SUCCESS; 1427 } 1428 if (ret != ISC_R_SUCCESS) 1429 return (ret); 1430 msg->question_ok = 1; 1431 1432 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1433 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1434 goto truncated; 1435 if (ret == DNS_R_RECOVERABLE) { 1436 seen_problem = 1; 1437 ret = ISC_R_SUCCESS; 1438 } 1439 if (ret != ISC_R_SUCCESS) 1440 return (ret); 1441 1442 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1443 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1444 goto truncated; 1445 if (ret == DNS_R_RECOVERABLE) { 1446 seen_problem = 1; 1447 ret = ISC_R_SUCCESS; 1448 } 1449 if (ret != ISC_R_SUCCESS) 1450 return (ret); 1451 1452 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1453 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1454 goto truncated; 1455 if (ret == DNS_R_RECOVERABLE) { 1456 seen_problem = 1; 1457 ret = ISC_R_SUCCESS; 1458 } 1459 if (ret != ISC_R_SUCCESS) 1460 return (ret); 1461 1462 isc_buffer_remainingregion(source, &r); 1463 if (r.length != 0) { 1464 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1465 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1466 "message has %u byte(s) of trailing garbage", 1467 r.length); 1468 } 1469 1470 truncated: 1471 isc_buffer_usedregion(&origsource, &msg->saved); 1472 1473 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1474 return (DNS_R_RECOVERABLE); 1475 if (seen_problem) 1476 return (DNS_R_RECOVERABLE); 1477 return (ISC_R_SUCCESS); 1478 } 1479 1480 isc_result_t 1481 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1482 isc_buffer_t *buffer) 1483 { 1484 isc_region_t r; 1485 1486 REQUIRE(buffer != NULL); 1487 REQUIRE(msg->buffer == NULL); 1488 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1489 1490 msg->cctx = cctx; 1491 1492 /* 1493 * Erase the contents of this buffer. 1494 */ 1495 isc_buffer_clear(buffer); 1496 1497 /* 1498 * Make certain there is enough for at least the header in this 1499 * buffer. 1500 */ 1501 isc_buffer_availableregion(buffer, &r); 1502 if (r.length < DNS_MESSAGE_HEADERLEN) 1503 return (ISC_R_NOSPACE); 1504 1505 if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved) 1506 return (ISC_R_NOSPACE); 1507 1508 /* 1509 * Reserve enough space for the header in this buffer. 1510 */ 1511 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1512 1513 msg->buffer = buffer; 1514 1515 return (ISC_R_SUCCESS); 1516 } 1517 1518 void 1519 dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1520 REQUIRE(space <= msg->reserved); 1521 1522 msg->reserved -= space; 1523 } 1524 1525 isc_result_t 1526 dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1527 isc_region_t r; 1528 1529 if (msg->buffer != NULL) { 1530 isc_buffer_availableregion(msg->buffer, &r); 1531 if (r.length < (space + msg->reserved)) 1532 return (ISC_R_NOSPACE); 1533 } 1534 1535 msg->reserved += space; 1536 1537 return (ISC_R_SUCCESS); 1538 } 1539 1540 static inline int 1541 wrong_priority(dns_rdataset_t *rds, int pass) { 1542 int pass_needed; 1543 1544 /* 1545 * If we are not rendering class IN, this ordering is bogus. 1546 */ 1547 if (rds->rdclass != dns_rdataclass_in) 1548 return (0); 1549 1550 switch (rds->type) { 1551 case dns_rdatatype_a: 1552 case dns_rdatatype_aaaa: 1553 pass_needed = 3; 1554 break; 1555 case dns_rdatatype_rrsig: 1556 case dns_rdatatype_dnskey: 1557 pass_needed = 2; 1558 break; 1559 default: 1560 pass_needed = 1; 1561 } 1562 1563 if (pass_needed >= pass) 1564 return (0); 1565 1566 return (1); 1567 } 1568 1569 static isc_result_t 1570 renderset(dns_rdataset_t *rdataset, dns_name_t *owner_name, 1571 dns_compress_t *cctx, isc_buffer_t *target, 1572 unsigned int reserved, unsigned int *countp) 1573 { 1574 isc_result_t result; 1575 1576 /* 1577 * Shrink the space in the buffer by the reserved amount. 1578 */ 1579 if (target->length - target->used < reserved) 1580 return (ISC_R_NOSPACE); 1581 1582 target->length -= reserved; 1583 result = dns_rdataset_towire(rdataset, owner_name, 1584 cctx, target, countp); 1585 target->length += reserved; 1586 1587 return (result); 1588 } 1589 1590 static void 1591 maybe_clear_ad(dns_message_t *msg, dns_section_t sectionid) { 1592 if (msg->counts[sectionid] == 0 && 1593 (sectionid == DNS_SECTION_ANSWER || 1594 (sectionid == DNS_SECTION_AUTHORITY && 1595 msg->counts[DNS_SECTION_ANSWER] == 0))) 1596 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1597 } 1598 1599 isc_result_t 1600 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid) 1601 { 1602 dns_namelist_t *section; 1603 dns_name_t *name, *next_name; 1604 dns_rdataset_t *rdataset, *next_rdataset; 1605 unsigned int count, total; 1606 isc_result_t result; 1607 isc_buffer_t st; /* for rollbacks */ 1608 int pass; 1609 1610 REQUIRE(msg->buffer != NULL); 1611 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1612 1613 section = &msg->sections[sectionid]; 1614 1615 if (sectionid == DNS_SECTION_ADDITIONAL) 1616 pass = 3; 1617 else 1618 pass = 1; 1619 1620 /* 1621 * Shrink the space in the buffer by the reserved amount. 1622 */ 1623 if (msg->buffer->length - msg->buffer->used < msg->reserved) 1624 return (ISC_R_NOSPACE); 1625 msg->buffer->length -= msg->reserved; 1626 1627 total = 0; 1628 1629 do { 1630 name = ISC_LIST_HEAD(*section); 1631 if (name == NULL) { 1632 msg->buffer->length += msg->reserved; 1633 msg->counts[sectionid] += total; 1634 return (ISC_R_SUCCESS); 1635 } 1636 1637 while (name != NULL) { 1638 next_name = ISC_LIST_NEXT(name, link); 1639 1640 rdataset = ISC_LIST_HEAD(name->list); 1641 while (rdataset != NULL) { 1642 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1643 1644 if ((rdataset->attributes & 1645 DNS_RDATASETATTR_RENDERED) != 0) 1646 goto next; 1647 1648 if ((sectionid == DNS_SECTION_ADDITIONAL) 1649 && wrong_priority(rdataset, pass)) 1650 goto next; 1651 1652 st = *(msg->buffer); 1653 1654 count = 0; 1655 result = dns_rdataset_towiresorted( 1656 rdataset, 1657 name, 1658 msg->cctx, 1659 msg->buffer, 1660 msg->order, 1661 msg->order_arg, 1662 &count); 1663 1664 total += count; 1665 1666 /* 1667 * If out of space, record stats on what we 1668 * rendered so far, and return that status. 1669 * 1670 */ 1671 if (result != ISC_R_SUCCESS) { 1672 INSIST(st.used < 65536); 1673 dns_compress_rollback(msg->cctx, 1674 (uint16_t)st.used); 1675 *(msg->buffer) = st; /* rollback */ 1676 msg->buffer->length += msg->reserved; 1677 msg->counts[sectionid] += total; 1678 maybe_clear_ad(msg, sectionid); 1679 return (result); 1680 } 1681 1682 /* 1683 * If we have rendered non-validated data, 1684 * ensure that the AD bit is not set. 1685 */ 1686 if (rdataset->trust != dns_trust_secure && 1687 (sectionid == DNS_SECTION_ANSWER || 1688 sectionid == DNS_SECTION_AUTHORITY)) 1689 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1690 if (OPTOUT(rdataset)) 1691 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1692 1693 rdataset->attributes |= 1694 DNS_RDATASETATTR_RENDERED; 1695 1696 next: 1697 rdataset = next_rdataset; 1698 } 1699 1700 name = next_name; 1701 } 1702 } while (--pass != 0); 1703 1704 msg->buffer->length += msg->reserved; 1705 msg->counts[sectionid] += total; 1706 1707 return (ISC_R_SUCCESS); 1708 } 1709 1710 void 1711 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 1712 uint16_t tmp; 1713 isc_region_t r; 1714 1715 REQUIRE(target != NULL); 1716 1717 isc_buffer_availableregion(target, &r); 1718 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 1719 1720 isc_buffer_putuint16(target, msg->id); 1721 1722 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 1723 & DNS_MESSAGE_OPCODE_MASK); 1724 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 1725 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 1726 1727 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 1728 msg->counts[DNS_SECTION_ANSWER] < 65536 && 1729 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 1730 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 1731 1732 isc_buffer_putuint16(target, tmp); 1733 isc_buffer_putuint16(target, 1734 (uint16_t)msg->counts[DNS_SECTION_QUESTION]); 1735 isc_buffer_putuint16(target, 1736 (uint16_t)msg->counts[DNS_SECTION_ANSWER]); 1737 isc_buffer_putuint16(target, 1738 (uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 1739 isc_buffer_putuint16(target, 1740 (uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 1741 } 1742 1743 isc_result_t 1744 dns_message_renderend(dns_message_t *msg) { 1745 isc_buffer_t tmpbuf; 1746 isc_region_t r; 1747 int result; 1748 unsigned int count; 1749 1750 REQUIRE(msg->buffer != NULL); 1751 1752 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 1753 /* 1754 * We have an extended rcode but are not using EDNS. 1755 */ 1756 return (DNS_R_FORMERR); 1757 } 1758 1759 /* 1760 * If we're adding a OPT, TSIG or SIG(0) to a truncated message, 1761 * clear all rdatasets from the message except for the question 1762 * before adding the OPT, TSIG or SIG(0). If the question doesn't 1763 * fit, don't include it. 1764 */ 1765 if ((msg->tsigkey != NULL || msg->opt) && 1766 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 1767 { 1768 isc_buffer_t *buf; 1769 1770 msgresetnames(msg, DNS_SECTION_ANSWER); 1771 buf = msg->buffer; 1772 dns_message_renderreset(msg); 1773 msg->buffer = buf; 1774 isc_buffer_clear(msg->buffer); 1775 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 1776 dns_compress_rollback(msg->cctx, 0); 1777 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION); 1778 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 1779 return (result); 1780 } 1781 1782 /* 1783 * If we've got an OPT record, render it. 1784 */ 1785 if (msg->opt != NULL) { 1786 dns_message_renderrelease(msg, msg->opt_reserved); 1787 msg->opt_reserved = 0; 1788 /* 1789 * Set the extended rcode. 1790 */ 1791 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 1792 msg->opt->ttl |= ((msg->rcode << 20) & 1793 DNS_MESSAGE_EDNSRCODE_MASK); 1794 /* 1795 * Render. 1796 */ 1797 count = 0; 1798 result = renderset(msg->opt, dns_rootname, msg->cctx, 1799 msg->buffer, msg->reserved, &count); 1800 msg->counts[DNS_SECTION_ADDITIONAL] += count; 1801 if (result != ISC_R_SUCCESS) 1802 return (result); 1803 } 1804 1805 /* 1806 * If we're adding a TSIG record, generate and render it. 1807 */ 1808 if (msg->tsigkey != NULL) { 1809 dns_message_renderrelease(msg, msg->sig_reserved); 1810 msg->sig_reserved = 0; 1811 result = dns_tsig_sign(msg); 1812 if (result != ISC_R_SUCCESS) 1813 return (result); 1814 count = 0; 1815 result = renderset(msg->tsig, msg->tsigname, msg->cctx, 1816 msg->buffer, msg->reserved, &count); 1817 msg->counts[DNS_SECTION_ADDITIONAL] += count; 1818 if (result != ISC_R_SUCCESS) 1819 return (result); 1820 } 1821 1822 isc_buffer_usedregion(msg->buffer, &r); 1823 isc_buffer_init(&tmpbuf, r.base, r.length); 1824 1825 dns_message_renderheader(msg, &tmpbuf); 1826 1827 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 1828 1829 return (ISC_R_SUCCESS); 1830 } 1831 1832 void 1833 dns_message_renderreset(dns_message_t *msg) { 1834 unsigned int i; 1835 dns_name_t *name; 1836 dns_rdataset_t *rds; 1837 1838 /* 1839 * Reset the message so that it may be rendered again. 1840 */ 1841 1842 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1843 1844 msg->buffer = NULL; 1845 1846 for (i = 0; i < DNS_SECTION_MAX; i++) { 1847 msg->cursors[i] = NULL; 1848 msg->counts[i] = 0; 1849 for (name = ISC_LIST_HEAD(msg->sections[i]); 1850 name != NULL; 1851 name = ISC_LIST_NEXT(name, link)) { 1852 for (rds = ISC_LIST_HEAD(name->list); 1853 rds != NULL; 1854 rds = ISC_LIST_NEXT(rds, link)) { 1855 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 1856 } 1857 } 1858 } 1859 if (msg->tsigname != NULL) 1860 dns_message_puttempname(msg, &msg->tsigname); 1861 if (msg->tsig != NULL) { 1862 dns_rdataset_disassociate(msg->tsig); 1863 dns_message_puttemprdataset(msg, &msg->tsig); 1864 } 1865 if (msg->sig0 != NULL) { 1866 dns_rdataset_disassociate(msg->sig0); 1867 dns_message_puttemprdataset(msg, &msg->sig0); 1868 } 1869 } 1870 1871 isc_result_t 1872 dns_message_firstname(dns_message_t *msg, dns_section_t section) { 1873 REQUIRE(VALID_NAMED_SECTION(section)); 1874 1875 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 1876 1877 if (msg->cursors[section] == NULL) 1878 return (ISC_R_NOMORE); 1879 1880 return (ISC_R_SUCCESS); 1881 } 1882 1883 isc_result_t 1884 dns_message_nextname(dns_message_t *msg, dns_section_t section) { 1885 REQUIRE(VALID_NAMED_SECTION(section)); 1886 REQUIRE(msg->cursors[section] != NULL); 1887 1888 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 1889 1890 if (msg->cursors[section] == NULL) 1891 return (ISC_R_NOMORE); 1892 1893 return (ISC_R_SUCCESS); 1894 } 1895 1896 void 1897 dns_message_currentname(dns_message_t *msg, dns_section_t section, 1898 dns_name_t **name) 1899 { 1900 REQUIRE(VALID_NAMED_SECTION(section)); 1901 REQUIRE(name != NULL && *name == NULL); 1902 REQUIRE(msg->cursors[section] != NULL); 1903 1904 *name = msg->cursors[section]; 1905 } 1906 1907 isc_result_t 1908 dns_message_findname(dns_message_t *msg, dns_section_t section, 1909 dns_name_t *target, dns_rdatatype_t type, 1910 dns_rdatatype_t covers, dns_name_t **name, 1911 dns_rdataset_t **rdataset) 1912 { 1913 dns_name_t *foundname; 1914 isc_result_t result; 1915 1916 /* 1917 * XXX These requirements are probably too intensive, especially 1918 * where things can be NULL, but as they are they ensure that if 1919 * something is NON-NULL, indicating that the caller expects it 1920 * to be filled in, that we can in fact fill it in. 1921 */ 1922 REQUIRE(msg != NULL); 1923 REQUIRE(VALID_SECTION(section)); 1924 REQUIRE(target != NULL); 1925 REQUIRE(name == NULL || *name == NULL); 1926 1927 if (type == dns_rdatatype_any) { 1928 REQUIRE(rdataset == NULL); 1929 } else { 1930 REQUIRE(rdataset == NULL || *rdataset == NULL); 1931 } 1932 1933 result = findname(&foundname, target, 1934 &msg->sections[section]); 1935 1936 if (result == ISC_R_NOTFOUND) 1937 return (DNS_R_NXDOMAIN); 1938 else if (result != ISC_R_SUCCESS) 1939 return (result); 1940 1941 if (name != NULL) 1942 *name = foundname; 1943 1944 /* 1945 * And now look for the type. 1946 */ 1947 if (type == dns_rdatatype_any) 1948 return (ISC_R_SUCCESS); 1949 1950 result = dns_message_findtype(foundname, type, covers, rdataset); 1951 if (result == ISC_R_NOTFOUND) 1952 return (DNS_R_NXRRSET); 1953 1954 return (result); 1955 } 1956 1957 void 1958 dns_message_addname(dns_message_t *msg, dns_name_t *name, 1959 dns_section_t section) 1960 { 1961 REQUIRE(msg != NULL); 1962 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1963 REQUIRE(name != NULL); 1964 REQUIRE(VALID_NAMED_SECTION(section)); 1965 1966 ISC_LIST_APPEND(msg->sections[section], name, link); 1967 } 1968 1969 isc_result_t 1970 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 1971 REQUIRE(item != NULL && *item == NULL); 1972 1973 UNUSED(msg); 1974 1975 *item = malloc(sizeof(dns_name_t)); 1976 if (*item == NULL) 1977 return (ISC_R_NOMEMORY); 1978 dns_name_init(*item, NULL); 1979 1980 return (ISC_R_SUCCESS); 1981 } 1982 1983 isc_result_t 1984 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 1985 REQUIRE(item != NULL && *item == NULL); 1986 1987 *item = newrdata(msg); 1988 if (*item == NULL) 1989 return (ISC_R_NOMEMORY); 1990 1991 return (ISC_R_SUCCESS); 1992 } 1993 1994 isc_result_t 1995 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 1996 REQUIRE(item != NULL && *item == NULL); 1997 1998 UNUSED(msg); 1999 2000 *item = malloc(sizeof(dns_rdataset_t)); 2001 if (*item == NULL) 2002 return (ISC_R_NOMEMORY); 2003 2004 dns_rdataset_init(*item); 2005 2006 return (ISC_R_SUCCESS); 2007 } 2008 2009 isc_result_t 2010 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2011 REQUIRE(item != NULL && *item == NULL); 2012 2013 *item = newrdatalist(msg); 2014 if (*item == NULL) 2015 return (ISC_R_NOMEMORY); 2016 2017 return (ISC_R_SUCCESS); 2018 } 2019 2020 void 2021 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2022 REQUIRE(item != NULL && *item != NULL); 2023 2024 UNUSED(msg); 2025 2026 if (dns_name_dynamic(*item)) 2027 dns_name_free(*item); 2028 free(*item); 2029 *item = NULL; 2030 } 2031 2032 void 2033 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2034 REQUIRE(item != NULL && *item != NULL); 2035 2036 releaserdata(msg, *item); 2037 *item = NULL; 2038 } 2039 2040 void 2041 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2042 REQUIRE(item != NULL && *item != NULL); 2043 REQUIRE(!dns_rdataset_isassociated(*item)); 2044 2045 UNUSED(msg); 2046 2047 free(*item); 2048 *item = NULL; 2049 } 2050 2051 void 2052 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2053 REQUIRE(item != NULL && *item != NULL); 2054 2055 releaserdatalist(msg, *item); 2056 *item = NULL; 2057 } 2058 2059 isc_result_t 2060 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2061 unsigned int *flagsp) 2062 { 2063 isc_region_t r; 2064 isc_buffer_t buffer; 2065 dns_messageid_t id; 2066 unsigned int flags; 2067 2068 REQUIRE(source != NULL); 2069 2070 buffer = *source; 2071 2072 isc_buffer_remainingregion(&buffer, &r); 2073 if (r.length < DNS_MESSAGE_HEADERLEN) 2074 return (ISC_R_UNEXPECTEDEND); 2075 2076 id = isc_buffer_getuint16(&buffer); 2077 flags = isc_buffer_getuint16(&buffer); 2078 flags &= DNS_MESSAGE_FLAG_MASK; 2079 2080 if (flagsp != NULL) 2081 *flagsp = flags; 2082 if (idp != NULL) 2083 *idp = id; 2084 2085 return (ISC_R_SUCCESS); 2086 } 2087 2088 dns_rdataset_t * 2089 dns_message_getopt(dns_message_t *msg) { 2090 2091 /* 2092 * Get the OPT record for 'msg'. 2093 */ 2094 return (msg->opt); 2095 } 2096 2097 isc_result_t 2098 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2099 isc_result_t result; 2100 dns_rdata_t rdata = DNS_RDATA_INIT; 2101 2102 /* 2103 * Set the OPT record for 'msg'. 2104 */ 2105 2106 /* 2107 * The space required for an OPT record is: 2108 * 2109 * 1 byte for the name 2110 * 2 bytes for the type 2111 * 2 bytes for the class 2112 * 4 bytes for the ttl 2113 * 2 bytes for the rdata length 2114 * --------------------------------- 2115 * 11 bytes 2116 * 2117 * plus the length of the rdata. 2118 */ 2119 2120 REQUIRE(opt->type == dns_rdatatype_opt); 2121 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2122 REQUIRE(msg->state == DNS_SECTION_ANY); 2123 2124 msgresetopt(msg); 2125 2126 result = dns_rdataset_first(opt); 2127 if (result != ISC_R_SUCCESS) 2128 goto cleanup; 2129 dns_rdataset_current(opt, &rdata); 2130 msg->opt_reserved = 11 + rdata.length; 2131 result = dns_message_renderreserve(msg, msg->opt_reserved); 2132 if (result != ISC_R_SUCCESS) { 2133 msg->opt_reserved = 0; 2134 goto cleanup; 2135 } 2136 2137 msg->opt = opt; 2138 2139 return (ISC_R_SUCCESS); 2140 2141 cleanup: 2142 dns_rdataset_disassociate(opt); 2143 dns_message_puttemprdataset(msg, &opt); 2144 return (result); 2145 } 2146 2147 dns_rdataset_t * 2148 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2149 2150 /* 2151 * Get the TSIG record and owner for 'msg'. 2152 */ 2153 2154 REQUIRE(owner == NULL || *owner == NULL); 2155 2156 if (owner != NULL) 2157 *owner = msg->tsigname; 2158 return (msg->tsig); 2159 } 2160 2161 isc_result_t 2162 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2163 isc_result_t result; 2164 2165 /* 2166 * Set the TSIG key for 'msg' 2167 */ 2168 2169 REQUIRE(msg->state == DNS_SECTION_ANY); 2170 2171 if (key == NULL && msg->tsigkey != NULL) { 2172 if (msg->sig_reserved != 0) { 2173 dns_message_renderrelease(msg, msg->sig_reserved); 2174 msg->sig_reserved = 0; 2175 } 2176 dns_tsigkey_detach(&msg->tsigkey); 2177 } 2178 if (key != NULL) { 2179 REQUIRE(msg->tsigkey == NULL); 2180 dns_tsigkey_attach(key, &msg->tsigkey); 2181 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2182 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2183 result = dns_message_renderreserve(msg, 2184 msg->sig_reserved); 2185 if (result != ISC_R_SUCCESS) { 2186 dns_tsigkey_detach(&msg->tsigkey); 2187 msg->sig_reserved = 0; 2188 return (result); 2189 } 2190 } 2191 } 2192 return (ISC_R_SUCCESS); 2193 } 2194 2195 dns_tsigkey_t * 2196 dns_message_gettsigkey(dns_message_t *msg) { 2197 2198 /* 2199 * Get the TSIG key for 'msg' 2200 */ 2201 return (msg->tsigkey); 2202 } 2203 2204 isc_result_t 2205 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2206 dns_rdata_t *rdata = NULL; 2207 dns_rdatalist_t *list = NULL; 2208 dns_rdataset_t *set = NULL; 2209 isc_buffer_t *buf = NULL; 2210 isc_region_t r; 2211 isc_result_t result; 2212 2213 REQUIRE(msg->querytsig == NULL); 2214 2215 if (querytsig == NULL) 2216 return (ISC_R_SUCCESS); 2217 2218 result = dns_message_gettemprdata(msg, &rdata); 2219 if (result != ISC_R_SUCCESS) 2220 goto cleanup; 2221 2222 result = dns_message_gettemprdatalist(msg, &list); 2223 if (result != ISC_R_SUCCESS) 2224 goto cleanup; 2225 result = dns_message_gettemprdataset(msg, &set); 2226 if (result != ISC_R_SUCCESS) 2227 goto cleanup; 2228 2229 isc_buffer_usedregion(querytsig, &r); 2230 result = isc_buffer_allocate(&buf, r.length); 2231 if (result != ISC_R_SUCCESS) 2232 goto cleanup; 2233 isc_buffer_putmem(buf, r.base, r.length); 2234 isc_buffer_usedregion(buf, &r); 2235 dns_rdata_init(rdata); 2236 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2237 dns_message_takebuffer(msg, &buf); 2238 ISC_LIST_APPEND(list->rdata, rdata, link); 2239 result = dns_rdatalist_tordataset(list, set); 2240 if (result != ISC_R_SUCCESS) 2241 goto cleanup; 2242 2243 msg->querytsig = set; 2244 2245 return (result); 2246 2247 cleanup: 2248 if (rdata != NULL) 2249 dns_message_puttemprdata(msg, &rdata); 2250 if (list != NULL) 2251 dns_message_puttemprdatalist(msg, &list); 2252 if (set != NULL) 2253 dns_message_puttemprdataset(msg, &set); 2254 return (ISC_R_NOMEMORY); 2255 } 2256 2257 isc_result_t 2258 dns_message_getquerytsig(dns_message_t *msg, isc_buffer_t **querytsig) { 2259 isc_result_t result; 2260 dns_rdata_t rdata = DNS_RDATA_INIT; 2261 isc_region_t r; 2262 2263 REQUIRE(querytsig != NULL && *querytsig == NULL); 2264 2265 if (msg->tsig == NULL) 2266 return (ISC_R_SUCCESS); 2267 2268 result = dns_rdataset_first(msg->tsig); 2269 if (result != ISC_R_SUCCESS) 2270 return (result); 2271 dns_rdataset_current(msg->tsig, &rdata); 2272 dns_rdata_toregion(&rdata, &r); 2273 2274 result = isc_buffer_allocate(querytsig, r.length); 2275 if (result != ISC_R_SUCCESS) 2276 return (result); 2277 isc_buffer_putmem(*querytsig, r.base, r.length); 2278 return (ISC_R_SUCCESS); 2279 } 2280 2281 dns_rdataset_t * 2282 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2283 2284 /* 2285 * Get the SIG(0) record for 'msg'. 2286 */ 2287 2288 REQUIRE(owner == NULL || *owner == NULL); 2289 2290 if (msg->sig0 != NULL && owner != NULL) { 2291 /* If dns_message_getsig0 is called on a rendered message 2292 * after the SIG(0) has been applied, we need to return the 2293 * root name, not NULL. 2294 */ 2295 if (msg->sig0name == NULL) 2296 *owner = dns_rootname; 2297 else 2298 *owner = msg->sig0name; 2299 } 2300 return (msg->sig0); 2301 } 2302 2303 void 2304 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2305 REQUIRE(buffer != NULL); 2306 2307 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2308 *buffer = NULL; 2309 } 2310 2311 isc_result_t 2312 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 2313 const dns_master_style_t *style, 2314 dns_messagetextflag_t flags, 2315 isc_buffer_t *target) { 2316 dns_name_t *name, empty_name; 2317 dns_rdataset_t *rdataset; 2318 isc_result_t result; 2319 int seensoa = 0; 2320 2321 REQUIRE(target != NULL); 2322 REQUIRE(VALID_SECTION(section)); 2323 2324 if (ISC_LIST_EMPTY(msg->sections[section])) 2325 return (ISC_R_SUCCESS); 2326 2327 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 2328 ADD_STRING(target, ";; "); 2329 if (msg->opcode != dns_opcode_update) { 2330 ADD_STRING(target, sectiontext[section]); 2331 } else { 2332 ADD_STRING(target, updsectiontext[section]); 2333 } 2334 ADD_STRING(target, " SECTION:\n"); 2335 } 2336 2337 dns_name_init(&empty_name, NULL); 2338 result = dns_message_firstname(msg, section); 2339 if (result != ISC_R_SUCCESS) { 2340 return (result); 2341 } 2342 do { 2343 name = NULL; 2344 dns_message_currentname(msg, section, &name); 2345 for (rdataset = ISC_LIST_HEAD(name->list); 2346 rdataset != NULL; 2347 rdataset = ISC_LIST_NEXT(rdataset, link)) { 2348 if (section == DNS_SECTION_ANSWER && 2349 rdataset->type == dns_rdatatype_soa) { 2350 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0) 2351 continue; 2352 if (seensoa && 2353 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0) 2354 continue; 2355 seensoa = 1; 2356 } 2357 if (section == DNS_SECTION_QUESTION) { 2358 ADD_STRING(target, ";"); 2359 result = dns_master_questiontotext(name, 2360 rdataset, 2361 style, 2362 target); 2363 } else { 2364 result = dns_master_rdatasettotext(name, 2365 rdataset, 2366 style, 2367 target); 2368 } 2369 if (result != ISC_R_SUCCESS) 2370 return (result); 2371 } 2372 result = dns_message_nextname(msg, section); 2373 } while (result == ISC_R_SUCCESS); 2374 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 2375 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2376 ADD_STRING(target, "\n"); 2377 if (result == ISC_R_NOMORE) 2378 result = ISC_R_SUCCESS; 2379 return (result); 2380 } 2381 2382 static isc_result_t 2383 render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) { 2384 int i; 2385 char addr[16], addr_text[64]; 2386 uint16_t family; 2387 uint8_t addrlen, addrbytes, scopelen; 2388 2389 /* 2390 * Note: This routine needs to handle malformed ECS options. 2391 */ 2392 2393 if (isc_buffer_remaininglength(ecsbuf) < 4) 2394 return (DNS_R_OPTERR); 2395 family = isc_buffer_getuint16(ecsbuf); 2396 addrlen = isc_buffer_getuint8(ecsbuf); 2397 scopelen = isc_buffer_getuint8(ecsbuf); 2398 2399 addrbytes = (addrlen + 7) / 8; 2400 if (isc_buffer_remaininglength(ecsbuf) < addrbytes) 2401 return (DNS_R_OPTERR); 2402 2403 if (addrbytes > sizeof(addr)) 2404 return (DNS_R_OPTERR); 2405 2406 memset(addr, 0, sizeof(addr)); 2407 for (i = 0; i < addrbytes; i ++) 2408 addr[i] = isc_buffer_getuint8(ecsbuf); 2409 2410 switch (family) { 2411 case 0: 2412 if (addrlen != 0U || scopelen != 0U) 2413 return (DNS_R_OPTERR); 2414 strlcpy(addr_text, "0", sizeof(addr_text)); 2415 break; 2416 case 1: 2417 if (addrlen > 32 || scopelen > 32) 2418 return (DNS_R_OPTERR); 2419 inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text)); 2420 break; 2421 case 2: 2422 if (addrlen > 128 || scopelen > 128) 2423 return (DNS_R_OPTERR); 2424 inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text)); 2425 break; 2426 default: 2427 return (DNS_R_OPTERR); 2428 } 2429 2430 ADD_STRING(target, ": "); 2431 ADD_STRING(target, addr_text); 2432 snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen); 2433 ADD_STRING(target, addr_text); 2434 return (ISC_R_SUCCESS); 2435 } 2436 2437 static const char * 2438 ede_info_code2str(uint16_t info_code) 2439 { 2440 if (info_code > 49151) 2441 return "Private Use"; 2442 2443 switch (info_code) { 2444 case 0: 2445 return "Other Error"; 2446 case 1: 2447 return "Unsupported DNSKEY Algorithm"; 2448 case 2: 2449 return "Unsupported DS Digest Type"; 2450 case 3: 2451 return "Stale Answer"; 2452 case 4: 2453 return "Forged Answer"; 2454 case 5: 2455 return "DNSSEC Indeterminate"; 2456 case 6: 2457 return "DNSSEC Bogus"; 2458 case 7: 2459 return "Signature Expired"; 2460 case 8: 2461 return "Signature Not Yet Valid"; 2462 case 9: 2463 return "DNSKEY Missing"; 2464 case 10: 2465 return "RRSIGs Missing"; 2466 case 11: 2467 return "No Zone Key Bit Set"; 2468 case 12: 2469 return "NSEC Missing"; 2470 case 13: 2471 return "Cached Error"; 2472 case 14: 2473 return "Not Ready"; 2474 case 15: 2475 return "Blocked"; 2476 case 16: 2477 return "Censored"; 2478 case 17: 2479 return "Filtered"; 2480 case 18: 2481 return "Prohibited"; 2482 case 19: 2483 return "Stale NXDomain Answer"; 2484 case 20: 2485 return "Not Authoritative"; 2486 case 21: 2487 return "Not Supported"; 2488 case 22: 2489 return "No Reachable Authority"; 2490 case 23: 2491 return "Network Error"; 2492 case 24: 2493 return "Invalid Data"; 2494 default: 2495 return "Unassigned"; 2496 } 2497 } 2498 2499 isc_result_t 2500 dns_message_pseudosectiontotext(dns_message_t *msg, 2501 dns_pseudosection_t section, 2502 const dns_master_style_t *style, 2503 dns_messagetextflag_t flags, 2504 isc_buffer_t *target) 2505 { 2506 dns_rdataset_t *ps = NULL; 2507 dns_name_t *name = NULL; 2508 isc_result_t result; 2509 char buf[sizeof("1234567890")]; 2510 uint32_t mbz; 2511 dns_rdata_t rdata; 2512 isc_buffer_t optbuf; 2513 uint16_t optcode, optlen; 2514 unsigned char *optdata; 2515 2516 REQUIRE(target != NULL); 2517 REQUIRE(VALID_PSEUDOSECTION(section)); 2518 2519 switch (section) { 2520 case DNS_PSEUDOSECTION_OPT: 2521 ps = dns_message_getopt(msg); 2522 if (ps == NULL) 2523 return (ISC_R_SUCCESS); 2524 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2525 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 2526 ADD_STRING(target, "; EDNS: version: "); 2527 snprintf(buf, sizeof(buf), "%u", 2528 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 2529 ADD_STRING(target, buf); 2530 ADD_STRING(target, ", flags:"); 2531 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 2532 ADD_STRING(target, " do"); 2533 mbz = ps->ttl & 0xffff; 2534 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 2535 if (mbz != 0) { 2536 ADD_STRING(target, "; MBZ: "); 2537 snprintf(buf, sizeof(buf), "0x%.4x", mbz); 2538 ADD_STRING(target, buf); 2539 ADD_STRING(target, ", udp: "); 2540 } else 2541 ADD_STRING(target, "; udp: "); 2542 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 2543 ADD_STRING(target, buf); 2544 2545 result = dns_rdataset_first(ps); 2546 if (result != ISC_R_SUCCESS) 2547 return (ISC_R_SUCCESS); 2548 2549 /* 2550 * Print EDNS info, if any. 2551 * 2552 * WARNING: The option contents may be malformed as 2553 * dig +ednsopt=value:<content> does not validity 2554 * checking. 2555 */ 2556 dns_rdata_init(&rdata); 2557 dns_rdataset_current(ps, &rdata); 2558 2559 isc_buffer_init(&optbuf, rdata.data, rdata.length); 2560 isc_buffer_add(&optbuf, rdata.length); 2561 while (isc_buffer_remaininglength(&optbuf) != 0) { 2562 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 2563 optcode = isc_buffer_getuint16(&optbuf); 2564 optlen = isc_buffer_getuint16(&optbuf); 2565 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 2566 2567 if (optcode == DNS_OPT_NSID) { 2568 ADD_STRING(target, "; NSID"); 2569 } else if (optcode == DNS_OPT_COOKIE) { 2570 ADD_STRING(target, "; COOKIE"); 2571 } else if (optcode == DNS_OPT_CLIENT_SUBNET) { 2572 isc_buffer_t ecsbuf; 2573 2574 ADD_STRING(target, "; CLIENT-SUBNET"); 2575 isc_buffer_init(&ecsbuf, 2576 isc_buffer_current(&optbuf), 2577 optlen); 2578 isc_buffer_add(&ecsbuf, optlen); 2579 result = render_ecs(&ecsbuf, target); 2580 if (result == ISC_R_NOSPACE) 2581 return (result); 2582 if (result == ISC_R_SUCCESS) { 2583 isc_buffer_forward(&optbuf, optlen); 2584 ADD_STRING(target, "\n"); 2585 continue; 2586 } 2587 } else if (optcode == DNS_OPT_EXPIRE) { 2588 if (optlen == 4) { 2589 uint32_t secs; 2590 secs = isc_buffer_getuint32(&optbuf); 2591 ADD_STRING(target, "; EXPIRE: "); 2592 snprintf(buf, sizeof(buf), "%u", secs); 2593 ADD_STRING(target, buf); 2594 ADD_STRING(target, " ("); 2595 result = dns_ttl_totext(secs, 2596 1, 2597 target); 2598 if (result != ISC_R_SUCCESS) 2599 return (result); 2600 ADD_STRING(target, ")\n"); 2601 continue; 2602 } 2603 ADD_STRING(target, "; EXPIRE"); 2604 } else if (optcode == DNS_OPT_PAD) { 2605 ADD_STRING(target, "; PAD"); 2606 } else if (optcode == DNS_OPT_KEY_TAG) { 2607 ADD_STRING(target, "; KEY-TAG"); 2608 if (optlen > 0U && (optlen % 2U) == 0U) { 2609 const char *sep = ": "; 2610 uint16_t id; 2611 while (optlen > 0U) { 2612 id = isc_buffer_getuint16(&optbuf); 2613 snprintf(buf, sizeof(buf), "%s%u", 2614 sep, id); 2615 ADD_STRING(target, buf); 2616 sep = ", "; 2617 optlen -= 2; 2618 } 2619 ADD_STRING(target, "\n"); 2620 continue; 2621 } 2622 } else if (optcode == DNS_OPT_EDE) { 2623 uint16_t info_code; 2624 ADD_STRING(target, "; EDE"); 2625 if (optlen >= 2) { 2626 info_code = 2627 isc_buffer_getuint16(&optbuf); 2628 optlen -= 2; 2629 snprintf(buf, sizeof(buf), ": %u (", 2630 info_code); 2631 ADD_STRING(target, buf); 2632 ADD_STRING(target, 2633 ede_info_code2str(info_code)); 2634 ADD_STRING(target, ")"); 2635 } 2636 } else { 2637 ADD_STRING(target, "; OPT="); 2638 snprintf(buf, sizeof(buf), "%u", optcode); 2639 ADD_STRING(target, buf); 2640 } 2641 2642 if (optlen != 0) { 2643 int i; 2644 ADD_STRING(target, ": "); 2645 2646 optdata = isc_buffer_current(&optbuf); 2647 for (i = 0; i < optlen; i++) { 2648 const char *sep; 2649 switch (optcode) { 2650 case DNS_OPT_COOKIE: 2651 sep = ""; 2652 break; 2653 default: 2654 sep = " "; 2655 break; 2656 } 2657 snprintf(buf, sizeof(buf), "%02x%s", 2658 optdata[i], sep); 2659 ADD_STRING(target, buf); 2660 } 2661 2662 isc_buffer_forward(&optbuf, optlen); 2663 2664 if (optcode == DNS_OPT_COOKIE) { 2665 if (msg->sitok) 2666 ADD_STRING(target, " (good)"); 2667 if (msg->sitbad) 2668 ADD_STRING(target, " (bad)"); 2669 ADD_STRING(target, "\n"); 2670 continue; 2671 } 2672 2673 if (optcode == DNS_OPT_CLIENT_SUBNET) { 2674 ADD_STRING(target, "\n"); 2675 continue; 2676 } 2677 2678 /* 2679 * For non-SIT options, add a printable 2680 * version 2681 */ 2682 ADD_STRING(target, "(\""); 2683 if (isc_buffer_availablelength(target) < optlen) 2684 return (ISC_R_NOSPACE); 2685 for (i = 0; i < optlen; i++) { 2686 if (isprint(optdata[i])) 2687 isc_buffer_putmem(target, 2688 &optdata[i], 2689 1); 2690 else 2691 isc_buffer_putstr(target, "."); 2692 } 2693 ADD_STRING(target, "\")"); 2694 } 2695 ADD_STRING(target, "\n"); 2696 } 2697 return (ISC_R_SUCCESS); 2698 case DNS_PSEUDOSECTION_TSIG: 2699 ps = dns_message_gettsig(msg, &name); 2700 if (ps == NULL) 2701 return (ISC_R_SUCCESS); 2702 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2703 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 2704 result = dns_master_rdatasettotext(name, ps, style, target); 2705 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 2706 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2707 ADD_STRING(target, "\n"); 2708 return (result); 2709 case DNS_PSEUDOSECTION_SIG0: 2710 ps = dns_message_getsig0(msg, &name); 2711 if (ps == NULL) 2712 return (ISC_R_SUCCESS); 2713 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2714 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 2715 result = dns_master_rdatasettotext(name, ps, style, target); 2716 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 2717 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 2718 ADD_STRING(target, "\n"); 2719 return (result); 2720 } 2721 return (ISC_R_UNEXPECTED); 2722 } 2723 2724 isc_result_t 2725 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, 2726 unsigned int version, uint16_t udpsize, 2727 unsigned int flags, dns_ednsopt_t *ednsopts, size_t count) 2728 { 2729 dns_rdataset_t *rdataset = NULL; 2730 dns_rdatalist_t *rdatalist = NULL; 2731 dns_rdata_t *rdata = NULL; 2732 isc_result_t result; 2733 unsigned int len = 0, i; 2734 2735 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL); 2736 2737 result = dns_message_gettemprdatalist(message, &rdatalist); 2738 if (result != ISC_R_SUCCESS) 2739 return (result); 2740 result = dns_message_gettemprdata(message, &rdata); 2741 if (result != ISC_R_SUCCESS) 2742 goto cleanup; 2743 result = dns_message_gettemprdataset(message, &rdataset); 2744 if (result != ISC_R_SUCCESS) 2745 goto cleanup; 2746 2747 rdatalist->type = dns_rdatatype_opt; 2748 2749 /* 2750 * Set Maximum UDP buffer size. 2751 */ 2752 rdatalist->rdclass = udpsize; 2753 2754 /* 2755 * Set EXTENDED-RCODE and Z to 0. 2756 */ 2757 rdatalist->ttl = (version << 16); 2758 rdatalist->ttl |= (flags & 0xffff); 2759 2760 /* 2761 * Set EDNS options if applicable 2762 */ 2763 if (count != 0U) { 2764 isc_buffer_t *buf = NULL; 2765 for (i = 0; i < count; i++) 2766 len += ednsopts[i].length + 4; 2767 2768 if (len > 0xffffU) { 2769 result = ISC_R_NOSPACE; 2770 goto cleanup; 2771 } 2772 2773 result = isc_buffer_allocate(&buf, len); 2774 if (result != ISC_R_SUCCESS) 2775 goto cleanup; 2776 2777 for (i = 0; i < count; i++) { 2778 isc_buffer_putuint16(buf, ednsopts[i].code); 2779 isc_buffer_putuint16(buf, ednsopts[i].length); 2780 if (ednsopts[i].length != 0) { 2781 isc_buffer_putmem(buf, ednsopts[i].value, 2782 ednsopts[i].length); 2783 } 2784 } 2785 rdata->data = isc_buffer_base(buf); 2786 rdata->length = len; 2787 dns_message_takebuffer(message, &buf); 2788 } else { 2789 rdata->data = NULL; 2790 rdata->length = 0; 2791 } 2792 2793 rdata->rdclass = rdatalist->rdclass; 2794 rdata->type = rdatalist->type; 2795 rdata->flags = 0; 2796 2797 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 2798 result = dns_rdatalist_tordataset(rdatalist, rdataset); 2799 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2800 2801 *rdatasetp = rdataset; 2802 return (ISC_R_SUCCESS); 2803 2804 cleanup: 2805 if (rdata != NULL) 2806 dns_message_puttemprdata(message, &rdata); 2807 if (rdataset != NULL) 2808 dns_message_puttemprdataset(message, &rdataset); 2809 if (rdatalist != NULL) 2810 dns_message_puttemprdatalist(message, &rdatalist); 2811 return (result); 2812 } 2813