2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.
18 /* $Id: message.c,v 1.222.18.10 2006/03/02 23:19:20 marka Exp $ */
28 #include <isc/buffer.h>
30 #include <isc/print.h>
31 #include <isc/string.h> /* Required for HP/UX (and others?) */
34 #include <dns/dnssec.h>
35 #include <dns/keyvalues.h>
37 #include <dns/masterdump.h>
38 #include <dns/message.h>
39 #include <dns/opcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/result.h>
48 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
49 #define DNS_MESSAGE_OPCODE_SHIFT 11
50 #define DNS_MESSAGE_RCODE_MASK 0x000fU
51 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
52 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
53 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
54 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
55 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
57 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
58 && ((s) < DNS_SECTION_MAX))
59 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
60 && ((s) < DNS_SECTION_MAX))
61 #define ADD_STRING(b, s) {if (strlen(s) >= \
62 isc_buffer_availablelength(b)) \
63 return(ISC_R_NOSPACE); else \
64 isc_buffer_putstr(b, s);}
65 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
66 && ((s) < DNS_PSEUDOSECTION_MAX))
69 * This is the size of each individual scratchpad buffer, and the numbers
70 * of various block allocations used within the server.
71 * XXXMLG These should come from a config setting.
73 #define SCRATCHPAD_SIZE 512
75 #define OFFSET_COUNT 4
77 #define RDATALIST_COUNT 8
78 #define RDATASET_COUNT RDATALIST_COUNT
81 * Text representation of the different items, for message_totext
84 static const char *sectiontext[] = {
91 static const char *updsectiontext[] = {
98 static const char *opcodetext[] = {
117 static const char *rcodetext[] = {
139 * "helper" type, which consists of a block of some type, and is linkable.
140 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
141 * size, or the allocated elements will not be alligned correctly.
143 struct dns_msgblock {
145 unsigned int remaining;
146 ISC_LINK(dns_msgblock_t) link;
147 }; /* dynamically sized */
149 static inline dns_msgblock_t *
150 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
152 #define msgblock_get(block, type) \
153 ((type *)msgblock_internalget(block, sizeof(type)))
156 msgblock_internalget(dns_msgblock_t *, unsigned int);
159 msgblock_reset(dns_msgblock_t *);
162 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
165 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
166 * is free, return NULL.
168 static inline dns_msgblock_t *
169 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
172 dns_msgblock_t *block;
175 length = sizeof(dns_msgblock_t) + (sizeof_type * count);
177 block = isc_mem_get(mctx, length);
181 block->count = count;
182 block->remaining = count;
184 ISC_LINK_INIT(block, link);
190 * Return an element from the msgblock. If no more are available, return
194 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
197 if (block == NULL || block->remaining == 0)
202 ptr = (((unsigned char *)block)
203 + sizeof(dns_msgblock_t)
204 + (sizeof_type * block->remaining));
210 msgblock_reset(dns_msgblock_t *block) {
211 block->remaining = block->count;
215 * Release memory associated with a message block.
218 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
222 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
224 isc_mem_put(mctx, block, length);
228 * Allocate a new dynamic buffer, and attach it to this message as the
229 * "current" buffer. (which is always the last on the list, for our
232 static inline isc_result_t
233 newbuffer(dns_message_t *msg, unsigned int size) {
235 isc_buffer_t *dynbuf;
238 result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
239 if (result != ISC_R_SUCCESS)
240 return (ISC_R_NOMEMORY);
242 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
243 return (ISC_R_SUCCESS);
246 static inline isc_buffer_t *
247 currentbuffer(dns_message_t *msg) {
248 isc_buffer_t *dynbuf;
250 dynbuf = ISC_LIST_TAIL(msg->scratchpad);
251 INSIST(dynbuf != NULL);
257 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
258 ISC_LIST_PREPEND(msg->freerdata, rdata, link);
261 static inline dns_rdata_t *
262 newrdata(dns_message_t *msg) {
263 dns_msgblock_t *msgblock;
266 rdata = ISC_LIST_HEAD(msg->freerdata);
268 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
272 msgblock = ISC_LIST_TAIL(msg->rdatas);
273 rdata = msgblock_get(msgblock, dns_rdata_t);
275 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
277 if (msgblock == NULL)
280 ISC_LIST_APPEND(msg->rdatas, msgblock, link);
282 rdata = msgblock_get(msgblock, dns_rdata_t);
285 dns_rdata_init(rdata);
290 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
291 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
294 static inline dns_rdatalist_t *
295 newrdatalist(dns_message_t *msg) {
296 dns_msgblock_t *msgblock;
297 dns_rdatalist_t *rdatalist;
299 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
300 if (rdatalist != NULL) {
301 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
305 msgblock = ISC_LIST_TAIL(msg->rdatalists);
306 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
307 if (rdatalist == NULL) {
308 msgblock = msgblock_allocate(msg->mctx,
309 sizeof(dns_rdatalist_t),
311 if (msgblock == NULL)
314 ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
316 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
322 static inline dns_offsets_t *
323 newoffsets(dns_message_t *msg) {
324 dns_msgblock_t *msgblock;
325 dns_offsets_t *offsets;
327 msgblock = ISC_LIST_TAIL(msg->offsets);
328 offsets = msgblock_get(msgblock, dns_offsets_t);
329 if (offsets == NULL) {
330 msgblock = msgblock_allocate(msg->mctx,
331 sizeof(dns_offsets_t),
333 if (msgblock == NULL)
336 ISC_LIST_APPEND(msg->offsets, msgblock, link);
338 offsets = msgblock_get(msgblock, dns_offsets_t);
345 msginitheader(dns_message_t *m) {
354 msginitprivate(dns_message_t *m) {
357 for (i = 0; i < DNS_SECTION_MAX; i++) {
358 m->cursors[i] = NULL;
366 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
374 msginittsig(dns_message_t *m) {
375 m->tsigstatus = dns_rcode_noerror;
376 m->querytsigstatus = dns_rcode_noerror;
381 m->sig0status = dns_rcode_noerror;
386 * Init elements to default state. Used both when allocating a new element
387 * and when resetting one.
390 msginit(dns_message_t *m) {
396 m->tcp_continuation = 0;
398 m->verify_attempted = 0;
401 m->query.base = NULL;
404 m->saved.base = NULL;
411 msgresetnames(dns_message_t *msg, unsigned int first_section) {
413 dns_name_t *name, *next_name;
414 dns_rdataset_t *rds, *next_rds;
417 * Clean up name lists by calling the rdataset disassociate function.
419 for (i = first_section; i < DNS_SECTION_MAX; i++) {
420 name = ISC_LIST_HEAD(msg->sections[i]);
421 while (name != NULL) {
422 next_name = ISC_LIST_NEXT(name, link);
423 ISC_LIST_UNLINK(msg->sections[i], name, link);
425 rds = ISC_LIST_HEAD(name->list);
426 while (rds != NULL) {
427 next_rds = ISC_LIST_NEXT(rds, link);
428 ISC_LIST_UNLINK(name->list, rds, link);
430 INSIST(dns_rdataset_isassociated(rds));
431 dns_rdataset_disassociate(rds);
432 isc_mempool_put(msg->rdspool, rds);
435 if (dns_name_dynamic(name))
436 dns_name_free(name, msg->mctx);
437 isc_mempool_put(msg->namepool, name);
444 msgresetopt(dns_message_t *msg)
446 if (msg->opt != NULL) {
447 if (msg->opt_reserved > 0) {
448 dns_message_renderrelease(msg, msg->opt_reserved);
449 msg->opt_reserved = 0;
451 INSIST(dns_rdataset_isassociated(msg->opt));
452 dns_rdataset_disassociate(msg->opt);
453 isc_mempool_put(msg->rdspool, msg->opt);
459 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
460 if (msg->sig_reserved > 0) {
461 dns_message_renderrelease(msg, msg->sig_reserved);
462 msg->sig_reserved = 0;
464 if (msg->tsig != NULL) {
465 INSIST(dns_rdataset_isassociated(msg->tsig));
466 INSIST(msg->namepool != NULL);
468 INSIST(msg->querytsig == NULL);
469 msg->querytsig = msg->tsig;
471 dns_rdataset_disassociate(msg->tsig);
472 isc_mempool_put(msg->rdspool, msg->tsig);
473 if (msg->querytsig != NULL) {
474 dns_rdataset_disassociate(msg->querytsig);
475 isc_mempool_put(msg->rdspool, msg->querytsig);
478 if (dns_name_dynamic(msg->tsigname))
479 dns_name_free(msg->tsigname, msg->mctx);
480 isc_mempool_put(msg->namepool, msg->tsigname);
482 msg->tsigname = NULL;
483 } else if (msg->querytsig != NULL && !replying) {
484 dns_rdataset_disassociate(msg->querytsig);
485 isc_mempool_put(msg->rdspool, msg->querytsig);
486 msg->querytsig = NULL;
488 if (msg->sig0 != NULL) {
489 INSIST(dns_rdataset_isassociated(msg->sig0));
490 dns_rdataset_disassociate(msg->sig0);
491 isc_mempool_put(msg->rdspool, msg->sig0);
492 if (msg->sig0name != NULL) {
493 if (dns_name_dynamic(msg->sig0name))
494 dns_name_free(msg->sig0name, msg->mctx);
495 isc_mempool_put(msg->namepool, msg->sig0name);
498 msg->sig0name = NULL;
503 * Free all but one (or everything) for this message. This is used by
504 * both dns_message_reset() and dns_message_destroy().
507 msgreset(dns_message_t *msg, isc_boolean_t everything) {
508 dns_msgblock_t *msgblock, *next_msgblock;
509 isc_buffer_t *dynbuf, *next_dynbuf;
511 dns_rdatalist_t *rdatalist;
513 msgresetnames(msg, 0);
515 msgresetsigs(msg, ISC_FALSE);
518 * Clean up linked lists.
522 * Run through the free lists, and just unlink anything found there.
523 * The memory isn't lost since these are part of message blocks we
526 rdata = ISC_LIST_HEAD(msg->freerdata);
527 while (rdata != NULL) {
528 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
529 rdata = ISC_LIST_HEAD(msg->freerdata);
531 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
532 while (rdatalist != NULL) {
533 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
534 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
537 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
538 INSIST(dynbuf != NULL);
540 isc_buffer_clear(dynbuf);
541 dynbuf = ISC_LIST_NEXT(dynbuf, link);
543 while (dynbuf != NULL) {
544 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
545 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
546 isc_buffer_free(&dynbuf);
547 dynbuf = next_dynbuf;
550 msgblock = ISC_LIST_HEAD(msg->rdatas);
551 if (!everything && msgblock != NULL) {
552 msgblock_reset(msgblock);
553 msgblock = ISC_LIST_NEXT(msgblock, link);
555 while (msgblock != NULL) {
556 next_msgblock = ISC_LIST_NEXT(msgblock, link);
557 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
558 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
559 msgblock = next_msgblock;
563 * rdatalists could be empty.
566 msgblock = ISC_LIST_HEAD(msg->rdatalists);
567 if (!everything && msgblock != NULL) {
568 msgblock_reset(msgblock);
569 msgblock = ISC_LIST_NEXT(msgblock, link);
571 while (msgblock != NULL) {
572 next_msgblock = ISC_LIST_NEXT(msgblock, link);
573 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
574 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
575 msgblock = next_msgblock;
578 msgblock = ISC_LIST_HEAD(msg->offsets);
579 if (!everything && msgblock != NULL) {
580 msgblock_reset(msgblock);
581 msgblock = ISC_LIST_NEXT(msgblock, link);
583 while (msgblock != NULL) {
584 next_msgblock = ISC_LIST_NEXT(msgblock, link);
585 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
586 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
587 msgblock = next_msgblock;
590 if (msg->tsigkey != NULL) {
591 dns_tsigkey_detach(&msg->tsigkey);
595 if (msg->query.base != NULL) {
596 if (msg->free_query != 0)
597 isc_mem_put(msg->mctx, msg->query.base,
599 msg->query.base = NULL;
600 msg->query.length = 0;
603 if (msg->saved.base != NULL) {
604 if (msg->free_saved != 0)
605 isc_mem_put(msg->mctx, msg->saved.base,
607 msg->saved.base = NULL;
608 msg->saved.length = 0;
612 * cleanup the buffer cleanup list
614 dynbuf = ISC_LIST_HEAD(msg->cleanup);
615 while (dynbuf != NULL) {
616 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
617 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
618 isc_buffer_free(&dynbuf);
619 dynbuf = next_dynbuf;
623 * Set other bits to normal default values.
628 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
629 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
633 spacefortsig(dns_tsigkey_t *key, int otherlen) {
639 * The space required for an TSIG record is:
641 * n1 bytes for the name
642 * 2 bytes for the type
643 * 2 bytes for the class
644 * 4 bytes for the ttl
645 * 2 bytes for the rdlength
646 * n2 bytes for the algorithm name
647 * 6 bytes for the time signed
648 * 2 bytes for the fudge
649 * 2 bytes for the MAC size
650 * x bytes for the MAC
651 * 2 bytes for the original id
652 * 2 bytes for the error
653 * 2 bytes for the other data length
654 * y bytes for the other data (at most)
655 * ---------------------------------
656 * 26 + n1 + n2 + x + y bytes
659 dns_name_toregion(&key->name, &r1);
660 dns_name_toregion(key->algorithm, &r2);
661 if (key->key == NULL)
664 result = dst_key_sigsize(key->key, &x);
665 if (result != ISC_R_SUCCESS)
668 return (26 + r1.length + r2.length + x + otherlen);
672 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
676 isc_buffer_t *dynbuf;
679 REQUIRE(mctx != NULL);
680 REQUIRE(msgp != NULL);
681 REQUIRE(*msgp == NULL);
682 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
683 || intent == DNS_MESSAGE_INTENTRENDER);
685 m = isc_mem_get(mctx, sizeof(dns_message_t));
687 return (ISC_R_NOMEMORY);
690 * No allocations until further notice. Just initialize all lists
691 * and other members that are freed in the cleanup phase here.
694 m->magic = DNS_MESSAGE_MAGIC;
695 m->from_to_wire = intent;
698 for (i = 0; i < DNS_SECTION_MAX; i++)
699 ISC_LIST_INIT(m->sections[i]);
702 ISC_LIST_INIT(m->scratchpad);
703 ISC_LIST_INIT(m->cleanup);
706 ISC_LIST_INIT(m->rdatas);
707 ISC_LIST_INIT(m->rdatalists);
708 ISC_LIST_INIT(m->offsets);
709 ISC_LIST_INIT(m->freerdata);
710 ISC_LIST_INIT(m->freerdatalist);
713 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
716 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
717 if (result != ISC_R_SUCCESS)
719 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
720 isc_mempool_setname(m->namepool, "msg:names");
722 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
724 if (result != ISC_R_SUCCESS)
726 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
727 isc_mempool_setname(m->rdspool, "msg:rdataset");
730 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
731 if (result != ISC_R_SUCCESS)
733 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
738 return (ISC_R_SUCCESS);
741 * Cleanup for error returns.
744 dynbuf = ISC_LIST_HEAD(m->scratchpad);
745 if (dynbuf != NULL) {
746 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
747 isc_buffer_free(&dynbuf);
749 if (m->namepool != NULL)
750 isc_mempool_destroy(&m->namepool);
751 if (m->rdspool != NULL)
752 isc_mempool_destroy(&m->rdspool);
754 isc_mem_put(mctx, m, sizeof(dns_message_t));
756 return (ISC_R_NOMEMORY);
760 dns_message_reset(dns_message_t *msg, unsigned int intent) {
761 REQUIRE(DNS_MESSAGE_VALID(msg));
762 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
763 || intent == DNS_MESSAGE_INTENTRENDER);
765 msgreset(msg, ISC_FALSE);
766 msg->from_to_wire = intent;
770 dns_message_destroy(dns_message_t **msgp) {
773 REQUIRE(msgp != NULL);
774 REQUIRE(DNS_MESSAGE_VALID(*msgp));
779 msgreset(msg, ISC_TRUE);
780 isc_mempool_destroy(&msg->namepool);
781 isc_mempool_destroy(&msg->rdspool);
783 isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
787 findname(dns_name_t **foundname, dns_name_t *target,
788 dns_namelist_t *section)
792 for (curr = ISC_LIST_TAIL(*section);
794 curr = ISC_LIST_PREV(curr, link)) {
795 if (dns_name_equal(curr, target)) {
796 if (foundname != NULL)
798 return (ISC_R_SUCCESS);
802 return (ISC_R_NOTFOUND);
806 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
807 dns_rdatatype_t type, dns_rdatatype_t covers,
808 dns_rdataset_t **rdataset)
810 dns_rdataset_t *curr;
812 if (rdataset != NULL) {
813 REQUIRE(*rdataset == NULL);
816 for (curr = ISC_LIST_TAIL(name->list);
818 curr = ISC_LIST_PREV(curr, link)) {
819 if (curr->rdclass == rdclass &&
820 curr->type == type && curr->covers == covers) {
821 if (rdataset != NULL)
823 return (ISC_R_SUCCESS);
827 return (ISC_R_NOTFOUND);
831 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
832 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
834 dns_rdataset_t *curr;
836 REQUIRE(name != NULL);
837 if (rdataset != NULL) {
838 REQUIRE(*rdataset == NULL);
841 for (curr = ISC_LIST_TAIL(name->list);
843 curr = ISC_LIST_PREV(curr, link)) {
844 if (curr->type == type && curr->covers == covers) {
845 if (rdataset != NULL)
847 return (ISC_R_SUCCESS);
851 return (ISC_R_NOTFOUND);
855 * Read a name from buffer "source".
858 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
859 dns_decompress_t *dctx)
861 isc_buffer_t *scratch;
865 scratch = currentbuffer(msg);
868 * First try: use current buffer.
869 * Second try: allocate a new buffer and use that.
873 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
876 if (result == ISC_R_NOSPACE) {
879 result = newbuffer(msg, SCRATCHPAD_SIZE);
880 if (result != ISC_R_SUCCESS)
883 scratch = currentbuffer(msg);
884 dns_name_reset(name);
890 INSIST(0); /* Cannot get here... */
891 return (ISC_R_UNEXPECTED);
895 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
896 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
897 unsigned int rdatalen, dns_rdata_t *rdata)
899 isc_buffer_t *scratch;
902 unsigned int trysize;
904 scratch = currentbuffer(msg);
906 isc_buffer_setactive(source, rdatalen);
909 * First try: use current buffer.
910 * Second try: allocate a new buffer of size
911 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
912 * (the data will fit if it was not more than 50% compressed)
913 * Subsequent tries: double buffer size on each try.
917 /* XXX possibly change this to a while (tries < 2) loop */
919 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
923 if (result == ISC_R_NOSPACE) {
925 trysize = 2 * rdatalen;
926 if (trysize < SCRATCHPAD_SIZE)
927 trysize = SCRATCHPAD_SIZE;
929 INSIST(trysize != 0);
930 if (trysize >= 65535)
931 return (ISC_R_NOSPACE);
932 /* XXX DNS_R_RRTOOLONG? */
936 result = newbuffer(msg, trysize);
937 if (result != ISC_R_SUCCESS)
940 scratch = currentbuffer(msg);
950 seen_problem = ISC_TRUE; \
952 result = DNS_R_FORMERR; \
958 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
959 unsigned int options)
965 dns_offsets_t *offsets;
966 dns_rdataset_t *rdataset;
967 dns_rdatalist_t *rdatalist;
969 dns_rdatatype_t rdtype;
970 dns_rdataclass_t rdclass;
971 dns_namelist_t *section;
972 isc_boolean_t free_name;
973 isc_boolean_t best_effort;
974 isc_boolean_t seen_problem;
976 section = &msg->sections[DNS_SECTION_QUESTION];
978 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
979 seen_problem = ISC_FALSE;
985 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
986 name = isc_mempool_get(msg->namepool);
988 return (ISC_R_NOMEMORY);
989 free_name = ISC_TRUE;
991 offsets = newoffsets(msg);
992 if (offsets == NULL) {
993 result = ISC_R_NOMEMORY;
996 dns_name_init(name, *offsets);
999 * Parse the name out of this packet.
1001 isc_buffer_remainingregion(source, &r);
1002 isc_buffer_setactive(source, r.length);
1003 result = getname(name, source, msg, dctx);
1004 if (result != ISC_R_SUCCESS)
1008 * Run through the section, looking to see if this name
1009 * is already there. If it is found, put back the allocated
1010 * name since we no longer need it, and set our name pointer
1011 * to point to the name we found.
1013 result = findname(&name2, name, section);
1016 * If it is the first name in the section, accept it.
1018 * If it is not, but is not the same as the name already
1019 * in the question section, append to the section. Note that
1020 * here in the question section this is illegal, so return
1021 * FORMERR. In the future, check the opcode to see if
1022 * this should be legal or not. In either case we no longer
1023 * need this name pointer.
1025 if (result != ISC_R_SUCCESS) {
1026 if (!ISC_LIST_EMPTY(*section))
1028 ISC_LIST_APPEND(*section, name, link);
1029 free_name = ISC_FALSE;
1031 isc_mempool_put(msg->namepool, name);
1034 free_name = ISC_FALSE;
1038 * Get type and class.
1040 isc_buffer_remainingregion(source, &r);
1042 result = ISC_R_UNEXPECTEDEND;
1045 rdtype = isc_buffer_getuint16(source);
1046 rdclass = isc_buffer_getuint16(source);
1049 * If this class is different than the one we already read,
1052 if (msg->state == DNS_SECTION_ANY) {
1053 msg->state = DNS_SECTION_QUESTION;
1054 msg->rdclass = rdclass;
1055 } else if (msg->rdclass != rdclass)
1059 * Can't ask the same question twice.
1061 result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1062 if (result == ISC_R_SUCCESS)
1066 * Allocate a new rdatalist.
1068 rdatalist = newrdatalist(msg);
1069 if (rdatalist == NULL) {
1070 result = ISC_R_NOMEMORY;
1073 rdataset = isc_mempool_get(msg->rdspool);
1074 if (rdataset == NULL) {
1075 result = ISC_R_NOMEMORY;
1080 * Convert rdatalist to rdataset, and attach the latter to
1083 rdatalist->type = rdtype;
1084 rdatalist->covers = 0;
1085 rdatalist->rdclass = rdclass;
1087 ISC_LIST_INIT(rdatalist->rdata);
1089 dns_rdataset_init(rdataset);
1090 result = dns_rdatalist_tordataset(rdatalist, rdataset);
1091 if (result != ISC_R_SUCCESS)
1094 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1096 ISC_LIST_APPEND(name->list, rdataset, link);
1101 return (DNS_R_RECOVERABLE);
1102 return (ISC_R_SUCCESS);
1105 if (rdataset != NULL) {
1106 INSIST(!dns_rdataset_isassociated(rdataset));
1107 isc_mempool_put(msg->rdspool, rdataset);
1110 if (rdatalist != NULL)
1111 isc_mempool_put(msg->rdlpool, rdatalist);
1114 isc_mempool_put(msg->namepool, name);
1119 static isc_boolean_t
1120 update(dns_section_t section, dns_rdataclass_t rdclass) {
1121 if (section == DNS_SECTION_PREREQUISITE)
1122 return (ISC_TF(rdclass == dns_rdataclass_any ||
1123 rdclass == dns_rdataclass_none));
1124 if (section == DNS_SECTION_UPDATE)
1125 return (ISC_TF(rdclass == dns_rdataclass_any));
1130 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1131 dns_section_t sectionid, unsigned int options)
1134 unsigned int count, rdatalen;
1137 dns_offsets_t *offsets;
1138 dns_rdataset_t *rdataset;
1139 dns_rdatalist_t *rdatalist;
1140 isc_result_t result;
1141 dns_rdatatype_t rdtype, covers;
1142 dns_rdataclass_t rdclass;
1145 dns_namelist_t *section;
1146 isc_boolean_t free_name, free_rdataset;
1147 isc_boolean_t preserve_order, best_effort, seen_problem;
1148 isc_boolean_t issigzero;
1150 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1151 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1152 seen_problem = ISC_FALSE;
1154 for (count = 0; count < msg->counts[sectionid]; count++) {
1155 int recstart = source->current;
1156 isc_boolean_t skip_name_search, skip_type_search;
1158 section = &msg->sections[sectionid];
1160 skip_name_search = ISC_FALSE;
1161 skip_type_search = ISC_FALSE;
1162 free_name = ISC_FALSE;
1163 free_rdataset = ISC_FALSE;
1165 name = isc_mempool_get(msg->namepool);
1167 return (ISC_R_NOMEMORY);
1168 free_name = ISC_TRUE;
1170 offsets = newoffsets(msg);
1171 if (offsets == NULL) {
1172 result = ISC_R_NOMEMORY;
1175 dns_name_init(name, *offsets);
1178 * Parse the name out of this packet.
1180 isc_buffer_remainingregion(source, &r);
1181 isc_buffer_setactive(source, r.length);
1182 result = getname(name, source, msg, dctx);
1183 if (result != ISC_R_SUCCESS)
1187 * Get type, class, ttl, and rdatalen. Verify that at least
1188 * rdatalen bytes remain. (Some of this is deferred to
1191 isc_buffer_remainingregion(source, &r);
1192 if (r.length < 2 + 2 + 4 + 2) {
1193 result = ISC_R_UNEXPECTEDEND;
1196 rdtype = isc_buffer_getuint16(source);
1197 rdclass = isc_buffer_getuint16(source);
1200 * If there was no question section, we may not yet have
1201 * established a class. Do so now.
1203 if (msg->state == DNS_SECTION_ANY &&
1204 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
1205 rdtype != dns_rdatatype_tsig && /* class is ANY */
1206 rdtype != dns_rdatatype_tkey) { /* class is undefined */
1207 msg->rdclass = rdclass;
1208 msg->state = DNS_SECTION_QUESTION;
1212 * If this class is different than the one in the question
1215 if (msg->opcode != dns_opcode_update
1216 && rdtype != dns_rdatatype_tsig
1217 && rdtype != dns_rdatatype_opt
1218 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
1219 && rdtype != dns_rdatatype_sig /* SIG(0) */
1220 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1221 && msg->rdclass != dns_rdataclass_any
1222 && msg->rdclass != rdclass)
1226 * Special type handling for TSIG, OPT, and TKEY.
1228 if (rdtype == dns_rdatatype_tsig) {
1230 * If it is a tsig, verify that it is in the
1231 * additional data section.
1233 if (sectionid != DNS_SECTION_ADDITIONAL ||
1234 rdclass != dns_rdataclass_any ||
1235 count != msg->counts[sectionid] - 1)
1237 msg->sigstart = recstart;
1238 skip_name_search = ISC_TRUE;
1239 skip_type_search = ISC_TRUE;
1240 } else if (rdtype == dns_rdatatype_opt) {
1242 * The name of an OPT record must be ".", it
1243 * must be in the additional data section, and
1244 * it must be the first OPT we've seen.
1246 if (!dns_name_equal(dns_rootname, name) ||
1249 skip_name_search = ISC_TRUE;
1250 skip_type_search = ISC_TRUE;
1251 } else if (rdtype == dns_rdatatype_tkey) {
1253 * A TKEY must be in the additional section if this
1254 * is a query, and the answer section if this is a
1255 * response. Unless it's a Win2000 client.
1257 * Its class is ignored.
1259 dns_section_t tkeysection;
1261 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1262 tkeysection = DNS_SECTION_ADDITIONAL;
1264 tkeysection = DNS_SECTION_ANSWER;
1265 if (sectionid != tkeysection &&
1266 sectionid != DNS_SECTION_ANSWER)
1271 * ... now get ttl and rdatalen, and check buffer.
1273 ttl = isc_buffer_getuint32(source);
1274 rdatalen = isc_buffer_getuint16(source);
1275 r.length -= (2 + 2 + 4 + 2);
1276 if (r.length < rdatalen) {
1277 result = ISC_R_UNEXPECTEDEND;
1282 * Read the rdata from the wire format. Interpret the
1283 * rdata according to its actual class, even if it had a
1284 * DynDNS meta-class in the packet (unless this is a TSIG).
1285 * Then put the meta-class back into the finished rdata.
1287 rdata = newrdata(msg);
1288 if (rdata == NULL) {
1289 result = ISC_R_NOMEMORY;
1292 if (msg->opcode == dns_opcode_update &&
1293 update(sectionid, rdclass)) {
1294 if (rdatalen != 0) {
1295 result = DNS_R_FORMERR;
1299 * When the rdata is empty, the data pointer is
1300 * never dereferenced, but it must still be non-NULL.
1301 * Casting 1 rather than "" avoids warnings about
1302 * discarding the const attribute of a string,
1303 * for compilers that would warn about such things.
1305 rdata->data = (unsigned char *)1;
1307 rdata->rdclass = rdclass;
1308 rdata->type = rdtype;
1309 rdata->flags = DNS_RDATA_UPDATE;
1310 result = ISC_R_SUCCESS;
1312 result = getrdata(source, msg, dctx, rdclass,
1313 rdtype, rdatalen, rdata);
1314 if (result != ISC_R_SUCCESS)
1316 rdata->rdclass = rdclass;
1317 issigzero = ISC_FALSE;
1318 if (rdtype == dns_rdatatype_rrsig &&
1319 rdata->flags == 0) {
1320 covers = dns_rdata_covers(rdata);
1323 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
1324 rdata->flags == 0) {
1325 covers = dns_rdata_covers(rdata);
1327 if (sectionid != DNS_SECTION_ADDITIONAL ||
1328 count != msg->counts[sectionid] - 1)
1330 msg->sigstart = recstart;
1331 skip_name_search = ISC_TRUE;
1332 skip_type_search = ISC_TRUE;
1333 issigzero = ISC_TRUE;
1339 * If we are doing a dynamic update or this is a meta-type,
1340 * don't bother searching for a name, just append this one
1341 * to the end of the message.
1343 if (preserve_order || msg->opcode == dns_opcode_update ||
1345 if (rdtype != dns_rdatatype_opt &&
1346 rdtype != dns_rdatatype_tsig &&
1349 ISC_LIST_APPEND(*section, name, link);
1350 free_name = ISC_FALSE;
1354 * Run through the section, looking to see if this name
1355 * is already there. If it is found, put back the
1356 * allocated name since we no longer need it, and set
1357 * our name pointer to point to the name we found.
1359 result = findname(&name2, name, section);
1362 * If it is a new name, append to the section.
1364 if (result == ISC_R_SUCCESS) {
1365 isc_mempool_put(msg->namepool, name);
1368 ISC_LIST_APPEND(*section, name, link);
1370 free_name = ISC_FALSE;
1374 * Search name for the particular type and class.
1375 * Skip this stage if in update mode or this is a meta-type.
1377 if (preserve_order || msg->opcode == dns_opcode_update ||
1379 result = ISC_R_NOTFOUND;
1382 * If this is a type that can only occur in
1383 * the question section, fail.
1385 if (dns_rdatatype_questiononly(rdtype))
1389 result = dns_message_find(name, rdclass, rdtype,
1394 * If we found an rdataset that matches, we need to
1395 * append this rdata to that set. If we did not, we need
1396 * to create a new rdatalist, store the important bits there,
1397 * convert it to an rdataset, and link the latter to the name.
1398 * Yuck. When appending, make certain that the type isn't
1399 * a singleton type, such as SOA or CNAME.
1401 * Note that this check will be bypassed when preserving order,
1402 * the opcode is an update, or the type search is skipped.
1404 if (result == ISC_R_SUCCESS) {
1405 if (dns_rdatatype_issingleton(rdtype))
1409 if (result == ISC_R_NOTFOUND) {
1410 rdataset = isc_mempool_get(msg->rdspool);
1411 if (rdataset == NULL) {
1412 result = ISC_R_NOMEMORY;
1415 free_rdataset = ISC_TRUE;
1417 rdatalist = newrdatalist(msg);
1418 if (rdatalist == NULL) {
1419 result = ISC_R_NOMEMORY;
1423 rdatalist->type = rdtype;
1424 rdatalist->covers = covers;
1425 rdatalist->rdclass = rdclass;
1426 rdatalist->ttl = ttl;
1427 ISC_LIST_INIT(rdatalist->rdata);
1429 dns_rdataset_init(rdataset);
1430 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
1434 if (rdtype != dns_rdatatype_opt &&
1435 rdtype != dns_rdatatype_tsig &&
1438 ISC_LIST_APPEND(name->list, rdataset, link);
1439 free_rdataset = ISC_FALSE;
1446 * Section 5.2 of RFC2181 says we should drop
1447 * nonauthoritative rrsets where the TTLs differ, but we
1448 * currently treat them the as if they were authoritative and
1451 if (ttl != rdataset->ttl) {
1452 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1453 if (ttl < rdataset->ttl)
1454 rdataset->ttl = ttl;
1458 * XXXMLG Perform a totally ugly hack here to pull
1459 * the rdatalist out of the private field in the rdataset,
1460 * and append this rdata to the rdatalist's linked list
1463 rdatalist = (dns_rdatalist_t *)(rdataset->private1);
1465 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1468 * If this is an OPT record, remember it. Also, set
1469 * the extended rcode. Note that msg->opt will only be set
1470 * if best-effort parsing is enabled.
1472 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1475 msg->opt = rdataset;
1477 free_rdataset = ISC_FALSE;
1478 ercode = (dns_rcode_t)
1479 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1481 msg->rcode |= ercode;
1482 isc_mempool_put(msg->namepool, name);
1483 free_name = ISC_FALSE;
1487 * If this is an SIG(0) or TSIG record, remember it. Note
1488 * that msg->sig0 or msg->tsig will only be set if best-effort
1489 * parsing is enabled.
1491 if (issigzero && msg->sig0 == NULL) {
1492 msg->sig0 = rdataset;
1493 msg->sig0name = name;
1495 free_rdataset = ISC_FALSE;
1496 free_name = ISC_FALSE;
1497 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1498 msg->tsig = rdataset;
1499 msg->tsigname = name;
1501 free_rdataset = ISC_FALSE;
1502 free_name = ISC_FALSE;
1507 isc_mempool_put(msg->namepool, name);
1509 isc_mempool_put(msg->rdspool, rdataset);
1510 free_name = free_rdataset = ISC_FALSE;
1512 INSIST(free_name == ISC_FALSE);
1513 INSIST(free_rdataset == ISC_FALSE);
1517 return (DNS_R_RECOVERABLE);
1518 return (ISC_R_SUCCESS);
1522 isc_mempool_put(msg->namepool, name);
1524 isc_mempool_put(msg->rdspool, rdataset);
1530 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1531 unsigned int options)
1534 dns_decompress_t dctx;
1536 isc_uint16_t tmpflags;
1537 isc_buffer_t origsource;
1538 isc_boolean_t seen_problem;
1539 isc_boolean_t ignore_tc;
1541 REQUIRE(DNS_MESSAGE_VALID(msg));
1542 REQUIRE(source != NULL);
1543 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1545 seen_problem = ISC_FALSE;
1546 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1548 origsource = *source;
1551 msg->question_ok = 0;
1553 isc_buffer_remainingregion(source, &r);
1554 if (r.length < DNS_MESSAGE_HEADERLEN)
1555 return (ISC_R_UNEXPECTEDEND);
1557 msg->id = isc_buffer_getuint16(source);
1558 tmpflags = isc_buffer_getuint16(source);
1559 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1560 >> DNS_MESSAGE_OPCODE_SHIFT);
1561 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1562 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1563 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1564 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1565 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1566 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1573 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1575 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1577 ret = getquestions(source, msg, &dctx, options);
1578 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1580 if (ret == DNS_R_RECOVERABLE) {
1581 seen_problem = ISC_TRUE;
1582 ret = ISC_R_SUCCESS;
1584 if (ret != ISC_R_SUCCESS)
1586 msg->question_ok = 1;
1588 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1589 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1591 if (ret == DNS_R_RECOVERABLE) {
1592 seen_problem = ISC_TRUE;
1593 ret = ISC_R_SUCCESS;
1595 if (ret != ISC_R_SUCCESS)
1598 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1599 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1601 if (ret == DNS_R_RECOVERABLE) {
1602 seen_problem = ISC_TRUE;
1603 ret = ISC_R_SUCCESS;
1605 if (ret != ISC_R_SUCCESS)
1608 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1609 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1611 if (ret == DNS_R_RECOVERABLE) {
1612 seen_problem = ISC_TRUE;
1613 ret = ISC_R_SUCCESS;
1615 if (ret != ISC_R_SUCCESS)
1618 isc_buffer_remainingregion(source, &r);
1619 if (r.length != 0) {
1620 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1621 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
1622 "message has %u byte(s) of trailing garbage",
1627 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1628 isc_buffer_usedregion(&origsource, &msg->saved);
1630 msg->saved.length = isc_buffer_usedlength(&origsource);
1631 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1632 if (msg->saved.base == NULL)
1633 return (ISC_R_NOMEMORY);
1634 memcpy(msg->saved.base, isc_buffer_base(&origsource),
1636 msg->free_saved = 1;
1639 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1640 return (DNS_R_RECOVERABLE);
1641 if (seen_problem == ISC_TRUE)
1642 return (DNS_R_RECOVERABLE);
1643 return (ISC_R_SUCCESS);
1647 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1648 isc_buffer_t *buffer)
1652 REQUIRE(DNS_MESSAGE_VALID(msg));
1653 REQUIRE(buffer != NULL);
1654 REQUIRE(msg->buffer == NULL);
1655 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1660 * Erase the contents of this buffer.
1662 isc_buffer_clear(buffer);
1665 * Make certain there is enough for at least the header in this
1668 isc_buffer_availableregion(buffer, &r);
1669 if (r.length < DNS_MESSAGE_HEADERLEN)
1670 return (ISC_R_NOSPACE);
1672 if (r.length < msg->reserved)
1673 return (ISC_R_NOSPACE);
1676 * Reserve enough space for the header in this buffer.
1678 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1680 msg->buffer = buffer;
1682 return (ISC_R_SUCCESS);
1686 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1689 REQUIRE(DNS_MESSAGE_VALID(msg));
1690 REQUIRE(buffer != NULL);
1691 REQUIRE(msg->buffer != NULL);
1694 * Ensure that the new buffer is empty, and has enough space to
1695 * hold the current contents.
1697 isc_buffer_clear(buffer);
1699 isc_buffer_availableregion(buffer, &rn);
1700 isc_buffer_usedregion(msg->buffer, &r);
1701 REQUIRE(rn.length > r.length);
1704 * Copy the contents from the old to the new buffer.
1706 isc_buffer_add(buffer, r.length);
1707 memcpy(rn.base, r.base, r.length);
1709 msg->buffer = buffer;
1711 return (ISC_R_SUCCESS);
1715 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1716 REQUIRE(DNS_MESSAGE_VALID(msg));
1717 REQUIRE(space <= msg->reserved);
1719 msg->reserved -= space;
1723 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1726 REQUIRE(DNS_MESSAGE_VALID(msg));
1728 if (msg->buffer != NULL) {
1729 isc_buffer_availableregion(msg->buffer, &r);
1730 if (r.length < (space + msg->reserved))
1731 return (ISC_R_NOSPACE);
1734 msg->reserved += space;
1736 return (ISC_R_SUCCESS);
1739 static inline isc_boolean_t
1740 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
1744 * If we are not rendering class IN, this ordering is bogus.
1746 if (rds->rdclass != dns_rdataclass_in)
1749 switch (rds->type) {
1750 case dns_rdatatype_a:
1751 case dns_rdatatype_aaaa:
1752 if (preferred_glue == rds->type)
1757 case dns_rdatatype_rrsig:
1758 case dns_rdatatype_dnskey:
1765 if (pass_needed >= pass)
1772 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1773 unsigned int options)
1775 dns_namelist_t *section;
1776 dns_name_t *name, *next_name;
1777 dns_rdataset_t *rdataset, *next_rdataset;
1778 unsigned int count, total;
1779 isc_result_t result;
1780 isc_buffer_t st; /* for rollbacks */
1782 isc_boolean_t partial = ISC_FALSE;
1783 unsigned int rd_options;
1784 dns_rdatatype_t preferred_glue = 0;
1786 REQUIRE(DNS_MESSAGE_VALID(msg));
1787 REQUIRE(msg->buffer != NULL);
1788 REQUIRE(VALID_NAMED_SECTION(sectionid));
1790 section = &msg->sections[sectionid];
1792 if ((sectionid == DNS_SECTION_ADDITIONAL)
1793 && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
1794 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
1795 preferred_glue = dns_rdatatype_a;
1797 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
1798 preferred_glue = dns_rdatatype_aaaa;
1805 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
1808 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
1811 * Shrink the space in the buffer by the reserved amount.
1813 msg->buffer->length -= msg->reserved;
1816 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1820 * Render required glue first. Set TC if it won't fit.
1822 name = ISC_LIST_HEAD(*section);
1824 rdataset = ISC_LIST_HEAD(name->list);
1825 if (rdataset != NULL &&
1826 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
1827 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
1828 const void *order_arg = msg->order_arg;
1829 st = *(msg->buffer);
1832 result = dns_rdataset_towirepartial(rdataset,
1842 result = dns_rdataset_towiresorted(rdataset,
1851 if (partial && result == ISC_R_NOSPACE) {
1852 msg->flags |= DNS_MESSAGEFLAG_TC;
1853 msg->buffer->length += msg->reserved;
1854 msg->counts[sectionid] += total;
1857 if (result != ISC_R_SUCCESS) {
1858 INSIST(st.used < 65536);
1859 dns_compress_rollback(msg->cctx,
1860 (isc_uint16_t)st.used);
1861 *(msg->buffer) = st; /* rollback */
1862 msg->buffer->length += msg->reserved;
1863 msg->counts[sectionid] += total;
1866 rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
1871 name = ISC_LIST_HEAD(*section);
1873 msg->buffer->length += msg->reserved;
1874 msg->counts[sectionid] += total;
1875 return (ISC_R_SUCCESS);
1878 while (name != NULL) {
1879 next_name = ISC_LIST_NEXT(name, link);
1881 rdataset = ISC_LIST_HEAD(name->list);
1882 while (rdataset != NULL) {
1883 next_rdataset = ISC_LIST_NEXT(rdataset, link);
1885 if ((rdataset->attributes &
1886 DNS_RDATASETATTR_RENDERED) != 0)
1889 if (((options & DNS_MESSAGERENDER_ORDERED)
1891 && (sectionid == DNS_SECTION_ADDITIONAL)
1892 && wrong_priority(rdataset, pass,
1896 st = *(msg->buffer);
1900 result = dns_rdataset_towirepartial(
1911 result = dns_rdataset_towiresorted(
1924 * If out of space, record stats on what we
1925 * rendered so far, and return that status.
1927 * XXXMLG Need to change this when
1928 * dns_rdataset_towire() can render partial
1929 * sets starting at some arbitary point in the
1930 * set. This will include setting a bit in the
1931 * rdataset to indicate that a partial
1932 * rendering was done, and some state saved
1933 * somewhere (probably in the message struct)
1934 * to indicate where to continue from.
1936 if (partial && result == ISC_R_NOSPACE) {
1937 msg->buffer->length += msg->reserved;
1938 msg->counts[sectionid] += total;
1941 if (result != ISC_R_SUCCESS) {
1942 INSIST(st.used < 65536);
1943 dns_compress_rollback(msg->cctx,
1944 (isc_uint16_t)st.used);
1945 *(msg->buffer) = st; /* rollback */
1946 msg->buffer->length += msg->reserved;
1947 msg->counts[sectionid] += total;
1952 * If we have rendered non-validated data,
1953 * ensure that the AD bit is not set.
1955 if (rdataset->trust != dns_trust_secure &&
1956 (sectionid == DNS_SECTION_ANSWER ||
1957 sectionid == DNS_SECTION_AUTHORITY))
1958 msg->flags &= ~DNS_MESSAGEFLAG_AD;
1960 rdataset->attributes |=
1961 DNS_RDATASETATTR_RENDERED;
1964 rdataset = next_rdataset;
1969 } while (--pass != 0);
1971 msg->buffer->length += msg->reserved;
1972 msg->counts[sectionid] += total;
1974 return (ISC_R_SUCCESS);
1978 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
1982 REQUIRE(DNS_MESSAGE_VALID(msg));
1983 REQUIRE(target != NULL);
1985 isc_buffer_availableregion(target, &r);
1986 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
1988 isc_buffer_putuint16(target, msg->id);
1990 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
1991 & DNS_MESSAGE_OPCODE_MASK);
1992 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
1993 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
1995 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
1996 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
1997 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
1998 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
2000 isc_buffer_putuint16(target, tmp);
2001 isc_buffer_putuint16(target,
2002 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
2003 isc_buffer_putuint16(target,
2004 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
2005 isc_buffer_putuint16(target,
2006 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2007 isc_buffer_putuint16(target,
2008 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
2012 dns_message_renderend(dns_message_t *msg) {
2013 isc_buffer_t tmpbuf;
2018 REQUIRE(DNS_MESSAGE_VALID(msg));
2019 REQUIRE(msg->buffer != NULL);
2021 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
2023 * We have an extended rcode but are not using EDNS.
2025 return (DNS_R_FORMERR);
2029 * If we've got an OPT record, render it.
2031 if (msg->opt != NULL) {
2032 dns_message_renderrelease(msg, msg->opt_reserved);
2033 msg->opt_reserved = 0;
2035 * Set the extended rcode.
2037 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
2038 msg->opt->ttl |= ((msg->rcode << 20) &
2039 DNS_MESSAGE_EDNSRCODE_MASK);
2044 result = dns_rdataset_towire(msg->opt, dns_rootname,
2045 msg->cctx, msg->buffer, 0,
2047 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2048 if (result != ISC_R_SUCCESS)
2053 * If we're adding a TSIG or SIG(0) to a truncated message,
2054 * clear all rdatasets from the message except for the question
2055 * before adding the TSIG or SIG(0). If the question doesn't fit,
2058 if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
2059 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2063 msgresetnames(msg, DNS_SECTION_ANSWER);
2065 dns_message_renderreset(msg);
2067 isc_buffer_clear(msg->buffer);
2068 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
2069 dns_compress_rollback(msg->cctx, 0);
2070 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
2072 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
2077 * If we're adding a TSIG record, generate and render it.
2079 if (msg->tsigkey != NULL) {
2080 dns_message_renderrelease(msg, msg->sig_reserved);
2081 msg->sig_reserved = 0;
2082 result = dns_tsig_sign(msg);
2083 if (result != ISC_R_SUCCESS)
2086 result = dns_rdataset_towire(msg->tsig, msg->tsigname,
2087 msg->cctx, msg->buffer, 0,
2089 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2090 if (result != ISC_R_SUCCESS)
2095 * If we're adding a SIG(0) record, generate and render it.
2097 if (msg->sig0key != NULL) {
2098 dns_message_renderrelease(msg, msg->sig_reserved);
2099 msg->sig_reserved = 0;
2100 result = dns_dnssec_signmessage(msg, msg->sig0key);
2101 if (result != ISC_R_SUCCESS)
2105 * Note: dns_rootname is used here, not msg->sig0name, since
2106 * the owner name of a SIG(0) is irrelevant, and will not
2107 * be set in a message being rendered.
2109 result = dns_rdataset_towire(msg->sig0, dns_rootname,
2110 msg->cctx, msg->buffer, 0,
2112 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2113 if (result != ISC_R_SUCCESS)
2117 isc_buffer_usedregion(msg->buffer, &r);
2118 isc_buffer_init(&tmpbuf, r.base, r.length);
2120 dns_message_renderheader(msg, &tmpbuf);
2122 msg->buffer = NULL; /* forget about this buffer only on success XXX */
2124 return (ISC_R_SUCCESS);
2128 dns_message_renderreset(dns_message_t *msg) {
2131 dns_rdataset_t *rds;
2134 * Reset the message so that it may be rendered again.
2137 REQUIRE(DNS_MESSAGE_VALID(msg));
2138 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2142 for (i = 0; i < DNS_SECTION_MAX; i++) {
2143 msg->cursors[i] = NULL;
2145 for (name = ISC_LIST_HEAD(msg->sections[i]);
2147 name = ISC_LIST_NEXT(name, link)) {
2148 for (rds = ISC_LIST_HEAD(name->list);
2150 rds = ISC_LIST_NEXT(rds, link)) {
2151 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2155 if (msg->tsigname != NULL)
2156 dns_message_puttempname(msg, &msg->tsigname);
2157 if (msg->tsig != NULL) {
2158 dns_rdataset_disassociate(msg->tsig);
2159 dns_message_puttemprdataset(msg, &msg->tsig);
2161 if (msg->sig0 != NULL) {
2162 dns_rdataset_disassociate(msg->sig0);
2163 dns_message_puttemprdataset(msg, &msg->sig0);
2168 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2169 REQUIRE(DNS_MESSAGE_VALID(msg));
2170 REQUIRE(VALID_NAMED_SECTION(section));
2172 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2174 if (msg->cursors[section] == NULL)
2175 return (ISC_R_NOMORE);
2177 return (ISC_R_SUCCESS);
2181 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2182 REQUIRE(DNS_MESSAGE_VALID(msg));
2183 REQUIRE(VALID_NAMED_SECTION(section));
2184 REQUIRE(msg->cursors[section] != NULL);
2186 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2188 if (msg->cursors[section] == NULL)
2189 return (ISC_R_NOMORE);
2191 return (ISC_R_SUCCESS);
2195 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2198 REQUIRE(DNS_MESSAGE_VALID(msg));
2199 REQUIRE(VALID_NAMED_SECTION(section));
2200 REQUIRE(name != NULL && *name == NULL);
2201 REQUIRE(msg->cursors[section] != NULL);
2203 *name = msg->cursors[section];
2207 dns_message_findname(dns_message_t *msg, dns_section_t section,
2208 dns_name_t *target, dns_rdatatype_t type,
2209 dns_rdatatype_t covers, dns_name_t **name,
2210 dns_rdataset_t **rdataset)
2212 dns_name_t *foundname;
2213 isc_result_t result;
2216 * XXX These requirements are probably too intensive, especially
2217 * where things can be NULL, but as they are they ensure that if
2218 * something is NON-NULL, indicating that the caller expects it
2219 * to be filled in, that we can in fact fill it in.
2221 REQUIRE(msg != NULL);
2222 REQUIRE(VALID_SECTION(section));
2223 REQUIRE(target != NULL);
2225 REQUIRE(*name == NULL);
2226 if (type == dns_rdatatype_any) {
2227 REQUIRE(rdataset == NULL);
2229 if (rdataset != NULL)
2230 REQUIRE(*rdataset == NULL);
2233 result = findname(&foundname, target,
2234 &msg->sections[section]);
2236 if (result == ISC_R_NOTFOUND)
2237 return (DNS_R_NXDOMAIN);
2238 else if (result != ISC_R_SUCCESS)
2245 * And now look for the type.
2247 if (type == dns_rdatatype_any)
2248 return (ISC_R_SUCCESS);
2250 result = dns_message_findtype(foundname, type, covers, rdataset);
2251 if (result == ISC_R_NOTFOUND)
2252 return (DNS_R_NXRRSET);
2258 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2259 dns_section_t fromsection,
2260 dns_section_t tosection)
2262 REQUIRE(msg != NULL);
2263 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2264 REQUIRE(name != NULL);
2265 REQUIRE(VALID_NAMED_SECTION(fromsection));
2266 REQUIRE(VALID_NAMED_SECTION(tosection));
2269 * Unlink the name from the old section
2271 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2272 ISC_LIST_APPEND(msg->sections[tosection], name, link);
2276 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2277 dns_section_t section)
2279 REQUIRE(msg != NULL);
2280 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2281 REQUIRE(name != NULL);
2282 REQUIRE(VALID_NAMED_SECTION(section));
2284 ISC_LIST_APPEND(msg->sections[section], name, link);
2288 dns_message_removename(dns_message_t *msg, dns_name_t *name,
2289 dns_section_t section)
2291 REQUIRE(msg != NULL);
2292 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2293 REQUIRE(name != NULL);
2294 REQUIRE(VALID_NAMED_SECTION(section));
2296 ISC_LIST_UNLINK(msg->sections[section], name, link);
2300 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2301 REQUIRE(DNS_MESSAGE_VALID(msg));
2302 REQUIRE(item != NULL && *item == NULL);
2304 *item = isc_mempool_get(msg->namepool);
2306 return (ISC_R_NOMEMORY);
2307 dns_name_init(*item, NULL);
2309 return (ISC_R_SUCCESS);
2313 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2314 REQUIRE(DNS_MESSAGE_VALID(msg));
2315 REQUIRE(item != NULL && *item == NULL);
2317 *item = newoffsets(msg);
2319 return (ISC_R_NOMEMORY);
2321 return (ISC_R_SUCCESS);
2325 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2326 REQUIRE(DNS_MESSAGE_VALID(msg));
2327 REQUIRE(item != NULL && *item == NULL);
2329 *item = newrdata(msg);
2331 return (ISC_R_NOMEMORY);
2333 return (ISC_R_SUCCESS);
2337 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2338 REQUIRE(DNS_MESSAGE_VALID(msg));
2339 REQUIRE(item != NULL && *item == NULL);
2341 *item = isc_mempool_get(msg->rdspool);
2343 return (ISC_R_NOMEMORY);
2345 dns_rdataset_init(*item);
2347 return (ISC_R_SUCCESS);
2351 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2352 REQUIRE(DNS_MESSAGE_VALID(msg));
2353 REQUIRE(item != NULL && *item == NULL);
2355 *item = newrdatalist(msg);
2357 return (ISC_R_NOMEMORY);
2359 return (ISC_R_SUCCESS);
2363 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2364 REQUIRE(DNS_MESSAGE_VALID(msg));
2365 REQUIRE(item != NULL && *item != NULL);
2367 if (dns_name_dynamic(*item))
2368 dns_name_free(*item, msg->mctx);
2369 isc_mempool_put(msg->namepool, *item);
2374 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2375 REQUIRE(DNS_MESSAGE_VALID(msg));
2376 REQUIRE(item != NULL && *item != NULL);
2378 releaserdata(msg, *item);
2383 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2384 REQUIRE(DNS_MESSAGE_VALID(msg));
2385 REQUIRE(item != NULL && *item != NULL);
2387 REQUIRE(!dns_rdataset_isassociated(*item));
2388 isc_mempool_put(msg->rdspool, *item);
2393 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2394 REQUIRE(DNS_MESSAGE_VALID(msg));
2395 REQUIRE(item != NULL && *item != NULL);
2397 releaserdatalist(msg, *item);
2402 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2403 unsigned int *flagsp)
2406 isc_buffer_t buffer;
2410 REQUIRE(source != NULL);
2414 isc_buffer_remainingregion(&buffer, &r);
2415 if (r.length < DNS_MESSAGE_HEADERLEN)
2416 return (ISC_R_UNEXPECTEDEND);
2418 id = isc_buffer_getuint16(&buffer);
2419 flags = isc_buffer_getuint16(&buffer);
2420 flags &= DNS_MESSAGE_FLAG_MASK;
2427 return (ISC_R_SUCCESS);
2431 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2432 unsigned int first_section;
2433 isc_result_t result;
2435 REQUIRE(DNS_MESSAGE_VALID(msg));
2436 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2438 if (!msg->header_ok)
2439 return (DNS_R_FORMERR);
2440 if (msg->opcode != dns_opcode_query &&
2441 msg->opcode != dns_opcode_notify)
2442 want_question_section = ISC_FALSE;
2443 if (want_question_section) {
2444 if (!msg->question_ok)
2445 return (DNS_R_FORMERR);
2446 first_section = DNS_SECTION_ANSWER;
2448 first_section = DNS_SECTION_QUESTION;
2449 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2450 msgresetnames(msg, first_section);
2452 msgresetsigs(msg, ISC_TRUE);
2453 msginitprivate(msg);
2455 * We now clear most flags and then set QR, ensuring that the
2456 * reply's flags will be in a reasonable state.
2458 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2459 msg->flags |= DNS_MESSAGEFLAG_QR;
2462 * This saves the query TSIG status, if the query was signed, and
2463 * reserves space in the reply for the TSIG.
2465 if (msg->tsigkey != NULL) {
2466 unsigned int otherlen = 0;
2467 msg->querytsigstatus = msg->tsigstatus;
2468 msg->tsigstatus = dns_rcode_noerror;
2469 if (msg->querytsigstatus == dns_tsigerror_badtime)
2471 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2472 result = dns_message_renderreserve(msg, msg->sig_reserved);
2473 if (result != ISC_R_SUCCESS) {
2474 msg->sig_reserved = 0;
2478 if (msg->saved.base != NULL) {
2479 msg->query.base = msg->saved.base;
2480 msg->query.length = msg->saved.length;
2481 msg->free_query = msg->free_saved;
2482 msg->saved.base = NULL;
2483 msg->saved.length = 0;
2484 msg->free_saved = 0;
2487 return (ISC_R_SUCCESS);
2491 dns_message_getopt(dns_message_t *msg) {
2494 * Get the OPT record for 'msg'.
2497 REQUIRE(DNS_MESSAGE_VALID(msg));
2503 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2504 isc_result_t result;
2505 dns_rdata_t rdata = DNS_RDATA_INIT;
2508 * Set the OPT record for 'msg'.
2512 * The space required for an OPT record is:
2514 * 1 byte for the name
2515 * 2 bytes for the type
2516 * 2 bytes for the class
2517 * 4 bytes for the ttl
2518 * 2 bytes for the rdata length
2519 * ---------------------------------
2522 * plus the length of the rdata.
2525 REQUIRE(DNS_MESSAGE_VALID(msg));
2526 REQUIRE(opt->type == dns_rdatatype_opt);
2527 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2528 REQUIRE(msg->state == DNS_SECTION_ANY);
2532 result = dns_rdataset_first(opt);
2533 if (result != ISC_R_SUCCESS)
2535 dns_rdataset_current(opt, &rdata);
2536 msg->opt_reserved = 11 + rdata.length;
2537 result = dns_message_renderreserve(msg, msg->opt_reserved);
2538 if (result != ISC_R_SUCCESS) {
2539 msg->opt_reserved = 0;
2545 return (ISC_R_SUCCESS);
2548 dns_message_puttemprdataset(msg, &opt);
2554 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2557 * Get the TSIG record and owner for 'msg'.
2560 REQUIRE(DNS_MESSAGE_VALID(msg));
2561 REQUIRE(owner == NULL || *owner == NULL);
2564 *owner = msg->tsigname;
2569 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2570 isc_result_t result;
2573 * Set the TSIG key for 'msg'
2576 REQUIRE(DNS_MESSAGE_VALID(msg));
2577 REQUIRE(msg->state == DNS_SECTION_ANY);
2579 if (key == NULL && msg->tsigkey != NULL) {
2580 if (msg->sig_reserved != 0) {
2581 dns_message_renderrelease(msg, msg->sig_reserved);
2582 msg->sig_reserved = 0;
2584 dns_tsigkey_detach(&msg->tsigkey);
2587 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
2588 dns_tsigkey_attach(key, &msg->tsigkey);
2589 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2590 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2591 result = dns_message_renderreserve(msg,
2593 if (result != ISC_R_SUCCESS) {
2594 dns_tsigkey_detach(&msg->tsigkey);
2595 msg->sig_reserved = 0;
2600 return (ISC_R_SUCCESS);
2604 dns_message_gettsigkey(dns_message_t *msg) {
2607 * Get the TSIG key for 'msg'
2610 REQUIRE(DNS_MESSAGE_VALID(msg));
2612 return (msg->tsigkey);
2616 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2617 dns_rdata_t *rdata = NULL;
2618 dns_rdatalist_t *list = NULL;
2619 dns_rdataset_t *set = NULL;
2620 isc_buffer_t *buf = NULL;
2622 isc_result_t result;
2624 REQUIRE(DNS_MESSAGE_VALID(msg));
2625 REQUIRE(msg->querytsig == NULL);
2627 if (querytsig == NULL)
2628 return (ISC_R_SUCCESS);
2630 result = dns_message_gettemprdata(msg, &rdata);
2631 if (result != ISC_R_SUCCESS)
2634 result = dns_message_gettemprdatalist(msg, &list);
2635 if (result != ISC_R_SUCCESS)
2637 result = dns_message_gettemprdataset(msg, &set);
2638 if (result != ISC_R_SUCCESS)
2641 isc_buffer_usedregion(querytsig, &r);
2642 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2643 if (result != ISC_R_SUCCESS)
2645 isc_buffer_putmem(buf, r.base, r.length);
2646 isc_buffer_usedregion(buf, &r);
2647 dns_rdata_init(rdata);
2648 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2649 dns_message_takebuffer(msg, &buf);
2650 ISC_LIST_INIT(list->rdata);
2651 ISC_LIST_APPEND(list->rdata, rdata, link);
2652 result = dns_rdatalist_tordataset(list, set);
2653 if (result != ISC_R_SUCCESS)
2656 msg->querytsig = set;
2662 dns_message_puttemprdata(msg, &rdata);
2664 dns_message_puttemprdatalist(msg, &list);
2666 dns_message_puttemprdataset(msg, &set);
2667 return (ISC_R_NOMEMORY);
2671 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2672 isc_buffer_t **querytsig) {
2673 isc_result_t result;
2674 dns_rdata_t rdata = DNS_RDATA_INIT;
2677 REQUIRE(DNS_MESSAGE_VALID(msg));
2678 REQUIRE(mctx != NULL);
2679 REQUIRE(querytsig != NULL && *querytsig == NULL);
2681 if (msg->tsig == NULL)
2682 return (ISC_R_SUCCESS);
2684 result = dns_rdataset_first(msg->tsig);
2685 if (result != ISC_R_SUCCESS)
2687 dns_rdataset_current(msg->tsig, &rdata);
2688 dns_rdata_toregion(&rdata, &r);
2690 result = isc_buffer_allocate(mctx, querytsig, r.length);
2691 if (result != ISC_R_SUCCESS)
2693 isc_buffer_putmem(*querytsig, r.base, r.length);
2694 return (ISC_R_SUCCESS);
2698 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2701 * Get the SIG(0) record for 'msg'.
2704 REQUIRE(DNS_MESSAGE_VALID(msg));
2705 REQUIRE(owner == NULL || *owner == NULL);
2707 if (msg->sig0 != NULL && owner != NULL) {
2708 /* If dns_message_getsig0 is called on a rendered message
2709 * after the SIG(0) has been applied, we need to return the
2710 * root name, not NULL.
2712 if (msg->sig0name == NULL)
2713 *owner = dns_rootname;
2715 *owner = msg->sig0name;
2721 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2724 isc_result_t result;
2727 * Set the SIG(0) key for 'msg'
2731 * The space required for an SIG(0) record is:
2733 * 1 byte for the name
2734 * 2 bytes for the type
2735 * 2 bytes for the class
2736 * 4 bytes for the ttl
2737 * 2 bytes for the type covered
2738 * 1 byte for the algorithm
2739 * 1 bytes for the labels
2740 * 4 bytes for the original ttl
2741 * 4 bytes for the signature expiration
2742 * 4 bytes for the signature inception
2743 * 2 bytes for the key tag
2744 * n bytes for the signer's name
2745 * x bytes for the signature
2746 * ---------------------------------
2749 REQUIRE(DNS_MESSAGE_VALID(msg));
2750 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2751 REQUIRE(msg->state == DNS_SECTION_ANY);
2754 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
2755 dns_name_toregion(dst_key_name(key), &r);
2756 result = dst_key_sigsize(key, &x);
2757 if (result != ISC_R_SUCCESS) {
2758 msg->sig_reserved = 0;
2761 msg->sig_reserved = 27 + r.length + x;
2762 result = dns_message_renderreserve(msg, msg->sig_reserved);
2763 if (result != ISC_R_SUCCESS) {
2764 msg->sig_reserved = 0;
2769 return (ISC_R_SUCCESS);
2773 dns_message_getsig0key(dns_message_t *msg) {
2776 * Get the SIG(0) key for 'msg'
2779 REQUIRE(DNS_MESSAGE_VALID(msg));
2781 return (msg->sig0key);
2785 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2786 REQUIRE(DNS_MESSAGE_VALID(msg));
2787 REQUIRE(buffer != NULL);
2788 REQUIRE(ISC_BUFFER_VALID(*buffer));
2790 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2795 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2796 isc_result_t result = ISC_R_SUCCESS;
2797 dns_rdata_t rdata = DNS_RDATA_INIT;
2799 REQUIRE(DNS_MESSAGE_VALID(msg));
2800 REQUIRE(signer != NULL);
2801 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2803 if (msg->tsig == NULL && msg->sig0 == NULL)
2804 return (ISC_R_NOTFOUND);
2806 if (msg->verify_attempted == 0)
2807 return (DNS_R_NOTVERIFIEDYET);
2809 if (!dns_name_hasbuffer(signer)) {
2810 isc_buffer_t *dynbuf = NULL;
2811 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2812 if (result != ISC_R_SUCCESS)
2814 dns_name_setbuffer(signer, dynbuf);
2815 dns_message_takebuffer(msg, &dynbuf);
2818 if (msg->sig0 != NULL) {
2819 dns_rdata_sig_t sig;
2821 result = dns_rdataset_first(msg->sig0);
2822 INSIST(result == ISC_R_SUCCESS);
2823 dns_rdataset_current(msg->sig0, &rdata);
2825 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2826 if (result != ISC_R_SUCCESS)
2829 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2830 result = ISC_R_SUCCESS;
2832 result = DNS_R_SIGINVALID;
2833 dns_name_clone(&sig.signer, signer);
2834 dns_rdata_freestruct(&sig);
2836 dns_name_t *identity;
2837 dns_rdata_any_tsig_t tsig;
2839 result = dns_rdataset_first(msg->tsig);
2840 INSIST(result == ISC_R_SUCCESS);
2841 dns_rdataset_current(msg->tsig, &rdata);
2843 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2844 if (msg->tsigstatus != dns_rcode_noerror)
2845 result = DNS_R_TSIGVERIFYFAILURE;
2846 else if (tsig.error != dns_rcode_noerror)
2847 result = DNS_R_TSIGERRORSET;
2849 result = ISC_R_SUCCESS;
2850 dns_rdata_freestruct(&tsig);
2852 if (msg->tsigkey == NULL) {
2854 * If msg->tsigstatus & tsig.error are both
2855 * dns_rcode_noerror, the message must have been
2856 * verified, which means msg->tsigkey will be
2859 INSIST(result != ISC_R_SUCCESS);
2861 identity = dns_tsigkey_identity(msg->tsigkey);
2862 if (identity == NULL) {
2863 if (result == ISC_R_SUCCESS)
2864 result = DNS_R_NOIDENTITY;
2865 identity = &msg->tsigkey->name;
2867 dns_name_clone(identity, signer);
2875 dns_message_resetsig(dns_message_t *msg) {
2876 REQUIRE(DNS_MESSAGE_VALID(msg));
2877 msg->verified_sig = 0;
2878 msg->verify_attempted = 0;
2879 msg->tsigstatus = dns_rcode_noerror;
2880 msg->sig0status = dns_rcode_noerror;
2881 msg->timeadjust = 0;
2882 if (msg->tsigkey != NULL) {
2883 dns_tsigkey_detach(&msg->tsigkey);
2884 msg->tsigkey = NULL;
2889 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
2890 dns_message_resetsig(msg);
2891 return (dns_message_checksig(msg, view));
2895 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
2896 isc_buffer_t b, msgb;
2898 REQUIRE(DNS_MESSAGE_VALID(msg));
2900 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
2901 return (ISC_R_SUCCESS);
2902 INSIST(msg->saved.base != NULL);
2903 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
2904 isc_buffer_add(&msgb, msg->saved.length);
2905 if (msg->tsigkey != NULL || msg->tsig != NULL) {
2907 return (dns_view_checksig(view, &msgb, msg));
2909 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
2911 dns_rdata_t rdata = DNS_RDATA_INIT;
2912 dns_rdata_sig_t sig;
2913 dns_rdataset_t keyset;
2914 isc_result_t result;
2916 result = dns_rdataset_first(msg->sig0);
2917 INSIST(result == ISC_R_SUCCESS);
2918 dns_rdataset_current(msg->sig0, &rdata);
2921 * This can occur when the message is a dynamic update, since
2922 * the rdata length checking is relaxed. This should not
2923 * happen in a well-formed message, since the SIG(0) is only
2924 * looked for in the additional section, and the dynamic update
2925 * meta-records are in the prerequisite and update sections.
2927 if (rdata.length == 0)
2928 return (ISC_R_UNEXPECTEDEND);
2930 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
2931 if (result != ISC_R_SUCCESS)
2934 dns_rdataset_init(&keyset);
2936 return (DNS_R_KEYUNAUTHORIZED);
2937 result = dns_view_simplefind(view, &sig.signer,
2938 dns_rdatatype_key /* SIG(0) */,
2939 0, 0, ISC_FALSE, &keyset, NULL);
2941 if (result != ISC_R_SUCCESS) {
2942 /* XXXBEW Should possibly create a fetch here */
2943 result = DNS_R_KEYUNAUTHORIZED;
2945 } else if (keyset.trust < dns_trust_secure) {
2946 /* XXXBEW Should call a validator here */
2947 result = DNS_R_KEYUNAUTHORIZED;
2950 result = dns_rdataset_first(&keyset);
2951 INSIST(result == ISC_R_SUCCESS);
2953 result == ISC_R_SUCCESS;
2954 result = dns_rdataset_next(&keyset))
2956 dst_key_t *key = NULL;
2958 dns_rdataset_current(&keyset, &rdata);
2959 isc_buffer_init(&b, rdata.data, rdata.length);
2960 isc_buffer_add(&b, rdata.length);
2962 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
2963 &b, view->mctx, &key);
2964 if (result != ISC_R_SUCCESS)
2966 if (dst_key_alg(key) != sig.algorithm ||
2967 dst_key_id(key) != sig.keyid ||
2968 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
2969 dst_key_proto(key) == DNS_KEYPROTO_ANY))
2974 result = dns_dnssec_verifymessage(&msgb, msg, key);
2976 if (result == ISC_R_SUCCESS)
2979 if (result == ISC_R_NOMORE)
2980 result = DNS_R_KEYUNAUTHORIZED;
2983 if (dns_rdataset_isassociated(&keyset))
2984 dns_rdataset_disassociate(&keyset);
2985 dns_rdata_freestruct(&sig);
2991 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
2992 const dns_master_style_t *style,
2993 dns_messagetextflag_t flags,
2994 isc_buffer_t *target) {
2995 dns_name_t *name, empty_name;
2996 dns_rdataset_t *rdataset;
2997 isc_result_t result;
2999 REQUIRE(DNS_MESSAGE_VALID(msg));
3000 REQUIRE(target != NULL);
3001 REQUIRE(VALID_SECTION(section));
3003 if (ISC_LIST_EMPTY(msg->sections[section]))
3004 return (ISC_R_SUCCESS);
3006 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
3007 ADD_STRING(target, ";; ");
3008 if (msg->opcode != dns_opcode_update) {
3009 ADD_STRING(target, sectiontext[section]);
3012 ADD_STRING(target, updsectiontext[section]);
3014 ADD_STRING(target, " SECTION:\n");
3017 dns_name_init(&empty_name, NULL);
3018 result = dns_message_firstname(msg, section);
3019 if (result != ISC_R_SUCCESS) {
3024 dns_message_currentname(msg, section, &name);
3025 for (rdataset = ISC_LIST_HEAD(name->list);
3027 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3028 if (section == DNS_SECTION_QUESTION) {
3029 ADD_STRING(target, ";");
3030 result = dns_master_questiontotext(name,
3035 result = dns_master_rdatasettotext(name,
3040 if (result != ISC_R_SUCCESS)
3043 result = dns_message_nextname(msg, section);
3044 } while (result == ISC_R_SUCCESS);
3045 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3046 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3047 ADD_STRING(target, "\n");
3048 if (result == ISC_R_NOMORE)
3049 result = ISC_R_SUCCESS;
3054 dns_message_pseudosectiontotext(dns_message_t *msg,
3055 dns_pseudosection_t section,
3056 const dns_master_style_t *style,
3057 dns_messagetextflag_t flags,
3058 isc_buffer_t *target) {
3059 dns_rdataset_t *ps = NULL;
3060 dns_name_t *name = NULL;
3061 isc_result_t result;
3062 char buf[sizeof("1234567890")];
3065 REQUIRE(DNS_MESSAGE_VALID(msg));
3066 REQUIRE(target != NULL);
3067 REQUIRE(VALID_PSEUDOSECTION(section));
3070 case DNS_PSEUDOSECTION_OPT:
3071 ps = dns_message_getopt(msg);
3073 return (ISC_R_SUCCESS);
3074 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3075 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
3076 ADD_STRING(target, "; EDNS: version: ");
3077 snprintf(buf, sizeof(buf), "%u",
3078 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
3079 ADD_STRING(target, buf);
3080 ADD_STRING(target, ", flags:");
3081 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
3082 ADD_STRING(target, " do");
3083 mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff;
3085 ADD_STRING(target, "; MBZ: ");
3086 snprintf(buf, sizeof(buf), "%.4x ", mbz);
3087 ADD_STRING(target, buf);
3088 ADD_STRING(target, ", udp: ");
3090 ADD_STRING(target, "; udp: ");
3091 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
3092 ADD_STRING(target, buf);
3093 return (ISC_R_SUCCESS);
3094 case DNS_PSEUDOSECTION_TSIG:
3095 ps = dns_message_gettsig(msg, &name);
3097 return (ISC_R_SUCCESS);
3098 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3099 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
3100 result = dns_master_rdatasettotext(name, ps, style, target);
3101 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3102 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3103 ADD_STRING(target, "\n");
3105 case DNS_PSEUDOSECTION_SIG0:
3106 ps = dns_message_getsig0(msg, &name);
3108 return (ISC_R_SUCCESS);
3109 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3110 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
3111 result = dns_master_rdatasettotext(name, ps, style, target);
3112 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3113 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3114 ADD_STRING(target, "\n");
3117 return (ISC_R_UNEXPECTED);
3121 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
3122 dns_messagetextflag_t flags, isc_buffer_t *target) {
3123 char buf[sizeof("1234567890")];
3124 isc_result_t result;
3126 REQUIRE(DNS_MESSAGE_VALID(msg));
3127 REQUIRE(target != NULL);
3129 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
3130 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
3131 ADD_STRING(target, opcodetext[msg->opcode]);
3132 ADD_STRING(target, ", status: ");
3133 ADD_STRING(target, rcodetext[msg->rcode]);
3134 ADD_STRING(target, ", id: ");
3135 snprintf(buf, sizeof(buf), "%6u", msg->id);
3136 ADD_STRING(target, buf);
3137 ADD_STRING(target, "\n;; flags: ");
3138 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
3139 ADD_STRING(target, "qr ");
3140 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
3141 ADD_STRING(target, "aa ");
3142 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
3143 ADD_STRING(target, "tc ");
3144 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
3145 ADD_STRING(target, "rd ");
3146 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
3147 ADD_STRING(target, "ra ");
3148 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3149 ADD_STRING(target, "ad ");
3150 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3151 ADD_STRING(target, "cd ");
3152 if (msg->opcode != dns_opcode_update) {
3153 ADD_STRING(target, "; QUESTION: ");
3155 ADD_STRING(target, "; ZONE: ");
3157 snprintf(buf, sizeof(buf), "%1u",
3158 msg->counts[DNS_SECTION_QUESTION]);
3159 ADD_STRING(target, buf);
3160 if (msg->opcode != dns_opcode_update) {
3161 ADD_STRING(target, ", ANSWER: ");
3163 ADD_STRING(target, ", PREREQ: ");
3165 snprintf(buf, sizeof(buf), "%1u",
3166 msg->counts[DNS_SECTION_ANSWER]);
3167 ADD_STRING(target, buf);
3168 if (msg->opcode != dns_opcode_update) {
3169 ADD_STRING(target, ", AUTHORITY: ");
3171 ADD_STRING(target, ", UPDATE: ");
3173 snprintf(buf, sizeof(buf), "%1u",
3174 msg->counts[DNS_SECTION_AUTHORITY]);
3175 ADD_STRING(target, buf);
3176 ADD_STRING(target, ", ADDITIONAL: ");
3177 snprintf(buf, sizeof(buf), "%1u",
3178 msg->counts[DNS_SECTION_ADDITIONAL]);
3179 ADD_STRING(target, buf);
3180 ADD_STRING(target, "\n");
3182 result = dns_message_pseudosectiontotext(msg,
3183 DNS_PSEUDOSECTION_OPT,
3184 style, flags, target);
3185 if (result != ISC_R_SUCCESS)
3188 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3189 style, flags, target);
3190 if (result != ISC_R_SUCCESS)
3192 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3193 style, flags, target);
3194 if (result != ISC_R_SUCCESS)
3196 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3197 style, flags, target);
3198 if (result != ISC_R_SUCCESS)
3200 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3201 style, flags, target);
3202 if (result != ISC_R_SUCCESS)
3205 result = dns_message_pseudosectiontotext(msg,
3206 DNS_PSEUDOSECTION_TSIG,
3207 style, flags, target);
3208 if (result != ISC_R_SUCCESS)
3211 result = dns_message_pseudosectiontotext(msg,
3212 DNS_PSEUDOSECTION_SIG0,
3213 style, flags, target);
3214 if (result != ISC_R_SUCCESS)
3217 return (ISC_R_SUCCESS);
3221 dns_message_getrawmessage(dns_message_t *msg) {
3222 REQUIRE(DNS_MESSAGE_VALID(msg));
3223 return (&msg->saved);
3227 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3228 const void *order_arg)
3230 REQUIRE(DNS_MESSAGE_VALID(msg));
3232 msg->order_arg = order_arg;
3236 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3237 REQUIRE(DNS_MESSAGE_VALID(msg));
3238 msg->timeadjust = timeadjust;
3242 dns_message_gettimeadjust(dns_message_t *msg) {
3243 REQUIRE(DNS_MESSAGE_VALID(msg));
3244 return (msg->timeadjust);
3248 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
3250 REQUIRE(opcode < 16);
3252 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
3253 return (ISC_R_NOSPACE);
3254 isc_buffer_putstr(target, opcodetext[opcode]);
3255 return (ISC_R_SUCCESS);