2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
29 #include <isc/buffer.h>
31 #include <isc/print.h>
32 #include <isc/string.h> /* Required for HP/UX (and others?) */
35 #include <dns/dnssec.h>
36 #include <dns/keyvalues.h>
38 #include <dns/masterdump.h>
39 #include <dns/message.h>
40 #include <dns/opcode.h>
41 #include <dns/rdata.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/rdatastruct.h>
45 #include <dns/result.h>
51 hexdump(const char *msg, const char *msg2, void *base, size_t len) {
58 printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
63 else if (cnt % 8 == 0)
65 printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
78 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
79 #define DNS_MESSAGE_OPCODE_SHIFT 11
80 #define DNS_MESSAGE_RCODE_MASK 0x000fU
81 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
82 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
83 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
84 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
85 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
87 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
88 && ((s) < DNS_SECTION_MAX))
89 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
90 && ((s) < DNS_SECTION_MAX))
91 #define ADD_STRING(b, s) {if (strlen(s) >= \
92 isc_buffer_availablelength(b)) \
93 return(ISC_R_NOSPACE); else \
94 isc_buffer_putstr(b, s);}
95 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
96 && ((s) < DNS_PSEUDOSECTION_MAX))
98 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
101 * This is the size of each individual scratchpad buffer, and the numbers
102 * of various block allocations used within the server.
103 * XXXMLG These should come from a config setting.
105 #define SCRATCHPAD_SIZE 512
107 #define OFFSET_COUNT 4
108 #define RDATA_COUNT 8
109 #define RDATALIST_COUNT 8
110 #define RDATASET_COUNT RDATALIST_COUNT
113 * Text representation of the different items, for message_totext
116 static const char *sectiontext[] = {
123 static const char *updsectiontext[] = {
130 static const char *opcodetext[] = {
149 static const char *rcodetext[] = {
171 * "helper" type, which consists of a block of some type, and is linkable.
172 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
173 * size, or the allocated elements will not be aligned correctly.
175 struct dns_msgblock {
177 unsigned int remaining;
178 ISC_LINK(dns_msgblock_t) link;
179 }; /* dynamically sized */
181 static inline dns_msgblock_t *
182 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
184 #define msgblock_get(block, type) \
185 ((type *)msgblock_internalget(block, sizeof(type)))
188 msgblock_internalget(dns_msgblock_t *, unsigned int);
191 msgblock_reset(dns_msgblock_t *);
194 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
197 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
198 * is free, return NULL.
200 static inline dns_msgblock_t *
201 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
204 dns_msgblock_t *block;
207 length = sizeof(dns_msgblock_t) + (sizeof_type * count);
209 block = isc_mem_get(mctx, length);
213 block->count = count;
214 block->remaining = count;
216 ISC_LINK_INIT(block, link);
222 * Return an element from the msgblock. If no more are available, return
226 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
229 if (block == NULL || block->remaining == 0)
234 ptr = (((unsigned char *)block)
235 + sizeof(dns_msgblock_t)
236 + (sizeof_type * block->remaining));
242 msgblock_reset(dns_msgblock_t *block) {
243 block->remaining = block->count;
247 * Release memory associated with a message block.
250 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
254 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
256 isc_mem_put(mctx, block, length);
260 * Allocate a new dynamic buffer, and attach it to this message as the
261 * "current" buffer. (which is always the last on the list, for our
264 static inline isc_result_t
265 newbuffer(dns_message_t *msg, unsigned int size) {
267 isc_buffer_t *dynbuf;
270 result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
271 if (result != ISC_R_SUCCESS)
272 return (ISC_R_NOMEMORY);
274 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
275 return (ISC_R_SUCCESS);
278 static inline isc_buffer_t *
279 currentbuffer(dns_message_t *msg) {
280 isc_buffer_t *dynbuf;
282 dynbuf = ISC_LIST_TAIL(msg->scratchpad);
283 INSIST(dynbuf != NULL);
289 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
290 ISC_LIST_PREPEND(msg->freerdata, rdata, link);
293 static inline dns_rdata_t *
294 newrdata(dns_message_t *msg) {
295 dns_msgblock_t *msgblock;
298 rdata = ISC_LIST_HEAD(msg->freerdata);
300 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
304 msgblock = ISC_LIST_TAIL(msg->rdatas);
305 rdata = msgblock_get(msgblock, dns_rdata_t);
307 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
309 if (msgblock == NULL)
312 ISC_LIST_APPEND(msg->rdatas, msgblock, link);
314 rdata = msgblock_get(msgblock, dns_rdata_t);
317 dns_rdata_init(rdata);
322 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
323 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
326 static inline dns_rdatalist_t *
327 newrdatalist(dns_message_t *msg) {
328 dns_msgblock_t *msgblock;
329 dns_rdatalist_t *rdatalist;
331 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
332 if (rdatalist != NULL) {
333 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
337 msgblock = ISC_LIST_TAIL(msg->rdatalists);
338 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
339 if (rdatalist == NULL) {
340 msgblock = msgblock_allocate(msg->mctx,
341 sizeof(dns_rdatalist_t),
343 if (msgblock == NULL)
346 ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
348 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
354 static inline dns_offsets_t *
355 newoffsets(dns_message_t *msg) {
356 dns_msgblock_t *msgblock;
357 dns_offsets_t *offsets;
359 msgblock = ISC_LIST_TAIL(msg->offsets);
360 offsets = msgblock_get(msgblock, dns_offsets_t);
361 if (offsets == NULL) {
362 msgblock = msgblock_allocate(msg->mctx,
363 sizeof(dns_offsets_t),
365 if (msgblock == NULL)
368 ISC_LIST_APPEND(msg->offsets, msgblock, link);
370 offsets = msgblock_get(msgblock, dns_offsets_t);
377 msginitheader(dns_message_t *m) {
386 msginitprivate(dns_message_t *m) {
389 for (i = 0; i < DNS_SECTION_MAX; i++) {
390 m->cursors[i] = NULL;
398 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
406 msginittsig(dns_message_t *m) {
407 m->tsigstatus = dns_rcode_noerror;
408 m->querytsigstatus = dns_rcode_noerror;
413 m->sig0status = dns_rcode_noerror;
418 * Init elements to default state. Used both when allocating a new element
419 * and when resetting one.
422 msginit(dns_message_t *m) {
428 m->tcp_continuation = 0;
430 m->verify_attempted = 0;
433 m->query.base = NULL;
436 m->saved.base = NULL;
445 msgresetnames(dns_message_t *msg, unsigned int first_section) {
447 dns_name_t *name, *next_name;
448 dns_rdataset_t *rds, *next_rds;
451 * Clean up name lists by calling the rdataset disassociate function.
453 for (i = first_section; i < DNS_SECTION_MAX; i++) {
454 name = ISC_LIST_HEAD(msg->sections[i]);
455 while (name != NULL) {
456 next_name = ISC_LIST_NEXT(name, link);
457 ISC_LIST_UNLINK(msg->sections[i], name, link);
459 rds = ISC_LIST_HEAD(name->list);
460 while (rds != NULL) {
461 next_rds = ISC_LIST_NEXT(rds, link);
462 ISC_LIST_UNLINK(name->list, rds, link);
464 INSIST(dns_rdataset_isassociated(rds));
465 dns_rdataset_disassociate(rds);
466 isc_mempool_put(msg->rdspool, rds);
469 if (dns_name_dynamic(name))
470 dns_name_free(name, msg->mctx);
471 isc_mempool_put(msg->namepool, name);
478 msgresetopt(dns_message_t *msg)
480 if (msg->opt != NULL) {
481 if (msg->opt_reserved > 0) {
482 dns_message_renderrelease(msg, msg->opt_reserved);
483 msg->opt_reserved = 0;
485 INSIST(dns_rdataset_isassociated(msg->opt));
486 dns_rdataset_disassociate(msg->opt);
487 isc_mempool_put(msg->rdspool, msg->opt);
493 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
494 if (msg->sig_reserved > 0) {
495 dns_message_renderrelease(msg, msg->sig_reserved);
496 msg->sig_reserved = 0;
498 if (msg->tsig != NULL) {
499 INSIST(dns_rdataset_isassociated(msg->tsig));
500 INSIST(msg->namepool != NULL);
502 INSIST(msg->querytsig == NULL);
503 msg->querytsig = msg->tsig;
505 dns_rdataset_disassociate(msg->tsig);
506 isc_mempool_put(msg->rdspool, msg->tsig);
507 if (msg->querytsig != NULL) {
508 dns_rdataset_disassociate(msg->querytsig);
509 isc_mempool_put(msg->rdspool, msg->querytsig);
512 if (dns_name_dynamic(msg->tsigname))
513 dns_name_free(msg->tsigname, msg->mctx);
514 isc_mempool_put(msg->namepool, msg->tsigname);
516 msg->tsigname = NULL;
517 } else if (msg->querytsig != NULL && !replying) {
518 dns_rdataset_disassociate(msg->querytsig);
519 isc_mempool_put(msg->rdspool, msg->querytsig);
520 msg->querytsig = NULL;
522 if (msg->sig0 != NULL) {
523 INSIST(dns_rdataset_isassociated(msg->sig0));
524 dns_rdataset_disassociate(msg->sig0);
525 isc_mempool_put(msg->rdspool, msg->sig0);
526 if (msg->sig0name != NULL) {
527 if (dns_name_dynamic(msg->sig0name))
528 dns_name_free(msg->sig0name, msg->mctx);
529 isc_mempool_put(msg->namepool, msg->sig0name);
532 msg->sig0name = NULL;
537 * Free all but one (or everything) for this message. This is used by
538 * both dns_message_reset() and dns_message_destroy().
541 msgreset(dns_message_t *msg, isc_boolean_t everything) {
542 dns_msgblock_t *msgblock, *next_msgblock;
543 isc_buffer_t *dynbuf, *next_dynbuf;
545 dns_rdatalist_t *rdatalist;
547 msgresetnames(msg, 0);
549 msgresetsigs(msg, ISC_FALSE);
552 * Clean up linked lists.
556 * Run through the free lists, and just unlink anything found there.
557 * The memory isn't lost since these are part of message blocks we
560 rdata = ISC_LIST_HEAD(msg->freerdata);
561 while (rdata != NULL) {
562 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
563 rdata = ISC_LIST_HEAD(msg->freerdata);
565 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
566 while (rdatalist != NULL) {
567 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
568 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
571 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
572 INSIST(dynbuf != NULL);
574 isc_buffer_clear(dynbuf);
575 dynbuf = ISC_LIST_NEXT(dynbuf, link);
577 while (dynbuf != NULL) {
578 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
579 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
580 isc_buffer_free(&dynbuf);
581 dynbuf = next_dynbuf;
584 msgblock = ISC_LIST_HEAD(msg->rdatas);
585 if (!everything && msgblock != NULL) {
586 msgblock_reset(msgblock);
587 msgblock = ISC_LIST_NEXT(msgblock, link);
589 while (msgblock != NULL) {
590 next_msgblock = ISC_LIST_NEXT(msgblock, link);
591 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
592 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
593 msgblock = next_msgblock;
597 * rdatalists could be empty.
600 msgblock = ISC_LIST_HEAD(msg->rdatalists);
601 if (!everything && msgblock != NULL) {
602 msgblock_reset(msgblock);
603 msgblock = ISC_LIST_NEXT(msgblock, link);
605 while (msgblock != NULL) {
606 next_msgblock = ISC_LIST_NEXT(msgblock, link);
607 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
608 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
609 msgblock = next_msgblock;
612 msgblock = ISC_LIST_HEAD(msg->offsets);
613 if (!everything && msgblock != NULL) {
614 msgblock_reset(msgblock);
615 msgblock = ISC_LIST_NEXT(msgblock, link);
617 while (msgblock != NULL) {
618 next_msgblock = ISC_LIST_NEXT(msgblock, link);
619 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
620 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
621 msgblock = next_msgblock;
624 if (msg->tsigkey != NULL) {
625 dns_tsigkey_detach(&msg->tsigkey);
629 if (msg->tsigctx != NULL)
630 dst_context_destroy(&msg->tsigctx);
632 if (msg->query.base != NULL) {
633 if (msg->free_query != 0)
634 isc_mem_put(msg->mctx, msg->query.base,
636 msg->query.base = NULL;
637 msg->query.length = 0;
640 if (msg->saved.base != NULL) {
641 if (msg->free_saved != 0)
642 isc_mem_put(msg->mctx, msg->saved.base,
644 msg->saved.base = NULL;
645 msg->saved.length = 0;
649 * cleanup the buffer cleanup list
651 dynbuf = ISC_LIST_HEAD(msg->cleanup);
652 while (dynbuf != NULL) {
653 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
654 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
655 isc_buffer_free(&dynbuf);
656 dynbuf = next_dynbuf;
660 * Set other bits to normal default values.
665 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
666 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
670 spacefortsig(dns_tsigkey_t *key, int otherlen) {
676 * The space required for an TSIG record is:
678 * n1 bytes for the name
679 * 2 bytes for the type
680 * 2 bytes for the class
681 * 4 bytes for the ttl
682 * 2 bytes for the rdlength
683 * n2 bytes for the algorithm name
684 * 6 bytes for the time signed
685 * 2 bytes for the fudge
686 * 2 bytes for the MAC size
687 * x bytes for the MAC
688 * 2 bytes for the original id
689 * 2 bytes for the error
690 * 2 bytes for the other data length
691 * y bytes for the other data (at most)
692 * ---------------------------------
693 * 26 + n1 + n2 + x + y bytes
696 dns_name_toregion(&key->name, &r1);
697 dns_name_toregion(key->algorithm, &r2);
698 if (key->key == NULL)
701 result = dst_key_sigsize(key->key, &x);
702 if (result != ISC_R_SUCCESS)
705 return (26 + r1.length + r2.length + x + otherlen);
709 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
713 isc_buffer_t *dynbuf;
716 REQUIRE(mctx != NULL);
717 REQUIRE(msgp != NULL);
718 REQUIRE(*msgp == NULL);
719 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
720 || intent == DNS_MESSAGE_INTENTRENDER);
722 m = isc_mem_get(mctx, sizeof(dns_message_t));
724 return (ISC_R_NOMEMORY);
727 * No allocations until further notice. Just initialize all lists
728 * and other members that are freed in the cleanup phase here.
731 m->magic = DNS_MESSAGE_MAGIC;
732 m->from_to_wire = intent;
735 for (i = 0; i < DNS_SECTION_MAX; i++)
736 ISC_LIST_INIT(m->sections[i]);
739 isc_mem_attach(mctx, &m->mctx);
741 ISC_LIST_INIT(m->scratchpad);
742 ISC_LIST_INIT(m->cleanup);
745 ISC_LIST_INIT(m->rdatas);
746 ISC_LIST_INIT(m->rdatalists);
747 ISC_LIST_INIT(m->offsets);
748 ISC_LIST_INIT(m->freerdata);
749 ISC_LIST_INIT(m->freerdatalist);
752 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
755 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
756 if (result != ISC_R_SUCCESS)
758 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
759 isc_mempool_setname(m->namepool, "msg:names");
761 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
763 if (result != ISC_R_SUCCESS)
765 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
766 isc_mempool_setname(m->rdspool, "msg:rdataset");
769 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
770 if (result != ISC_R_SUCCESS)
772 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
777 return (ISC_R_SUCCESS);
780 * Cleanup for error returns.
783 dynbuf = ISC_LIST_HEAD(m->scratchpad);
784 if (dynbuf != NULL) {
785 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
786 isc_buffer_free(&dynbuf);
788 if (m->namepool != NULL)
789 isc_mempool_destroy(&m->namepool);
790 if (m->rdspool != NULL)
791 isc_mempool_destroy(&m->rdspool);
793 isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t));
795 return (ISC_R_NOMEMORY);
799 dns_message_reset(dns_message_t *msg, unsigned int intent) {
800 REQUIRE(DNS_MESSAGE_VALID(msg));
801 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
802 || intent == DNS_MESSAGE_INTENTRENDER);
804 msgreset(msg, ISC_FALSE);
805 msg->from_to_wire = intent;
809 dns_message_destroy(dns_message_t **msgp) {
812 REQUIRE(msgp != NULL);
813 REQUIRE(DNS_MESSAGE_VALID(*msgp));
818 msgreset(msg, ISC_TRUE);
819 isc_mempool_destroy(&msg->namepool);
820 isc_mempool_destroy(&msg->rdspool);
822 isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
826 findname(dns_name_t **foundname, dns_name_t *target,
827 dns_namelist_t *section)
831 for (curr = ISC_LIST_TAIL(*section);
833 curr = ISC_LIST_PREV(curr, link)) {
834 if (dns_name_equal(curr, target)) {
835 if (foundname != NULL)
837 return (ISC_R_SUCCESS);
841 return (ISC_R_NOTFOUND);
845 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
846 dns_rdatatype_t type, dns_rdatatype_t covers,
847 dns_rdataset_t **rdataset)
849 dns_rdataset_t *curr;
851 if (rdataset != NULL) {
852 REQUIRE(*rdataset == NULL);
855 for (curr = ISC_LIST_TAIL(name->list);
857 curr = ISC_LIST_PREV(curr, link)) {
858 if (curr->rdclass == rdclass &&
859 curr->type == type && curr->covers == covers) {
860 if (rdataset != NULL)
862 return (ISC_R_SUCCESS);
866 return (ISC_R_NOTFOUND);
870 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
871 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
873 dns_rdataset_t *curr;
875 REQUIRE(name != NULL);
876 if (rdataset != NULL) {
877 REQUIRE(*rdataset == NULL);
880 for (curr = ISC_LIST_TAIL(name->list);
882 curr = ISC_LIST_PREV(curr, link)) {
883 if (curr->type == type && curr->covers == covers) {
884 if (rdataset != NULL)
886 return (ISC_R_SUCCESS);
890 return (ISC_R_NOTFOUND);
894 * Read a name from buffer "source".
897 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
898 dns_decompress_t *dctx)
900 isc_buffer_t *scratch;
904 scratch = currentbuffer(msg);
907 * First try: use current buffer.
908 * Second try: allocate a new buffer and use that.
912 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
915 if (result == ISC_R_NOSPACE) {
918 result = newbuffer(msg, SCRATCHPAD_SIZE);
919 if (result != ISC_R_SUCCESS)
922 scratch = currentbuffer(msg);
923 dns_name_reset(name);
929 INSIST(0); /* Cannot get here... */
930 return (ISC_R_UNEXPECTED);
934 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
935 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
936 unsigned int rdatalen, dns_rdata_t *rdata)
938 isc_buffer_t *scratch;
941 unsigned int trysize;
943 scratch = currentbuffer(msg);
945 isc_buffer_setactive(source, rdatalen);
948 * First try: use current buffer.
949 * Second try: allocate a new buffer of size
950 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
951 * (the data will fit if it was not more than 50% compressed)
952 * Subsequent tries: double buffer size on each try.
956 /* XXX possibly change this to a while (tries < 2) loop */
958 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
962 if (result == ISC_R_NOSPACE) {
964 trysize = 2 * rdatalen;
965 if (trysize < SCRATCHPAD_SIZE)
966 trysize = SCRATCHPAD_SIZE;
968 INSIST(trysize != 0);
969 if (trysize >= 65535)
970 return (ISC_R_NOSPACE);
971 /* XXX DNS_R_RRTOOLONG? */
975 result = newbuffer(msg, trysize);
976 if (result != ISC_R_SUCCESS)
979 scratch = currentbuffer(msg);
989 seen_problem = ISC_TRUE; \
991 result = DNS_R_FORMERR; \
997 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
998 unsigned int options)
1004 dns_offsets_t *offsets;
1005 dns_rdataset_t *rdataset;
1006 dns_rdatalist_t *rdatalist;
1007 isc_result_t result;
1008 dns_rdatatype_t rdtype;
1009 dns_rdataclass_t rdclass;
1010 dns_namelist_t *section;
1011 isc_boolean_t free_name;
1012 isc_boolean_t best_effort;
1013 isc_boolean_t seen_problem;
1015 section = &msg->sections[DNS_SECTION_QUESTION];
1017 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1018 seen_problem = ISC_FALSE;
1024 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
1025 name = isc_mempool_get(msg->namepool);
1027 return (ISC_R_NOMEMORY);
1028 free_name = ISC_TRUE;
1030 offsets = newoffsets(msg);
1031 if (offsets == NULL) {
1032 result = ISC_R_NOMEMORY;
1035 dns_name_init(name, *offsets);
1038 * Parse the name out of this packet.
1040 isc_buffer_remainingregion(source, &r);
1041 isc_buffer_setactive(source, r.length);
1042 result = getname(name, source, msg, dctx);
1043 if (result != ISC_R_SUCCESS)
1047 * Run through the section, looking to see if this name
1048 * is already there. If it is found, put back the allocated
1049 * name since we no longer need it, and set our name pointer
1050 * to point to the name we found.
1052 result = findname(&name2, name, section);
1055 * If it is the first name in the section, accept it.
1057 * If it is not, but is not the same as the name already
1058 * in the question section, append to the section. Note that
1059 * here in the question section this is illegal, so return
1060 * FORMERR. In the future, check the opcode to see if
1061 * this should be legal or not. In either case we no longer
1062 * need this name pointer.
1064 if (result != ISC_R_SUCCESS) {
1065 if (!ISC_LIST_EMPTY(*section))
1067 ISC_LIST_APPEND(*section, name, link);
1068 free_name = ISC_FALSE;
1070 isc_mempool_put(msg->namepool, name);
1073 free_name = ISC_FALSE;
1077 * Get type and class.
1079 isc_buffer_remainingregion(source, &r);
1081 result = ISC_R_UNEXPECTEDEND;
1084 rdtype = isc_buffer_getuint16(source);
1085 rdclass = isc_buffer_getuint16(source);
1088 * If this class is different than the one we already read,
1091 if (msg->rdclass_set == 0) {
1092 msg->rdclass = rdclass;
1093 msg->rdclass_set = 1;
1094 } else if (msg->rdclass != rdclass)
1098 * Is this a TKEY query?
1100 if (rdtype == dns_rdatatype_tkey)
1104 * Can't ask the same question twice.
1106 result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1107 if (result == ISC_R_SUCCESS)
1111 * Allocate a new rdatalist.
1113 rdatalist = newrdatalist(msg);
1114 if (rdatalist == NULL) {
1115 result = ISC_R_NOMEMORY;
1118 rdataset = isc_mempool_get(msg->rdspool);
1119 if (rdataset == NULL) {
1120 result = ISC_R_NOMEMORY;
1125 * Convert rdatalist to rdataset, and attach the latter to
1128 rdatalist->type = rdtype;
1129 rdatalist->covers = 0;
1130 rdatalist->rdclass = rdclass;
1132 ISC_LIST_INIT(rdatalist->rdata);
1134 dns_rdataset_init(rdataset);
1135 result = dns_rdatalist_tordataset(rdatalist, rdataset);
1136 if (result != ISC_R_SUCCESS)
1139 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1141 ISC_LIST_APPEND(name->list, rdataset, link);
1146 return (DNS_R_RECOVERABLE);
1147 return (ISC_R_SUCCESS);
1150 if (rdataset != NULL) {
1151 INSIST(!dns_rdataset_isassociated(rdataset));
1152 isc_mempool_put(msg->rdspool, rdataset);
1155 if (rdatalist != NULL)
1156 isc_mempool_put(msg->rdlpool, rdatalist);
1159 isc_mempool_put(msg->namepool, name);
1164 static isc_boolean_t
1165 update(dns_section_t section, dns_rdataclass_t rdclass) {
1166 if (section == DNS_SECTION_PREREQUISITE)
1167 return (ISC_TF(rdclass == dns_rdataclass_any ||
1168 rdclass == dns_rdataclass_none));
1169 if (section == DNS_SECTION_UPDATE)
1170 return (ISC_TF(rdclass == dns_rdataclass_any));
1175 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1176 dns_section_t sectionid, unsigned int options)
1179 unsigned int count, rdatalen;
1182 dns_offsets_t *offsets;
1183 dns_rdataset_t *rdataset;
1184 dns_rdatalist_t *rdatalist;
1185 isc_result_t result;
1186 dns_rdatatype_t rdtype, covers;
1187 dns_rdataclass_t rdclass;
1190 dns_namelist_t *section;
1191 isc_boolean_t free_name, free_rdataset;
1192 isc_boolean_t preserve_order, best_effort, seen_problem;
1193 isc_boolean_t issigzero;
1195 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1196 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1197 seen_problem = ISC_FALSE;
1199 for (count = 0; count < msg->counts[sectionid]; count++) {
1200 int recstart = source->current;
1201 isc_boolean_t skip_name_search, skip_type_search;
1203 section = &msg->sections[sectionid];
1205 skip_name_search = ISC_FALSE;
1206 skip_type_search = ISC_FALSE;
1207 free_rdataset = ISC_FALSE;
1209 name = isc_mempool_get(msg->namepool);
1211 return (ISC_R_NOMEMORY);
1212 free_name = ISC_TRUE;
1214 offsets = newoffsets(msg);
1215 if (offsets == NULL) {
1216 result = ISC_R_NOMEMORY;
1219 dns_name_init(name, *offsets);
1222 * Parse the name out of this packet.
1224 isc_buffer_remainingregion(source, &r);
1225 isc_buffer_setactive(source, r.length);
1226 result = getname(name, source, msg, dctx);
1227 if (result != ISC_R_SUCCESS)
1231 * Get type, class, ttl, and rdatalen. Verify that at least
1232 * rdatalen bytes remain. (Some of this is deferred to
1235 isc_buffer_remainingregion(source, &r);
1236 if (r.length < 2 + 2 + 4 + 2) {
1237 result = ISC_R_UNEXPECTEDEND;
1240 rdtype = isc_buffer_getuint16(source);
1241 rdclass = isc_buffer_getuint16(source);
1244 * If there was no question section, we may not yet have
1245 * established a class. Do so now.
1247 if (msg->rdclass_set == 0 &&
1248 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
1249 rdtype != dns_rdatatype_tsig && /* class is ANY */
1250 rdtype != dns_rdatatype_tkey) { /* class is undefined */
1251 msg->rdclass = rdclass;
1252 msg->rdclass_set = 1;
1256 * If this class is different than the one in the question
1259 if (msg->opcode != dns_opcode_update
1260 && rdtype != dns_rdatatype_tsig
1261 && rdtype != dns_rdatatype_opt
1262 && rdtype != dns_rdatatype_key /* in a TKEY query */
1263 && rdtype != dns_rdatatype_sig /* SIG(0) */
1264 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1265 && msg->rdclass != dns_rdataclass_any
1266 && msg->rdclass != rdclass)
1270 * If this is not a TKEY query/response then the KEY
1271 * record's class needs to match.
1273 if (msg->opcode != dns_opcode_update && !msg->tkey &&
1274 rdtype == dns_rdatatype_key &&
1275 msg->rdclass != dns_rdataclass_any &&
1276 msg->rdclass != rdclass)
1280 * Special type handling for TSIG, OPT, and TKEY.
1282 if (rdtype == dns_rdatatype_tsig) {
1284 * If it is a tsig, verify that it is in the
1285 * additional data section.
1287 if (sectionid != DNS_SECTION_ADDITIONAL ||
1288 rdclass != dns_rdataclass_any ||
1289 count != msg->counts[sectionid] - 1)
1291 msg->sigstart = recstart;
1292 skip_name_search = ISC_TRUE;
1293 skip_type_search = ISC_TRUE;
1294 } else if (rdtype == dns_rdatatype_opt) {
1296 * The name of an OPT record must be ".", it
1297 * must be in the additional data section, and
1298 * it must be the first OPT we've seen.
1300 if (!dns_name_equal(dns_rootname, name) ||
1303 skip_name_search = ISC_TRUE;
1304 skip_type_search = ISC_TRUE;
1305 } else if (rdtype == dns_rdatatype_tkey) {
1307 * A TKEY must be in the additional section if this
1308 * is a query, and the answer section if this is a
1309 * response. Unless it's a Win2000 client.
1311 * Its class is ignored.
1313 dns_section_t tkeysection;
1315 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1316 tkeysection = DNS_SECTION_ADDITIONAL;
1318 tkeysection = DNS_SECTION_ANSWER;
1319 if (sectionid != tkeysection &&
1320 sectionid != DNS_SECTION_ANSWER)
1325 * ... now get ttl and rdatalen, and check buffer.
1327 ttl = isc_buffer_getuint32(source);
1328 rdatalen = isc_buffer_getuint16(source);
1329 r.length -= (2 + 2 + 4 + 2);
1330 if (r.length < rdatalen) {
1331 result = ISC_R_UNEXPECTEDEND;
1336 * Read the rdata from the wire format. Interpret the
1337 * rdata according to its actual class, even if it had a
1338 * DynDNS meta-class in the packet (unless this is a TSIG).
1339 * Then put the meta-class back into the finished rdata.
1341 rdata = newrdata(msg);
1342 if (rdata == NULL) {
1343 result = ISC_R_NOMEMORY;
1346 if (msg->opcode == dns_opcode_update &&
1347 update(sectionid, rdclass)) {
1348 if (rdatalen != 0) {
1349 result = DNS_R_FORMERR;
1353 * When the rdata is empty, the data pointer is
1354 * never dereferenced, but it must still be non-NULL.
1355 * Casting 1 rather than "" avoids warnings about
1356 * discarding the const attribute of a string,
1357 * for compilers that would warn about such things.
1359 rdata->data = (unsigned char *)1;
1361 rdata->rdclass = rdclass;
1362 rdata->type = rdtype;
1363 rdata->flags = DNS_RDATA_UPDATE;
1364 result = ISC_R_SUCCESS;
1365 } else if (rdclass == dns_rdataclass_none &&
1366 msg->opcode == dns_opcode_update &&
1367 sectionid == DNS_SECTION_UPDATE) {
1368 result = getrdata(source, msg, dctx, msg->rdclass,
1369 rdtype, rdatalen, rdata);
1371 result = getrdata(source, msg, dctx, rdclass,
1372 rdtype, rdatalen, rdata);
1373 if (result != ISC_R_SUCCESS)
1375 rdata->rdclass = rdclass;
1376 issigzero = ISC_FALSE;
1377 if (rdtype == dns_rdatatype_rrsig &&
1378 rdata->flags == 0) {
1379 covers = dns_rdata_covers(rdata);
1382 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
1383 rdata->flags == 0) {
1384 covers = dns_rdata_covers(rdata);
1386 if (sectionid != DNS_SECTION_ADDITIONAL ||
1387 count != msg->counts[sectionid] - 1)
1389 msg->sigstart = recstart;
1390 skip_name_search = ISC_TRUE;
1391 skip_type_search = ISC_TRUE;
1392 issigzero = ISC_TRUE;
1394 if (msg->rdclass != dns_rdataclass_any &&
1395 msg->rdclass != rdclass)
1402 * If we are doing a dynamic update or this is a meta-type,
1403 * don't bother searching for a name, just append this one
1404 * to the end of the message.
1406 if (preserve_order || msg->opcode == dns_opcode_update ||
1408 if (rdtype != dns_rdatatype_opt &&
1409 rdtype != dns_rdatatype_tsig &&
1412 ISC_LIST_APPEND(*section, name, link);
1413 free_name = ISC_FALSE;
1417 * Run through the section, looking to see if this name
1418 * is already there. If it is found, put back the
1419 * allocated name since we no longer need it, and set
1420 * our name pointer to point to the name we found.
1422 result = findname(&name2, name, section);
1425 * If it is a new name, append to the section.
1427 if (result == ISC_R_SUCCESS) {
1428 isc_mempool_put(msg->namepool, name);
1431 ISC_LIST_APPEND(*section, name, link);
1433 free_name = ISC_FALSE;
1437 * Search name for the particular type and class.
1438 * Skip this stage if in update mode or this is a meta-type.
1440 if (preserve_order || msg->opcode == dns_opcode_update ||
1442 result = ISC_R_NOTFOUND;
1445 * If this is a type that can only occur in
1446 * the question section, fail.
1448 if (dns_rdatatype_questiononly(rdtype))
1452 result = dns_message_find(name, rdclass, rdtype,
1457 * If we found an rdataset that matches, we need to
1458 * append this rdata to that set. If we did not, we need
1459 * to create a new rdatalist, store the important bits there,
1460 * convert it to an rdataset, and link the latter to the name.
1461 * Yuck. When appending, make certain that the type isn't
1462 * a singleton type, such as SOA or CNAME.
1464 * Note that this check will be bypassed when preserving order,
1465 * the opcode is an update, or the type search is skipped.
1467 if (result == ISC_R_SUCCESS) {
1468 if (dns_rdatatype_issingleton(rdtype)) {
1470 dns_rdatalist_fromrdataset(rdataset,
1472 first = ISC_LIST_HEAD(rdatalist->rdata);
1473 INSIST(first != NULL);
1474 if (dns_rdata_compare(rdata, first) != 0)
1479 if (result == ISC_R_NOTFOUND) {
1480 rdataset = isc_mempool_get(msg->rdspool);
1481 if (rdataset == NULL) {
1482 result = ISC_R_NOMEMORY;
1485 free_rdataset = ISC_TRUE;
1487 rdatalist = newrdatalist(msg);
1488 if (rdatalist == NULL) {
1489 result = ISC_R_NOMEMORY;
1493 rdatalist->type = rdtype;
1494 rdatalist->covers = covers;
1495 rdatalist->rdclass = rdclass;
1496 rdatalist->ttl = ttl;
1497 ISC_LIST_INIT(rdatalist->rdata);
1499 dns_rdataset_init(rdataset);
1500 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
1504 if (rdtype != dns_rdatatype_opt &&
1505 rdtype != dns_rdatatype_tsig &&
1508 ISC_LIST_APPEND(name->list, rdataset, link);
1509 free_rdataset = ISC_FALSE;
1516 * Section 5.2 of RFC2181 says we should drop
1517 * nonauthoritative rrsets where the TTLs differ, but we
1518 * currently treat them the as if they were authoritative and
1521 if (ttl != rdataset->ttl) {
1522 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1523 if (ttl < rdataset->ttl)
1524 rdataset->ttl = ttl;
1527 /* Append this rdata to the rdataset. */
1528 dns_rdatalist_fromrdataset(rdataset, &rdatalist);
1529 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1532 * If this is an OPT record, remember it. Also, set
1533 * the extended rcode. Note that msg->opt will only be set
1534 * if best-effort parsing is enabled.
1536 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1539 msg->opt = rdataset;
1541 free_rdataset = ISC_FALSE;
1542 ercode = (dns_rcode_t)
1543 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1545 msg->rcode |= ercode;
1546 isc_mempool_put(msg->namepool, name);
1547 free_name = ISC_FALSE;
1551 * If this is an SIG(0) or TSIG record, remember it. Note
1552 * that msg->sig0 or msg->tsig will only be set if best-effort
1553 * parsing is enabled.
1555 if (issigzero && msg->sig0 == NULL) {
1556 msg->sig0 = rdataset;
1557 msg->sig0name = name;
1559 free_rdataset = ISC_FALSE;
1560 free_name = ISC_FALSE;
1561 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1562 msg->tsig = rdataset;
1563 msg->tsigname = name;
1564 /* Windows doesn't like TSIG names to be compressed. */
1565 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1567 free_rdataset = ISC_FALSE;
1568 free_name = ISC_FALSE;
1573 isc_mempool_put(msg->namepool, name);
1575 isc_mempool_put(msg->rdspool, rdataset);
1576 free_name = free_rdataset = ISC_FALSE;
1578 INSIST(free_name == ISC_FALSE);
1579 INSIST(free_rdataset == ISC_FALSE);
1583 return (DNS_R_RECOVERABLE);
1584 return (ISC_R_SUCCESS);
1588 isc_mempool_put(msg->namepool, name);
1590 isc_mempool_put(msg->rdspool, rdataset);
1596 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1597 unsigned int options)
1600 dns_decompress_t dctx;
1602 isc_uint16_t tmpflags;
1603 isc_buffer_t origsource;
1604 isc_boolean_t seen_problem;
1605 isc_boolean_t ignore_tc;
1607 REQUIRE(DNS_MESSAGE_VALID(msg));
1608 REQUIRE(source != NULL);
1609 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1611 seen_problem = ISC_FALSE;
1612 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1614 origsource = *source;
1617 msg->question_ok = 0;
1619 isc_buffer_remainingregion(source, &r);
1620 if (r.length < DNS_MESSAGE_HEADERLEN)
1621 return (ISC_R_UNEXPECTEDEND);
1623 msg->id = isc_buffer_getuint16(source);
1624 tmpflags = isc_buffer_getuint16(source);
1625 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1626 >> DNS_MESSAGE_OPCODE_SHIFT);
1627 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1628 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1629 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1630 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1631 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1632 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1635 msg->state = DNS_SECTION_QUESTION;
1640 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1642 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1644 ret = getquestions(source, msg, &dctx, options);
1645 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1647 if (ret == DNS_R_RECOVERABLE) {
1648 seen_problem = ISC_TRUE;
1649 ret = ISC_R_SUCCESS;
1651 if (ret != ISC_R_SUCCESS)
1653 msg->question_ok = 1;
1655 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1656 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1658 if (ret == DNS_R_RECOVERABLE) {
1659 seen_problem = ISC_TRUE;
1660 ret = ISC_R_SUCCESS;
1662 if (ret != ISC_R_SUCCESS)
1665 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1666 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1668 if (ret == DNS_R_RECOVERABLE) {
1669 seen_problem = ISC_TRUE;
1670 ret = ISC_R_SUCCESS;
1672 if (ret != ISC_R_SUCCESS)
1675 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1676 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1678 if (ret == DNS_R_RECOVERABLE) {
1679 seen_problem = ISC_TRUE;
1680 ret = ISC_R_SUCCESS;
1682 if (ret != ISC_R_SUCCESS)
1685 isc_buffer_remainingregion(source, &r);
1686 if (r.length != 0) {
1687 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1688 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
1689 "message has %u byte(s) of trailing garbage",
1694 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1695 isc_buffer_usedregion(&origsource, &msg->saved);
1697 msg->saved.length = isc_buffer_usedlength(&origsource);
1698 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1699 if (msg->saved.base == NULL)
1700 return (ISC_R_NOMEMORY);
1701 memmove(msg->saved.base, isc_buffer_base(&origsource),
1703 msg->free_saved = 1;
1706 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1707 return (DNS_R_RECOVERABLE);
1708 if (seen_problem == ISC_TRUE)
1709 return (DNS_R_RECOVERABLE);
1710 return (ISC_R_SUCCESS);
1714 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1715 isc_buffer_t *buffer)
1719 REQUIRE(DNS_MESSAGE_VALID(msg));
1720 REQUIRE(buffer != NULL);
1721 REQUIRE(msg->buffer == NULL);
1722 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1727 * Erase the contents of this buffer.
1729 isc_buffer_clear(buffer);
1732 * Make certain there is enough for at least the header in this
1735 isc_buffer_availableregion(buffer, &r);
1736 if (r.length < DNS_MESSAGE_HEADERLEN)
1737 return (ISC_R_NOSPACE);
1739 if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved)
1740 return (ISC_R_NOSPACE);
1743 * Reserve enough space for the header in this buffer.
1745 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1747 msg->buffer = buffer;
1749 return (ISC_R_SUCCESS);
1753 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1756 REQUIRE(DNS_MESSAGE_VALID(msg));
1757 REQUIRE(buffer != NULL);
1758 REQUIRE(msg->buffer != NULL);
1761 * Ensure that the new buffer is empty, and has enough space to
1762 * hold the current contents.
1764 isc_buffer_clear(buffer);
1766 isc_buffer_availableregion(buffer, &rn);
1767 isc_buffer_usedregion(msg->buffer, &r);
1768 REQUIRE(rn.length > r.length);
1771 * Copy the contents from the old to the new buffer.
1773 isc_buffer_add(buffer, r.length);
1774 memmove(rn.base, r.base, r.length);
1776 msg->buffer = buffer;
1778 return (ISC_R_SUCCESS);
1782 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1783 REQUIRE(DNS_MESSAGE_VALID(msg));
1784 REQUIRE(space <= msg->reserved);
1786 msg->reserved -= space;
1790 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1793 REQUIRE(DNS_MESSAGE_VALID(msg));
1795 if (msg->buffer != NULL) {
1796 isc_buffer_availableregion(msg->buffer, &r);
1797 if (r.length < (space + msg->reserved))
1798 return (ISC_R_NOSPACE);
1801 msg->reserved += space;
1803 return (ISC_R_SUCCESS);
1806 static inline isc_boolean_t
1807 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
1811 * If we are not rendering class IN, this ordering is bogus.
1813 if (rds->rdclass != dns_rdataclass_in)
1816 switch (rds->type) {
1817 case dns_rdatatype_a:
1818 case dns_rdatatype_aaaa:
1819 if (preferred_glue == rds->type)
1824 case dns_rdatatype_rrsig:
1825 case dns_rdatatype_dnskey:
1832 if (pass_needed >= pass)
1838 #ifdef ALLOW_FILTER_AAAA_ON_V4
1840 * Decide whether to not answer with an AAAA record and its RRSIG
1842 static inline isc_boolean_t
1843 norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
1845 switch (rdataset->type) {
1846 case dns_rdatatype_aaaa:
1847 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
1851 case dns_rdatatype_rrsig:
1852 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
1853 rdataset->covers != dns_rdatatype_aaaa)
1861 if (rdataset->rdclass != dns_rdataclass_in)
1869 renderset(dns_rdataset_t *rdataset, dns_name_t *owner_name,
1870 dns_compress_t *cctx, isc_buffer_t *target,
1871 unsigned int reserved, unsigned int options, unsigned int *countp)
1873 isc_result_t result;
1876 * Shrink the space in the buffer by the reserved amount.
1878 if (target->length - target->used < reserved)
1879 return (ISC_R_NOSPACE);
1881 target->length -= reserved;
1882 result = dns_rdataset_towire(rdataset, owner_name,
1883 cctx, target, options, countp);
1884 target->length += reserved;
1890 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1891 unsigned int options)
1893 dns_namelist_t *section;
1894 dns_name_t *name, *next_name;
1895 dns_rdataset_t *rdataset, *next_rdataset;
1896 unsigned int count, total;
1897 isc_result_t result;
1898 isc_buffer_t st; /* for rollbacks */
1900 isc_boolean_t partial = ISC_FALSE;
1901 unsigned int rd_options;
1902 dns_rdatatype_t preferred_glue = 0;
1904 REQUIRE(DNS_MESSAGE_VALID(msg));
1905 REQUIRE(msg->buffer != NULL);
1906 REQUIRE(VALID_NAMED_SECTION(sectionid));
1908 section = &msg->sections[sectionid];
1910 if ((sectionid == DNS_SECTION_ADDITIONAL)
1911 && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
1912 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
1913 preferred_glue = dns_rdatatype_a;
1915 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
1916 preferred_glue = dns_rdatatype_aaaa;
1923 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
1926 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
1929 * Shrink the space in the buffer by the reserved amount.
1931 if (msg->buffer->length - msg->buffer->used < msg->reserved)
1932 return (ISC_R_NOSPACE);
1933 msg->buffer->length -= msg->reserved;
1936 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1940 * Render required glue first. Set TC if it won't fit.
1942 name = ISC_LIST_HEAD(*section);
1944 rdataset = ISC_LIST_HEAD(name->list);
1945 if (rdataset != NULL &&
1946 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
1947 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
1948 const void *order_arg = msg->order_arg;
1949 st = *(msg->buffer);
1952 result = dns_rdataset_towirepartial(rdataset,
1962 result = dns_rdataset_towiresorted(rdataset,
1971 if (partial && result == ISC_R_NOSPACE) {
1972 msg->flags |= DNS_MESSAGEFLAG_TC;
1973 msg->buffer->length += msg->reserved;
1974 msg->counts[sectionid] += total;
1977 if (result == ISC_R_NOSPACE)
1978 msg->flags |= DNS_MESSAGEFLAG_TC;
1979 if (result != ISC_R_SUCCESS) {
1980 INSIST(st.used < 65536);
1981 dns_compress_rollback(msg->cctx,
1982 (isc_uint16_t)st.used);
1983 *(msg->buffer) = st; /* rollback */
1984 msg->buffer->length += msg->reserved;
1985 msg->counts[sectionid] += total;
1988 rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
1993 name = ISC_LIST_HEAD(*section);
1995 msg->buffer->length += msg->reserved;
1996 msg->counts[sectionid] += total;
1997 return (ISC_R_SUCCESS);
2000 while (name != NULL) {
2001 next_name = ISC_LIST_NEXT(name, link);
2003 rdataset = ISC_LIST_HEAD(name->list);
2004 while (rdataset != NULL) {
2005 next_rdataset = ISC_LIST_NEXT(rdataset, link);
2007 if ((rdataset->attributes &
2008 DNS_RDATASETATTR_RENDERED) != 0)
2011 if (((options & DNS_MESSAGERENDER_ORDERED)
2013 && (sectionid == DNS_SECTION_ADDITIONAL)
2014 && wrong_priority(rdataset, pass,
2018 #ifdef ALLOW_FILTER_AAAA_ON_V4
2020 * Suppress AAAAs if asked and we are
2021 * not doing DNSSEC or are breaking DNSSEC.
2022 * Say so in the AD bit if we break DNSSEC.
2024 if (norender_rdataset(rdataset, options) &&
2025 sectionid != DNS_SECTION_QUESTION) {
2026 if (sectionid == DNS_SECTION_ANSWER ||
2027 sectionid == DNS_SECTION_AUTHORITY)
2028 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2029 if (OPTOUT(rdataset))
2030 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2035 st = *(msg->buffer);
2039 result = dns_rdataset_towirepartial(
2050 result = dns_rdataset_towiresorted(
2063 * If out of space, record stats on what we
2064 * rendered so far, and return that status.
2066 * XXXMLG Need to change this when
2067 * dns_rdataset_towire() can render partial
2068 * sets starting at some arbitrary point in the
2069 * set. This will include setting a bit in the
2070 * rdataset to indicate that a partial
2071 * rendering was done, and some state saved
2072 * somewhere (probably in the message struct)
2073 * to indicate where to continue from.
2075 if (partial && result == ISC_R_NOSPACE) {
2076 msg->buffer->length += msg->reserved;
2077 msg->counts[sectionid] += total;
2080 if (result != ISC_R_SUCCESS) {
2081 INSIST(st.used < 65536);
2082 dns_compress_rollback(msg->cctx,
2083 (isc_uint16_t)st.used);
2084 *(msg->buffer) = st; /* rollback */
2085 msg->buffer->length += msg->reserved;
2086 msg->counts[sectionid] += total;
2091 * If we have rendered non-validated data,
2092 * ensure that the AD bit is not set.
2094 if (rdataset->trust != dns_trust_secure &&
2095 (sectionid == DNS_SECTION_ANSWER ||
2096 sectionid == DNS_SECTION_AUTHORITY))
2097 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2098 if (OPTOUT(rdataset))
2099 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2101 rdataset->attributes |=
2102 DNS_RDATASETATTR_RENDERED;
2105 rdataset = next_rdataset;
2110 } while (--pass != 0);
2112 msg->buffer->length += msg->reserved;
2113 msg->counts[sectionid] += total;
2115 return (ISC_R_SUCCESS);
2119 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
2123 REQUIRE(DNS_MESSAGE_VALID(msg));
2124 REQUIRE(target != NULL);
2126 isc_buffer_availableregion(target, &r);
2127 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
2129 isc_buffer_putuint16(target, msg->id);
2131 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
2132 & DNS_MESSAGE_OPCODE_MASK);
2133 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
2134 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
2136 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
2137 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
2138 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
2139 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
2141 isc_buffer_putuint16(target, tmp);
2142 isc_buffer_putuint16(target,
2143 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
2144 isc_buffer_putuint16(target,
2145 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
2146 isc_buffer_putuint16(target,
2147 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2148 isc_buffer_putuint16(target,
2149 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
2153 dns_message_renderend(dns_message_t *msg) {
2154 isc_buffer_t tmpbuf;
2159 REQUIRE(DNS_MESSAGE_VALID(msg));
2160 REQUIRE(msg->buffer != NULL);
2162 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
2164 * We have an extended rcode but are not using EDNS.
2166 return (DNS_R_FORMERR);
2170 * If we're adding a OPT, TSIG or SIG(0) to a truncated message,
2171 * clear all rdatasets from the message except for the question
2172 * before adding the OPT, TSIG or SIG(0). If the question doesn't
2173 * fit, don't include it.
2175 if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) &&
2176 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2180 msgresetnames(msg, DNS_SECTION_ANSWER);
2182 dns_message_renderreset(msg);
2184 isc_buffer_clear(msg->buffer);
2185 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
2186 dns_compress_rollback(msg->cctx, 0);
2187 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
2189 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
2194 * If we've got an OPT record, render it.
2196 if (msg->opt != NULL) {
2197 dns_message_renderrelease(msg, msg->opt_reserved);
2198 msg->opt_reserved = 0;
2200 * Set the extended rcode.
2202 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
2203 msg->opt->ttl |= ((msg->rcode << 20) &
2204 DNS_MESSAGE_EDNSRCODE_MASK);
2209 result = renderset(msg->opt, dns_rootname, msg->cctx,
2210 msg->buffer, msg->reserved, 0, &count);
2211 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2212 if (result != ISC_R_SUCCESS)
2217 * If we're adding a TSIG record, generate and render it.
2219 if (msg->tsigkey != NULL) {
2220 dns_message_renderrelease(msg, msg->sig_reserved);
2221 msg->sig_reserved = 0;
2222 result = dns_tsig_sign(msg);
2223 if (result != ISC_R_SUCCESS)
2226 result = renderset(msg->tsig, msg->tsigname, msg->cctx,
2227 msg->buffer, msg->reserved, 0, &count);
2228 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2229 if (result != ISC_R_SUCCESS)
2234 * If we're adding a SIG(0) record, generate and render it.
2236 if (msg->sig0key != NULL) {
2237 dns_message_renderrelease(msg, msg->sig_reserved);
2238 msg->sig_reserved = 0;
2239 result = dns_dnssec_signmessage(msg, msg->sig0key);
2240 if (result != ISC_R_SUCCESS)
2244 * Note: dns_rootname is used here, not msg->sig0name, since
2245 * the owner name of a SIG(0) is irrelevant, and will not
2246 * be set in a message being rendered.
2248 result = renderset(msg->sig0, dns_rootname, msg->cctx,
2249 msg->buffer, msg->reserved, 0, &count);
2250 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2251 if (result != ISC_R_SUCCESS)
2255 isc_buffer_usedregion(msg->buffer, &r);
2256 isc_buffer_init(&tmpbuf, r.base, r.length);
2258 dns_message_renderheader(msg, &tmpbuf);
2260 msg->buffer = NULL; /* forget about this buffer only on success XXX */
2262 return (ISC_R_SUCCESS);
2266 dns_message_renderreset(dns_message_t *msg) {
2269 dns_rdataset_t *rds;
2272 * Reset the message so that it may be rendered again.
2275 REQUIRE(DNS_MESSAGE_VALID(msg));
2276 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2280 for (i = 0; i < DNS_SECTION_MAX; i++) {
2281 msg->cursors[i] = NULL;
2283 for (name = ISC_LIST_HEAD(msg->sections[i]);
2285 name = ISC_LIST_NEXT(name, link)) {
2286 for (rds = ISC_LIST_HEAD(name->list);
2288 rds = ISC_LIST_NEXT(rds, link)) {
2289 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2293 if (msg->tsigname != NULL)
2294 dns_message_puttempname(msg, &msg->tsigname);
2295 if (msg->tsig != NULL) {
2296 dns_rdataset_disassociate(msg->tsig);
2297 dns_message_puttemprdataset(msg, &msg->tsig);
2299 if (msg->sig0 != NULL) {
2300 dns_rdataset_disassociate(msg->sig0);
2301 dns_message_puttemprdataset(msg, &msg->sig0);
2306 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2307 REQUIRE(DNS_MESSAGE_VALID(msg));
2308 REQUIRE(VALID_NAMED_SECTION(section));
2310 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2312 if (msg->cursors[section] == NULL)
2313 return (ISC_R_NOMORE);
2315 return (ISC_R_SUCCESS);
2319 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2320 REQUIRE(DNS_MESSAGE_VALID(msg));
2321 REQUIRE(VALID_NAMED_SECTION(section));
2322 REQUIRE(msg->cursors[section] != NULL);
2324 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2326 if (msg->cursors[section] == NULL)
2327 return (ISC_R_NOMORE);
2329 return (ISC_R_SUCCESS);
2333 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2336 REQUIRE(DNS_MESSAGE_VALID(msg));
2337 REQUIRE(VALID_NAMED_SECTION(section));
2338 REQUIRE(name != NULL && *name == NULL);
2339 REQUIRE(msg->cursors[section] != NULL);
2341 *name = msg->cursors[section];
2345 dns_message_findname(dns_message_t *msg, dns_section_t section,
2346 dns_name_t *target, dns_rdatatype_t type,
2347 dns_rdatatype_t covers, dns_name_t **name,
2348 dns_rdataset_t **rdataset)
2350 dns_name_t *foundname;
2351 isc_result_t result;
2354 * XXX These requirements are probably too intensive, especially
2355 * where things can be NULL, but as they are they ensure that if
2356 * something is NON-NULL, indicating that the caller expects it
2357 * to be filled in, that we can in fact fill it in.
2359 REQUIRE(msg != NULL);
2360 REQUIRE(VALID_SECTION(section));
2361 REQUIRE(target != NULL);
2363 REQUIRE(*name == NULL);
2364 if (type == dns_rdatatype_any) {
2365 REQUIRE(rdataset == NULL);
2367 if (rdataset != NULL)
2368 REQUIRE(*rdataset == NULL);
2371 result = findname(&foundname, target,
2372 &msg->sections[section]);
2374 if (result == ISC_R_NOTFOUND)
2375 return (DNS_R_NXDOMAIN);
2376 else if (result != ISC_R_SUCCESS)
2383 * And now look for the type.
2385 if (type == dns_rdatatype_any)
2386 return (ISC_R_SUCCESS);
2388 result = dns_message_findtype(foundname, type, covers, rdataset);
2389 if (result == ISC_R_NOTFOUND)
2390 return (DNS_R_NXRRSET);
2396 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2397 dns_section_t fromsection,
2398 dns_section_t tosection)
2400 REQUIRE(msg != NULL);
2401 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2402 REQUIRE(name != NULL);
2403 REQUIRE(VALID_NAMED_SECTION(fromsection));
2404 REQUIRE(VALID_NAMED_SECTION(tosection));
2407 * Unlink the name from the old section
2409 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2410 ISC_LIST_APPEND(msg->sections[tosection], name, link);
2414 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2415 dns_section_t section)
2417 REQUIRE(msg != NULL);
2418 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2419 REQUIRE(name != NULL);
2420 REQUIRE(VALID_NAMED_SECTION(section));
2422 ISC_LIST_APPEND(msg->sections[section], name, link);
2426 dns_message_removename(dns_message_t *msg, dns_name_t *name,
2427 dns_section_t section)
2429 REQUIRE(msg != NULL);
2430 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2431 REQUIRE(name != NULL);
2432 REQUIRE(VALID_NAMED_SECTION(section));
2434 ISC_LIST_UNLINK(msg->sections[section], name, link);
2438 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2439 REQUIRE(DNS_MESSAGE_VALID(msg));
2440 REQUIRE(item != NULL && *item == NULL);
2442 *item = isc_mempool_get(msg->namepool);
2444 return (ISC_R_NOMEMORY);
2445 dns_name_init(*item, NULL);
2447 return (ISC_R_SUCCESS);
2451 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2452 REQUIRE(DNS_MESSAGE_VALID(msg));
2453 REQUIRE(item != NULL && *item == NULL);
2455 *item = newoffsets(msg);
2457 return (ISC_R_NOMEMORY);
2459 return (ISC_R_SUCCESS);
2463 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2464 REQUIRE(DNS_MESSAGE_VALID(msg));
2465 REQUIRE(item != NULL && *item == NULL);
2467 *item = newrdata(msg);
2469 return (ISC_R_NOMEMORY);
2471 return (ISC_R_SUCCESS);
2475 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2476 REQUIRE(DNS_MESSAGE_VALID(msg));
2477 REQUIRE(item != NULL && *item == NULL);
2479 *item = isc_mempool_get(msg->rdspool);
2481 return (ISC_R_NOMEMORY);
2483 dns_rdataset_init(*item);
2485 return (ISC_R_SUCCESS);
2489 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2490 REQUIRE(DNS_MESSAGE_VALID(msg));
2491 REQUIRE(item != NULL && *item == NULL);
2493 *item = newrdatalist(msg);
2495 return (ISC_R_NOMEMORY);
2497 return (ISC_R_SUCCESS);
2501 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2502 REQUIRE(DNS_MESSAGE_VALID(msg));
2503 REQUIRE(item != NULL && *item != NULL);
2505 if (dns_name_dynamic(*item))
2506 dns_name_free(*item, msg->mctx);
2507 isc_mempool_put(msg->namepool, *item);
2512 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2513 REQUIRE(DNS_MESSAGE_VALID(msg));
2514 REQUIRE(item != NULL && *item != NULL);
2516 releaserdata(msg, *item);
2521 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2522 REQUIRE(DNS_MESSAGE_VALID(msg));
2523 REQUIRE(item != NULL && *item != NULL);
2525 REQUIRE(!dns_rdataset_isassociated(*item));
2526 isc_mempool_put(msg->rdspool, *item);
2531 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2532 REQUIRE(DNS_MESSAGE_VALID(msg));
2533 REQUIRE(item != NULL && *item != NULL);
2535 releaserdatalist(msg, *item);
2540 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2541 unsigned int *flagsp)
2544 isc_buffer_t buffer;
2548 REQUIRE(source != NULL);
2552 isc_buffer_remainingregion(&buffer, &r);
2553 if (r.length < DNS_MESSAGE_HEADERLEN)
2554 return (ISC_R_UNEXPECTEDEND);
2556 id = isc_buffer_getuint16(&buffer);
2557 flags = isc_buffer_getuint16(&buffer);
2558 flags &= DNS_MESSAGE_FLAG_MASK;
2565 return (ISC_R_SUCCESS);
2569 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2570 unsigned int clear_after;
2571 isc_result_t result;
2573 REQUIRE(DNS_MESSAGE_VALID(msg));
2574 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2576 if (!msg->header_ok)
2577 return (DNS_R_FORMERR);
2578 if (msg->opcode != dns_opcode_query &&
2579 msg->opcode != dns_opcode_notify)
2580 want_question_section = ISC_FALSE;
2581 if (msg->opcode == dns_opcode_update)
2582 clear_after = DNS_SECTION_PREREQUISITE;
2583 else if (want_question_section) {
2584 if (!msg->question_ok)
2585 return (DNS_R_FORMERR);
2586 clear_after = DNS_SECTION_ANSWER;
2588 clear_after = DNS_SECTION_QUESTION;
2589 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2590 msgresetnames(msg, clear_after);
2592 msgresetsigs(msg, ISC_TRUE);
2593 msginitprivate(msg);
2595 * We now clear most flags and then set QR, ensuring that the
2596 * reply's flags will be in a reasonable state.
2598 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2599 msg->flags |= DNS_MESSAGEFLAG_QR;
2602 * This saves the query TSIG status, if the query was signed, and
2603 * reserves space in the reply for the TSIG.
2605 if (msg->tsigkey != NULL) {
2606 unsigned int otherlen = 0;
2607 msg->querytsigstatus = msg->tsigstatus;
2608 msg->tsigstatus = dns_rcode_noerror;
2609 if (msg->querytsigstatus == dns_tsigerror_badtime)
2611 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2612 result = dns_message_renderreserve(msg, msg->sig_reserved);
2613 if (result != ISC_R_SUCCESS) {
2614 msg->sig_reserved = 0;
2618 if (msg->saved.base != NULL) {
2619 msg->query.base = msg->saved.base;
2620 msg->query.length = msg->saved.length;
2621 msg->free_query = msg->free_saved;
2622 msg->saved.base = NULL;
2623 msg->saved.length = 0;
2624 msg->free_saved = 0;
2627 return (ISC_R_SUCCESS);
2631 dns_message_getopt(dns_message_t *msg) {
2634 * Get the OPT record for 'msg'.
2637 REQUIRE(DNS_MESSAGE_VALID(msg));
2643 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2644 isc_result_t result;
2645 dns_rdata_t rdata = DNS_RDATA_INIT;
2648 * Set the OPT record for 'msg'.
2652 * The space required for an OPT record is:
2654 * 1 byte for the name
2655 * 2 bytes for the type
2656 * 2 bytes for the class
2657 * 4 bytes for the ttl
2658 * 2 bytes for the rdata length
2659 * ---------------------------------
2662 * plus the length of the rdata.
2665 REQUIRE(DNS_MESSAGE_VALID(msg));
2666 REQUIRE(opt->type == dns_rdatatype_opt);
2667 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2668 REQUIRE(msg->state == DNS_SECTION_ANY);
2672 result = dns_rdataset_first(opt);
2673 if (result != ISC_R_SUCCESS)
2675 dns_rdataset_current(opt, &rdata);
2676 msg->opt_reserved = 11 + rdata.length;
2677 result = dns_message_renderreserve(msg, msg->opt_reserved);
2678 if (result != ISC_R_SUCCESS) {
2679 msg->opt_reserved = 0;
2685 return (ISC_R_SUCCESS);
2688 dns_rdataset_disassociate(opt);
2689 dns_message_puttemprdataset(msg, &opt);
2694 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2697 * Get the TSIG record and owner for 'msg'.
2700 REQUIRE(DNS_MESSAGE_VALID(msg));
2701 REQUIRE(owner == NULL || *owner == NULL);
2704 *owner = msg->tsigname;
2709 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2710 isc_result_t result;
2713 * Set the TSIG key for 'msg'
2716 REQUIRE(DNS_MESSAGE_VALID(msg));
2717 REQUIRE(msg->state == DNS_SECTION_ANY);
2719 if (key == NULL && msg->tsigkey != NULL) {
2720 if (msg->sig_reserved != 0) {
2721 dns_message_renderrelease(msg, msg->sig_reserved);
2722 msg->sig_reserved = 0;
2724 dns_tsigkey_detach(&msg->tsigkey);
2727 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
2728 dns_tsigkey_attach(key, &msg->tsigkey);
2729 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2730 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2731 result = dns_message_renderreserve(msg,
2733 if (result != ISC_R_SUCCESS) {
2734 dns_tsigkey_detach(&msg->tsigkey);
2735 msg->sig_reserved = 0;
2740 return (ISC_R_SUCCESS);
2744 dns_message_gettsigkey(dns_message_t *msg) {
2747 * Get the TSIG key for 'msg'
2750 REQUIRE(DNS_MESSAGE_VALID(msg));
2752 return (msg->tsigkey);
2756 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2757 dns_rdata_t *rdata = NULL;
2758 dns_rdatalist_t *list = NULL;
2759 dns_rdataset_t *set = NULL;
2760 isc_buffer_t *buf = NULL;
2762 isc_result_t result;
2764 REQUIRE(DNS_MESSAGE_VALID(msg));
2765 REQUIRE(msg->querytsig == NULL);
2767 if (querytsig == NULL)
2768 return (ISC_R_SUCCESS);
2770 result = dns_message_gettemprdata(msg, &rdata);
2771 if (result != ISC_R_SUCCESS)
2774 result = dns_message_gettemprdatalist(msg, &list);
2775 if (result != ISC_R_SUCCESS)
2777 result = dns_message_gettemprdataset(msg, &set);
2778 if (result != ISC_R_SUCCESS)
2781 isc_buffer_usedregion(querytsig, &r);
2782 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2783 if (result != ISC_R_SUCCESS)
2785 isc_buffer_putmem(buf, r.base, r.length);
2786 isc_buffer_usedregion(buf, &r);
2787 dns_rdata_init(rdata);
2788 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2789 dns_message_takebuffer(msg, &buf);
2790 ISC_LIST_INIT(list->rdata);
2791 ISC_LIST_APPEND(list->rdata, rdata, link);
2792 result = dns_rdatalist_tordataset(list, set);
2793 if (result != ISC_R_SUCCESS)
2796 msg->querytsig = set;
2802 dns_message_puttemprdata(msg, &rdata);
2804 dns_message_puttemprdatalist(msg, &list);
2806 dns_message_puttemprdataset(msg, &set);
2807 return (ISC_R_NOMEMORY);
2811 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2812 isc_buffer_t **querytsig) {
2813 isc_result_t result;
2814 dns_rdata_t rdata = DNS_RDATA_INIT;
2817 REQUIRE(DNS_MESSAGE_VALID(msg));
2818 REQUIRE(mctx != NULL);
2819 REQUIRE(querytsig != NULL && *querytsig == NULL);
2821 if (msg->tsig == NULL)
2822 return (ISC_R_SUCCESS);
2824 result = dns_rdataset_first(msg->tsig);
2825 if (result != ISC_R_SUCCESS)
2827 dns_rdataset_current(msg->tsig, &rdata);
2828 dns_rdata_toregion(&rdata, &r);
2830 result = isc_buffer_allocate(mctx, querytsig, r.length);
2831 if (result != ISC_R_SUCCESS)
2833 isc_buffer_putmem(*querytsig, r.base, r.length);
2834 return (ISC_R_SUCCESS);
2838 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2841 * Get the SIG(0) record for 'msg'.
2844 REQUIRE(DNS_MESSAGE_VALID(msg));
2845 REQUIRE(owner == NULL || *owner == NULL);
2847 if (msg->sig0 != NULL && owner != NULL) {
2848 /* If dns_message_getsig0 is called on a rendered message
2849 * after the SIG(0) has been applied, we need to return the
2850 * root name, not NULL.
2852 if (msg->sig0name == NULL)
2853 *owner = dns_rootname;
2855 *owner = msg->sig0name;
2861 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2864 isc_result_t result;
2867 * Set the SIG(0) key for 'msg'
2871 * The space required for an SIG(0) record is:
2873 * 1 byte for the name
2874 * 2 bytes for the type
2875 * 2 bytes for the class
2876 * 4 bytes for the ttl
2877 * 2 bytes for the type covered
2878 * 1 byte for the algorithm
2879 * 1 bytes for the labels
2880 * 4 bytes for the original ttl
2881 * 4 bytes for the signature expiration
2882 * 4 bytes for the signature inception
2883 * 2 bytes for the key tag
2884 * n bytes for the signer's name
2885 * x bytes for the signature
2886 * ---------------------------------
2889 REQUIRE(DNS_MESSAGE_VALID(msg));
2890 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2891 REQUIRE(msg->state == DNS_SECTION_ANY);
2894 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
2895 dns_name_toregion(dst_key_name(key), &r);
2896 result = dst_key_sigsize(key, &x);
2897 if (result != ISC_R_SUCCESS) {
2898 msg->sig_reserved = 0;
2901 msg->sig_reserved = 27 + r.length + x;
2902 result = dns_message_renderreserve(msg, msg->sig_reserved);
2903 if (result != ISC_R_SUCCESS) {
2904 msg->sig_reserved = 0;
2909 return (ISC_R_SUCCESS);
2913 dns_message_getsig0key(dns_message_t *msg) {
2916 * Get the SIG(0) key for 'msg'
2919 REQUIRE(DNS_MESSAGE_VALID(msg));
2921 return (msg->sig0key);
2925 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2926 REQUIRE(DNS_MESSAGE_VALID(msg));
2927 REQUIRE(buffer != NULL);
2928 REQUIRE(ISC_BUFFER_VALID(*buffer));
2930 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2935 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2936 isc_result_t result = ISC_R_SUCCESS;
2937 dns_rdata_t rdata = DNS_RDATA_INIT;
2939 REQUIRE(DNS_MESSAGE_VALID(msg));
2940 REQUIRE(signer != NULL);
2941 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2943 if (msg->tsig == NULL && msg->sig0 == NULL)
2944 return (ISC_R_NOTFOUND);
2946 if (msg->verify_attempted == 0)
2947 return (DNS_R_NOTVERIFIEDYET);
2949 if (!dns_name_hasbuffer(signer)) {
2950 isc_buffer_t *dynbuf = NULL;
2951 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2952 if (result != ISC_R_SUCCESS)
2954 dns_name_setbuffer(signer, dynbuf);
2955 dns_message_takebuffer(msg, &dynbuf);
2958 if (msg->sig0 != NULL) {
2959 dns_rdata_sig_t sig;
2961 result = dns_rdataset_first(msg->sig0);
2962 INSIST(result == ISC_R_SUCCESS);
2963 dns_rdataset_current(msg->sig0, &rdata);
2965 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2966 if (result != ISC_R_SUCCESS)
2969 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2970 result = ISC_R_SUCCESS;
2972 result = DNS_R_SIGINVALID;
2973 dns_name_clone(&sig.signer, signer);
2974 dns_rdata_freestruct(&sig);
2976 dns_name_t *identity;
2977 dns_rdata_any_tsig_t tsig;
2979 result = dns_rdataset_first(msg->tsig);
2980 INSIST(result == ISC_R_SUCCESS);
2981 dns_rdataset_current(msg->tsig, &rdata);
2983 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2984 INSIST(result == ISC_R_SUCCESS);
2985 if (msg->tsigstatus != dns_rcode_noerror)
2986 result = DNS_R_TSIGVERIFYFAILURE;
2987 else if (tsig.error != dns_rcode_noerror)
2988 result = DNS_R_TSIGERRORSET;
2990 result = ISC_R_SUCCESS;
2991 dns_rdata_freestruct(&tsig);
2993 if (msg->tsigkey == NULL) {
2995 * If msg->tsigstatus & tsig.error are both
2996 * dns_rcode_noerror, the message must have been
2997 * verified, which means msg->tsigkey will be
3000 INSIST(result != ISC_R_SUCCESS);
3002 identity = dns_tsigkey_identity(msg->tsigkey);
3003 if (identity == NULL) {
3004 if (result == ISC_R_SUCCESS)
3005 result = DNS_R_NOIDENTITY;
3006 identity = &msg->tsigkey->name;
3008 dns_name_clone(identity, signer);
3016 dns_message_resetsig(dns_message_t *msg) {
3017 REQUIRE(DNS_MESSAGE_VALID(msg));
3018 msg->verified_sig = 0;
3019 msg->verify_attempted = 0;
3020 msg->tsigstatus = dns_rcode_noerror;
3021 msg->sig0status = dns_rcode_noerror;
3022 msg->timeadjust = 0;
3023 if (msg->tsigkey != NULL) {
3024 dns_tsigkey_detach(&msg->tsigkey);
3025 msg->tsigkey = NULL;
3030 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
3031 dns_message_resetsig(msg);
3032 return (dns_message_checksig(msg, view));
3035 #ifdef SKAN_MSG_DEBUG
3037 dns_message_dumpsig(dns_message_t *msg, char *txt1) {
3038 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
3039 dns_rdata_any_tsig_t querytsig;
3040 isc_result_t result;
3042 if (msg->tsig != NULL) {
3043 result = dns_rdataset_first(msg->tsig);
3044 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3045 dns_rdataset_current(msg->tsig, &querytsigrdata);
3046 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3047 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3048 hexdump(txt1, "TSIG", querytsig.signature,
3052 if (msg->querytsig != NULL) {
3053 result = dns_rdataset_first(msg->querytsig);
3054 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3055 dns_rdataset_current(msg->querytsig, &querytsigrdata);
3056 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3057 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3058 hexdump(txt1, "QUERYTSIG", querytsig.signature,
3065 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
3066 isc_buffer_t b, msgb;
3068 REQUIRE(DNS_MESSAGE_VALID(msg));
3070 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
3071 return (ISC_R_SUCCESS);
3073 INSIST(msg->saved.base != NULL);
3074 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
3075 isc_buffer_add(&msgb, msg->saved.length);
3076 if (msg->tsigkey != NULL || msg->tsig != NULL) {
3077 #ifdef SKAN_MSG_DEBUG
3078 dns_message_dumpsig(msg, "dns_message_checksig#1");
3081 return (dns_view_checksig(view, &msgb, msg));
3083 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
3085 dns_rdata_t rdata = DNS_RDATA_INIT;
3086 dns_rdata_sig_t sig;
3087 dns_rdataset_t keyset;
3088 isc_result_t result;
3090 result = dns_rdataset_first(msg->sig0);
3091 INSIST(result == ISC_R_SUCCESS);
3092 dns_rdataset_current(msg->sig0, &rdata);
3095 * This can occur when the message is a dynamic update, since
3096 * the rdata length checking is relaxed. This should not
3097 * happen in a well-formed message, since the SIG(0) is only
3098 * looked for in the additional section, and the dynamic update
3099 * meta-records are in the prerequisite and update sections.
3101 if (rdata.length == 0)
3102 return (ISC_R_UNEXPECTEDEND);
3104 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
3105 if (result != ISC_R_SUCCESS)
3108 dns_rdataset_init(&keyset);
3110 return (DNS_R_KEYUNAUTHORIZED);
3111 result = dns_view_simplefind(view, &sig.signer,
3112 dns_rdatatype_key /* SIG(0) */,
3113 0, 0, ISC_FALSE, &keyset, NULL);
3115 if (result != ISC_R_SUCCESS) {
3116 /* XXXBEW Should possibly create a fetch here */
3117 result = DNS_R_KEYUNAUTHORIZED;
3119 } else if (keyset.trust < dns_trust_secure) {
3120 /* XXXBEW Should call a validator here */
3121 result = DNS_R_KEYUNAUTHORIZED;
3124 result = dns_rdataset_first(&keyset);
3125 INSIST(result == ISC_R_SUCCESS);
3127 result == ISC_R_SUCCESS;
3128 result = dns_rdataset_next(&keyset))
3130 dst_key_t *key = NULL;
3132 dns_rdata_reset(&rdata);
3133 dns_rdataset_current(&keyset, &rdata);
3134 isc_buffer_init(&b, rdata.data, rdata.length);
3135 isc_buffer_add(&b, rdata.length);
3137 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
3138 &b, view->mctx, &key);
3139 if (result != ISC_R_SUCCESS)
3141 if (dst_key_alg(key) != sig.algorithm ||
3142 dst_key_id(key) != sig.keyid ||
3143 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
3144 dst_key_proto(key) == DNS_KEYPROTO_ANY))
3149 result = dns_dnssec_verifymessage(&msgb, msg, key);
3151 if (result == ISC_R_SUCCESS)
3154 if (result == ISC_R_NOMORE)
3155 result = DNS_R_KEYUNAUTHORIZED;
3158 if (dns_rdataset_isassociated(&keyset))
3159 dns_rdataset_disassociate(&keyset);
3160 dns_rdata_freestruct(&sig);
3166 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
3167 const dns_master_style_t *style,
3168 dns_messagetextflag_t flags,
3169 isc_buffer_t *target) {
3170 dns_name_t *name, empty_name;
3171 dns_rdataset_t *rdataset;
3172 isc_result_t result;
3173 isc_boolean_t seensoa = ISC_FALSE;
3175 REQUIRE(DNS_MESSAGE_VALID(msg));
3176 REQUIRE(target != NULL);
3177 REQUIRE(VALID_SECTION(section));
3179 if (ISC_LIST_EMPTY(msg->sections[section]))
3180 return (ISC_R_SUCCESS);
3182 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
3183 ADD_STRING(target, ";; ");
3184 if (msg->opcode != dns_opcode_update) {
3185 ADD_STRING(target, sectiontext[section]);
3187 ADD_STRING(target, updsectiontext[section]);
3189 ADD_STRING(target, " SECTION:\n");
3192 dns_name_init(&empty_name, NULL);
3193 result = dns_message_firstname(msg, section);
3194 if (result != ISC_R_SUCCESS) {
3199 dns_message_currentname(msg, section, &name);
3200 for (rdataset = ISC_LIST_HEAD(name->list);
3202 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3203 if (section == DNS_SECTION_ANSWER &&
3204 rdataset->type == dns_rdatatype_soa) {
3205 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
3208 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
3212 if (section == DNS_SECTION_QUESTION) {
3213 ADD_STRING(target, ";");
3214 result = dns_master_questiontotext(name,
3219 result = dns_master_rdatasettotext(name,
3224 if (result != ISC_R_SUCCESS)
3227 result = dns_message_nextname(msg, section);
3228 } while (result == ISC_R_SUCCESS);
3229 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3230 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3231 ADD_STRING(target, "\n");
3232 if (result == ISC_R_NOMORE)
3233 result = ISC_R_SUCCESS;
3238 dns_message_pseudosectiontotext(dns_message_t *msg,
3239 dns_pseudosection_t section,
3240 const dns_master_style_t *style,
3241 dns_messagetextflag_t flags,
3242 isc_buffer_t *target) {
3243 dns_rdataset_t *ps = NULL;
3244 dns_name_t *name = NULL;
3245 isc_result_t result;
3246 char buf[sizeof("1234567890")];
3249 isc_buffer_t optbuf;
3250 isc_uint16_t optcode, optlen;
3251 unsigned char *optdata;
3253 REQUIRE(DNS_MESSAGE_VALID(msg));
3254 REQUIRE(target != NULL);
3255 REQUIRE(VALID_PSEUDOSECTION(section));
3258 case DNS_PSEUDOSECTION_OPT:
3259 ps = dns_message_getopt(msg);
3261 return (ISC_R_SUCCESS);
3262 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3263 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
3264 ADD_STRING(target, "; EDNS: version: ");
3265 snprintf(buf, sizeof(buf), "%u",
3266 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
3267 ADD_STRING(target, buf);
3268 ADD_STRING(target, ", flags:");
3269 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
3270 ADD_STRING(target, " do");
3271 mbz = ps->ttl & 0xffff;
3272 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */
3274 ADD_STRING(target, "; MBZ: ");
3275 snprintf(buf, sizeof(buf), "%.4x ", mbz);
3276 ADD_STRING(target, buf);
3277 ADD_STRING(target, ", udp: ");
3279 ADD_STRING(target, "; udp: ");
3280 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
3281 ADD_STRING(target, buf);
3283 result = dns_rdataset_first(ps);
3284 if (result != ISC_R_SUCCESS)
3285 return (ISC_R_SUCCESS);
3287 /* Print EDNS info, if any */
3288 dns_rdata_init(&rdata);
3289 dns_rdataset_current(ps, &rdata);
3291 isc_buffer_init(&optbuf, rdata.data, rdata.length);
3292 isc_buffer_add(&optbuf, rdata.length);
3293 while (isc_buffer_remaininglength(&optbuf) != 0) {
3294 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
3295 optcode = isc_buffer_getuint16(&optbuf);
3296 optlen = isc_buffer_getuint16(&optbuf);
3297 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
3299 if (optcode == DNS_OPT_NSID) {
3300 ADD_STRING(target, "; NSID");
3302 ADD_STRING(target, "; OPT=");
3303 sprintf(buf, "%u", optcode);
3304 ADD_STRING(target, buf);
3309 ADD_STRING(target, ": ");
3311 optdata = isc_buffer_current(&optbuf);
3312 for (i = 0; i < optlen; i++) {
3313 sprintf(buf, "%02x ", optdata[i]);
3314 ADD_STRING(target, buf);
3316 for (i = 0; i < optlen; i++) {
3317 ADD_STRING(target, " (");
3318 if (isprint(optdata[i]))
3319 isc_buffer_putmem(target,
3323 isc_buffer_putstr(target, ".");
3324 ADD_STRING(target, ")");
3326 isc_buffer_forward(&optbuf, optlen);
3328 ADD_STRING(target, "\n");
3330 return (ISC_R_SUCCESS);
3331 case DNS_PSEUDOSECTION_TSIG:
3332 ps = dns_message_gettsig(msg, &name);
3334 return (ISC_R_SUCCESS);
3335 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3336 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
3337 result = dns_master_rdatasettotext(name, ps, style, target);
3338 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3339 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3340 ADD_STRING(target, "\n");
3342 case DNS_PSEUDOSECTION_SIG0:
3343 ps = dns_message_getsig0(msg, &name);
3345 return (ISC_R_SUCCESS);
3346 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3347 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
3348 result = dns_master_rdatasettotext(name, ps, style, target);
3349 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3350 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3351 ADD_STRING(target, "\n");
3354 return (ISC_R_UNEXPECTED);
3358 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
3359 dns_messagetextflag_t flags, isc_buffer_t *target) {
3360 char buf[sizeof("1234567890")];
3361 isc_result_t result;
3363 REQUIRE(DNS_MESSAGE_VALID(msg));
3364 REQUIRE(target != NULL);
3366 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
3367 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
3368 ADD_STRING(target, opcodetext[msg->opcode]);
3369 ADD_STRING(target, ", status: ");
3370 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
3371 ADD_STRING(target, rcodetext[msg->rcode]);
3373 snprintf(buf, sizeof(buf), "%4u", msg->rcode);
3374 ADD_STRING(target, buf);
3376 ADD_STRING(target, ", id: ");
3377 snprintf(buf, sizeof(buf), "%6u", msg->id);
3378 ADD_STRING(target, buf);
3379 ADD_STRING(target, "\n;; flags:");
3380 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
3381 ADD_STRING(target, " qr");
3382 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
3383 ADD_STRING(target, " aa");
3384 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
3385 ADD_STRING(target, " tc");
3386 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
3387 ADD_STRING(target, " rd");
3388 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
3389 ADD_STRING(target, " ra");
3390 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3391 ADD_STRING(target, " ad");
3392 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3393 ADD_STRING(target, " cd");
3395 * The final unnamed flag must be zero.
3397 if ((msg->flags & 0x0040U) != 0)
3398 ADD_STRING(target, "; MBZ: 0x4");
3399 if (msg->opcode != dns_opcode_update) {
3400 ADD_STRING(target, "; QUESTION: ");
3402 ADD_STRING(target, "; ZONE: ");
3404 snprintf(buf, sizeof(buf), "%1u",
3405 msg->counts[DNS_SECTION_QUESTION]);
3406 ADD_STRING(target, buf);
3407 if (msg->opcode != dns_opcode_update) {
3408 ADD_STRING(target, ", ANSWER: ");
3410 ADD_STRING(target, ", PREREQ: ");
3412 snprintf(buf, sizeof(buf), "%1u",
3413 msg->counts[DNS_SECTION_ANSWER]);
3414 ADD_STRING(target, buf);
3415 if (msg->opcode != dns_opcode_update) {
3416 ADD_STRING(target, ", AUTHORITY: ");
3418 ADD_STRING(target, ", UPDATE: ");
3420 snprintf(buf, sizeof(buf), "%1u",
3421 msg->counts[DNS_SECTION_AUTHORITY]);
3422 ADD_STRING(target, buf);
3423 ADD_STRING(target, ", ADDITIONAL: ");
3424 snprintf(buf, sizeof(buf), "%1u",
3425 msg->counts[DNS_SECTION_ADDITIONAL]);
3426 ADD_STRING(target, buf);
3427 ADD_STRING(target, "\n");
3429 result = dns_message_pseudosectiontotext(msg,
3430 DNS_PSEUDOSECTION_OPT,
3431 style, flags, target);
3432 if (result != ISC_R_SUCCESS)
3435 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3436 style, flags, target);
3437 if (result != ISC_R_SUCCESS)
3439 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3440 style, flags, target);
3441 if (result != ISC_R_SUCCESS)
3443 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3444 style, flags, target);
3445 if (result != ISC_R_SUCCESS)
3447 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3448 style, flags, target);
3449 if (result != ISC_R_SUCCESS)
3452 result = dns_message_pseudosectiontotext(msg,
3453 DNS_PSEUDOSECTION_TSIG,
3454 style, flags, target);
3455 if (result != ISC_R_SUCCESS)
3458 result = dns_message_pseudosectiontotext(msg,
3459 DNS_PSEUDOSECTION_SIG0,
3460 style, flags, target);
3461 if (result != ISC_R_SUCCESS)
3464 return (ISC_R_SUCCESS);
3468 dns_message_getrawmessage(dns_message_t *msg) {
3469 REQUIRE(DNS_MESSAGE_VALID(msg));
3470 return (&msg->saved);
3474 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3475 const void *order_arg)
3477 REQUIRE(DNS_MESSAGE_VALID(msg));
3479 msg->order_arg = order_arg;
3483 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3484 REQUIRE(DNS_MESSAGE_VALID(msg));
3485 msg->timeadjust = timeadjust;
3489 dns_message_gettimeadjust(dns_message_t *msg) {
3490 REQUIRE(DNS_MESSAGE_VALID(msg));
3491 return (msg->timeadjust);
3495 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
3497 REQUIRE(opcode < 16);
3499 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
3500 return (ISC_R_NOSPACE);
3501 isc_buffer_putstr(target, opcodetext[opcode]);
3502 return (ISC_R_SUCCESS);
3506 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
3507 unsigned int version, isc_uint16_t udpsize,
3508 unsigned int flags, dns_ednsopt_t *ednsopts, size_t count)
3510 dns_rdataset_t *rdataset = NULL;
3511 dns_rdatalist_t *rdatalist = NULL;
3512 dns_rdata_t *rdata = NULL;
3513 isc_result_t result;
3514 unsigned int len = 0, i;
3516 REQUIRE(DNS_MESSAGE_VALID(message));
3517 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
3519 result = dns_message_gettemprdatalist(message, &rdatalist);
3520 if (result != ISC_R_SUCCESS)
3522 result = dns_message_gettemprdata(message, &rdata);
3523 if (result != ISC_R_SUCCESS)
3525 result = dns_message_gettemprdataset(message, &rdataset);
3526 if (result != ISC_R_SUCCESS)
3528 dns_rdataset_init(rdataset);
3530 rdatalist->type = dns_rdatatype_opt;
3531 rdatalist->covers = 0;
3534 * Set Maximum UDP buffer size.
3536 rdatalist->rdclass = udpsize;
3539 * Set EXTENDED-RCODE and Z to 0.
3541 rdatalist->ttl = (version << 16);
3542 rdatalist->ttl |= (flags & 0xffff);
3545 * Set EDNS options if applicable
3548 isc_buffer_t *buf = NULL;
3549 for (i = 0; i < count; i++)
3550 len += ednsopts[i].length + 4;
3552 if (len > 0xffffU) {
3553 result = ISC_R_NOSPACE;
3557 result = isc_buffer_allocate(message->mctx, &buf, len);
3558 if (result != ISC_R_SUCCESS)
3561 for (i = 0; i < count; i++) {
3562 isc_buffer_putuint16(buf, ednsopts[i].code);
3563 isc_buffer_putuint16(buf, ednsopts[i].length);
3564 isc_buffer_putmem(buf, ednsopts[i].value,
3565 ednsopts[i].length);
3567 rdata->data = isc_buffer_base(buf);
3568 rdata->length = len;
3569 dns_message_takebuffer(message, &buf);
3575 rdata->rdclass = rdatalist->rdclass;
3576 rdata->type = rdatalist->type;
3579 ISC_LIST_INIT(rdatalist->rdata);
3580 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
3581 result = dns_rdatalist_tordataset(rdatalist, rdataset);
3582 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3584 *rdatasetp = rdataset;
3585 return (ISC_R_SUCCESS);
3589 dns_message_puttemprdata(message, &rdata);
3590 if (rdataset != NULL)
3591 dns_message_puttemprdataset(message, &rdataset);
3592 if (rdatalist != NULL)
3593 dns_message_puttemprdatalist(message, &rdatalist);
3598 dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) {
3600 REQUIRE(DNS_MESSAGE_VALID(msg));
3601 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
3602 REQUIRE(msg->state == DNS_SECTION_ANY);
3603 REQUIRE(msg->rdclass_set == 0);
3605 msg->rdclass = rdclass;
3606 msg->rdclass_set = 1;