2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: message.c,v 1.237.110.8 2009/01/19 23:47:02 tbox Exp $ */
29 #include <isc/buffer.h>
31 #include <isc/print.h>
32 #include <isc/string.h> /* Required for HP/UX (and others?) */
35 #include <dns/dnssec.h>
36 #include <dns/keyvalues.h>
38 #include <dns/masterdump.h>
39 #include <dns/message.h>
40 #include <dns/opcode.h>
41 #include <dns/rdata.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/rdatastruct.h>
45 #include <dns/result.h>
51 hexdump(const char *msg
, const char *msg2
, void *base
, size_t len
) {
58 printf("*** %s [%s] (%u bytes @ %p)\n", msg
, msg2
, len
, base
);
63 else if (cnt
% 8 == 0)
65 printf(" %02x %c", *p
, (isprint(*p
) ? *p
: ' '));
78 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
79 #define DNS_MESSAGE_OPCODE_SHIFT 11
80 #define DNS_MESSAGE_RCODE_MASK 0x000fU
81 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
82 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
83 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
84 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
85 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
87 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
88 && ((s) < DNS_SECTION_MAX))
89 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
90 && ((s) < DNS_SECTION_MAX))
91 #define ADD_STRING(b, s) {if (strlen(s) >= \
92 isc_buffer_availablelength(b)) \
93 return(ISC_R_NOSPACE); else \
94 isc_buffer_putstr(b, s);}
95 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
96 && ((s) < DNS_PSEUDOSECTION_MAX))
99 * This is the size of each individual scratchpad buffer, and the numbers
100 * of various block allocations used within the server.
101 * XXXMLG These should come from a config setting.
103 #define SCRATCHPAD_SIZE 512
105 #define OFFSET_COUNT 4
106 #define RDATA_COUNT 8
107 #define RDATALIST_COUNT 8
108 #define RDATASET_COUNT RDATALIST_COUNT
111 * Text representation of the different items, for message_totext
114 static const char *sectiontext
[] = {
121 static const char *updsectiontext
[] = {
128 static const char *opcodetext
[] = {
147 static const char *rcodetext
[] = {
169 * "helper" type, which consists of a block of some type, and is linkable.
170 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
171 * size, or the allocated elements will not be aligned correctly.
173 struct dns_msgblock
{
175 unsigned int remaining
;
176 ISC_LINK(dns_msgblock_t
) link
;
177 }; /* dynamically sized */
179 static inline dns_msgblock_t
*
180 msgblock_allocate(isc_mem_t
*, unsigned int, unsigned int);
182 #define msgblock_get(block, type) \
183 ((type *)msgblock_internalget(block, sizeof(type)))
186 msgblock_internalget(dns_msgblock_t
*, unsigned int);
189 msgblock_reset(dns_msgblock_t
*);
192 msgblock_free(isc_mem_t
*, dns_msgblock_t
*, unsigned int);
195 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
196 * is free, return NULL.
198 static inline dns_msgblock_t
*
199 msgblock_allocate(isc_mem_t
*mctx
, unsigned int sizeof_type
,
202 dns_msgblock_t
*block
;
205 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* count
);
207 block
= isc_mem_get(mctx
, length
);
211 block
->count
= count
;
212 block
->remaining
= count
;
214 ISC_LINK_INIT(block
, link
);
220 * Return an element from the msgblock. If no more are available, return
224 msgblock_internalget(dns_msgblock_t
*block
, unsigned int sizeof_type
) {
227 if (block
== NULL
|| block
->remaining
== 0)
232 ptr
= (((unsigned char *)block
)
233 + sizeof(dns_msgblock_t
)
234 + (sizeof_type
* block
->remaining
));
240 msgblock_reset(dns_msgblock_t
*block
) {
241 block
->remaining
= block
->count
;
245 * Release memory associated with a message block.
248 msgblock_free(isc_mem_t
*mctx
, dns_msgblock_t
*block
, unsigned int sizeof_type
)
252 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* block
->count
);
254 isc_mem_put(mctx
, block
, length
);
258 * Allocate a new dynamic buffer, and attach it to this message as the
259 * "current" buffer. (which is always the last on the list, for our
262 static inline isc_result_t
263 newbuffer(dns_message_t
*msg
, unsigned int size
) {
265 isc_buffer_t
*dynbuf
;
268 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, size
);
269 if (result
!= ISC_R_SUCCESS
)
270 return (ISC_R_NOMEMORY
);
272 ISC_LIST_APPEND(msg
->scratchpad
, dynbuf
, link
);
273 return (ISC_R_SUCCESS
);
276 static inline isc_buffer_t
*
277 currentbuffer(dns_message_t
*msg
) {
278 isc_buffer_t
*dynbuf
;
280 dynbuf
= ISC_LIST_TAIL(msg
->scratchpad
);
281 INSIST(dynbuf
!= NULL
);
287 releaserdata(dns_message_t
*msg
, dns_rdata_t
*rdata
) {
288 ISC_LIST_PREPEND(msg
->freerdata
, rdata
, link
);
291 static inline dns_rdata_t
*
292 newrdata(dns_message_t
*msg
) {
293 dns_msgblock_t
*msgblock
;
296 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
298 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
302 msgblock
= ISC_LIST_TAIL(msg
->rdatas
);
303 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
305 msgblock
= msgblock_allocate(msg
->mctx
, sizeof(dns_rdata_t
),
307 if (msgblock
== NULL
)
310 ISC_LIST_APPEND(msg
->rdatas
, msgblock
, link
);
312 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
315 dns_rdata_init(rdata
);
320 releaserdatalist(dns_message_t
*msg
, dns_rdatalist_t
*rdatalist
) {
321 ISC_LIST_PREPEND(msg
->freerdatalist
, rdatalist
, link
);
324 static inline dns_rdatalist_t
*
325 newrdatalist(dns_message_t
*msg
) {
326 dns_msgblock_t
*msgblock
;
327 dns_rdatalist_t
*rdatalist
;
329 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
330 if (rdatalist
!= NULL
) {
331 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
335 msgblock
= ISC_LIST_TAIL(msg
->rdatalists
);
336 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
337 if (rdatalist
== NULL
) {
338 msgblock
= msgblock_allocate(msg
->mctx
,
339 sizeof(dns_rdatalist_t
),
341 if (msgblock
== NULL
)
344 ISC_LIST_APPEND(msg
->rdatalists
, msgblock
, link
);
346 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
352 static inline dns_offsets_t
*
353 newoffsets(dns_message_t
*msg
) {
354 dns_msgblock_t
*msgblock
;
355 dns_offsets_t
*offsets
;
357 msgblock
= ISC_LIST_TAIL(msg
->offsets
);
358 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
359 if (offsets
== NULL
) {
360 msgblock
= msgblock_allocate(msg
->mctx
,
361 sizeof(dns_offsets_t
),
363 if (msgblock
== NULL
)
366 ISC_LIST_APPEND(msg
->offsets
, msgblock
, link
);
368 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
375 msginitheader(dns_message_t
*m
) {
384 msginitprivate(dns_message_t
*m
) {
387 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
388 m
->cursors
[i
] = NULL
;
396 m
->state
= DNS_SECTION_ANY
; /* indicate nothing parsed or rendered */
404 msginittsig(dns_message_t
*m
) {
405 m
->tsigstatus
= dns_rcode_noerror
;
406 m
->querytsigstatus
= dns_rcode_noerror
;
411 m
->sig0status
= dns_rcode_noerror
;
416 * Init elements to default state. Used both when allocating a new element
417 * and when resetting one.
420 msginit(dns_message_t
*m
) {
426 m
->tcp_continuation
= 0;
428 m
->verify_attempted
= 0;
431 m
->query
.base
= NULL
;
434 m
->saved
.base
= NULL
;
441 msgresetnames(dns_message_t
*msg
, unsigned int first_section
) {
443 dns_name_t
*name
, *next_name
;
444 dns_rdataset_t
*rds
, *next_rds
;
447 * Clean up name lists by calling the rdataset disassociate function.
449 for (i
= first_section
; i
< DNS_SECTION_MAX
; i
++) {
450 name
= ISC_LIST_HEAD(msg
->sections
[i
]);
451 while (name
!= NULL
) {
452 next_name
= ISC_LIST_NEXT(name
, link
);
453 ISC_LIST_UNLINK(msg
->sections
[i
], name
, link
);
455 rds
= ISC_LIST_HEAD(name
->list
);
456 while (rds
!= NULL
) {
457 next_rds
= ISC_LIST_NEXT(rds
, link
);
458 ISC_LIST_UNLINK(name
->list
, rds
, link
);
460 INSIST(dns_rdataset_isassociated(rds
));
461 dns_rdataset_disassociate(rds
);
462 isc_mempool_put(msg
->rdspool
, rds
);
465 if (dns_name_dynamic(name
))
466 dns_name_free(name
, msg
->mctx
);
467 isc_mempool_put(msg
->namepool
, name
);
474 msgresetopt(dns_message_t
*msg
)
476 if (msg
->opt
!= NULL
) {
477 if (msg
->opt_reserved
> 0) {
478 dns_message_renderrelease(msg
, msg
->opt_reserved
);
479 msg
->opt_reserved
= 0;
481 INSIST(dns_rdataset_isassociated(msg
->opt
));
482 dns_rdataset_disassociate(msg
->opt
);
483 isc_mempool_put(msg
->rdspool
, msg
->opt
);
489 msgresetsigs(dns_message_t
*msg
, isc_boolean_t replying
) {
490 if (msg
->sig_reserved
> 0) {
491 dns_message_renderrelease(msg
, msg
->sig_reserved
);
492 msg
->sig_reserved
= 0;
494 if (msg
->tsig
!= NULL
) {
495 INSIST(dns_rdataset_isassociated(msg
->tsig
));
496 INSIST(msg
->namepool
!= NULL
);
498 INSIST(msg
->querytsig
== NULL
);
499 msg
->querytsig
= msg
->tsig
;
501 dns_rdataset_disassociate(msg
->tsig
);
502 isc_mempool_put(msg
->rdspool
, msg
->tsig
);
503 if (msg
->querytsig
!= NULL
) {
504 dns_rdataset_disassociate(msg
->querytsig
);
505 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
508 if (dns_name_dynamic(msg
->tsigname
))
509 dns_name_free(msg
->tsigname
, msg
->mctx
);
510 isc_mempool_put(msg
->namepool
, msg
->tsigname
);
512 msg
->tsigname
= NULL
;
513 } else if (msg
->querytsig
!= NULL
&& !replying
) {
514 dns_rdataset_disassociate(msg
->querytsig
);
515 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
516 msg
->querytsig
= NULL
;
518 if (msg
->sig0
!= NULL
) {
519 INSIST(dns_rdataset_isassociated(msg
->sig0
));
520 dns_rdataset_disassociate(msg
->sig0
);
521 isc_mempool_put(msg
->rdspool
, msg
->sig0
);
522 if (msg
->sig0name
!= NULL
) {
523 if (dns_name_dynamic(msg
->sig0name
))
524 dns_name_free(msg
->sig0name
, msg
->mctx
);
525 isc_mempool_put(msg
->namepool
, msg
->sig0name
);
528 msg
->sig0name
= NULL
;
533 * Free all but one (or everything) for this message. This is used by
534 * both dns_message_reset() and dns_message_destroy().
537 msgreset(dns_message_t
*msg
, isc_boolean_t everything
) {
538 dns_msgblock_t
*msgblock
, *next_msgblock
;
539 isc_buffer_t
*dynbuf
, *next_dynbuf
;
541 dns_rdatalist_t
*rdatalist
;
543 msgresetnames(msg
, 0);
545 msgresetsigs(msg
, ISC_FALSE
);
548 * Clean up linked lists.
552 * Run through the free lists, and just unlink anything found there.
553 * The memory isn't lost since these are part of message blocks we
556 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
557 while (rdata
!= NULL
) {
558 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
559 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
561 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
562 while (rdatalist
!= NULL
) {
563 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
564 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
567 dynbuf
= ISC_LIST_HEAD(msg
->scratchpad
);
568 INSIST(dynbuf
!= NULL
);
570 isc_buffer_clear(dynbuf
);
571 dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
573 while (dynbuf
!= NULL
) {
574 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
575 ISC_LIST_UNLINK(msg
->scratchpad
, dynbuf
, link
);
576 isc_buffer_free(&dynbuf
);
577 dynbuf
= next_dynbuf
;
580 msgblock
= ISC_LIST_HEAD(msg
->rdatas
);
581 if (!everything
&& msgblock
!= NULL
) {
582 msgblock_reset(msgblock
);
583 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
585 while (msgblock
!= NULL
) {
586 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
587 ISC_LIST_UNLINK(msg
->rdatas
, msgblock
, link
);
588 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdata_t
));
589 msgblock
= next_msgblock
;
593 * rdatalists could be empty.
596 msgblock
= ISC_LIST_HEAD(msg
->rdatalists
);
597 if (!everything
&& msgblock
!= NULL
) {
598 msgblock_reset(msgblock
);
599 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
601 while (msgblock
!= NULL
) {
602 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
603 ISC_LIST_UNLINK(msg
->rdatalists
, msgblock
, link
);
604 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdatalist_t
));
605 msgblock
= next_msgblock
;
608 msgblock
= ISC_LIST_HEAD(msg
->offsets
);
609 if (!everything
&& msgblock
!= NULL
) {
610 msgblock_reset(msgblock
);
611 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
613 while (msgblock
!= NULL
) {
614 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
615 ISC_LIST_UNLINK(msg
->offsets
, msgblock
, link
);
616 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_offsets_t
));
617 msgblock
= next_msgblock
;
620 if (msg
->tsigkey
!= NULL
) {
621 dns_tsigkey_detach(&msg
->tsigkey
);
625 if (msg
->tsigctx
!= NULL
)
626 dst_context_destroy(&msg
->tsigctx
);
628 if (msg
->query
.base
!= NULL
) {
629 if (msg
->free_query
!= 0)
630 isc_mem_put(msg
->mctx
, msg
->query
.base
,
632 msg
->query
.base
= NULL
;
633 msg
->query
.length
= 0;
636 if (msg
->saved
.base
!= NULL
) {
637 if (msg
->free_saved
!= 0)
638 isc_mem_put(msg
->mctx
, msg
->saved
.base
,
640 msg
->saved
.base
= NULL
;
641 msg
->saved
.length
= 0;
645 * cleanup the buffer cleanup list
647 dynbuf
= ISC_LIST_HEAD(msg
->cleanup
);
648 while (dynbuf
!= NULL
) {
649 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
650 ISC_LIST_UNLINK(msg
->cleanup
, dynbuf
, link
);
651 isc_buffer_free(&dynbuf
);
652 dynbuf
= next_dynbuf
;
656 * Set other bits to normal default values.
661 ENSURE(isc_mempool_getallocated(msg
->namepool
) == 0);
662 ENSURE(isc_mempool_getallocated(msg
->rdspool
) == 0);
666 spacefortsig(dns_tsigkey_t
*key
, int otherlen
) {
672 * The space required for an TSIG record is:
674 * n1 bytes for the name
675 * 2 bytes for the type
676 * 2 bytes for the class
677 * 4 bytes for the ttl
678 * 2 bytes for the rdlength
679 * n2 bytes for the algorithm name
680 * 6 bytes for the time signed
681 * 2 bytes for the fudge
682 * 2 bytes for the MAC size
683 * x bytes for the MAC
684 * 2 bytes for the original id
685 * 2 bytes for the error
686 * 2 bytes for the other data length
687 * y bytes for the other data (at most)
688 * ---------------------------------
689 * 26 + n1 + n2 + x + y bytes
692 dns_name_toregion(&key
->name
, &r1
);
693 dns_name_toregion(key
->algorithm
, &r2
);
694 if (key
->key
== NULL
)
697 result
= dst_key_sigsize(key
->key
, &x
);
698 if (result
!= ISC_R_SUCCESS
)
701 return (26 + r1
.length
+ r2
.length
+ x
+ otherlen
);
705 dns_message_create(isc_mem_t
*mctx
, unsigned int intent
, dns_message_t
**msgp
)
709 isc_buffer_t
*dynbuf
;
712 REQUIRE(mctx
!= NULL
);
713 REQUIRE(msgp
!= NULL
);
714 REQUIRE(*msgp
== NULL
);
715 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
716 || intent
== DNS_MESSAGE_INTENTRENDER
);
718 m
= isc_mem_get(mctx
, sizeof(dns_message_t
));
720 return (ISC_R_NOMEMORY
);
723 * No allocations until further notice. Just initialize all lists
724 * and other members that are freed in the cleanup phase here.
727 m
->magic
= DNS_MESSAGE_MAGIC
;
728 m
->from_to_wire
= intent
;
731 for (i
= 0; i
< DNS_SECTION_MAX
; i
++)
732 ISC_LIST_INIT(m
->sections
[i
]);
735 ISC_LIST_INIT(m
->scratchpad
);
736 ISC_LIST_INIT(m
->cleanup
);
739 ISC_LIST_INIT(m
->rdatas
);
740 ISC_LIST_INIT(m
->rdatalists
);
741 ISC_LIST_INIT(m
->offsets
);
742 ISC_LIST_INIT(m
->freerdata
);
743 ISC_LIST_INIT(m
->freerdatalist
);
746 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
749 result
= isc_mempool_create(m
->mctx
, sizeof(dns_name_t
), &m
->namepool
);
750 if (result
!= ISC_R_SUCCESS
)
752 isc_mempool_setfreemax(m
->namepool
, NAME_COUNT
);
753 isc_mempool_setname(m
->namepool
, "msg:names");
755 result
= isc_mempool_create(m
->mctx
, sizeof(dns_rdataset_t
),
757 if (result
!= ISC_R_SUCCESS
)
759 isc_mempool_setfreemax(m
->rdspool
, NAME_COUNT
);
760 isc_mempool_setname(m
->rdspool
, "msg:rdataset");
763 result
= isc_buffer_allocate(mctx
, &dynbuf
, SCRATCHPAD_SIZE
);
764 if (result
!= ISC_R_SUCCESS
)
766 ISC_LIST_APPEND(m
->scratchpad
, dynbuf
, link
);
771 return (ISC_R_SUCCESS
);
774 * Cleanup for error returns.
777 dynbuf
= ISC_LIST_HEAD(m
->scratchpad
);
778 if (dynbuf
!= NULL
) {
779 ISC_LIST_UNLINK(m
->scratchpad
, dynbuf
, link
);
780 isc_buffer_free(&dynbuf
);
782 if (m
->namepool
!= NULL
)
783 isc_mempool_destroy(&m
->namepool
);
784 if (m
->rdspool
!= NULL
)
785 isc_mempool_destroy(&m
->rdspool
);
787 isc_mem_put(mctx
, m
, sizeof(dns_message_t
));
789 return (ISC_R_NOMEMORY
);
793 dns_message_reset(dns_message_t
*msg
, unsigned int intent
) {
794 REQUIRE(DNS_MESSAGE_VALID(msg
));
795 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
796 || intent
== DNS_MESSAGE_INTENTRENDER
);
798 msgreset(msg
, ISC_FALSE
);
799 msg
->from_to_wire
= intent
;
803 dns_message_destroy(dns_message_t
**msgp
) {
806 REQUIRE(msgp
!= NULL
);
807 REQUIRE(DNS_MESSAGE_VALID(*msgp
));
812 msgreset(msg
, ISC_TRUE
);
813 isc_mempool_destroy(&msg
->namepool
);
814 isc_mempool_destroy(&msg
->rdspool
);
816 isc_mem_put(msg
->mctx
, msg
, sizeof(dns_message_t
));
820 findname(dns_name_t
**foundname
, dns_name_t
*target
,
821 dns_namelist_t
*section
)
825 for (curr
= ISC_LIST_TAIL(*section
);
827 curr
= ISC_LIST_PREV(curr
, link
)) {
828 if (dns_name_equal(curr
, target
)) {
829 if (foundname
!= NULL
)
831 return (ISC_R_SUCCESS
);
835 return (ISC_R_NOTFOUND
);
839 dns_message_find(dns_name_t
*name
, dns_rdataclass_t rdclass
,
840 dns_rdatatype_t type
, dns_rdatatype_t covers
,
841 dns_rdataset_t
**rdataset
)
843 dns_rdataset_t
*curr
;
845 if (rdataset
!= NULL
) {
846 REQUIRE(*rdataset
== NULL
);
849 for (curr
= ISC_LIST_TAIL(name
->list
);
851 curr
= ISC_LIST_PREV(curr
, link
)) {
852 if (curr
->rdclass
== rdclass
&&
853 curr
->type
== type
&& curr
->covers
== covers
) {
854 if (rdataset
!= NULL
)
856 return (ISC_R_SUCCESS
);
860 return (ISC_R_NOTFOUND
);
864 dns_message_findtype(dns_name_t
*name
, dns_rdatatype_t type
,
865 dns_rdatatype_t covers
, dns_rdataset_t
**rdataset
)
867 dns_rdataset_t
*curr
;
869 REQUIRE(name
!= NULL
);
870 if (rdataset
!= NULL
) {
871 REQUIRE(*rdataset
== NULL
);
874 for (curr
= ISC_LIST_TAIL(name
->list
);
876 curr
= ISC_LIST_PREV(curr
, link
)) {
877 if (curr
->type
== type
&& curr
->covers
== covers
) {
878 if (rdataset
!= NULL
)
880 return (ISC_R_SUCCESS
);
884 return (ISC_R_NOTFOUND
);
888 * Read a name from buffer "source".
891 getname(dns_name_t
*name
, isc_buffer_t
*source
, dns_message_t
*msg
,
892 dns_decompress_t
*dctx
)
894 isc_buffer_t
*scratch
;
898 scratch
= currentbuffer(msg
);
901 * First try: use current buffer.
902 * Second try: allocate a new buffer and use that.
906 result
= dns_name_fromwire(name
, source
, dctx
, ISC_FALSE
,
909 if (result
== ISC_R_NOSPACE
) {
912 result
= newbuffer(msg
, SCRATCHPAD_SIZE
);
913 if (result
!= ISC_R_SUCCESS
)
916 scratch
= currentbuffer(msg
);
917 dns_name_reset(name
);
923 INSIST(0); /* Cannot get here... */
924 return (ISC_R_UNEXPECTED
);
928 getrdata(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
929 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
,
930 unsigned int rdatalen
, dns_rdata_t
*rdata
)
932 isc_buffer_t
*scratch
;
935 unsigned int trysize
;
937 scratch
= currentbuffer(msg
);
939 isc_buffer_setactive(source
, rdatalen
);
942 * First try: use current buffer.
943 * Second try: allocate a new buffer of size
944 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
945 * (the data will fit if it was not more than 50% compressed)
946 * Subsequent tries: double buffer size on each try.
950 /* XXX possibly change this to a while (tries < 2) loop */
952 result
= dns_rdata_fromwire(rdata
, rdclass
, rdtype
,
956 if (result
== ISC_R_NOSPACE
) {
958 trysize
= 2 * rdatalen
;
959 if (trysize
< SCRATCHPAD_SIZE
)
960 trysize
= SCRATCHPAD_SIZE
;
962 INSIST(trysize
!= 0);
963 if (trysize
>= 65535)
964 return (ISC_R_NOSPACE
);
965 /* XXX DNS_R_RRTOOLONG? */
969 result
= newbuffer(msg
, trysize
);
970 if (result
!= ISC_R_SUCCESS
)
973 scratch
= currentbuffer(msg
);
983 seen_problem = ISC_TRUE; \
985 result = DNS_R_FORMERR; \
991 getquestions(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
992 unsigned int options
)
998 dns_offsets_t
*offsets
;
999 dns_rdataset_t
*rdataset
;
1000 dns_rdatalist_t
*rdatalist
;
1001 isc_result_t result
;
1002 dns_rdatatype_t rdtype
;
1003 dns_rdataclass_t rdclass
;
1004 dns_namelist_t
*section
;
1005 isc_boolean_t free_name
;
1006 isc_boolean_t best_effort
;
1007 isc_boolean_t seen_problem
;
1009 section
= &msg
->sections
[DNS_SECTION_QUESTION
];
1011 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1012 seen_problem
= ISC_FALSE
;
1018 for (count
= 0; count
< msg
->counts
[DNS_SECTION_QUESTION
]; count
++) {
1019 name
= isc_mempool_get(msg
->namepool
);
1021 return (ISC_R_NOMEMORY
);
1022 free_name
= ISC_TRUE
;
1024 offsets
= newoffsets(msg
);
1025 if (offsets
== NULL
) {
1026 result
= ISC_R_NOMEMORY
;
1029 dns_name_init(name
, *offsets
);
1032 * Parse the name out of this packet.
1034 isc_buffer_remainingregion(source
, &r
);
1035 isc_buffer_setactive(source
, r
.length
);
1036 result
= getname(name
, source
, msg
, dctx
);
1037 if (result
!= ISC_R_SUCCESS
)
1041 * Run through the section, looking to see if this name
1042 * is already there. If it is found, put back the allocated
1043 * name since we no longer need it, and set our name pointer
1044 * to point to the name we found.
1046 result
= findname(&name2
, name
, section
);
1049 * If it is the first name in the section, accept it.
1051 * If it is not, but is not the same as the name already
1052 * in the question section, append to the section. Note that
1053 * here in the question section this is illegal, so return
1054 * FORMERR. In the future, check the opcode to see if
1055 * this should be legal or not. In either case we no longer
1056 * need this name pointer.
1058 if (result
!= ISC_R_SUCCESS
) {
1059 if (!ISC_LIST_EMPTY(*section
))
1061 ISC_LIST_APPEND(*section
, name
, link
);
1062 free_name
= ISC_FALSE
;
1064 isc_mempool_put(msg
->namepool
, name
);
1067 free_name
= ISC_FALSE
;
1071 * Get type and class.
1073 isc_buffer_remainingregion(source
, &r
);
1075 result
= ISC_R_UNEXPECTEDEND
;
1078 rdtype
= isc_buffer_getuint16(source
);
1079 rdclass
= isc_buffer_getuint16(source
);
1082 * If this class is different than the one we already read,
1085 if (msg
->state
== DNS_SECTION_ANY
) {
1086 msg
->state
= DNS_SECTION_QUESTION
;
1087 msg
->rdclass
= rdclass
;
1088 } else if (msg
->rdclass
!= rdclass
)
1092 * Can't ask the same question twice.
1094 result
= dns_message_find(name
, rdclass
, rdtype
, 0, NULL
);
1095 if (result
== ISC_R_SUCCESS
)
1099 * Allocate a new rdatalist.
1101 rdatalist
= newrdatalist(msg
);
1102 if (rdatalist
== NULL
) {
1103 result
= ISC_R_NOMEMORY
;
1106 rdataset
= isc_mempool_get(msg
->rdspool
);
1107 if (rdataset
== NULL
) {
1108 result
= ISC_R_NOMEMORY
;
1113 * Convert rdatalist to rdataset, and attach the latter to
1116 rdatalist
->type
= rdtype
;
1117 rdatalist
->covers
= 0;
1118 rdatalist
->rdclass
= rdclass
;
1120 ISC_LIST_INIT(rdatalist
->rdata
);
1122 dns_rdataset_init(rdataset
);
1123 result
= dns_rdatalist_tordataset(rdatalist
, rdataset
);
1124 if (result
!= ISC_R_SUCCESS
)
1127 rdataset
->attributes
|= DNS_RDATASETATTR_QUESTION
;
1129 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1134 return (DNS_R_RECOVERABLE
);
1135 return (ISC_R_SUCCESS
);
1138 if (rdataset
!= NULL
) {
1139 INSIST(!dns_rdataset_isassociated(rdataset
));
1140 isc_mempool_put(msg
->rdspool
, rdataset
);
1143 if (rdatalist
!= NULL
)
1144 isc_mempool_put(msg
->rdlpool
, rdatalist
);
1147 isc_mempool_put(msg
->namepool
, name
);
1152 static isc_boolean_t
1153 update(dns_section_t section
, dns_rdataclass_t rdclass
) {
1154 if (section
== DNS_SECTION_PREREQUISITE
)
1155 return (ISC_TF(rdclass
== dns_rdataclass_any
||
1156 rdclass
== dns_rdataclass_none
));
1157 if (section
== DNS_SECTION_UPDATE
)
1158 return (ISC_TF(rdclass
== dns_rdataclass_any
));
1163 getsection(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
1164 dns_section_t sectionid
, unsigned int options
)
1167 unsigned int count
, rdatalen
;
1170 dns_offsets_t
*offsets
;
1171 dns_rdataset_t
*rdataset
;
1172 dns_rdatalist_t
*rdatalist
;
1173 isc_result_t result
;
1174 dns_rdatatype_t rdtype
, covers
;
1175 dns_rdataclass_t rdclass
;
1178 dns_namelist_t
*section
;
1179 isc_boolean_t free_name
, free_rdataset
;
1180 isc_boolean_t preserve_order
, best_effort
, seen_problem
;
1181 isc_boolean_t issigzero
;
1183 preserve_order
= ISC_TF(options
& DNS_MESSAGEPARSE_PRESERVEORDER
);
1184 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1185 seen_problem
= ISC_FALSE
;
1187 for (count
= 0; count
< msg
->counts
[sectionid
]; count
++) {
1188 int recstart
= source
->current
;
1189 isc_boolean_t skip_name_search
, skip_type_search
;
1191 section
= &msg
->sections
[sectionid
];
1193 skip_name_search
= ISC_FALSE
;
1194 skip_type_search
= ISC_FALSE
;
1195 free_name
= ISC_FALSE
;
1196 free_rdataset
= ISC_FALSE
;
1198 name
= isc_mempool_get(msg
->namepool
);
1200 return (ISC_R_NOMEMORY
);
1201 free_name
= ISC_TRUE
;
1203 offsets
= newoffsets(msg
);
1204 if (offsets
== NULL
) {
1205 result
= ISC_R_NOMEMORY
;
1208 dns_name_init(name
, *offsets
);
1211 * Parse the name out of this packet.
1213 isc_buffer_remainingregion(source
, &r
);
1214 isc_buffer_setactive(source
, r
.length
);
1215 result
= getname(name
, source
, msg
, dctx
);
1216 if (result
!= ISC_R_SUCCESS
)
1220 * Get type, class, ttl, and rdatalen. Verify that at least
1221 * rdatalen bytes remain. (Some of this is deferred to
1224 isc_buffer_remainingregion(source
, &r
);
1225 if (r
.length
< 2 + 2 + 4 + 2) {
1226 result
= ISC_R_UNEXPECTEDEND
;
1229 rdtype
= isc_buffer_getuint16(source
);
1230 rdclass
= isc_buffer_getuint16(source
);
1233 * If there was no question section, we may not yet have
1234 * established a class. Do so now.
1236 if (msg
->state
== DNS_SECTION_ANY
&&
1237 rdtype
!= dns_rdatatype_opt
&& /* class is UDP SIZE */
1238 rdtype
!= dns_rdatatype_tsig
&& /* class is ANY */
1239 rdtype
!= dns_rdatatype_tkey
) { /* class is undefined */
1240 msg
->rdclass
= rdclass
;
1241 msg
->state
= DNS_SECTION_QUESTION
;
1245 * If this class is different than the one in the question
1248 if (msg
->opcode
!= dns_opcode_update
1249 && rdtype
!= dns_rdatatype_tsig
1250 && rdtype
!= dns_rdatatype_opt
1251 && rdtype
!= dns_rdatatype_dnskey
/* in a TKEY query */
1252 && rdtype
!= dns_rdatatype_sig
/* SIG(0) */
1253 && rdtype
!= dns_rdatatype_tkey
/* Win2000 TKEY */
1254 && msg
->rdclass
!= dns_rdataclass_any
1255 && msg
->rdclass
!= rdclass
)
1259 * Special type handling for TSIG, OPT, and TKEY.
1261 if (rdtype
== dns_rdatatype_tsig
) {
1263 * If it is a tsig, verify that it is in the
1264 * additional data section.
1266 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1267 rdclass
!= dns_rdataclass_any
||
1268 count
!= msg
->counts
[sectionid
] - 1)
1270 msg
->sigstart
= recstart
;
1271 skip_name_search
= ISC_TRUE
;
1272 skip_type_search
= ISC_TRUE
;
1273 } else if (rdtype
== dns_rdatatype_opt
) {
1275 * The name of an OPT record must be ".", it
1276 * must be in the additional data section, and
1277 * it must be the first OPT we've seen.
1279 if (!dns_name_equal(dns_rootname
, name
) ||
1282 skip_name_search
= ISC_TRUE
;
1283 skip_type_search
= ISC_TRUE
;
1284 } else if (rdtype
== dns_rdatatype_tkey
) {
1286 * A TKEY must be in the additional section if this
1287 * is a query, and the answer section if this is a
1288 * response. Unless it's a Win2000 client.
1290 * Its class is ignored.
1292 dns_section_t tkeysection
;
1294 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0)
1295 tkeysection
= DNS_SECTION_ADDITIONAL
;
1297 tkeysection
= DNS_SECTION_ANSWER
;
1298 if (sectionid
!= tkeysection
&&
1299 sectionid
!= DNS_SECTION_ANSWER
)
1304 * ... now get ttl and rdatalen, and check buffer.
1306 ttl
= isc_buffer_getuint32(source
);
1307 rdatalen
= isc_buffer_getuint16(source
);
1308 r
.length
-= (2 + 2 + 4 + 2);
1309 if (r
.length
< rdatalen
) {
1310 result
= ISC_R_UNEXPECTEDEND
;
1315 * Read the rdata from the wire format. Interpret the
1316 * rdata according to its actual class, even if it had a
1317 * DynDNS meta-class in the packet (unless this is a TSIG).
1318 * Then put the meta-class back into the finished rdata.
1320 rdata
= newrdata(msg
);
1321 if (rdata
== NULL
) {
1322 result
= ISC_R_NOMEMORY
;
1325 if (msg
->opcode
== dns_opcode_update
&&
1326 update(sectionid
, rdclass
)) {
1327 if (rdatalen
!= 0) {
1328 result
= DNS_R_FORMERR
;
1332 * When the rdata is empty, the data pointer is
1333 * never dereferenced, but it must still be non-NULL.
1334 * Casting 1 rather than "" avoids warnings about
1335 * discarding the const attribute of a string,
1336 * for compilers that would warn about such things.
1338 rdata
->data
= (unsigned char *)1;
1340 rdata
->rdclass
= rdclass
;
1341 rdata
->type
= rdtype
;
1342 rdata
->flags
= DNS_RDATA_UPDATE
;
1343 result
= ISC_R_SUCCESS
;
1344 } else if (rdclass
== dns_rdataclass_none
&&
1345 msg
->opcode
== dns_opcode_update
&&
1346 sectionid
== DNS_SECTION_UPDATE
) {
1347 result
= getrdata(source
, msg
, dctx
, msg
->rdclass
,
1348 rdtype
, rdatalen
, rdata
);
1350 result
= getrdata(source
, msg
, dctx
, rdclass
,
1351 rdtype
, rdatalen
, rdata
);
1352 if (result
!= ISC_R_SUCCESS
)
1354 rdata
->rdclass
= rdclass
;
1355 issigzero
= ISC_FALSE
;
1356 if (rdtype
== dns_rdatatype_rrsig
&&
1357 rdata
->flags
== 0) {
1358 covers
= dns_rdata_covers(rdata
);
1361 } else if (rdtype
== dns_rdatatype_sig
/* SIG(0) */ &&
1362 rdata
->flags
== 0) {
1363 covers
= dns_rdata_covers(rdata
);
1365 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1366 count
!= msg
->counts
[sectionid
] - 1)
1368 msg
->sigstart
= recstart
;
1369 skip_name_search
= ISC_TRUE
;
1370 skip_type_search
= ISC_TRUE
;
1371 issigzero
= ISC_TRUE
;
1377 * If we are doing a dynamic update or this is a meta-type,
1378 * don't bother searching for a name, just append this one
1379 * to the end of the message.
1381 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1383 if (rdtype
!= dns_rdatatype_opt
&&
1384 rdtype
!= dns_rdatatype_tsig
&&
1387 ISC_LIST_APPEND(*section
, name
, link
);
1388 free_name
= ISC_FALSE
;
1392 * Run through the section, looking to see if this name
1393 * is already there. If it is found, put back the
1394 * allocated name since we no longer need it, and set
1395 * our name pointer to point to the name we found.
1397 result
= findname(&name2
, name
, section
);
1400 * If it is a new name, append to the section.
1402 if (result
== ISC_R_SUCCESS
) {
1403 isc_mempool_put(msg
->namepool
, name
);
1406 ISC_LIST_APPEND(*section
, name
, link
);
1408 free_name
= ISC_FALSE
;
1412 * Search name for the particular type and class.
1413 * Skip this stage if in update mode or this is a meta-type.
1415 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1417 result
= ISC_R_NOTFOUND
;
1420 * If this is a type that can only occur in
1421 * the question section, fail.
1423 if (dns_rdatatype_questiononly(rdtype
))
1427 result
= dns_message_find(name
, rdclass
, rdtype
,
1432 * If we found an rdataset that matches, we need to
1433 * append this rdata to that set. If we did not, we need
1434 * to create a new rdatalist, store the important bits there,
1435 * convert it to an rdataset, and link the latter to the name.
1436 * Yuck. When appending, make certain that the type isn't
1437 * a singleton type, such as SOA or CNAME.
1439 * Note that this check will be bypassed when preserving order,
1440 * the opcode is an update, or the type search is skipped.
1442 if (result
== ISC_R_SUCCESS
) {
1443 if (dns_rdatatype_issingleton(rdtype
))
1447 if (result
== ISC_R_NOTFOUND
) {
1448 rdataset
= isc_mempool_get(msg
->rdspool
);
1449 if (rdataset
== NULL
) {
1450 result
= ISC_R_NOMEMORY
;
1453 free_rdataset
= ISC_TRUE
;
1455 rdatalist
= newrdatalist(msg
);
1456 if (rdatalist
== NULL
) {
1457 result
= ISC_R_NOMEMORY
;
1461 rdatalist
->type
= rdtype
;
1462 rdatalist
->covers
= covers
;
1463 rdatalist
->rdclass
= rdclass
;
1464 rdatalist
->ttl
= ttl
;
1465 ISC_LIST_INIT(rdatalist
->rdata
);
1467 dns_rdataset_init(rdataset
);
1468 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
,
1472 if (rdtype
!= dns_rdatatype_opt
&&
1473 rdtype
!= dns_rdatatype_tsig
&&
1476 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1477 free_rdataset
= ISC_FALSE
;
1484 * Section 5.2 of RFC2181 says we should drop
1485 * nonauthoritative rrsets where the TTLs differ, but we
1486 * currently treat them the as if they were authoritative and
1489 if (ttl
!= rdataset
->ttl
) {
1490 rdataset
->attributes
|= DNS_RDATASETATTR_TTLADJUSTED
;
1491 if (ttl
< rdataset
->ttl
)
1492 rdataset
->ttl
= ttl
;
1495 /* Append this rdata to the rdataset. */
1496 dns_rdatalist_fromrdataset(rdataset
, &rdatalist
);
1497 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1500 * If this is an OPT record, remember it. Also, set
1501 * the extended rcode. Note that msg->opt will only be set
1502 * if best-effort parsing is enabled.
1504 if (rdtype
== dns_rdatatype_opt
&& msg
->opt
== NULL
) {
1507 msg
->opt
= rdataset
;
1509 free_rdataset
= ISC_FALSE
;
1510 ercode
= (dns_rcode_t
)
1511 ((msg
->opt
->ttl
& DNS_MESSAGE_EDNSRCODE_MASK
)
1513 msg
->rcode
|= ercode
;
1514 isc_mempool_put(msg
->namepool
, name
);
1515 free_name
= ISC_FALSE
;
1519 * If this is an SIG(0) or TSIG record, remember it. Note
1520 * that msg->sig0 or msg->tsig will only be set if best-effort
1521 * parsing is enabled.
1523 if (issigzero
&& msg
->sig0
== NULL
) {
1524 msg
->sig0
= rdataset
;
1525 msg
->sig0name
= name
;
1527 free_rdataset
= ISC_FALSE
;
1528 free_name
= ISC_FALSE
;
1529 } else if (rdtype
== dns_rdatatype_tsig
&& msg
->tsig
== NULL
) {
1530 msg
->tsig
= rdataset
;
1531 msg
->tsigname
= name
;
1533 free_rdataset
= ISC_FALSE
;
1534 free_name
= ISC_FALSE
;
1539 isc_mempool_put(msg
->namepool
, name
);
1541 isc_mempool_put(msg
->rdspool
, rdataset
);
1542 free_name
= free_rdataset
= ISC_FALSE
;
1544 INSIST(free_name
== ISC_FALSE
);
1545 INSIST(free_rdataset
== ISC_FALSE
);
1549 return (DNS_R_RECOVERABLE
);
1550 return (ISC_R_SUCCESS
);
1554 isc_mempool_put(msg
->namepool
, name
);
1556 isc_mempool_put(msg
->rdspool
, rdataset
);
1562 dns_message_parse(dns_message_t
*msg
, isc_buffer_t
*source
,
1563 unsigned int options
)
1566 dns_decompress_t dctx
;
1568 isc_uint16_t tmpflags
;
1569 isc_buffer_t origsource
;
1570 isc_boolean_t seen_problem
;
1571 isc_boolean_t ignore_tc
;
1573 REQUIRE(DNS_MESSAGE_VALID(msg
));
1574 REQUIRE(source
!= NULL
);
1575 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
1577 seen_problem
= ISC_FALSE
;
1578 ignore_tc
= ISC_TF(options
& DNS_MESSAGEPARSE_IGNORETRUNCATION
);
1580 origsource
= *source
;
1583 msg
->question_ok
= 0;
1585 isc_buffer_remainingregion(source
, &r
);
1586 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1587 return (ISC_R_UNEXPECTEDEND
);
1589 msg
->id
= isc_buffer_getuint16(source
);
1590 tmpflags
= isc_buffer_getuint16(source
);
1591 msg
->opcode
= ((tmpflags
& DNS_MESSAGE_OPCODE_MASK
)
1592 >> DNS_MESSAGE_OPCODE_SHIFT
);
1593 msg
->rcode
= (dns_rcode_t
)(tmpflags
& DNS_MESSAGE_RCODE_MASK
);
1594 msg
->flags
= (tmpflags
& DNS_MESSAGE_FLAG_MASK
);
1595 msg
->counts
[DNS_SECTION_QUESTION
] = isc_buffer_getuint16(source
);
1596 msg
->counts
[DNS_SECTION_ANSWER
] = isc_buffer_getuint16(source
);
1597 msg
->counts
[DNS_SECTION_AUTHORITY
] = isc_buffer_getuint16(source
);
1598 msg
->counts
[DNS_SECTION_ADDITIONAL
] = isc_buffer_getuint16(source
);
1605 dns_decompress_init(&dctx
, -1, DNS_DECOMPRESS_ANY
);
1607 dns_decompress_setmethods(&dctx
, DNS_COMPRESS_GLOBAL14
);
1609 ret
= getquestions(source
, msg
, &dctx
, options
);
1610 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1612 if (ret
== DNS_R_RECOVERABLE
) {
1613 seen_problem
= ISC_TRUE
;
1614 ret
= ISC_R_SUCCESS
;
1616 if (ret
!= ISC_R_SUCCESS
)
1618 msg
->question_ok
= 1;
1620 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ANSWER
, options
);
1621 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1623 if (ret
== DNS_R_RECOVERABLE
) {
1624 seen_problem
= ISC_TRUE
;
1625 ret
= ISC_R_SUCCESS
;
1627 if (ret
!= ISC_R_SUCCESS
)
1630 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_AUTHORITY
, options
);
1631 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1633 if (ret
== DNS_R_RECOVERABLE
) {
1634 seen_problem
= ISC_TRUE
;
1635 ret
= ISC_R_SUCCESS
;
1637 if (ret
!= ISC_R_SUCCESS
)
1640 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ADDITIONAL
, options
);
1641 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1643 if (ret
== DNS_R_RECOVERABLE
) {
1644 seen_problem
= ISC_TRUE
;
1645 ret
= ISC_R_SUCCESS
;
1647 if (ret
!= ISC_R_SUCCESS
)
1650 isc_buffer_remainingregion(source
, &r
);
1651 if (r
.length
!= 0) {
1652 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1653 DNS_LOGMODULE_MESSAGE
, ISC_LOG_DEBUG(3),
1654 "message has %u byte(s) of trailing garbage",
1659 if ((options
& DNS_MESSAGEPARSE_CLONEBUFFER
) == 0)
1660 isc_buffer_usedregion(&origsource
, &msg
->saved
);
1662 msg
->saved
.length
= isc_buffer_usedlength(&origsource
);
1663 msg
->saved
.base
= isc_mem_get(msg
->mctx
, msg
->saved
.length
);
1664 if (msg
->saved
.base
== NULL
)
1665 return (ISC_R_NOMEMORY
);
1666 memcpy(msg
->saved
.base
, isc_buffer_base(&origsource
),
1668 msg
->free_saved
= 1;
1671 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1672 return (DNS_R_RECOVERABLE
);
1673 if (seen_problem
== ISC_TRUE
)
1674 return (DNS_R_RECOVERABLE
);
1675 return (ISC_R_SUCCESS
);
1679 dns_message_renderbegin(dns_message_t
*msg
, dns_compress_t
*cctx
,
1680 isc_buffer_t
*buffer
)
1684 REQUIRE(DNS_MESSAGE_VALID(msg
));
1685 REQUIRE(buffer
!= NULL
);
1686 REQUIRE(msg
->buffer
== NULL
);
1687 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
1692 * Erase the contents of this buffer.
1694 isc_buffer_clear(buffer
);
1697 * Make certain there is enough for at least the header in this
1700 isc_buffer_availableregion(buffer
, &r
);
1701 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1702 return (ISC_R_NOSPACE
);
1704 if (r
.length
< msg
->reserved
)
1705 return (ISC_R_NOSPACE
);
1708 * Reserve enough space for the header in this buffer.
1710 isc_buffer_add(buffer
, DNS_MESSAGE_HEADERLEN
);
1712 msg
->buffer
= buffer
;
1714 return (ISC_R_SUCCESS
);
1718 dns_message_renderchangebuffer(dns_message_t
*msg
, isc_buffer_t
*buffer
) {
1721 REQUIRE(DNS_MESSAGE_VALID(msg
));
1722 REQUIRE(buffer
!= NULL
);
1723 REQUIRE(msg
->buffer
!= NULL
);
1726 * Ensure that the new buffer is empty, and has enough space to
1727 * hold the current contents.
1729 isc_buffer_clear(buffer
);
1731 isc_buffer_availableregion(buffer
, &rn
);
1732 isc_buffer_usedregion(msg
->buffer
, &r
);
1733 REQUIRE(rn
.length
> r
.length
);
1736 * Copy the contents from the old to the new buffer.
1738 isc_buffer_add(buffer
, r
.length
);
1739 memcpy(rn
.base
, r
.base
, r
.length
);
1741 msg
->buffer
= buffer
;
1743 return (ISC_R_SUCCESS
);
1747 dns_message_renderrelease(dns_message_t
*msg
, unsigned int space
) {
1748 REQUIRE(DNS_MESSAGE_VALID(msg
));
1749 REQUIRE(space
<= msg
->reserved
);
1751 msg
->reserved
-= space
;
1755 dns_message_renderreserve(dns_message_t
*msg
, unsigned int space
) {
1758 REQUIRE(DNS_MESSAGE_VALID(msg
));
1760 if (msg
->buffer
!= NULL
) {
1761 isc_buffer_availableregion(msg
->buffer
, &r
);
1762 if (r
.length
< (space
+ msg
->reserved
))
1763 return (ISC_R_NOSPACE
);
1766 msg
->reserved
+= space
;
1768 return (ISC_R_SUCCESS
);
1771 static inline isc_boolean_t
1772 wrong_priority(dns_rdataset_t
*rds
, int pass
, dns_rdatatype_t preferred_glue
) {
1776 * If we are not rendering class IN, this ordering is bogus.
1778 if (rds
->rdclass
!= dns_rdataclass_in
)
1781 switch (rds
->type
) {
1782 case dns_rdatatype_a
:
1783 case dns_rdatatype_aaaa
:
1784 if (preferred_glue
== rds
->type
)
1789 case dns_rdatatype_rrsig
:
1790 case dns_rdatatype_dnskey
:
1797 if (pass_needed
>= pass
)
1804 dns_message_rendersection(dns_message_t
*msg
, dns_section_t sectionid
,
1805 unsigned int options
)
1807 dns_namelist_t
*section
;
1808 dns_name_t
*name
, *next_name
;
1809 dns_rdataset_t
*rdataset
, *next_rdataset
;
1810 unsigned int count
, total
;
1811 isc_result_t result
;
1812 isc_buffer_t st
; /* for rollbacks */
1814 isc_boolean_t partial
= ISC_FALSE
;
1815 unsigned int rd_options
;
1816 dns_rdatatype_t preferred_glue
= 0;
1818 REQUIRE(DNS_MESSAGE_VALID(msg
));
1819 REQUIRE(msg
->buffer
!= NULL
);
1820 REQUIRE(VALID_NAMED_SECTION(sectionid
));
1822 section
= &msg
->sections
[sectionid
];
1824 if ((sectionid
== DNS_SECTION_ADDITIONAL
)
1825 && (options
& DNS_MESSAGERENDER_ORDERED
) == 0) {
1826 if ((options
& DNS_MESSAGERENDER_PREFER_A
) != 0) {
1827 preferred_glue
= dns_rdatatype_a
;
1829 } else if ((options
& DNS_MESSAGERENDER_PREFER_AAAA
) != 0) {
1830 preferred_glue
= dns_rdatatype_aaaa
;
1837 if ((options
& DNS_MESSAGERENDER_OMITDNSSEC
) == 0)
1840 rd_options
= DNS_RDATASETTOWIRE_OMITDNSSEC
;
1843 * Shrink the space in the buffer by the reserved amount.
1845 msg
->buffer
->length
-= msg
->reserved
;
1848 if (msg
->reserved
== 0 && (options
& DNS_MESSAGERENDER_PARTIAL
) != 0)
1852 * Render required glue first. Set TC if it won't fit.
1854 name
= ISC_LIST_HEAD(*section
);
1856 rdataset
= ISC_LIST_HEAD(name
->list
);
1857 if (rdataset
!= NULL
&&
1858 (rdataset
->attributes
& DNS_RDATASETATTR_REQUIREDGLUE
) != 0 &&
1859 (rdataset
->attributes
& DNS_RDATASETATTR_RENDERED
) == 0) {
1860 const void *order_arg
= msg
->order_arg
;
1861 st
= *(msg
->buffer
);
1864 result
= dns_rdataset_towirepartial(rdataset
,
1874 result
= dns_rdataset_towiresorted(rdataset
,
1883 if (partial
&& result
== ISC_R_NOSPACE
) {
1884 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1885 msg
->buffer
->length
+= msg
->reserved
;
1886 msg
->counts
[sectionid
] += total
;
1889 if (result
!= ISC_R_SUCCESS
) {
1890 INSIST(st
.used
< 65536);
1891 dns_compress_rollback(msg
->cctx
,
1892 (isc_uint16_t
)st
.used
);
1893 *(msg
->buffer
) = st
; /* rollback */
1894 msg
->buffer
->length
+= msg
->reserved
;
1895 msg
->counts
[sectionid
] += total
;
1898 rdataset
->attributes
|= DNS_RDATASETATTR_RENDERED
;
1903 name
= ISC_LIST_HEAD(*section
);
1905 msg
->buffer
->length
+= msg
->reserved
;
1906 msg
->counts
[sectionid
] += total
;
1907 return (ISC_R_SUCCESS
);
1910 while (name
!= NULL
) {
1911 next_name
= ISC_LIST_NEXT(name
, link
);
1913 rdataset
= ISC_LIST_HEAD(name
->list
);
1914 while (rdataset
!= NULL
) {
1915 next_rdataset
= ISC_LIST_NEXT(rdataset
, link
);
1917 if ((rdataset
->attributes
&
1918 DNS_RDATASETATTR_RENDERED
) != 0)
1921 if (((options
& DNS_MESSAGERENDER_ORDERED
)
1923 && (sectionid
== DNS_SECTION_ADDITIONAL
)
1924 && wrong_priority(rdataset
, pass
,
1928 st
= *(msg
->buffer
);
1932 result
= dns_rdataset_towirepartial(
1943 result
= dns_rdataset_towiresorted(
1956 * If out of space, record stats on what we
1957 * rendered so far, and return that status.
1959 * XXXMLG Need to change this when
1960 * dns_rdataset_towire() can render partial
1961 * sets starting at some arbitrary point in the
1962 * set. This will include setting a bit in the
1963 * rdataset to indicate that a partial
1964 * rendering was done, and some state saved
1965 * somewhere (probably in the message struct)
1966 * to indicate where to continue from.
1968 if (partial
&& result
== ISC_R_NOSPACE
) {
1969 msg
->buffer
->length
+= msg
->reserved
;
1970 msg
->counts
[sectionid
] += total
;
1973 if (result
!= ISC_R_SUCCESS
) {
1974 INSIST(st
.used
< 65536);
1975 dns_compress_rollback(msg
->cctx
,
1976 (isc_uint16_t
)st
.used
);
1977 *(msg
->buffer
) = st
; /* rollback */
1978 msg
->buffer
->length
+= msg
->reserved
;
1979 msg
->counts
[sectionid
] += total
;
1984 * If we have rendered non-validated data,
1985 * ensure that the AD bit is not set.
1987 if (rdataset
->trust
!= dns_trust_secure
&&
1988 (sectionid
== DNS_SECTION_ANSWER
||
1989 sectionid
== DNS_SECTION_AUTHORITY
))
1990 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
1992 rdataset
->attributes
|=
1993 DNS_RDATASETATTR_RENDERED
;
1996 rdataset
= next_rdataset
;
2001 } while (--pass
!= 0);
2003 msg
->buffer
->length
+= msg
->reserved
;
2004 msg
->counts
[sectionid
] += total
;
2006 return (ISC_R_SUCCESS
);
2010 dns_message_renderheader(dns_message_t
*msg
, isc_buffer_t
*target
) {
2014 REQUIRE(DNS_MESSAGE_VALID(msg
));
2015 REQUIRE(target
!= NULL
);
2017 isc_buffer_availableregion(target
, &r
);
2018 REQUIRE(r
.length
>= DNS_MESSAGE_HEADERLEN
);
2020 isc_buffer_putuint16(target
, msg
->id
);
2022 tmp
= ((msg
->opcode
<< DNS_MESSAGE_OPCODE_SHIFT
)
2023 & DNS_MESSAGE_OPCODE_MASK
);
2024 tmp
|= (msg
->rcode
& DNS_MESSAGE_RCODE_MASK
);
2025 tmp
|= (msg
->flags
& DNS_MESSAGE_FLAG_MASK
);
2027 INSIST(msg
->counts
[DNS_SECTION_QUESTION
] < 65536 &&
2028 msg
->counts
[DNS_SECTION_ANSWER
] < 65536 &&
2029 msg
->counts
[DNS_SECTION_AUTHORITY
] < 65536 &&
2030 msg
->counts
[DNS_SECTION_ADDITIONAL
] < 65536);
2032 isc_buffer_putuint16(target
, tmp
);
2033 isc_buffer_putuint16(target
,
2034 (isc_uint16_t
)msg
->counts
[DNS_SECTION_QUESTION
]);
2035 isc_buffer_putuint16(target
,
2036 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ANSWER
]);
2037 isc_buffer_putuint16(target
,
2038 (isc_uint16_t
)msg
->counts
[DNS_SECTION_AUTHORITY
]);
2039 isc_buffer_putuint16(target
,
2040 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ADDITIONAL
]);
2044 dns_message_renderend(dns_message_t
*msg
) {
2045 isc_buffer_t tmpbuf
;
2050 REQUIRE(DNS_MESSAGE_VALID(msg
));
2051 REQUIRE(msg
->buffer
!= NULL
);
2053 if ((msg
->rcode
& ~DNS_MESSAGE_RCODE_MASK
) != 0 && msg
->opt
== NULL
) {
2055 * We have an extended rcode but are not using EDNS.
2057 return (DNS_R_FORMERR
);
2061 * If we've got an OPT record, render it.
2063 if (msg
->opt
!= NULL
) {
2064 dns_message_renderrelease(msg
, msg
->opt_reserved
);
2065 msg
->opt_reserved
= 0;
2067 * Set the extended rcode.
2069 msg
->opt
->ttl
&= ~DNS_MESSAGE_EDNSRCODE_MASK
;
2070 msg
->opt
->ttl
|= ((msg
->rcode
<< 20) &
2071 DNS_MESSAGE_EDNSRCODE_MASK
);
2076 result
= dns_rdataset_towire(msg
->opt
, dns_rootname
,
2077 msg
->cctx
, msg
->buffer
, 0,
2079 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2080 if (result
!= ISC_R_SUCCESS
)
2085 * If we're adding a TSIG or SIG(0) to a truncated message,
2086 * clear all rdatasets from the message except for the question
2087 * before adding the TSIG or SIG(0). If the question doesn't fit,
2090 if ((msg
->tsigkey
!= NULL
|| msg
->sig0key
!= NULL
) &&
2091 (msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
2095 msgresetnames(msg
, DNS_SECTION_ANSWER
);
2097 dns_message_renderreset(msg
);
2099 isc_buffer_clear(msg
->buffer
);
2100 isc_buffer_add(msg
->buffer
, DNS_MESSAGE_HEADERLEN
);
2101 dns_compress_rollback(msg
->cctx
, 0);
2102 result
= dns_message_rendersection(msg
, DNS_SECTION_QUESTION
,
2104 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
2109 * If we're adding a TSIG record, generate and render it.
2111 if (msg
->tsigkey
!= NULL
) {
2112 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2113 msg
->sig_reserved
= 0;
2114 result
= dns_tsig_sign(msg
);
2115 if (result
!= ISC_R_SUCCESS
)
2118 result
= dns_rdataset_towire(msg
->tsig
, msg
->tsigname
,
2119 msg
->cctx
, msg
->buffer
, 0,
2121 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2122 if (result
!= ISC_R_SUCCESS
)
2127 * If we're adding a SIG(0) record, generate and render it.
2129 if (msg
->sig0key
!= NULL
) {
2130 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2131 msg
->sig_reserved
= 0;
2132 result
= dns_dnssec_signmessage(msg
, msg
->sig0key
);
2133 if (result
!= ISC_R_SUCCESS
)
2137 * Note: dns_rootname is used here, not msg->sig0name, since
2138 * the owner name of a SIG(0) is irrelevant, and will not
2139 * be set in a message being rendered.
2141 result
= dns_rdataset_towire(msg
->sig0
, dns_rootname
,
2142 msg
->cctx
, msg
->buffer
, 0,
2144 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2145 if (result
!= ISC_R_SUCCESS
)
2149 isc_buffer_usedregion(msg
->buffer
, &r
);
2150 isc_buffer_init(&tmpbuf
, r
.base
, r
.length
);
2152 dns_message_renderheader(msg
, &tmpbuf
);
2154 msg
->buffer
= NULL
; /* forget about this buffer only on success XXX */
2156 return (ISC_R_SUCCESS
);
2160 dns_message_renderreset(dns_message_t
*msg
) {
2163 dns_rdataset_t
*rds
;
2166 * Reset the message so that it may be rendered again.
2169 REQUIRE(DNS_MESSAGE_VALID(msg
));
2170 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2174 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
2175 msg
->cursors
[i
] = NULL
;
2177 for (name
= ISC_LIST_HEAD(msg
->sections
[i
]);
2179 name
= ISC_LIST_NEXT(name
, link
)) {
2180 for (rds
= ISC_LIST_HEAD(name
->list
);
2182 rds
= ISC_LIST_NEXT(rds
, link
)) {
2183 rds
->attributes
&= ~DNS_RDATASETATTR_RENDERED
;
2187 if (msg
->tsigname
!= NULL
)
2188 dns_message_puttempname(msg
, &msg
->tsigname
);
2189 if (msg
->tsig
!= NULL
) {
2190 dns_rdataset_disassociate(msg
->tsig
);
2191 dns_message_puttemprdataset(msg
, &msg
->tsig
);
2193 if (msg
->sig0
!= NULL
) {
2194 dns_rdataset_disassociate(msg
->sig0
);
2195 dns_message_puttemprdataset(msg
, &msg
->sig0
);
2200 dns_message_firstname(dns_message_t
*msg
, dns_section_t section
) {
2201 REQUIRE(DNS_MESSAGE_VALID(msg
));
2202 REQUIRE(VALID_NAMED_SECTION(section
));
2204 msg
->cursors
[section
] = ISC_LIST_HEAD(msg
->sections
[section
]);
2206 if (msg
->cursors
[section
] == NULL
)
2207 return (ISC_R_NOMORE
);
2209 return (ISC_R_SUCCESS
);
2213 dns_message_nextname(dns_message_t
*msg
, dns_section_t section
) {
2214 REQUIRE(DNS_MESSAGE_VALID(msg
));
2215 REQUIRE(VALID_NAMED_SECTION(section
));
2216 REQUIRE(msg
->cursors
[section
] != NULL
);
2218 msg
->cursors
[section
] = ISC_LIST_NEXT(msg
->cursors
[section
], link
);
2220 if (msg
->cursors
[section
] == NULL
)
2221 return (ISC_R_NOMORE
);
2223 return (ISC_R_SUCCESS
);
2227 dns_message_currentname(dns_message_t
*msg
, dns_section_t section
,
2230 REQUIRE(DNS_MESSAGE_VALID(msg
));
2231 REQUIRE(VALID_NAMED_SECTION(section
));
2232 REQUIRE(name
!= NULL
&& *name
== NULL
);
2233 REQUIRE(msg
->cursors
[section
] != NULL
);
2235 *name
= msg
->cursors
[section
];
2239 dns_message_findname(dns_message_t
*msg
, dns_section_t section
,
2240 dns_name_t
*target
, dns_rdatatype_t type
,
2241 dns_rdatatype_t covers
, dns_name_t
**name
,
2242 dns_rdataset_t
**rdataset
)
2244 dns_name_t
*foundname
;
2245 isc_result_t result
;
2248 * XXX These requirements are probably too intensive, especially
2249 * where things can be NULL, but as they are they ensure that if
2250 * something is NON-NULL, indicating that the caller expects it
2251 * to be filled in, that we can in fact fill it in.
2253 REQUIRE(msg
!= NULL
);
2254 REQUIRE(VALID_SECTION(section
));
2255 REQUIRE(target
!= NULL
);
2257 REQUIRE(*name
== NULL
);
2258 if (type
== dns_rdatatype_any
) {
2259 REQUIRE(rdataset
== NULL
);
2261 if (rdataset
!= NULL
)
2262 REQUIRE(*rdataset
== NULL
);
2265 result
= findname(&foundname
, target
,
2266 &msg
->sections
[section
]);
2268 if (result
== ISC_R_NOTFOUND
)
2269 return (DNS_R_NXDOMAIN
);
2270 else if (result
!= ISC_R_SUCCESS
)
2277 * And now look for the type.
2279 if (type
== dns_rdatatype_any
)
2280 return (ISC_R_SUCCESS
);
2282 result
= dns_message_findtype(foundname
, type
, covers
, rdataset
);
2283 if (result
== ISC_R_NOTFOUND
)
2284 return (DNS_R_NXRRSET
);
2290 dns_message_movename(dns_message_t
*msg
, dns_name_t
*name
,
2291 dns_section_t fromsection
,
2292 dns_section_t tosection
)
2294 REQUIRE(msg
!= NULL
);
2295 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2296 REQUIRE(name
!= NULL
);
2297 REQUIRE(VALID_NAMED_SECTION(fromsection
));
2298 REQUIRE(VALID_NAMED_SECTION(tosection
));
2301 * Unlink the name from the old section
2303 ISC_LIST_UNLINK(msg
->sections
[fromsection
], name
, link
);
2304 ISC_LIST_APPEND(msg
->sections
[tosection
], name
, link
);
2308 dns_message_addname(dns_message_t
*msg
, dns_name_t
*name
,
2309 dns_section_t section
)
2311 REQUIRE(msg
!= NULL
);
2312 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2313 REQUIRE(name
!= NULL
);
2314 REQUIRE(VALID_NAMED_SECTION(section
));
2316 ISC_LIST_APPEND(msg
->sections
[section
], name
, link
);
2320 dns_message_removename(dns_message_t
*msg
, dns_name_t
*name
,
2321 dns_section_t section
)
2323 REQUIRE(msg
!= NULL
);
2324 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2325 REQUIRE(name
!= NULL
);
2326 REQUIRE(VALID_NAMED_SECTION(section
));
2328 ISC_LIST_UNLINK(msg
->sections
[section
], name
, link
);
2332 dns_message_gettempname(dns_message_t
*msg
, dns_name_t
**item
) {
2333 REQUIRE(DNS_MESSAGE_VALID(msg
));
2334 REQUIRE(item
!= NULL
&& *item
== NULL
);
2336 *item
= isc_mempool_get(msg
->namepool
);
2338 return (ISC_R_NOMEMORY
);
2339 dns_name_init(*item
, NULL
);
2341 return (ISC_R_SUCCESS
);
2345 dns_message_gettempoffsets(dns_message_t
*msg
, dns_offsets_t
**item
) {
2346 REQUIRE(DNS_MESSAGE_VALID(msg
));
2347 REQUIRE(item
!= NULL
&& *item
== NULL
);
2349 *item
= newoffsets(msg
);
2351 return (ISC_R_NOMEMORY
);
2353 return (ISC_R_SUCCESS
);
2357 dns_message_gettemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2358 REQUIRE(DNS_MESSAGE_VALID(msg
));
2359 REQUIRE(item
!= NULL
&& *item
== NULL
);
2361 *item
= newrdata(msg
);
2363 return (ISC_R_NOMEMORY
);
2365 return (ISC_R_SUCCESS
);
2369 dns_message_gettemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2370 REQUIRE(DNS_MESSAGE_VALID(msg
));
2371 REQUIRE(item
!= NULL
&& *item
== NULL
);
2373 *item
= isc_mempool_get(msg
->rdspool
);
2375 return (ISC_R_NOMEMORY
);
2377 dns_rdataset_init(*item
);
2379 return (ISC_R_SUCCESS
);
2383 dns_message_gettemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2384 REQUIRE(DNS_MESSAGE_VALID(msg
));
2385 REQUIRE(item
!= NULL
&& *item
== NULL
);
2387 *item
= newrdatalist(msg
);
2389 return (ISC_R_NOMEMORY
);
2391 return (ISC_R_SUCCESS
);
2395 dns_message_puttempname(dns_message_t
*msg
, dns_name_t
**item
) {
2396 REQUIRE(DNS_MESSAGE_VALID(msg
));
2397 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2399 if (dns_name_dynamic(*item
))
2400 dns_name_free(*item
, msg
->mctx
);
2401 isc_mempool_put(msg
->namepool
, *item
);
2406 dns_message_puttemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2407 REQUIRE(DNS_MESSAGE_VALID(msg
));
2408 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2410 releaserdata(msg
, *item
);
2415 dns_message_puttemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2416 REQUIRE(DNS_MESSAGE_VALID(msg
));
2417 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2419 REQUIRE(!dns_rdataset_isassociated(*item
));
2420 isc_mempool_put(msg
->rdspool
, *item
);
2425 dns_message_puttemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2426 REQUIRE(DNS_MESSAGE_VALID(msg
));
2427 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2429 releaserdatalist(msg
, *item
);
2434 dns_message_peekheader(isc_buffer_t
*source
, dns_messageid_t
*idp
,
2435 unsigned int *flagsp
)
2438 isc_buffer_t buffer
;
2442 REQUIRE(source
!= NULL
);
2446 isc_buffer_remainingregion(&buffer
, &r
);
2447 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
2448 return (ISC_R_UNEXPECTEDEND
);
2450 id
= isc_buffer_getuint16(&buffer
);
2451 flags
= isc_buffer_getuint16(&buffer
);
2452 flags
&= DNS_MESSAGE_FLAG_MASK
;
2459 return (ISC_R_SUCCESS
);
2463 dns_message_reply(dns_message_t
*msg
, isc_boolean_t want_question_section
) {
2464 unsigned int first_section
;
2465 isc_result_t result
;
2467 REQUIRE(DNS_MESSAGE_VALID(msg
));
2468 REQUIRE((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0);
2470 if (!msg
->header_ok
)
2471 return (DNS_R_FORMERR
);
2472 if (msg
->opcode
!= dns_opcode_query
&&
2473 msg
->opcode
!= dns_opcode_notify
)
2474 want_question_section
= ISC_FALSE
;
2475 if (want_question_section
) {
2476 if (!msg
->question_ok
)
2477 return (DNS_R_FORMERR
);
2478 first_section
= DNS_SECTION_ANSWER
;
2480 first_section
= DNS_SECTION_QUESTION
;
2481 msg
->from_to_wire
= DNS_MESSAGE_INTENTRENDER
;
2482 msgresetnames(msg
, first_section
);
2484 msgresetsigs(msg
, ISC_TRUE
);
2485 msginitprivate(msg
);
2487 * We now clear most flags and then set QR, ensuring that the
2488 * reply's flags will be in a reasonable state.
2490 msg
->flags
&= DNS_MESSAGE_REPLYPRESERVE
;
2491 msg
->flags
|= DNS_MESSAGEFLAG_QR
;
2494 * This saves the query TSIG status, if the query was signed, and
2495 * reserves space in the reply for the TSIG.
2497 if (msg
->tsigkey
!= NULL
) {
2498 unsigned int otherlen
= 0;
2499 msg
->querytsigstatus
= msg
->tsigstatus
;
2500 msg
->tsigstatus
= dns_rcode_noerror
;
2501 if (msg
->querytsigstatus
== dns_tsigerror_badtime
)
2503 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, otherlen
);
2504 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2505 if (result
!= ISC_R_SUCCESS
) {
2506 msg
->sig_reserved
= 0;
2510 if (msg
->saved
.base
!= NULL
) {
2511 msg
->query
.base
= msg
->saved
.base
;
2512 msg
->query
.length
= msg
->saved
.length
;
2513 msg
->free_query
= msg
->free_saved
;
2514 msg
->saved
.base
= NULL
;
2515 msg
->saved
.length
= 0;
2516 msg
->free_saved
= 0;
2519 return (ISC_R_SUCCESS
);
2523 dns_message_getopt(dns_message_t
*msg
) {
2526 * Get the OPT record for 'msg'.
2529 REQUIRE(DNS_MESSAGE_VALID(msg
));
2535 dns_message_setopt(dns_message_t
*msg
, dns_rdataset_t
*opt
) {
2536 isc_result_t result
;
2537 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2540 * Set the OPT record for 'msg'.
2544 * The space required for an OPT record is:
2546 * 1 byte for the name
2547 * 2 bytes for the type
2548 * 2 bytes for the class
2549 * 4 bytes for the ttl
2550 * 2 bytes for the rdata length
2551 * ---------------------------------
2554 * plus the length of the rdata.
2557 REQUIRE(DNS_MESSAGE_VALID(msg
));
2558 REQUIRE(opt
->type
== dns_rdatatype_opt
);
2559 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2560 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2564 result
= dns_rdataset_first(opt
);
2565 if (result
!= ISC_R_SUCCESS
)
2567 dns_rdataset_current(opt
, &rdata
);
2568 msg
->opt_reserved
= 11 + rdata
.length
;
2569 result
= dns_message_renderreserve(msg
, msg
->opt_reserved
);
2570 if (result
!= ISC_R_SUCCESS
) {
2571 msg
->opt_reserved
= 0;
2577 return (ISC_R_SUCCESS
);
2580 dns_message_puttemprdataset(msg
, &opt
);
2586 dns_message_gettsig(dns_message_t
*msg
, dns_name_t
**owner
) {
2589 * Get the TSIG record and owner for 'msg'.
2592 REQUIRE(DNS_MESSAGE_VALID(msg
));
2593 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2596 *owner
= msg
->tsigname
;
2601 dns_message_settsigkey(dns_message_t
*msg
, dns_tsigkey_t
*key
) {
2602 isc_result_t result
;
2605 * Set the TSIG key for 'msg'
2608 REQUIRE(DNS_MESSAGE_VALID(msg
));
2609 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2611 if (key
== NULL
&& msg
->tsigkey
!= NULL
) {
2612 if (msg
->sig_reserved
!= 0) {
2613 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2614 msg
->sig_reserved
= 0;
2616 dns_tsigkey_detach(&msg
->tsigkey
);
2619 REQUIRE(msg
->tsigkey
== NULL
&& msg
->sig0key
== NULL
);
2620 dns_tsigkey_attach(key
, &msg
->tsigkey
);
2621 if (msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
) {
2622 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, 0);
2623 result
= dns_message_renderreserve(msg
,
2625 if (result
!= ISC_R_SUCCESS
) {
2626 dns_tsigkey_detach(&msg
->tsigkey
);
2627 msg
->sig_reserved
= 0;
2632 return (ISC_R_SUCCESS
);
2636 dns_message_gettsigkey(dns_message_t
*msg
) {
2639 * Get the TSIG key for 'msg'
2642 REQUIRE(DNS_MESSAGE_VALID(msg
));
2644 return (msg
->tsigkey
);
2648 dns_message_setquerytsig(dns_message_t
*msg
, isc_buffer_t
*querytsig
) {
2649 dns_rdata_t
*rdata
= NULL
;
2650 dns_rdatalist_t
*list
= NULL
;
2651 dns_rdataset_t
*set
= NULL
;
2652 isc_buffer_t
*buf
= NULL
;
2654 isc_result_t result
;
2656 REQUIRE(DNS_MESSAGE_VALID(msg
));
2657 REQUIRE(msg
->querytsig
== NULL
);
2659 if (querytsig
== NULL
)
2660 return (ISC_R_SUCCESS
);
2662 result
= dns_message_gettemprdata(msg
, &rdata
);
2663 if (result
!= ISC_R_SUCCESS
)
2666 result
= dns_message_gettemprdatalist(msg
, &list
);
2667 if (result
!= ISC_R_SUCCESS
)
2669 result
= dns_message_gettemprdataset(msg
, &set
);
2670 if (result
!= ISC_R_SUCCESS
)
2673 isc_buffer_usedregion(querytsig
, &r
);
2674 result
= isc_buffer_allocate(msg
->mctx
, &buf
, r
.length
);
2675 if (result
!= ISC_R_SUCCESS
)
2677 isc_buffer_putmem(buf
, r
.base
, r
.length
);
2678 isc_buffer_usedregion(buf
, &r
);
2679 dns_rdata_init(rdata
);
2680 dns_rdata_fromregion(rdata
, dns_rdataclass_any
, dns_rdatatype_tsig
, &r
);
2681 dns_message_takebuffer(msg
, &buf
);
2682 ISC_LIST_INIT(list
->rdata
);
2683 ISC_LIST_APPEND(list
->rdata
, rdata
, link
);
2684 result
= dns_rdatalist_tordataset(list
, set
);
2685 if (result
!= ISC_R_SUCCESS
)
2688 msg
->querytsig
= set
;
2694 dns_message_puttemprdata(msg
, &rdata
);
2696 dns_message_puttemprdatalist(msg
, &list
);
2698 dns_message_puttemprdataset(msg
, &set
);
2699 return (ISC_R_NOMEMORY
);
2703 dns_message_getquerytsig(dns_message_t
*msg
, isc_mem_t
*mctx
,
2704 isc_buffer_t
**querytsig
) {
2705 isc_result_t result
;
2706 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2709 REQUIRE(DNS_MESSAGE_VALID(msg
));
2710 REQUIRE(mctx
!= NULL
);
2711 REQUIRE(querytsig
!= NULL
&& *querytsig
== NULL
);
2713 if (msg
->tsig
== NULL
)
2714 return (ISC_R_SUCCESS
);
2716 result
= dns_rdataset_first(msg
->tsig
);
2717 if (result
!= ISC_R_SUCCESS
)
2719 dns_rdataset_current(msg
->tsig
, &rdata
);
2720 dns_rdata_toregion(&rdata
, &r
);
2722 result
= isc_buffer_allocate(mctx
, querytsig
, r
.length
);
2723 if (result
!= ISC_R_SUCCESS
)
2725 isc_buffer_putmem(*querytsig
, r
.base
, r
.length
);
2726 return (ISC_R_SUCCESS
);
2730 dns_message_getsig0(dns_message_t
*msg
, dns_name_t
**owner
) {
2733 * Get the SIG(0) record for 'msg'.
2736 REQUIRE(DNS_MESSAGE_VALID(msg
));
2737 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2739 if (msg
->sig0
!= NULL
&& owner
!= NULL
) {
2740 /* If dns_message_getsig0 is called on a rendered message
2741 * after the SIG(0) has been applied, we need to return the
2742 * root name, not NULL.
2744 if (msg
->sig0name
== NULL
)
2745 *owner
= dns_rootname
;
2747 *owner
= msg
->sig0name
;
2753 dns_message_setsig0key(dns_message_t
*msg
, dst_key_t
*key
) {
2756 isc_result_t result
;
2759 * Set the SIG(0) key for 'msg'
2763 * The space required for an SIG(0) record is:
2765 * 1 byte for the name
2766 * 2 bytes for the type
2767 * 2 bytes for the class
2768 * 4 bytes for the ttl
2769 * 2 bytes for the type covered
2770 * 1 byte for the algorithm
2771 * 1 bytes for the labels
2772 * 4 bytes for the original ttl
2773 * 4 bytes for the signature expiration
2774 * 4 bytes for the signature inception
2775 * 2 bytes for the key tag
2776 * n bytes for the signer's name
2777 * x bytes for the signature
2778 * ---------------------------------
2781 REQUIRE(DNS_MESSAGE_VALID(msg
));
2782 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2783 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2786 REQUIRE(msg
->sig0key
== NULL
&& msg
->tsigkey
== NULL
);
2787 dns_name_toregion(dst_key_name(key
), &r
);
2788 result
= dst_key_sigsize(key
, &x
);
2789 if (result
!= ISC_R_SUCCESS
) {
2790 msg
->sig_reserved
= 0;
2793 msg
->sig_reserved
= 27 + r
.length
+ x
;
2794 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2795 if (result
!= ISC_R_SUCCESS
) {
2796 msg
->sig_reserved
= 0;
2801 return (ISC_R_SUCCESS
);
2805 dns_message_getsig0key(dns_message_t
*msg
) {
2808 * Get the SIG(0) key for 'msg'
2811 REQUIRE(DNS_MESSAGE_VALID(msg
));
2813 return (msg
->sig0key
);
2817 dns_message_takebuffer(dns_message_t
*msg
, isc_buffer_t
**buffer
) {
2818 REQUIRE(DNS_MESSAGE_VALID(msg
));
2819 REQUIRE(buffer
!= NULL
);
2820 REQUIRE(ISC_BUFFER_VALID(*buffer
));
2822 ISC_LIST_APPEND(msg
->cleanup
, *buffer
, link
);
2827 dns_message_signer(dns_message_t
*msg
, dns_name_t
*signer
) {
2828 isc_result_t result
= ISC_R_SUCCESS
;
2829 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2831 REQUIRE(DNS_MESSAGE_VALID(msg
));
2832 REQUIRE(signer
!= NULL
);
2833 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
2835 if (msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2836 return (ISC_R_NOTFOUND
);
2838 if (msg
->verify_attempted
== 0)
2839 return (DNS_R_NOTVERIFIEDYET
);
2841 if (!dns_name_hasbuffer(signer
)) {
2842 isc_buffer_t
*dynbuf
= NULL
;
2843 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, 512);
2844 if (result
!= ISC_R_SUCCESS
)
2846 dns_name_setbuffer(signer
, dynbuf
);
2847 dns_message_takebuffer(msg
, &dynbuf
);
2850 if (msg
->sig0
!= NULL
) {
2851 dns_rdata_sig_t sig
;
2853 result
= dns_rdataset_first(msg
->sig0
);
2854 INSIST(result
== ISC_R_SUCCESS
);
2855 dns_rdataset_current(msg
->sig0
, &rdata
);
2857 result
= dns_rdata_tostruct(&rdata
, &sig
, NULL
);
2858 if (result
!= ISC_R_SUCCESS
)
2861 if (msg
->verified_sig
&& msg
->sig0status
== dns_rcode_noerror
)
2862 result
= ISC_R_SUCCESS
;
2864 result
= DNS_R_SIGINVALID
;
2865 dns_name_clone(&sig
.signer
, signer
);
2866 dns_rdata_freestruct(&sig
);
2868 dns_name_t
*identity
;
2869 dns_rdata_any_tsig_t tsig
;
2871 result
= dns_rdataset_first(msg
->tsig
);
2872 INSIST(result
== ISC_R_SUCCESS
);
2873 dns_rdataset_current(msg
->tsig
, &rdata
);
2875 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
2876 if (msg
->tsigstatus
!= dns_rcode_noerror
)
2877 result
= DNS_R_TSIGVERIFYFAILURE
;
2878 else if (tsig
.error
!= dns_rcode_noerror
)
2879 result
= DNS_R_TSIGERRORSET
;
2881 result
= ISC_R_SUCCESS
;
2882 dns_rdata_freestruct(&tsig
);
2884 if (msg
->tsigkey
== NULL
) {
2886 * If msg->tsigstatus & tsig.error are both
2887 * dns_rcode_noerror, the message must have been
2888 * verified, which means msg->tsigkey will be
2891 INSIST(result
!= ISC_R_SUCCESS
);
2893 identity
= dns_tsigkey_identity(msg
->tsigkey
);
2894 if (identity
== NULL
) {
2895 if (result
== ISC_R_SUCCESS
)
2896 result
= DNS_R_NOIDENTITY
;
2897 identity
= &msg
->tsigkey
->name
;
2899 dns_name_clone(identity
, signer
);
2907 dns_message_resetsig(dns_message_t
*msg
) {
2908 REQUIRE(DNS_MESSAGE_VALID(msg
));
2909 msg
->verified_sig
= 0;
2910 msg
->verify_attempted
= 0;
2911 msg
->tsigstatus
= dns_rcode_noerror
;
2912 msg
->sig0status
= dns_rcode_noerror
;
2913 msg
->timeadjust
= 0;
2914 if (msg
->tsigkey
!= NULL
) {
2915 dns_tsigkey_detach(&msg
->tsigkey
);
2916 msg
->tsigkey
= NULL
;
2921 dns_message_rechecksig(dns_message_t
*msg
, dns_view_t
*view
) {
2922 dns_message_resetsig(msg
);
2923 return (dns_message_checksig(msg
, view
));
2926 #ifdef SKAN_MSG_DEBUG
2928 dns_message_dumpsig(dns_message_t
*msg
, char *txt1
) {
2929 dns_rdata_t querytsigrdata
= DNS_RDATA_INIT
;
2930 dns_rdata_any_tsig_t querytsig
;
2931 isc_result_t result
;
2933 if (msg
->tsig
!= NULL
) {
2934 result
= dns_rdataset_first(msg
->tsig
);
2935 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2936 dns_rdataset_current(msg
->tsig
, &querytsigrdata
);
2937 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
2938 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2939 hexdump(txt1
, "TSIG", querytsig
.signature
,
2943 if (msg
->querytsig
!= NULL
) {
2944 result
= dns_rdataset_first(msg
->querytsig
);
2945 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2946 dns_rdataset_current(msg
->querytsig
, &querytsigrdata
);
2947 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
2948 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2949 hexdump(txt1
, "QUERYTSIG", querytsig
.signature
,
2956 dns_message_checksig(dns_message_t
*msg
, dns_view_t
*view
) {
2957 isc_buffer_t b
, msgb
;
2959 REQUIRE(DNS_MESSAGE_VALID(msg
));
2961 if (msg
->tsigkey
== NULL
&& msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2962 return (ISC_R_SUCCESS
);
2964 INSIST(msg
->saved
.base
!= NULL
);
2965 isc_buffer_init(&msgb
, msg
->saved
.base
, msg
->saved
.length
);
2966 isc_buffer_add(&msgb
, msg
->saved
.length
);
2967 if (msg
->tsigkey
!= NULL
|| msg
->tsig
!= NULL
) {
2968 #ifdef SKAN_MSG_DEBUG
2969 dns_message_dumpsig(msg
, "dns_message_checksig#1");
2972 return (dns_view_checksig(view
, &msgb
, msg
));
2974 return (dns_tsig_verify(&msgb
, msg
, NULL
, NULL
));
2976 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2977 dns_rdata_sig_t sig
;
2978 dns_rdataset_t keyset
;
2979 isc_result_t result
;
2981 result
= dns_rdataset_first(msg
->sig0
);
2982 INSIST(result
== ISC_R_SUCCESS
);
2983 dns_rdataset_current(msg
->sig0
, &rdata
);
2986 * This can occur when the message is a dynamic update, since
2987 * the rdata length checking is relaxed. This should not
2988 * happen in a well-formed message, since the SIG(0) is only
2989 * looked for in the additional section, and the dynamic update
2990 * meta-records are in the prerequisite and update sections.
2992 if (rdata
.length
== 0)
2993 return (ISC_R_UNEXPECTEDEND
);
2995 result
= dns_rdata_tostruct(&rdata
, &sig
, msg
->mctx
);
2996 if (result
!= ISC_R_SUCCESS
)
2999 dns_rdataset_init(&keyset
);
3001 return (DNS_R_KEYUNAUTHORIZED
);
3002 result
= dns_view_simplefind(view
, &sig
.signer
,
3003 dns_rdatatype_key
/* SIG(0) */,
3004 0, 0, ISC_FALSE
, &keyset
, NULL
);
3006 if (result
!= ISC_R_SUCCESS
) {
3007 /* XXXBEW Should possibly create a fetch here */
3008 result
= DNS_R_KEYUNAUTHORIZED
;
3010 } else if (keyset
.trust
< dns_trust_secure
) {
3011 /* XXXBEW Should call a validator here */
3012 result
= DNS_R_KEYUNAUTHORIZED
;
3015 result
= dns_rdataset_first(&keyset
);
3016 INSIST(result
== ISC_R_SUCCESS
);
3018 result
== ISC_R_SUCCESS
;
3019 result
= dns_rdataset_next(&keyset
))
3021 dst_key_t
*key
= NULL
;
3023 dns_rdataset_current(&keyset
, &rdata
);
3024 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
3025 isc_buffer_add(&b
, rdata
.length
);
3027 result
= dst_key_fromdns(&sig
.signer
, rdata
.rdclass
,
3028 &b
, view
->mctx
, &key
);
3029 if (result
!= ISC_R_SUCCESS
)
3031 if (dst_key_alg(key
) != sig
.algorithm
||
3032 dst_key_id(key
) != sig
.keyid
||
3033 !(dst_key_proto(key
) == DNS_KEYPROTO_DNSSEC
||
3034 dst_key_proto(key
) == DNS_KEYPROTO_ANY
))
3039 result
= dns_dnssec_verifymessage(&msgb
, msg
, key
);
3041 if (result
== ISC_R_SUCCESS
)
3044 if (result
== ISC_R_NOMORE
)
3045 result
= DNS_R_KEYUNAUTHORIZED
;
3048 if (dns_rdataset_isassociated(&keyset
))
3049 dns_rdataset_disassociate(&keyset
);
3050 dns_rdata_freestruct(&sig
);
3056 dns_message_sectiontotext(dns_message_t
*msg
, dns_section_t section
,
3057 const dns_master_style_t
*style
,
3058 dns_messagetextflag_t flags
,
3059 isc_buffer_t
*target
) {
3060 dns_name_t
*name
, empty_name
;
3061 dns_rdataset_t
*rdataset
;
3062 isc_result_t result
;
3064 REQUIRE(DNS_MESSAGE_VALID(msg
));
3065 REQUIRE(target
!= NULL
);
3066 REQUIRE(VALID_SECTION(section
));
3068 if (ISC_LIST_EMPTY(msg
->sections
[section
]))
3069 return (ISC_R_SUCCESS
);
3071 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0) {
3072 ADD_STRING(target
, ";; ");
3073 if (msg
->opcode
!= dns_opcode_update
) {
3074 ADD_STRING(target
, sectiontext
[section
]);
3076 ADD_STRING(target
, updsectiontext
[section
]);
3078 ADD_STRING(target
, " SECTION:\n");
3081 dns_name_init(&empty_name
, NULL
);
3082 result
= dns_message_firstname(msg
, section
);
3083 if (result
!= ISC_R_SUCCESS
) {
3088 dns_message_currentname(msg
, section
, &name
);
3089 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3091 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3092 if (section
== DNS_SECTION_QUESTION
) {
3093 ADD_STRING(target
, ";");
3094 result
= dns_master_questiontotext(name
,
3099 result
= dns_master_rdatasettotext(name
,
3104 if (result
!= ISC_R_SUCCESS
)
3107 result
= dns_message_nextname(msg
, section
);
3108 } while (result
== ISC_R_SUCCESS
);
3109 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3110 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3111 ADD_STRING(target
, "\n");
3112 if (result
== ISC_R_NOMORE
)
3113 result
= ISC_R_SUCCESS
;
3118 dns_message_pseudosectiontotext(dns_message_t
*msg
,
3119 dns_pseudosection_t section
,
3120 const dns_master_style_t
*style
,
3121 dns_messagetextflag_t flags
,
3122 isc_buffer_t
*target
) {
3123 dns_rdataset_t
*ps
= NULL
;
3124 dns_name_t
*name
= NULL
;
3125 isc_result_t result
;
3126 char buf
[sizeof("1234567890")];
3129 isc_buffer_t optbuf
;
3130 isc_uint16_t optcode
, optlen
;
3131 unsigned char *optdata
;
3133 REQUIRE(DNS_MESSAGE_VALID(msg
));
3134 REQUIRE(target
!= NULL
);
3135 REQUIRE(VALID_PSEUDOSECTION(section
));
3138 case DNS_PSEUDOSECTION_OPT
:
3139 ps
= dns_message_getopt(msg
);
3141 return (ISC_R_SUCCESS
);
3142 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3143 ADD_STRING(target
, ";; OPT PSEUDOSECTION:\n");
3144 ADD_STRING(target
, "; EDNS: version: ");
3145 snprintf(buf
, sizeof(buf
), "%u",
3146 (unsigned int)((ps
->ttl
& 0x00ff0000) >> 16));
3147 ADD_STRING(target
, buf
);
3148 ADD_STRING(target
, ", flags:");
3149 if ((ps
->ttl
& DNS_MESSAGEEXTFLAG_DO
) != 0)
3150 ADD_STRING(target
, " do");
3151 mbz
= ps
->ttl
& ~DNS_MESSAGEEXTFLAG_DO
& 0xffff;
3153 ADD_STRING(target
, "; MBZ: ");
3154 snprintf(buf
, sizeof(buf
), "%.4x ", mbz
);
3155 ADD_STRING(target
, buf
);
3156 ADD_STRING(target
, ", udp: ");
3158 ADD_STRING(target
, "; udp: ");
3159 snprintf(buf
, sizeof(buf
), "%u\n", (unsigned int)ps
->rdclass
);
3160 ADD_STRING(target
, buf
);
3162 result
= dns_rdataset_first(ps
);
3163 if (result
!= ISC_R_SUCCESS
)
3164 return (ISC_R_SUCCESS
);
3166 /* Print EDNS info, if any */
3167 dns_rdata_init(&rdata
);
3168 dns_rdataset_current(ps
, &rdata
);
3169 if (rdata
.length
< 4)
3170 return (ISC_R_SUCCESS
);
3172 isc_buffer_init(&optbuf
, rdata
.data
, rdata
.length
);
3173 isc_buffer_add(&optbuf
, rdata
.length
);
3174 optcode
= isc_buffer_getuint16(&optbuf
);
3175 optlen
= isc_buffer_getuint16(&optbuf
);
3177 if (optcode
== DNS_OPT_NSID
) {
3178 ADD_STRING(target
, "; NSID");
3180 ADD_STRING(target
, "; OPT=");
3181 sprintf(buf
, "%u", optcode
);
3182 ADD_STRING(target
, buf
);
3187 ADD_STRING(target
, ": ");
3189 optdata
= rdata
.data
+ 4;
3190 for (i
= 0; i
< optlen
; i
++) {
3191 sprintf(buf
, "%02x ", optdata
[i
]);
3192 ADD_STRING(target
, buf
);
3194 for (i
= 0; i
< optlen
; i
++) {
3195 ADD_STRING(target
, " (");
3196 if (isprint(optdata
[i
]))
3197 isc_buffer_putmem(target
, &optdata
[i
],
3200 isc_buffer_putstr(target
, ".");
3201 ADD_STRING(target
, ")");
3204 ADD_STRING(target
, "\n");
3205 return (ISC_R_SUCCESS
);
3206 case DNS_PSEUDOSECTION_TSIG
:
3207 ps
= dns_message_gettsig(msg
, &name
);
3209 return (ISC_R_SUCCESS
);
3210 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3211 ADD_STRING(target
, ";; TSIG PSEUDOSECTION:\n");
3212 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3213 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3214 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3215 ADD_STRING(target
, "\n");
3217 case DNS_PSEUDOSECTION_SIG0
:
3218 ps
= dns_message_getsig0(msg
, &name
);
3220 return (ISC_R_SUCCESS
);
3221 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3222 ADD_STRING(target
, ";; SIG0 PSEUDOSECTION:\n");
3223 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3224 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3225 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3226 ADD_STRING(target
, "\n");
3229 return (ISC_R_UNEXPECTED
);
3233 dns_message_totext(dns_message_t
*msg
, const dns_master_style_t
*style
,
3234 dns_messagetextflag_t flags
, isc_buffer_t
*target
) {
3235 char buf
[sizeof("1234567890")];
3236 isc_result_t result
;
3238 REQUIRE(DNS_MESSAGE_VALID(msg
));
3239 REQUIRE(target
!= NULL
);
3241 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0) {
3242 ADD_STRING(target
, ";; ->>HEADER<<- opcode: ");
3243 ADD_STRING(target
, opcodetext
[msg
->opcode
]);
3244 ADD_STRING(target
, ", status: ");
3245 if (msg
->rcode
< (sizeof(rcodetext
)/sizeof(rcodetext
[0]))) {
3246 ADD_STRING(target
, rcodetext
[msg
->rcode
]);
3248 snprintf(buf
, sizeof(buf
), "%4u", msg
->rcode
);
3249 ADD_STRING(target
, buf
);
3251 ADD_STRING(target
, ", id: ");
3252 snprintf(buf
, sizeof(buf
), "%6u", msg
->id
);
3253 ADD_STRING(target
, buf
);
3254 ADD_STRING(target
, "\n;; flags: ");
3255 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) != 0)
3256 ADD_STRING(target
, "qr ");
3257 if ((msg
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3258 ADD_STRING(target
, "aa ");
3259 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
3260 ADD_STRING(target
, "tc ");
3261 if ((msg
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3262 ADD_STRING(target
, "rd ");
3263 if ((msg
->flags
& DNS_MESSAGEFLAG_RA
) != 0)
3264 ADD_STRING(target
, "ra ");
3265 if ((msg
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
3266 ADD_STRING(target
, "ad ");
3267 if ((msg
->flags
& DNS_MESSAGEFLAG_CD
) != 0)
3268 ADD_STRING(target
, "cd ");
3269 if (msg
->opcode
!= dns_opcode_update
) {
3270 ADD_STRING(target
, "; QUESTION: ");
3272 ADD_STRING(target
, "; ZONE: ");
3274 snprintf(buf
, sizeof(buf
), "%1u",
3275 msg
->counts
[DNS_SECTION_QUESTION
]);
3276 ADD_STRING(target
, buf
);
3277 if (msg
->opcode
!= dns_opcode_update
) {
3278 ADD_STRING(target
, ", ANSWER: ");
3280 ADD_STRING(target
, ", PREREQ: ");
3282 snprintf(buf
, sizeof(buf
), "%1u",
3283 msg
->counts
[DNS_SECTION_ANSWER
]);
3284 ADD_STRING(target
, buf
);
3285 if (msg
->opcode
!= dns_opcode_update
) {
3286 ADD_STRING(target
, ", AUTHORITY: ");
3288 ADD_STRING(target
, ", UPDATE: ");
3290 snprintf(buf
, sizeof(buf
), "%1u",
3291 msg
->counts
[DNS_SECTION_AUTHORITY
]);
3292 ADD_STRING(target
, buf
);
3293 ADD_STRING(target
, ", ADDITIONAL: ");
3294 snprintf(buf
, sizeof(buf
), "%1u",
3295 msg
->counts
[DNS_SECTION_ADDITIONAL
]);
3296 ADD_STRING(target
, buf
);
3297 ADD_STRING(target
, "\n");
3299 result
= dns_message_pseudosectiontotext(msg
,
3300 DNS_PSEUDOSECTION_OPT
,
3301 style
, flags
, target
);
3302 if (result
!= ISC_R_SUCCESS
)
3305 result
= dns_message_sectiontotext(msg
, DNS_SECTION_QUESTION
,
3306 style
, flags
, target
);
3307 if (result
!= ISC_R_SUCCESS
)
3309 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ANSWER
,
3310 style
, flags
, target
);
3311 if (result
!= ISC_R_SUCCESS
)
3313 result
= dns_message_sectiontotext(msg
, DNS_SECTION_AUTHORITY
,
3314 style
, flags
, target
);
3315 if (result
!= ISC_R_SUCCESS
)
3317 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ADDITIONAL
,
3318 style
, flags
, target
);
3319 if (result
!= ISC_R_SUCCESS
)
3322 result
= dns_message_pseudosectiontotext(msg
,
3323 DNS_PSEUDOSECTION_TSIG
,
3324 style
, flags
, target
);
3325 if (result
!= ISC_R_SUCCESS
)
3328 result
= dns_message_pseudosectiontotext(msg
,
3329 DNS_PSEUDOSECTION_SIG0
,
3330 style
, flags
, target
);
3331 if (result
!= ISC_R_SUCCESS
)
3334 return (ISC_R_SUCCESS
);
3338 dns_message_getrawmessage(dns_message_t
*msg
) {
3339 REQUIRE(DNS_MESSAGE_VALID(msg
));
3340 return (&msg
->saved
);
3344 dns_message_setsortorder(dns_message_t
*msg
, dns_rdatasetorderfunc_t order
,
3345 const void *order_arg
)
3347 REQUIRE(DNS_MESSAGE_VALID(msg
));
3349 msg
->order_arg
= order_arg
;
3353 dns_message_settimeadjust(dns_message_t
*msg
, int timeadjust
) {
3354 REQUIRE(DNS_MESSAGE_VALID(msg
));
3355 msg
->timeadjust
= timeadjust
;
3359 dns_message_gettimeadjust(dns_message_t
*msg
) {
3360 REQUIRE(DNS_MESSAGE_VALID(msg
));
3361 return (msg
->timeadjust
);
3365 dns_opcode_totext(dns_opcode_t opcode
, isc_buffer_t
*target
) {
3367 REQUIRE(opcode
< 16);
3369 if (isc_buffer_availablelength(target
) < strlen(opcodetext
[opcode
]))
3370 return (ISC_R_NOSPACE
);
3371 isc_buffer_putstr(target
, opcodetext
[opcode
]);
3372 return (ISC_R_SUCCESS
);