2 * Copyright (C) 2004 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.194.2.13 2004/03/10 00:50:02 marka Exp $ */
26 #include <isc/buffer.h>
28 #include <isc/print.h>
29 #include <isc/string.h> /* Required for HP/UX (and others?) */
32 #include <dns/dnssec.h>
33 #include <dns/keyvalues.h>
35 #include <dns/masterdump.h>
36 #include <dns/message.h>
37 #include <dns/rdata.h>
38 #include <dns/rdatalist.h>
39 #include <dns/rdataset.h>
40 #include <dns/rdatastruct.h>
41 #include <dns/result.h>
45 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
46 #define DNS_MESSAGE_OPCODE_SHIFT 11
47 #define DNS_MESSAGE_RCODE_MASK 0x000fU
48 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
49 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
50 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
51 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
52 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
54 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
55 && ((s) < DNS_SECTION_MAX))
56 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
57 && ((s) < DNS_SECTION_MAX))
58 #define ADD_STRING(b, s) {if (strlen(s) >= \
59 isc_buffer_availablelength(b)) \
60 return(ISC_R_NOSPACE); else \
61 isc_buffer_putstr(b, s);}
62 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
63 && ((s) < DNS_PSEUDOSECTION_MAX))
66 * This is the size of each individual scratchpad buffer, and the numbers
67 * of various block allocations used within the server.
68 * XXXMLG These should come from a config setting.
70 #define SCRATCHPAD_SIZE 512
72 #define OFFSET_COUNT 4
74 #define RDATALIST_COUNT 8
75 #define RDATASET_COUNT RDATALIST_COUNT
78 * Text representation of the different items, for message_totext
81 static const char *sectiontext[] = {
88 static const char *updsectiontext[] = {
95 static const char *opcodetext[] = {
114 static const char *rcodetext[] = {
136 * "helper" type, which consists of a block of some type, and is linkable.
137 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
138 * size, or the allocated elements will not be alligned correctly.
140 struct dns_msgblock {
142 unsigned int remaining;
143 ISC_LINK(dns_msgblock_t) link;
144 }; /* dynamically sized */
146 static inline dns_msgblock_t *
147 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
149 #define msgblock_get(block, type) \
150 ((type *)msgblock_internalget(block, sizeof(type)))
153 msgblock_internalget(dns_msgblock_t *, unsigned int);
156 msgblock_reset(dns_msgblock_t *);
159 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
162 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
163 * is free, return NULL.
165 static inline dns_msgblock_t *
166 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
169 dns_msgblock_t *block;
172 length = sizeof(dns_msgblock_t) + (sizeof_type * count);
174 block = isc_mem_get(mctx, length);
178 block->count = count;
179 block->remaining = count;
181 ISC_LINK_INIT(block, link);
187 * Return an element from the msgblock. If no more are available, return
191 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
194 if (block == NULL || block->remaining == 0)
199 ptr = (((unsigned char *)block)
200 + sizeof(dns_msgblock_t)
201 + (sizeof_type * block->remaining));
207 msgblock_reset(dns_msgblock_t *block) {
208 block->remaining = block->count;
212 * Release memory associated with a message block.
215 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
219 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
221 isc_mem_put(mctx, block, length);
225 * Allocate a new dynamic buffer, and attach it to this message as the
226 * "current" buffer. (which is always the last on the list, for our
229 static inline isc_result_t
230 newbuffer(dns_message_t *msg, unsigned int size) {
232 isc_buffer_t *dynbuf;
235 result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
236 if (result != ISC_R_SUCCESS)
237 return (ISC_R_NOMEMORY);
239 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
240 return (ISC_R_SUCCESS);
243 static inline isc_buffer_t *
244 currentbuffer(dns_message_t *msg) {
245 isc_buffer_t *dynbuf;
247 dynbuf = ISC_LIST_TAIL(msg->scratchpad);
248 INSIST(dynbuf != NULL);
254 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
255 ISC_LIST_PREPEND(msg->freerdata, rdata, link);
258 static inline dns_rdata_t *
259 newrdata(dns_message_t *msg) {
260 dns_msgblock_t *msgblock;
263 rdata = ISC_LIST_HEAD(msg->freerdata);
265 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
269 msgblock = ISC_LIST_TAIL(msg->rdatas);
270 rdata = msgblock_get(msgblock, dns_rdata_t);
272 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
274 if (msgblock == NULL)
277 ISC_LIST_APPEND(msg->rdatas, msgblock, link);
279 rdata = msgblock_get(msgblock, dns_rdata_t);
282 dns_rdata_init(rdata);
287 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
288 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
291 static inline dns_rdatalist_t *
292 newrdatalist(dns_message_t *msg) {
293 dns_msgblock_t *msgblock;
294 dns_rdatalist_t *rdatalist;
296 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
297 if (rdatalist != NULL) {
298 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
302 msgblock = ISC_LIST_TAIL(msg->rdatalists);
303 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
304 if (rdatalist == NULL) {
305 msgblock = msgblock_allocate(msg->mctx,
306 sizeof(dns_rdatalist_t),
308 if (msgblock == NULL)
311 ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
313 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
319 static inline dns_offsets_t *
320 newoffsets(dns_message_t *msg) {
321 dns_msgblock_t *msgblock;
322 dns_offsets_t *offsets;
324 msgblock = ISC_LIST_TAIL(msg->offsets);
325 offsets = msgblock_get(msgblock, dns_offsets_t);
326 if (offsets == NULL) {
327 msgblock = msgblock_allocate(msg->mctx,
328 sizeof(dns_offsets_t),
330 if (msgblock == NULL)
333 ISC_LIST_APPEND(msg->offsets, msgblock, link);
335 offsets = msgblock_get(msgblock, dns_offsets_t);
342 msginitheader(dns_message_t *m) {
351 msginitprivate(dns_message_t *m) {
354 for (i = 0; i < DNS_SECTION_MAX; i++) {
355 m->cursors[i] = NULL;
363 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
371 msginittsig(dns_message_t *m) {
372 m->tsigstatus = dns_rcode_noerror;
373 m->querytsigstatus = dns_rcode_noerror;
378 m->sig0status = dns_rcode_noerror;
383 * Init elements to default state. Used both when allocating a new element
384 * and when resetting one.
387 msginit(dns_message_t *m) {
393 m->tcp_continuation = 0;
395 m->verify_attempted = 0;
398 m->query.base = NULL;
401 m->saved.base = NULL;
408 msgresetnames(dns_message_t *msg, unsigned int first_section) {
410 dns_name_t *name, *next_name;
411 dns_rdataset_t *rds, *next_rds;
414 * Clean up name lists by calling the rdataset disassociate function.
416 for (i = first_section; i < DNS_SECTION_MAX; i++) {
417 name = ISC_LIST_HEAD(msg->sections[i]);
418 while (name != NULL) {
419 next_name = ISC_LIST_NEXT(name, link);
420 ISC_LIST_UNLINK(msg->sections[i], name, link);
422 rds = ISC_LIST_HEAD(name->list);
423 while (rds != NULL) {
424 next_rds = ISC_LIST_NEXT(rds, link);
425 ISC_LIST_UNLINK(name->list, rds, link);
427 INSIST(dns_rdataset_isassociated(rds));
428 dns_rdataset_disassociate(rds);
429 isc_mempool_put(msg->rdspool, rds);
432 if (dns_name_dynamic(name))
433 dns_name_free(name, msg->mctx);
434 isc_mempool_put(msg->namepool, name);
441 msgresetopt(dns_message_t *msg)
443 if (msg->opt != NULL) {
444 if (msg->opt_reserved > 0) {
445 dns_message_renderrelease(msg, msg->opt_reserved);
446 msg->opt_reserved = 0;
448 INSIST(dns_rdataset_isassociated(msg->opt));
449 dns_rdataset_disassociate(msg->opt);
450 isc_mempool_put(msg->rdspool, msg->opt);
456 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
457 if (msg->sig_reserved > 0) {
458 dns_message_renderrelease(msg, msg->sig_reserved);
459 msg->sig_reserved = 0;
461 if (msg->tsig != NULL) {
462 INSIST(dns_rdataset_isassociated(msg->tsig));
463 INSIST(msg->namepool != NULL);
465 INSIST(msg->querytsig == NULL);
466 msg->querytsig = msg->tsig;
468 dns_rdataset_disassociate(msg->tsig);
469 isc_mempool_put(msg->rdspool, msg->tsig);
470 if (msg->querytsig != NULL) {
471 dns_rdataset_disassociate(msg->querytsig);
472 isc_mempool_put(msg->rdspool, msg->querytsig);
475 if (dns_name_dynamic(msg->tsigname))
476 dns_name_free(msg->tsigname, msg->mctx);
477 isc_mempool_put(msg->namepool, msg->tsigname);
479 msg->tsigname = NULL;
480 } else if (msg->querytsig != NULL && !replying) {
481 dns_rdataset_disassociate(msg->querytsig);
482 isc_mempool_put(msg->rdspool, msg->querytsig);
483 msg->querytsig = NULL;
485 if (msg->sig0 != NULL) {
486 INSIST(dns_rdataset_isassociated(msg->sig0));
487 dns_rdataset_disassociate(msg->sig0);
488 isc_mempool_put(msg->rdspool, msg->sig0);
489 if (msg->sig0name != NULL) {
490 if (dns_name_dynamic(msg->sig0name))
491 dns_name_free(msg->sig0name, msg->mctx);
492 isc_mempool_put(msg->namepool, msg->sig0name);
495 msg->sig0name = NULL;
500 * Free all but one (or everything) for this message. This is used by
501 * both dns_message_reset() and dns_message_destroy().
504 msgreset(dns_message_t *msg, isc_boolean_t everything) {
505 dns_msgblock_t *msgblock, *next_msgblock;
506 isc_buffer_t *dynbuf, *next_dynbuf;
508 dns_rdatalist_t *rdatalist;
510 msgresetnames(msg, 0);
512 msgresetsigs(msg, ISC_FALSE);
515 * Clean up linked lists.
519 * Run through the free lists, and just unlink anything found there.
520 * The memory isn't lost since these are part of message blocks we
523 rdata = ISC_LIST_HEAD(msg->freerdata);
524 while (rdata != NULL) {
525 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
526 rdata = ISC_LIST_HEAD(msg->freerdata);
528 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
529 while (rdatalist != NULL) {
530 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
531 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
534 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
535 INSIST(dynbuf != NULL);
537 isc_buffer_clear(dynbuf);
538 dynbuf = ISC_LIST_NEXT(dynbuf, link);
540 while (dynbuf != NULL) {
541 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
542 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
543 isc_buffer_free(&dynbuf);
544 dynbuf = next_dynbuf;
547 msgblock = ISC_LIST_HEAD(msg->rdatas);
548 if (!everything && msgblock != NULL) {
549 msgblock_reset(msgblock);
550 msgblock = ISC_LIST_NEXT(msgblock, link);
552 while (msgblock != NULL) {
553 next_msgblock = ISC_LIST_NEXT(msgblock, link);
554 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
555 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
556 msgblock = next_msgblock;
560 * rdatalists could be empty.
563 msgblock = ISC_LIST_HEAD(msg->rdatalists);
564 if (!everything && msgblock != NULL) {
565 msgblock_reset(msgblock);
566 msgblock = ISC_LIST_NEXT(msgblock, link);
568 while (msgblock != NULL) {
569 next_msgblock = ISC_LIST_NEXT(msgblock, link);
570 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
571 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
572 msgblock = next_msgblock;
575 msgblock = ISC_LIST_HEAD(msg->offsets);
576 if (!everything && msgblock != NULL) {
577 msgblock_reset(msgblock);
578 msgblock = ISC_LIST_NEXT(msgblock, link);
580 while (msgblock != NULL) {
581 next_msgblock = ISC_LIST_NEXT(msgblock, link);
582 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
583 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
584 msgblock = next_msgblock;
587 if (msg->tsigkey != NULL) {
588 dns_tsigkey_detach(&msg->tsigkey);
592 if (msg->query.base != NULL) {
593 if (msg->free_query != 0)
594 isc_mem_put(msg->mctx, msg->query.base,
596 msg->query.base = NULL;
597 msg->query.length = 0;
600 if (msg->saved.base != NULL) {
601 if (msg->free_saved != 0)
602 isc_mem_put(msg->mctx, msg->saved.base,
604 msg->saved.base = NULL;
605 msg->saved.length = 0;
609 * cleanup the buffer cleanup list
611 dynbuf = ISC_LIST_HEAD(msg->cleanup);
612 while (dynbuf != NULL) {
613 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
614 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
615 isc_buffer_free(&dynbuf);
616 dynbuf = next_dynbuf;
620 * Set other bits to normal default values.
625 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
626 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
630 spacefortsig(dns_tsigkey_t *key, int otherlen) {
636 * The space required for an TSIG record is:
638 * n1 bytes for the name
639 * 2 bytes for the type
640 * 2 bytes for the class
641 * 4 bytes for the ttl
642 * 2 bytes for the rdlength
643 * n2 bytes for the algorithm name
644 * 6 bytes for the time signed
645 * 2 bytes for the fudge
646 * 2 bytes for the MAC size
647 * x bytes for the MAC
648 * 2 bytes for the original id
649 * 2 bytes for the error
650 * 2 bytes for the other data length
651 * y bytes for the other data (at most)
652 * ---------------------------------
653 * 26 + n1 + n2 + x + y bytes
656 dns_name_toregion(&key->name, &r1);
657 dns_name_toregion(key->algorithm, &r2);
658 if (key->key == NULL)
661 result = dst_key_sigsize(key->key, &x);
662 if (result != ISC_R_SUCCESS)
665 return (26 + r1.length + r2.length + x + otherlen);
669 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
673 isc_buffer_t *dynbuf;
676 REQUIRE(mctx != NULL);
677 REQUIRE(msgp != NULL);
678 REQUIRE(*msgp == NULL);
679 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
680 || intent == DNS_MESSAGE_INTENTRENDER);
682 m = isc_mem_get(mctx, sizeof(dns_message_t));
684 return (ISC_R_NOMEMORY);
687 * No allocations until further notice. Just initialize all lists
688 * and other members that are freed in the cleanup phase here.
691 m->magic = DNS_MESSAGE_MAGIC;
692 m->from_to_wire = intent;
695 for (i = 0 ; i < DNS_SECTION_MAX ; i++)
696 ISC_LIST_INIT(m->sections[i]);
699 ISC_LIST_INIT(m->scratchpad);
700 ISC_LIST_INIT(m->cleanup);
703 ISC_LIST_INIT(m->rdatas);
704 ISC_LIST_INIT(m->rdatalists);
705 ISC_LIST_INIT(m->offsets);
706 ISC_LIST_INIT(m->freerdata);
707 ISC_LIST_INIT(m->freerdatalist);
710 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
713 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
714 if (result != ISC_R_SUCCESS)
716 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
717 isc_mempool_setname(m->namepool, "msg:names");
719 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
721 if (result != ISC_R_SUCCESS)
723 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
724 isc_mempool_setname(m->rdspool, "msg:rdataset");
727 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
728 if (result != ISC_R_SUCCESS)
730 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
735 return (ISC_R_SUCCESS);
738 * Cleanup for error returns.
741 dynbuf = ISC_LIST_HEAD(m->scratchpad);
742 if (dynbuf != NULL) {
743 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
744 isc_buffer_free(&dynbuf);
746 if (m->namepool != NULL)
747 isc_mempool_destroy(&m->namepool);
748 if (m->rdspool != NULL)
749 isc_mempool_destroy(&m->rdspool);
751 isc_mem_put(mctx, m, sizeof(dns_message_t));
753 return (ISC_R_NOMEMORY);
757 dns_message_reset(dns_message_t *msg, unsigned int intent) {
758 REQUIRE(DNS_MESSAGE_VALID(msg));
759 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
760 || intent == DNS_MESSAGE_INTENTRENDER);
762 msgreset(msg, ISC_FALSE);
763 msg->from_to_wire = intent;
767 dns_message_destroy(dns_message_t **msgp) {
770 REQUIRE(msgp != NULL);
771 REQUIRE(DNS_MESSAGE_VALID(*msgp));
776 msgreset(msg, ISC_TRUE);
777 isc_mempool_destroy(&msg->namepool);
778 isc_mempool_destroy(&msg->rdspool);
780 isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
784 findname(dns_name_t **foundname, dns_name_t *target,
785 dns_namelist_t *section)
789 for (curr = ISC_LIST_TAIL(*section) ;
791 curr = ISC_LIST_PREV(curr, link)) {
792 if (dns_name_equal(curr, target)) {
793 if (foundname != NULL)
795 return (ISC_R_SUCCESS);
799 return (ISC_R_NOTFOUND);
803 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
804 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
806 dns_rdataset_t *curr;
808 if (rdataset != NULL) {
809 REQUIRE(*rdataset == NULL);
812 for (curr = ISC_LIST_TAIL(name->list) ;
814 curr = ISC_LIST_PREV(curr, link)) {
815 if (curr->type == type && curr->covers == covers) {
816 if (rdataset != NULL)
818 return (ISC_R_SUCCESS);
822 return (ISC_R_NOTFOUND);
826 * Read a name from buffer "source".
829 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
830 dns_decompress_t *dctx)
832 isc_buffer_t *scratch;
836 scratch = currentbuffer(msg);
839 * First try: use current buffer.
840 * Second try: allocate a new buffer and use that.
844 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
847 if (result == ISC_R_NOSPACE) {
850 result = newbuffer(msg, SCRATCHPAD_SIZE);
851 if (result != ISC_R_SUCCESS)
854 scratch = currentbuffer(msg);
855 dns_name_reset(name);
861 INSIST(0); /* Cannot get here... */
862 return (ISC_R_UNEXPECTED);
866 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
867 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
868 unsigned int rdatalen, dns_rdata_t *rdata)
870 isc_buffer_t *scratch;
873 unsigned int trysize;
875 scratch = currentbuffer(msg);
877 isc_buffer_setactive(source, rdatalen);
880 * First try: use current buffer.
881 * Second try: allocate a new buffer of size
882 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
883 * (the data will fit if it was not more than 50% compressed)
884 * Subsequent tries: double buffer size on each try.
888 /* XXX possibly change this to a while (tries < 2) loop */
890 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
891 source, dctx, ISC_FALSE,
894 if (result == ISC_R_NOSPACE) {
896 trysize = 2 * rdatalen;
897 if (trysize < SCRATCHPAD_SIZE)
898 trysize = SCRATCHPAD_SIZE;
900 INSIST(trysize != 0);
901 if (trysize >= 65535)
902 return (ISC_R_NOSPACE);
903 /* XXX DNS_R_RRTOOLONG? */
907 result = newbuffer(msg, trysize);
908 if (result != ISC_R_SUCCESS)
911 scratch = currentbuffer(msg);
921 seen_problem = ISC_TRUE; \
923 result = DNS_R_FORMERR; \
929 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
930 unsigned int options)
936 dns_offsets_t *offsets;
937 dns_rdataset_t *rdataset;
938 dns_rdatalist_t *rdatalist;
940 dns_rdatatype_t rdtype;
941 dns_rdataclass_t rdclass;
942 dns_namelist_t *section;
943 isc_boolean_t free_name;
944 isc_boolean_t best_effort;
945 isc_boolean_t seen_problem;
947 section = &msg->sections[DNS_SECTION_QUESTION];
949 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
950 seen_problem = ISC_FALSE;
956 for (count = 0 ; count < msg->counts[DNS_SECTION_QUESTION] ; count++) {
957 name = isc_mempool_get(msg->namepool);
959 return (ISC_R_NOMEMORY);
960 free_name = ISC_TRUE;
962 offsets = newoffsets(msg);
963 if (offsets == NULL) {
964 result = ISC_R_NOMEMORY;
967 dns_name_init(name, *offsets);
970 * Parse the name out of this packet.
972 isc_buffer_remainingregion(source, &r);
973 isc_buffer_setactive(source, r.length);
974 result = getname(name, source, msg, dctx);
975 if (result != ISC_R_SUCCESS)
979 * Run through the section, looking to see if this name
980 * is already there. If it is found, put back the allocated
981 * name since we no longer need it, and set our name pointer
982 * to point to the name we found.
984 result = findname(&name2, name, section);
987 * If it is the first name in the section, accept it.
989 * If it is not, but is not the same as the name already
990 * in the question section, append to the section. Note that
991 * here in the question section this is illegal, so return
992 * FORMERR. In the future, check the opcode to see if
993 * this should be legal or not. In either case we no longer
994 * need this name pointer.
996 if (result != ISC_R_SUCCESS) {
997 if (!ISC_LIST_EMPTY(*section))
999 ISC_LIST_APPEND(*section, name, link);
1000 free_name = ISC_FALSE;
1002 isc_mempool_put(msg->namepool, name);
1005 free_name = ISC_FALSE;
1009 * Get type and class.
1011 isc_buffer_remainingregion(source, &r);
1013 result = ISC_R_UNEXPECTEDEND;
1016 rdtype = isc_buffer_getuint16(source);
1017 rdclass = isc_buffer_getuint16(source);
1020 * If this class is different than the one we already read,
1023 if (msg->state == DNS_SECTION_ANY) {
1024 msg->state = DNS_SECTION_QUESTION;
1025 msg->rdclass = rdclass;
1026 } else if (msg->rdclass != rdclass)
1030 * Can't ask the same question twice.
1032 result = dns_message_findtype(name, rdtype, 0, NULL);
1033 if (result == ISC_R_SUCCESS)
1037 * Allocate a new rdatalist.
1039 rdatalist = newrdatalist(msg);
1040 if (rdatalist == NULL) {
1041 result = ISC_R_NOMEMORY;
1044 rdataset = isc_mempool_get(msg->rdspool);
1045 if (rdataset == NULL) {
1046 result = ISC_R_NOMEMORY;
1051 * Convert rdatalist to rdataset, and attach the latter to
1054 rdatalist->type = rdtype;
1055 rdatalist->covers = 0;
1056 rdatalist->rdclass = rdclass;
1058 ISC_LIST_INIT(rdatalist->rdata);
1060 dns_rdataset_init(rdataset);
1061 result = dns_rdatalist_tordataset(rdatalist, rdataset);
1062 if (result != ISC_R_SUCCESS)
1065 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1067 ISC_LIST_APPEND(name->list, rdataset, link);
1072 return (DNS_R_RECOVERABLE);
1073 return (ISC_R_SUCCESS);
1076 if (rdataset != NULL) {
1077 INSIST(!dns_rdataset_isassociated(rdataset));
1078 isc_mempool_put(msg->rdspool, rdataset);
1081 if (rdatalist != NULL)
1082 isc_mempool_put(msg->rdlpool, rdatalist);
1085 isc_mempool_put(msg->namepool, name);
1090 static isc_boolean_t
1091 update(dns_section_t section, dns_rdataclass_t rdclass) {
1092 if (section == DNS_SECTION_PREREQUISITE)
1093 return (ISC_TF(rdclass == dns_rdataclass_any ||
1094 rdclass == dns_rdataclass_none));
1095 if (section == DNS_SECTION_UPDATE)
1096 return (ISC_TF(rdclass == dns_rdataclass_any));
1101 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1102 dns_section_t sectionid, unsigned int options)
1105 unsigned int count, rdatalen;
1108 dns_offsets_t *offsets;
1109 dns_rdataset_t *rdataset;
1110 dns_rdatalist_t *rdatalist;
1111 isc_result_t result;
1112 dns_rdatatype_t rdtype, covers;
1113 dns_rdataclass_t rdclass;
1116 dns_namelist_t *section;
1117 isc_boolean_t free_name, free_rdataset;
1118 isc_boolean_t preserve_order, best_effort, seen_problem;
1119 isc_boolean_t issigzero;
1121 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1122 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1123 seen_problem = ISC_FALSE;
1125 for (count = 0 ; count < msg->counts[sectionid] ; count++) {
1126 int recstart = source->current;
1127 isc_boolean_t skip_name_search, skip_type_search;
1129 section = &msg->sections[sectionid];
1131 skip_name_search = ISC_FALSE;
1132 skip_type_search = ISC_FALSE;
1133 free_name = ISC_FALSE;
1134 free_rdataset = ISC_FALSE;
1136 name = isc_mempool_get(msg->namepool);
1138 return (ISC_R_NOMEMORY);
1139 free_name = ISC_TRUE;
1141 offsets = newoffsets(msg);
1142 if (offsets == NULL) {
1143 result = ISC_R_NOMEMORY;
1146 dns_name_init(name, *offsets);
1149 * Parse the name out of this packet.
1151 isc_buffer_remainingregion(source, &r);
1152 isc_buffer_setactive(source, r.length);
1153 result = getname(name, source, msg, dctx);
1154 if (result != ISC_R_SUCCESS)
1158 * Get type, class, ttl, and rdatalen. Verify that at least
1159 * rdatalen bytes remain. (Some of this is deferred to
1162 isc_buffer_remainingregion(source, &r);
1163 if (r.length < 2 + 2 + 4 + 2) {
1164 result = ISC_R_UNEXPECTEDEND;
1167 rdtype = isc_buffer_getuint16(source);
1168 rdclass = isc_buffer_getuint16(source);
1171 * If there was no question section, we may not yet have
1172 * established a class. Do so now.
1174 if (msg->state == DNS_SECTION_ANY &&
1175 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
1176 rdtype != dns_rdatatype_tsig && /* class is ANY */
1177 rdtype != dns_rdatatype_tkey) { /* class is undefined */
1178 msg->rdclass = rdclass;
1179 msg->state = DNS_SECTION_QUESTION;
1183 * If this class is different than the one in the question
1186 if (msg->opcode != dns_opcode_update
1187 && rdtype != dns_rdatatype_tsig
1188 && rdtype != dns_rdatatype_opt
1189 && rdtype != dns_rdatatype_key /* in a TKEY query */
1190 && rdtype != dns_rdatatype_sig /* SIG(0) */
1191 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1192 && msg->rdclass != rdclass)
1196 * Special type handling for TSIG, OPT, and TKEY.
1198 if (rdtype == dns_rdatatype_tsig) {
1200 * If it is a tsig, verify that it is in the
1201 * additional data section.
1203 if (sectionid != DNS_SECTION_ADDITIONAL ||
1204 rdclass != dns_rdataclass_any ||
1205 count != msg->counts[sectionid] - 1)
1207 msg->sigstart = recstart;
1208 skip_name_search = ISC_TRUE;
1209 skip_type_search = ISC_TRUE;
1210 } else if (rdtype == dns_rdatatype_opt) {
1212 * The name of an OPT record must be ".", it
1213 * must be in the additional data section, and
1214 * it must be the first OPT we've seen.
1216 if (!dns_name_equal(dns_rootname, name) ||
1219 skip_name_search = ISC_TRUE;
1220 skip_type_search = ISC_TRUE;
1221 } else if (rdtype == dns_rdatatype_tkey) {
1223 * A TKEY must be in the additional section if this
1224 * is a query, and the answer section if this is a
1225 * response. Unless it's a Win2000 client.
1227 * Its class is ignored.
1229 dns_section_t tkeysection;
1231 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1232 tkeysection = DNS_SECTION_ADDITIONAL;
1234 tkeysection = DNS_SECTION_ANSWER;
1235 if (sectionid != tkeysection &&
1236 sectionid != DNS_SECTION_ANSWER)
1241 * ... now get ttl and rdatalen, and check buffer.
1243 ttl = isc_buffer_getuint32(source);
1244 rdatalen = isc_buffer_getuint16(source);
1245 r.length -= (2 + 2 + 4 + 2);
1246 if (r.length < rdatalen) {
1247 result = ISC_R_UNEXPECTEDEND;
1252 * Read the rdata from the wire format. Interpret the
1253 * rdata according to its actual class, even if it had a
1254 * DynDNS meta-class in the packet (unless this is a TSIG).
1255 * Then put the meta-class back into the finished rdata.
1257 rdata = newrdata(msg);
1258 if (rdata == NULL) {
1259 result = ISC_R_NOMEMORY;
1262 if (msg->opcode == dns_opcode_update &&
1263 update(sectionid, rdclass)) {
1264 if (rdatalen != 0) {
1265 result = DNS_R_FORMERR;
1269 * When the rdata is empty, the data pointer is
1270 * never dereferenced, but it must still be non-NULL.
1271 * Casting 1 rather than "" avoids warnings about
1272 * discarding the const attribute of a string,
1273 * for compilers that would warn about such things.
1275 rdata->data = (unsigned char *)1;
1277 rdata->rdclass = rdclass;
1278 rdata->type = rdtype;
1279 rdata->flags = DNS_RDATA_UPDATE;
1280 result = ISC_R_SUCCESS;
1281 } else if (rdtype == dns_rdatatype_tsig)
1282 result = getrdata(source, msg, dctx, rdclass,
1283 rdtype, rdatalen, rdata);
1285 result = getrdata(source, msg, dctx, msg->rdclass,
1286 rdtype, rdatalen, rdata);
1287 if (result != ISC_R_SUCCESS)
1289 rdata->rdclass = rdclass;
1290 issigzero = ISC_FALSE;
1291 if (rdtype == dns_rdatatype_sig && rdata->flags == 0) {
1292 covers = dns_rdata_covers(rdata);
1294 if (sectionid != DNS_SECTION_ADDITIONAL ||
1295 count != msg->counts[sectionid] - 1)
1297 msg->sigstart = recstart;
1298 skip_name_search = ISC_TRUE;
1299 skip_type_search = ISC_TRUE;
1300 issigzero = ISC_TRUE;
1306 * If we are doing a dynamic update or this is a meta-type,
1307 * don't bother searching for a name, just append this one
1308 * to the end of the message.
1310 if (preserve_order || msg->opcode == dns_opcode_update ||
1312 if (rdtype != dns_rdatatype_opt &&
1313 rdtype != dns_rdatatype_tsig &&
1316 ISC_LIST_APPEND(*section, name, link);
1317 free_name = ISC_FALSE;
1321 * Run through the section, looking to see if this name
1322 * is already there. If it is found, put back the
1323 * allocated name since we no longer need it, and set
1324 * our name pointer to point to the name we found.
1326 result = findname(&name2, name, section);
1329 * If it is a new name, append to the section.
1331 if (result == ISC_R_SUCCESS) {
1332 isc_mempool_put(msg->namepool, name);
1335 ISC_LIST_APPEND(*section, name, link);
1337 free_name = ISC_FALSE;
1341 * Search name for the particular type and class.
1342 * Skip this stage if in update mode or this is a meta-type.
1344 if (preserve_order || msg->opcode == dns_opcode_update ||
1346 result = ISC_R_NOTFOUND;
1349 * If this is a type that can only occur in
1350 * the question section, fail.
1352 if (dns_rdatatype_questiononly(rdtype))
1356 result = dns_message_findtype(name, rdtype, covers,
1361 * If we found an rdataset that matches, we need to
1362 * append this rdata to that set. If we did not, we need
1363 * to create a new rdatalist, store the important bits there,
1364 * convert it to an rdataset, and link the latter to the name.
1365 * Yuck. When appending, make certain that the type isn't
1366 * a singleton type, such as SOA or CNAME.
1368 * Note that this check will be bypassed when preserving order,
1369 * the opcode is an update, or the type search is skipped.
1371 if (result == ISC_R_SUCCESS) {
1372 if (dns_rdatatype_issingleton(rdtype))
1376 if (result == ISC_R_NOTFOUND) {
1377 rdataset = isc_mempool_get(msg->rdspool);
1378 if (rdataset == NULL) {
1379 result = ISC_R_NOMEMORY;
1382 free_rdataset = ISC_TRUE;
1384 rdatalist = newrdatalist(msg);
1385 if (rdatalist == NULL) {
1386 result = ISC_R_NOMEMORY;
1390 rdatalist->type = rdtype;
1391 rdatalist->covers = covers;
1392 rdatalist->rdclass = rdclass;
1393 rdatalist->ttl = ttl;
1394 ISC_LIST_INIT(rdatalist->rdata);
1396 dns_rdataset_init(rdataset);
1397 dns_rdatalist_tordataset(rdatalist, rdataset);
1399 if (rdtype != dns_rdatatype_opt &&
1400 rdtype != dns_rdatatype_tsig &&
1403 ISC_LIST_APPEND(name->list, rdataset, link);
1404 free_rdataset = ISC_FALSE;
1411 * Section 5.2 of RFC 2181 says we should drop
1412 * nonauthoritative rrsets where the TTLs differ, but we
1413 * currently treat them the as if they were authoritative and
1416 if (ttl != rdataset->ttl) {
1417 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1418 if (ttl < rdataset->ttl)
1419 rdataset->ttl = ttl;
1423 * XXXMLG Perform a totally ugly hack here to pull
1424 * the rdatalist out of the private field in the rdataset,
1425 * and append this rdata to the rdatalist's linked list
1428 rdatalist = (dns_rdatalist_t *)(rdataset->private1);
1430 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1433 * If this is an OPT record, remember it. Also, set
1434 * the extended rcode. Note that msg->opt will only be set
1435 * if best-effort parsing is enabled.
1437 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1440 msg->opt = rdataset;
1442 free_rdataset = ISC_FALSE;
1443 ercode = (dns_rcode_t)
1444 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1446 msg->rcode |= ercode;
1447 isc_mempool_put(msg->namepool, name);
1448 free_name = ISC_FALSE;
1452 * If this is an SIG(0) or TSIG record, remember it. Note
1453 * that msg->sig0 or msg->tsig will only be set if best-effort
1454 * parsing is enabled.
1456 if (issigzero && msg->sig0 == NULL) {
1457 msg->sig0 = rdataset;
1458 msg->sig0name = name;
1460 free_rdataset = ISC_FALSE;
1461 free_name = ISC_FALSE;
1463 else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1464 msg->tsig = rdataset;
1465 msg->tsigname = name;
1467 free_rdataset = ISC_FALSE;
1468 free_name = ISC_FALSE;
1471 INSIST(free_name == ISC_FALSE);
1472 INSIST(free_rdataset == ISC_FALSE);
1476 return (DNS_R_RECOVERABLE);
1477 return (ISC_R_SUCCESS);
1481 isc_mempool_put(msg->namepool, name);
1483 isc_mempool_put(msg->rdspool, rdataset);
1489 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1490 unsigned int options)
1493 dns_decompress_t dctx;
1495 isc_uint16_t tmpflags;
1496 isc_buffer_t origsource;
1497 isc_boolean_t seen_problem;
1498 isc_boolean_t ignore_tc;
1500 REQUIRE(DNS_MESSAGE_VALID(msg));
1501 REQUIRE(source != NULL);
1502 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1504 seen_problem = ISC_FALSE;
1505 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1507 origsource = *source;
1510 msg->question_ok = 0;
1512 isc_buffer_remainingregion(source, &r);
1513 if (r.length < DNS_MESSAGE_HEADERLEN)
1514 return (ISC_R_UNEXPECTEDEND);
1516 msg->id = isc_buffer_getuint16(source);
1517 tmpflags = isc_buffer_getuint16(source);
1518 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1519 >> DNS_MESSAGE_OPCODE_SHIFT);
1520 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1521 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1522 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1523 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1524 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1525 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1532 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1534 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1536 ret = getquestions(source, msg, &dctx, options);
1537 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1539 if (ret == DNS_R_RECOVERABLE) {
1540 seen_problem = ISC_TRUE;
1541 ret = ISC_R_SUCCESS;
1543 if (ret != ISC_R_SUCCESS)
1545 msg->question_ok = 1;
1547 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1548 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1550 if (ret == DNS_R_RECOVERABLE) {
1551 seen_problem = ISC_TRUE;
1552 ret = ISC_R_SUCCESS;
1554 if (ret != ISC_R_SUCCESS)
1557 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1558 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1560 if (ret == DNS_R_RECOVERABLE) {
1561 seen_problem = ISC_TRUE;
1562 ret = ISC_R_SUCCESS;
1564 if (ret != ISC_R_SUCCESS)
1567 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1568 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1570 if (ret == DNS_R_RECOVERABLE) {
1571 seen_problem = ISC_TRUE;
1572 ret = ISC_R_SUCCESS;
1574 if (ret != ISC_R_SUCCESS)
1577 isc_buffer_remainingregion(source, &r);
1578 if (r.length != 0) {
1579 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1580 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(1),
1581 "message has %u byte(s) of trailing garbage",
1586 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1587 isc_buffer_usedregion(&origsource, &msg->saved);
1589 msg->saved.length = isc_buffer_usedlength(&origsource);
1590 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1591 if (msg->saved.base == NULL)
1592 return (ISC_R_NOMEMORY);
1593 memcpy(msg->saved.base, isc_buffer_base(&origsource),
1595 msg->free_saved = 1;
1598 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1599 return (DNS_R_RECOVERABLE);
1600 if (seen_problem == ISC_TRUE)
1601 return (DNS_R_RECOVERABLE);
1602 return (ISC_R_SUCCESS);
1606 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1607 isc_buffer_t *buffer)
1611 REQUIRE(DNS_MESSAGE_VALID(msg));
1612 REQUIRE(buffer != NULL);
1613 REQUIRE(msg->buffer == NULL);
1614 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1619 * Erase the contents of this buffer.
1621 isc_buffer_clear(buffer);
1624 * Make certain there is enough for at least the header in this
1627 isc_buffer_availableregion(buffer, &r);
1628 if (r.length < DNS_MESSAGE_HEADERLEN)
1629 return (ISC_R_NOSPACE);
1631 if (r.length < msg->reserved)
1632 return (ISC_R_NOSPACE);
1635 * Reserve enough space for the header in this buffer.
1637 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1639 msg->buffer = buffer;
1641 return (ISC_R_SUCCESS);
1645 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1648 REQUIRE(DNS_MESSAGE_VALID(msg));
1649 REQUIRE(buffer != NULL);
1650 REQUIRE(msg->buffer != NULL);
1653 * Ensure that the new buffer is empty, and has enough space to
1654 * hold the current contents.
1656 isc_buffer_clear(buffer);
1658 isc_buffer_availableregion(buffer, &rn);
1659 isc_buffer_usedregion(msg->buffer, &r);
1660 REQUIRE(rn.length > r.length);
1663 * Copy the contents from the old to the new buffer.
1665 isc_buffer_add(buffer, r.length);
1666 memcpy(rn.base, r.base, r.length);
1668 msg->buffer = buffer;
1670 return (ISC_R_SUCCESS);
1674 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1675 REQUIRE(DNS_MESSAGE_VALID(msg));
1676 REQUIRE(space <= msg->reserved);
1678 msg->reserved -= space;
1682 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1685 REQUIRE(DNS_MESSAGE_VALID(msg));
1687 if (msg->buffer != NULL) {
1688 isc_buffer_availableregion(msg->buffer, &r);
1689 if (r.length < (space + msg->reserved))
1690 return (ISC_R_NOSPACE);
1693 msg->reserved += space;
1695 return (ISC_R_SUCCESS);
1698 static inline isc_boolean_t
1699 wrong_priority(dns_rdataset_t *rds, int pass) {
1703 * If we are not rendering class IN, this ordering is bogus.
1705 if (rds->rdclass != dns_rdataclass_in)
1708 switch (rds->type) {
1709 case dns_rdatatype_a:
1710 case dns_rdatatype_aaaa:
1711 case dns_rdatatype_a6:
1714 case dns_rdatatype_sig:
1715 case dns_rdatatype_key:
1722 if (pass_needed >= pass)
1729 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1730 unsigned int options)
1732 dns_namelist_t *section;
1733 dns_name_t *name, *next_name;
1734 dns_rdataset_t *rdataset, *next_rdataset;
1735 unsigned int count, total;
1736 isc_result_t result;
1737 isc_buffer_t st; /* for rollbacks */
1739 isc_boolean_t partial = ISC_FALSE;
1741 REQUIRE(DNS_MESSAGE_VALID(msg));
1742 REQUIRE(msg->buffer != NULL);
1743 REQUIRE(VALID_NAMED_SECTION(sectionid));
1745 section = &msg->sections[sectionid];
1747 if ((sectionid == DNS_SECTION_ADDITIONAL)
1748 && (options & DNS_MESSAGERENDER_ORDERED) == 0)
1754 * Shrink the space in the buffer by the reserved amount.
1756 msg->buffer->length -= msg->reserved;
1759 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1763 name = ISC_LIST_HEAD(*section);
1765 msg->buffer->length += msg->reserved;
1766 msg->counts[sectionid] += total;
1767 return (ISC_R_SUCCESS);
1770 while (name != NULL) {
1771 next_name = ISC_LIST_NEXT(name, link);
1773 rdataset = ISC_LIST_HEAD(name->list);
1774 while (rdataset != NULL) {
1775 next_rdataset = ISC_LIST_NEXT(rdataset, link);
1777 if ((rdataset->attributes &
1778 DNS_RDATASETATTR_RENDERED) != 0)
1781 if (((options & DNS_MESSAGERENDER_ORDERED)
1783 && (sectionid == DNS_SECTION_ADDITIONAL)
1784 && wrong_priority(rdataset, pass))
1787 st = *(msg->buffer);
1791 result = dns_rdataset_towirepartial(
1801 result = dns_rdataset_towiresorted(
1813 * If out of space, record stats on what we
1814 * rendered so far, and return that status.
1816 * XXXMLG Need to change this when
1817 * dns_rdataset_towire() can render partial
1818 * sets starting at some arbitary point in the
1819 * set. This will include setting a bit in the
1820 * rdataset to indicate that a partial
1821 * rendering was done, and some state saved
1822 * somewhere (probably in the message struct)
1823 * to indicate where to continue from.
1825 if (partial && result == ISC_R_NOSPACE) {
1826 msg->buffer->length += msg->reserved;
1827 msg->counts[sectionid] += total;
1830 if (result != ISC_R_SUCCESS) {
1831 INSIST(st.used < 65536);
1832 dns_compress_rollback(msg->cctx,
1833 (isc_uint16_t)st.used);
1834 *(msg->buffer) = st; /* rollback */
1835 msg->buffer->length += msg->reserved;
1836 msg->counts[sectionid] += total;
1841 * If we have rendered non-validated data,
1842 * ensure that the AD bit is not set.
1844 if (rdataset->trust != dns_trust_secure &&
1845 (sectionid == DNS_SECTION_ANSWER ||
1846 sectionid == DNS_SECTION_AUTHORITY))
1847 msg->flags &= ~DNS_MESSAGEFLAG_AD;
1849 rdataset->attributes |=
1850 DNS_RDATASETATTR_RENDERED;
1853 rdataset = next_rdataset;
1858 } while (--pass != 0);
1860 msg->buffer->length += msg->reserved;
1861 msg->counts[sectionid] += total;
1863 return (ISC_R_SUCCESS);
1867 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
1871 REQUIRE(DNS_MESSAGE_VALID(msg));
1872 REQUIRE(target != NULL);
1874 isc_buffer_availableregion(target, &r);
1875 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
1877 isc_buffer_putuint16(target, msg->id);
1879 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
1880 & DNS_MESSAGE_OPCODE_MASK);
1881 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
1882 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
1884 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
1885 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
1886 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
1887 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
1889 isc_buffer_putuint16(target, tmp);
1890 isc_buffer_putuint16(target,
1891 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
1892 isc_buffer_putuint16(target,
1893 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
1894 isc_buffer_putuint16(target,
1895 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
1896 isc_buffer_putuint16(target,
1897 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
1901 dns_message_renderend(dns_message_t *msg) {
1902 isc_buffer_t tmpbuf;
1907 REQUIRE(DNS_MESSAGE_VALID(msg));
1908 REQUIRE(msg->buffer != NULL);
1910 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
1912 * We have an extended rcode but are not using EDNS.
1914 return (DNS_R_FORMERR);
1918 * If we've got an OPT record, render it.
1920 if (msg->opt != NULL) {
1921 dns_message_renderrelease(msg, msg->opt_reserved);
1922 msg->opt_reserved = 0;
1924 * Set the extended rcode.
1926 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
1927 msg->opt->ttl |= ((msg->rcode << 20) &
1928 DNS_MESSAGE_EDNSRCODE_MASK);
1933 result = dns_rdataset_towire(msg->opt, dns_rootname,
1934 msg->cctx, msg->buffer, &count);
1935 msg->counts[DNS_SECTION_ADDITIONAL] += count;
1936 if (result != ISC_R_SUCCESS)
1941 * If we're adding a TSIG or SIG(0) to a truncated message,
1942 * clear all rdatasets from the message except for the question
1943 * before adding the TSIG or SIG(0). If the question doesn't fit,
1946 if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
1947 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
1951 msgresetnames(msg, DNS_SECTION_ANSWER);
1953 dns_message_renderreset(msg);
1955 isc_buffer_clear(msg->buffer);
1956 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
1957 dns_compress_rollback(msg->cctx, 0);
1958 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
1960 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1965 * If we're adding a TSIG record, generate and render it.
1967 if (msg->tsigkey != NULL) {
1968 dns_message_renderrelease(msg, msg->sig_reserved);
1969 msg->sig_reserved = 0;
1970 result = dns_tsig_sign(msg);
1971 if (result != ISC_R_SUCCESS)
1974 result = dns_rdataset_towire(msg->tsig, msg->tsigname,
1975 msg->cctx, msg->buffer, &count);
1976 msg->counts[DNS_SECTION_ADDITIONAL] += count;
1977 if (result != ISC_R_SUCCESS)
1982 * If we're adding a SIG(0) record, generate and render it.
1984 if (msg->sig0key != NULL) {
1985 dns_message_renderrelease(msg, msg->sig_reserved);
1986 msg->sig_reserved = 0;
1987 result = dns_dnssec_signmessage(msg, msg->sig0key);
1988 if (result != ISC_R_SUCCESS)
1992 * Note: dns_rootname is used here, not msg->sig0name, since
1993 * the owner name of a SIG(0) is irrelevant, and will not
1994 * be set in a message being rendered.
1996 result = dns_rdataset_towire(msg->sig0, dns_rootname,
1997 msg->cctx, msg->buffer, &count);
1998 msg->counts[DNS_SECTION_ADDITIONAL] += count;
1999 if (result != ISC_R_SUCCESS)
2003 isc_buffer_usedregion(msg->buffer, &r);
2004 isc_buffer_init(&tmpbuf, r.base, r.length);
2006 dns_message_renderheader(msg, &tmpbuf);
2008 msg->buffer = NULL; /* forget about this buffer only on success XXX */
2010 return (ISC_R_SUCCESS);
2014 dns_message_renderreset(dns_message_t *msg) {
2017 dns_rdataset_t *rds;
2020 * Reset the message so that it may be rendered again.
2023 REQUIRE(DNS_MESSAGE_VALID(msg));
2024 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2028 for (i = 0; i < DNS_SECTION_MAX; i++) {
2029 msg->cursors[i] = NULL;
2031 for (name = ISC_LIST_HEAD(msg->sections[i]);
2033 name = ISC_LIST_NEXT(name, link)) {
2034 for (rds = ISC_LIST_HEAD(name->list);
2036 rds = ISC_LIST_NEXT(rds, link)) {
2037 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2041 if (msg->tsigname != NULL)
2042 dns_message_puttempname(msg, &msg->tsigname);
2043 if (msg->tsig != NULL) {
2044 dns_rdataset_disassociate(msg->tsig);
2045 dns_message_puttemprdataset(msg, &msg->tsig);
2047 if (msg->sig0 != NULL) {
2048 dns_rdataset_disassociate(msg->sig0);
2049 dns_message_puttemprdataset(msg, &msg->sig0);
2054 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2055 REQUIRE(DNS_MESSAGE_VALID(msg));
2056 REQUIRE(VALID_NAMED_SECTION(section));
2058 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2060 if (msg->cursors[section] == NULL)
2061 return (ISC_R_NOMORE);
2063 return (ISC_R_SUCCESS);
2067 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2068 REQUIRE(DNS_MESSAGE_VALID(msg));
2069 REQUIRE(VALID_NAMED_SECTION(section));
2070 REQUIRE(msg->cursors[section] != NULL);
2072 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2074 if (msg->cursors[section] == NULL)
2075 return (ISC_R_NOMORE);
2077 return (ISC_R_SUCCESS);
2081 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2084 REQUIRE(DNS_MESSAGE_VALID(msg));
2085 REQUIRE(VALID_NAMED_SECTION(section));
2086 REQUIRE(name != NULL && *name == NULL);
2087 REQUIRE(msg->cursors[section] != NULL);
2089 *name = msg->cursors[section];
2093 dns_message_findname(dns_message_t *msg, dns_section_t section,
2094 dns_name_t *target, dns_rdatatype_t type,
2095 dns_rdatatype_t covers, dns_name_t **name,
2096 dns_rdataset_t **rdataset)
2098 dns_name_t *foundname;
2099 isc_result_t result;
2102 * XXX These requirements are probably too intensive, especially
2103 * where things can be NULL, but as they are they ensure that if
2104 * something is NON-NULL, indicating that the caller expects it
2105 * to be filled in, that we can in fact fill it in.
2107 REQUIRE(msg != NULL);
2108 REQUIRE(VALID_SECTION(section));
2109 REQUIRE(target != NULL);
2111 REQUIRE(*name == NULL);
2112 if (type == dns_rdatatype_any) {
2113 REQUIRE(rdataset == NULL);
2115 if (rdataset != NULL)
2116 REQUIRE(*rdataset == NULL);
2119 result = findname(&foundname, target,
2120 &msg->sections[section]);
2122 if (result == ISC_R_NOTFOUND)
2123 return (DNS_R_NXDOMAIN);
2124 else if (result != ISC_R_SUCCESS)
2131 * And now look for the type.
2133 if (type == dns_rdatatype_any)
2134 return (ISC_R_SUCCESS);
2136 result = dns_message_findtype(foundname, type, covers, rdataset);
2137 if (result == ISC_R_NOTFOUND)
2138 return (DNS_R_NXRRSET);
2144 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2145 dns_section_t fromsection,
2146 dns_section_t tosection)
2148 REQUIRE(msg != NULL);
2149 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2150 REQUIRE(name != NULL);
2151 REQUIRE(VALID_NAMED_SECTION(fromsection));
2152 REQUIRE(VALID_NAMED_SECTION(tosection));
2155 * Unlink the name from the old section
2157 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2158 ISC_LIST_APPEND(msg->sections[tosection], name, link);
2162 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2163 dns_section_t section)
2165 REQUIRE(msg != NULL);
2166 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2167 REQUIRE(name != NULL);
2168 REQUIRE(VALID_NAMED_SECTION(section));
2170 ISC_LIST_APPEND(msg->sections[section], name, link);
2174 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2175 REQUIRE(DNS_MESSAGE_VALID(msg));
2176 REQUIRE(item != NULL && *item == NULL);
2178 *item = isc_mempool_get(msg->namepool);
2180 return (ISC_R_NOMEMORY);
2181 dns_name_init(*item, NULL);
2183 return (ISC_R_SUCCESS);
2187 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2188 REQUIRE(DNS_MESSAGE_VALID(msg));
2189 REQUIRE(item != NULL && *item == NULL);
2191 *item = newoffsets(msg);
2193 return (ISC_R_NOMEMORY);
2195 return (ISC_R_SUCCESS);
2199 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2200 REQUIRE(DNS_MESSAGE_VALID(msg));
2201 REQUIRE(item != NULL && *item == NULL);
2203 *item = newrdata(msg);
2205 return (ISC_R_NOMEMORY);
2207 return (ISC_R_SUCCESS);
2211 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2212 REQUIRE(DNS_MESSAGE_VALID(msg));
2213 REQUIRE(item != NULL && *item == NULL);
2215 *item = isc_mempool_get(msg->rdspool);
2217 return (ISC_R_NOMEMORY);
2219 dns_rdataset_init(*item);
2221 return (ISC_R_SUCCESS);
2225 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2226 REQUIRE(DNS_MESSAGE_VALID(msg));
2227 REQUIRE(item != NULL && *item == NULL);
2229 *item = newrdatalist(msg);
2231 return (ISC_R_NOMEMORY);
2233 return (ISC_R_SUCCESS);
2237 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2238 REQUIRE(DNS_MESSAGE_VALID(msg));
2239 REQUIRE(item != NULL && *item != NULL);
2241 if (dns_name_dynamic(*item))
2242 dns_name_free(*item, msg->mctx);
2243 isc_mempool_put(msg->namepool, *item);
2248 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2249 REQUIRE(DNS_MESSAGE_VALID(msg));
2250 REQUIRE(item != NULL && *item != NULL);
2252 releaserdata(msg, *item);
2257 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2258 REQUIRE(DNS_MESSAGE_VALID(msg));
2259 REQUIRE(item != NULL && *item != NULL);
2261 REQUIRE(!dns_rdataset_isassociated(*item));
2262 isc_mempool_put(msg->rdspool, *item);
2267 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2268 REQUIRE(DNS_MESSAGE_VALID(msg));
2269 REQUIRE(item != NULL && *item != NULL);
2271 releaserdatalist(msg, *item);
2276 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2277 unsigned int *flagsp)
2280 isc_buffer_t buffer;
2284 REQUIRE(source != NULL);
2288 isc_buffer_remainingregion(&buffer, &r);
2289 if (r.length < DNS_MESSAGE_HEADERLEN)
2290 return (ISC_R_UNEXPECTEDEND);
2292 id = isc_buffer_getuint16(&buffer);
2293 flags = isc_buffer_getuint16(&buffer);
2294 flags &= DNS_MESSAGE_FLAG_MASK;
2301 return (ISC_R_SUCCESS);
2305 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2306 unsigned int first_section;
2307 isc_result_t result;
2309 REQUIRE(DNS_MESSAGE_VALID(msg));
2310 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2312 if (!msg->header_ok)
2313 return (DNS_R_FORMERR);
2314 if (msg->opcode != dns_opcode_query &&
2315 msg->opcode != dns_opcode_notify)
2316 want_question_section = ISC_FALSE;
2317 if (want_question_section) {
2318 if (!msg->question_ok)
2319 return (DNS_R_FORMERR);
2320 first_section = DNS_SECTION_ANSWER;
2322 first_section = DNS_SECTION_QUESTION;
2323 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2324 msgresetnames(msg, first_section);
2326 msgresetsigs(msg, ISC_TRUE);
2327 msginitprivate(msg);
2329 * We now clear most flags and then set QR, ensuring that the
2330 * reply's flags will be in a reasonable state.
2332 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2333 msg->flags |= DNS_MESSAGEFLAG_QR;
2336 * This saves the query TSIG status, if the query was signed, and
2337 * reserves space in the reply for the TSIG.
2339 if (msg->tsigkey != NULL) {
2340 unsigned int otherlen = 0;
2341 msg->querytsigstatus = msg->tsigstatus;
2342 msg->tsigstatus = dns_rcode_noerror;
2343 if (msg->querytsigstatus == dns_tsigerror_badtime)
2345 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2346 result = dns_message_renderreserve(msg, msg->sig_reserved);
2347 if (result != ISC_R_SUCCESS) {
2348 msg->sig_reserved = 0;
2352 if (msg->saved.base != NULL) {
2353 msg->query.base = msg->saved.base;
2354 msg->query.length = msg->saved.length;
2355 msg->free_query = msg->free_saved;
2356 msg->saved.base = NULL;
2357 msg->saved.length = 0;
2358 msg->free_saved = 0;
2361 return (ISC_R_SUCCESS);
2365 dns_message_getopt(dns_message_t *msg) {
2368 * Get the OPT record for 'msg'.
2371 REQUIRE(DNS_MESSAGE_VALID(msg));
2377 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2378 isc_result_t result;
2379 dns_rdata_t rdata = DNS_RDATA_INIT;
2382 * Set the OPT record for 'msg'.
2386 * The space required for an OPT record is:
2388 * 1 byte for the name
2389 * 2 bytes for the type
2390 * 2 bytes for the class
2391 * 4 bytes for the ttl
2392 * 2 bytes for the rdata length
2393 * ---------------------------------
2396 * plus the length of the rdata.
2399 REQUIRE(DNS_MESSAGE_VALID(msg));
2400 REQUIRE(opt->type == dns_rdatatype_opt);
2401 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2402 REQUIRE(msg->buffer != NULL);
2403 REQUIRE(msg->state == DNS_SECTION_ANY);
2407 result = dns_rdataset_first(opt);
2408 if (result != ISC_R_SUCCESS)
2410 dns_rdataset_current(opt, &rdata);
2411 msg->opt_reserved = 11 + rdata.length;
2412 result = dns_message_renderreserve(msg, msg->opt_reserved);
2413 if (result != ISC_R_SUCCESS) {
2414 msg->opt_reserved = 0;
2420 return (ISC_R_SUCCESS);
2423 dns_message_puttemprdataset(msg, &opt);
2429 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2432 * Get the TSIG record and owner for 'msg'.
2435 REQUIRE(DNS_MESSAGE_VALID(msg));
2436 REQUIRE(owner == NULL || *owner == NULL);
2439 *owner = msg->tsigname;
2444 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2445 isc_result_t result;
2448 * Set the TSIG key for 'msg'
2451 REQUIRE(DNS_MESSAGE_VALID(msg));
2452 REQUIRE(msg->state == DNS_SECTION_ANY);
2454 if (key == NULL && msg->tsigkey != NULL) {
2455 if (msg->sig_reserved != 0) {
2456 dns_message_renderrelease(msg, msg->sig_reserved);
2457 msg->sig_reserved = 0;
2459 dns_tsigkey_detach(&msg->tsigkey);
2462 dns_tsigkey_attach(key, &msg->tsigkey);
2463 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2464 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2465 result = dns_message_renderreserve(msg,
2467 if (result != ISC_R_SUCCESS) {
2468 msg->sig_reserved = 0;
2473 return (ISC_R_SUCCESS);
2477 dns_message_gettsigkey(dns_message_t *msg) {
2480 * Get the TSIG key for 'msg'
2483 REQUIRE(DNS_MESSAGE_VALID(msg));
2485 return (msg->tsigkey);
2489 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2490 dns_rdata_t *rdata = NULL;
2491 dns_rdatalist_t *list = NULL;
2492 dns_rdataset_t *set = NULL;
2493 isc_buffer_t *buf = NULL;
2495 isc_result_t result;
2497 REQUIRE(DNS_MESSAGE_VALID(msg));
2498 REQUIRE(msg->querytsig == NULL);
2500 if (querytsig == NULL)
2501 return (ISC_R_SUCCESS);
2503 result = dns_message_gettemprdata(msg, &rdata);
2504 if (result != ISC_R_SUCCESS)
2507 result = dns_message_gettemprdatalist(msg, &list);
2508 if (result != ISC_R_SUCCESS)
2510 result = dns_message_gettemprdataset(msg, &set);
2511 if (result != ISC_R_SUCCESS)
2514 isc_buffer_usedregion(querytsig, &r);
2515 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2516 if (result != ISC_R_SUCCESS)
2518 isc_buffer_putmem(buf, r.base, r.length);
2519 isc_buffer_usedregion(buf, &r);
2520 dns_rdata_init(rdata);
2521 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2522 dns_message_takebuffer(msg, &buf);
2523 ISC_LIST_INIT(list->rdata);
2524 ISC_LIST_APPEND(list->rdata, rdata, link);
2525 result = dns_rdatalist_tordataset(list, set);
2526 if (result != ISC_R_SUCCESS)
2529 msg->querytsig = set;
2535 dns_message_puttemprdata(msg, &rdata);
2537 dns_message_puttemprdatalist(msg, &list);
2539 dns_message_puttemprdataset(msg, &set);
2540 return (ISC_R_NOMEMORY);
2544 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2545 isc_buffer_t **querytsig) {
2546 isc_result_t result;
2547 dns_rdata_t rdata = DNS_RDATA_INIT;
2550 REQUIRE(DNS_MESSAGE_VALID(msg));
2551 REQUIRE(mctx != NULL);
2552 REQUIRE(querytsig != NULL && *querytsig == NULL);
2554 if (msg->tsig == NULL)
2555 return (ISC_R_SUCCESS);
2557 result = dns_rdataset_first(msg->tsig);
2558 if (result != ISC_R_SUCCESS)
2560 dns_rdataset_current(msg->tsig, &rdata);
2561 dns_rdata_toregion(&rdata, &r);
2563 result = isc_buffer_allocate(mctx, querytsig, r.length);
2564 if (result != ISC_R_SUCCESS)
2566 isc_buffer_putmem(*querytsig, r.base, r.length);
2567 return (ISC_R_SUCCESS);
2571 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2574 * Get the SIG(0) record for 'msg'.
2577 REQUIRE(DNS_MESSAGE_VALID(msg));
2578 REQUIRE(owner == NULL || *owner == NULL);
2580 if (msg->sig0 != NULL && owner != NULL) {
2581 /* If dns_message_getsig0 is called on a rendered message
2582 * after the SIG(0) has been applied, we need to return the
2583 * root name, not NULL.
2585 if (msg->sig0name == NULL)
2586 *owner = dns_rootname;
2588 *owner = msg->sig0name;
2594 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2597 isc_result_t result;
2600 * Set the SIG(0) key for 'msg'
2604 * The space required for an SIG(0) record is:
2606 * 1 byte for the name
2607 * 2 bytes for the type
2608 * 2 bytes for the class
2609 * 4 bytes for the ttl
2610 * 2 bytes for the type covered
2611 * 1 byte for the algorithm
2612 * 1 bytes for the labels
2613 * 4 bytes for the original ttl
2614 * 4 bytes for the signature expiration
2615 * 4 bytes for the signature inception
2616 * 2 bytes for the key tag
2617 * n bytes for the signer's name
2618 * x bytes for the signature
2619 * ---------------------------------
2622 REQUIRE(DNS_MESSAGE_VALID(msg));
2623 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2624 REQUIRE(msg->state == DNS_SECTION_ANY);
2628 dns_name_toregion(dst_key_name(key), &r);
2629 result = dst_key_sigsize(key, &x);
2630 if (result != ISC_R_SUCCESS) {
2631 msg->sig_reserved = 0;
2634 msg->sig_reserved = 27 + r.length + x;
2635 result = dns_message_renderreserve(msg, msg->sig_reserved);
2636 if (result != ISC_R_SUCCESS) {
2637 msg->sig_reserved = 0;
2641 return (ISC_R_SUCCESS);
2645 dns_message_getsig0key(dns_message_t *msg) {
2648 * Get the SIG(0) key for 'msg'
2651 REQUIRE(DNS_MESSAGE_VALID(msg));
2653 return (msg->sig0key);
2657 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2658 REQUIRE(DNS_MESSAGE_VALID(msg));
2659 REQUIRE(buffer != NULL);
2660 REQUIRE(ISC_BUFFER_VALID(*buffer));
2662 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2667 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2668 isc_result_t result = ISC_R_SUCCESS;
2669 dns_rdata_t rdata = DNS_RDATA_INIT;
2671 REQUIRE(DNS_MESSAGE_VALID(msg));
2672 REQUIRE(signer != NULL);
2673 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2675 if (msg->tsig == NULL && msg->sig0 == NULL)
2676 return (ISC_R_NOTFOUND);
2678 if (msg->verify_attempted == 0)
2679 return (DNS_R_NOTVERIFIEDYET);
2681 if (!dns_name_hasbuffer(signer)) {
2682 isc_buffer_t *dynbuf = NULL;
2683 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2684 if (result != ISC_R_SUCCESS)
2686 dns_name_setbuffer(signer, dynbuf);
2687 dns_message_takebuffer(msg, &dynbuf);
2690 if (msg->sig0 != NULL) {
2691 dns_rdata_sig_t sig;
2693 result = dns_rdataset_first(msg->sig0);
2694 INSIST(result == ISC_R_SUCCESS);
2695 dns_rdataset_current(msg->sig0, &rdata);
2697 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2698 if (result != ISC_R_SUCCESS)
2701 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2702 result = ISC_R_SUCCESS;
2704 result = DNS_R_SIGINVALID;
2705 dns_name_clone(&sig.signer, signer);
2706 dns_rdata_freestruct(&sig);
2708 dns_name_t *identity;
2709 dns_rdata_any_tsig_t tsig;
2711 result = dns_rdataset_first(msg->tsig);
2712 INSIST(result == ISC_R_SUCCESS);
2713 dns_rdataset_current(msg->tsig, &rdata);
2715 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2716 if (msg->tsigstatus != dns_rcode_noerror)
2717 result = DNS_R_TSIGVERIFYFAILURE;
2718 else if (tsig.error != dns_rcode_noerror)
2719 result = DNS_R_TSIGERRORSET;
2721 result = ISC_R_SUCCESS;
2722 dns_rdata_freestruct(&tsig);
2724 if (msg->tsigkey == NULL) {
2726 * If msg->tsigstatus & tsig.error are both
2727 * dns_rcode_noerror, the message must have been
2728 * verified, which means msg->tsigkey will be
2731 INSIST(result != ISC_R_SUCCESS);
2733 identity = dns_tsigkey_identity(msg->tsigkey);
2734 if (identity == NULL) {
2735 if (result == ISC_R_SUCCESS)
2736 result = DNS_R_NOIDENTITY;
2737 identity = &msg->tsigkey->name;
2739 dns_name_clone(identity, signer);
2747 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
2748 isc_buffer_t b, msgb;
2750 REQUIRE(DNS_MESSAGE_VALID(msg));
2752 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
2753 return (ISC_R_SUCCESS);
2754 INSIST(msg->saved.base != NULL);
2755 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
2756 isc_buffer_add(&msgb, msg->saved.length);
2757 if (msg->tsigkey != NULL || msg->tsig != NULL) {
2759 return (dns_view_checksig(view, &msgb, msg));
2761 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
2763 dns_rdata_t rdata = DNS_RDATA_INIT;
2764 dns_rdata_sig_t sig;
2765 dns_rdataset_t keyset;
2766 isc_result_t result;
2768 result = dns_rdataset_first(msg->sig0);
2769 INSIST(result == ISC_R_SUCCESS);
2770 dns_rdataset_current(msg->sig0, &rdata);
2773 * This can occur when the message is a dynamic update, since
2774 * the rdata length checking is relaxed. This should not
2775 * happen in a well-formed message, since the SIG(0) is only
2776 * looked for in the additional section, and the dynamic update
2777 * meta-records are in the prerequisite and update sections.
2779 if (rdata.length == 0)
2780 return (ISC_R_UNEXPECTEDEND);
2782 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
2783 if (result != ISC_R_SUCCESS)
2786 dns_rdataset_init(&keyset);
2788 return (DNS_R_KEYUNAUTHORIZED);
2789 result = dns_view_simplefind(view, &sig.signer,
2790 dns_rdatatype_key, 0, 0,
2791 ISC_FALSE, &keyset, NULL);
2793 if (result != ISC_R_SUCCESS) {
2794 /* XXXBEW Should possibly create a fetch here */
2795 result = DNS_R_KEYUNAUTHORIZED;
2797 } else if (keyset.trust < dns_trust_secure) {
2798 /* XXXBEW Should call a validator here */
2799 result = DNS_R_KEYUNAUTHORIZED;
2802 result = dns_rdataset_first(&keyset);
2803 INSIST(result == ISC_R_SUCCESS);
2805 result == ISC_R_SUCCESS;
2806 result = dns_rdataset_next(&keyset))
2808 dst_key_t *key = NULL;
2810 dns_rdataset_current(&keyset, &rdata);
2811 isc_buffer_init(&b, rdata.data, rdata.length);
2812 isc_buffer_add(&b, rdata.length);
2814 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
2815 &b, view->mctx, &key);
2816 if (result != ISC_R_SUCCESS)
2818 if (dst_key_alg(key) != sig.algorithm ||
2819 dst_key_id(key) != sig.keyid ||
2820 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
2821 dst_key_proto(key) == DNS_KEYPROTO_ANY))
2826 result = dns_dnssec_verifymessage(&msgb, msg, key);
2828 if (result == ISC_R_SUCCESS)
2831 if (result == ISC_R_NOMORE)
2832 result = DNS_R_KEYUNAUTHORIZED;
2835 if (dns_rdataset_isassociated(&keyset))
2836 dns_rdataset_disassociate(&keyset);
2837 dns_rdata_freestruct(&sig);
2843 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
2844 const dns_master_style_t *style,
2845 dns_messagetextflag_t flags,
2846 isc_buffer_t *target) {
2847 dns_name_t *name, empty_name;
2848 dns_rdataset_t *rdataset;
2849 isc_result_t result;
2851 REQUIRE(DNS_MESSAGE_VALID(msg));
2852 REQUIRE(target != NULL);
2853 REQUIRE(VALID_SECTION(section));
2855 if (ISC_LIST_EMPTY(msg->sections[section]))
2856 return (ISC_R_SUCCESS);
2858 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
2859 ADD_STRING(target, ";; ");
2860 if (msg->opcode != dns_opcode_update) {
2861 ADD_STRING(target, sectiontext[section]);
2864 ADD_STRING(target, updsectiontext[section]);
2866 ADD_STRING(target, " SECTION:\n");
2869 dns_name_init(&empty_name, NULL);
2870 result = dns_message_firstname(msg, section);
2871 if (result != ISC_R_SUCCESS) {
2876 dns_message_currentname(msg, section, &name);
2877 for (rdataset = ISC_LIST_HEAD(name->list);
2879 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2880 if (section == DNS_SECTION_QUESTION) {
2881 ADD_STRING(target, ";");
2882 result = dns_master_questiontotext(name,
2887 result = dns_master_rdatasettotext(name,
2892 if (result != ISC_R_SUCCESS)
2895 result = dns_message_nextname(msg, section);
2896 } while (result == ISC_R_SUCCESS);
2897 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
2898 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2899 ADD_STRING(target, "\n");
2900 if (result == ISC_R_NOMORE)
2901 result = ISC_R_SUCCESS;
2906 dns_message_pseudosectiontotext(dns_message_t *msg,
2907 dns_pseudosection_t section,
2908 const dns_master_style_t *style,
2909 dns_messagetextflag_t flags,
2910 isc_buffer_t *target) {
2911 dns_rdataset_t *ps = NULL;
2912 dns_name_t *name = NULL;
2913 isc_result_t result;
2914 char buf[sizeof("1234567890")];
2917 REQUIRE(DNS_MESSAGE_VALID(msg));
2918 REQUIRE(target != NULL);
2919 REQUIRE(VALID_PSEUDOSECTION(section));
2922 case DNS_PSEUDOSECTION_OPT:
2923 ps = dns_message_getopt(msg);
2925 return (ISC_R_SUCCESS);
2926 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2927 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
2928 ADD_STRING(target, "; EDNS: version: ");
2929 snprintf(buf, sizeof(buf), "%u",
2930 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
2931 ADD_STRING(target, buf);
2932 ADD_STRING(target, ", flags:");
2933 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
2934 ADD_STRING(target, " do");
2935 mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff;
2937 ADD_STRING(target, "; MBZ: ");
2938 snprintf(buf, sizeof(buf), "%.4x ", mbz);
2939 ADD_STRING(target, buf);
2940 ADD_STRING(target, ", udp: ");
2942 ADD_STRING(target, "; udp: ");
2943 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
2944 ADD_STRING(target, buf);
2945 return (ISC_R_SUCCESS);
2946 case DNS_PSEUDOSECTION_TSIG:
2947 ps = dns_message_gettsig(msg, &name);
2949 return (ISC_R_SUCCESS);
2950 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2951 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
2952 result = dns_master_rdatasettotext(name, ps, style, target);
2953 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
2954 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2955 ADD_STRING(target, "\n");
2957 case DNS_PSEUDOSECTION_SIG0:
2958 ps = dns_message_getsig0(msg, &name);
2960 return (ISC_R_SUCCESS);
2961 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2962 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
2963 result = dns_master_rdatasettotext(name, ps, style, target);
2964 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
2965 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
2966 ADD_STRING(target, "\n");
2969 return (ISC_R_UNEXPECTED);
2973 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
2974 dns_messagetextflag_t flags, isc_buffer_t *target) {
2975 char buf[sizeof "1234567890"];
2976 isc_result_t result;
2978 REQUIRE(DNS_MESSAGE_VALID(msg));
2979 REQUIRE(target != NULL);
2981 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
2982 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
2983 ADD_STRING(target, opcodetext[msg->opcode]);
2984 ADD_STRING(target, ", status: ");
2985 ADD_STRING(target, rcodetext[msg->rcode]);
2986 ADD_STRING(target, ", id: ");
2987 sprintf(buf, "%6u", msg->id);
2988 ADD_STRING(target, buf);
2989 ADD_STRING(target, "\n;; flags: ");
2990 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
2991 ADD_STRING(target, "qr ");
2992 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
2993 ADD_STRING(target, "aa ");
2994 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2995 ADD_STRING(target, "tc ");
2996 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
2997 ADD_STRING(target, "rd ");
2998 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
2999 ADD_STRING(target, "ra ");
3000 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3001 ADD_STRING(target, "ad ");
3002 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3003 ADD_STRING(target, "cd ");
3004 if (msg->opcode != dns_opcode_update) {
3005 ADD_STRING(target, "; QUESTION: ");
3007 ADD_STRING(target, "; ZONE: ");
3009 sprintf(buf, "%1u", msg->counts[DNS_SECTION_QUESTION]);
3010 ADD_STRING(target, buf);
3011 if (msg->opcode != dns_opcode_update) {
3012 ADD_STRING(target, ", ANSWER: ");
3014 ADD_STRING(target, ", PREREQ: ");
3016 sprintf(buf, "%1u", msg->counts[DNS_SECTION_ANSWER]);
3017 ADD_STRING(target, buf);
3018 if (msg->opcode != dns_opcode_update) {
3019 ADD_STRING(target, ", AUTHORITY: ");
3021 ADD_STRING(target, ", UPDATE: ");
3023 sprintf(buf, "%1u", msg->counts[DNS_SECTION_AUTHORITY]);
3024 ADD_STRING(target, buf);
3025 ADD_STRING(target, ", ADDITIONAL: ");
3026 sprintf(buf, "%1u", msg->counts[DNS_SECTION_ADDITIONAL]);
3027 ADD_STRING(target, buf);
3028 ADD_STRING(target, "\n");
3030 result = dns_message_pseudosectiontotext(msg,
3031 DNS_PSEUDOSECTION_OPT,
3032 style, flags, target);
3033 if (result != ISC_R_SUCCESS)
3036 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3037 style, flags, target);
3038 if (result != ISC_R_SUCCESS)
3040 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3041 style, flags, target);
3042 if (result != ISC_R_SUCCESS)
3044 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3045 style, flags, target);
3046 if (result != ISC_R_SUCCESS)
3048 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3049 style, flags, target);
3050 if (result != ISC_R_SUCCESS)
3053 result = dns_message_pseudosectiontotext(msg,
3054 DNS_PSEUDOSECTION_TSIG,
3055 style, flags, target);
3056 if (result != ISC_R_SUCCESS)
3059 result = dns_message_pseudosectiontotext(msg,
3060 DNS_PSEUDOSECTION_SIG0,
3061 style, flags, target);
3062 if (result != ISC_R_SUCCESS)
3065 return (ISC_R_SUCCESS);
3069 dns_message_getrawmessage(dns_message_t *msg) {
3070 REQUIRE(DNS_MESSAGE_VALID(msg));
3071 return (&msg->saved);
3075 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3078 REQUIRE(DNS_MESSAGE_VALID(msg));
3080 msg->order_arg = order_arg;
3084 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3085 REQUIRE(DNS_MESSAGE_VALID(msg));
3086 msg->timeadjust = timeadjust;
3090 dns_message_gettimeadjust(dns_message_t *msg) {
3091 REQUIRE(DNS_MESSAGE_VALID(msg));
3092 return (msg->timeadjust);