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;
443 msgresetnames(dns_message_t *msg, unsigned int first_section) {
445 dns_name_t *name, *next_name;
446 dns_rdataset_t *rds, *next_rds;
449 * Clean up name lists by calling the rdataset disassociate function.
451 for (i = first_section; i < DNS_SECTION_MAX; i++) {
452 name = ISC_LIST_HEAD(msg->sections[i]);
453 while (name != NULL) {
454 next_name = ISC_LIST_NEXT(name, link);
455 ISC_LIST_UNLINK(msg->sections[i], name, link);
457 rds = ISC_LIST_HEAD(name->list);
458 while (rds != NULL) {
459 next_rds = ISC_LIST_NEXT(rds, link);
460 ISC_LIST_UNLINK(name->list, rds, link);
462 INSIST(dns_rdataset_isassociated(rds));
463 dns_rdataset_disassociate(rds);
464 isc_mempool_put(msg->rdspool, rds);
467 if (dns_name_dynamic(name))
468 dns_name_free(name, msg->mctx);
469 isc_mempool_put(msg->namepool, name);
476 msgresetopt(dns_message_t *msg)
478 if (msg->opt != NULL) {
479 if (msg->opt_reserved > 0) {
480 dns_message_renderrelease(msg, msg->opt_reserved);
481 msg->opt_reserved = 0;
483 INSIST(dns_rdataset_isassociated(msg->opt));
484 dns_rdataset_disassociate(msg->opt);
485 isc_mempool_put(msg->rdspool, msg->opt);
491 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
492 if (msg->sig_reserved > 0) {
493 dns_message_renderrelease(msg, msg->sig_reserved);
494 msg->sig_reserved = 0;
496 if (msg->tsig != NULL) {
497 INSIST(dns_rdataset_isassociated(msg->tsig));
498 INSIST(msg->namepool != NULL);
500 INSIST(msg->querytsig == NULL);
501 msg->querytsig = msg->tsig;
503 dns_rdataset_disassociate(msg->tsig);
504 isc_mempool_put(msg->rdspool, msg->tsig);
505 if (msg->querytsig != NULL) {
506 dns_rdataset_disassociate(msg->querytsig);
507 isc_mempool_put(msg->rdspool, msg->querytsig);
510 if (dns_name_dynamic(msg->tsigname))
511 dns_name_free(msg->tsigname, msg->mctx);
512 isc_mempool_put(msg->namepool, msg->tsigname);
514 msg->tsigname = NULL;
515 } else if (msg->querytsig != NULL && !replying) {
516 dns_rdataset_disassociate(msg->querytsig);
517 isc_mempool_put(msg->rdspool, msg->querytsig);
518 msg->querytsig = NULL;
520 if (msg->sig0 != NULL) {
521 INSIST(dns_rdataset_isassociated(msg->sig0));
522 dns_rdataset_disassociate(msg->sig0);
523 isc_mempool_put(msg->rdspool, msg->sig0);
524 if (msg->sig0name != NULL) {
525 if (dns_name_dynamic(msg->sig0name))
526 dns_name_free(msg->sig0name, msg->mctx);
527 isc_mempool_put(msg->namepool, msg->sig0name);
530 msg->sig0name = NULL;
535 * Free all but one (or everything) for this message. This is used by
536 * both dns_message_reset() and dns_message_destroy().
539 msgreset(dns_message_t *msg, isc_boolean_t everything) {
540 dns_msgblock_t *msgblock, *next_msgblock;
541 isc_buffer_t *dynbuf, *next_dynbuf;
543 dns_rdatalist_t *rdatalist;
545 msgresetnames(msg, 0);
547 msgresetsigs(msg, ISC_FALSE);
550 * Clean up linked lists.
554 * Run through the free lists, and just unlink anything found there.
555 * The memory isn't lost since these are part of message blocks we
558 rdata = ISC_LIST_HEAD(msg->freerdata);
559 while (rdata != NULL) {
560 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
561 rdata = ISC_LIST_HEAD(msg->freerdata);
563 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
564 while (rdatalist != NULL) {
565 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
566 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
569 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
570 INSIST(dynbuf != NULL);
572 isc_buffer_clear(dynbuf);
573 dynbuf = ISC_LIST_NEXT(dynbuf, link);
575 while (dynbuf != NULL) {
576 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
577 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
578 isc_buffer_free(&dynbuf);
579 dynbuf = next_dynbuf;
582 msgblock = ISC_LIST_HEAD(msg->rdatas);
583 if (!everything && msgblock != NULL) {
584 msgblock_reset(msgblock);
585 msgblock = ISC_LIST_NEXT(msgblock, link);
587 while (msgblock != NULL) {
588 next_msgblock = ISC_LIST_NEXT(msgblock, link);
589 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
590 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
591 msgblock = next_msgblock;
595 * rdatalists could be empty.
598 msgblock = ISC_LIST_HEAD(msg->rdatalists);
599 if (!everything && msgblock != NULL) {
600 msgblock_reset(msgblock);
601 msgblock = ISC_LIST_NEXT(msgblock, link);
603 while (msgblock != NULL) {
604 next_msgblock = ISC_LIST_NEXT(msgblock, link);
605 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
606 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
607 msgblock = next_msgblock;
610 msgblock = ISC_LIST_HEAD(msg->offsets);
611 if (!everything && msgblock != NULL) {
612 msgblock_reset(msgblock);
613 msgblock = ISC_LIST_NEXT(msgblock, link);
615 while (msgblock != NULL) {
616 next_msgblock = ISC_LIST_NEXT(msgblock, link);
617 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
618 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
619 msgblock = next_msgblock;
622 if (msg->tsigkey != NULL) {
623 dns_tsigkey_detach(&msg->tsigkey);
627 if (msg->tsigctx != NULL)
628 dst_context_destroy(&msg->tsigctx);
630 if (msg->query.base != NULL) {
631 if (msg->free_query != 0)
632 isc_mem_put(msg->mctx, msg->query.base,
634 msg->query.base = NULL;
635 msg->query.length = 0;
638 if (msg->saved.base != NULL) {
639 if (msg->free_saved != 0)
640 isc_mem_put(msg->mctx, msg->saved.base,
642 msg->saved.base = NULL;
643 msg->saved.length = 0;
647 * cleanup the buffer cleanup list
649 dynbuf = ISC_LIST_HEAD(msg->cleanup);
650 while (dynbuf != NULL) {
651 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
652 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
653 isc_buffer_free(&dynbuf);
654 dynbuf = next_dynbuf;
658 * Set other bits to normal default values.
663 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
664 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
668 spacefortsig(dns_tsigkey_t *key, int otherlen) {
674 * The space required for an TSIG record is:
676 * n1 bytes for the name
677 * 2 bytes for the type
678 * 2 bytes for the class
679 * 4 bytes for the ttl
680 * 2 bytes for the rdlength
681 * n2 bytes for the algorithm name
682 * 6 bytes for the time signed
683 * 2 bytes for the fudge
684 * 2 bytes for the MAC size
685 * x bytes for the MAC
686 * 2 bytes for the original id
687 * 2 bytes for the error
688 * 2 bytes for the other data length
689 * y bytes for the other data (at most)
690 * ---------------------------------
691 * 26 + n1 + n2 + x + y bytes
694 dns_name_toregion(&key->name, &r1);
695 dns_name_toregion(key->algorithm, &r2);
696 if (key->key == NULL)
699 result = dst_key_sigsize(key->key, &x);
700 if (result != ISC_R_SUCCESS)
703 return (26 + r1.length + r2.length + x + otherlen);
707 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
711 isc_buffer_t *dynbuf;
714 REQUIRE(mctx != NULL);
715 REQUIRE(msgp != NULL);
716 REQUIRE(*msgp == NULL);
717 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
718 || intent == DNS_MESSAGE_INTENTRENDER);
720 m = isc_mem_get(mctx, sizeof(dns_message_t));
722 return (ISC_R_NOMEMORY);
725 * No allocations until further notice. Just initialize all lists
726 * and other members that are freed in the cleanup phase here.
729 m->magic = DNS_MESSAGE_MAGIC;
730 m->from_to_wire = intent;
733 for (i = 0; i < DNS_SECTION_MAX; i++)
734 ISC_LIST_INIT(m->sections[i]);
737 isc_mem_attach(mctx, &m->mctx);
739 ISC_LIST_INIT(m->scratchpad);
740 ISC_LIST_INIT(m->cleanup);
743 ISC_LIST_INIT(m->rdatas);
744 ISC_LIST_INIT(m->rdatalists);
745 ISC_LIST_INIT(m->offsets);
746 ISC_LIST_INIT(m->freerdata);
747 ISC_LIST_INIT(m->freerdatalist);
750 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
753 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
754 if (result != ISC_R_SUCCESS)
756 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
757 isc_mempool_setname(m->namepool, "msg:names");
759 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
761 if (result != ISC_R_SUCCESS)
763 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
764 isc_mempool_setname(m->rdspool, "msg:rdataset");
767 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
768 if (result != ISC_R_SUCCESS)
770 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
775 return (ISC_R_SUCCESS);
778 * Cleanup for error returns.
781 dynbuf = ISC_LIST_HEAD(m->scratchpad);
782 if (dynbuf != NULL) {
783 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
784 isc_buffer_free(&dynbuf);
786 if (m->namepool != NULL)
787 isc_mempool_destroy(&m->namepool);
788 if (m->rdspool != NULL)
789 isc_mempool_destroy(&m->rdspool);
791 isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t));
793 return (ISC_R_NOMEMORY);
797 dns_message_reset(dns_message_t *msg, unsigned int intent) {
798 REQUIRE(DNS_MESSAGE_VALID(msg));
799 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
800 || intent == DNS_MESSAGE_INTENTRENDER);
802 msgreset(msg, ISC_FALSE);
803 msg->from_to_wire = intent;
807 dns_message_destroy(dns_message_t **msgp) {
810 REQUIRE(msgp != NULL);
811 REQUIRE(DNS_MESSAGE_VALID(*msgp));
816 msgreset(msg, ISC_TRUE);
817 isc_mempool_destroy(&msg->namepool);
818 isc_mempool_destroy(&msg->rdspool);
820 isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
824 findname(dns_name_t **foundname, dns_name_t *target,
825 dns_namelist_t *section)
829 for (curr = ISC_LIST_TAIL(*section);
831 curr = ISC_LIST_PREV(curr, link)) {
832 if (dns_name_equal(curr, target)) {
833 if (foundname != NULL)
835 return (ISC_R_SUCCESS);
839 return (ISC_R_NOTFOUND);
843 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
844 dns_rdatatype_t type, dns_rdatatype_t covers,
845 dns_rdataset_t **rdataset)
847 dns_rdataset_t *curr;
849 if (rdataset != NULL) {
850 REQUIRE(*rdataset == NULL);
853 for (curr = ISC_LIST_TAIL(name->list);
855 curr = ISC_LIST_PREV(curr, link)) {
856 if (curr->rdclass == rdclass &&
857 curr->type == type && curr->covers == covers) {
858 if (rdataset != NULL)
860 return (ISC_R_SUCCESS);
864 return (ISC_R_NOTFOUND);
868 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
869 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
871 dns_rdataset_t *curr;
873 REQUIRE(name != NULL);
874 if (rdataset != NULL) {
875 REQUIRE(*rdataset == NULL);
878 for (curr = ISC_LIST_TAIL(name->list);
880 curr = ISC_LIST_PREV(curr, link)) {
881 if (curr->type == type && curr->covers == covers) {
882 if (rdataset != NULL)
884 return (ISC_R_SUCCESS);
888 return (ISC_R_NOTFOUND);
892 * Read a name from buffer "source".
895 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
896 dns_decompress_t *dctx)
898 isc_buffer_t *scratch;
902 scratch = currentbuffer(msg);
905 * First try: use current buffer.
906 * Second try: allocate a new buffer and use that.
910 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
913 if (result == ISC_R_NOSPACE) {
916 result = newbuffer(msg, SCRATCHPAD_SIZE);
917 if (result != ISC_R_SUCCESS)
920 scratch = currentbuffer(msg);
921 dns_name_reset(name);
927 INSIST(0); /* Cannot get here... */
928 return (ISC_R_UNEXPECTED);
932 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
933 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
934 unsigned int rdatalen, dns_rdata_t *rdata)
936 isc_buffer_t *scratch;
939 unsigned int trysize;
941 scratch = currentbuffer(msg);
943 isc_buffer_setactive(source, rdatalen);
946 * First try: use current buffer.
947 * Second try: allocate a new buffer of size
948 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
949 * (the data will fit if it was not more than 50% compressed)
950 * Subsequent tries: double buffer size on each try.
954 /* XXX possibly change this to a while (tries < 2) loop */
956 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
960 if (result == ISC_R_NOSPACE) {
962 trysize = 2 * rdatalen;
963 if (trysize < SCRATCHPAD_SIZE)
964 trysize = SCRATCHPAD_SIZE;
966 INSIST(trysize != 0);
967 if (trysize >= 65535)
968 return (ISC_R_NOSPACE);
969 /* XXX DNS_R_RRTOOLONG? */
973 result = newbuffer(msg, trysize);
974 if (result != ISC_R_SUCCESS)
977 scratch = currentbuffer(msg);
987 seen_problem = ISC_TRUE; \
989 result = DNS_R_FORMERR; \
995 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
996 unsigned int options)
1002 dns_offsets_t *offsets;
1003 dns_rdataset_t *rdataset;
1004 dns_rdatalist_t *rdatalist;
1005 isc_result_t result;
1006 dns_rdatatype_t rdtype;
1007 dns_rdataclass_t rdclass;
1008 dns_namelist_t *section;
1009 isc_boolean_t free_name;
1010 isc_boolean_t best_effort;
1011 isc_boolean_t seen_problem;
1013 section = &msg->sections[DNS_SECTION_QUESTION];
1015 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1016 seen_problem = ISC_FALSE;
1022 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
1023 name = isc_mempool_get(msg->namepool);
1025 return (ISC_R_NOMEMORY);
1026 free_name = ISC_TRUE;
1028 offsets = newoffsets(msg);
1029 if (offsets == NULL) {
1030 result = ISC_R_NOMEMORY;
1033 dns_name_init(name, *offsets);
1036 * Parse the name out of this packet.
1038 isc_buffer_remainingregion(source, &r);
1039 isc_buffer_setactive(source, r.length);
1040 result = getname(name, source, msg, dctx);
1041 if (result != ISC_R_SUCCESS)
1045 * Run through the section, looking to see if this name
1046 * is already there. If it is found, put back the allocated
1047 * name since we no longer need it, and set our name pointer
1048 * to point to the name we found.
1050 result = findname(&name2, name, section);
1053 * If it is the first name in the section, accept it.
1055 * If it is not, but is not the same as the name already
1056 * in the question section, append to the section. Note that
1057 * here in the question section this is illegal, so return
1058 * FORMERR. In the future, check the opcode to see if
1059 * this should be legal or not. In either case we no longer
1060 * need this name pointer.
1062 if (result != ISC_R_SUCCESS) {
1063 if (!ISC_LIST_EMPTY(*section))
1065 ISC_LIST_APPEND(*section, name, link);
1066 free_name = ISC_FALSE;
1068 isc_mempool_put(msg->namepool, name);
1071 free_name = ISC_FALSE;
1075 * Get type and class.
1077 isc_buffer_remainingregion(source, &r);
1079 result = ISC_R_UNEXPECTEDEND;
1082 rdtype = isc_buffer_getuint16(source);
1083 rdclass = isc_buffer_getuint16(source);
1086 * If this class is different than the one we already read,
1089 if (msg->state == DNS_SECTION_ANY) {
1090 msg->state = DNS_SECTION_QUESTION;
1091 msg->rdclass = rdclass;
1092 } else if (msg->rdclass != rdclass)
1096 * Can't ask the same question twice.
1098 result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1099 if (result == ISC_R_SUCCESS)
1103 * Allocate a new rdatalist.
1105 rdatalist = newrdatalist(msg);
1106 if (rdatalist == NULL) {
1107 result = ISC_R_NOMEMORY;
1110 rdataset = isc_mempool_get(msg->rdspool);
1111 if (rdataset == NULL) {
1112 result = ISC_R_NOMEMORY;
1117 * Convert rdatalist to rdataset, and attach the latter to
1120 rdatalist->type = rdtype;
1121 rdatalist->covers = 0;
1122 rdatalist->rdclass = rdclass;
1124 ISC_LIST_INIT(rdatalist->rdata);
1126 dns_rdataset_init(rdataset);
1127 result = dns_rdatalist_tordataset(rdatalist, rdataset);
1128 if (result != ISC_R_SUCCESS)
1131 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1133 ISC_LIST_APPEND(name->list, rdataset, link);
1138 return (DNS_R_RECOVERABLE);
1139 return (ISC_R_SUCCESS);
1142 if (rdataset != NULL) {
1143 INSIST(!dns_rdataset_isassociated(rdataset));
1144 isc_mempool_put(msg->rdspool, rdataset);
1147 if (rdatalist != NULL)
1148 isc_mempool_put(msg->rdlpool, rdatalist);
1151 isc_mempool_put(msg->namepool, name);
1156 static isc_boolean_t
1157 update(dns_section_t section, dns_rdataclass_t rdclass) {
1158 if (section == DNS_SECTION_PREREQUISITE)
1159 return (ISC_TF(rdclass == dns_rdataclass_any ||
1160 rdclass == dns_rdataclass_none));
1161 if (section == DNS_SECTION_UPDATE)
1162 return (ISC_TF(rdclass == dns_rdataclass_any));
1167 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1168 dns_section_t sectionid, unsigned int options)
1171 unsigned int count, rdatalen;
1174 dns_offsets_t *offsets;
1175 dns_rdataset_t *rdataset;
1176 dns_rdatalist_t *rdatalist;
1177 isc_result_t result;
1178 dns_rdatatype_t rdtype, covers;
1179 dns_rdataclass_t rdclass;
1182 dns_namelist_t *section;
1183 isc_boolean_t free_name, free_rdataset;
1184 isc_boolean_t preserve_order, best_effort, seen_problem;
1185 isc_boolean_t issigzero;
1187 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1188 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1189 seen_problem = ISC_FALSE;
1191 for (count = 0; count < msg->counts[sectionid]; count++) {
1192 int recstart = source->current;
1193 isc_boolean_t skip_name_search, skip_type_search;
1195 section = &msg->sections[sectionid];
1197 skip_name_search = ISC_FALSE;
1198 skip_type_search = ISC_FALSE;
1199 free_rdataset = ISC_FALSE;
1201 name = isc_mempool_get(msg->namepool);
1203 return (ISC_R_NOMEMORY);
1204 free_name = ISC_TRUE;
1206 offsets = newoffsets(msg);
1207 if (offsets == NULL) {
1208 result = ISC_R_NOMEMORY;
1211 dns_name_init(name, *offsets);
1214 * Parse the name out of this packet.
1216 isc_buffer_remainingregion(source, &r);
1217 isc_buffer_setactive(source, r.length);
1218 result = getname(name, source, msg, dctx);
1219 if (result != ISC_R_SUCCESS)
1223 * Get type, class, ttl, and rdatalen. Verify that at least
1224 * rdatalen bytes remain. (Some of this is deferred to
1227 isc_buffer_remainingregion(source, &r);
1228 if (r.length < 2 + 2 + 4 + 2) {
1229 result = ISC_R_UNEXPECTEDEND;
1232 rdtype = isc_buffer_getuint16(source);
1233 rdclass = isc_buffer_getuint16(source);
1236 * If there was no question section, we may not yet have
1237 * established a class. Do so now.
1239 if (msg->state == DNS_SECTION_ANY &&
1240 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
1241 rdtype != dns_rdatatype_tsig && /* class is ANY */
1242 rdtype != dns_rdatatype_tkey) { /* class is undefined */
1243 msg->rdclass = rdclass;
1244 msg->state = DNS_SECTION_QUESTION;
1248 * If this class is different than the one in the question
1251 if (msg->opcode != dns_opcode_update
1252 && rdtype != dns_rdatatype_tsig
1253 && rdtype != dns_rdatatype_opt
1254 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
1255 && rdtype != dns_rdatatype_sig /* SIG(0) */
1256 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1257 && msg->rdclass != dns_rdataclass_any
1258 && msg->rdclass != rdclass)
1262 * Special type handling for TSIG, OPT, and TKEY.
1264 if (rdtype == dns_rdatatype_tsig) {
1266 * If it is a tsig, verify that it is in the
1267 * additional data section.
1269 if (sectionid != DNS_SECTION_ADDITIONAL ||
1270 rdclass != dns_rdataclass_any ||
1271 count != msg->counts[sectionid] - 1)
1273 msg->sigstart = recstart;
1274 skip_name_search = ISC_TRUE;
1275 skip_type_search = ISC_TRUE;
1276 } else if (rdtype == dns_rdatatype_opt) {
1278 * The name of an OPT record must be ".", it
1279 * must be in the additional data section, and
1280 * it must be the first OPT we've seen.
1282 if (!dns_name_equal(dns_rootname, name) ||
1285 skip_name_search = ISC_TRUE;
1286 skip_type_search = ISC_TRUE;
1287 } else if (rdtype == dns_rdatatype_tkey) {
1289 * A TKEY must be in the additional section if this
1290 * is a query, and the answer section if this is a
1291 * response. Unless it's a Win2000 client.
1293 * Its class is ignored.
1295 dns_section_t tkeysection;
1297 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1298 tkeysection = DNS_SECTION_ADDITIONAL;
1300 tkeysection = DNS_SECTION_ANSWER;
1301 if (sectionid != tkeysection &&
1302 sectionid != DNS_SECTION_ANSWER)
1307 * ... now get ttl and rdatalen, and check buffer.
1309 ttl = isc_buffer_getuint32(source);
1310 rdatalen = isc_buffer_getuint16(source);
1311 r.length -= (2 + 2 + 4 + 2);
1312 if (r.length < rdatalen) {
1313 result = ISC_R_UNEXPECTEDEND;
1318 * Read the rdata from the wire format. Interpret the
1319 * rdata according to its actual class, even if it had a
1320 * DynDNS meta-class in the packet (unless this is a TSIG).
1321 * Then put the meta-class back into the finished rdata.
1323 rdata = newrdata(msg);
1324 if (rdata == NULL) {
1325 result = ISC_R_NOMEMORY;
1328 if (msg->opcode == dns_opcode_update &&
1329 update(sectionid, rdclass)) {
1330 if (rdatalen != 0) {
1331 result = DNS_R_FORMERR;
1335 * When the rdata is empty, the data pointer is
1336 * never dereferenced, but it must still be non-NULL.
1337 * Casting 1 rather than "" avoids warnings about
1338 * discarding the const attribute of a string,
1339 * for compilers that would warn about such things.
1341 rdata->data = (unsigned char *)1;
1343 rdata->rdclass = rdclass;
1344 rdata->type = rdtype;
1345 rdata->flags = DNS_RDATA_UPDATE;
1346 result = ISC_R_SUCCESS;
1347 } else if (rdclass == dns_rdataclass_none &&
1348 msg->opcode == dns_opcode_update &&
1349 sectionid == DNS_SECTION_UPDATE) {
1350 result = getrdata(source, msg, dctx, msg->rdclass,
1351 rdtype, rdatalen, rdata);
1353 result = getrdata(source, msg, dctx, rdclass,
1354 rdtype, rdatalen, rdata);
1355 if (result != ISC_R_SUCCESS)
1357 rdata->rdclass = rdclass;
1358 issigzero = ISC_FALSE;
1359 if (rdtype == dns_rdatatype_rrsig &&
1360 rdata->flags == 0) {
1361 covers = dns_rdata_covers(rdata);
1364 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
1365 rdata->flags == 0) {
1366 covers = dns_rdata_covers(rdata);
1368 if (sectionid != DNS_SECTION_ADDITIONAL ||
1369 count != msg->counts[sectionid] - 1)
1371 msg->sigstart = recstart;
1372 skip_name_search = ISC_TRUE;
1373 skip_type_search = ISC_TRUE;
1374 issigzero = ISC_TRUE;
1380 * Check the ownername of NSEC3 records
1382 if (rdtype == dns_rdatatype_nsec3 &&
1383 !dns_rdata_checkowner(name, msg->rdclass, rdtype,
1385 result = DNS_R_BADOWNERNAME;
1390 * If we are doing a dynamic update or this is a meta-type,
1391 * don't bother searching for a name, just append this one
1392 * to the end of the message.
1394 if (preserve_order || msg->opcode == dns_opcode_update ||
1396 if (rdtype != dns_rdatatype_opt &&
1397 rdtype != dns_rdatatype_tsig &&
1400 ISC_LIST_APPEND(*section, name, link);
1401 free_name = ISC_FALSE;
1405 * Run through the section, looking to see if this name
1406 * is already there. If it is found, put back the
1407 * allocated name since we no longer need it, and set
1408 * our name pointer to point to the name we found.
1410 result = findname(&name2, name, section);
1413 * If it is a new name, append to the section.
1415 if (result == ISC_R_SUCCESS) {
1416 isc_mempool_put(msg->namepool, name);
1419 ISC_LIST_APPEND(*section, name, link);
1421 free_name = ISC_FALSE;
1425 * Search name for the particular type and class.
1426 * Skip this stage if in update mode or this is a meta-type.
1428 if (preserve_order || msg->opcode == dns_opcode_update ||
1430 result = ISC_R_NOTFOUND;
1433 * If this is a type that can only occur in
1434 * the question section, fail.
1436 if (dns_rdatatype_questiononly(rdtype))
1440 result = dns_message_find(name, rdclass, rdtype,
1445 * If we found an rdataset that matches, we need to
1446 * append this rdata to that set. If we did not, we need
1447 * to create a new rdatalist, store the important bits there,
1448 * convert it to an rdataset, and link the latter to the name.
1449 * Yuck. When appending, make certain that the type isn't
1450 * a singleton type, such as SOA or CNAME.
1452 * Note that this check will be bypassed when preserving order,
1453 * the opcode is an update, or the type search is skipped.
1455 if (result == ISC_R_SUCCESS) {
1456 if (dns_rdatatype_issingleton(rdtype)) {
1458 dns_rdatalist_fromrdataset(rdataset,
1460 first = ISC_LIST_HEAD(rdatalist->rdata);
1461 INSIST(first != NULL);
1462 if (dns_rdata_compare(rdata, first) != 0)
1467 if (result == ISC_R_NOTFOUND) {
1468 rdataset = isc_mempool_get(msg->rdspool);
1469 if (rdataset == NULL) {
1470 result = ISC_R_NOMEMORY;
1473 free_rdataset = ISC_TRUE;
1475 rdatalist = newrdatalist(msg);
1476 if (rdatalist == NULL) {
1477 result = ISC_R_NOMEMORY;
1481 rdatalist->type = rdtype;
1482 rdatalist->covers = covers;
1483 rdatalist->rdclass = rdclass;
1484 rdatalist->ttl = ttl;
1485 ISC_LIST_INIT(rdatalist->rdata);
1487 dns_rdataset_init(rdataset);
1488 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
1492 if (rdtype != dns_rdatatype_opt &&
1493 rdtype != dns_rdatatype_tsig &&
1496 ISC_LIST_APPEND(name->list, rdataset, link);
1497 free_rdataset = ISC_FALSE;
1504 * Section 5.2 of RFC2181 says we should drop
1505 * nonauthoritative rrsets where the TTLs differ, but we
1506 * currently treat them the as if they were authoritative and
1509 if (ttl != rdataset->ttl) {
1510 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1511 if (ttl < rdataset->ttl)
1512 rdataset->ttl = ttl;
1515 /* Append this rdata to the rdataset. */
1516 dns_rdatalist_fromrdataset(rdataset, &rdatalist);
1517 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1520 * If this is an OPT record, remember it. Also, set
1521 * the extended rcode. Note that msg->opt will only be set
1522 * if best-effort parsing is enabled.
1524 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1527 msg->opt = rdataset;
1529 free_rdataset = ISC_FALSE;
1530 ercode = (dns_rcode_t)
1531 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1533 msg->rcode |= ercode;
1534 isc_mempool_put(msg->namepool, name);
1535 free_name = ISC_FALSE;
1539 * If this is an SIG(0) or TSIG record, remember it. Note
1540 * that msg->sig0 or msg->tsig will only be set if best-effort
1541 * parsing is enabled.
1543 if (issigzero && msg->sig0 == NULL) {
1544 msg->sig0 = rdataset;
1545 msg->sig0name = name;
1547 free_rdataset = ISC_FALSE;
1548 free_name = ISC_FALSE;
1549 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1550 msg->tsig = rdataset;
1551 msg->tsigname = name;
1552 /* Windows doesn't like TSIG names to be compressed. */
1553 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1555 free_rdataset = ISC_FALSE;
1556 free_name = ISC_FALSE;
1561 isc_mempool_put(msg->namepool, name);
1563 isc_mempool_put(msg->rdspool, rdataset);
1564 free_name = free_rdataset = ISC_FALSE;
1566 INSIST(free_name == ISC_FALSE);
1567 INSIST(free_rdataset == ISC_FALSE);
1571 return (DNS_R_RECOVERABLE);
1572 return (ISC_R_SUCCESS);
1576 isc_mempool_put(msg->namepool, name);
1578 isc_mempool_put(msg->rdspool, rdataset);
1584 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1585 unsigned int options)
1588 dns_decompress_t dctx;
1590 isc_uint16_t tmpflags;
1591 isc_buffer_t origsource;
1592 isc_boolean_t seen_problem;
1593 isc_boolean_t ignore_tc;
1595 REQUIRE(DNS_MESSAGE_VALID(msg));
1596 REQUIRE(source != NULL);
1597 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1599 seen_problem = ISC_FALSE;
1600 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1602 origsource = *source;
1605 msg->question_ok = 0;
1607 isc_buffer_remainingregion(source, &r);
1608 if (r.length < DNS_MESSAGE_HEADERLEN)
1609 return (ISC_R_UNEXPECTEDEND);
1611 msg->id = isc_buffer_getuint16(source);
1612 tmpflags = isc_buffer_getuint16(source);
1613 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1614 >> DNS_MESSAGE_OPCODE_SHIFT);
1615 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1616 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1617 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1618 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1619 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1620 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1627 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1629 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1631 ret = getquestions(source, msg, &dctx, options);
1632 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1634 if (ret == DNS_R_RECOVERABLE) {
1635 seen_problem = ISC_TRUE;
1636 ret = ISC_R_SUCCESS;
1638 if (ret != ISC_R_SUCCESS)
1640 msg->question_ok = 1;
1642 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1643 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1645 if (ret == DNS_R_RECOVERABLE) {
1646 seen_problem = ISC_TRUE;
1647 ret = ISC_R_SUCCESS;
1649 if (ret != ISC_R_SUCCESS)
1652 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1653 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1655 if (ret == DNS_R_RECOVERABLE) {
1656 seen_problem = ISC_TRUE;
1657 ret = ISC_R_SUCCESS;
1659 if (ret != ISC_R_SUCCESS)
1662 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1663 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1665 if (ret == DNS_R_RECOVERABLE) {
1666 seen_problem = ISC_TRUE;
1667 ret = ISC_R_SUCCESS;
1669 if (ret != ISC_R_SUCCESS)
1672 isc_buffer_remainingregion(source, &r);
1673 if (r.length != 0) {
1674 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1675 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
1676 "message has %u byte(s) of trailing garbage",
1681 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1682 isc_buffer_usedregion(&origsource, &msg->saved);
1684 msg->saved.length = isc_buffer_usedlength(&origsource);
1685 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1686 if (msg->saved.base == NULL)
1687 return (ISC_R_NOMEMORY);
1688 memmove(msg->saved.base, isc_buffer_base(&origsource),
1690 msg->free_saved = 1;
1693 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1694 return (DNS_R_RECOVERABLE);
1695 if (seen_problem == ISC_TRUE)
1696 return (DNS_R_RECOVERABLE);
1697 return (ISC_R_SUCCESS);
1701 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1702 isc_buffer_t *buffer)
1706 REQUIRE(DNS_MESSAGE_VALID(msg));
1707 REQUIRE(buffer != NULL);
1708 REQUIRE(msg->buffer == NULL);
1709 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1714 * Erase the contents of this buffer.
1716 isc_buffer_clear(buffer);
1719 * Make certain there is enough for at least the header in this
1722 isc_buffer_availableregion(buffer, &r);
1723 if (r.length < DNS_MESSAGE_HEADERLEN)
1724 return (ISC_R_NOSPACE);
1726 if (r.length < msg->reserved)
1727 return (ISC_R_NOSPACE);
1730 * Reserve enough space for the header in this buffer.
1732 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1734 msg->buffer = buffer;
1736 return (ISC_R_SUCCESS);
1740 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1743 REQUIRE(DNS_MESSAGE_VALID(msg));
1744 REQUIRE(buffer != NULL);
1745 REQUIRE(msg->buffer != NULL);
1748 * Ensure that the new buffer is empty, and has enough space to
1749 * hold the current contents.
1751 isc_buffer_clear(buffer);
1753 isc_buffer_availableregion(buffer, &rn);
1754 isc_buffer_usedregion(msg->buffer, &r);
1755 REQUIRE(rn.length > r.length);
1758 * Copy the contents from the old to the new buffer.
1760 isc_buffer_add(buffer, r.length);
1761 memmove(rn.base, r.base, r.length);
1763 msg->buffer = buffer;
1765 return (ISC_R_SUCCESS);
1769 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1770 REQUIRE(DNS_MESSAGE_VALID(msg));
1771 REQUIRE(space <= msg->reserved);
1773 msg->reserved -= space;
1777 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1780 REQUIRE(DNS_MESSAGE_VALID(msg));
1782 if (msg->buffer != NULL) {
1783 isc_buffer_availableregion(msg->buffer, &r);
1784 if (r.length < (space + msg->reserved))
1785 return (ISC_R_NOSPACE);
1788 msg->reserved += space;
1790 return (ISC_R_SUCCESS);
1793 static inline isc_boolean_t
1794 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
1798 * If we are not rendering class IN, this ordering is bogus.
1800 if (rds->rdclass != dns_rdataclass_in)
1803 switch (rds->type) {
1804 case dns_rdatatype_a:
1805 case dns_rdatatype_aaaa:
1806 if (preferred_glue == rds->type)
1811 case dns_rdatatype_rrsig:
1812 case dns_rdatatype_dnskey:
1819 if (pass_needed >= pass)
1825 #ifdef ALLOW_FILTER_AAAA_ON_V4
1827 * Decide whether to not answer with an AAAA record and its RRSIG
1829 static inline isc_boolean_t
1830 norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
1832 switch (rdataset->type) {
1833 case dns_rdatatype_aaaa:
1834 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
1838 case dns_rdatatype_rrsig:
1839 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
1840 rdataset->covers != dns_rdatatype_aaaa)
1848 if (rdataset->rdclass != dns_rdataclass_in)
1856 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1857 unsigned int options)
1859 dns_namelist_t *section;
1860 dns_name_t *name, *next_name;
1861 dns_rdataset_t *rdataset, *next_rdataset;
1862 unsigned int count, total;
1863 isc_result_t result;
1864 isc_buffer_t st; /* for rollbacks */
1866 isc_boolean_t partial = ISC_FALSE;
1867 unsigned int rd_options;
1868 dns_rdatatype_t preferred_glue = 0;
1870 REQUIRE(DNS_MESSAGE_VALID(msg));
1871 REQUIRE(msg->buffer != NULL);
1872 REQUIRE(VALID_NAMED_SECTION(sectionid));
1874 section = &msg->sections[sectionid];
1876 if ((sectionid == DNS_SECTION_ADDITIONAL)
1877 && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
1878 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
1879 preferred_glue = dns_rdatatype_a;
1881 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
1882 preferred_glue = dns_rdatatype_aaaa;
1889 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
1892 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
1895 * Shrink the space in the buffer by the reserved amount.
1897 msg->buffer->length -= msg->reserved;
1900 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1904 * Render required glue first. Set TC if it won't fit.
1906 name = ISC_LIST_HEAD(*section);
1908 rdataset = ISC_LIST_HEAD(name->list);
1909 if (rdataset != NULL &&
1910 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
1911 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
1912 const void *order_arg = msg->order_arg;
1913 st = *(msg->buffer);
1916 result = dns_rdataset_towirepartial(rdataset,
1926 result = dns_rdataset_towiresorted(rdataset,
1935 if (partial && result == ISC_R_NOSPACE) {
1936 msg->flags |= DNS_MESSAGEFLAG_TC;
1937 msg->buffer->length += msg->reserved;
1938 msg->counts[sectionid] += total;
1941 if (result == ISC_R_NOSPACE)
1942 msg->flags |= DNS_MESSAGEFLAG_TC;
1943 if (result != ISC_R_SUCCESS) {
1944 INSIST(st.used < 65536);
1945 dns_compress_rollback(msg->cctx,
1946 (isc_uint16_t)st.used);
1947 *(msg->buffer) = st; /* rollback */
1948 msg->buffer->length += msg->reserved;
1949 msg->counts[sectionid] += total;
1952 rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
1957 name = ISC_LIST_HEAD(*section);
1959 msg->buffer->length += msg->reserved;
1960 msg->counts[sectionid] += total;
1961 return (ISC_R_SUCCESS);
1964 while (name != NULL) {
1965 next_name = ISC_LIST_NEXT(name, link);
1967 rdataset = ISC_LIST_HEAD(name->list);
1968 while (rdataset != NULL) {
1969 next_rdataset = ISC_LIST_NEXT(rdataset, link);
1971 if ((rdataset->attributes &
1972 DNS_RDATASETATTR_RENDERED) != 0)
1975 if (((options & DNS_MESSAGERENDER_ORDERED)
1977 && (sectionid == DNS_SECTION_ADDITIONAL)
1978 && wrong_priority(rdataset, pass,
1982 #ifdef ALLOW_FILTER_AAAA_ON_V4
1984 * Suppress AAAAs if asked and we are
1985 * not doing DNSSEC or are breaking DNSSEC.
1986 * Say so in the AD bit if we break DNSSEC.
1988 if (norender_rdataset(rdataset, options) &&
1989 sectionid != DNS_SECTION_QUESTION) {
1990 if (sectionid == DNS_SECTION_ANSWER ||
1991 sectionid == DNS_SECTION_AUTHORITY)
1992 msg->flags &= ~DNS_MESSAGEFLAG_AD;
1993 if (OPTOUT(rdataset))
1994 msg->flags &= ~DNS_MESSAGEFLAG_AD;
1999 st = *(msg->buffer);
2003 result = dns_rdataset_towirepartial(
2014 result = dns_rdataset_towiresorted(
2027 * If out of space, record stats on what we
2028 * rendered so far, and return that status.
2030 * XXXMLG Need to change this when
2031 * dns_rdataset_towire() can render partial
2032 * sets starting at some arbitrary point in the
2033 * set. This will include setting a bit in the
2034 * rdataset to indicate that a partial
2035 * rendering was done, and some state saved
2036 * somewhere (probably in the message struct)
2037 * to indicate where to continue from.
2039 if (partial && result == ISC_R_NOSPACE) {
2040 msg->buffer->length += msg->reserved;
2041 msg->counts[sectionid] += total;
2044 if (result != ISC_R_SUCCESS) {
2045 INSIST(st.used < 65536);
2046 dns_compress_rollback(msg->cctx,
2047 (isc_uint16_t)st.used);
2048 *(msg->buffer) = st; /* rollback */
2049 msg->buffer->length += msg->reserved;
2050 msg->counts[sectionid] += total;
2055 * If we have rendered non-validated data,
2056 * ensure that the AD bit is not set.
2058 if (rdataset->trust != dns_trust_secure &&
2059 (sectionid == DNS_SECTION_ANSWER ||
2060 sectionid == DNS_SECTION_AUTHORITY))
2061 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2062 if (OPTOUT(rdataset))
2063 msg->flags &= ~DNS_MESSAGEFLAG_AD;
2065 rdataset->attributes |=
2066 DNS_RDATASETATTR_RENDERED;
2069 rdataset = next_rdataset;
2074 } while (--pass != 0);
2076 msg->buffer->length += msg->reserved;
2077 msg->counts[sectionid] += total;
2079 return (ISC_R_SUCCESS);
2083 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
2087 REQUIRE(DNS_MESSAGE_VALID(msg));
2088 REQUIRE(target != NULL);
2090 isc_buffer_availableregion(target, &r);
2091 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
2093 isc_buffer_putuint16(target, msg->id);
2095 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
2096 & DNS_MESSAGE_OPCODE_MASK);
2097 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
2098 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
2100 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
2101 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
2102 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
2103 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
2105 isc_buffer_putuint16(target, tmp);
2106 isc_buffer_putuint16(target,
2107 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
2108 isc_buffer_putuint16(target,
2109 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
2110 isc_buffer_putuint16(target,
2111 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2112 isc_buffer_putuint16(target,
2113 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
2117 dns_message_renderend(dns_message_t *msg) {
2118 isc_buffer_t tmpbuf;
2123 REQUIRE(DNS_MESSAGE_VALID(msg));
2124 REQUIRE(msg->buffer != NULL);
2126 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
2128 * We have an extended rcode but are not using EDNS.
2130 return (DNS_R_FORMERR);
2134 * If we're adding a OPT, TSIG or SIG(0) to a truncated message,
2135 * clear all rdatasets from the message except for the question
2136 * before adding the OPT, TSIG or SIG(0). If the question doesn't
2137 * fit, don't include it.
2139 if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) &&
2140 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2144 msgresetnames(msg, DNS_SECTION_ANSWER);
2146 dns_message_renderreset(msg);
2148 isc_buffer_clear(msg->buffer);
2149 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
2150 dns_compress_rollback(msg->cctx, 0);
2151 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
2153 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
2158 * If we've got an OPT record, render it.
2160 if (msg->opt != NULL) {
2161 dns_message_renderrelease(msg, msg->opt_reserved);
2162 msg->opt_reserved = 0;
2164 * Set the extended rcode.
2166 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
2167 msg->opt->ttl |= ((msg->rcode << 20) &
2168 DNS_MESSAGE_EDNSRCODE_MASK);
2173 result = dns_rdataset_towire(msg->opt, dns_rootname,
2174 msg->cctx, msg->buffer, 0,
2176 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2177 if (result != ISC_R_SUCCESS)
2182 * If we're adding a TSIG record, generate and render it.
2184 if (msg->tsigkey != NULL) {
2185 dns_message_renderrelease(msg, msg->sig_reserved);
2186 msg->sig_reserved = 0;
2187 result = dns_tsig_sign(msg);
2188 if (result != ISC_R_SUCCESS)
2191 result = dns_rdataset_towire(msg->tsig, msg->tsigname,
2192 msg->cctx, msg->buffer, 0,
2194 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2195 if (result != ISC_R_SUCCESS)
2200 * If we're adding a SIG(0) record, generate and render it.
2202 if (msg->sig0key != NULL) {
2203 dns_message_renderrelease(msg, msg->sig_reserved);
2204 msg->sig_reserved = 0;
2205 result = dns_dnssec_signmessage(msg, msg->sig0key);
2206 if (result != ISC_R_SUCCESS)
2210 * Note: dns_rootname is used here, not msg->sig0name, since
2211 * the owner name of a SIG(0) is irrelevant, and will not
2212 * be set in a message being rendered.
2214 result = dns_rdataset_towire(msg->sig0, dns_rootname,
2215 msg->cctx, msg->buffer, 0,
2217 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2218 if (result != ISC_R_SUCCESS)
2222 isc_buffer_usedregion(msg->buffer, &r);
2223 isc_buffer_init(&tmpbuf, r.base, r.length);
2225 dns_message_renderheader(msg, &tmpbuf);
2227 msg->buffer = NULL; /* forget about this buffer only on success XXX */
2229 return (ISC_R_SUCCESS);
2233 dns_message_renderreset(dns_message_t *msg) {
2236 dns_rdataset_t *rds;
2239 * Reset the message so that it may be rendered again.
2242 REQUIRE(DNS_MESSAGE_VALID(msg));
2243 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2247 for (i = 0; i < DNS_SECTION_MAX; i++) {
2248 msg->cursors[i] = NULL;
2250 for (name = ISC_LIST_HEAD(msg->sections[i]);
2252 name = ISC_LIST_NEXT(name, link)) {
2253 for (rds = ISC_LIST_HEAD(name->list);
2255 rds = ISC_LIST_NEXT(rds, link)) {
2256 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2260 if (msg->tsigname != NULL)
2261 dns_message_puttempname(msg, &msg->tsigname);
2262 if (msg->tsig != NULL) {
2263 dns_rdataset_disassociate(msg->tsig);
2264 dns_message_puttemprdataset(msg, &msg->tsig);
2266 if (msg->sig0 != NULL) {
2267 dns_rdataset_disassociate(msg->sig0);
2268 dns_message_puttemprdataset(msg, &msg->sig0);
2273 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2274 REQUIRE(DNS_MESSAGE_VALID(msg));
2275 REQUIRE(VALID_NAMED_SECTION(section));
2277 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2279 if (msg->cursors[section] == NULL)
2280 return (ISC_R_NOMORE);
2282 return (ISC_R_SUCCESS);
2286 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2287 REQUIRE(DNS_MESSAGE_VALID(msg));
2288 REQUIRE(VALID_NAMED_SECTION(section));
2289 REQUIRE(msg->cursors[section] != NULL);
2291 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2293 if (msg->cursors[section] == NULL)
2294 return (ISC_R_NOMORE);
2296 return (ISC_R_SUCCESS);
2300 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2303 REQUIRE(DNS_MESSAGE_VALID(msg));
2304 REQUIRE(VALID_NAMED_SECTION(section));
2305 REQUIRE(name != NULL && *name == NULL);
2306 REQUIRE(msg->cursors[section] != NULL);
2308 *name = msg->cursors[section];
2312 dns_message_findname(dns_message_t *msg, dns_section_t section,
2313 dns_name_t *target, dns_rdatatype_t type,
2314 dns_rdatatype_t covers, dns_name_t **name,
2315 dns_rdataset_t **rdataset)
2317 dns_name_t *foundname;
2318 isc_result_t result;
2321 * XXX These requirements are probably too intensive, especially
2322 * where things can be NULL, but as they are they ensure that if
2323 * something is NON-NULL, indicating that the caller expects it
2324 * to be filled in, that we can in fact fill it in.
2326 REQUIRE(msg != NULL);
2327 REQUIRE(VALID_SECTION(section));
2328 REQUIRE(target != NULL);
2330 REQUIRE(*name == NULL);
2331 if (type == dns_rdatatype_any) {
2332 REQUIRE(rdataset == NULL);
2334 if (rdataset != NULL)
2335 REQUIRE(*rdataset == NULL);
2338 result = findname(&foundname, target,
2339 &msg->sections[section]);
2341 if (result == ISC_R_NOTFOUND)
2342 return (DNS_R_NXDOMAIN);
2343 else if (result != ISC_R_SUCCESS)
2350 * And now look for the type.
2352 if (type == dns_rdatatype_any)
2353 return (ISC_R_SUCCESS);
2355 result = dns_message_findtype(foundname, type, covers, rdataset);
2356 if (result == ISC_R_NOTFOUND)
2357 return (DNS_R_NXRRSET);
2363 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2364 dns_section_t fromsection,
2365 dns_section_t tosection)
2367 REQUIRE(msg != NULL);
2368 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2369 REQUIRE(name != NULL);
2370 REQUIRE(VALID_NAMED_SECTION(fromsection));
2371 REQUIRE(VALID_NAMED_SECTION(tosection));
2374 * Unlink the name from the old section
2376 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2377 ISC_LIST_APPEND(msg->sections[tosection], name, link);
2381 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2382 dns_section_t section)
2384 REQUIRE(msg != NULL);
2385 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2386 REQUIRE(name != NULL);
2387 REQUIRE(VALID_NAMED_SECTION(section));
2389 ISC_LIST_APPEND(msg->sections[section], name, link);
2393 dns_message_removename(dns_message_t *msg, dns_name_t *name,
2394 dns_section_t section)
2396 REQUIRE(msg != NULL);
2397 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2398 REQUIRE(name != NULL);
2399 REQUIRE(VALID_NAMED_SECTION(section));
2401 ISC_LIST_UNLINK(msg->sections[section], name, link);
2405 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2406 REQUIRE(DNS_MESSAGE_VALID(msg));
2407 REQUIRE(item != NULL && *item == NULL);
2409 *item = isc_mempool_get(msg->namepool);
2411 return (ISC_R_NOMEMORY);
2412 dns_name_init(*item, NULL);
2414 return (ISC_R_SUCCESS);
2418 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2419 REQUIRE(DNS_MESSAGE_VALID(msg));
2420 REQUIRE(item != NULL && *item == NULL);
2422 *item = newoffsets(msg);
2424 return (ISC_R_NOMEMORY);
2426 return (ISC_R_SUCCESS);
2430 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2431 REQUIRE(DNS_MESSAGE_VALID(msg));
2432 REQUIRE(item != NULL && *item == NULL);
2434 *item = newrdata(msg);
2436 return (ISC_R_NOMEMORY);
2438 return (ISC_R_SUCCESS);
2442 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2443 REQUIRE(DNS_MESSAGE_VALID(msg));
2444 REQUIRE(item != NULL && *item == NULL);
2446 *item = isc_mempool_get(msg->rdspool);
2448 return (ISC_R_NOMEMORY);
2450 dns_rdataset_init(*item);
2452 return (ISC_R_SUCCESS);
2456 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2457 REQUIRE(DNS_MESSAGE_VALID(msg));
2458 REQUIRE(item != NULL && *item == NULL);
2460 *item = newrdatalist(msg);
2462 return (ISC_R_NOMEMORY);
2464 return (ISC_R_SUCCESS);
2468 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2469 REQUIRE(DNS_MESSAGE_VALID(msg));
2470 REQUIRE(item != NULL && *item != NULL);
2472 if (dns_name_dynamic(*item))
2473 dns_name_free(*item, msg->mctx);
2474 isc_mempool_put(msg->namepool, *item);
2479 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2480 REQUIRE(DNS_MESSAGE_VALID(msg));
2481 REQUIRE(item != NULL && *item != NULL);
2483 releaserdata(msg, *item);
2488 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2489 REQUIRE(DNS_MESSAGE_VALID(msg));
2490 REQUIRE(item != NULL && *item != NULL);
2492 REQUIRE(!dns_rdataset_isassociated(*item));
2493 isc_mempool_put(msg->rdspool, *item);
2498 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2499 REQUIRE(DNS_MESSAGE_VALID(msg));
2500 REQUIRE(item != NULL && *item != NULL);
2502 releaserdatalist(msg, *item);
2507 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2508 unsigned int *flagsp)
2511 isc_buffer_t buffer;
2515 REQUIRE(source != NULL);
2519 isc_buffer_remainingregion(&buffer, &r);
2520 if (r.length < DNS_MESSAGE_HEADERLEN)
2521 return (ISC_R_UNEXPECTEDEND);
2523 id = isc_buffer_getuint16(&buffer);
2524 flags = isc_buffer_getuint16(&buffer);
2525 flags &= DNS_MESSAGE_FLAG_MASK;
2532 return (ISC_R_SUCCESS);
2536 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2537 unsigned int clear_after;
2538 isc_result_t result;
2540 REQUIRE(DNS_MESSAGE_VALID(msg));
2541 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2543 if (!msg->header_ok)
2544 return (DNS_R_FORMERR);
2545 if (msg->opcode != dns_opcode_query &&
2546 msg->opcode != dns_opcode_notify)
2547 want_question_section = ISC_FALSE;
2548 if (msg->opcode == dns_opcode_update)
2549 clear_after = DNS_SECTION_PREREQUISITE;
2550 else if (want_question_section) {
2551 if (!msg->question_ok)
2552 return (DNS_R_FORMERR);
2553 clear_after = DNS_SECTION_ANSWER;
2555 clear_after = DNS_SECTION_QUESTION;
2556 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2557 msgresetnames(msg, clear_after);
2559 msgresetsigs(msg, ISC_TRUE);
2560 msginitprivate(msg);
2562 * We now clear most flags and then set QR, ensuring that the
2563 * reply's flags will be in a reasonable state.
2565 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2566 msg->flags |= DNS_MESSAGEFLAG_QR;
2569 * This saves the query TSIG status, if the query was signed, and
2570 * reserves space in the reply for the TSIG.
2572 if (msg->tsigkey != NULL) {
2573 unsigned int otherlen = 0;
2574 msg->querytsigstatus = msg->tsigstatus;
2575 msg->tsigstatus = dns_rcode_noerror;
2576 if (msg->querytsigstatus == dns_tsigerror_badtime)
2578 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2579 result = dns_message_renderreserve(msg, msg->sig_reserved);
2580 if (result != ISC_R_SUCCESS) {
2581 msg->sig_reserved = 0;
2585 if (msg->saved.base != NULL) {
2586 msg->query.base = msg->saved.base;
2587 msg->query.length = msg->saved.length;
2588 msg->free_query = msg->free_saved;
2589 msg->saved.base = NULL;
2590 msg->saved.length = 0;
2591 msg->free_saved = 0;
2594 return (ISC_R_SUCCESS);
2598 dns_message_getopt(dns_message_t *msg) {
2601 * Get the OPT record for 'msg'.
2604 REQUIRE(DNS_MESSAGE_VALID(msg));
2610 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2611 isc_result_t result;
2612 dns_rdata_t rdata = DNS_RDATA_INIT;
2615 * Set the OPT record for 'msg'.
2619 * The space required for an OPT record is:
2621 * 1 byte for the name
2622 * 2 bytes for the type
2623 * 2 bytes for the class
2624 * 4 bytes for the ttl
2625 * 2 bytes for the rdata length
2626 * ---------------------------------
2629 * plus the length of the rdata.
2632 REQUIRE(DNS_MESSAGE_VALID(msg));
2633 REQUIRE(opt->type == dns_rdatatype_opt);
2634 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2635 REQUIRE(msg->state == DNS_SECTION_ANY);
2639 result = dns_rdataset_first(opt);
2640 if (result != ISC_R_SUCCESS)
2642 dns_rdataset_current(opt, &rdata);
2643 msg->opt_reserved = 11 + rdata.length;
2644 result = dns_message_renderreserve(msg, msg->opt_reserved);
2645 if (result != ISC_R_SUCCESS) {
2646 msg->opt_reserved = 0;
2652 return (ISC_R_SUCCESS);
2655 dns_rdataset_disassociate(opt);
2656 dns_message_puttemprdataset(msg, &opt);
2661 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2664 * Get the TSIG record and owner for 'msg'.
2667 REQUIRE(DNS_MESSAGE_VALID(msg));
2668 REQUIRE(owner == NULL || *owner == NULL);
2671 *owner = msg->tsigname;
2676 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2677 isc_result_t result;
2680 * Set the TSIG key for 'msg'
2683 REQUIRE(DNS_MESSAGE_VALID(msg));
2684 REQUIRE(msg->state == DNS_SECTION_ANY);
2686 if (key == NULL && msg->tsigkey != NULL) {
2687 if (msg->sig_reserved != 0) {
2688 dns_message_renderrelease(msg, msg->sig_reserved);
2689 msg->sig_reserved = 0;
2691 dns_tsigkey_detach(&msg->tsigkey);
2694 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
2695 dns_tsigkey_attach(key, &msg->tsigkey);
2696 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2697 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2698 result = dns_message_renderreserve(msg,
2700 if (result != ISC_R_SUCCESS) {
2701 dns_tsigkey_detach(&msg->tsigkey);
2702 msg->sig_reserved = 0;
2707 return (ISC_R_SUCCESS);
2711 dns_message_gettsigkey(dns_message_t *msg) {
2714 * Get the TSIG key for 'msg'
2717 REQUIRE(DNS_MESSAGE_VALID(msg));
2719 return (msg->tsigkey);
2723 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2724 dns_rdata_t *rdata = NULL;
2725 dns_rdatalist_t *list = NULL;
2726 dns_rdataset_t *set = NULL;
2727 isc_buffer_t *buf = NULL;
2729 isc_result_t result;
2731 REQUIRE(DNS_MESSAGE_VALID(msg));
2732 REQUIRE(msg->querytsig == NULL);
2734 if (querytsig == NULL)
2735 return (ISC_R_SUCCESS);
2737 result = dns_message_gettemprdata(msg, &rdata);
2738 if (result != ISC_R_SUCCESS)
2741 result = dns_message_gettemprdatalist(msg, &list);
2742 if (result != ISC_R_SUCCESS)
2744 result = dns_message_gettemprdataset(msg, &set);
2745 if (result != ISC_R_SUCCESS)
2748 isc_buffer_usedregion(querytsig, &r);
2749 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2750 if (result != ISC_R_SUCCESS)
2752 isc_buffer_putmem(buf, r.base, r.length);
2753 isc_buffer_usedregion(buf, &r);
2754 dns_rdata_init(rdata);
2755 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2756 dns_message_takebuffer(msg, &buf);
2757 ISC_LIST_INIT(list->rdata);
2758 ISC_LIST_APPEND(list->rdata, rdata, link);
2759 result = dns_rdatalist_tordataset(list, set);
2760 if (result != ISC_R_SUCCESS)
2763 msg->querytsig = set;
2769 dns_message_puttemprdata(msg, &rdata);
2771 dns_message_puttemprdatalist(msg, &list);
2773 dns_message_puttemprdataset(msg, &set);
2774 return (ISC_R_NOMEMORY);
2778 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2779 isc_buffer_t **querytsig) {
2780 isc_result_t result;
2781 dns_rdata_t rdata = DNS_RDATA_INIT;
2784 REQUIRE(DNS_MESSAGE_VALID(msg));
2785 REQUIRE(mctx != NULL);
2786 REQUIRE(querytsig != NULL && *querytsig == NULL);
2788 if (msg->tsig == NULL)
2789 return (ISC_R_SUCCESS);
2791 result = dns_rdataset_first(msg->tsig);
2792 if (result != ISC_R_SUCCESS)
2794 dns_rdataset_current(msg->tsig, &rdata);
2795 dns_rdata_toregion(&rdata, &r);
2797 result = isc_buffer_allocate(mctx, querytsig, r.length);
2798 if (result != ISC_R_SUCCESS)
2800 isc_buffer_putmem(*querytsig, r.base, r.length);
2801 return (ISC_R_SUCCESS);
2805 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2808 * Get the SIG(0) record for 'msg'.
2811 REQUIRE(DNS_MESSAGE_VALID(msg));
2812 REQUIRE(owner == NULL || *owner == NULL);
2814 if (msg->sig0 != NULL && owner != NULL) {
2815 /* If dns_message_getsig0 is called on a rendered message
2816 * after the SIG(0) has been applied, we need to return the
2817 * root name, not NULL.
2819 if (msg->sig0name == NULL)
2820 *owner = dns_rootname;
2822 *owner = msg->sig0name;
2828 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2831 isc_result_t result;
2834 * Set the SIG(0) key for 'msg'
2838 * The space required for an SIG(0) record is:
2840 * 1 byte for the name
2841 * 2 bytes for the type
2842 * 2 bytes for the class
2843 * 4 bytes for the ttl
2844 * 2 bytes for the type covered
2845 * 1 byte for the algorithm
2846 * 1 bytes for the labels
2847 * 4 bytes for the original ttl
2848 * 4 bytes for the signature expiration
2849 * 4 bytes for the signature inception
2850 * 2 bytes for the key tag
2851 * n bytes for the signer's name
2852 * x bytes for the signature
2853 * ---------------------------------
2856 REQUIRE(DNS_MESSAGE_VALID(msg));
2857 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2858 REQUIRE(msg->state == DNS_SECTION_ANY);
2861 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
2862 dns_name_toregion(dst_key_name(key), &r);
2863 result = dst_key_sigsize(key, &x);
2864 if (result != ISC_R_SUCCESS) {
2865 msg->sig_reserved = 0;
2868 msg->sig_reserved = 27 + r.length + x;
2869 result = dns_message_renderreserve(msg, msg->sig_reserved);
2870 if (result != ISC_R_SUCCESS) {
2871 msg->sig_reserved = 0;
2876 return (ISC_R_SUCCESS);
2880 dns_message_getsig0key(dns_message_t *msg) {
2883 * Get the SIG(0) key for 'msg'
2886 REQUIRE(DNS_MESSAGE_VALID(msg));
2888 return (msg->sig0key);
2892 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2893 REQUIRE(DNS_MESSAGE_VALID(msg));
2894 REQUIRE(buffer != NULL);
2895 REQUIRE(ISC_BUFFER_VALID(*buffer));
2897 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2902 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2903 isc_result_t result = ISC_R_SUCCESS;
2904 dns_rdata_t rdata = DNS_RDATA_INIT;
2906 REQUIRE(DNS_MESSAGE_VALID(msg));
2907 REQUIRE(signer != NULL);
2908 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2910 if (msg->tsig == NULL && msg->sig0 == NULL)
2911 return (ISC_R_NOTFOUND);
2913 if (msg->verify_attempted == 0)
2914 return (DNS_R_NOTVERIFIEDYET);
2916 if (!dns_name_hasbuffer(signer)) {
2917 isc_buffer_t *dynbuf = NULL;
2918 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2919 if (result != ISC_R_SUCCESS)
2921 dns_name_setbuffer(signer, dynbuf);
2922 dns_message_takebuffer(msg, &dynbuf);
2925 if (msg->sig0 != NULL) {
2926 dns_rdata_sig_t sig;
2928 result = dns_rdataset_first(msg->sig0);
2929 INSIST(result == ISC_R_SUCCESS);
2930 dns_rdataset_current(msg->sig0, &rdata);
2932 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2933 if (result != ISC_R_SUCCESS)
2936 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2937 result = ISC_R_SUCCESS;
2939 result = DNS_R_SIGINVALID;
2940 dns_name_clone(&sig.signer, signer);
2941 dns_rdata_freestruct(&sig);
2943 dns_name_t *identity;
2944 dns_rdata_any_tsig_t tsig;
2946 result = dns_rdataset_first(msg->tsig);
2947 INSIST(result == ISC_R_SUCCESS);
2948 dns_rdataset_current(msg->tsig, &rdata);
2950 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2951 INSIST(result == ISC_R_SUCCESS);
2952 if (msg->tsigstatus != dns_rcode_noerror)
2953 result = DNS_R_TSIGVERIFYFAILURE;
2954 else if (tsig.error != dns_rcode_noerror)
2955 result = DNS_R_TSIGERRORSET;
2957 result = ISC_R_SUCCESS;
2958 dns_rdata_freestruct(&tsig);
2960 if (msg->tsigkey == NULL) {
2962 * If msg->tsigstatus & tsig.error are both
2963 * dns_rcode_noerror, the message must have been
2964 * verified, which means msg->tsigkey will be
2967 INSIST(result != ISC_R_SUCCESS);
2969 identity = dns_tsigkey_identity(msg->tsigkey);
2970 if (identity == NULL) {
2971 if (result == ISC_R_SUCCESS)
2972 result = DNS_R_NOIDENTITY;
2973 identity = &msg->tsigkey->name;
2975 dns_name_clone(identity, signer);
2983 dns_message_resetsig(dns_message_t *msg) {
2984 REQUIRE(DNS_MESSAGE_VALID(msg));
2985 msg->verified_sig = 0;
2986 msg->verify_attempted = 0;
2987 msg->tsigstatus = dns_rcode_noerror;
2988 msg->sig0status = dns_rcode_noerror;
2989 msg->timeadjust = 0;
2990 if (msg->tsigkey != NULL) {
2991 dns_tsigkey_detach(&msg->tsigkey);
2992 msg->tsigkey = NULL;
2997 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
2998 dns_message_resetsig(msg);
2999 return (dns_message_checksig(msg, view));
3002 #ifdef SKAN_MSG_DEBUG
3004 dns_message_dumpsig(dns_message_t *msg, char *txt1) {
3005 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
3006 dns_rdata_any_tsig_t querytsig;
3007 isc_result_t result;
3009 if (msg->tsig != NULL) {
3010 result = dns_rdataset_first(msg->tsig);
3011 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3012 dns_rdataset_current(msg->tsig, &querytsigrdata);
3013 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3014 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3015 hexdump(txt1, "TSIG", querytsig.signature,
3019 if (msg->querytsig != NULL) {
3020 result = dns_rdataset_first(msg->querytsig);
3021 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3022 dns_rdataset_current(msg->querytsig, &querytsigrdata);
3023 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3024 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3025 hexdump(txt1, "QUERYTSIG", querytsig.signature,
3032 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
3033 isc_buffer_t b, msgb;
3035 REQUIRE(DNS_MESSAGE_VALID(msg));
3037 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
3038 return (ISC_R_SUCCESS);
3040 INSIST(msg->saved.base != NULL);
3041 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
3042 isc_buffer_add(&msgb, msg->saved.length);
3043 if (msg->tsigkey != NULL || msg->tsig != NULL) {
3044 #ifdef SKAN_MSG_DEBUG
3045 dns_message_dumpsig(msg, "dns_message_checksig#1");
3048 return (dns_view_checksig(view, &msgb, msg));
3050 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
3052 dns_rdata_t rdata = DNS_RDATA_INIT;
3053 dns_rdata_sig_t sig;
3054 dns_rdataset_t keyset;
3055 isc_result_t result;
3057 result = dns_rdataset_first(msg->sig0);
3058 INSIST(result == ISC_R_SUCCESS);
3059 dns_rdataset_current(msg->sig0, &rdata);
3062 * This can occur when the message is a dynamic update, since
3063 * the rdata length checking is relaxed. This should not
3064 * happen in a well-formed message, since the SIG(0) is only
3065 * looked for in the additional section, and the dynamic update
3066 * meta-records are in the prerequisite and update sections.
3068 if (rdata.length == 0)
3069 return (ISC_R_UNEXPECTEDEND);
3071 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
3072 if (result != ISC_R_SUCCESS)
3075 dns_rdataset_init(&keyset);
3077 return (DNS_R_KEYUNAUTHORIZED);
3078 result = dns_view_simplefind(view, &sig.signer,
3079 dns_rdatatype_key /* SIG(0) */,
3080 0, 0, ISC_FALSE, &keyset, NULL);
3082 if (result != ISC_R_SUCCESS) {
3083 /* XXXBEW Should possibly create a fetch here */
3084 result = DNS_R_KEYUNAUTHORIZED;
3086 } else if (keyset.trust < dns_trust_secure) {
3087 /* XXXBEW Should call a validator here */
3088 result = DNS_R_KEYUNAUTHORIZED;
3091 result = dns_rdataset_first(&keyset);
3092 INSIST(result == ISC_R_SUCCESS);
3094 result == ISC_R_SUCCESS;
3095 result = dns_rdataset_next(&keyset))
3097 dst_key_t *key = NULL;
3099 dns_rdata_reset(&rdata);
3100 dns_rdataset_current(&keyset, &rdata);
3101 isc_buffer_init(&b, rdata.data, rdata.length);
3102 isc_buffer_add(&b, rdata.length);
3104 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
3105 &b, view->mctx, &key);
3106 if (result != ISC_R_SUCCESS)
3108 if (dst_key_alg(key) != sig.algorithm ||
3109 dst_key_id(key) != sig.keyid ||
3110 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
3111 dst_key_proto(key) == DNS_KEYPROTO_ANY))
3116 result = dns_dnssec_verifymessage(&msgb, msg, key);
3118 if (result == ISC_R_SUCCESS)
3121 if (result == ISC_R_NOMORE)
3122 result = DNS_R_KEYUNAUTHORIZED;
3125 if (dns_rdataset_isassociated(&keyset))
3126 dns_rdataset_disassociate(&keyset);
3127 dns_rdata_freestruct(&sig);
3133 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
3134 const dns_master_style_t *style,
3135 dns_messagetextflag_t flags,
3136 isc_buffer_t *target) {
3137 dns_name_t *name, empty_name;
3138 dns_rdataset_t *rdataset;
3139 isc_result_t result;
3140 isc_boolean_t seensoa = ISC_FALSE;
3142 REQUIRE(DNS_MESSAGE_VALID(msg));
3143 REQUIRE(target != NULL);
3144 REQUIRE(VALID_SECTION(section));
3146 if (ISC_LIST_EMPTY(msg->sections[section]))
3147 return (ISC_R_SUCCESS);
3149 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
3150 ADD_STRING(target, ";; ");
3151 if (msg->opcode != dns_opcode_update) {
3152 ADD_STRING(target, sectiontext[section]);
3154 ADD_STRING(target, updsectiontext[section]);
3156 ADD_STRING(target, " SECTION:\n");
3159 dns_name_init(&empty_name, NULL);
3160 result = dns_message_firstname(msg, section);
3161 if (result != ISC_R_SUCCESS) {
3166 dns_message_currentname(msg, section, &name);
3167 for (rdataset = ISC_LIST_HEAD(name->list);
3169 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3170 if (section == DNS_SECTION_ANSWER &&
3171 rdataset->type == dns_rdatatype_soa) {
3172 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
3175 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
3179 if (section == DNS_SECTION_QUESTION) {
3180 ADD_STRING(target, ";");
3181 result = dns_master_questiontotext(name,
3186 result = dns_master_rdatasettotext(name,
3191 if (result != ISC_R_SUCCESS)
3194 result = dns_message_nextname(msg, section);
3195 } while (result == ISC_R_SUCCESS);
3196 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3197 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3198 ADD_STRING(target, "\n");
3199 if (result == ISC_R_NOMORE)
3200 result = ISC_R_SUCCESS;
3205 dns_message_pseudosectiontotext(dns_message_t *msg,
3206 dns_pseudosection_t section,
3207 const dns_master_style_t *style,
3208 dns_messagetextflag_t flags,
3209 isc_buffer_t *target)
3211 dns_rdataset_t *ps = NULL;
3212 dns_name_t *name = NULL;
3213 isc_result_t result;
3214 char buf[sizeof("1234567890")];
3217 isc_buffer_t optbuf;
3218 isc_uint16_t optcode, optlen;
3219 unsigned char *optdata;
3221 REQUIRE(DNS_MESSAGE_VALID(msg));
3222 REQUIRE(target != NULL);
3223 REQUIRE(VALID_PSEUDOSECTION(section));
3226 case DNS_PSEUDOSECTION_OPT:
3227 ps = dns_message_getopt(msg);
3229 return (ISC_R_SUCCESS);
3230 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3231 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
3232 ADD_STRING(target, "; EDNS: version: ");
3233 snprintf(buf, sizeof(buf), "%u",
3234 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
3235 ADD_STRING(target, buf);
3236 ADD_STRING(target, ", flags:");
3237 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
3238 ADD_STRING(target, " do");
3239 mbz = ps->ttl & 0xffff;
3240 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */
3242 ADD_STRING(target, "; MBZ: ");
3243 snprintf(buf, sizeof(buf), "%.4x ", mbz);
3244 ADD_STRING(target, buf);
3245 ADD_STRING(target, ", udp: ");
3247 ADD_STRING(target, "; udp: ");
3248 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
3249 ADD_STRING(target, buf);
3251 result = dns_rdataset_first(ps);
3252 if (result != ISC_R_SUCCESS)
3253 return (ISC_R_SUCCESS);
3255 /* Print EDNS info, if any */
3256 dns_rdata_init(&rdata);
3257 dns_rdataset_current(ps, &rdata);
3259 isc_buffer_init(&optbuf, rdata.data, rdata.length);
3260 isc_buffer_add(&optbuf, rdata.length);
3261 while (isc_buffer_remaininglength(&optbuf) != 0) {
3262 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
3263 optcode = isc_buffer_getuint16(&optbuf);
3264 optlen = isc_buffer_getuint16(&optbuf);
3265 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
3267 if (optcode == DNS_OPT_NSID) {
3268 ADD_STRING(target, "; NSID");
3270 ADD_STRING(target, "; OPT=");
3271 sprintf(buf, "%u", optcode);
3272 ADD_STRING(target, buf);
3277 ADD_STRING(target, ": ");
3279 optdata = isc_buffer_current(&optbuf);
3280 for (i = 0; i < optlen; i++) {
3281 sprintf(buf, "%02x ", optdata[i]);
3282 ADD_STRING(target, buf);
3285 for (i = 0; i < optlen; i++) {
3286 ADD_STRING(target, " (");
3287 if (!isc_buffer_availablelength(target))
3288 return (ISC_R_NOSPACE);
3289 if (isprint(optdata[i]))
3290 isc_buffer_putmem(target,
3294 isc_buffer_putstr(target, ".");
3295 ADD_STRING(target, ")");
3297 isc_buffer_forward(&optbuf, optlen);
3299 ADD_STRING(target, "\n");
3301 return (ISC_R_SUCCESS);
3302 case DNS_PSEUDOSECTION_TSIG:
3303 ps = dns_message_gettsig(msg, &name);
3305 return (ISC_R_SUCCESS);
3306 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3307 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
3308 result = dns_master_rdatasettotext(name, ps, style, target);
3309 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3310 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3311 ADD_STRING(target, "\n");
3313 case DNS_PSEUDOSECTION_SIG0:
3314 ps = dns_message_getsig0(msg, &name);
3316 return (ISC_R_SUCCESS);
3317 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3318 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
3319 result = dns_master_rdatasettotext(name, ps, style, target);
3320 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3321 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3322 ADD_STRING(target, "\n");
3325 return (ISC_R_UNEXPECTED);
3329 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
3330 dns_messagetextflag_t flags, isc_buffer_t *target) {
3331 char buf[sizeof("1234567890")];
3332 isc_result_t result;
3334 REQUIRE(DNS_MESSAGE_VALID(msg));
3335 REQUIRE(target != NULL);
3337 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
3338 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
3339 ADD_STRING(target, opcodetext[msg->opcode]);
3340 ADD_STRING(target, ", status: ");
3341 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
3342 ADD_STRING(target, rcodetext[msg->rcode]);
3344 snprintf(buf, sizeof(buf), "%4u", msg->rcode);
3345 ADD_STRING(target, buf);
3347 ADD_STRING(target, ", id: ");
3348 snprintf(buf, sizeof(buf), "%6u", msg->id);
3349 ADD_STRING(target, buf);
3350 ADD_STRING(target, "\n;; flags:");
3351 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
3352 ADD_STRING(target, " qr");
3353 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
3354 ADD_STRING(target, " aa");
3355 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
3356 ADD_STRING(target, " tc");
3357 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
3358 ADD_STRING(target, " rd");
3359 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
3360 ADD_STRING(target, " ra");
3361 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3362 ADD_STRING(target, " ad");
3363 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3364 ADD_STRING(target, " cd");
3366 * The final unnamed flag must be zero.
3368 if ((msg->flags & 0x0040U) != 0)
3369 ADD_STRING(target, "; MBZ: 0x4");
3370 if (msg->opcode != dns_opcode_update) {
3371 ADD_STRING(target, "; QUESTION: ");
3373 ADD_STRING(target, "; ZONE: ");
3375 snprintf(buf, sizeof(buf), "%1u",
3376 msg->counts[DNS_SECTION_QUESTION]);
3377 ADD_STRING(target, buf);
3378 if (msg->opcode != dns_opcode_update) {
3379 ADD_STRING(target, ", ANSWER: ");
3381 ADD_STRING(target, ", PREREQ: ");
3383 snprintf(buf, sizeof(buf), "%1u",
3384 msg->counts[DNS_SECTION_ANSWER]);
3385 ADD_STRING(target, buf);
3386 if (msg->opcode != dns_opcode_update) {
3387 ADD_STRING(target, ", AUTHORITY: ");
3389 ADD_STRING(target, ", UPDATE: ");
3391 snprintf(buf, sizeof(buf), "%1u",
3392 msg->counts[DNS_SECTION_AUTHORITY]);
3393 ADD_STRING(target, buf);
3394 ADD_STRING(target, ", ADDITIONAL: ");
3395 snprintf(buf, sizeof(buf), "%1u",
3396 msg->counts[DNS_SECTION_ADDITIONAL]);
3397 ADD_STRING(target, buf);
3398 ADD_STRING(target, "\n");
3400 result = dns_message_pseudosectiontotext(msg,
3401 DNS_PSEUDOSECTION_OPT,
3402 style, flags, target);
3403 if (result != ISC_R_SUCCESS)
3406 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3407 style, flags, target);
3408 if (result != ISC_R_SUCCESS)
3410 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3411 style, flags, target);
3412 if (result != ISC_R_SUCCESS)
3414 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3415 style, flags, target);
3416 if (result != ISC_R_SUCCESS)
3418 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3419 style, flags, target);
3420 if (result != ISC_R_SUCCESS)
3423 result = dns_message_pseudosectiontotext(msg,
3424 DNS_PSEUDOSECTION_TSIG,
3425 style, flags, target);
3426 if (result != ISC_R_SUCCESS)
3429 result = dns_message_pseudosectiontotext(msg,
3430 DNS_PSEUDOSECTION_SIG0,
3431 style, flags, target);
3432 if (result != ISC_R_SUCCESS)
3435 return (ISC_R_SUCCESS);
3439 dns_message_getrawmessage(dns_message_t *msg) {
3440 REQUIRE(DNS_MESSAGE_VALID(msg));
3441 return (&msg->saved);
3445 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3446 const void *order_arg)
3448 REQUIRE(DNS_MESSAGE_VALID(msg));
3450 msg->order_arg = order_arg;
3454 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3455 REQUIRE(DNS_MESSAGE_VALID(msg));
3456 msg->timeadjust = timeadjust;
3460 dns_message_gettimeadjust(dns_message_t *msg) {
3461 REQUIRE(DNS_MESSAGE_VALID(msg));
3462 return (msg->timeadjust);
3466 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
3468 REQUIRE(opcode < 16);
3470 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
3471 return (ISC_R_NOSPACE);
3472 isc_buffer_putstr(target, opcodetext[opcode]);
3473 return (ISC_R_SUCCESS);
3477 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
3478 unsigned int version, isc_uint16_t udpsize,
3479 unsigned int flags, dns_ednsopt_t *ednsopts, size_t count)
3481 dns_rdataset_t *rdataset = NULL;
3482 dns_rdatalist_t *rdatalist = NULL;
3483 dns_rdata_t *rdata = NULL;
3484 isc_result_t result;
3485 unsigned int len = 0, i;
3487 REQUIRE(DNS_MESSAGE_VALID(message));
3488 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
3490 result = dns_message_gettemprdatalist(message, &rdatalist);
3491 if (result != ISC_R_SUCCESS)
3493 result = dns_message_gettemprdata(message, &rdata);
3494 if (result != ISC_R_SUCCESS)
3496 result = dns_message_gettemprdataset(message, &rdataset);
3497 if (result != ISC_R_SUCCESS)
3499 dns_rdataset_init(rdataset);
3501 rdatalist->type = dns_rdatatype_opt;
3502 rdatalist->covers = 0;
3505 * Set Maximum UDP buffer size.
3507 rdatalist->rdclass = udpsize;
3510 * Set EXTENDED-RCODE and Z to 0.
3512 rdatalist->ttl = (version << 16);
3513 rdatalist->ttl |= (flags & 0xffff);
3516 * Set EDNS options if applicable
3519 isc_buffer_t *buf = NULL;
3520 for (i = 0; i < count; i++)
3521 len += ednsopts[i].length + 4;
3523 if (len > 0xffffU) {
3524 result = ISC_R_NOSPACE;
3528 result = isc_buffer_allocate(message->mctx, &buf, len);
3529 if (result != ISC_R_SUCCESS)
3532 for (i = 0; i < count; i++) {
3533 isc_buffer_putuint16(buf, ednsopts[i].code);
3534 isc_buffer_putuint16(buf, ednsopts[i].length);
3535 isc_buffer_putmem(buf, ednsopts[i].value,
3536 ednsopts[i].length);
3538 rdata->data = isc_buffer_base(buf);
3539 rdata->length = len;
3540 dns_message_takebuffer(message, &buf);
3546 rdata->rdclass = rdatalist->rdclass;
3547 rdata->type = rdatalist->type;
3550 ISC_LIST_INIT(rdatalist->rdata);
3551 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
3552 result = dns_rdatalist_tordataset(rdatalist, rdataset);
3553 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3555 *rdatasetp = rdataset;
3556 return (ISC_R_SUCCESS);
3560 dns_message_puttemprdata(message, &rdata);
3561 if (rdataset != NULL)
3562 dns_message_puttemprdataset(message, &rdataset);
3563 if (rdatalist != NULL)
3564 dns_message_puttemprdatalist(message, &rdatalist);