1 /* $NetBSD: message.c,v 1.1.1.3 2009/12/26 22:24:41 christos Exp $ */
4 * Copyright (C) 2004-2009 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.
20 /* Id: message.c,v 1.249 2009/11/24 03:20:02 marka Exp */
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>
53 hexdump(const char *msg
, const char *msg2
, void *base
, size_t len
) {
60 printf("*** %s [%s] (%u bytes @ %p)\n", msg
, msg2
, len
, base
);
65 else if (cnt
% 8 == 0)
67 printf(" %02x %c", *p
, (isprint(*p
) ? *p
: ' '));
80 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
81 #define DNS_MESSAGE_OPCODE_SHIFT 11
82 #define DNS_MESSAGE_RCODE_MASK 0x000fU
83 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
84 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
85 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
86 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
87 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
89 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
90 && ((s) < DNS_SECTION_MAX))
91 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
92 && ((s) < DNS_SECTION_MAX))
93 #define ADD_STRING(b, s) {if (strlen(s) >= \
94 isc_buffer_availablelength(b)) \
95 return(ISC_R_NOSPACE); else \
96 isc_buffer_putstr(b, s);}
97 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
98 && ((s) < DNS_PSEUDOSECTION_MAX))
100 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
103 * This is the size of each individual scratchpad buffer, and the numbers
104 * of various block allocations used within the server.
105 * XXXMLG These should come from a config setting.
107 #define SCRATCHPAD_SIZE 512
109 #define OFFSET_COUNT 4
110 #define RDATA_COUNT 8
111 #define RDATALIST_COUNT 8
112 #define RDATASET_COUNT RDATALIST_COUNT
115 * Text representation of the different items, for message_totext
118 static const char *sectiontext
[] = {
125 static const char *updsectiontext
[] = {
132 static const char *opcodetext
[] = {
151 static const char *rcodetext
[] = {
173 * "helper" type, which consists of a block of some type, and is linkable.
174 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
175 * size, or the allocated elements will not be aligned correctly.
177 struct dns_msgblock
{
179 unsigned int remaining
;
180 ISC_LINK(dns_msgblock_t
) link
;
181 }; /* dynamically sized */
183 static inline dns_msgblock_t
*
184 msgblock_allocate(isc_mem_t
*, unsigned int, unsigned int);
186 #define msgblock_get(block, type) \
187 ((type *)msgblock_internalget(block, sizeof(type)))
190 msgblock_internalget(dns_msgblock_t
*, unsigned int);
193 msgblock_reset(dns_msgblock_t
*);
196 msgblock_free(isc_mem_t
*, dns_msgblock_t
*, unsigned int);
199 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
200 * is free, return NULL.
202 static inline dns_msgblock_t
*
203 msgblock_allocate(isc_mem_t
*mctx
, unsigned int sizeof_type
,
206 dns_msgblock_t
*block
;
209 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* count
);
211 block
= isc_mem_get(mctx
, length
);
215 block
->count
= count
;
216 block
->remaining
= count
;
218 ISC_LINK_INIT(block
, link
);
224 * Return an element from the msgblock. If no more are available, return
228 msgblock_internalget(dns_msgblock_t
*block
, unsigned int sizeof_type
) {
231 if (block
== NULL
|| block
->remaining
== 0)
236 ptr
= (((unsigned char *)block
)
237 + sizeof(dns_msgblock_t
)
238 + (sizeof_type
* block
->remaining
));
244 msgblock_reset(dns_msgblock_t
*block
) {
245 block
->remaining
= block
->count
;
249 * Release memory associated with a message block.
252 msgblock_free(isc_mem_t
*mctx
, dns_msgblock_t
*block
, unsigned int sizeof_type
)
256 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* block
->count
);
258 isc_mem_put(mctx
, block
, length
);
262 * Allocate a new dynamic buffer, and attach it to this message as the
263 * "current" buffer. (which is always the last on the list, for our
266 static inline isc_result_t
267 newbuffer(dns_message_t
*msg
, unsigned int size
) {
269 isc_buffer_t
*dynbuf
;
272 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, size
);
273 if (result
!= ISC_R_SUCCESS
)
274 return (ISC_R_NOMEMORY
);
276 ISC_LIST_APPEND(msg
->scratchpad
, dynbuf
, link
);
277 return (ISC_R_SUCCESS
);
280 static inline isc_buffer_t
*
281 currentbuffer(dns_message_t
*msg
) {
282 isc_buffer_t
*dynbuf
;
284 dynbuf
= ISC_LIST_TAIL(msg
->scratchpad
);
285 INSIST(dynbuf
!= NULL
);
291 releaserdata(dns_message_t
*msg
, dns_rdata_t
*rdata
) {
292 ISC_LIST_PREPEND(msg
->freerdata
, rdata
, link
);
295 static inline dns_rdata_t
*
296 newrdata(dns_message_t
*msg
) {
297 dns_msgblock_t
*msgblock
;
300 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
302 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
306 msgblock
= ISC_LIST_TAIL(msg
->rdatas
);
307 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
309 msgblock
= msgblock_allocate(msg
->mctx
, sizeof(dns_rdata_t
),
311 if (msgblock
== NULL
)
314 ISC_LIST_APPEND(msg
->rdatas
, msgblock
, link
);
316 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
319 dns_rdata_init(rdata
);
324 releaserdatalist(dns_message_t
*msg
, dns_rdatalist_t
*rdatalist
) {
325 ISC_LIST_PREPEND(msg
->freerdatalist
, rdatalist
, link
);
328 static inline dns_rdatalist_t
*
329 newrdatalist(dns_message_t
*msg
) {
330 dns_msgblock_t
*msgblock
;
331 dns_rdatalist_t
*rdatalist
;
333 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
334 if (rdatalist
!= NULL
) {
335 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
339 msgblock
= ISC_LIST_TAIL(msg
->rdatalists
);
340 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
341 if (rdatalist
== NULL
) {
342 msgblock
= msgblock_allocate(msg
->mctx
,
343 sizeof(dns_rdatalist_t
),
345 if (msgblock
== NULL
)
348 ISC_LIST_APPEND(msg
->rdatalists
, msgblock
, link
);
350 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
356 static inline dns_offsets_t
*
357 newoffsets(dns_message_t
*msg
) {
358 dns_msgblock_t
*msgblock
;
359 dns_offsets_t
*offsets
;
361 msgblock
= ISC_LIST_TAIL(msg
->offsets
);
362 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
363 if (offsets
== NULL
) {
364 msgblock
= msgblock_allocate(msg
->mctx
,
365 sizeof(dns_offsets_t
),
367 if (msgblock
== NULL
)
370 ISC_LIST_APPEND(msg
->offsets
, msgblock
, link
);
372 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
379 msginitheader(dns_message_t
*m
) {
388 msginitprivate(dns_message_t
*m
) {
391 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
392 m
->cursors
[i
] = NULL
;
400 m
->state
= DNS_SECTION_ANY
; /* indicate nothing parsed or rendered */
408 msginittsig(dns_message_t
*m
) {
409 m
->tsigstatus
= dns_rcode_noerror
;
410 m
->querytsigstatus
= dns_rcode_noerror
;
415 m
->sig0status
= dns_rcode_noerror
;
420 * Init elements to default state. Used both when allocating a new element
421 * and when resetting one.
424 msginit(dns_message_t
*m
) {
430 m
->tcp_continuation
= 0;
432 m
->verify_attempted
= 0;
435 m
->query
.base
= NULL
;
438 m
->saved
.base
= NULL
;
445 msgresetnames(dns_message_t
*msg
, unsigned int first_section
) {
447 dns_name_t
*name
, *next_name
;
448 dns_rdataset_t
*rds
, *next_rds
;
451 * Clean up name lists by calling the rdataset disassociate function.
453 for (i
= first_section
; i
< DNS_SECTION_MAX
; i
++) {
454 name
= ISC_LIST_HEAD(msg
->sections
[i
]);
455 while (name
!= NULL
) {
456 next_name
= ISC_LIST_NEXT(name
, link
);
457 ISC_LIST_UNLINK(msg
->sections
[i
], name
, link
);
459 rds
= ISC_LIST_HEAD(name
->list
);
460 while (rds
!= NULL
) {
461 next_rds
= ISC_LIST_NEXT(rds
, link
);
462 ISC_LIST_UNLINK(name
->list
, rds
, link
);
464 INSIST(dns_rdataset_isassociated(rds
));
465 dns_rdataset_disassociate(rds
);
466 isc_mempool_put(msg
->rdspool
, rds
);
469 if (dns_name_dynamic(name
))
470 dns_name_free(name
, msg
->mctx
);
471 isc_mempool_put(msg
->namepool
, name
);
478 msgresetopt(dns_message_t
*msg
)
480 if (msg
->opt
!= NULL
) {
481 if (msg
->opt_reserved
> 0) {
482 dns_message_renderrelease(msg
, msg
->opt_reserved
);
483 msg
->opt_reserved
= 0;
485 INSIST(dns_rdataset_isassociated(msg
->opt
));
486 dns_rdataset_disassociate(msg
->opt
);
487 isc_mempool_put(msg
->rdspool
, msg
->opt
);
493 msgresetsigs(dns_message_t
*msg
, isc_boolean_t replying
) {
494 if (msg
->sig_reserved
> 0) {
495 dns_message_renderrelease(msg
, msg
->sig_reserved
);
496 msg
->sig_reserved
= 0;
498 if (msg
->tsig
!= NULL
) {
499 INSIST(dns_rdataset_isassociated(msg
->tsig
));
500 INSIST(msg
->namepool
!= NULL
);
502 INSIST(msg
->querytsig
== NULL
);
503 msg
->querytsig
= msg
->tsig
;
505 dns_rdataset_disassociate(msg
->tsig
);
506 isc_mempool_put(msg
->rdspool
, msg
->tsig
);
507 if (msg
->querytsig
!= NULL
) {
508 dns_rdataset_disassociate(msg
->querytsig
);
509 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
512 if (dns_name_dynamic(msg
->tsigname
))
513 dns_name_free(msg
->tsigname
, msg
->mctx
);
514 isc_mempool_put(msg
->namepool
, msg
->tsigname
);
516 msg
->tsigname
= NULL
;
517 } else if (msg
->querytsig
!= NULL
&& !replying
) {
518 dns_rdataset_disassociate(msg
->querytsig
);
519 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
520 msg
->querytsig
= NULL
;
522 if (msg
->sig0
!= NULL
) {
523 INSIST(dns_rdataset_isassociated(msg
->sig0
));
524 dns_rdataset_disassociate(msg
->sig0
);
525 isc_mempool_put(msg
->rdspool
, msg
->sig0
);
526 if (msg
->sig0name
!= NULL
) {
527 if (dns_name_dynamic(msg
->sig0name
))
528 dns_name_free(msg
->sig0name
, msg
->mctx
);
529 isc_mempool_put(msg
->namepool
, msg
->sig0name
);
532 msg
->sig0name
= NULL
;
537 * Free all but one (or everything) for this message. This is used by
538 * both dns_message_reset() and dns_message_destroy().
541 msgreset(dns_message_t
*msg
, isc_boolean_t everything
) {
542 dns_msgblock_t
*msgblock
, *next_msgblock
;
543 isc_buffer_t
*dynbuf
, *next_dynbuf
;
545 dns_rdatalist_t
*rdatalist
;
547 msgresetnames(msg
, 0);
549 msgresetsigs(msg
, ISC_FALSE
);
552 * Clean up linked lists.
556 * Run through the free lists, and just unlink anything found there.
557 * The memory isn't lost since these are part of message blocks we
560 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
561 while (rdata
!= NULL
) {
562 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
563 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
565 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
566 while (rdatalist
!= NULL
) {
567 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
568 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
571 dynbuf
= ISC_LIST_HEAD(msg
->scratchpad
);
572 INSIST(dynbuf
!= NULL
);
574 isc_buffer_clear(dynbuf
);
575 dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
577 while (dynbuf
!= NULL
) {
578 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
579 ISC_LIST_UNLINK(msg
->scratchpad
, dynbuf
, link
);
580 isc_buffer_free(&dynbuf
);
581 dynbuf
= next_dynbuf
;
584 msgblock
= ISC_LIST_HEAD(msg
->rdatas
);
585 if (!everything
&& msgblock
!= NULL
) {
586 msgblock_reset(msgblock
);
587 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
589 while (msgblock
!= NULL
) {
590 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
591 ISC_LIST_UNLINK(msg
->rdatas
, msgblock
, link
);
592 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdata_t
));
593 msgblock
= next_msgblock
;
597 * rdatalists could be empty.
600 msgblock
= ISC_LIST_HEAD(msg
->rdatalists
);
601 if (!everything
&& msgblock
!= NULL
) {
602 msgblock_reset(msgblock
);
603 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
605 while (msgblock
!= NULL
) {
606 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
607 ISC_LIST_UNLINK(msg
->rdatalists
, msgblock
, link
);
608 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdatalist_t
));
609 msgblock
= next_msgblock
;
612 msgblock
= ISC_LIST_HEAD(msg
->offsets
);
613 if (!everything
&& msgblock
!= NULL
) {
614 msgblock_reset(msgblock
);
615 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
617 while (msgblock
!= NULL
) {
618 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
619 ISC_LIST_UNLINK(msg
->offsets
, msgblock
, link
);
620 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_offsets_t
));
621 msgblock
= next_msgblock
;
624 if (msg
->tsigkey
!= NULL
) {
625 dns_tsigkey_detach(&msg
->tsigkey
);
629 if (msg
->tsigctx
!= NULL
)
630 dst_context_destroy(&msg
->tsigctx
);
632 if (msg
->query
.base
!= NULL
) {
633 if (msg
->free_query
!= 0)
634 isc_mem_put(msg
->mctx
, msg
->query
.base
,
636 msg
->query
.base
= NULL
;
637 msg
->query
.length
= 0;
640 if (msg
->saved
.base
!= NULL
) {
641 if (msg
->free_saved
!= 0)
642 isc_mem_put(msg
->mctx
, msg
->saved
.base
,
644 msg
->saved
.base
= NULL
;
645 msg
->saved
.length
= 0;
649 * cleanup the buffer cleanup list
651 dynbuf
= ISC_LIST_HEAD(msg
->cleanup
);
652 while (dynbuf
!= NULL
) {
653 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
654 ISC_LIST_UNLINK(msg
->cleanup
, dynbuf
, link
);
655 isc_buffer_free(&dynbuf
);
656 dynbuf
= next_dynbuf
;
660 * Set other bits to normal default values.
665 ENSURE(isc_mempool_getallocated(msg
->namepool
) == 0);
666 ENSURE(isc_mempool_getallocated(msg
->rdspool
) == 0);
670 spacefortsig(dns_tsigkey_t
*key
, int otherlen
) {
676 * The space required for an TSIG record is:
678 * n1 bytes for the name
679 * 2 bytes for the type
680 * 2 bytes for the class
681 * 4 bytes for the ttl
682 * 2 bytes for the rdlength
683 * n2 bytes for the algorithm name
684 * 6 bytes for the time signed
685 * 2 bytes for the fudge
686 * 2 bytes for the MAC size
687 * x bytes for the MAC
688 * 2 bytes for the original id
689 * 2 bytes for the error
690 * 2 bytes for the other data length
691 * y bytes for the other data (at most)
692 * ---------------------------------
693 * 26 + n1 + n2 + x + y bytes
696 dns_name_toregion(&key
->name
, &r1
);
697 dns_name_toregion(key
->algorithm
, &r2
);
698 if (key
->key
== NULL
)
701 result
= dst_key_sigsize(key
->key
, &x
);
702 if (result
!= ISC_R_SUCCESS
)
705 return (26 + r1
.length
+ r2
.length
+ x
+ otherlen
);
709 dns_message_create(isc_mem_t
*mctx
, unsigned int intent
, dns_message_t
**msgp
)
713 isc_buffer_t
*dynbuf
;
716 REQUIRE(mctx
!= NULL
);
717 REQUIRE(msgp
!= NULL
);
718 REQUIRE(*msgp
== NULL
);
719 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
720 || intent
== DNS_MESSAGE_INTENTRENDER
);
722 m
= isc_mem_get(mctx
, sizeof(dns_message_t
));
724 return (ISC_R_NOMEMORY
);
727 * No allocations until further notice. Just initialize all lists
728 * and other members that are freed in the cleanup phase here.
731 m
->magic
= DNS_MESSAGE_MAGIC
;
732 m
->from_to_wire
= intent
;
735 for (i
= 0; i
< DNS_SECTION_MAX
; i
++)
736 ISC_LIST_INIT(m
->sections
[i
]);
739 ISC_LIST_INIT(m
->scratchpad
);
740 ISC_LIST_INIT(m
->cleanup
);
743 ISC_LIST_INIT(m
->rdatas
);
744 ISC_LIST_INIT(m
->rdatalists
);
745 ISC_LIST_INIT(m
->offsets
);
746 ISC_LIST_INIT(m
->freerdata
);
747 ISC_LIST_INIT(m
->freerdatalist
);
750 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
753 result
= isc_mempool_create(m
->mctx
, sizeof(dns_name_t
), &m
->namepool
);
754 if (result
!= ISC_R_SUCCESS
)
756 isc_mempool_setfreemax(m
->namepool
, NAME_COUNT
);
757 isc_mempool_setname(m
->namepool
, "msg:names");
759 result
= isc_mempool_create(m
->mctx
, sizeof(dns_rdataset_t
),
761 if (result
!= ISC_R_SUCCESS
)
763 isc_mempool_setfreemax(m
->rdspool
, NAME_COUNT
);
764 isc_mempool_setname(m
->rdspool
, "msg:rdataset");
767 result
= isc_buffer_allocate(mctx
, &dynbuf
, SCRATCHPAD_SIZE
);
768 if (result
!= ISC_R_SUCCESS
)
770 ISC_LIST_APPEND(m
->scratchpad
, dynbuf
, link
);
775 return (ISC_R_SUCCESS
);
778 * Cleanup for error returns.
781 dynbuf
= ISC_LIST_HEAD(m
->scratchpad
);
782 if (dynbuf
!= NULL
) {
783 ISC_LIST_UNLINK(m
->scratchpad
, dynbuf
, link
);
784 isc_buffer_free(&dynbuf
);
786 if (m
->namepool
!= NULL
)
787 isc_mempool_destroy(&m
->namepool
);
788 if (m
->rdspool
!= NULL
)
789 isc_mempool_destroy(&m
->rdspool
);
791 isc_mem_put(mctx
, m
, sizeof(dns_message_t
));
793 return (ISC_R_NOMEMORY
);
797 dns_message_reset(dns_message_t
*msg
, unsigned int intent
) {
798 REQUIRE(DNS_MESSAGE_VALID(msg
));
799 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
800 || intent
== DNS_MESSAGE_INTENTRENDER
);
802 msgreset(msg
, ISC_FALSE
);
803 msg
->from_to_wire
= intent
;
807 dns_message_destroy(dns_message_t
**msgp
) {
810 REQUIRE(msgp
!= NULL
);
811 REQUIRE(DNS_MESSAGE_VALID(*msgp
));
816 msgreset(msg
, ISC_TRUE
);
817 isc_mempool_destroy(&msg
->namepool
);
818 isc_mempool_destroy(&msg
->rdspool
);
820 isc_mem_put(msg
->mctx
, msg
, sizeof(dns_message_t
));
824 findname(dns_name_t
**foundname
, dns_name_t
*target
,
825 dns_namelist_t
*section
)
829 for (curr
= ISC_LIST_TAIL(*section
);
831 curr
= ISC_LIST_PREV(curr
, link
)) {
832 if (dns_name_equal(curr
, target
)) {
833 if (foundname
!= NULL
)
835 return (ISC_R_SUCCESS
);
839 return (ISC_R_NOTFOUND
);
843 dns_message_find(dns_name_t
*name
, dns_rdataclass_t rdclass
,
844 dns_rdatatype_t type
, dns_rdatatype_t covers
,
845 dns_rdataset_t
**rdataset
)
847 dns_rdataset_t
*curr
;
849 if (rdataset
!= NULL
) {
850 REQUIRE(*rdataset
== NULL
);
853 for (curr
= ISC_LIST_TAIL(name
->list
);
855 curr
= ISC_LIST_PREV(curr
, link
)) {
856 if (curr
->rdclass
== rdclass
&&
857 curr
->type
== type
&& curr
->covers
== covers
) {
858 if (rdataset
!= NULL
)
860 return (ISC_R_SUCCESS
);
864 return (ISC_R_NOTFOUND
);
868 dns_message_findtype(dns_name_t
*name
, dns_rdatatype_t type
,
869 dns_rdatatype_t covers
, dns_rdataset_t
**rdataset
)
871 dns_rdataset_t
*curr
;
873 REQUIRE(name
!= NULL
);
874 if (rdataset
!= NULL
) {
875 REQUIRE(*rdataset
== NULL
);
878 for (curr
= ISC_LIST_TAIL(name
->list
);
880 curr
= ISC_LIST_PREV(curr
, link
)) {
881 if (curr
->type
== type
&& curr
->covers
== covers
) {
882 if (rdataset
!= NULL
)
884 return (ISC_R_SUCCESS
);
888 return (ISC_R_NOTFOUND
);
892 * Read a name from buffer "source".
895 getname(dns_name_t
*name
, isc_buffer_t
*source
, dns_message_t
*msg
,
896 dns_decompress_t
*dctx
)
898 isc_buffer_t
*scratch
;
902 scratch
= currentbuffer(msg
);
905 * First try: use current buffer.
906 * Second try: allocate a new buffer and use that.
910 result
= dns_name_fromwire(name
, source
, dctx
, ISC_FALSE
,
913 if (result
== ISC_R_NOSPACE
) {
916 result
= newbuffer(msg
, SCRATCHPAD_SIZE
);
917 if (result
!= ISC_R_SUCCESS
)
920 scratch
= currentbuffer(msg
);
921 dns_name_reset(name
);
927 INSIST(0); /* Cannot get here... */
928 return (ISC_R_UNEXPECTED
);
932 getrdata(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
933 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
,
934 unsigned int rdatalen
, dns_rdata_t
*rdata
)
936 isc_buffer_t
*scratch
;
939 unsigned int trysize
;
941 scratch
= currentbuffer(msg
);
943 isc_buffer_setactive(source
, rdatalen
);
946 * First try: use current buffer.
947 * Second try: allocate a new buffer of size
948 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
949 * (the data will fit if it was not more than 50% compressed)
950 * Subsequent tries: double buffer size on each try.
954 /* XXX possibly change this to a while (tries < 2) loop */
956 result
= dns_rdata_fromwire(rdata
, rdclass
, rdtype
,
960 if (result
== ISC_R_NOSPACE
) {
962 trysize
= 2 * rdatalen
;
963 if (trysize
< SCRATCHPAD_SIZE
)
964 trysize
= SCRATCHPAD_SIZE
;
966 INSIST(trysize
!= 0);
967 if (trysize
>= 65535)
968 return (ISC_R_NOSPACE
);
969 /* XXX DNS_R_RRTOOLONG? */
973 result
= newbuffer(msg
, trysize
);
974 if (result
!= ISC_R_SUCCESS
)
977 scratch
= currentbuffer(msg
);
987 seen_problem = ISC_TRUE; \
989 result = DNS_R_FORMERR; \
995 getquestions(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
996 unsigned int options
)
1002 dns_offsets_t
*offsets
;
1003 dns_rdataset_t
*rdataset
;
1004 dns_rdatalist_t
*rdatalist
;
1005 isc_result_t result
;
1006 dns_rdatatype_t rdtype
;
1007 dns_rdataclass_t rdclass
;
1008 dns_namelist_t
*section
;
1009 isc_boolean_t free_name
;
1010 isc_boolean_t best_effort
;
1011 isc_boolean_t seen_problem
;
1013 section
= &msg
->sections
[DNS_SECTION_QUESTION
];
1015 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1016 seen_problem
= ISC_FALSE
;
1022 for (count
= 0; count
< msg
->counts
[DNS_SECTION_QUESTION
]; count
++) {
1023 name
= isc_mempool_get(msg
->namepool
);
1025 return (ISC_R_NOMEMORY
);
1026 free_name
= ISC_TRUE
;
1028 offsets
= newoffsets(msg
);
1029 if (offsets
== NULL
) {
1030 result
= ISC_R_NOMEMORY
;
1033 dns_name_init(name
, *offsets
);
1036 * Parse the name out of this packet.
1038 isc_buffer_remainingregion(source
, &r
);
1039 isc_buffer_setactive(source
, r
.length
);
1040 result
= getname(name
, source
, msg
, dctx
);
1041 if (result
!= ISC_R_SUCCESS
)
1045 * Run through the section, looking to see if this name
1046 * is already there. If it is found, put back the allocated
1047 * name since we no longer need it, and set our name pointer
1048 * to point to the name we found.
1050 result
= findname(&name2
, name
, section
);
1053 * If it is the first name in the section, accept it.
1055 * If it is not, but is not the same as the name already
1056 * in the question section, append to the section. Note that
1057 * here in the question section this is illegal, so return
1058 * FORMERR. In the future, check the opcode to see if
1059 * this should be legal or not. In either case we no longer
1060 * need this name pointer.
1062 if (result
!= ISC_R_SUCCESS
) {
1063 if (!ISC_LIST_EMPTY(*section
))
1065 ISC_LIST_APPEND(*section
, name
, link
);
1066 free_name
= ISC_FALSE
;
1068 isc_mempool_put(msg
->namepool
, name
);
1071 free_name
= ISC_FALSE
;
1075 * Get type and class.
1077 isc_buffer_remainingregion(source
, &r
);
1079 result
= ISC_R_UNEXPECTEDEND
;
1082 rdtype
= isc_buffer_getuint16(source
);
1083 rdclass
= isc_buffer_getuint16(source
);
1086 * If this class is different than the one we already read,
1089 if (msg
->state
== DNS_SECTION_ANY
) {
1090 msg
->state
= DNS_SECTION_QUESTION
;
1091 msg
->rdclass
= rdclass
;
1092 } else if (msg
->rdclass
!= rdclass
)
1096 * Can't ask the same question twice.
1098 result
= dns_message_find(name
, rdclass
, rdtype
, 0, NULL
);
1099 if (result
== ISC_R_SUCCESS
)
1103 * Allocate a new rdatalist.
1105 rdatalist
= newrdatalist(msg
);
1106 if (rdatalist
== NULL
) {
1107 result
= ISC_R_NOMEMORY
;
1110 rdataset
= isc_mempool_get(msg
->rdspool
);
1111 if (rdataset
== NULL
) {
1112 result
= ISC_R_NOMEMORY
;
1117 * Convert rdatalist to rdataset, and attach the latter to
1120 rdatalist
->type
= rdtype
;
1121 rdatalist
->covers
= 0;
1122 rdatalist
->rdclass
= rdclass
;
1124 ISC_LIST_INIT(rdatalist
->rdata
);
1126 dns_rdataset_init(rdataset
);
1127 result
= dns_rdatalist_tordataset(rdatalist
, rdataset
);
1128 if (result
!= ISC_R_SUCCESS
)
1131 rdataset
->attributes
|= DNS_RDATASETATTR_QUESTION
;
1133 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1138 return (DNS_R_RECOVERABLE
);
1139 return (ISC_R_SUCCESS
);
1142 if (rdataset
!= NULL
) {
1143 INSIST(!dns_rdataset_isassociated(rdataset
));
1144 isc_mempool_put(msg
->rdspool
, rdataset
);
1147 if (rdatalist
!= NULL
)
1148 isc_mempool_put(msg
->rdlpool
, rdatalist
);
1151 isc_mempool_put(msg
->namepool
, name
);
1156 static isc_boolean_t
1157 update(dns_section_t section
, dns_rdataclass_t rdclass
) {
1158 if (section
== DNS_SECTION_PREREQUISITE
)
1159 return (ISC_TF(rdclass
== dns_rdataclass_any
||
1160 rdclass
== dns_rdataclass_none
));
1161 if (section
== DNS_SECTION_UPDATE
)
1162 return (ISC_TF(rdclass
== dns_rdataclass_any
));
1167 getsection(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
1168 dns_section_t sectionid
, unsigned int options
)
1171 unsigned int count
, rdatalen
;
1174 dns_offsets_t
*offsets
;
1175 dns_rdataset_t
*rdataset
= NULL
;
1176 dns_rdatalist_t
*rdatalist
;
1177 isc_result_t result
;
1178 dns_rdatatype_t rdtype
, covers
;
1179 dns_rdataclass_t rdclass
;
1182 dns_namelist_t
*section
;
1183 isc_boolean_t free_name
, free_rdataset
;
1184 isc_boolean_t preserve_order
, best_effort
, seen_problem
;
1185 isc_boolean_t issigzero
;
1187 preserve_order
= ISC_TF(options
& DNS_MESSAGEPARSE_PRESERVEORDER
);
1188 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1189 seen_problem
= ISC_FALSE
;
1191 for (count
= 0; count
< msg
->counts
[sectionid
]; count
++) {
1192 int recstart
= source
->current
;
1193 isc_boolean_t skip_name_search
, skip_type_search
;
1195 section
= &msg
->sections
[sectionid
];
1197 skip_name_search
= ISC_FALSE
;
1198 skip_type_search
= ISC_FALSE
;
1199 free_name
= ISC_FALSE
;
1200 free_rdataset
= ISC_FALSE
;
1202 name
= isc_mempool_get(msg
->namepool
);
1204 return (ISC_R_NOMEMORY
);
1205 free_name
= ISC_TRUE
;
1207 offsets
= newoffsets(msg
);
1208 if (offsets
== NULL
) {
1209 result
= ISC_R_NOMEMORY
;
1212 dns_name_init(name
, *offsets
);
1215 * Parse the name out of this packet.
1217 isc_buffer_remainingregion(source
, &r
);
1218 isc_buffer_setactive(source
, r
.length
);
1219 result
= getname(name
, source
, msg
, dctx
);
1220 if (result
!= ISC_R_SUCCESS
)
1224 * Get type, class, ttl, and rdatalen. Verify that at least
1225 * rdatalen bytes remain. (Some of this is deferred to
1228 isc_buffer_remainingregion(source
, &r
);
1229 if (r
.length
< 2 + 2 + 4 + 2) {
1230 result
= ISC_R_UNEXPECTEDEND
;
1233 rdtype
= isc_buffer_getuint16(source
);
1234 rdclass
= isc_buffer_getuint16(source
);
1237 * If there was no question section, we may not yet have
1238 * established a class. Do so now.
1240 if (msg
->state
== DNS_SECTION_ANY
&&
1241 rdtype
!= dns_rdatatype_opt
&& /* class is UDP SIZE */
1242 rdtype
!= dns_rdatatype_tsig
&& /* class is ANY */
1243 rdtype
!= dns_rdatatype_tkey
) { /* class is undefined */
1244 msg
->rdclass
= rdclass
;
1245 msg
->state
= DNS_SECTION_QUESTION
;
1249 * If this class is different than the one in the question
1252 if (msg
->opcode
!= dns_opcode_update
1253 && rdtype
!= dns_rdatatype_tsig
1254 && rdtype
!= dns_rdatatype_opt
1255 && rdtype
!= dns_rdatatype_dnskey
/* in a TKEY query */
1256 && rdtype
!= dns_rdatatype_sig
/* SIG(0) */
1257 && rdtype
!= dns_rdatatype_tkey
/* Win2000 TKEY */
1258 && msg
->rdclass
!= dns_rdataclass_any
1259 && msg
->rdclass
!= rdclass
)
1263 * Special type handling for TSIG, OPT, and TKEY.
1265 if (rdtype
== dns_rdatatype_tsig
) {
1267 * If it is a tsig, verify that it is in the
1268 * additional data section.
1270 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1271 rdclass
!= dns_rdataclass_any
||
1272 count
!= msg
->counts
[sectionid
] - 1)
1274 msg
->sigstart
= recstart
;
1275 skip_name_search
= ISC_TRUE
;
1276 skip_type_search
= ISC_TRUE
;
1277 } else if (rdtype
== dns_rdatatype_opt
) {
1279 * The name of an OPT record must be ".", it
1280 * must be in the additional data section, and
1281 * it must be the first OPT we've seen.
1283 if (!dns_name_equal(dns_rootname
, name
) ||
1286 skip_name_search
= ISC_TRUE
;
1287 skip_type_search
= ISC_TRUE
;
1288 } else if (rdtype
== dns_rdatatype_tkey
) {
1290 * A TKEY must be in the additional section if this
1291 * is a query, and the answer section if this is a
1292 * response. Unless it's a Win2000 client.
1294 * Its class is ignored.
1296 dns_section_t tkeysection
;
1298 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0)
1299 tkeysection
= DNS_SECTION_ADDITIONAL
;
1301 tkeysection
= DNS_SECTION_ANSWER
;
1302 if (sectionid
!= tkeysection
&&
1303 sectionid
!= DNS_SECTION_ANSWER
)
1308 * ... now get ttl and rdatalen, and check buffer.
1310 ttl
= isc_buffer_getuint32(source
);
1311 rdatalen
= isc_buffer_getuint16(source
);
1312 r
.length
-= (2 + 2 + 4 + 2);
1313 if (r
.length
< rdatalen
) {
1314 result
= ISC_R_UNEXPECTEDEND
;
1319 * Read the rdata from the wire format. Interpret the
1320 * rdata according to its actual class, even if it had a
1321 * DynDNS meta-class in the packet (unless this is a TSIG).
1322 * Then put the meta-class back into the finished rdata.
1324 rdata
= newrdata(msg
);
1325 if (rdata
== NULL
) {
1326 result
= ISC_R_NOMEMORY
;
1329 if (msg
->opcode
== dns_opcode_update
&&
1330 update(sectionid
, rdclass
)) {
1331 if (rdatalen
!= 0) {
1332 result
= DNS_R_FORMERR
;
1336 * When the rdata is empty, the data pointer is
1337 * never dereferenced, but it must still be non-NULL.
1338 * Casting 1 rather than "" avoids warnings about
1339 * discarding the const attribute of a string,
1340 * for compilers that would warn about such things.
1342 rdata
->data
= (unsigned char *)1;
1344 rdata
->rdclass
= rdclass
;
1345 rdata
->type
= rdtype
;
1346 rdata
->flags
= DNS_RDATA_UPDATE
;
1347 result
= ISC_R_SUCCESS
;
1348 } else if (rdclass
== dns_rdataclass_none
&&
1349 msg
->opcode
== dns_opcode_update
&&
1350 sectionid
== DNS_SECTION_UPDATE
) {
1351 result
= getrdata(source
, msg
, dctx
, msg
->rdclass
,
1352 rdtype
, rdatalen
, rdata
);
1354 result
= getrdata(source
, msg
, dctx
, rdclass
,
1355 rdtype
, rdatalen
, rdata
);
1356 if (result
!= ISC_R_SUCCESS
)
1358 rdata
->rdclass
= rdclass
;
1359 issigzero
= ISC_FALSE
;
1360 if (rdtype
== dns_rdatatype_rrsig
&&
1361 rdata
->flags
== 0) {
1362 covers
= dns_rdata_covers(rdata
);
1365 } else if (rdtype
== dns_rdatatype_sig
/* SIG(0) */ &&
1366 rdata
->flags
== 0) {
1367 covers
= dns_rdata_covers(rdata
);
1369 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1370 count
!= msg
->counts
[sectionid
] - 1)
1372 msg
->sigstart
= recstart
;
1373 skip_name_search
= ISC_TRUE
;
1374 skip_type_search
= ISC_TRUE
;
1375 issigzero
= ISC_TRUE
;
1381 * If we are doing a dynamic update or this is a meta-type,
1382 * don't bother searching for a name, just append this one
1383 * to the end of the message.
1385 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1387 if (rdtype
!= dns_rdatatype_opt
&&
1388 rdtype
!= dns_rdatatype_tsig
&&
1391 ISC_LIST_APPEND(*section
, name
, link
);
1392 free_name
= ISC_FALSE
;
1396 * Run through the section, looking to see if this name
1397 * is already there. If it is found, put back the
1398 * allocated name since we no longer need it, and set
1399 * our name pointer to point to the name we found.
1401 result
= findname(&name2
, name
, section
);
1404 * If it is a new name, append to the section.
1406 if (result
== ISC_R_SUCCESS
) {
1407 isc_mempool_put(msg
->namepool
, name
);
1410 ISC_LIST_APPEND(*section
, name
, link
);
1412 free_name
= ISC_FALSE
;
1416 * Search name for the particular type and class.
1417 * Skip this stage if in update mode or this is a meta-type.
1419 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1421 result
= ISC_R_NOTFOUND
;
1424 * If this is a type that can only occur in
1425 * the question section, fail.
1427 if (dns_rdatatype_questiononly(rdtype
))
1431 result
= dns_message_find(name
, rdclass
, rdtype
,
1436 * If we found an rdataset that matches, we need to
1437 * append this rdata to that set. If we did not, we need
1438 * to create a new rdatalist, store the important bits there,
1439 * convert it to an rdataset, and link the latter to the name.
1440 * Yuck. When appending, make certain that the type isn't
1441 * a singleton type, such as SOA or CNAME.
1443 * Note that this check will be bypassed when preserving order,
1444 * the opcode is an update, or the type search is skipped.
1446 if (result
== ISC_R_SUCCESS
) {
1447 if (dns_rdatatype_issingleton(rdtype
))
1451 if (result
== ISC_R_NOTFOUND
) {
1452 rdataset
= isc_mempool_get(msg
->rdspool
);
1453 if (rdataset
== NULL
) {
1454 result
= ISC_R_NOMEMORY
;
1457 free_rdataset
= ISC_TRUE
;
1459 rdatalist
= newrdatalist(msg
);
1460 if (rdatalist
== NULL
) {
1461 result
= ISC_R_NOMEMORY
;
1465 rdatalist
->type
= rdtype
;
1466 rdatalist
->covers
= covers
;
1467 rdatalist
->rdclass
= rdclass
;
1468 rdatalist
->ttl
= ttl
;
1469 ISC_LIST_INIT(rdatalist
->rdata
);
1471 dns_rdataset_init(rdataset
);
1472 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
,
1476 if (rdtype
!= dns_rdatatype_opt
&&
1477 rdtype
!= dns_rdatatype_tsig
&&
1480 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1481 free_rdataset
= ISC_FALSE
;
1488 * Section 5.2 of RFC2181 says we should drop
1489 * nonauthoritative rrsets where the TTLs differ, but we
1490 * currently treat them the as if they were authoritative and
1493 if (ttl
!= rdataset
->ttl
) {
1494 rdataset
->attributes
|= DNS_RDATASETATTR_TTLADJUSTED
;
1495 if (ttl
< rdataset
->ttl
)
1496 rdataset
->ttl
= ttl
;
1499 /* Append this rdata to the rdataset. */
1500 dns_rdatalist_fromrdataset(rdataset
, &rdatalist
);
1501 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1504 * If this is an OPT record, remember it. Also, set
1505 * the extended rcode. Note that msg->opt will only be set
1506 * if best-effort parsing is enabled.
1508 if (rdtype
== dns_rdatatype_opt
&& msg
->opt
== NULL
) {
1511 msg
->opt
= rdataset
;
1513 free_rdataset
= ISC_FALSE
;
1514 ercode
= (dns_rcode_t
)
1515 ((msg
->opt
->ttl
& DNS_MESSAGE_EDNSRCODE_MASK
)
1517 msg
->rcode
|= ercode
;
1518 isc_mempool_put(msg
->namepool
, name
);
1519 free_name
= ISC_FALSE
;
1523 * If this is an SIG(0) or TSIG record, remember it. Note
1524 * that msg->sig0 or msg->tsig will only be set if best-effort
1525 * parsing is enabled.
1527 if (issigzero
&& msg
->sig0
== NULL
) {
1528 msg
->sig0
= rdataset
;
1529 msg
->sig0name
= name
;
1531 free_rdataset
= ISC_FALSE
;
1532 free_name
= ISC_FALSE
;
1533 } else if (rdtype
== dns_rdatatype_tsig
&& msg
->tsig
== NULL
) {
1534 msg
->tsig
= rdataset
;
1535 msg
->tsigname
= name
;
1537 free_rdataset
= ISC_FALSE
;
1538 free_name
= ISC_FALSE
;
1543 isc_mempool_put(msg
->namepool
, name
);
1545 isc_mempool_put(msg
->rdspool
, rdataset
);
1546 free_name
= free_rdataset
= ISC_FALSE
;
1548 INSIST(free_name
== ISC_FALSE
);
1549 INSIST(free_rdataset
== ISC_FALSE
);
1553 return (DNS_R_RECOVERABLE
);
1554 return (ISC_R_SUCCESS
);
1558 isc_mempool_put(msg
->namepool
, name
);
1560 isc_mempool_put(msg
->rdspool
, rdataset
);
1566 dns_message_parse(dns_message_t
*msg
, isc_buffer_t
*source
,
1567 unsigned int options
)
1570 dns_decompress_t dctx
;
1572 isc_uint16_t tmpflags
;
1573 isc_buffer_t origsource
;
1574 isc_boolean_t seen_problem
;
1575 isc_boolean_t ignore_tc
;
1577 REQUIRE(DNS_MESSAGE_VALID(msg
));
1578 REQUIRE(source
!= NULL
);
1579 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
1581 seen_problem
= ISC_FALSE
;
1582 ignore_tc
= ISC_TF(options
& DNS_MESSAGEPARSE_IGNORETRUNCATION
);
1584 origsource
= *source
;
1587 msg
->question_ok
= 0;
1589 isc_buffer_remainingregion(source
, &r
);
1590 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1591 return (ISC_R_UNEXPECTEDEND
);
1593 msg
->id
= isc_buffer_getuint16(source
);
1594 tmpflags
= isc_buffer_getuint16(source
);
1595 msg
->opcode
= ((tmpflags
& DNS_MESSAGE_OPCODE_MASK
)
1596 >> DNS_MESSAGE_OPCODE_SHIFT
);
1597 msg
->rcode
= (dns_rcode_t
)(tmpflags
& DNS_MESSAGE_RCODE_MASK
);
1598 msg
->flags
= (tmpflags
& DNS_MESSAGE_FLAG_MASK
);
1599 msg
->counts
[DNS_SECTION_QUESTION
] = isc_buffer_getuint16(source
);
1600 msg
->counts
[DNS_SECTION_ANSWER
] = isc_buffer_getuint16(source
);
1601 msg
->counts
[DNS_SECTION_AUTHORITY
] = isc_buffer_getuint16(source
);
1602 msg
->counts
[DNS_SECTION_ADDITIONAL
] = isc_buffer_getuint16(source
);
1609 dns_decompress_init(&dctx
, -1, DNS_DECOMPRESS_ANY
);
1611 dns_decompress_setmethods(&dctx
, DNS_COMPRESS_GLOBAL14
);
1613 ret
= getquestions(source
, msg
, &dctx
, options
);
1614 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1616 if (ret
== DNS_R_RECOVERABLE
) {
1617 seen_problem
= ISC_TRUE
;
1618 ret
= ISC_R_SUCCESS
;
1620 if (ret
!= ISC_R_SUCCESS
)
1622 msg
->question_ok
= 1;
1624 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ANSWER
, options
);
1625 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1627 if (ret
== DNS_R_RECOVERABLE
) {
1628 seen_problem
= ISC_TRUE
;
1629 ret
= ISC_R_SUCCESS
;
1631 if (ret
!= ISC_R_SUCCESS
)
1634 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_AUTHORITY
, options
);
1635 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1637 if (ret
== DNS_R_RECOVERABLE
) {
1638 seen_problem
= ISC_TRUE
;
1639 ret
= ISC_R_SUCCESS
;
1641 if (ret
!= ISC_R_SUCCESS
)
1644 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ADDITIONAL
, options
);
1645 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1647 if (ret
== DNS_R_RECOVERABLE
) {
1648 seen_problem
= ISC_TRUE
;
1649 ret
= ISC_R_SUCCESS
;
1651 if (ret
!= ISC_R_SUCCESS
)
1654 isc_buffer_remainingregion(source
, &r
);
1655 if (r
.length
!= 0) {
1656 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1657 DNS_LOGMODULE_MESSAGE
, ISC_LOG_DEBUG(3),
1658 "message has %u byte(s) of trailing garbage",
1663 if ((options
& DNS_MESSAGEPARSE_CLONEBUFFER
) == 0)
1664 isc_buffer_usedregion(&origsource
, &msg
->saved
);
1666 msg
->saved
.length
= isc_buffer_usedlength(&origsource
);
1667 msg
->saved
.base
= isc_mem_get(msg
->mctx
, msg
->saved
.length
);
1668 if (msg
->saved
.base
== NULL
)
1669 return (ISC_R_NOMEMORY
);
1670 memcpy(msg
->saved
.base
, isc_buffer_base(&origsource
),
1672 msg
->free_saved
= 1;
1675 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1676 return (DNS_R_RECOVERABLE
);
1677 if (seen_problem
== ISC_TRUE
)
1678 return (DNS_R_RECOVERABLE
);
1679 return (ISC_R_SUCCESS
);
1683 dns_message_renderbegin(dns_message_t
*msg
, dns_compress_t
*cctx
,
1684 isc_buffer_t
*buffer
)
1688 REQUIRE(DNS_MESSAGE_VALID(msg
));
1689 REQUIRE(buffer
!= NULL
);
1690 REQUIRE(msg
->buffer
== NULL
);
1691 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
1696 * Erase the contents of this buffer.
1698 isc_buffer_clear(buffer
);
1701 * Make certain there is enough for at least the header in this
1704 isc_buffer_availableregion(buffer
, &r
);
1705 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1706 return (ISC_R_NOSPACE
);
1708 if (r
.length
< msg
->reserved
)
1709 return (ISC_R_NOSPACE
);
1712 * Reserve enough space for the header in this buffer.
1714 isc_buffer_add(buffer
, DNS_MESSAGE_HEADERLEN
);
1716 msg
->buffer
= buffer
;
1718 return (ISC_R_SUCCESS
);
1722 dns_message_renderchangebuffer(dns_message_t
*msg
, isc_buffer_t
*buffer
) {
1725 REQUIRE(DNS_MESSAGE_VALID(msg
));
1726 REQUIRE(buffer
!= NULL
);
1727 REQUIRE(msg
->buffer
!= NULL
);
1730 * Ensure that the new buffer is empty, and has enough space to
1731 * hold the current contents.
1733 isc_buffer_clear(buffer
);
1735 isc_buffer_availableregion(buffer
, &rn
);
1736 isc_buffer_usedregion(msg
->buffer
, &r
);
1737 REQUIRE(rn
.length
> r
.length
);
1740 * Copy the contents from the old to the new buffer.
1742 isc_buffer_add(buffer
, r
.length
);
1743 memcpy(rn
.base
, r
.base
, r
.length
);
1745 msg
->buffer
= buffer
;
1747 return (ISC_R_SUCCESS
);
1751 dns_message_renderrelease(dns_message_t
*msg
, unsigned int space
) {
1752 REQUIRE(DNS_MESSAGE_VALID(msg
));
1753 REQUIRE(space
<= msg
->reserved
);
1755 msg
->reserved
-= space
;
1759 dns_message_renderreserve(dns_message_t
*msg
, unsigned int space
) {
1762 REQUIRE(DNS_MESSAGE_VALID(msg
));
1764 if (msg
->buffer
!= NULL
) {
1765 isc_buffer_availableregion(msg
->buffer
, &r
);
1766 if (r
.length
< (space
+ msg
->reserved
))
1767 return (ISC_R_NOSPACE
);
1770 msg
->reserved
+= space
;
1772 return (ISC_R_SUCCESS
);
1775 static inline isc_boolean_t
1776 wrong_priority(dns_rdataset_t
*rds
, int pass
, dns_rdatatype_t preferred_glue
) {
1780 * If we are not rendering class IN, this ordering is bogus.
1782 if (rds
->rdclass
!= dns_rdataclass_in
)
1785 switch (rds
->type
) {
1786 case dns_rdatatype_a
:
1787 case dns_rdatatype_aaaa
:
1788 if (preferred_glue
== rds
->type
)
1793 case dns_rdatatype_rrsig
:
1794 case dns_rdatatype_dnskey
:
1801 if (pass_needed
>= pass
)
1807 #ifdef ALLOW_FILTER_AAAA_ON_V4
1809 * Decide whether to not answer with an AAAA record and its RRSIG
1811 static inline isc_boolean_t
1812 norender_rdataset(const dns_rdataset_t
*rdataset
, unsigned int options
)
1814 switch (rdataset
->type
) {
1815 case dns_rdatatype_aaaa
:
1816 if ((options
& DNS_MESSAGERENDER_FILTER_AAAA
) == 0)
1820 case dns_rdatatype_rrsig
:
1821 if ((options
& DNS_MESSAGERENDER_FILTER_AAAA
) == 0 ||
1822 rdataset
->covers
!= dns_rdatatype_aaaa
)
1830 if (rdataset
->rdclass
!= dns_rdataclass_in
)
1838 dns_message_rendersection(dns_message_t
*msg
, dns_section_t sectionid
,
1839 unsigned int options
)
1841 dns_namelist_t
*section
;
1842 dns_name_t
*name
, *next_name
;
1843 dns_rdataset_t
*rdataset
, *next_rdataset
;
1844 unsigned int count
, total
;
1845 isc_result_t result
;
1846 isc_buffer_t st
; /* for rollbacks */
1848 isc_boolean_t partial
= ISC_FALSE
;
1849 unsigned int rd_options
;
1850 dns_rdatatype_t preferred_glue
= 0;
1852 REQUIRE(DNS_MESSAGE_VALID(msg
));
1853 REQUIRE(msg
->buffer
!= NULL
);
1854 REQUIRE(VALID_NAMED_SECTION(sectionid
));
1856 section
= &msg
->sections
[sectionid
];
1858 if ((sectionid
== DNS_SECTION_ADDITIONAL
)
1859 && (options
& DNS_MESSAGERENDER_ORDERED
) == 0) {
1860 if ((options
& DNS_MESSAGERENDER_PREFER_A
) != 0) {
1861 preferred_glue
= dns_rdatatype_a
;
1863 } else if ((options
& DNS_MESSAGERENDER_PREFER_AAAA
) != 0) {
1864 preferred_glue
= dns_rdatatype_aaaa
;
1871 if ((options
& DNS_MESSAGERENDER_OMITDNSSEC
) == 0)
1874 rd_options
= DNS_RDATASETTOWIRE_OMITDNSSEC
;
1877 * Shrink the space in the buffer by the reserved amount.
1879 msg
->buffer
->length
-= msg
->reserved
;
1882 if (msg
->reserved
== 0 && (options
& DNS_MESSAGERENDER_PARTIAL
) != 0)
1886 * Render required glue first. Set TC if it won't fit.
1888 name
= ISC_LIST_HEAD(*section
);
1890 rdataset
= ISC_LIST_HEAD(name
->list
);
1891 if (rdataset
!= NULL
&&
1892 (rdataset
->attributes
& DNS_RDATASETATTR_REQUIREDGLUE
) != 0 &&
1893 (rdataset
->attributes
& DNS_RDATASETATTR_RENDERED
) == 0) {
1894 const void *order_arg
= msg
->order_arg
;
1895 st
= *(msg
->buffer
);
1898 result
= dns_rdataset_towirepartial(rdataset
,
1908 result
= dns_rdataset_towiresorted(rdataset
,
1917 if (partial
&& result
== ISC_R_NOSPACE
) {
1918 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1919 msg
->buffer
->length
+= msg
->reserved
;
1920 msg
->counts
[sectionid
] += total
;
1923 if (result
== ISC_R_NOSPACE
)
1924 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1925 if (result
!= ISC_R_SUCCESS
) {
1926 INSIST(st
.used
< 65536);
1927 dns_compress_rollback(msg
->cctx
,
1928 (isc_uint16_t
)st
.used
);
1929 *(msg
->buffer
) = st
; /* rollback */
1930 msg
->buffer
->length
+= msg
->reserved
;
1931 msg
->counts
[sectionid
] += total
;
1934 rdataset
->attributes
|= DNS_RDATASETATTR_RENDERED
;
1939 name
= ISC_LIST_HEAD(*section
);
1941 msg
->buffer
->length
+= msg
->reserved
;
1942 msg
->counts
[sectionid
] += total
;
1943 return (ISC_R_SUCCESS
);
1946 while (name
!= NULL
) {
1947 next_name
= ISC_LIST_NEXT(name
, link
);
1949 rdataset
= ISC_LIST_HEAD(name
->list
);
1950 while (rdataset
!= NULL
) {
1951 next_rdataset
= ISC_LIST_NEXT(rdataset
, link
);
1953 if ((rdataset
->attributes
&
1954 DNS_RDATASETATTR_RENDERED
) != 0)
1957 if (((options
& DNS_MESSAGERENDER_ORDERED
)
1959 && (sectionid
== DNS_SECTION_ADDITIONAL
)
1960 && wrong_priority(rdataset
, pass
,
1964 #ifdef ALLOW_FILTER_AAAA_ON_V4
1966 * Suppress AAAAs if asked and we are
1967 * not doing DNSSEC or are breaking DNSSEC.
1968 * Say so in the AD bit if we break DNSSEC.
1970 if (norender_rdataset(rdataset
, options
) &&
1971 sectionid
!= DNS_SECTION_QUESTION
) {
1972 if (sectionid
== DNS_SECTION_ANSWER
||
1973 sectionid
== DNS_SECTION_AUTHORITY
)
1974 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
1975 if (OPTOUT(rdataset
))
1976 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
1981 st
= *(msg
->buffer
);
1985 result
= dns_rdataset_towirepartial(
1996 result
= dns_rdataset_towiresorted(
2009 * If out of space, record stats on what we
2010 * rendered so far, and return that status.
2012 * XXXMLG Need to change this when
2013 * dns_rdataset_towire() can render partial
2014 * sets starting at some arbitrary point in the
2015 * set. This will include setting a bit in the
2016 * rdataset to indicate that a partial
2017 * rendering was done, and some state saved
2018 * somewhere (probably in the message struct)
2019 * to indicate where to continue from.
2021 if (partial
&& result
== ISC_R_NOSPACE
) {
2022 msg
->buffer
->length
+= msg
->reserved
;
2023 msg
->counts
[sectionid
] += total
;
2026 if (result
!= ISC_R_SUCCESS
) {
2027 INSIST(st
.used
< 65536);
2028 dns_compress_rollback(msg
->cctx
,
2029 (isc_uint16_t
)st
.used
);
2030 *(msg
->buffer
) = st
; /* rollback */
2031 msg
->buffer
->length
+= msg
->reserved
;
2032 msg
->counts
[sectionid
] += total
;
2037 * If we have rendered non-validated data,
2038 * ensure that the AD bit is not set.
2040 if (rdataset
->trust
!= dns_trust_secure
&&
2041 (sectionid
== DNS_SECTION_ANSWER
||
2042 sectionid
== DNS_SECTION_AUTHORITY
))
2043 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2044 if (OPTOUT(rdataset
))
2045 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
2047 rdataset
->attributes
|=
2048 DNS_RDATASETATTR_RENDERED
;
2051 rdataset
= next_rdataset
;
2056 } while (--pass
!= 0);
2058 msg
->buffer
->length
+= msg
->reserved
;
2059 msg
->counts
[sectionid
] += total
;
2061 return (ISC_R_SUCCESS
);
2065 dns_message_renderheader(dns_message_t
*msg
, isc_buffer_t
*target
) {
2069 REQUIRE(DNS_MESSAGE_VALID(msg
));
2070 REQUIRE(target
!= NULL
);
2072 isc_buffer_availableregion(target
, &r
);
2073 REQUIRE(r
.length
>= DNS_MESSAGE_HEADERLEN
);
2075 isc_buffer_putuint16(target
, msg
->id
);
2077 tmp
= ((msg
->opcode
<< DNS_MESSAGE_OPCODE_SHIFT
)
2078 & DNS_MESSAGE_OPCODE_MASK
);
2079 tmp
|= (msg
->rcode
& DNS_MESSAGE_RCODE_MASK
);
2080 tmp
|= (msg
->flags
& DNS_MESSAGE_FLAG_MASK
);
2082 INSIST(msg
->counts
[DNS_SECTION_QUESTION
] < 65536 &&
2083 msg
->counts
[DNS_SECTION_ANSWER
] < 65536 &&
2084 msg
->counts
[DNS_SECTION_AUTHORITY
] < 65536 &&
2085 msg
->counts
[DNS_SECTION_ADDITIONAL
] < 65536);
2087 isc_buffer_putuint16(target
, tmp
);
2088 isc_buffer_putuint16(target
,
2089 (isc_uint16_t
)msg
->counts
[DNS_SECTION_QUESTION
]);
2090 isc_buffer_putuint16(target
,
2091 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ANSWER
]);
2092 isc_buffer_putuint16(target
,
2093 (isc_uint16_t
)msg
->counts
[DNS_SECTION_AUTHORITY
]);
2094 isc_buffer_putuint16(target
,
2095 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ADDITIONAL
]);
2099 dns_message_renderend(dns_message_t
*msg
) {
2100 isc_buffer_t tmpbuf
;
2105 REQUIRE(DNS_MESSAGE_VALID(msg
));
2106 REQUIRE(msg
->buffer
!= NULL
);
2108 if ((msg
->rcode
& ~DNS_MESSAGE_RCODE_MASK
) != 0 && msg
->opt
== NULL
) {
2110 * We have an extended rcode but are not using EDNS.
2112 return (DNS_R_FORMERR
);
2116 * If we've got an OPT record, render it.
2118 if (msg
->opt
!= NULL
) {
2119 dns_message_renderrelease(msg
, msg
->opt_reserved
);
2120 msg
->opt_reserved
= 0;
2122 * Set the extended rcode.
2124 msg
->opt
->ttl
&= ~DNS_MESSAGE_EDNSRCODE_MASK
;
2125 msg
->opt
->ttl
|= ((msg
->rcode
<< 20) &
2126 DNS_MESSAGE_EDNSRCODE_MASK
);
2131 result
= dns_rdataset_towire(msg
->opt
, dns_rootname
,
2132 msg
->cctx
, msg
->buffer
, 0,
2134 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2135 if (result
!= ISC_R_SUCCESS
)
2140 * If we're adding a TSIG or SIG(0) to a truncated message,
2141 * clear all rdatasets from the message except for the question
2142 * before adding the TSIG or SIG(0). If the question doesn't fit,
2145 if ((msg
->tsigkey
!= NULL
|| msg
->sig0key
!= NULL
) &&
2146 (msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
2150 msgresetnames(msg
, DNS_SECTION_ANSWER
);
2152 dns_message_renderreset(msg
);
2154 isc_buffer_clear(msg
->buffer
);
2155 isc_buffer_add(msg
->buffer
, DNS_MESSAGE_HEADERLEN
);
2156 dns_compress_rollback(msg
->cctx
, 0);
2157 result
= dns_message_rendersection(msg
, DNS_SECTION_QUESTION
,
2159 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
2164 * If we're adding a TSIG record, generate and render it.
2166 if (msg
->tsigkey
!= NULL
) {
2167 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2168 msg
->sig_reserved
= 0;
2169 result
= dns_tsig_sign(msg
);
2170 if (result
!= ISC_R_SUCCESS
)
2173 result
= dns_rdataset_towire(msg
->tsig
, msg
->tsigname
,
2174 msg
->cctx
, msg
->buffer
, 0,
2176 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2177 if (result
!= ISC_R_SUCCESS
)
2182 * If we're adding a SIG(0) record, generate and render it.
2184 if (msg
->sig0key
!= NULL
) {
2185 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2186 msg
->sig_reserved
= 0;
2187 result
= dns_dnssec_signmessage(msg
, msg
->sig0key
);
2188 if (result
!= ISC_R_SUCCESS
)
2192 * Note: dns_rootname is used here, not msg->sig0name, since
2193 * the owner name of a SIG(0) is irrelevant, and will not
2194 * be set in a message being rendered.
2196 result
= dns_rdataset_towire(msg
->sig0
, dns_rootname
,
2197 msg
->cctx
, msg
->buffer
, 0,
2199 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2200 if (result
!= ISC_R_SUCCESS
)
2204 isc_buffer_usedregion(msg
->buffer
, &r
);
2205 isc_buffer_init(&tmpbuf
, r
.base
, r
.length
);
2207 dns_message_renderheader(msg
, &tmpbuf
);
2209 msg
->buffer
= NULL
; /* forget about this buffer only on success XXX */
2211 return (ISC_R_SUCCESS
);
2215 dns_message_renderreset(dns_message_t
*msg
) {
2218 dns_rdataset_t
*rds
;
2221 * Reset the message so that it may be rendered again.
2224 REQUIRE(DNS_MESSAGE_VALID(msg
));
2225 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2229 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
2230 msg
->cursors
[i
] = NULL
;
2232 for (name
= ISC_LIST_HEAD(msg
->sections
[i
]);
2234 name
= ISC_LIST_NEXT(name
, link
)) {
2235 for (rds
= ISC_LIST_HEAD(name
->list
);
2237 rds
= ISC_LIST_NEXT(rds
, link
)) {
2238 rds
->attributes
&= ~DNS_RDATASETATTR_RENDERED
;
2242 if (msg
->tsigname
!= NULL
)
2243 dns_message_puttempname(msg
, &msg
->tsigname
);
2244 if (msg
->tsig
!= NULL
) {
2245 dns_rdataset_disassociate(msg
->tsig
);
2246 dns_message_puttemprdataset(msg
, &msg
->tsig
);
2248 if (msg
->sig0
!= NULL
) {
2249 dns_rdataset_disassociate(msg
->sig0
);
2250 dns_message_puttemprdataset(msg
, &msg
->sig0
);
2255 dns_message_firstname(dns_message_t
*msg
, dns_section_t section
) {
2256 REQUIRE(DNS_MESSAGE_VALID(msg
));
2257 REQUIRE(VALID_NAMED_SECTION(section
));
2259 msg
->cursors
[section
] = ISC_LIST_HEAD(msg
->sections
[section
]);
2261 if (msg
->cursors
[section
] == NULL
)
2262 return (ISC_R_NOMORE
);
2264 return (ISC_R_SUCCESS
);
2268 dns_message_nextname(dns_message_t
*msg
, dns_section_t section
) {
2269 REQUIRE(DNS_MESSAGE_VALID(msg
));
2270 REQUIRE(VALID_NAMED_SECTION(section
));
2271 REQUIRE(msg
->cursors
[section
] != NULL
);
2273 msg
->cursors
[section
] = ISC_LIST_NEXT(msg
->cursors
[section
], link
);
2275 if (msg
->cursors
[section
] == NULL
)
2276 return (ISC_R_NOMORE
);
2278 return (ISC_R_SUCCESS
);
2282 dns_message_currentname(dns_message_t
*msg
, dns_section_t section
,
2285 REQUIRE(DNS_MESSAGE_VALID(msg
));
2286 REQUIRE(VALID_NAMED_SECTION(section
));
2287 REQUIRE(name
!= NULL
&& *name
== NULL
);
2288 REQUIRE(msg
->cursors
[section
] != NULL
);
2290 *name
= msg
->cursors
[section
];
2294 dns_message_findname(dns_message_t
*msg
, dns_section_t section
,
2295 dns_name_t
*target
, dns_rdatatype_t type
,
2296 dns_rdatatype_t covers
, dns_name_t
**name
,
2297 dns_rdataset_t
**rdataset
)
2299 dns_name_t
*foundname
;
2300 isc_result_t result
;
2303 * XXX These requirements are probably too intensive, especially
2304 * where things can be NULL, but as they are they ensure that if
2305 * something is NON-NULL, indicating that the caller expects it
2306 * to be filled in, that we can in fact fill it in.
2308 REQUIRE(msg
!= NULL
);
2309 REQUIRE(VALID_SECTION(section
));
2310 REQUIRE(target
!= NULL
);
2312 REQUIRE(*name
== NULL
);
2313 if (type
== dns_rdatatype_any
) {
2314 REQUIRE(rdataset
== NULL
);
2316 if (rdataset
!= NULL
)
2317 REQUIRE(*rdataset
== NULL
);
2320 result
= findname(&foundname
, target
,
2321 &msg
->sections
[section
]);
2323 if (result
== ISC_R_NOTFOUND
)
2324 return (DNS_R_NXDOMAIN
);
2325 else if (result
!= ISC_R_SUCCESS
)
2332 * And now look for the type.
2334 if (type
== dns_rdatatype_any
)
2335 return (ISC_R_SUCCESS
);
2337 result
= dns_message_findtype(foundname
, type
, covers
, rdataset
);
2338 if (result
== ISC_R_NOTFOUND
)
2339 return (DNS_R_NXRRSET
);
2345 dns_message_movename(dns_message_t
*msg
, dns_name_t
*name
,
2346 dns_section_t fromsection
,
2347 dns_section_t tosection
)
2349 REQUIRE(msg
!= NULL
);
2350 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2351 REQUIRE(name
!= NULL
);
2352 REQUIRE(VALID_NAMED_SECTION(fromsection
));
2353 REQUIRE(VALID_NAMED_SECTION(tosection
));
2356 * Unlink the name from the old section
2358 ISC_LIST_UNLINK(msg
->sections
[fromsection
], name
, link
);
2359 ISC_LIST_APPEND(msg
->sections
[tosection
], name
, link
);
2363 dns_message_addname(dns_message_t
*msg
, dns_name_t
*name
,
2364 dns_section_t section
)
2366 REQUIRE(msg
!= NULL
);
2367 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2368 REQUIRE(name
!= NULL
);
2369 REQUIRE(VALID_NAMED_SECTION(section
));
2371 ISC_LIST_APPEND(msg
->sections
[section
], name
, link
);
2375 dns_message_removename(dns_message_t
*msg
, dns_name_t
*name
,
2376 dns_section_t section
)
2378 REQUIRE(msg
!= NULL
);
2379 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2380 REQUIRE(name
!= NULL
);
2381 REQUIRE(VALID_NAMED_SECTION(section
));
2383 ISC_LIST_UNLINK(msg
->sections
[section
], name
, link
);
2387 dns_message_gettempname(dns_message_t
*msg
, dns_name_t
**item
) {
2388 REQUIRE(DNS_MESSAGE_VALID(msg
));
2389 REQUIRE(item
!= NULL
&& *item
== NULL
);
2391 *item
= isc_mempool_get(msg
->namepool
);
2393 return (ISC_R_NOMEMORY
);
2394 dns_name_init(*item
, NULL
);
2396 return (ISC_R_SUCCESS
);
2400 dns_message_gettempoffsets(dns_message_t
*msg
, dns_offsets_t
**item
) {
2401 REQUIRE(DNS_MESSAGE_VALID(msg
));
2402 REQUIRE(item
!= NULL
&& *item
== NULL
);
2404 *item
= newoffsets(msg
);
2406 return (ISC_R_NOMEMORY
);
2408 return (ISC_R_SUCCESS
);
2412 dns_message_gettemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2413 REQUIRE(DNS_MESSAGE_VALID(msg
));
2414 REQUIRE(item
!= NULL
&& *item
== NULL
);
2416 *item
= newrdata(msg
);
2418 return (ISC_R_NOMEMORY
);
2420 return (ISC_R_SUCCESS
);
2424 dns_message_gettemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2425 REQUIRE(DNS_MESSAGE_VALID(msg
));
2426 REQUIRE(item
!= NULL
&& *item
== NULL
);
2428 *item
= isc_mempool_get(msg
->rdspool
);
2430 return (ISC_R_NOMEMORY
);
2432 dns_rdataset_init(*item
);
2434 return (ISC_R_SUCCESS
);
2438 dns_message_gettemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2439 REQUIRE(DNS_MESSAGE_VALID(msg
));
2440 REQUIRE(item
!= NULL
&& *item
== NULL
);
2442 *item
= newrdatalist(msg
);
2444 return (ISC_R_NOMEMORY
);
2446 return (ISC_R_SUCCESS
);
2450 dns_message_puttempname(dns_message_t
*msg
, dns_name_t
**item
) {
2451 REQUIRE(DNS_MESSAGE_VALID(msg
));
2452 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2454 if (dns_name_dynamic(*item
))
2455 dns_name_free(*item
, msg
->mctx
);
2456 isc_mempool_put(msg
->namepool
, *item
);
2461 dns_message_puttemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2462 REQUIRE(DNS_MESSAGE_VALID(msg
));
2463 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2465 releaserdata(msg
, *item
);
2470 dns_message_puttemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2471 REQUIRE(DNS_MESSAGE_VALID(msg
));
2472 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2474 REQUIRE(!dns_rdataset_isassociated(*item
));
2475 isc_mempool_put(msg
->rdspool
, *item
);
2480 dns_message_puttemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2481 REQUIRE(DNS_MESSAGE_VALID(msg
));
2482 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2484 releaserdatalist(msg
, *item
);
2489 dns_message_peekheader(isc_buffer_t
*source
, dns_messageid_t
*idp
,
2490 unsigned int *flagsp
)
2493 isc_buffer_t buffer
;
2497 REQUIRE(source
!= NULL
);
2501 isc_buffer_remainingregion(&buffer
, &r
);
2502 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
2503 return (ISC_R_UNEXPECTEDEND
);
2505 id
= isc_buffer_getuint16(&buffer
);
2506 flags
= isc_buffer_getuint16(&buffer
);
2507 flags
&= DNS_MESSAGE_FLAG_MASK
;
2514 return (ISC_R_SUCCESS
);
2518 dns_message_reply(dns_message_t
*msg
, isc_boolean_t want_question_section
) {
2519 unsigned int first_section
;
2520 isc_result_t result
;
2522 REQUIRE(DNS_MESSAGE_VALID(msg
));
2523 REQUIRE((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0);
2525 if (!msg
->header_ok
)
2526 return (DNS_R_FORMERR
);
2527 if (msg
->opcode
!= dns_opcode_query
&&
2528 msg
->opcode
!= dns_opcode_notify
)
2529 want_question_section
= ISC_FALSE
;
2530 if (want_question_section
) {
2531 if (!msg
->question_ok
)
2532 return (DNS_R_FORMERR
);
2533 first_section
= DNS_SECTION_ANSWER
;
2535 first_section
= DNS_SECTION_QUESTION
;
2536 msg
->from_to_wire
= DNS_MESSAGE_INTENTRENDER
;
2537 msgresetnames(msg
, first_section
);
2539 msgresetsigs(msg
, ISC_TRUE
);
2540 msginitprivate(msg
);
2542 * We now clear most flags and then set QR, ensuring that the
2543 * reply's flags will be in a reasonable state.
2545 msg
->flags
&= DNS_MESSAGE_REPLYPRESERVE
;
2546 msg
->flags
|= DNS_MESSAGEFLAG_QR
;
2549 * This saves the query TSIG status, if the query was signed, and
2550 * reserves space in the reply for the TSIG.
2552 if (msg
->tsigkey
!= NULL
) {
2553 unsigned int otherlen
= 0;
2554 msg
->querytsigstatus
= msg
->tsigstatus
;
2555 msg
->tsigstatus
= dns_rcode_noerror
;
2556 if (msg
->querytsigstatus
== dns_tsigerror_badtime
)
2558 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, otherlen
);
2559 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2560 if (result
!= ISC_R_SUCCESS
) {
2561 msg
->sig_reserved
= 0;
2565 if (msg
->saved
.base
!= NULL
) {
2566 msg
->query
.base
= msg
->saved
.base
;
2567 msg
->query
.length
= msg
->saved
.length
;
2568 msg
->free_query
= msg
->free_saved
;
2569 msg
->saved
.base
= NULL
;
2570 msg
->saved
.length
= 0;
2571 msg
->free_saved
= 0;
2574 return (ISC_R_SUCCESS
);
2578 dns_message_getopt(dns_message_t
*msg
) {
2581 * Get the OPT record for 'msg'.
2584 REQUIRE(DNS_MESSAGE_VALID(msg
));
2590 dns_message_setopt(dns_message_t
*msg
, dns_rdataset_t
*opt
) {
2591 isc_result_t result
;
2592 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2595 * Set the OPT record for 'msg'.
2599 * The space required for an OPT record is:
2601 * 1 byte for the name
2602 * 2 bytes for the type
2603 * 2 bytes for the class
2604 * 4 bytes for the ttl
2605 * 2 bytes for the rdata length
2606 * ---------------------------------
2609 * plus the length of the rdata.
2612 REQUIRE(DNS_MESSAGE_VALID(msg
));
2613 REQUIRE(opt
->type
== dns_rdatatype_opt
);
2614 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2615 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2619 result
= dns_rdataset_first(opt
);
2620 if (result
!= ISC_R_SUCCESS
)
2622 dns_rdataset_current(opt
, &rdata
);
2623 msg
->opt_reserved
= 11 + rdata
.length
;
2624 result
= dns_message_renderreserve(msg
, msg
->opt_reserved
);
2625 if (result
!= ISC_R_SUCCESS
) {
2626 msg
->opt_reserved
= 0;
2632 return (ISC_R_SUCCESS
);
2635 dns_message_puttemprdataset(msg
, &opt
);
2641 dns_message_gettsig(dns_message_t
*msg
, dns_name_t
**owner
) {
2644 * Get the TSIG record and owner for 'msg'.
2647 REQUIRE(DNS_MESSAGE_VALID(msg
));
2648 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2651 *owner
= msg
->tsigname
;
2656 dns_message_settsigkey(dns_message_t
*msg
, dns_tsigkey_t
*key
) {
2657 isc_result_t result
;
2660 * Set the TSIG key for 'msg'
2663 REQUIRE(DNS_MESSAGE_VALID(msg
));
2664 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2666 if (key
== NULL
&& msg
->tsigkey
!= NULL
) {
2667 if (msg
->sig_reserved
!= 0) {
2668 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2669 msg
->sig_reserved
= 0;
2671 dns_tsigkey_detach(&msg
->tsigkey
);
2674 REQUIRE(msg
->tsigkey
== NULL
&& msg
->sig0key
== NULL
);
2675 dns_tsigkey_attach(key
, &msg
->tsigkey
);
2676 if (msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
) {
2677 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, 0);
2678 result
= dns_message_renderreserve(msg
,
2680 if (result
!= ISC_R_SUCCESS
) {
2681 dns_tsigkey_detach(&msg
->tsigkey
);
2682 msg
->sig_reserved
= 0;
2687 return (ISC_R_SUCCESS
);
2691 dns_message_gettsigkey(dns_message_t
*msg
) {
2694 * Get the TSIG key for 'msg'
2697 REQUIRE(DNS_MESSAGE_VALID(msg
));
2699 return (msg
->tsigkey
);
2703 dns_message_setquerytsig(dns_message_t
*msg
, isc_buffer_t
*querytsig
) {
2704 dns_rdata_t
*rdata
= NULL
;
2705 dns_rdatalist_t
*list
= NULL
;
2706 dns_rdataset_t
*set
= NULL
;
2707 isc_buffer_t
*buf
= NULL
;
2709 isc_result_t result
;
2711 REQUIRE(DNS_MESSAGE_VALID(msg
));
2712 REQUIRE(msg
->querytsig
== NULL
);
2714 if (querytsig
== NULL
)
2715 return (ISC_R_SUCCESS
);
2717 result
= dns_message_gettemprdata(msg
, &rdata
);
2718 if (result
!= ISC_R_SUCCESS
)
2721 result
= dns_message_gettemprdatalist(msg
, &list
);
2722 if (result
!= ISC_R_SUCCESS
)
2724 result
= dns_message_gettemprdataset(msg
, &set
);
2725 if (result
!= ISC_R_SUCCESS
)
2728 isc_buffer_usedregion(querytsig
, &r
);
2729 result
= isc_buffer_allocate(msg
->mctx
, &buf
, r
.length
);
2730 if (result
!= ISC_R_SUCCESS
)
2732 isc_buffer_putmem(buf
, r
.base
, r
.length
);
2733 isc_buffer_usedregion(buf
, &r
);
2734 dns_rdata_init(rdata
);
2735 dns_rdata_fromregion(rdata
, dns_rdataclass_any
, dns_rdatatype_tsig
, &r
);
2736 dns_message_takebuffer(msg
, &buf
);
2737 ISC_LIST_INIT(list
->rdata
);
2738 ISC_LIST_APPEND(list
->rdata
, rdata
, link
);
2739 result
= dns_rdatalist_tordataset(list
, set
);
2740 if (result
!= ISC_R_SUCCESS
)
2743 msg
->querytsig
= set
;
2749 dns_message_puttemprdata(msg
, &rdata
);
2751 dns_message_puttemprdatalist(msg
, &list
);
2753 dns_message_puttemprdataset(msg
, &set
);
2754 return (ISC_R_NOMEMORY
);
2758 dns_message_getquerytsig(dns_message_t
*msg
, isc_mem_t
*mctx
,
2759 isc_buffer_t
**querytsig
) {
2760 isc_result_t result
;
2761 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2764 REQUIRE(DNS_MESSAGE_VALID(msg
));
2765 REQUIRE(mctx
!= NULL
);
2766 REQUIRE(querytsig
!= NULL
&& *querytsig
== NULL
);
2768 if (msg
->tsig
== NULL
)
2769 return (ISC_R_SUCCESS
);
2771 result
= dns_rdataset_first(msg
->tsig
);
2772 if (result
!= ISC_R_SUCCESS
)
2774 dns_rdataset_current(msg
->tsig
, &rdata
);
2775 dns_rdata_toregion(&rdata
, &r
);
2777 result
= isc_buffer_allocate(mctx
, querytsig
, r
.length
);
2778 if (result
!= ISC_R_SUCCESS
)
2780 isc_buffer_putmem(*querytsig
, r
.base
, r
.length
);
2781 return (ISC_R_SUCCESS
);
2785 dns_message_getsig0(dns_message_t
*msg
, dns_name_t
**owner
) {
2788 * Get the SIG(0) record for 'msg'.
2791 REQUIRE(DNS_MESSAGE_VALID(msg
));
2792 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2794 if (msg
->sig0
!= NULL
&& owner
!= NULL
) {
2795 /* If dns_message_getsig0 is called on a rendered message
2796 * after the SIG(0) has been applied, we need to return the
2797 * root name, not NULL.
2799 if (msg
->sig0name
== NULL
)
2800 *owner
= dns_rootname
;
2802 *owner
= msg
->sig0name
;
2808 dns_message_setsig0key(dns_message_t
*msg
, dst_key_t
*key
) {
2811 isc_result_t result
;
2814 * Set the SIG(0) key for 'msg'
2818 * The space required for an SIG(0) record is:
2820 * 1 byte for the name
2821 * 2 bytes for the type
2822 * 2 bytes for the class
2823 * 4 bytes for the ttl
2824 * 2 bytes for the type covered
2825 * 1 byte for the algorithm
2826 * 1 bytes for the labels
2827 * 4 bytes for the original ttl
2828 * 4 bytes for the signature expiration
2829 * 4 bytes for the signature inception
2830 * 2 bytes for the key tag
2831 * n bytes for the signer's name
2832 * x bytes for the signature
2833 * ---------------------------------
2836 REQUIRE(DNS_MESSAGE_VALID(msg
));
2837 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2838 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2841 REQUIRE(msg
->sig0key
== NULL
&& msg
->tsigkey
== NULL
);
2842 dns_name_toregion(dst_key_name(key
), &r
);
2843 result
= dst_key_sigsize(key
, &x
);
2844 if (result
!= ISC_R_SUCCESS
) {
2845 msg
->sig_reserved
= 0;
2848 msg
->sig_reserved
= 27 + r
.length
+ x
;
2849 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2850 if (result
!= ISC_R_SUCCESS
) {
2851 msg
->sig_reserved
= 0;
2856 return (ISC_R_SUCCESS
);
2860 dns_message_getsig0key(dns_message_t
*msg
) {
2863 * Get the SIG(0) key for 'msg'
2866 REQUIRE(DNS_MESSAGE_VALID(msg
));
2868 return (msg
->sig0key
);
2872 dns_message_takebuffer(dns_message_t
*msg
, isc_buffer_t
**buffer
) {
2873 REQUIRE(DNS_MESSAGE_VALID(msg
));
2874 REQUIRE(buffer
!= NULL
);
2875 REQUIRE(ISC_BUFFER_VALID(*buffer
));
2877 ISC_LIST_APPEND(msg
->cleanup
, *buffer
, link
);
2882 dns_message_signer(dns_message_t
*msg
, dns_name_t
*signer
) {
2883 isc_result_t result
= ISC_R_SUCCESS
;
2884 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2886 REQUIRE(DNS_MESSAGE_VALID(msg
));
2887 REQUIRE(signer
!= NULL
);
2888 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
2890 if (msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2891 return (ISC_R_NOTFOUND
);
2893 if (msg
->verify_attempted
== 0)
2894 return (DNS_R_NOTVERIFIEDYET
);
2896 if (!dns_name_hasbuffer(signer
)) {
2897 isc_buffer_t
*dynbuf
= NULL
;
2898 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, 512);
2899 if (result
!= ISC_R_SUCCESS
)
2901 dns_name_setbuffer(signer
, dynbuf
);
2902 dns_message_takebuffer(msg
, &dynbuf
);
2905 if (msg
->sig0
!= NULL
) {
2906 dns_rdata_sig_t sig
;
2908 result
= dns_rdataset_first(msg
->sig0
);
2909 INSIST(result
== ISC_R_SUCCESS
);
2910 dns_rdataset_current(msg
->sig0
, &rdata
);
2912 result
= dns_rdata_tostruct(&rdata
, &sig
, NULL
);
2913 if (result
!= ISC_R_SUCCESS
)
2916 if (msg
->verified_sig
&& msg
->sig0status
== dns_rcode_noerror
)
2917 result
= ISC_R_SUCCESS
;
2919 result
= DNS_R_SIGINVALID
;
2920 dns_name_clone(&sig
.signer
, signer
);
2921 dns_rdata_freestruct(&sig
);
2923 dns_name_t
*identity
;
2924 dns_rdata_any_tsig_t tsig
;
2926 result
= dns_rdataset_first(msg
->tsig
);
2927 INSIST(result
== ISC_R_SUCCESS
);
2928 dns_rdataset_current(msg
->tsig
, &rdata
);
2930 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
2931 if (msg
->tsigstatus
!= dns_rcode_noerror
)
2932 result
= DNS_R_TSIGVERIFYFAILURE
;
2933 else if (tsig
.error
!= dns_rcode_noerror
)
2934 result
= DNS_R_TSIGERRORSET
;
2936 result
= ISC_R_SUCCESS
;
2937 dns_rdata_freestruct(&tsig
);
2939 if (msg
->tsigkey
== NULL
) {
2941 * If msg->tsigstatus & tsig.error are both
2942 * dns_rcode_noerror, the message must have been
2943 * verified, which means msg->tsigkey will be
2946 INSIST(result
!= ISC_R_SUCCESS
);
2948 identity
= dns_tsigkey_identity(msg
->tsigkey
);
2949 if (identity
== NULL
) {
2950 if (result
== ISC_R_SUCCESS
)
2951 result
= DNS_R_NOIDENTITY
;
2952 identity
= &msg
->tsigkey
->name
;
2954 dns_name_clone(identity
, signer
);
2962 dns_message_resetsig(dns_message_t
*msg
) {
2963 REQUIRE(DNS_MESSAGE_VALID(msg
));
2964 msg
->verified_sig
= 0;
2965 msg
->verify_attempted
= 0;
2966 msg
->tsigstatus
= dns_rcode_noerror
;
2967 msg
->sig0status
= dns_rcode_noerror
;
2968 msg
->timeadjust
= 0;
2969 if (msg
->tsigkey
!= NULL
) {
2970 dns_tsigkey_detach(&msg
->tsigkey
);
2971 msg
->tsigkey
= NULL
;
2976 dns_message_rechecksig(dns_message_t
*msg
, dns_view_t
*view
) {
2977 dns_message_resetsig(msg
);
2978 return (dns_message_checksig(msg
, view
));
2981 #ifdef SKAN_MSG_DEBUG
2983 dns_message_dumpsig(dns_message_t
*msg
, char *txt1
) {
2984 dns_rdata_t querytsigrdata
= DNS_RDATA_INIT
;
2985 dns_rdata_any_tsig_t querytsig
;
2986 isc_result_t result
;
2988 if (msg
->tsig
!= NULL
) {
2989 result
= dns_rdataset_first(msg
->tsig
);
2990 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2991 dns_rdataset_current(msg
->tsig
, &querytsigrdata
);
2992 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
2993 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
2994 hexdump(txt1
, "TSIG", querytsig
.signature
,
2998 if (msg
->querytsig
!= NULL
) {
2999 result
= dns_rdataset_first(msg
->querytsig
);
3000 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3001 dns_rdataset_current(msg
->querytsig
, &querytsigrdata
);
3002 result
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
, NULL
);
3003 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
3004 hexdump(txt1
, "QUERYTSIG", querytsig
.signature
,
3011 dns_message_checksig(dns_message_t
*msg
, dns_view_t
*view
) {
3012 isc_buffer_t b
, msgb
;
3014 REQUIRE(DNS_MESSAGE_VALID(msg
));
3016 if (msg
->tsigkey
== NULL
&& msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
3017 return (ISC_R_SUCCESS
);
3019 INSIST(msg
->saved
.base
!= NULL
);
3020 isc_buffer_init(&msgb
, msg
->saved
.base
, msg
->saved
.length
);
3021 isc_buffer_add(&msgb
, msg
->saved
.length
);
3022 if (msg
->tsigkey
!= NULL
|| msg
->tsig
!= NULL
) {
3023 #ifdef SKAN_MSG_DEBUG
3024 dns_message_dumpsig(msg
, "dns_message_checksig#1");
3027 return (dns_view_checksig(view
, &msgb
, msg
));
3029 return (dns_tsig_verify(&msgb
, msg
, NULL
, NULL
));
3031 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3032 dns_rdata_sig_t sig
;
3033 dns_rdataset_t keyset
;
3034 isc_result_t result
;
3036 result
= dns_rdataset_first(msg
->sig0
);
3037 INSIST(result
== ISC_R_SUCCESS
);
3038 dns_rdataset_current(msg
->sig0
, &rdata
);
3041 * This can occur when the message is a dynamic update, since
3042 * the rdata length checking is relaxed. This should not
3043 * happen in a well-formed message, since the SIG(0) is only
3044 * looked for in the additional section, and the dynamic update
3045 * meta-records are in the prerequisite and update sections.
3047 if (rdata
.length
== 0)
3048 return (ISC_R_UNEXPECTEDEND
);
3050 result
= dns_rdata_tostruct(&rdata
, &sig
, msg
->mctx
);
3051 if (result
!= ISC_R_SUCCESS
)
3054 dns_rdataset_init(&keyset
);
3056 return (DNS_R_KEYUNAUTHORIZED
);
3057 result
= dns_view_simplefind(view
, &sig
.signer
,
3058 dns_rdatatype_key
/* SIG(0) */,
3059 0, 0, ISC_FALSE
, &keyset
, NULL
);
3061 if (result
!= ISC_R_SUCCESS
) {
3062 /* XXXBEW Should possibly create a fetch here */
3063 result
= DNS_R_KEYUNAUTHORIZED
;
3065 } else if (keyset
.trust
< dns_trust_secure
) {
3066 /* XXXBEW Should call a validator here */
3067 result
= DNS_R_KEYUNAUTHORIZED
;
3070 result
= dns_rdataset_first(&keyset
);
3071 INSIST(result
== ISC_R_SUCCESS
);
3073 result
== ISC_R_SUCCESS
;
3074 result
= dns_rdataset_next(&keyset
))
3076 dst_key_t
*key
= NULL
;
3078 dns_rdata_reset(&rdata
);
3079 dns_rdataset_current(&keyset
, &rdata
);
3080 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
3081 isc_buffer_add(&b
, rdata
.length
);
3083 result
= dst_key_fromdns(&sig
.signer
, rdata
.rdclass
,
3084 &b
, view
->mctx
, &key
);
3085 if (result
!= ISC_R_SUCCESS
)
3087 if (dst_key_alg(key
) != sig
.algorithm
||
3088 dst_key_id(key
) != sig
.keyid
||
3089 !(dst_key_proto(key
) == DNS_KEYPROTO_DNSSEC
||
3090 dst_key_proto(key
) == DNS_KEYPROTO_ANY
))
3095 result
= dns_dnssec_verifymessage(&msgb
, msg
, key
);
3097 if (result
== ISC_R_SUCCESS
)
3100 if (result
== ISC_R_NOMORE
)
3101 result
= DNS_R_KEYUNAUTHORIZED
;
3104 if (dns_rdataset_isassociated(&keyset
))
3105 dns_rdataset_disassociate(&keyset
);
3106 dns_rdata_freestruct(&sig
);
3112 dns_message_sectiontotext(dns_message_t
*msg
, dns_section_t section
,
3113 const dns_master_style_t
*style
,
3114 dns_messagetextflag_t flags
,
3115 isc_buffer_t
*target
) {
3116 dns_name_t
*name
, empty_name
;
3117 dns_rdataset_t
*rdataset
;
3118 isc_result_t result
;
3120 REQUIRE(DNS_MESSAGE_VALID(msg
));
3121 REQUIRE(target
!= NULL
);
3122 REQUIRE(VALID_SECTION(section
));
3124 if (ISC_LIST_EMPTY(msg
->sections
[section
]))
3125 return (ISC_R_SUCCESS
);
3127 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0) {
3128 ADD_STRING(target
, ";; ");
3129 if (msg
->opcode
!= dns_opcode_update
) {
3130 ADD_STRING(target
, sectiontext
[section
]);
3132 ADD_STRING(target
, updsectiontext
[section
]);
3134 ADD_STRING(target
, " SECTION:\n");
3137 dns_name_init(&empty_name
, NULL
);
3138 result
= dns_message_firstname(msg
, section
);
3139 if (result
!= ISC_R_SUCCESS
) {
3144 dns_message_currentname(msg
, section
, &name
);
3145 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3147 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3148 if (section
== DNS_SECTION_QUESTION
) {
3149 ADD_STRING(target
, ";");
3150 result
= dns_master_questiontotext(name
,
3155 result
= dns_master_rdatasettotext(name
,
3160 if (result
!= ISC_R_SUCCESS
)
3163 result
= dns_message_nextname(msg
, section
);
3164 } while (result
== ISC_R_SUCCESS
);
3165 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3166 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3167 ADD_STRING(target
, "\n");
3168 if (result
== ISC_R_NOMORE
)
3169 result
= ISC_R_SUCCESS
;
3174 dns_message_pseudosectiontotext(dns_message_t
*msg
,
3175 dns_pseudosection_t section
,
3176 const dns_master_style_t
*style
,
3177 dns_messagetextflag_t flags
,
3178 isc_buffer_t
*target
) {
3179 dns_rdataset_t
*ps
= NULL
;
3180 dns_name_t
*name
= NULL
;
3181 isc_result_t result
;
3182 char buf
[sizeof("1234567890")];
3185 isc_buffer_t optbuf
;
3186 isc_uint16_t optcode
, optlen
;
3187 unsigned char *optdata
;
3189 REQUIRE(DNS_MESSAGE_VALID(msg
));
3190 REQUIRE(target
!= NULL
);
3191 REQUIRE(VALID_PSEUDOSECTION(section
));
3194 case DNS_PSEUDOSECTION_OPT
:
3195 ps
= dns_message_getopt(msg
);
3197 return (ISC_R_SUCCESS
);
3198 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3199 ADD_STRING(target
, ";; OPT PSEUDOSECTION:\n");
3200 ADD_STRING(target
, "; EDNS: version: ");
3201 snprintf(buf
, sizeof(buf
), "%u",
3202 (unsigned int)((ps
->ttl
& 0x00ff0000) >> 16));
3203 ADD_STRING(target
, buf
);
3204 ADD_STRING(target
, ", flags:");
3205 if ((ps
->ttl
& DNS_MESSAGEEXTFLAG_DO
) != 0)
3206 ADD_STRING(target
, " do");
3207 mbz
= ps
->ttl
& ~DNS_MESSAGEEXTFLAG_DO
& 0xffff;
3209 ADD_STRING(target
, "; MBZ: ");
3210 snprintf(buf
, sizeof(buf
), "%.4x ", mbz
);
3211 ADD_STRING(target
, buf
);
3212 ADD_STRING(target
, ", udp: ");
3214 ADD_STRING(target
, "; udp: ");
3215 snprintf(buf
, sizeof(buf
), "%u\n", (unsigned int)ps
->rdclass
);
3216 ADD_STRING(target
, buf
);
3218 result
= dns_rdataset_first(ps
);
3219 if (result
!= ISC_R_SUCCESS
)
3220 return (ISC_R_SUCCESS
);
3222 /* Print EDNS info, if any */
3223 dns_rdata_init(&rdata
);
3224 dns_rdataset_current(ps
, &rdata
);
3225 if (rdata
.length
< 4)
3226 return (ISC_R_SUCCESS
);
3228 isc_buffer_init(&optbuf
, rdata
.data
, rdata
.length
);
3229 isc_buffer_add(&optbuf
, rdata
.length
);
3230 optcode
= isc_buffer_getuint16(&optbuf
);
3231 optlen
= isc_buffer_getuint16(&optbuf
);
3233 if (optcode
== DNS_OPT_NSID
) {
3234 ADD_STRING(target
, "; NSID");
3236 ADD_STRING(target
, "; OPT=");
3237 sprintf(buf
, "%u", optcode
);
3238 ADD_STRING(target
, buf
);
3243 ADD_STRING(target
, ": ");
3245 optdata
= rdata
.data
+ 4;
3246 for (i
= 0; i
< optlen
; i
++) {
3247 sprintf(buf
, "%02x ", optdata
[i
]);
3248 ADD_STRING(target
, buf
);
3250 for (i
= 0; i
< optlen
; i
++) {
3251 ADD_STRING(target
, " (");
3252 if (isprint(optdata
[i
]))
3253 isc_buffer_putmem(target
, &optdata
[i
],
3256 isc_buffer_putstr(target
, ".");
3257 ADD_STRING(target
, ")");
3260 ADD_STRING(target
, "\n");
3261 return (ISC_R_SUCCESS
);
3262 case DNS_PSEUDOSECTION_TSIG
:
3263 ps
= dns_message_gettsig(msg
, &name
);
3265 return (ISC_R_SUCCESS
);
3266 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3267 ADD_STRING(target
, ";; TSIG PSEUDOSECTION:\n");
3268 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3269 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3270 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3271 ADD_STRING(target
, "\n");
3273 case DNS_PSEUDOSECTION_SIG0
:
3274 ps
= dns_message_getsig0(msg
, &name
);
3276 return (ISC_R_SUCCESS
);
3277 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3278 ADD_STRING(target
, ";; SIG0 PSEUDOSECTION:\n");
3279 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3280 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3281 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3282 ADD_STRING(target
, "\n");
3285 return (ISC_R_UNEXPECTED
);
3289 dns_message_totext(dns_message_t
*msg
, const dns_master_style_t
*style
,
3290 dns_messagetextflag_t flags
, isc_buffer_t
*target
) {
3291 char buf
[sizeof("1234567890")];
3292 isc_result_t result
;
3294 REQUIRE(DNS_MESSAGE_VALID(msg
));
3295 REQUIRE(target
!= NULL
);
3297 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0) {
3298 ADD_STRING(target
, ";; ->>HEADER<<- opcode: ");
3299 ADD_STRING(target
, opcodetext
[msg
->opcode
]);
3300 ADD_STRING(target
, ", status: ");
3301 if (msg
->rcode
< (sizeof(rcodetext
)/sizeof(rcodetext
[0]))) {
3302 ADD_STRING(target
, rcodetext
[msg
->rcode
]);
3304 snprintf(buf
, sizeof(buf
), "%4u", msg
->rcode
);
3305 ADD_STRING(target
, buf
);
3307 ADD_STRING(target
, ", id: ");
3308 snprintf(buf
, sizeof(buf
), "%6u", msg
->id
);
3309 ADD_STRING(target
, buf
);
3310 ADD_STRING(target
, "\n;; flags: ");
3311 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) != 0)
3312 ADD_STRING(target
, "qr ");
3313 if ((msg
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3314 ADD_STRING(target
, "aa ");
3315 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
3316 ADD_STRING(target
, "tc ");
3317 if ((msg
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3318 ADD_STRING(target
, "rd ");
3319 if ((msg
->flags
& DNS_MESSAGEFLAG_RA
) != 0)
3320 ADD_STRING(target
, "ra ");
3321 if ((msg
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
3322 ADD_STRING(target
, "ad ");
3323 if ((msg
->flags
& DNS_MESSAGEFLAG_CD
) != 0)
3324 ADD_STRING(target
, "cd ");
3325 if (msg
->opcode
!= dns_opcode_update
) {
3326 ADD_STRING(target
, "; QUESTION: ");
3328 ADD_STRING(target
, "; ZONE: ");
3330 snprintf(buf
, sizeof(buf
), "%1u",
3331 msg
->counts
[DNS_SECTION_QUESTION
]);
3332 ADD_STRING(target
, buf
);
3333 if (msg
->opcode
!= dns_opcode_update
) {
3334 ADD_STRING(target
, ", ANSWER: ");
3336 ADD_STRING(target
, ", PREREQ: ");
3338 snprintf(buf
, sizeof(buf
), "%1u",
3339 msg
->counts
[DNS_SECTION_ANSWER
]);
3340 ADD_STRING(target
, buf
);
3341 if (msg
->opcode
!= dns_opcode_update
) {
3342 ADD_STRING(target
, ", AUTHORITY: ");
3344 ADD_STRING(target
, ", UPDATE: ");
3346 snprintf(buf
, sizeof(buf
), "%1u",
3347 msg
->counts
[DNS_SECTION_AUTHORITY
]);
3348 ADD_STRING(target
, buf
);
3349 ADD_STRING(target
, ", ADDITIONAL: ");
3350 snprintf(buf
, sizeof(buf
), "%1u",
3351 msg
->counts
[DNS_SECTION_ADDITIONAL
]);
3352 ADD_STRING(target
, buf
);
3353 ADD_STRING(target
, "\n");
3355 result
= dns_message_pseudosectiontotext(msg
,
3356 DNS_PSEUDOSECTION_OPT
,
3357 style
, flags
, target
);
3358 if (result
!= ISC_R_SUCCESS
)
3361 result
= dns_message_sectiontotext(msg
, DNS_SECTION_QUESTION
,
3362 style
, flags
, target
);
3363 if (result
!= ISC_R_SUCCESS
)
3365 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ANSWER
,
3366 style
, flags
, target
);
3367 if (result
!= ISC_R_SUCCESS
)
3369 result
= dns_message_sectiontotext(msg
, DNS_SECTION_AUTHORITY
,
3370 style
, flags
, target
);
3371 if (result
!= ISC_R_SUCCESS
)
3373 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ADDITIONAL
,
3374 style
, flags
, target
);
3375 if (result
!= ISC_R_SUCCESS
)
3378 result
= dns_message_pseudosectiontotext(msg
,
3379 DNS_PSEUDOSECTION_TSIG
,
3380 style
, flags
, target
);
3381 if (result
!= ISC_R_SUCCESS
)
3384 result
= dns_message_pseudosectiontotext(msg
,
3385 DNS_PSEUDOSECTION_SIG0
,
3386 style
, flags
, target
);
3387 if (result
!= ISC_R_SUCCESS
)
3390 return (ISC_R_SUCCESS
);
3394 dns_message_getrawmessage(dns_message_t
*msg
) {
3395 REQUIRE(DNS_MESSAGE_VALID(msg
));
3396 return (&msg
->saved
);
3400 dns_message_setsortorder(dns_message_t
*msg
, dns_rdatasetorderfunc_t order
,
3401 const void *order_arg
)
3403 REQUIRE(DNS_MESSAGE_VALID(msg
));
3405 msg
->order_arg
= order_arg
;
3409 dns_message_settimeadjust(dns_message_t
*msg
, int timeadjust
) {
3410 REQUIRE(DNS_MESSAGE_VALID(msg
));
3411 msg
->timeadjust
= timeadjust
;
3415 dns_message_gettimeadjust(dns_message_t
*msg
) {
3416 REQUIRE(DNS_MESSAGE_VALID(msg
));
3417 return (msg
->timeadjust
);
3421 dns_opcode_totext(dns_opcode_t opcode
, isc_buffer_t
*target
) {
3423 REQUIRE(opcode
< 16);
3425 if (isc_buffer_availablelength(target
) < strlen(opcodetext
[opcode
]))
3426 return (ISC_R_NOSPACE
);
3427 isc_buffer_putstr(target
, opcodetext
[opcode
]);
3428 return (ISC_R_SUCCESS
);