1 /* $NetBSD: message.c,v 1.15 2015/07/08 17:28:58 christos Exp $ */
4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
31 #include <isc/buffer.h>
33 #include <isc/print.h>
34 #include <isc/string.h> /* Required for HP/UX (and others?) */
37 #include <dns/dnssec.h>
38 #include <dns/keyvalues.h>
40 #include <dns/masterdump.h>
41 #include <dns/message.h>
42 #include <dns/opcode.h>
43 #include <dns/rdata.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/result.h>
54 hexdump(const char *msg
, const char *msg2
, void *base
, size_t len
) {
61 printf("*** %s [%s] (%u bytes @ %p)\n", msg
, msg2
, len
, base
);
66 else if (cnt
% 8 == 0)
68 printf(" %02x %c", *p
, (isprint(*p
) ? *p
: ' '));
81 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
82 #define DNS_MESSAGE_OPCODE_SHIFT 11
83 #define DNS_MESSAGE_RCODE_MASK 0x000fU
84 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
85 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
86 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
87 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
88 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
90 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
91 && ((s) < DNS_SECTION_MAX))
92 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
93 && ((s) < DNS_SECTION_MAX))
94 #define ADD_STRING(b, s) {if (strlen(s) >= \
95 isc_buffer_availablelength(b)) \
96 return(ISC_R_NOSPACE); else \
97 isc_buffer_putstr(b, s);}
98 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
99 && ((s) < DNS_PSEUDOSECTION_MAX))
101 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
104 * This is the size of each individual scratchpad buffer, and the numbers
105 * of various block allocations used within the server.
106 * XXXMLG These should come from a config setting.
108 #define SCRATCHPAD_SIZE 512
110 #define OFFSET_COUNT 4
111 #define RDATA_COUNT 8
112 #define RDATALIST_COUNT 8
113 #define RDATASET_COUNT RDATALIST_COUNT
116 * Text representation of the different items, for message_totext
119 static const char *sectiontext
[] = {
126 static const char *updsectiontext
[] = {
133 static const char *opcodetext
[] = {
152 static const char *rcodetext
[] = {
174 * "helper" type, which consists of a block of some type, and is linkable.
175 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
176 * size, or the allocated elements will not be aligned correctly.
178 struct dns_msgblock
{
180 unsigned int remaining
;
181 ISC_LINK(dns_msgblock_t
) link
;
182 }; /* dynamically sized */
184 static inline dns_msgblock_t
*
185 msgblock_allocate(isc_mem_t
*, unsigned int, unsigned int);
187 #define msgblock_get(block, type) \
188 ((type *)msgblock_internalget(block, sizeof(type)))
191 msgblock_internalget(dns_msgblock_t
*, unsigned int);
194 msgblock_reset(dns_msgblock_t
*);
197 msgblock_free(isc_mem_t
*, dns_msgblock_t
*, unsigned int);
200 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
201 * is free, return NULL.
203 static inline dns_msgblock_t
*
204 msgblock_allocate(isc_mem_t
*mctx
, unsigned int sizeof_type
,
207 dns_msgblock_t
*block
;
210 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* count
);
212 block
= isc_mem_get(mctx
, length
);
216 block
->count
= count
;
217 block
->remaining
= count
;
219 ISC_LINK_INIT(block
, link
);
225 * Return an element from the msgblock. If no more are available, return
229 msgblock_internalget(dns_msgblock_t
*block
, unsigned int sizeof_type
) {
232 if (block
== NULL
|| block
->remaining
== 0)
237 ptr
= (((unsigned char *)block
)
238 + sizeof(dns_msgblock_t
)
239 + (sizeof_type
* block
->remaining
));
245 msgblock_reset(dns_msgblock_t
*block
) {
246 block
->remaining
= block
->count
;
250 * Release memory associated with a message block.
253 msgblock_free(isc_mem_t
*mctx
, dns_msgblock_t
*block
, unsigned int sizeof_type
)
257 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* block
->count
);
259 isc_mem_put(mctx
, block
, length
);
263 * Allocate a new dynamic buffer, and attach it to this message as the
264 * "current" buffer. (which is always the last on the list, for our
267 static inline isc_result_t
268 newbuffer(dns_message_t
*msg
, unsigned int size
) {
270 isc_buffer_t
*dynbuf
;
273 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, size
);
274 if (result
!= ISC_R_SUCCESS
)
275 return (ISC_R_NOMEMORY
);
277 ISC_LIST_APPEND(msg
->scratchpad
, dynbuf
, link
);
278 return (ISC_R_SUCCESS
);
281 static inline isc_buffer_t
*
282 currentbuffer(dns_message_t
*msg
) {
283 isc_buffer_t
*dynbuf
;
285 dynbuf
= ISC_LIST_TAIL(msg
->scratchpad
);
286 INSIST(dynbuf
!= NULL
);
292 releaserdata(dns_message_t
*msg
, dns_rdata_t
*rdata
) {
293 ISC_LIST_PREPEND(msg
->freerdata
, rdata
, link
);
296 static inline dns_rdata_t
*
297 newrdata(dns_message_t
*msg
) {
298 dns_msgblock_t
*msgblock
;
301 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
303 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
307 msgblock
= ISC_LIST_TAIL(msg
->rdatas
);
308 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
310 msgblock
= msgblock_allocate(msg
->mctx
, sizeof(dns_rdata_t
),
312 if (msgblock
== NULL
)
315 ISC_LIST_APPEND(msg
->rdatas
, msgblock
, link
);
317 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
320 dns_rdata_init(rdata
);
325 releaserdatalist(dns_message_t
*msg
, dns_rdatalist_t
*rdatalist
) {
326 ISC_LIST_PREPEND(msg
->freerdatalist
, rdatalist
, link
);
329 static inline dns_rdatalist_t
*
330 newrdatalist(dns_message_t
*msg
) {
331 dns_msgblock_t
*msgblock
;
332 dns_rdatalist_t
*rdatalist
;
334 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
335 if (rdatalist
!= NULL
) {
336 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
340 msgblock
= ISC_LIST_TAIL(msg
->rdatalists
);
341 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
342 if (rdatalist
== NULL
) {
343 msgblock
= msgblock_allocate(msg
->mctx
,
344 sizeof(dns_rdatalist_t
),
346 if (msgblock
== NULL
)
349 ISC_LIST_APPEND(msg
->rdatalists
, msgblock
, link
);
351 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
357 static inline dns_offsets_t
*
358 newoffsets(dns_message_t
*msg
) {
359 dns_msgblock_t
*msgblock
;
360 dns_offsets_t
*offsets
;
362 msgblock
= ISC_LIST_TAIL(msg
->offsets
);
363 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
364 if (offsets
== NULL
) {
365 msgblock
= msgblock_allocate(msg
->mctx
,
366 sizeof(dns_offsets_t
),
368 if (msgblock
== NULL
)
371 ISC_LIST_APPEND(msg
->offsets
, msgblock
, link
);
373 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
380 msginitheader(dns_message_t
*m
) {
389 msginitprivate(dns_message_t
*m
) {
392 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
393 m
->cursors
[i
] = NULL
;
401 m
->state
= DNS_SECTION_ANY
; /* indicate nothing parsed or rendered */
409 msginittsig(dns_message_t
*m
) {
410 m
->tsigstatus
= dns_rcode_noerror
;
411 m
->querytsigstatus
= dns_rcode_noerror
;
416 m
->sig0status
= dns_rcode_noerror
;
421 * Init elements to default state. Used both when allocating a new element
422 * and when resetting one.
425 msginit(dns_message_t
*m
) {
431 m
->tcp_continuation
= 0;
433 m
->verify_attempted
= 0;
436 m
->query
.base
= NULL
;
439 m
->saved
.base
= NULL
;
448 msgresetnames(dns_message_t
*msg
, unsigned int first_section
) {
450 dns_name_t
*name
, *next_name
;
451 dns_rdataset_t
*rds
, *next_rds
;
454 * Clean up name lists by calling the rdataset disassociate function.
456 for (i
= first_section
; i
< DNS_SECTION_MAX
; i
++) {
457 name
= ISC_LIST_HEAD(msg
->sections
[i
]);
458 while (name
!= NULL
) {
459 next_name
= ISC_LIST_NEXT(name
, link
);
460 ISC_LIST_UNLINK(msg
->sections
[i
], name
, link
);
462 rds
= ISC_LIST_HEAD(name
->list
);
463 while (rds
!= NULL
) {
464 next_rds
= ISC_LIST_NEXT(rds
, link
);
465 ISC_LIST_UNLINK(name
->list
, rds
, link
);
467 INSIST(dns_rdataset_isassociated(rds
));
468 dns_rdataset_disassociate(rds
);
469 isc_mempool_put(msg
->rdspool
, rds
);
472 if (dns_name_dynamic(name
))
473 dns_name_free(name
, msg
->mctx
);
474 isc_mempool_put(msg
->namepool
, name
);
481 msgresetopt(dns_message_t
*msg
)
483 if (msg
->opt
!= NULL
) {
484 if (msg
->opt_reserved
> 0) {
485 dns_message_renderrelease(msg
, msg
->opt_reserved
);
486 msg
->opt_reserved
= 0;
488 INSIST(dns_rdataset_isassociated(msg
->opt
));
489 dns_rdataset_disassociate(msg
->opt
);
490 isc_mempool_put(msg
->rdspool
, msg
->opt
);
498 msgresetsigs(dns_message_t
*msg
, isc_boolean_t replying
) {
499 if (msg
->sig_reserved
> 0) {
500 dns_message_renderrelease(msg
, msg
->sig_reserved
);
501 msg
->sig_reserved
= 0;
503 if (msg
->tsig
!= NULL
) {
504 INSIST(dns_rdataset_isassociated(msg
->tsig
));
505 INSIST(msg
->namepool
!= NULL
);
507 INSIST(msg
->querytsig
== NULL
);
508 msg
->querytsig
= msg
->tsig
;
510 dns_rdataset_disassociate(msg
->tsig
);
511 isc_mempool_put(msg
->rdspool
, msg
->tsig
);
512 if (msg
->querytsig
!= NULL
) {
513 dns_rdataset_disassociate(msg
->querytsig
);
514 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
517 if (dns_name_dynamic(msg
->tsigname
))
518 dns_name_free(msg
->tsigname
, msg
->mctx
);
519 isc_mempool_put(msg
->namepool
, msg
->tsigname
);
521 msg
->tsigname
= NULL
;
522 } else if (msg
->querytsig
!= NULL
&& !replying
) {
523 dns_rdataset_disassociate(msg
->querytsig
);
524 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
525 msg
->querytsig
= NULL
;
527 if (msg
->sig0
!= NULL
) {
528 INSIST(dns_rdataset_isassociated(msg
->sig0
));
529 dns_rdataset_disassociate(msg
->sig0
);
530 isc_mempool_put(msg
->rdspool
, msg
->sig0
);
531 if (msg
->sig0name
!= NULL
) {
532 if (dns_name_dynamic(msg
->sig0name
))
533 dns_name_free(msg
->sig0name
, msg
->mctx
);
534 isc_mempool_put(msg
->namepool
, msg
->sig0name
);
537 msg
->sig0name
= NULL
;
542 * Free all but one (or everything) for this message. This is used by
543 * both dns_message_reset() and dns_message_destroy().
546 msgreset(dns_message_t
*msg
, isc_boolean_t everything
) {
547 dns_msgblock_t
*msgblock
, *next_msgblock
;
548 isc_buffer_t
*dynbuf
, *next_dynbuf
;
550 dns_rdatalist_t
*rdatalist
;
552 msgresetnames(msg
, 0);
554 msgresetsigs(msg
, ISC_FALSE
);
557 * Clean up linked lists.
561 * Run through the free lists, and just unlink anything found there.
562 * The memory isn't lost since these are part of message blocks we
565 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
566 while (rdata
!= NULL
) {
567 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
568 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
570 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
571 while (rdatalist
!= NULL
) {
572 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
573 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
576 dynbuf
= ISC_LIST_HEAD(msg
->scratchpad
);
577 INSIST(dynbuf
!= NULL
);
579 isc_buffer_clear(dynbuf
);
580 dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
582 while (dynbuf
!= NULL
) {
583 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
584 ISC_LIST_UNLINK(msg
->scratchpad
, dynbuf
, link
);
585 isc_buffer_free(&dynbuf
);
586 dynbuf
= next_dynbuf
;
589 msgblock
= ISC_LIST_HEAD(msg
->rdatas
);
590 if (!everything
&& msgblock
!= NULL
) {
591 msgblock_reset(msgblock
);
592 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
594 while (msgblock
!= NULL
) {
595 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
596 ISC_LIST_UNLINK(msg
->rdatas
, msgblock
, link
);
597 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdata_t
));
598 msgblock
= next_msgblock
;
602 * rdatalists could be empty.
605 msgblock
= ISC_LIST_HEAD(msg
->rdatalists
);
606 if (!everything
&& msgblock
!= NULL
) {
607 msgblock_reset(msgblock
);
608 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
610 while (msgblock
!= NULL
) {
611 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
612 ISC_LIST_UNLINK(msg
->rdatalists
, msgblock
, link
);
613 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdatalist_t
));
614 msgblock
= next_msgblock
;
617 msgblock
= ISC_LIST_HEAD(msg
->offsets
);
618 if (!everything
&& msgblock
!= NULL
) {
619 msgblock_reset(msgblock
);
620 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
622 while (msgblock
!= NULL
) {
623 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
624 ISC_LIST_UNLINK(msg
->offsets
, msgblock
, link
);
625 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_offsets_t
));
626 msgblock
= next_msgblock
;
629 if (msg
->tsigkey
!= NULL
) {
630 dns_tsigkey_detach(&msg
->tsigkey
);
634 if (msg
->tsigctx
!= NULL
)
635 dst_context_destroy(&msg
->tsigctx
);
637 if (msg
->query
.base
!= NULL
) {
638 if (msg
->free_query
!= 0)
639 isc_mem_put(msg
->mctx
, msg
->query
.base
,
641 msg
->query
.base
= NULL
;
642 msg
->query
.length
= 0;
645 if (msg
->saved
.base
!= NULL
) {
646 if (msg
->free_saved
!= 0)
647 isc_mem_put(msg
->mctx
, msg
->saved
.base
,
649 msg
->saved
.base
= NULL
;
650 msg
->saved
.length
= 0;
654 * cleanup the buffer cleanup list
656 dynbuf
= ISC_LIST_HEAD(msg
->cleanup
);
657 while (dynbuf
!= NULL
) {
658 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
659 ISC_LIST_UNLINK(msg
->cleanup
, dynbuf
, link
);
660 isc_buffer_free(&dynbuf
);
661 dynbuf
= next_dynbuf
;
665 * Set other bits to normal default values.
670 ENSURE(isc_mempool_getallocated(msg
->namepool
) == 0);
671 ENSURE(isc_mempool_getallocated(msg
->rdspool
) == 0);
675 spacefortsig(dns_tsigkey_t
*key
, int otherlen
) {
681 * The space required for an TSIG record is:
683 * n1 bytes for the name
684 * 2 bytes for the type
685 * 2 bytes for the class
686 * 4 bytes for the ttl
687 * 2 bytes for the rdlength
688 * n2 bytes for the algorithm name
689 * 6 bytes for the time signed
690 * 2 bytes for the fudge
691 * 2 bytes for the MAC size
692 * x bytes for the MAC
693 * 2 bytes for the original id
694 * 2 bytes for the error
695 * 2 bytes for the other data length
696 * y bytes for the other data (at most)
697 * ---------------------------------
698 * 26 + n1 + n2 + x + y bytes
701 dns_name_toregion(&key
->name
, &r1
);
702 dns_name_toregion(key
->algorithm
, &r2
);
703 if (key
->key
== NULL
)
706 result
= dst_key_sigsize(key
->key
, &x
);
707 if (result
!= ISC_R_SUCCESS
)
710 return (26 + r1
.length
+ r2
.length
+ x
+ otherlen
);
714 dns_message_create(isc_mem_t
*mctx
, unsigned int intent
, dns_message_t
**msgp
)
718 isc_buffer_t
*dynbuf
;
721 REQUIRE(mctx
!= NULL
);
722 REQUIRE(msgp
!= NULL
);
723 REQUIRE(*msgp
== NULL
);
724 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
725 || intent
== DNS_MESSAGE_INTENTRENDER
);
727 m
= isc_mem_get(mctx
, sizeof(dns_message_t
));
729 return (ISC_R_NOMEMORY
);
732 * No allocations until further notice. Just initialize all lists
733 * and other members that are freed in the cleanup phase here.
736 m
->magic
= DNS_MESSAGE_MAGIC
;
737 m
->from_to_wire
= intent
;
740 for (i
= 0; i
< DNS_SECTION_MAX
; i
++)
741 ISC_LIST_INIT(m
->sections
[i
]);
744 isc_mem_attach(mctx
, &m
->mctx
);
746 ISC_LIST_INIT(m
->scratchpad
);
747 ISC_LIST_INIT(m
->cleanup
);
750 ISC_LIST_INIT(m
->rdatas
);
751 ISC_LIST_INIT(m
->rdatalists
);
752 ISC_LIST_INIT(m
->offsets
);
753 ISC_LIST_INIT(m
->freerdata
);
754 ISC_LIST_INIT(m
->freerdatalist
);
757 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
760 result
= isc_mempool_create(m
->mctx
, sizeof(dns_name_t
), &m
->namepool
);
761 if (result
!= ISC_R_SUCCESS
)
763 isc_mempool_setfreemax(m
->namepool
, NAME_COUNT
);
764 isc_mempool_setname(m
->namepool
, "msg:names");
766 result
= isc_mempool_create(m
->mctx
, sizeof(dns_rdataset_t
),
768 if (result
!= ISC_R_SUCCESS
)
770 isc_mempool_setfreemax(m
->rdspool
, NAME_COUNT
);
771 isc_mempool_setname(m
->rdspool
, "msg:rdataset");
774 result
= isc_buffer_allocate(mctx
, &dynbuf
, SCRATCHPAD_SIZE
);
775 if (result
!= ISC_R_SUCCESS
)
777 ISC_LIST_APPEND(m
->scratchpad
, dynbuf
, link
);
782 return (ISC_R_SUCCESS
);
785 * Cleanup for error returns.
788 dynbuf
= ISC_LIST_HEAD(m
->scratchpad
);
789 if (dynbuf
!= NULL
) {
790 ISC_LIST_UNLINK(m
->scratchpad
, dynbuf
, link
);
791 isc_buffer_free(&dynbuf
);
793 if (m
->namepool
!= NULL
)
794 isc_mempool_destroy(&m
->namepool
);
795 if (m
->rdspool
!= NULL
)
796 isc_mempool_destroy(&m
->rdspool
);
798 isc_mem_putanddetach(&mctx
, m
, sizeof(dns_message_t
));
800 return (ISC_R_NOMEMORY
);
804 dns_message_reset(dns_message_t
*msg
, unsigned int intent
) {
805 REQUIRE(DNS_MESSAGE_VALID(msg
));
806 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
807 || intent
== DNS_MESSAGE_INTENTRENDER
);
809 msgreset(msg
, ISC_FALSE
);
810 msg
->from_to_wire
= intent
;
814 dns_message_destroy(dns_message_t
**msgp
) {
817 REQUIRE(msgp
!= NULL
);
818 REQUIRE(DNS_MESSAGE_VALID(*msgp
));
823 msgreset(msg
, ISC_TRUE
);
824 isc_mempool_destroy(&msg
->namepool
);
825 isc_mempool_destroy(&msg
->rdspool
);
827 isc_mem_putanddetach(&msg
->mctx
, msg
, sizeof(dns_message_t
));
831 findname(dns_name_t
**foundname
, dns_name_t
*target
,
832 dns_namelist_t
*section
)
836 for (curr
= ISC_LIST_TAIL(*section
);
838 curr
= ISC_LIST_PREV(curr
, link
)) {
839 if (dns_name_equal(curr
, target
)) {
840 if (foundname
!= NULL
)
842 return (ISC_R_SUCCESS
);
846 return (ISC_R_NOTFOUND
);
850 dns_message_find(dns_name_t
*name
, dns_rdataclass_t rdclass
,
851 dns_rdatatype_t type
, dns_rdatatype_t covers
,
852 dns_rdataset_t
**rdataset
)
854 dns_rdataset_t
*curr
;
856 if (rdataset
!= NULL
) {
857 REQUIRE(*rdataset
== NULL
);
860 for (curr
= ISC_LIST_TAIL(name
->list
);
862 curr
= ISC_LIST_PREV(curr
, link
)) {
863 if (curr
->rdclass
== rdclass
&&
864 curr
->type
== type
&& curr
->covers
== covers
) {
865 if (rdataset
!= NULL
)
867 return (ISC_R_SUCCESS
);
871 return (ISC_R_NOTFOUND
);
875 dns_message_findtype(dns_name_t
*name
, dns_rdatatype_t type
,
876 dns_rdatatype_t covers
, dns_rdataset_t
**rdataset
)
878 dns_rdataset_t
*curr
;
880 REQUIRE(name
!= NULL
);
881 if (rdataset
!= NULL
) {
882 REQUIRE(*rdataset
== NULL
);
885 for (curr
= ISC_LIST_TAIL(name
->list
);
887 curr
= ISC_LIST_PREV(curr
, link
)) {
888 if (curr
->type
== type
&& curr
->covers
== covers
) {
889 if (rdataset
!= NULL
)
891 return (ISC_R_SUCCESS
);
895 return (ISC_R_NOTFOUND
);
899 * Read a name from buffer "source".
902 getname(dns_name_t
*name
, isc_buffer_t
*source
, dns_message_t
*msg
,
903 dns_decompress_t
*dctx
)
905 isc_buffer_t
*scratch
;
909 scratch
= currentbuffer(msg
);
912 * First try: use current buffer.
913 * Second try: allocate a new buffer and use that.
917 result
= dns_name_fromwire(name
, source
, dctx
, ISC_FALSE
,
920 if (result
== ISC_R_NOSPACE
) {
923 result
= newbuffer(msg
, SCRATCHPAD_SIZE
);
924 if (result
!= ISC_R_SUCCESS
)
927 scratch
= currentbuffer(msg
);
928 dns_name_reset(name
);
934 INSIST(0); /* Cannot get here... */
935 return (ISC_R_UNEXPECTED
);
939 getrdata(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
940 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
,
941 unsigned int rdatalen
, dns_rdata_t
*rdata
)
943 isc_buffer_t
*scratch
;
946 unsigned int trysize
;
948 scratch
= currentbuffer(msg
);
950 isc_buffer_setactive(source
, rdatalen
);
953 * First try: use current buffer.
954 * Second try: allocate a new buffer of size
955 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
956 * (the data will fit if it was not more than 50% compressed)
957 * Subsequent tries: double buffer size on each try.
961 /* XXX possibly change this to a while (tries < 2) loop */
963 result
= dns_rdata_fromwire(rdata
, rdclass
, rdtype
,
967 if (result
== ISC_R_NOSPACE
) {
969 trysize
= 2 * rdatalen
;
970 if (trysize
< SCRATCHPAD_SIZE
)
971 trysize
= SCRATCHPAD_SIZE
;
973 INSIST(trysize
!= 0);
974 if (trysize
>= 65535)
975 return (ISC_R_NOSPACE
);
976 /* XXX DNS_R_RRTOOLONG? */
980 result
= newbuffer(msg
, trysize
);
981 if (result
!= ISC_R_SUCCESS
)
984 scratch
= currentbuffer(msg
);
994 seen_problem = ISC_TRUE; \
996 result = DNS_R_FORMERR; \
999 } while (/*CONSTCOND*/0)
1002 getquestions(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
1003 unsigned int options
)
1009 dns_offsets_t
*offsets
;
1010 dns_rdataset_t
*rdataset
;
1011 dns_rdatalist_t
*rdatalist
;
1012 isc_result_t result
;
1013 dns_rdatatype_t rdtype
;
1014 dns_rdataclass_t rdclass
;
1015 dns_namelist_t
*section
;
1016 isc_boolean_t free_name
;
1017 isc_boolean_t best_effort
;
1018 isc_boolean_t seen_problem
;
1020 section
= &msg
->sections
[DNS_SECTION_QUESTION
];
1022 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1023 seen_problem
= ISC_FALSE
;
1029 for (count
= 0; count
< msg
->counts
[DNS_SECTION_QUESTION
]; count
++) {
1030 name
= isc_mempool_get(msg
->namepool
);
1032 return (ISC_R_NOMEMORY
);
1033 free_name
= ISC_TRUE
;
1035 offsets
= newoffsets(msg
);
1036 if (offsets
== NULL
) {
1037 result
= ISC_R_NOMEMORY
;
1040 dns_name_init(name
, *offsets
);
1043 * Parse the name out of this packet.
1045 isc_buffer_remainingregion(source
, &r
);
1046 isc_buffer_setactive(source
, r
.length
);
1047 result
= getname(name
, source
, msg
, dctx
);
1048 if (result
!= ISC_R_SUCCESS
)
1052 * Run through the section, looking to see if this name
1053 * is already there. If it is found, put back the allocated
1054 * name since we no longer need it, and set our name pointer
1055 * to point to the name we found.
1057 result
= findname(&name2
, name
, section
);
1060 * If it is the first name in the section, accept it.
1062 * If it is not, but is not the same as the name already
1063 * in the question section, append to the section. Note that
1064 * here in the question section this is illegal, so return
1065 * FORMERR. In the future, check the opcode to see if
1066 * this should be legal or not. In either case we no longer
1067 * need this name pointer.
1069 if (result
!= ISC_R_SUCCESS
) {
1070 if (!ISC_LIST_EMPTY(*section
))
1072 ISC_LIST_APPEND(*section
, name
, link
);
1073 free_name
= ISC_FALSE
;
1075 isc_mempool_put(msg
->namepool
, name
);
1078 free_name
= ISC_FALSE
;
1082 * Get type and class.
1084 isc_buffer_remainingregion(source
, &r
);
1086 result
= ISC_R_UNEXPECTEDEND
;
1089 rdtype
= isc_buffer_getuint16(source
);
1090 rdclass
= isc_buffer_getuint16(source
);
1093 * If this class is different than the one we already read,
1096 if (msg
->state
== DNS_SECTION_ANY
) {
1097 msg
->state
= DNS_SECTION_QUESTION
;
1098 msg
->rdclass
= rdclass
;
1099 } else if (msg
->rdclass
!= rdclass
)
1103 * Can't ask the same question twice.
1105 result
= dns_message_find(name
, rdclass
, rdtype
, 0, NULL
);
1106 if (result
== ISC_R_SUCCESS
)
1110 * Allocate a new rdatalist.
1112 rdatalist
= newrdatalist(msg
);
1113 if (rdatalist
== NULL
) {
1114 result
= ISC_R_NOMEMORY
;
1117 rdataset
= isc_mempool_get(msg
->rdspool
);
1118 if (rdataset
== NULL
) {
1119 result
= ISC_R_NOMEMORY
;
1124 * Convert rdatalist to rdataset, and attach the latter to
1127 rdatalist
->type
= rdtype
;
1128 rdatalist
->covers
= 0;
1129 rdatalist
->rdclass
= rdclass
;
1131 ISC_LIST_INIT(rdatalist
->rdata
);
1133 dns_rdataset_init(rdataset
);
1134 result
= dns_rdatalist_tordataset(rdatalist
, rdataset
);
1135 if (result
!= ISC_R_SUCCESS
)
1138 rdataset
->attributes
|= DNS_RDATASETATTR_QUESTION
;
1140 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1145 return (DNS_R_RECOVERABLE
);
1146 return (ISC_R_SUCCESS
);
1149 if (rdataset
!= NULL
) {
1150 INSIST(!dns_rdataset_isassociated(rdataset
));
1151 isc_mempool_put(msg
->rdspool
, rdataset
);
1154 if (rdatalist
!= NULL
)
1155 isc_mempool_put(msg
->rdlpool
, rdatalist
);
1158 isc_mempool_put(msg
->namepool
, name
);
1163 static isc_boolean_t
1164 update(dns_section_t section
, dns_rdataclass_t rdclass
) {
1165 if (section
== DNS_SECTION_PREREQUISITE
)
1166 return (ISC_TF(rdclass
== dns_rdataclass_any
||
1167 rdclass
== dns_rdataclass_none
));
1168 if (section
== DNS_SECTION_UPDATE
)
1169 return (ISC_TF(rdclass
== dns_rdataclass_any
));
1174 getsection(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
1175 dns_section_t sectionid
, unsigned int options
)
1178 unsigned int count
, rdatalen
;
1181 dns_offsets_t
*offsets
;
1182 dns_rdataset_t
*rdataset
= NULL
;
1183 dns_rdatalist_t
*rdatalist
;
1184 isc_result_t result
;
1185 dns_rdatatype_t rdtype
, covers
;
1186 dns_rdataclass_t rdclass
;
1189 dns_namelist_t
*section
;
1190 isc_boolean_t free_name
, free_rdataset
;
1191 isc_boolean_t preserve_order
, best_effort
, seen_problem
;
1192 isc_boolean_t issigzero
;
1194 preserve_order
= ISC_TF(options
& DNS_MESSAGEPARSE_PRESERVEORDER
);
1195 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1196 seen_problem
= ISC_FALSE
;
1198 for (count
= 0; count
< msg
->counts
[sectionid
]; count
++) {
1199 int recstart
= source
->current
;
1200 isc_boolean_t skip_name_search
, skip_type_search
;
1202 section
= &msg
->sections
[sectionid
];
1204 skip_name_search
= ISC_FALSE
;
1205 skip_type_search
= ISC_FALSE
;
1206 free_rdataset
= ISC_FALSE
;
1208 name
= isc_mempool_get(msg
->namepool
);
1210 return (ISC_R_NOMEMORY
);
1211 free_name
= ISC_TRUE
;
1213 offsets
= newoffsets(msg
);
1214 if (offsets
== NULL
) {
1215 result
= ISC_R_NOMEMORY
;
1218 dns_name_init(name
, *offsets
);
1221 * Parse the name out of this packet.
1223 isc_buffer_remainingregion(source
, &r
);
1224 isc_buffer_setactive(source
, r
.length
);
1225 result
= getname(name
, source
, msg
, dctx
);
1226 if (result
!= ISC_R_SUCCESS
)
1230 * Get type, class, ttl, and rdatalen. Verify that at least
1231 * rdatalen bytes remain. (Some of this is deferred to
1234 isc_buffer_remainingregion(source
, &r
);
1235 if (r
.length
< 2 + 2 + 4 + 2) {
1236 result
= ISC_R_UNEXPECTEDEND
;
1239 rdtype
= isc_buffer_getuint16(source
);
1240 rdclass
= isc_buffer_getuint16(source
);
1243 * If there was no question section, we may not yet have
1244 * established a class. Do so now.
1246 if (msg
->state
== DNS_SECTION_ANY
&&
1247 rdtype
!= dns_rdatatype_opt
&& /* class is UDP SIZE */
1248 rdtype
!= dns_rdatatype_tsig
&& /* class is ANY */
1249 rdtype
!= dns_rdatatype_tkey
) { /* class is undefined */
1250 msg
->rdclass
= rdclass
;
1251 msg
->state
= DNS_SECTION_QUESTION
;
1255 * If this class is different than the one in the question
1258 if (msg
->opcode
!= dns_opcode_update
1259 && rdtype
!= dns_rdatatype_tsig
1260 && rdtype
!= dns_rdatatype_opt
1261 && rdtype
!= dns_rdatatype_dnskey
/* in a TKEY query */
1262 && rdtype
!= dns_rdatatype_sig
/* SIG(0) */
1263 && rdtype
!= dns_rdatatype_tkey
/* Win2000 TKEY */
1264 && msg
->rdclass
!= dns_rdataclass_any
1265 && msg
->rdclass
!= rdclass
)
1269 * Special type handling for TSIG, OPT, and TKEY.
1271 if (rdtype
== dns_rdatatype_tsig
) {
1273 * If it is a tsig, verify that it is in the
1274 * additional data section.
1276 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1277 rdclass
!= dns_rdataclass_any
||
1278 count
!= msg
->counts
[sectionid
] - 1)
1280 msg
->sigstart
= recstart
;
1281 skip_name_search
= ISC_TRUE
;
1282 skip_type_search
= ISC_TRUE
;
1283 } else if (rdtype
== dns_rdatatype_opt
) {
1285 * The name of an OPT record must be ".", it
1286 * must be in the additional data section, and
1287 * it must be the first OPT we've seen.
1289 if (!dns_name_equal(dns_rootname
, name
) ||
1292 skip_name_search
= ISC_TRUE
;
1293 skip_type_search
= ISC_TRUE
;
1294 } else if (rdtype
== dns_rdatatype_tkey
) {
1296 * A TKEY must be in the additional section if this
1297 * is a query, and the answer section if this is a
1298 * response. Unless it's a Win2000 client.
1300 * Its class is ignored.
1302 dns_section_t tkeysection
;
1304 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0)
1305 tkeysection
= DNS_SECTION_ADDITIONAL
;
1307 tkeysection
= DNS_SECTION_ANSWER
;
1308 if (sectionid
!= tkeysection
&&
1309 sectionid
!= DNS_SECTION_ANSWER
)
1314 * ... now get ttl and rdatalen, and check buffer.
1316 ttl
= isc_buffer_getuint32(source
);
1317 rdatalen
= isc_buffer_getuint16(source
);
1318 r
.length
-= (2 + 2 + 4 + 2);
1319 if (r
.length
< rdatalen
) {
1320 result
= ISC_R_UNEXPECTEDEND
;
1325 * Read the rdata from the wire format. Interpret the
1326 * rdata according to its actual class, even if it had a
1327 * DynDNS meta-class in the packet (unless this is a TSIG).
1328 * Then put the meta-class back into the finished rdata.
1330 rdata
= newrdata(msg
);
1331 if (rdata
== NULL
) {
1332 result
= ISC_R_NOMEMORY
;
1335 if (msg
->opcode
== dns_opcode_update
&&
1336 update(sectionid
, rdclass
)) {
1337 if (rdatalen
!= 0) {
1338 result
= DNS_R_FORMERR
;
1342 * When the rdata is empty, the data pointer is
1343 * never dereferenced, but it must still be non-NULL.
1344 * Casting 1 rather than "" avoids warnings about
1345 * discarding the const attribute of a string,
1346 * for compilers that would warn about such things.
1348 rdata
->data
= (unsigned char *)1;
1350 rdata
->rdclass
= rdclass
;
1351 rdata
->type
= rdtype
;
1352 rdata
->flags
= DNS_RDATA_UPDATE
;
1353 result
= ISC_R_SUCCESS
;
1354 } else if (rdclass
== dns_rdataclass_none
&&
1355 msg
->opcode
== dns_opcode_update
&&
1356 sectionid
== DNS_SECTION_UPDATE
) {
1357 result
= getrdata(source
, msg
, dctx
, msg
->rdclass
,
1358 rdtype
, rdatalen
, rdata
);
1360 result
= getrdata(source
, msg
, dctx
, rdclass
,
1361 rdtype
, rdatalen
, rdata
);
1362 if (result
!= ISC_R_SUCCESS
)
1364 rdata
->rdclass
= rdclass
;
1365 issigzero
= ISC_FALSE
;
1366 if (rdtype
== dns_rdatatype_rrsig
&&
1367 rdata
->flags
== 0) {
1368 covers
= dns_rdata_covers(rdata
);
1371 } else if (rdtype
== dns_rdatatype_sig
/* SIG(0) */ &&
1372 rdata
->flags
== 0) {
1373 covers
= dns_rdata_covers(rdata
);
1375 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1376 count
!= msg
->counts
[sectionid
] - 1)
1378 msg
->sigstart
= recstart
;
1379 skip_name_search
= ISC_TRUE
;
1380 skip_type_search
= ISC_TRUE
;
1381 issigzero
= ISC_TRUE
;
1387 * Check the ownername of NSEC3 records
1389 if (rdtype
== dns_rdatatype_nsec3
&&
1390 !dns_rdata_checkowner(name
, msg
->rdclass
, rdtype
,
1392 result
= DNS_R_BADOWNERNAME
;
1397 * If we are doing a dynamic update or this is a meta-type,
1398 * don't bother searching for a name, just append this one
1399 * to the end of the message.
1401 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1403 if (rdtype
!= dns_rdatatype_opt
&&
1404 rdtype
!= dns_rdatatype_tsig
&&
1407 ISC_LIST_APPEND(*section
, name
, link
);
1408 free_name
= ISC_FALSE
;
1412 * Run through the section, looking to see if this name
1413 * is already there. If it is found, put back the
1414 * allocated name since we no longer need it, and set
1415 * our name pointer to point to the name we found.
1417 result
= findname(&name2
, name
, section
);
1420 * If it is a new name, append to the section.
1422 if (result
== ISC_R_SUCCESS
) {
1423 isc_mempool_put(msg
->namepool
, name
);
1426 ISC_LIST_APPEND(*section
, name
, link
);
1428 free_name
= ISC_FALSE
;
1432 * Search name for the particular type and class.
1433 * Skip this stage if in update mode or this is a meta-type.
1435 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1437 result
= ISC_R_NOTFOUND
;
1440 * If this is a type that can only occur in
1441 * the question section, fail.
1443 if (dns_rdatatype_questiononly(rdtype
))
1447 result
= dns_message_find(name
, rdclass
, rdtype
,
1452 * If we found an rdataset that matches, we need to
1453 * append this rdata to that set. If we did not, we need
1454 * to create a new rdatalist, store the important bits there,
1455 * convert it to an rdataset, and link the latter to the name.
1456 * Yuck. When appending, make certain that the type isn't
1457 * a singleton type, such as SOA or CNAME.
1459 * Note that this check will be bypassed when preserving order,
1460 * the opcode is an update, or the type search is skipped.
1462 if (result
== ISC_R_SUCCESS
) {
1463 if (dns_rdatatype_issingleton(rdtype
)) {
1465 dns_rdatalist_fromrdataset(rdataset
,
1467 first
= ISC_LIST_HEAD(rdatalist
->rdata
);
1468 INSIST(first
!= NULL
);
1469 if (dns_rdata_compare(rdata
, first
) != 0)
1474 if (result
== ISC_R_NOTFOUND
) {
1475 rdataset
= isc_mempool_get(msg
->rdspool
);
1476 if (rdataset
== NULL
) {
1477 result
= ISC_R_NOMEMORY
;
1480 free_rdataset
= ISC_TRUE
;
1482 rdatalist
= newrdatalist(msg
);
1483 if (rdatalist
== NULL
) {
1484 result
= ISC_R_NOMEMORY
;
1488 rdatalist
->type
= rdtype
;
1489 rdatalist
->covers
= covers
;
1490 rdatalist
->rdclass
= rdclass
;
1491 rdatalist
->ttl
= ttl
;
1492 ISC_LIST_INIT(rdatalist
->rdata
);
1494 dns_rdataset_init(rdataset
);
1495 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
,
1499 if (rdtype
!= dns_rdatatype_opt
&&
1500 rdtype
!= dns_rdatatype_tsig
&&
1503 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1504 free_rdataset
= ISC_FALSE
;
1511 * Section 5.2 of RFC2181 says we should drop
1512 * nonauthoritative rrsets where the TTLs differ, but we
1513 * currently treat them the as if they were authoritative and
1516 if (ttl
!= rdataset
->ttl
) {
1517 rdataset
->attributes
|= DNS_RDATASETATTR_TTLADJUSTED
;
1518 if (ttl
< rdataset
->ttl
)
1519 rdataset
->ttl
= ttl
;
1522 /* Append this rdata to the rdataset. */
1523 dns_rdatalist_fromrdataset(rdataset
, &rdatalist
);
1524 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1527 * If this is an OPT record, remember it. Also, set
1528 * the extended rcode. Note that msg->opt will only be set
1529 * if best-effort parsing is enabled.
1531 if (rdtype
== dns_rdatatype_opt
&& msg
->opt
== NULL
) {
1534 msg
->opt
= rdataset
;
1536 free_rdataset
= ISC_FALSE
;
1537 ercode
= (dns_rcode_t
)
1538 ((msg
->opt
->ttl
& DNS_MESSAGE_EDNSRCODE_MASK
)
1540 msg
->rcode
|= ercode
;
1541 isc_mempool_put(msg
->namepool
, name
);
1542 free_name
= ISC_FALSE
;
1546 * If this is an SIG(0) or TSIG record, remember it. Note
1547 * that msg->sig0 or msg->tsig will only be set if best-effort
1548 * parsing is enabled.
1550 if (issigzero
&& msg
->sig0
== NULL
) {
1551 msg
->sig0
= rdataset
;
1552 msg
->sig0name
= name
;
1554 free_rdataset
= ISC_FALSE
;
1555 free_name
= ISC_FALSE
;
1556 } else if (rdtype
== dns_rdatatype_tsig
&& msg
->tsig
== NULL
) {
1557 msg
->tsig
= rdataset
;
1558 msg
->tsigname
= name
;
1559 /* Windows doesn't like TSIG names to be compressed. */
1560 msg
->tsigname
->attributes
|= DNS_NAMEATTR_NOCOMPRESS
;
1562 free_rdataset
= ISC_FALSE
;
1563 free_name
= ISC_FALSE
;
1568 isc_mempool_put(msg
->namepool
, name
);
1570 isc_mempool_put(msg
->rdspool
, rdataset
);
1571 free_name
= free_rdataset
= ISC_FALSE
;
1573 INSIST(free_name
== ISC_FALSE
);
1574 INSIST(free_rdataset
== ISC_FALSE
);
1578 return (DNS_R_RECOVERABLE
);
1579 return (ISC_R_SUCCESS
);
1583 isc_mempool_put(msg
->namepool
, name
);
1585 isc_mempool_put(msg
->rdspool
, rdataset
);
1591 dns_message_parse(dns_message_t
*msg
, isc_buffer_t
*source
,
1592 unsigned int options
)
1595 dns_decompress_t dctx
;
1597 isc_uint16_t tmpflags
;
1598 isc_buffer_t origsource
;
1599 isc_boolean_t seen_problem
;
1600 isc_boolean_t ignore_tc
;
1602 REQUIRE(DNS_MESSAGE_VALID(msg
));
1603 REQUIRE(source
!= NULL
);
1604 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
1606 seen_problem
= ISC_FALSE
;
1607 ignore_tc
= ISC_TF(options
& DNS_MESSAGEPARSE_IGNORETRUNCATION
);
1609 origsource
= *source
;
1612 msg
->question_ok
= 0;
1614 isc_buffer_remainingregion(source
, &r
);
1615 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1616 return (ISC_R_UNEXPECTEDEND
);
1618 msg
->id
= isc_buffer_getuint16(source
);
1619 tmpflags
= isc_buffer_getuint16(source
);
1620 msg
->opcode
= ((tmpflags
& DNS_MESSAGE_OPCODE_MASK
)
1621 >> DNS_MESSAGE_OPCODE_SHIFT
);
1622 msg
->rcode
= (dns_rcode_t
)(tmpflags
& DNS_MESSAGE_RCODE_MASK
);
1623 msg
->flags
= (tmpflags
& DNS_MESSAGE_FLAG_MASK
);
1624 msg
->counts
[DNS_SECTION_QUESTION
] = isc_buffer_getuint16(source
);
1625 msg
->counts
[DNS_SECTION_ANSWER
] = isc_buffer_getuint16(source
);
1626 msg
->counts
[DNS_SECTION_AUTHORITY
] = isc_buffer_getuint16(source
);
1627 msg
->counts
[DNS_SECTION_ADDITIONAL
] = isc_buffer_getuint16(source
);
1634 dns_decompress_init(&dctx
, -1, DNS_DECOMPRESS_ANY
);
1636 dns_decompress_setmethods(&dctx
, DNS_COMPRESS_GLOBAL14
);
1638 ret
= getquestions(source
, msg
, &dctx
, options
);
1639 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1641 if (ret
== DNS_R_RECOVERABLE
) {
1642 seen_problem
= ISC_TRUE
;
1643 ret
= ISC_R_SUCCESS
;
1645 if (ret
!= ISC_R_SUCCESS
)
1647 msg
->question_ok
= 1;
1649 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ANSWER
, options
);
1650 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1652 if (ret
== DNS_R_RECOVERABLE
) {
1653 seen_problem
= ISC_TRUE
;
1654 ret
= ISC_R_SUCCESS
;
1656 if (ret
!= ISC_R_SUCCESS
)
1659 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_AUTHORITY
, options
);
1660 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1662 if (ret
== DNS_R_RECOVERABLE
) {
1663 seen_problem
= ISC_TRUE
;
1664 ret
= ISC_R_SUCCESS
;
1666 if (ret
!= ISC_R_SUCCESS
)
1669 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ADDITIONAL
, options
);
1670 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1672 if (ret
== DNS_R_RECOVERABLE
) {
1673 seen_problem
= ISC_TRUE
;
1674 ret
= ISC_R_SUCCESS
;
1676 if (ret
!= ISC_R_SUCCESS
)
1679 isc_buffer_remainingregion(source
, &r
);
1680 if (r
.length
!= 0) {
1681 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1682 DNS_LOGMODULE_MESSAGE
, ISC_LOG_DEBUG(3),
1683 "message has %u byte(s) of trailing garbage",
1688 if ((options
& DNS_MESSAGEPARSE_CLONEBUFFER
) == 0)
1689 isc_buffer_usedregion(&origsource
, &msg
->saved
);
1691 msg
->saved
.length
= isc_buffer_usedlength(&origsource
);
1692 msg
->saved
.base
= isc_mem_get(msg
->mctx
, msg
->saved
.length
);
1693 if (msg
->saved
.base
== NULL
)
1694 return (ISC_R_NOMEMORY
);
1695 memmove(msg
->saved
.base
, isc_buffer_base(&origsource
),
1697 msg
->free_saved
= 1;
1700 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1701 return (DNS_R_RECOVERABLE
);
1702 if (seen_problem
== ISC_TRUE
)
1703 return (DNS_R_RECOVERABLE
);
1704 return (ISC_R_SUCCESS
);
1708 dns_message_renderbegin(dns_message_t
*msg
, dns_compress_t
*cctx
,
1709 isc_buffer_t
*buffer
)
1713 REQUIRE(DNS_MESSAGE_VALID(msg
));
1714 REQUIRE(buffer
!= NULL
);
1715 REQUIRE(msg
->buffer
== NULL
);
1716 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
1721 * Erase the contents of this buffer.
1723 isc_buffer_clear(buffer
);
1726 * Make certain there is enough for at least the header in this
1729 isc_buffer_availableregion(buffer
, &r
);
1730 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1731 return (ISC_R_NOSPACE
);
1733 if (r
.length
< msg
->reserved
)
1734 return (ISC_R_NOSPACE
);
1737 * Reserve enough space for the header in this buffer.
1739 isc_buffer_add(buffer
, DNS_MESSAGE_HEADERLEN
);
1741 msg
->buffer
= buffer
;
1743 return (ISC_R_SUCCESS
);
1747 dns_message_renderchangebuffer(dns_message_t
*msg
, isc_buffer_t
*buffer
) {
1750 REQUIRE(DNS_MESSAGE_VALID(msg
));
1751 REQUIRE(buffer
!= NULL
);
1752 REQUIRE(msg
->buffer
!= NULL
);
1755 * Ensure that the new buffer is empty, and has enough space to
1756 * hold the current contents.
1758 isc_buffer_clear(buffer
);
1760 isc_buffer_availableregion(buffer
, &rn
);
1761 isc_buffer_usedregion(msg
->buffer
, &r
);
1762 REQUIRE(rn
.length
> r
.length
);
1765 * Copy the contents from the old to the new buffer.
1767 isc_buffer_add(buffer
, r
.length
);
1768 memmove(rn
.base
, r
.base
, r
.length
);
1770 msg
->buffer
= buffer
;
1772 return (ISC_R_SUCCESS
);
1776 dns_message_renderrelease(dns_message_t
*msg
, unsigned int space
) {
1777 REQUIRE(DNS_MESSAGE_VALID(msg
));
1778 REQUIRE(space
<= msg
->reserved
);
1780 msg
->reserved
-= space
;
1784 dns_message_renderreserve(dns_message_t
*msg
, unsigned int space
) {
1787 REQUIRE(DNS_MESSAGE_VALID(msg
));
1789 if (msg
->buffer
!= NULL
) {
1790 isc_buffer_availableregion(msg
->buffer
, &r
);
1791 if (r
.length
< (space
+ msg
->reserved
))
1792 return (ISC_R_NOSPACE
);
1795 msg
->reserved
+= space
;
1797 return (ISC_R_SUCCESS
);
1800 static inline isc_boolean_t
1801 wrong_priority(dns_rdataset_t
*rds
, int pass
, dns_rdatatype_t preferred_glue
) {
1805 * If we are not rendering class IN, this ordering is bogus.
1807 if (rds
->rdclass
!= dns_rdataclass_in
)
1810 switch (rds
->type
) {
1811 case dns_rdatatype_a
:
1812 case dns_rdatatype_aaaa
:
1813 if (preferred_glue
== rds
->type
)
1818 case dns_rdatatype_rrsig
:
1819 case dns_rdatatype_dnskey
:
1826 if (pass_needed
>= pass
)
1832 #ifdef ALLOW_FILTER_AAAA
1834 * Decide whether to not answer with an AAAA record and its RRSIG
1836 static inline isc_boolean_t
1837 norender_rdataset(const dns_rdataset_t
*rdataset
, unsigned int options
)
1839 switch (rdataset
->type
) {
1840 case dns_rdatatype_aaaa
:
1841 if ((options
& DNS_MESSAGERENDER_FILTER_AAAA
) == 0)
1845 case dns_rdatatype_rrsig
:
1846 if ((options
& DNS_MESSAGERENDER_FILTER_AAAA
) == 0 ||
1847 rdataset
->covers
!= dns_rdatatype_aaaa
)
1855 if (rdataset
->rdclass
!= dns_rdataclass_in
)
1863 dns_message_rendersection(dns_message_t
*msg
, dns_section_t sectionid
,
1864 unsigned int options
)
1866 dns_namelist_t
*section
;
1867 dns_name_t
*name
, *next_name
;
1868 dns_rdataset_t
*rdataset
, *next_rdataset
;
1869 unsigned int count
, total
;
1870 isc_result_t result
;
1871 isc_buffer_t st
; /* for rollbacks */
1873 isc_boolean_t partial
= ISC_FALSE
;
1874 unsigned int rd_options
;
1875 dns_rdatatype_t preferred_glue
= 0;
1877 REQUIRE(DNS_MESSAGE_VALID(msg
));
1878 REQUIRE(msg
->buffer
!= NULL
);
1879 REQUIRE(VALID_NAMED_SECTION(sectionid
));
1881 section
= &msg
->sections
[sectionid
];
1883 if ((sectionid
== DNS_SECTION_ADDITIONAL
)
1884 && (options
& DNS_MESSAGERENDER_ORDERED
) == 0) {
1885 if ((options
& DNS_MESSAGERENDER_PREFER_A
) != 0) {
1886 preferred_glue
= dns_rdatatype_a
;
1888 } else if ((options
& DNS_MESSAGERENDER_PREFER_AAAA
) != 0) {
1889 preferred_glue
= dns_rdatatype_aaaa
;
1896 if ((options
& DNS_MESSAGERENDER_OMITDNSSEC
) == 0)
1899 rd_options
= DNS_RDATASETTOWIRE_OMITDNSSEC
;
1902 * Shrink the space in the buffer by the reserved amount.
1904 msg
->buffer
->length
-= msg
->reserved
;
1907 if (msg
->reserved
== 0 && (options
& DNS_MESSAGERENDER_PARTIAL
) != 0)
1911 * Render required glue first. Set TC if it won't fit.
1913 name
= ISC_LIST_HEAD(*section
);
1915 rdataset
= ISC_LIST_HEAD(name
->list
);
1916 if (rdataset
!= NULL
&&
1917 (rdataset
->attributes
& DNS_RDATASETATTR_REQUIREDGLUE
) != 0 &&
1918 (rdataset
->attributes
& DNS_RDATASETATTR_RENDERED
) == 0) {
1919 const void *order_arg
= msg
->order_arg
;
1920 st
= *(msg
->buffer
);
1923 result
= dns_rdataset_towirepartial(rdataset
,
1933 result
= dns_rdataset_towiresorted(rdataset
,
1942 if (partial
&& result
== ISC_R_NOSPACE
) {
1943 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1944 msg
->buffer
->length
+= msg
->reserved
;
1945 msg
->counts
[sectionid
] += total
;
1948 if (result
== ISC_R_NOSPACE
)
1949 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1950 if (result
!= ISC_R_SUCCESS
) {
1951 INSIST(st
.used
< 65536);
1952 dns_compress_rollback(msg
->cctx
,
1953 (isc_uint16_t
)st
.used
);
1954 *(msg
->buffer
) = st
; /* rollback */
1955 msg
->buffer
->length
+= msg
->reserved
;
1956 msg
->counts
[sectionid
] += total
;
1959 rdataset
->attributes
|= DNS_RDATASETATTR_RENDERED
;
1964 name
= ISC_LIST_HEAD(*section
);
1966 msg
->buffer
->length
+= msg
->reserved
;
1967 msg
->counts
[sectionid
] += total
;
1968 return (ISC_R_SUCCESS
);
1971 while (name
!= NULL
) {
1972 next_name
= ISC_LIST_NEXT(name
, link
);
1974 rdataset
= ISC_LIST_HEAD(name
->list
);
1975 while (rdataset
!= NULL
) {
1976 next_rdataset
= ISC_LIST_NEXT(rdataset
, link
);
1978 if ((rdataset
->attributes
&
1979 DNS_RDATASETATTR_RENDERED
) != 0)
1982 if (((options
& DNS_MESSAGERENDER_ORDERED
)
1984 && (sectionid
== DNS_SECTION_ADDITIONAL
)
1985 && wrong_priority(rdataset
, pass
,
1989 #ifdef ALLOW_FILTER_AAAA
1991 * Suppress AAAAs if asked and we are
1992 * not doing DNSSEC or are breaking DNSSEC.
1993 * Say so in the AD bit if we break DNSSEC.
1995 if (norender_rdataset(rdataset
, options
) &&
1996 sectionid
!= DNS_SECTION_QUESTION
) {
1997 if (sectionid
== DNS_SECTION_ANSWER
||
1998 sectionid
== DNS_SECTION_AUTHORITY
)
1999 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2000 if (OPTOUT(rdataset
))
2001 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2006 st
= *(msg
->buffer
);
2010 result
= dns_rdataset_towirepartial(
2021 result
= dns_rdataset_towiresorted(
2034 * If out of space, record stats on what we
2035 * rendered so far, and return that status.
2037 * XXXMLG Need to change this when
2038 * dns_rdataset_towire() can render partial
2039 * sets starting at some arbitrary point in the
2040 * set. This will include setting a bit in the
2041 * rdataset to indicate that a partial
2042 * rendering was done, and some state saved
2043 * somewhere (probably in the message struct)
2044 * to indicate where to continue from.
2046 if (partial
&& result
== ISC_R_NOSPACE
) {
2047 msg
->buffer
->length
+= msg
->reserved
;
2048 msg
->counts
[sectionid
] += total
;
2051 if (result
!= ISC_R_SUCCESS
) {
2052 INSIST(st
.used
< 65536);
2053 dns_compress_rollback(msg
->cctx
,
2054 (isc_uint16_t
)st
.used
);
2055 *(msg
->buffer
) = st
; /* rollback */
2056 msg
->buffer
->length
+= msg
->reserved
;
2057 msg
->counts
[sectionid
] += total
;
2062 * If we have rendered non-validated data,
2063 * ensure that the AD bit is not set.
2065 if (rdataset
->trust
!= dns_trust_secure
&&
2066 (sectionid
== DNS_SECTION_ANSWER
||
2067 sectionid
== DNS_SECTION_AUTHORITY
))
2068 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2069 if (OPTOUT(rdataset
))
2070 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2072 rdataset
->attributes
|=
2073 DNS_RDATASETATTR_RENDERED
;
2076 rdataset
= next_rdataset
;
2081 } while (--pass
!= 0);
2083 msg
->buffer
->length
+= msg
->reserved
;
2084 msg
->counts
[sectionid
] += total
;
2086 return (ISC_R_SUCCESS
);
2090 dns_message_renderheader(dns_message_t
*msg
, isc_buffer_t
*target
) {
2094 REQUIRE(DNS_MESSAGE_VALID(msg
));
2095 REQUIRE(target
!= NULL
);
2097 isc_buffer_availableregion(target
, &r
);
2098 REQUIRE(r
.length
>= DNS_MESSAGE_HEADERLEN
);
2100 isc_buffer_putuint16(target
, msg
->id
);
2102 tmp
= ((msg
->opcode
<< DNS_MESSAGE_OPCODE_SHIFT
)
2103 & DNS_MESSAGE_OPCODE_MASK
);
2104 tmp
|= (msg
->rcode
& DNS_MESSAGE_RCODE_MASK
);
2105 tmp
|= (msg
->flags
& DNS_MESSAGE_FLAG_MASK
);
2107 INSIST(msg
->counts
[DNS_SECTION_QUESTION
] < 65536 &&
2108 msg
->counts
[DNS_SECTION_ANSWER
] < 65536 &&
2109 msg
->counts
[DNS_SECTION_AUTHORITY
] < 65536 &&
2110 msg
->counts
[DNS_SECTION_ADDITIONAL
] < 65536);
2112 isc_buffer_putuint16(target
, tmp
);
2113 isc_buffer_putuint16(target
,
2114 (isc_uint16_t
)msg
->counts
[DNS_SECTION_QUESTION
]);
2115 isc_buffer_putuint16(target
,
2116 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ANSWER
]);
2117 isc_buffer_putuint16(target
,
2118 (isc_uint16_t
)msg
->counts
[DNS_SECTION_AUTHORITY
]);
2119 isc_buffer_putuint16(target
,
2120 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ADDITIONAL
]);
2124 dns_message_renderend(dns_message_t
*msg
) {
2125 isc_buffer_t tmpbuf
;
2130 REQUIRE(DNS_MESSAGE_VALID(msg
));
2131 REQUIRE(msg
->buffer
!= NULL
);
2133 if ((msg
->rcode
& ~DNS_MESSAGE_RCODE_MASK
) != 0 && msg
->opt
== NULL
) {
2135 * We have an extended rcode but are not using EDNS.
2137 return (DNS_R_FORMERR
);
2141 * If we're adding a OPT, TSIG or SIG(0) to a truncated message,
2142 * clear all rdatasets from the message except for the question
2143 * before adding the OPT, TSIG or SIG(0). If the question doesn't
2144 * fit, don't include it.
2146 if ((msg
->tsigkey
!= NULL
|| msg
->sig0key
!= NULL
|| msg
->opt
) &&
2147 (msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
2151 msgresetnames(msg
, DNS_SECTION_ANSWER
);
2153 dns_message_renderreset(msg
);
2155 isc_buffer_clear(msg
->buffer
);
2156 isc_buffer_add(msg
->buffer
, DNS_MESSAGE_HEADERLEN
);
2157 dns_compress_rollback(msg
->cctx
, 0);
2158 result
= dns_message_rendersection(msg
, DNS_SECTION_QUESTION
,
2160 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
2165 * If we've got an OPT record, render it.
2167 if (msg
->opt
!= NULL
) {
2168 dns_message_renderrelease(msg
, msg
->opt_reserved
);
2169 msg
->opt_reserved
= 0;
2171 * Set the extended rcode.
2173 msg
->opt
->ttl
&= ~DNS_MESSAGE_EDNSRCODE_MASK
;
2174 msg
->opt
->ttl
|= ((msg
->rcode
<< 20) &
2175 DNS_MESSAGE_EDNSRCODE_MASK
);
2180 result
= dns_rdataset_towire(msg
->opt
, dns_rootname
,
2181 msg
->cctx
, msg
->buffer
, 0,
2183 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2184 if (result
!= ISC_R_SUCCESS
)
2189 * If we're adding a TSIG record, generate and render it.
2191 if (msg
->tsigkey
!= NULL
) {
2192 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2193 msg
->sig_reserved
= 0;
2194 result
= dns_tsig_sign(msg
);
2195 if (result
!= ISC_R_SUCCESS
)
2198 result
= dns_rdataset_towire(msg
->tsig
, msg
->tsigname
,
2199 msg
->cctx
, msg
->buffer
, 0,
2201 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2202 if (result
!= ISC_R_SUCCESS
)
2207 * If we're adding a SIG(0) record, generate and render it.
2209 if (msg
->sig0key
!= NULL
) {
2210 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2211 msg
->sig_reserved
= 0;
2212 result
= dns_dnssec_signmessage(msg
, msg
->sig0key
);
2213 if (result
!= ISC_R_SUCCESS
)
2217 * Note: dns_rootname is used here, not msg->sig0name, since
2218 * the owner name of a SIG(0) is irrelevant, and will not
2219 * be set in a message being rendered.
2221 result
= dns_rdataset_towire(msg
->sig0
, dns_rootname
,
2222 msg
->cctx
, msg
->buffer
, 0,
2224 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2225 if (result
!= ISC_R_SUCCESS
)
2229 isc_buffer_usedregion(msg
->buffer
, &r
);
2230 isc_buffer_init(&tmpbuf
, r
.base
, r
.length
);
2232 dns_message_renderheader(msg
, &tmpbuf
);
2234 msg
->buffer
= NULL
; /* forget about this buffer only on success XXX */
2236 return (ISC_R_SUCCESS
);
2240 dns_message_renderreset(dns_message_t
*msg
) {
2243 dns_rdataset_t
*rds
;
2246 * Reset the message so that it may be rendered again.
2249 REQUIRE(DNS_MESSAGE_VALID(msg
));
2250 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2254 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
2255 msg
->cursors
[i
] = NULL
;
2257 for (name
= ISC_LIST_HEAD(msg
->sections
[i
]);
2259 name
= ISC_LIST_NEXT(name
, link
)) {
2260 for (rds
= ISC_LIST_HEAD(name
->list
);
2262 rds
= ISC_LIST_NEXT(rds
, link
)) {
2263 rds
->attributes
&= ~DNS_RDATASETATTR_RENDERED
;
2267 if (msg
->tsigname
!= NULL
)
2268 dns_message_puttempname(msg
, &msg
->tsigname
);
2269 if (msg
->tsig
!= NULL
) {
2270 dns_rdataset_disassociate(msg
->tsig
);
2271 dns_message_puttemprdataset(msg
, &msg
->tsig
);
2273 if (msg
->sig0
!= NULL
) {
2274 dns_rdataset_disassociate(msg
->sig0
);
2275 dns_message_puttemprdataset(msg
, &msg
->sig0
);
2280 dns_message_firstname(dns_message_t
*msg
, dns_section_t section
) {
2281 REQUIRE(DNS_MESSAGE_VALID(msg
));
2282 REQUIRE(VALID_NAMED_SECTION(section
));
2284 msg
->cursors
[section
] = ISC_LIST_HEAD(msg
->sections
[section
]);
2286 if (msg
->cursors
[section
] == NULL
)
2287 return (ISC_R_NOMORE
);
2289 return (ISC_R_SUCCESS
);
2293 dns_message_nextname(dns_message_t
*msg
, dns_section_t section
) {
2294 REQUIRE(DNS_MESSAGE_VALID(msg
));
2295 REQUIRE(VALID_NAMED_SECTION(section
));
2296 REQUIRE(msg
->cursors
[section
] != NULL
);
2298 msg
->cursors
[section
] = ISC_LIST_NEXT(msg
->cursors
[section
], link
);
2300 if (msg
->cursors
[section
] == NULL
)
2301 return (ISC_R_NOMORE
);
2303 return (ISC_R_SUCCESS
);
2307 dns_message_currentname(dns_message_t
*msg
, dns_section_t section
,
2310 REQUIRE(DNS_MESSAGE_VALID(msg
));
2311 REQUIRE(VALID_NAMED_SECTION(section
));
2312 REQUIRE(name
!= NULL
&& *name
== NULL
);
2313 REQUIRE(msg
->cursors
[section
] != NULL
);
2315 *name
= msg
->cursors
[section
];
2319 dns_message_findname(dns_message_t
*msg
, dns_section_t section
,
2320 dns_name_t
*target
, dns_rdatatype_t type
,
2321 dns_rdatatype_t covers
, dns_name_t
**name
,
2322 dns_rdataset_t
**rdataset
)
2324 dns_name_t
*foundname
;
2325 isc_result_t result
;
2328 * XXX These requirements are probably too intensive, especially
2329 * where things can be NULL, but as they are they ensure that if
2330 * something is NON-NULL, indicating that the caller expects it
2331 * to be filled in, that we can in fact fill it in.
2333 REQUIRE(msg
!= NULL
);
2334 REQUIRE(VALID_SECTION(section
));
2335 REQUIRE(target
!= NULL
);
2337 REQUIRE(*name
== NULL
);
2338 if (type
== dns_rdatatype_any
) {
2339 REQUIRE(rdataset
== NULL
);
2341 if (rdataset
!= NULL
)
2342 REQUIRE(*rdataset
== NULL
);
2345 result
= findname(&foundname
, target
,
2346 &msg
->sections
[section
]);
2348 if (result
== ISC_R_NOTFOUND
)
2349 return (DNS_R_NXDOMAIN
);
2350 else if (result
!= ISC_R_SUCCESS
)
2357 * And now look for the type.
2359 if (type
== dns_rdatatype_any
)
2360 return (ISC_R_SUCCESS
);
2362 result
= dns_message_findtype(foundname
, type
, covers
, rdataset
);
2363 if (result
== ISC_R_NOTFOUND
)
2364 return (DNS_R_NXRRSET
);
2370 dns_message_movename(dns_message_t
*msg
, dns_name_t
*name
,
2371 dns_section_t fromsection
,
2372 dns_section_t tosection
)
2374 REQUIRE(msg
!= NULL
);
2375 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2376 REQUIRE(name
!= NULL
);
2377 REQUIRE(VALID_NAMED_SECTION(fromsection
));
2378 REQUIRE(VALID_NAMED_SECTION(tosection
));
2381 * Unlink the name from the old section
2383 ISC_LIST_UNLINK(msg
->sections
[fromsection
], name
, link
);
2384 ISC_LIST_APPEND(msg
->sections
[tosection
], name
, link
);
2388 dns_message_addname(dns_message_t
*msg
, dns_name_t
*name
,
2389 dns_section_t section
)
2391 REQUIRE(msg
!= NULL
);
2392 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2393 REQUIRE(name
!= NULL
);
2394 REQUIRE(VALID_NAMED_SECTION(section
));
2396 ISC_LIST_APPEND(msg
->sections
[section
], name
, link
);
2400 dns_message_removename(dns_message_t
*msg
, dns_name_t
*name
,
2401 dns_section_t section
)
2403 REQUIRE(msg
!= NULL
);
2404 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2405 REQUIRE(name
!= NULL
);
2406 REQUIRE(VALID_NAMED_SECTION(section
));
2408 ISC_LIST_UNLINK(msg
->sections
[section
], name
, link
);
2412 dns_message_gettempname(dns_message_t
*msg
, dns_name_t
**item
) {
2413 REQUIRE(DNS_MESSAGE_VALID(msg
));
2414 REQUIRE(item
!= NULL
&& *item
== NULL
);
2416 *item
= isc_mempool_get(msg
->namepool
);
2418 return (ISC_R_NOMEMORY
);
2419 dns_name_init(*item
, NULL
);
2421 return (ISC_R_SUCCESS
);
2425 dns_message_gettempoffsets(dns_message_t
*msg
, dns_offsets_t
**item
) {
2426 REQUIRE(DNS_MESSAGE_VALID(msg
));
2427 REQUIRE(item
!= NULL
&& *item
== NULL
);
2429 *item
= newoffsets(msg
);
2431 return (ISC_R_NOMEMORY
);
2433 return (ISC_R_SUCCESS
);
2437 dns_message_gettemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2438 REQUIRE(DNS_MESSAGE_VALID(msg
));
2439 REQUIRE(item
!= NULL
&& *item
== NULL
);
2441 *item
= newrdata(msg
);
2443 return (ISC_R_NOMEMORY
);
2445 return (ISC_R_SUCCESS
);
2449 dns_message_gettemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2450 REQUIRE(DNS_MESSAGE_VALID(msg
));
2451 REQUIRE(item
!= NULL
&& *item
== NULL
);
2453 *item
= isc_mempool_get(msg
->rdspool
);
2455 return (ISC_R_NOMEMORY
);
2457 dns_rdataset_init(*item
);
2459 return (ISC_R_SUCCESS
);
2463 dns_message_gettemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2464 REQUIRE(DNS_MESSAGE_VALID(msg
));
2465 REQUIRE(item
!= NULL
&& *item
== NULL
);
2467 *item
= newrdatalist(msg
);
2469 return (ISC_R_NOMEMORY
);
2471 return (ISC_R_SUCCESS
);
2475 dns_message_puttempname(dns_message_t
*msg
, dns_name_t
**item
) {
2476 REQUIRE(DNS_MESSAGE_VALID(msg
));
2477 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2479 if (dns_name_dynamic(*item
))
2480 dns_name_free(*item
, msg
->mctx
);
2481 isc_mempool_put(msg
->namepool
, *item
);
2486 dns_message_puttemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2487 REQUIRE(DNS_MESSAGE_VALID(msg
));
2488 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2490 releaserdata(msg
, *item
);
2495 dns_message_puttemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2496 REQUIRE(DNS_MESSAGE_VALID(msg
));
2497 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2499 REQUIRE(!dns_rdataset_isassociated(*item
));
2500 isc_mempool_put(msg
->rdspool
, *item
);
2505 dns_message_puttemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2506 REQUIRE(DNS_MESSAGE_VALID(msg
));
2507 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2509 releaserdatalist(msg
, *item
);
2514 dns_message_peekheader(isc_buffer_t
*source
, dns_messageid_t
*idp
,
2515 unsigned int *flagsp
)
2518 isc_buffer_t buffer
;
2522 REQUIRE(source
!= NULL
);
2526 isc_buffer_remainingregion(&buffer
, &r
);
2527 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
2528 return (ISC_R_UNEXPECTEDEND
);
2530 id
= isc_buffer_getuint16(&buffer
);
2531 flags
= isc_buffer_getuint16(&buffer
);
2532 flags
&= DNS_MESSAGE_FLAG_MASK
;
2539 return (ISC_R_SUCCESS
);
2543 dns_message_reply(dns_message_t
*msg
, isc_boolean_t want_question_section
) {
2544 unsigned int clear_after
;
2545 isc_result_t result
;
2547 REQUIRE(DNS_MESSAGE_VALID(msg
));
2548 REQUIRE((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0);
2550 if (!msg
->header_ok
)
2551 return (DNS_R_FORMERR
);
2552 if (msg
->opcode
!= dns_opcode_query
&&
2553 msg
->opcode
!= dns_opcode_notify
)
2554 want_question_section
= ISC_FALSE
;
2555 if (msg
->opcode
== dns_opcode_update
)
2556 clear_after
= DNS_SECTION_PREREQUISITE
;
2557 else if (want_question_section
) {
2558 if (!msg
->question_ok
)
2559 return (DNS_R_FORMERR
);
2560 clear_after
= DNS_SECTION_ANSWER
;
2562 clear_after
= DNS_SECTION_QUESTION
;
2563 msg
->from_to_wire
= DNS_MESSAGE_INTENTRENDER
;
2564 msgresetnames(msg
, clear_after
);
2566 msgresetsigs(msg
, ISC_TRUE
);
2567 msginitprivate(msg
);
2569 * We now clear most flags and then set QR, ensuring that the
2570 * reply's flags will be in a reasonable state.
2572 msg
->flags
&= DNS_MESSAGE_REPLYPRESERVE
;
2573 msg
->flags
|= DNS_MESSAGEFLAG_QR
;
2576 * This saves the query TSIG status, if the query was signed, and
2577 * reserves space in the reply for the TSIG.
2579 if (msg
->tsigkey
!= NULL
) {
2580 unsigned int otherlen
= 0;
2581 msg
->querytsigstatus
= msg
->tsigstatus
;
2582 msg
->tsigstatus
= dns_rcode_noerror
;
2583 if (msg
->querytsigstatus
== dns_tsigerror_badtime
)
2585 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, otherlen
);
2586 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2587 if (result
!= ISC_R_SUCCESS
) {
2588 msg
->sig_reserved
= 0;
2592 if (msg
->saved
.base
!= NULL
) {
2593 msg
->query
.base
= msg
->saved
.base
;
2594 msg
->query
.length
= msg
->saved
.length
;
2595 msg
->free_query
= msg
->free_saved
;
2596 msg
->saved
.base
= NULL
;
2597 msg
->saved
.length
= 0;
2598 msg
->free_saved
= 0;
2601 return (ISC_R_SUCCESS
);
2605 dns_message_getopt(dns_message_t
*msg
) {
2608 * Get the OPT record for 'msg'.
2611 REQUIRE(DNS_MESSAGE_VALID(msg
));
2617 dns_message_setopt(dns_message_t
*msg
, dns_rdataset_t
*opt
) {
2618 isc_result_t result
;
2619 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2622 * Set the OPT record for 'msg'.
2626 * The space required for an OPT record is:
2628 * 1 byte for the name
2629 * 2 bytes for the type
2630 * 2 bytes for the class
2631 * 4 bytes for the ttl
2632 * 2 bytes for the rdata length
2633 * ---------------------------------
2636 * plus the length of the rdata.
2639 REQUIRE(DNS_MESSAGE_VALID(msg
));
2640 REQUIRE(opt
->type
== dns_rdatatype_opt
);
2641 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2642 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2646 result
= dns_rdataset_first(opt
);
2647 if (result
!= ISC_R_SUCCESS
)
2649 dns_rdataset_current(opt
, &rdata
);
2650 msg
->opt_reserved
= 11 + rdata
.length
;
2651 result
= dns_message_renderreserve(msg
, msg
->opt_reserved
);
2652 if (result
!= ISC_R_SUCCESS
) {
2653 msg
->opt_reserved
= 0;
2659 return (ISC_R_SUCCESS
);
2662 dns_rdataset_disassociate(opt
);
2663 dns_message_puttemprdataset(msg
, &opt
);
2668 dns_message_gettsig(dns_message_t
*msg
, dns_name_t
**owner
) {
2671 * Get the TSIG record and owner for 'msg'.
2674 REQUIRE(DNS_MESSAGE_VALID(msg
));
2675 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2678 *owner
= msg
->tsigname
;
2683 dns_message_settsigkey(dns_message_t
*msg
, dns_tsigkey_t
*key
) {
2684 isc_result_t result
;
2687 * Set the TSIG key for 'msg'
2690 REQUIRE(DNS_MESSAGE_VALID(msg
));
2691 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2693 if (key
== NULL
&& msg
->tsigkey
!= NULL
) {
2694 if (msg
->sig_reserved
!= 0) {
2695 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2696 msg
->sig_reserved
= 0;
2698 dns_tsigkey_detach(&msg
->tsigkey
);
2701 REQUIRE(msg
->tsigkey
== NULL
&& msg
->sig0key
== NULL
);
2702 dns_tsigkey_attach(key
, &msg
->tsigkey
);
2703 if (msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
) {
2704 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, 0);
2705 result
= dns_message_renderreserve(msg
,
2707 if (result
!= ISC_R_SUCCESS
) {
2708 dns_tsigkey_detach(&msg
->tsigkey
);
2709 msg
->sig_reserved
= 0;
2714 return (ISC_R_SUCCESS
);
2718 dns_message_gettsigkey(dns_message_t
*msg
) {
2721 * Get the TSIG key for 'msg'
2724 REQUIRE(DNS_MESSAGE_VALID(msg
));
2726 return (msg
->tsigkey
);
2730 dns_message_setquerytsig(dns_message_t
*msg
, isc_buffer_t
*querytsig
) {
2731 dns_rdata_t
*rdata
= NULL
;
2732 dns_rdatalist_t
*list
= NULL
;
2733 dns_rdataset_t
*set
= NULL
;
2734 isc_buffer_t
*buf
= NULL
;
2736 isc_result_t result
;
2738 REQUIRE(DNS_MESSAGE_VALID(msg
));
2739 REQUIRE(msg
->querytsig
== NULL
);
2741 if (querytsig
== NULL
)
2742 return (ISC_R_SUCCESS
);
2744 result
= dns_message_gettemprdata(msg
, &rdata
);
2745 if (result
!= ISC_R_SUCCESS
)
2748 result
= dns_message_gettemprdatalist(msg
, &list
);
2749 if (result
!= ISC_R_SUCCESS
)
2751 result
= dns_message_gettemprdataset(msg
, &set
);
2752 if (result
!= ISC_R_SUCCESS
)
2755 isc_buffer_usedregion(querytsig
, &r
);
2756 result
= isc_buffer_allocate(msg
->mctx
, &buf
, r
.length
);
2757 if (result
!= ISC_R_SUCCESS
)
2759 isc_buffer_putmem(buf
, r
.base
, r
.length
);
2760 isc_buffer_usedregion(buf
, &r
);
2761 dns_rdata_init(rdata
);
2762 dns_rdata_fromregion(rdata
, dns_rdataclass_any
, dns_rdatatype_tsig
, &r
);
2763 dns_message_takebuffer(msg
, &buf
);
2764 ISC_LIST_INIT(list
->rdata
);
2765 ISC_LIST_APPEND(list
->rdata
, rdata
, link
);
2766 result
= dns_rdatalist_tordataset(list
, set
);
2767 if (result
!= ISC_R_SUCCESS
)
2770 msg
->querytsig
= set
;
2776 dns_message_puttemprdata(msg
, &rdata
);
2778 dns_message_puttemprdatalist(msg
, &list
);
2780 dns_message_puttemprdataset(msg
, &set
);
2781 return (ISC_R_NOMEMORY
);
2785 dns_message_getquerytsig(dns_message_t
*msg
, isc_mem_t
*mctx
,
2786 isc_buffer_t
**querytsig
) {
2787 isc_result_t result
;
2788 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2791 REQUIRE(DNS_MESSAGE_VALID(msg
));
2792 REQUIRE(mctx
!= NULL
);
2793 REQUIRE(querytsig
!= NULL
&& *querytsig
== NULL
);
2795 if (msg
->tsig
== NULL
)
2796 return (ISC_R_SUCCESS
);
2798 result
= dns_rdataset_first(msg
->tsig
);
2799 if (result
!= ISC_R_SUCCESS
)
2801 dns_rdataset_current(msg
->tsig
, &rdata
);
2802 dns_rdata_toregion(&rdata
, &r
);
2804 result
= isc_buffer_allocate(mctx
, querytsig
, r
.length
);
2805 if (result
!= ISC_R_SUCCESS
)
2807 isc_buffer_putmem(*querytsig
, r
.base
, r
.length
);
2808 return (ISC_R_SUCCESS
);
2812 dns_message_getsig0(dns_message_t
*msg
, dns_name_t
**owner
) {
2815 * Get the SIG(0) record for 'msg'.
2818 REQUIRE(DNS_MESSAGE_VALID(msg
));
2819 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2821 if (msg
->sig0
!= NULL
&& owner
!= NULL
) {
2822 /* If dns_message_getsig0 is called on a rendered message
2823 * after the SIG(0) has been applied, we need to return the
2824 * root name, not NULL.
2826 if (msg
->sig0name
== NULL
)
2827 *owner
= dns_rootname
;
2829 *owner
= msg
->sig0name
;
2835 dns_message_setsig0key(dns_message_t
*msg
, dst_key_t
*key
) {
2838 isc_result_t result
;
2841 * Set the SIG(0) key for 'msg'
2845 * The space required for an SIG(0) record is:
2847 * 1 byte for the name
2848 * 2 bytes for the type
2849 * 2 bytes for the class
2850 * 4 bytes for the ttl
2851 * 2 bytes for the type covered
2852 * 1 byte for the algorithm
2853 * 1 bytes for the labels
2854 * 4 bytes for the original ttl
2855 * 4 bytes for the signature expiration
2856 * 4 bytes for the signature inception
2857 * 2 bytes for the key tag
2858 * n bytes for the signer's name
2859 * x bytes for the signature
2860 * ---------------------------------
2863 REQUIRE(DNS_MESSAGE_VALID(msg
));
2864 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2865 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2868 REQUIRE(msg
->sig0key
== NULL
&& msg
->tsigkey
== NULL
);
2869 dns_name_toregion(dst_key_name(key
), &r
);
2870 result
= dst_key_sigsize(key
, &x
);
2871 if (result
!= ISC_R_SUCCESS
) {
2872 msg
->sig_reserved
= 0;
2875 msg
->sig_reserved
= 27 + r
.length
+ x
;
2876 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2877 if (result
!= ISC_R_SUCCESS
) {
2878 msg
->sig_reserved
= 0;
2883 return (ISC_R_SUCCESS
);
2887 dns_message_getsig0key(dns_message_t
*msg
) {
2890 * Get the SIG(0) key for 'msg'
2893 REQUIRE(DNS_MESSAGE_VALID(msg
));
2895 return (msg
->sig0key
);
2899 dns_message_takebuffer(dns_message_t
*msg
, isc_buffer_t
**buffer
) {
2900 REQUIRE(DNS_MESSAGE_VALID(msg
));
2901 REQUIRE(buffer
!= NULL
);
2902 REQUIRE(ISC_BUFFER_VALID(*buffer
));
2904 ISC_LIST_APPEND(msg
->cleanup
, *buffer
, link
);
2909 dns_message_signer(dns_message_t
*msg
, dns_name_t
*signer
) {
2910 isc_result_t result
= ISC_R_SUCCESS
;
2911 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2913 REQUIRE(DNS_MESSAGE_VALID(msg
));
2914 REQUIRE(signer
!= NULL
);
2915 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
2917 if (msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2918 return (ISC_R_NOTFOUND
);
2920 if (msg
->verify_attempted
== 0)
2921 return (DNS_R_NOTVERIFIEDYET
);
2923 if (!dns_name_hasbuffer(signer
)) {
2924 isc_buffer_t
*dynbuf
= NULL
;
2925 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, 512);
2926 if (result
!= ISC_R_SUCCESS
)
2928 dns_name_setbuffer(signer
, dynbuf
);
2929 dns_message_takebuffer(msg
, &dynbuf
);
2932 if (msg
->sig0
!= NULL
) {
2933 dns_rdata_sig_t sig
;
2935 result
= dns_rdataset_first(msg
->sig0
);
2936 INSIST(result
== ISC_R_SUCCESS
);
2937 dns_rdataset_current(msg
->sig0
, &rdata
);
2939 result
= dns_rdata_tostruct(&rdata
, &sig
, NULL
);
2940 if (result
!= ISC_R_SUCCESS
)
2943 if (msg
->verified_sig
&& msg
->sig0status
== dns_rcode_noerror
)
2944 result
= ISC_R_SUCCESS
;
2946 result
= DNS_R_SIGINVALID
;
2947 dns_name_clone(&sig
.signer
, signer
);
2948 dns_rdata_freestruct(&sig
);
2950 dns_name_t
*identity
;
2951 dns_rdata_any_tsig_t tsig
;
2953 result
= dns_rdataset_first(msg
->tsig
);
2954 INSIST(result
== ISC_R_SUCCESS
);
2955 dns_rdataset_current(msg
->tsig
, &rdata
);
2957 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
2958 INSIST(result
== ISC_R_SUCCESS
);
2959 if (msg
->tsigstatus
!= dns_rcode_noerror
)
2960 result
= DNS_R_TSIGVERIFYFAILURE
;
2961 else if (tsig
.error
!= dns_rcode_noerror
)
2962 result
= DNS_R_TSIGERRORSET
;
2964 result
= ISC_R_SUCCESS
;
2965 dns_rdata_freestruct(&tsig
);
2967 if (msg
->tsigkey
== NULL
) {
2969 * If msg->tsigstatus & tsig.error are both
2970 * dns_rcode_noerror, the message must have been
2971 * verified, which means msg->tsigkey will be
2974 INSIST(result
!= ISC_R_SUCCESS
);
2976 identity
= dns_tsigkey_identity(msg
->tsigkey
);
2977 if (identity
== NULL
) {
2978 if (result
== ISC_R_SUCCESS
)
2979 result
= DNS_R_NOIDENTITY
;
2980 identity
= &msg
->tsigkey
->name
;
2982 dns_name_clone(identity
, signer
);
2990 dns_message_resetsig(dns_message_t
*msg
) {
2991 REQUIRE(DNS_MESSAGE_VALID(msg
));
2992 msg
->verified_sig
= 0;
2993 msg
->verify_attempted
= 0;
2994 msg
->tsigstatus
= dns_rcode_noerror
;
2995 msg
->sig0status
= dns_rcode_noerror
;
2996 msg
->timeadjust
= 0;
2997 if (msg
->tsigkey
!= NULL
) {
2998 dns_tsigkey_detach(&msg
->tsigkey
);
2999 msg
->tsigkey
= NULL
;
3004 dns_message_rechecksig(dns_message_t
*msg
, dns_view_t
*view
) {
3005 dns_message_resetsig(msg
);
3006 return (dns_message_checksig(msg
, view
));
3009 #ifdef SKAN_MSG_DEBUG
3011 dns_message_dumpsig(dns_message_t
*msg
, char *txt1
) {
3012 dns_rdata_t querytsigrdata
= DNS_RDATA_INIT
;
3013 dns_rdata_any_tsig_t querytsig
;
3014 isc_result_t result
;
3016 if (msg
->tsig
!= NULL
) {
3017 result
= dns_rdataset_first(msg
->tsig
);
3018 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3019 dns_rdataset_current(msg
->tsig
, &querytsigrdata
);
3020 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
3021 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3022 hexdump(txt1
, "TSIG", querytsig
.signature
,
3026 if (msg
->querytsig
!= NULL
) {
3027 result
= dns_rdataset_first(msg
->querytsig
);
3028 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3029 dns_rdataset_current(msg
->querytsig
, &querytsigrdata
);
3030 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
3031 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3032 hexdump(txt1
, "QUERYTSIG", querytsig
.signature
,
3039 dns_message_checksig(dns_message_t
*msg
, dns_view_t
*view
) {
3040 isc_buffer_t b
, msgb
;
3042 REQUIRE(DNS_MESSAGE_VALID(msg
));
3044 if (msg
->tsigkey
== NULL
&& msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
3045 return (ISC_R_SUCCESS
);
3047 INSIST(msg
->saved
.base
!= NULL
);
3048 isc_buffer_init(&msgb
, msg
->saved
.base
, msg
->saved
.length
);
3049 isc_buffer_add(&msgb
, msg
->saved
.length
);
3050 if (msg
->tsigkey
!= NULL
|| msg
->tsig
!= NULL
) {
3051 #ifdef SKAN_MSG_DEBUG
3052 dns_message_dumpsig(msg
, "dns_message_checksig#1");
3055 return (dns_view_checksig(view
, &msgb
, msg
));
3057 return (dns_tsig_verify(&msgb
, msg
, NULL
, NULL
));
3059 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3060 dns_rdata_sig_t sig
;
3061 dns_rdataset_t keyset
;
3062 isc_result_t result
;
3064 result
= dns_rdataset_first(msg
->sig0
);
3065 INSIST(result
== ISC_R_SUCCESS
);
3066 dns_rdataset_current(msg
->sig0
, &rdata
);
3069 * This can occur when the message is a dynamic update, since
3070 * the rdata length checking is relaxed. This should not
3071 * happen in a well-formed message, since the SIG(0) is only
3072 * looked for in the additional section, and the dynamic update
3073 * meta-records are in the prerequisite and update sections.
3075 if (rdata
.length
== 0)
3076 return (ISC_R_UNEXPECTEDEND
);
3078 result
= dns_rdata_tostruct(&rdata
, &sig
, msg
->mctx
);
3079 if (result
!= ISC_R_SUCCESS
)
3082 dns_rdataset_init(&keyset
);
3084 return (DNS_R_KEYUNAUTHORIZED
);
3085 result
= dns_view_simplefind(view
, &sig
.signer
,
3086 dns_rdatatype_key
/* SIG(0) */,
3087 0, 0, ISC_FALSE
, &keyset
, NULL
);
3089 if (result
!= ISC_R_SUCCESS
) {
3090 /* XXXBEW Should possibly create a fetch here */
3091 result
= DNS_R_KEYUNAUTHORIZED
;
3093 } else if (keyset
.trust
< dns_trust_secure
) {
3094 /* XXXBEW Should call a validator here */
3095 result
= DNS_R_KEYUNAUTHORIZED
;
3098 result
= dns_rdataset_first(&keyset
);
3099 INSIST(result
== ISC_R_SUCCESS
);
3101 result
== ISC_R_SUCCESS
;
3102 result
= dns_rdataset_next(&keyset
))
3104 dst_key_t
*key
= NULL
;
3106 dns_rdata_reset(&rdata
);
3107 dns_rdataset_current(&keyset
, &rdata
);
3108 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
3109 isc_buffer_add(&b
, rdata
.length
);
3111 result
= dst_key_fromdns(&sig
.signer
, rdata
.rdclass
,
3112 &b
, view
->mctx
, &key
);
3113 if (result
!= ISC_R_SUCCESS
)
3115 if (dst_key_alg(key
) != sig
.algorithm
||
3116 dst_key_id(key
) != sig
.keyid
||
3117 !(dst_key_proto(key
) == DNS_KEYPROTO_DNSSEC
||
3118 dst_key_proto(key
) == DNS_KEYPROTO_ANY
))
3123 result
= dns_dnssec_verifymessage(&msgb
, msg
, key
);
3125 if (result
== ISC_R_SUCCESS
)
3128 if (result
== ISC_R_NOMORE
)
3129 result
= DNS_R_KEYUNAUTHORIZED
;
3132 if (dns_rdataset_isassociated(&keyset
))
3133 dns_rdataset_disassociate(&keyset
);
3134 dns_rdata_freestruct(&sig
);
3140 dns_message_sectiontotext(dns_message_t
*msg
, dns_section_t section
,
3141 const dns_master_style_t
*style
,
3142 dns_messagetextflag_t flags
,
3143 isc_buffer_t
*target
) {
3144 dns_name_t
*name
, empty_name
;
3145 dns_rdataset_t
*rdataset
;
3146 isc_result_t result
;
3147 isc_boolean_t seensoa
= ISC_FALSE
;
3149 REQUIRE(DNS_MESSAGE_VALID(msg
));
3150 REQUIRE(target
!= NULL
);
3151 REQUIRE(VALID_SECTION(section
));
3153 if (ISC_LIST_EMPTY(msg
->sections
[section
]))
3154 return (ISC_R_SUCCESS
);
3156 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0) {
3157 ADD_STRING(target
, ";; ");
3158 if (msg
->opcode
!= dns_opcode_update
) {
3159 ADD_STRING(target
, sectiontext
[section
]);
3161 ADD_STRING(target
, updsectiontext
[section
]);
3163 ADD_STRING(target
, " SECTION:\n");
3166 dns_name_init(&empty_name
, NULL
);
3167 result
= dns_message_firstname(msg
, section
);
3168 if (result
!= ISC_R_SUCCESS
) {
3173 dns_message_currentname(msg
, section
, &name
);
3174 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3176 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3177 if (section
== DNS_SECTION_ANSWER
&&
3178 rdataset
->type
== dns_rdatatype_soa
) {
3179 if ((flags
& DNS_MESSAGETEXTFLAG_OMITSOA
) != 0)
3182 (flags
& DNS_MESSAGETEXTFLAG_ONESOA
) != 0)
3186 if (section
== DNS_SECTION_QUESTION
) {
3187 ADD_STRING(target
, ";");
3188 result
= dns_master_questiontotext(name
,
3193 result
= dns_master_rdatasettotext(name
,
3198 if (result
!= ISC_R_SUCCESS
)
3201 result
= dns_message_nextname(msg
, section
);
3202 } while (result
== ISC_R_SUCCESS
);
3203 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3204 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3205 ADD_STRING(target
, "\n");
3206 if (result
== ISC_R_NOMORE
)
3207 result
= ISC_R_SUCCESS
;
3212 render_ecs(isc_buffer_t
*optbuf
, isc_buffer_t
*target
) {
3214 char addr
[16], addr_text
[64];
3215 isc_uint16_t family
;
3216 isc_uint8_t addrlen
, addrbytes
, scopelen
;
3218 INSIST(isc_buffer_remaininglength(optbuf
) >= 4);
3219 family
= isc_buffer_getuint16(optbuf
);
3220 addrlen
= isc_buffer_getuint8(optbuf
);
3221 scopelen
= isc_buffer_getuint8(optbuf
);
3223 addrbytes
= (addrlen
+ 7) / 8;
3224 INSIST(isc_buffer_remaininglength(optbuf
) >= addrbytes
);
3226 memset(addr
, 0, sizeof(addr
));
3227 for (i
= 0; i
< addrbytes
; i
++)
3228 addr
[i
] = isc_buffer_getuint8(optbuf
);
3231 inet_ntop(AF_INET
, addr
, addr_text
, sizeof(addr_text
));
3232 else if (family
== 2)
3233 inet_ntop(AF_INET6
, addr
, addr_text
, sizeof(addr_text
));
3235 snprintf(addr_text
, sizeof(addr_text
),
3236 "Unsupported family %u", family
);
3237 ADD_STRING(target
, addr_text
);
3238 return (ISC_R_SUCCESS
);
3241 ADD_STRING(target
, addr_text
);
3242 snprintf(addr_text
, sizeof(addr_text
), "/%d/%d", addrlen
, scopelen
);
3243 ADD_STRING(target
, addr_text
);
3244 return (ISC_R_SUCCESS
);
3248 dns_message_pseudosectiontotext(dns_message_t
*msg
,
3249 dns_pseudosection_t section
,
3250 const dns_master_style_t
*style
,
3251 dns_messagetextflag_t flags
,
3252 isc_buffer_t
*target
)
3254 dns_rdataset_t
*ps
= NULL
;
3255 dns_name_t
*name
= NULL
;
3256 isc_result_t result
;
3257 char buf
[sizeof("1234567890")];
3260 isc_buffer_t optbuf
;
3261 isc_uint16_t optcode
, optlen
;
3262 unsigned char *optdata
;
3264 REQUIRE(DNS_MESSAGE_VALID(msg
));
3265 REQUIRE(target
!= NULL
);
3266 REQUIRE(VALID_PSEUDOSECTION(section
));
3269 case DNS_PSEUDOSECTION_OPT
:
3270 ps
= dns_message_getopt(msg
);
3272 return (ISC_R_SUCCESS
);
3273 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3274 ADD_STRING(target
, ";; OPT PSEUDOSECTION:\n");
3275 ADD_STRING(target
, "; EDNS: version: ");
3276 snprintf(buf
, sizeof(buf
), "%u",
3277 (unsigned int)((ps
->ttl
& 0x00ff0000) >> 16));
3278 ADD_STRING(target
, buf
);
3279 ADD_STRING(target
, ", flags:");
3280 if ((ps
->ttl
& DNS_MESSAGEEXTFLAG_DO
) != 0)
3281 ADD_STRING(target
, " do");
3282 mbz
= ps
->ttl
& 0xffff;
3283 mbz
&= ~DNS_MESSAGEEXTFLAG_DO
; /* Known Flags. */
3285 ADD_STRING(target
, "; MBZ: ");
3286 snprintf(buf
, sizeof(buf
), "%.4x ", mbz
);
3287 ADD_STRING(target
, buf
);
3288 ADD_STRING(target
, ", udp: ");
3290 ADD_STRING(target
, "; udp: ");
3291 snprintf(buf
, sizeof(buf
), "%u\n", (unsigned int)ps
->rdclass
);
3292 ADD_STRING(target
, buf
);
3294 result
= dns_rdataset_first(ps
);
3295 if (result
!= ISC_R_SUCCESS
)
3296 return (ISC_R_SUCCESS
);
3298 /* Print EDNS info, if any */
3299 dns_rdata_init(&rdata
);
3300 dns_rdataset_current(ps
, &rdata
);
3302 isc_buffer_init(&optbuf
, rdata
.data
, rdata
.length
);
3303 isc_buffer_add(&optbuf
, rdata
.length
);
3304 while (isc_buffer_remaininglength(&optbuf
) != 0) {
3305 INSIST(isc_buffer_remaininglength(&optbuf
) >= 4U);
3306 optcode
= isc_buffer_getuint16(&optbuf
);
3307 optlen
= isc_buffer_getuint16(&optbuf
);
3308 INSIST(isc_buffer_remaininglength(&optbuf
) >= optlen
);
3310 if (optcode
== DNS_OPT_NSID
) {
3311 ADD_STRING(target
, "; NSID");
3312 } else if (optcode
== DNS_OPT_SIT
) {
3313 ADD_STRING(target
, "; SIT");
3314 } else if (optcode
== DNS_OPT_CLIENT_SUBNET
) {
3315 ADD_STRING(target
, "; CLIENT-SUBNET: ");
3316 render_ecs(&optbuf
, target
);
3317 ADD_STRING(target
, "\n");
3319 } else if (optcode
== DNS_OPT_EXPIRE
) {
3322 secs
= isc_buffer_getuint32(&optbuf
);
3323 ADD_STRING(target
, "; EXPIRE: ");
3324 snprintf(buf
, sizeof(buf
), "%u", secs
);
3325 ADD_STRING(target
, buf
);
3326 ADD_STRING(target
, " (");
3327 dns_ttl_totext(secs
, ISC_TRUE
, target
);
3328 ADD_STRING(target
, ")\n");
3331 ADD_STRING(target
, "; EXPIRE");
3333 ADD_STRING(target
, "; OPT=");
3334 snprintf(buf
, sizeof(buf
), "%u", optcode
);
3335 ADD_STRING(target
, buf
);
3340 ADD_STRING(target
, ": ");
3342 optdata
= isc_buffer_current(&optbuf
);
3343 for (i
= 0; i
< optlen
; i
++) {
3353 snprintf(buf
, sizeof(buf
), "%02x%s",
3355 ADD_STRING(target
, buf
);
3358 isc_buffer_forward(&optbuf
, optlen
);
3360 if (optcode
== DNS_OPT_SIT
) {
3362 ADD_STRING(target
, " (good)");
3364 ADD_STRING(target
, " (bad)");
3365 ADD_STRING(target
, "\n");
3370 * For non-SIT options, add a printable
3373 ADD_STRING(target
, "(\"");
3374 if (isc_buffer_availablelength(target
) < optlen
)
3375 return (ISC_R_NOSPACE
);
3376 for (i
= 0; i
< optlen
; i
++) {
3377 if (isprint(optdata
[i
]))
3378 isc_buffer_putmem(target
,
3382 isc_buffer_putstr(target
, ".");
3384 ADD_STRING(target
, "\")");
3386 ADD_STRING(target
, "\n");
3388 return (ISC_R_SUCCESS
);
3389 case DNS_PSEUDOSECTION_TSIG
:
3390 ps
= dns_message_gettsig(msg
, &name
);
3392 return (ISC_R_SUCCESS
);
3393 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3394 ADD_STRING(target
, ";; TSIG PSEUDOSECTION:\n");
3395 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3396 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3397 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3398 ADD_STRING(target
, "\n");
3400 case DNS_PSEUDOSECTION_SIG0
:
3401 ps
= dns_message_getsig0(msg
, &name
);
3403 return (ISC_R_SUCCESS
);
3404 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3405 ADD_STRING(target
, ";; SIG0 PSEUDOSECTION:\n");
3406 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3407 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3408 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3409 ADD_STRING(target
, "\n");
3412 return (ISC_R_UNEXPECTED
);
3416 dns_message_totext(dns_message_t
*msg
, const dns_master_style_t
*style
,
3417 dns_messagetextflag_t flags
, isc_buffer_t
*target
) {
3418 char buf
[sizeof("1234567890")];
3419 isc_result_t result
;
3421 REQUIRE(DNS_MESSAGE_VALID(msg
));
3422 REQUIRE(target
!= NULL
);
3424 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0) {
3425 ADD_STRING(target
, ";; ->>HEADER<<- opcode: ");
3426 ADD_STRING(target
, opcodetext
[msg
->opcode
]);
3427 ADD_STRING(target
, ", status: ");
3428 if (msg
->rcode
< (sizeof(rcodetext
)/sizeof(rcodetext
[0]))) {
3429 ADD_STRING(target
, rcodetext
[msg
->rcode
]);
3431 snprintf(buf
, sizeof(buf
), "%4u", msg
->rcode
);
3432 ADD_STRING(target
, buf
);
3434 ADD_STRING(target
, ", id: ");
3435 snprintf(buf
, sizeof(buf
), "%6u", msg
->id
);
3436 ADD_STRING(target
, buf
);
3437 ADD_STRING(target
, "\n;; flags:");
3438 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) != 0)
3439 ADD_STRING(target
, " qr");
3440 if ((msg
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3441 ADD_STRING(target
, " aa");
3442 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
3443 ADD_STRING(target
, " tc");
3444 if ((msg
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3445 ADD_STRING(target
, " rd");
3446 if ((msg
->flags
& DNS_MESSAGEFLAG_RA
) != 0)
3447 ADD_STRING(target
, " ra");
3448 if ((msg
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
3449 ADD_STRING(target
, " ad");
3450 if ((msg
->flags
& DNS_MESSAGEFLAG_CD
) != 0)
3451 ADD_STRING(target
, " cd");
3453 * The final unnamed flag must be zero.
3455 if ((msg
->flags
& 0x0040U
) != 0)
3456 ADD_STRING(target
, "; MBZ: 0x4");
3457 if (msg
->opcode
!= dns_opcode_update
) {
3458 ADD_STRING(target
, "; QUESTION: ");
3460 ADD_STRING(target
, "; ZONE: ");
3462 snprintf(buf
, sizeof(buf
), "%1u",
3463 msg
->counts
[DNS_SECTION_QUESTION
]);
3464 ADD_STRING(target
, buf
);
3465 if (msg
->opcode
!= dns_opcode_update
) {
3466 ADD_STRING(target
, ", ANSWER: ");
3468 ADD_STRING(target
, ", PREREQ: ");
3470 snprintf(buf
, sizeof(buf
), "%1u",
3471 msg
->counts
[DNS_SECTION_ANSWER
]);
3472 ADD_STRING(target
, buf
);
3473 if (msg
->opcode
!= dns_opcode_update
) {
3474 ADD_STRING(target
, ", AUTHORITY: ");
3476 ADD_STRING(target
, ", UPDATE: ");
3478 snprintf(buf
, sizeof(buf
), "%1u",
3479 msg
->counts
[DNS_SECTION_AUTHORITY
]);
3480 ADD_STRING(target
, buf
);
3481 ADD_STRING(target
, ", ADDITIONAL: ");
3482 snprintf(buf
, sizeof(buf
), "%1u",
3483 msg
->counts
[DNS_SECTION_ADDITIONAL
]);
3484 ADD_STRING(target
, buf
);
3485 ADD_STRING(target
, "\n");
3487 result
= dns_message_pseudosectiontotext(msg
,
3488 DNS_PSEUDOSECTION_OPT
,
3489 style
, flags
, target
);
3490 if (result
!= ISC_R_SUCCESS
)
3493 result
= dns_message_sectiontotext(msg
, DNS_SECTION_QUESTION
,
3494 style
, flags
, target
);
3495 if (result
!= ISC_R_SUCCESS
)
3497 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ANSWER
,
3498 style
, flags
, target
);
3499 if (result
!= ISC_R_SUCCESS
)
3501 result
= dns_message_sectiontotext(msg
, DNS_SECTION_AUTHORITY
,
3502 style
, flags
, target
);
3503 if (result
!= ISC_R_SUCCESS
)
3505 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ADDITIONAL
,
3506 style
, flags
, target
);
3507 if (result
!= ISC_R_SUCCESS
)
3510 result
= dns_message_pseudosectiontotext(msg
,
3511 DNS_PSEUDOSECTION_TSIG
,
3512 style
, flags
, target
);
3513 if (result
!= ISC_R_SUCCESS
)
3516 result
= dns_message_pseudosectiontotext(msg
,
3517 DNS_PSEUDOSECTION_SIG0
,
3518 style
, flags
, target
);
3519 if (result
!= ISC_R_SUCCESS
)
3522 return (ISC_R_SUCCESS
);
3526 dns_message_getrawmessage(dns_message_t
*msg
) {
3527 REQUIRE(DNS_MESSAGE_VALID(msg
));
3528 return (&msg
->saved
);
3532 dns_message_setsortorder(dns_message_t
*msg
, dns_rdatasetorderfunc_t order
,
3533 const void *order_arg
)
3535 REQUIRE(DNS_MESSAGE_VALID(msg
));
3537 msg
->order_arg
= order_arg
;
3541 dns_message_settimeadjust(dns_message_t
*msg
, int timeadjust
) {
3542 REQUIRE(DNS_MESSAGE_VALID(msg
));
3543 msg
->timeadjust
= timeadjust
;
3547 dns_message_gettimeadjust(dns_message_t
*msg
) {
3548 REQUIRE(DNS_MESSAGE_VALID(msg
));
3549 return (msg
->timeadjust
);
3553 dns_opcode_totext(dns_opcode_t opcode
, isc_buffer_t
*target
) {
3555 REQUIRE(opcode
< 16);
3557 if (isc_buffer_availablelength(target
) < strlen(opcodetext
[opcode
]))
3558 return (ISC_R_NOSPACE
);
3559 isc_buffer_putstr(target
, opcodetext
[opcode
]);
3560 return (ISC_R_SUCCESS
);
3564 dns_message_logpacket(dns_message_t
*message
, const char *description
,
3565 isc_logcategory_t
*category
, isc_logmodule_t
*module
,
3566 int level
, isc_mem_t
*mctx
)
3568 dns_message_logfmtpacket(message
, description
, category
, module
,
3569 &dns_master_style_debug
, level
, mctx
);
3573 dns_message_logfmtpacket(dns_message_t
*message
, const char *description
,
3574 isc_logcategory_t
*category
, isc_logmodule_t
*module
,
3575 const dns_master_style_t
*style
, int level
,
3578 isc_buffer_t buffer
;
3581 isc_result_t result
;
3583 if (! isc_log_wouldlog(dns_lctx
, level
))
3587 * Note that these are multiline debug messages. We want a newline
3588 * to appear in the log after each message.
3592 buf
= isc_mem_get(mctx
, len
);
3595 isc_buffer_init(&buffer
, buf
, len
);
3596 result
= dns_message_totext(message
, style
, 0, &buffer
);
3597 if (result
== ISC_R_NOSPACE
) {
3598 isc_mem_put(mctx
, buf
, len
);
3600 } else if (result
== ISC_R_SUCCESS
)
3601 isc_log_write(dns_lctx
, category
, module
, level
,
3602 "%s%.*s", description
,
3603 (int)isc_buffer_usedlength(&buffer
),
3605 } while (result
== ISC_R_NOSPACE
);
3608 isc_mem_put(mctx
, buf
, len
);
3612 dns_message_buildopt(dns_message_t
*message
, dns_rdataset_t
**rdatasetp
,
3613 unsigned int version
, isc_uint16_t udpsize
,
3614 unsigned int flags
, dns_ednsopt_t
*ednsopts
, size_t count
)
3616 dns_rdataset_t
*rdataset
= NULL
;
3617 dns_rdatalist_t
*rdatalist
= NULL
;
3618 dns_rdata_t
*rdata
= NULL
;
3619 isc_result_t result
;
3620 unsigned int len
= 0, i
;
3622 REQUIRE(DNS_MESSAGE_VALID(message
));
3623 REQUIRE(rdatasetp
!= NULL
&& *rdatasetp
== NULL
);
3625 result
= dns_message_gettemprdatalist(message
, &rdatalist
);
3626 if (result
!= ISC_R_SUCCESS
)
3628 result
= dns_message_gettemprdata(message
, &rdata
);
3629 if (result
!= ISC_R_SUCCESS
)
3631 result
= dns_message_gettemprdataset(message
, &rdataset
);
3632 if (result
!= ISC_R_SUCCESS
)
3635 rdatalist
->type
= dns_rdatatype_opt
;
3636 rdatalist
->covers
= 0;
3639 * Set Maximum UDP buffer size.
3641 rdatalist
->rdclass
= udpsize
;
3644 * Set EXTENDED-RCODE and Z to 0.
3646 rdatalist
->ttl
= (version
<< 16);
3647 rdatalist
->ttl
|= (flags
& 0xffff);
3650 * Set EDNS options if applicable
3653 isc_buffer_t
*buf
= NULL
;
3654 for (i
= 0; i
< count
; i
++)
3655 len
+= ednsopts
[i
].length
+ 4;
3657 if (len
> 0xffffU
) {
3658 result
= ISC_R_NOSPACE
;
3662 result
= isc_buffer_allocate(message
->mctx
, &buf
, len
);
3663 if (result
!= ISC_R_SUCCESS
)
3666 for (i
= 0; i
< count
; i
++) {
3667 isc_buffer_putuint16(buf
, ednsopts
[i
].code
);
3668 isc_buffer_putuint16(buf
, ednsopts
[i
].length
);
3669 isc_buffer_putmem(buf
, ednsopts
[i
].value
,
3670 ednsopts
[i
].length
);
3672 rdata
->data
= isc_buffer_base(buf
);
3673 rdata
->length
= len
;
3674 dns_message_takebuffer(message
, &buf
);
3680 rdata
->rdclass
= rdatalist
->rdclass
;
3681 rdata
->type
= rdatalist
->type
;
3684 ISC_LIST_INIT(rdatalist
->rdata
);
3685 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
3686 result
= dns_rdatalist_tordataset(rdatalist
, rdataset
);
3687 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3689 *rdatasetp
= rdataset
;
3690 return (ISC_R_SUCCESS
);
3694 dns_message_puttemprdata(message
, &rdata
);
3695 if (rdataset
!= NULL
)
3696 dns_message_puttemprdataset(message
, &rdataset
);
3697 if (rdatalist
!= NULL
)
3698 dns_message_puttemprdatalist(message
, &rdatalist
);