2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: message.c,v 1.194.2.10.2.24 2006/02/28 06:32:54 marka Exp $ */
26 #include <isc/buffer.h>
28 #include <isc/print.h>
29 #include <isc/string.h> /* Required for HP/UX (and others?) */
32 #include <dns/dnssec.h>
33 #include <dns/keyvalues.h>
35 #include <dns/masterdump.h>
36 #include <dns/message.h>
37 #include <dns/opcode.h>
38 #include <dns/rdata.h>
39 #include <dns/rdatalist.h>
40 #include <dns/rdataset.h>
41 #include <dns/rdatastruct.h>
42 #include <dns/result.h>
46 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
47 #define DNS_MESSAGE_OPCODE_SHIFT 11
48 #define DNS_MESSAGE_RCODE_MASK 0x000fU
49 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
50 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
51 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
52 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
53 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
55 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
56 && ((s) < DNS_SECTION_MAX))
57 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
58 && ((s) < DNS_SECTION_MAX))
59 #define ADD_STRING(b, s) {if (strlen(s) >= \
60 isc_buffer_availablelength(b)) \
61 return(ISC_R_NOSPACE); else \
62 isc_buffer_putstr(b, s);}
63 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
64 && ((s) < DNS_PSEUDOSECTION_MAX))
67 * This is the size of each individual scratchpad buffer, and the numbers
68 * of various block allocations used within the server.
69 * XXXMLG These should come from a config setting.
71 #define SCRATCHPAD_SIZE 512
73 #define OFFSET_COUNT 4
75 #define RDATALIST_COUNT 8
76 #define RDATASET_COUNT RDATALIST_COUNT
79 * Text representation of the different items, for message_totext
82 static const char *sectiontext
[] = {
89 static const char *updsectiontext
[] = {
96 static const char *opcodetext
[] = {
115 static const char *rcodetext
[] = {
137 * "helper" type, which consists of a block of some type, and is linkable.
138 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
139 * size, or the allocated elements will not be alligned correctly.
141 struct dns_msgblock
{
143 unsigned int remaining
;
144 ISC_LINK(dns_msgblock_t
) link
;
145 }; /* dynamically sized */
147 static inline dns_msgblock_t
*
148 msgblock_allocate(isc_mem_t
*, unsigned int, unsigned int);
150 #define msgblock_get(block, type) \
151 ((type *)msgblock_internalget(block, sizeof(type)))
154 msgblock_internalget(dns_msgblock_t
*, unsigned int);
157 msgblock_reset(dns_msgblock_t
*);
160 msgblock_free(isc_mem_t
*, dns_msgblock_t
*, unsigned int);
163 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
164 * is free, return NULL.
166 static inline dns_msgblock_t
*
167 msgblock_allocate(isc_mem_t
*mctx
, unsigned int sizeof_type
,
170 dns_msgblock_t
*block
;
173 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* count
);
175 block
= isc_mem_get(mctx
, length
);
179 block
->count
= count
;
180 block
->remaining
= count
;
182 ISC_LINK_INIT(block
, link
);
188 * Return an element from the msgblock. If no more are available, return
192 msgblock_internalget(dns_msgblock_t
*block
, unsigned int sizeof_type
) {
195 if (block
== NULL
|| block
->remaining
== 0)
200 ptr
= (((unsigned char *)block
)
201 + sizeof(dns_msgblock_t
)
202 + (sizeof_type
* block
->remaining
));
208 msgblock_reset(dns_msgblock_t
*block
) {
209 block
->remaining
= block
->count
;
213 * Release memory associated with a message block.
216 msgblock_free(isc_mem_t
*mctx
, dns_msgblock_t
*block
, unsigned int sizeof_type
)
220 length
= sizeof(dns_msgblock_t
) + (sizeof_type
* block
->count
);
222 isc_mem_put(mctx
, block
, length
);
226 * Allocate a new dynamic buffer, and attach it to this message as the
227 * "current" buffer. (which is always the last on the list, for our
230 static inline isc_result_t
231 newbuffer(dns_message_t
*msg
, unsigned int size
) {
233 isc_buffer_t
*dynbuf
;
236 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, size
);
237 if (result
!= ISC_R_SUCCESS
)
238 return (ISC_R_NOMEMORY
);
240 ISC_LIST_APPEND(msg
->scratchpad
, dynbuf
, link
);
241 return (ISC_R_SUCCESS
);
244 static inline isc_buffer_t
*
245 currentbuffer(dns_message_t
*msg
) {
246 isc_buffer_t
*dynbuf
;
248 dynbuf
= ISC_LIST_TAIL(msg
->scratchpad
);
249 INSIST(dynbuf
!= NULL
);
255 releaserdata(dns_message_t
*msg
, dns_rdata_t
*rdata
) {
256 ISC_LIST_PREPEND(msg
->freerdata
, rdata
, link
);
259 static inline dns_rdata_t
*
260 newrdata(dns_message_t
*msg
) {
261 dns_msgblock_t
*msgblock
;
264 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
266 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
270 msgblock
= ISC_LIST_TAIL(msg
->rdatas
);
271 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
273 msgblock
= msgblock_allocate(msg
->mctx
, sizeof(dns_rdata_t
),
275 if (msgblock
== NULL
)
278 ISC_LIST_APPEND(msg
->rdatas
, msgblock
, link
);
280 rdata
= msgblock_get(msgblock
, dns_rdata_t
);
283 dns_rdata_init(rdata
);
288 releaserdatalist(dns_message_t
*msg
, dns_rdatalist_t
*rdatalist
) {
289 ISC_LIST_PREPEND(msg
->freerdatalist
, rdatalist
, link
);
292 static inline dns_rdatalist_t
*
293 newrdatalist(dns_message_t
*msg
) {
294 dns_msgblock_t
*msgblock
;
295 dns_rdatalist_t
*rdatalist
;
297 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
298 if (rdatalist
!= NULL
) {
299 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
303 msgblock
= ISC_LIST_TAIL(msg
->rdatalists
);
304 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
305 if (rdatalist
== NULL
) {
306 msgblock
= msgblock_allocate(msg
->mctx
,
307 sizeof(dns_rdatalist_t
),
309 if (msgblock
== NULL
)
312 ISC_LIST_APPEND(msg
->rdatalists
, msgblock
, link
);
314 rdatalist
= msgblock_get(msgblock
, dns_rdatalist_t
);
320 static inline dns_offsets_t
*
321 newoffsets(dns_message_t
*msg
) {
322 dns_msgblock_t
*msgblock
;
323 dns_offsets_t
*offsets
;
325 msgblock
= ISC_LIST_TAIL(msg
->offsets
);
326 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
327 if (offsets
== NULL
) {
328 msgblock
= msgblock_allocate(msg
->mctx
,
329 sizeof(dns_offsets_t
),
331 if (msgblock
== NULL
)
334 ISC_LIST_APPEND(msg
->offsets
, msgblock
, link
);
336 offsets
= msgblock_get(msgblock
, dns_offsets_t
);
343 msginitheader(dns_message_t
*m
) {
352 msginitprivate(dns_message_t
*m
) {
355 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
356 m
->cursors
[i
] = NULL
;
364 m
->state
= DNS_SECTION_ANY
; /* indicate nothing parsed or rendered */
372 msginittsig(dns_message_t
*m
) {
373 m
->tsigstatus
= dns_rcode_noerror
;
374 m
->querytsigstatus
= dns_rcode_noerror
;
379 m
->sig0status
= dns_rcode_noerror
;
384 * Init elements to default state. Used both when allocating a new element
385 * and when resetting one.
388 msginit(dns_message_t
*m
) {
394 m
->tcp_continuation
= 0;
396 m
->verify_attempted
= 0;
399 m
->query
.base
= NULL
;
402 m
->saved
.base
= NULL
;
409 msgresetnames(dns_message_t
*msg
, unsigned int first_section
) {
411 dns_name_t
*name
, *next_name
;
412 dns_rdataset_t
*rds
, *next_rds
;
415 * Clean up name lists by calling the rdataset disassociate function.
417 for (i
= first_section
; i
< DNS_SECTION_MAX
; i
++) {
418 name
= ISC_LIST_HEAD(msg
->sections
[i
]);
419 while (name
!= NULL
) {
420 next_name
= ISC_LIST_NEXT(name
, link
);
421 ISC_LIST_UNLINK(msg
->sections
[i
], name
, link
);
423 rds
= ISC_LIST_HEAD(name
->list
);
424 while (rds
!= NULL
) {
425 next_rds
= ISC_LIST_NEXT(rds
, link
);
426 ISC_LIST_UNLINK(name
->list
, rds
, link
);
428 INSIST(dns_rdataset_isassociated(rds
));
429 dns_rdataset_disassociate(rds
);
430 isc_mempool_put(msg
->rdspool
, rds
);
433 if (dns_name_dynamic(name
))
434 dns_name_free(name
, msg
->mctx
);
435 isc_mempool_put(msg
->namepool
, name
);
442 msgresetopt(dns_message_t
*msg
)
444 if (msg
->opt
!= NULL
) {
445 if (msg
->opt_reserved
> 0) {
446 dns_message_renderrelease(msg
, msg
->opt_reserved
);
447 msg
->opt_reserved
= 0;
449 INSIST(dns_rdataset_isassociated(msg
->opt
));
450 dns_rdataset_disassociate(msg
->opt
);
451 isc_mempool_put(msg
->rdspool
, msg
->opt
);
457 msgresetsigs(dns_message_t
*msg
, isc_boolean_t replying
) {
458 if (msg
->sig_reserved
> 0) {
459 dns_message_renderrelease(msg
, msg
->sig_reserved
);
460 msg
->sig_reserved
= 0;
462 if (msg
->tsig
!= NULL
) {
463 INSIST(dns_rdataset_isassociated(msg
->tsig
));
464 INSIST(msg
->namepool
!= NULL
);
466 INSIST(msg
->querytsig
== NULL
);
467 msg
->querytsig
= msg
->tsig
;
469 dns_rdataset_disassociate(msg
->tsig
);
470 isc_mempool_put(msg
->rdspool
, msg
->tsig
);
471 if (msg
->querytsig
!= NULL
) {
472 dns_rdataset_disassociate(msg
->querytsig
);
473 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
476 if (dns_name_dynamic(msg
->tsigname
))
477 dns_name_free(msg
->tsigname
, msg
->mctx
);
478 isc_mempool_put(msg
->namepool
, msg
->tsigname
);
480 msg
->tsigname
= NULL
;
481 } else if (msg
->querytsig
!= NULL
&& !replying
) {
482 dns_rdataset_disassociate(msg
->querytsig
);
483 isc_mempool_put(msg
->rdspool
, msg
->querytsig
);
484 msg
->querytsig
= NULL
;
486 if (msg
->sig0
!= NULL
) {
487 INSIST(dns_rdataset_isassociated(msg
->sig0
));
488 dns_rdataset_disassociate(msg
->sig0
);
489 isc_mempool_put(msg
->rdspool
, msg
->sig0
);
490 if (msg
->sig0name
!= NULL
) {
491 if (dns_name_dynamic(msg
->sig0name
))
492 dns_name_free(msg
->sig0name
, msg
->mctx
);
493 isc_mempool_put(msg
->namepool
, msg
->sig0name
);
496 msg
->sig0name
= NULL
;
501 * Free all but one (or everything) for this message. This is used by
502 * both dns_message_reset() and dns_message_destroy().
505 msgreset(dns_message_t
*msg
, isc_boolean_t everything
) {
506 dns_msgblock_t
*msgblock
, *next_msgblock
;
507 isc_buffer_t
*dynbuf
, *next_dynbuf
;
509 dns_rdatalist_t
*rdatalist
;
511 msgresetnames(msg
, 0);
513 msgresetsigs(msg
, ISC_FALSE
);
516 * Clean up linked lists.
520 * Run through the free lists, and just unlink anything found there.
521 * The memory isn't lost since these are part of message blocks we
524 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
525 while (rdata
!= NULL
) {
526 ISC_LIST_UNLINK(msg
->freerdata
, rdata
, link
);
527 rdata
= ISC_LIST_HEAD(msg
->freerdata
);
529 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
530 while (rdatalist
!= NULL
) {
531 ISC_LIST_UNLINK(msg
->freerdatalist
, rdatalist
, link
);
532 rdatalist
= ISC_LIST_HEAD(msg
->freerdatalist
);
535 dynbuf
= ISC_LIST_HEAD(msg
->scratchpad
);
536 INSIST(dynbuf
!= NULL
);
538 isc_buffer_clear(dynbuf
);
539 dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
541 while (dynbuf
!= NULL
) {
542 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
543 ISC_LIST_UNLINK(msg
->scratchpad
, dynbuf
, link
);
544 isc_buffer_free(&dynbuf
);
545 dynbuf
= next_dynbuf
;
548 msgblock
= ISC_LIST_HEAD(msg
->rdatas
);
549 if (!everything
&& msgblock
!= NULL
) {
550 msgblock_reset(msgblock
);
551 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
553 while (msgblock
!= NULL
) {
554 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
555 ISC_LIST_UNLINK(msg
->rdatas
, msgblock
, link
);
556 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdata_t
));
557 msgblock
= next_msgblock
;
561 * rdatalists could be empty.
564 msgblock
= ISC_LIST_HEAD(msg
->rdatalists
);
565 if (!everything
&& msgblock
!= NULL
) {
566 msgblock_reset(msgblock
);
567 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
569 while (msgblock
!= NULL
) {
570 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
571 ISC_LIST_UNLINK(msg
->rdatalists
, msgblock
, link
);
572 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_rdatalist_t
));
573 msgblock
= next_msgblock
;
576 msgblock
= ISC_LIST_HEAD(msg
->offsets
);
577 if (!everything
&& msgblock
!= NULL
) {
578 msgblock_reset(msgblock
);
579 msgblock
= ISC_LIST_NEXT(msgblock
, link
);
581 while (msgblock
!= NULL
) {
582 next_msgblock
= ISC_LIST_NEXT(msgblock
, link
);
583 ISC_LIST_UNLINK(msg
->offsets
, msgblock
, link
);
584 msgblock_free(msg
->mctx
, msgblock
, sizeof(dns_offsets_t
));
585 msgblock
= next_msgblock
;
588 if (msg
->tsigkey
!= NULL
) {
589 dns_tsigkey_detach(&msg
->tsigkey
);
593 if (msg
->query
.base
!= NULL
) {
594 if (msg
->free_query
!= 0)
595 isc_mem_put(msg
->mctx
, msg
->query
.base
,
597 msg
->query
.base
= NULL
;
598 msg
->query
.length
= 0;
601 if (msg
->saved
.base
!= NULL
) {
602 if (msg
->free_saved
!= 0)
603 isc_mem_put(msg
->mctx
, msg
->saved
.base
,
605 msg
->saved
.base
= NULL
;
606 msg
->saved
.length
= 0;
610 * cleanup the buffer cleanup list
612 dynbuf
= ISC_LIST_HEAD(msg
->cleanup
);
613 while (dynbuf
!= NULL
) {
614 next_dynbuf
= ISC_LIST_NEXT(dynbuf
, link
);
615 ISC_LIST_UNLINK(msg
->cleanup
, dynbuf
, link
);
616 isc_buffer_free(&dynbuf
);
617 dynbuf
= next_dynbuf
;
621 * Set other bits to normal default values.
626 ENSURE(isc_mempool_getallocated(msg
->namepool
) == 0);
627 ENSURE(isc_mempool_getallocated(msg
->rdspool
) == 0);
631 spacefortsig(dns_tsigkey_t
*key
, int otherlen
) {
637 * The space required for an TSIG record is:
639 * n1 bytes for the name
640 * 2 bytes for the type
641 * 2 bytes for the class
642 * 4 bytes for the ttl
643 * 2 bytes for the rdlength
644 * n2 bytes for the algorithm name
645 * 6 bytes for the time signed
646 * 2 bytes for the fudge
647 * 2 bytes for the MAC size
648 * x bytes for the MAC
649 * 2 bytes for the original id
650 * 2 bytes for the error
651 * 2 bytes for the other data length
652 * y bytes for the other data (at most)
653 * ---------------------------------
654 * 26 + n1 + n2 + x + y bytes
657 dns_name_toregion(&key
->name
, &r1
);
658 dns_name_toregion(key
->algorithm
, &r2
);
659 if (key
->key
== NULL
)
662 result
= dst_key_sigsize(key
->key
, &x
);
663 if (result
!= ISC_R_SUCCESS
)
666 return (26 + r1
.length
+ r2
.length
+ x
+ otherlen
);
670 dns_message_create(isc_mem_t
*mctx
, unsigned int intent
, dns_message_t
**msgp
)
674 isc_buffer_t
*dynbuf
;
677 REQUIRE(mctx
!= NULL
);
678 REQUIRE(msgp
!= NULL
);
679 REQUIRE(*msgp
== NULL
);
680 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
681 || intent
== DNS_MESSAGE_INTENTRENDER
);
683 m
= isc_mem_get(mctx
, sizeof(dns_message_t
));
685 return (ISC_R_NOMEMORY
);
688 * No allocations until further notice. Just initialize all lists
689 * and other members that are freed in the cleanup phase here.
692 m
->magic
= DNS_MESSAGE_MAGIC
;
693 m
->from_to_wire
= intent
;
696 for (i
= 0; i
< DNS_SECTION_MAX
; i
++)
697 ISC_LIST_INIT(m
->sections
[i
]);
700 ISC_LIST_INIT(m
->scratchpad
);
701 ISC_LIST_INIT(m
->cleanup
);
704 ISC_LIST_INIT(m
->rdatas
);
705 ISC_LIST_INIT(m
->rdatalists
);
706 ISC_LIST_INIT(m
->offsets
);
707 ISC_LIST_INIT(m
->freerdata
);
708 ISC_LIST_INIT(m
->freerdatalist
);
711 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
714 result
= isc_mempool_create(m
->mctx
, sizeof(dns_name_t
), &m
->namepool
);
715 if (result
!= ISC_R_SUCCESS
)
717 isc_mempool_setfreemax(m
->namepool
, NAME_COUNT
);
718 isc_mempool_setname(m
->namepool
, "msg:names");
720 result
= isc_mempool_create(m
->mctx
, sizeof(dns_rdataset_t
),
722 if (result
!= ISC_R_SUCCESS
)
724 isc_mempool_setfreemax(m
->rdspool
, NAME_COUNT
);
725 isc_mempool_setname(m
->rdspool
, "msg:rdataset");
728 result
= isc_buffer_allocate(mctx
, &dynbuf
, SCRATCHPAD_SIZE
);
729 if (result
!= ISC_R_SUCCESS
)
731 ISC_LIST_APPEND(m
->scratchpad
, dynbuf
, link
);
736 return (ISC_R_SUCCESS
);
739 * Cleanup for error returns.
742 dynbuf
= ISC_LIST_HEAD(m
->scratchpad
);
743 if (dynbuf
!= NULL
) {
744 ISC_LIST_UNLINK(m
->scratchpad
, dynbuf
, link
);
745 isc_buffer_free(&dynbuf
);
747 if (m
->namepool
!= NULL
)
748 isc_mempool_destroy(&m
->namepool
);
749 if (m
->rdspool
!= NULL
)
750 isc_mempool_destroy(&m
->rdspool
);
752 isc_mem_put(mctx
, m
, sizeof(dns_message_t
));
754 return (ISC_R_NOMEMORY
);
758 dns_message_reset(dns_message_t
*msg
, unsigned int intent
) {
759 REQUIRE(DNS_MESSAGE_VALID(msg
));
760 REQUIRE(intent
== DNS_MESSAGE_INTENTPARSE
761 || intent
== DNS_MESSAGE_INTENTRENDER
);
763 msgreset(msg
, ISC_FALSE
);
764 msg
->from_to_wire
= intent
;
768 dns_message_destroy(dns_message_t
**msgp
) {
771 REQUIRE(msgp
!= NULL
);
772 REQUIRE(DNS_MESSAGE_VALID(*msgp
));
777 msgreset(msg
, ISC_TRUE
);
778 isc_mempool_destroy(&msg
->namepool
);
779 isc_mempool_destroy(&msg
->rdspool
);
781 isc_mem_put(msg
->mctx
, msg
, sizeof(dns_message_t
));
785 findname(dns_name_t
**foundname
, dns_name_t
*target
,
786 dns_namelist_t
*section
)
790 for (curr
= ISC_LIST_TAIL(*section
);
792 curr
= ISC_LIST_PREV(curr
, link
)) {
793 if (dns_name_equal(curr
, target
)) {
794 if (foundname
!= NULL
)
796 return (ISC_R_SUCCESS
);
800 return (ISC_R_NOTFOUND
);
804 dns_message_find(dns_name_t
*name
, dns_rdataclass_t rdclass
,
805 dns_rdatatype_t type
, dns_rdatatype_t covers
,
806 dns_rdataset_t
**rdataset
)
808 dns_rdataset_t
*curr
;
810 if (rdataset
!= NULL
) {
811 REQUIRE(*rdataset
== NULL
);
814 for (curr
= ISC_LIST_TAIL(name
->list
);
816 curr
= ISC_LIST_PREV(curr
, link
)) {
817 if (curr
->rdclass
== rdclass
&&
818 curr
->type
== type
&& curr
->covers
== covers
) {
819 if (rdataset
!= NULL
)
821 return (ISC_R_SUCCESS
);
825 return (ISC_R_NOTFOUND
);
829 dns_message_findtype(dns_name_t
*name
, dns_rdatatype_t type
,
830 dns_rdatatype_t covers
, dns_rdataset_t
**rdataset
)
832 dns_rdataset_t
*curr
;
834 REQUIRE(name
!= NULL
);
835 if (rdataset
!= NULL
) {
836 REQUIRE(*rdataset
== NULL
);
839 for (curr
= ISC_LIST_TAIL(name
->list
);
841 curr
= ISC_LIST_PREV(curr
, link
)) {
842 if (curr
->type
== type
&& curr
->covers
== covers
) {
843 if (rdataset
!= NULL
)
845 return (ISC_R_SUCCESS
);
849 return (ISC_R_NOTFOUND
);
853 * Read a name from buffer "source".
856 getname(dns_name_t
*name
, isc_buffer_t
*source
, dns_message_t
*msg
,
857 dns_decompress_t
*dctx
)
859 isc_buffer_t
*scratch
;
863 scratch
= currentbuffer(msg
);
866 * First try: use current buffer.
867 * Second try: allocate a new buffer and use that.
871 result
= dns_name_fromwire(name
, source
, dctx
, ISC_FALSE
,
874 if (result
== ISC_R_NOSPACE
) {
877 result
= newbuffer(msg
, SCRATCHPAD_SIZE
);
878 if (result
!= ISC_R_SUCCESS
)
881 scratch
= currentbuffer(msg
);
882 dns_name_reset(name
);
888 INSIST(0); /* Cannot get here... */
889 return (ISC_R_UNEXPECTED
);
893 getrdata(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
894 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
,
895 unsigned int rdatalen
, dns_rdata_t
*rdata
)
897 isc_buffer_t
*scratch
;
900 unsigned int trysize
;
902 scratch
= currentbuffer(msg
);
904 isc_buffer_setactive(source
, rdatalen
);
907 * First try: use current buffer.
908 * Second try: allocate a new buffer of size
909 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
910 * (the data will fit if it was not more than 50% compressed)
911 * Subsequent tries: double buffer size on each try.
915 /* XXX possibly change this to a while (tries < 2) loop */
917 result
= dns_rdata_fromwire(rdata
, rdclass
, rdtype
,
921 if (result
== ISC_R_NOSPACE
) {
923 trysize
= 2 * rdatalen
;
924 if (trysize
< SCRATCHPAD_SIZE
)
925 trysize
= SCRATCHPAD_SIZE
;
927 INSIST(trysize
!= 0);
928 if (trysize
>= 65535)
929 return (ISC_R_NOSPACE
);
930 /* XXX DNS_R_RRTOOLONG? */
934 result
= newbuffer(msg
, trysize
);
935 if (result
!= ISC_R_SUCCESS
)
938 scratch
= currentbuffer(msg
);
948 seen_problem = ISC_TRUE; \
950 result = DNS_R_FORMERR; \
956 getquestions(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
957 unsigned int options
)
963 dns_offsets_t
*offsets
;
964 dns_rdataset_t
*rdataset
;
965 dns_rdatalist_t
*rdatalist
;
967 dns_rdatatype_t rdtype
;
968 dns_rdataclass_t rdclass
;
969 dns_namelist_t
*section
;
970 isc_boolean_t free_name
;
971 isc_boolean_t best_effort
;
972 isc_boolean_t seen_problem
;
974 section
= &msg
->sections
[DNS_SECTION_QUESTION
];
976 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
977 seen_problem
= ISC_FALSE
;
983 for (count
= 0; count
< msg
->counts
[DNS_SECTION_QUESTION
]; count
++) {
984 name
= isc_mempool_get(msg
->namepool
);
986 return (ISC_R_NOMEMORY
);
987 free_name
= ISC_TRUE
;
989 offsets
= newoffsets(msg
);
990 if (offsets
== NULL
) {
991 result
= ISC_R_NOMEMORY
;
994 dns_name_init(name
, *offsets
);
997 * Parse the name out of this packet.
999 isc_buffer_remainingregion(source
, &r
);
1000 isc_buffer_setactive(source
, r
.length
);
1001 result
= getname(name
, source
, msg
, dctx
);
1002 if (result
!= ISC_R_SUCCESS
)
1006 * Run through the section, looking to see if this name
1007 * is already there. If it is found, put back the allocated
1008 * name since we no longer need it, and set our name pointer
1009 * to point to the name we found.
1011 result
= findname(&name2
, name
, section
);
1014 * If it is the first name in the section, accept it.
1016 * If it is not, but is not the same as the name already
1017 * in the question section, append to the section. Note that
1018 * here in the question section this is illegal, so return
1019 * FORMERR. In the future, check the opcode to see if
1020 * this should be legal or not. In either case we no longer
1021 * need this name pointer.
1023 if (result
!= ISC_R_SUCCESS
) {
1024 if (!ISC_LIST_EMPTY(*section
))
1026 ISC_LIST_APPEND(*section
, name
, link
);
1027 free_name
= ISC_FALSE
;
1029 isc_mempool_put(msg
->namepool
, name
);
1032 free_name
= ISC_FALSE
;
1036 * Get type and class.
1038 isc_buffer_remainingregion(source
, &r
);
1040 result
= ISC_R_UNEXPECTEDEND
;
1043 rdtype
= isc_buffer_getuint16(source
);
1044 rdclass
= isc_buffer_getuint16(source
);
1047 * If this class is different than the one we already read,
1050 if (msg
->state
== DNS_SECTION_ANY
) {
1051 msg
->state
= DNS_SECTION_QUESTION
;
1052 msg
->rdclass
= rdclass
;
1053 } else if (msg
->rdclass
!= rdclass
)
1057 * Can't ask the same question twice.
1059 result
= dns_message_find(name
, rdclass
, rdtype
, 0, NULL
);
1060 if (result
== ISC_R_SUCCESS
)
1064 * Allocate a new rdatalist.
1066 rdatalist
= newrdatalist(msg
);
1067 if (rdatalist
== NULL
) {
1068 result
= ISC_R_NOMEMORY
;
1071 rdataset
= isc_mempool_get(msg
->rdspool
);
1072 if (rdataset
== NULL
) {
1073 result
= ISC_R_NOMEMORY
;
1078 * Convert rdatalist to rdataset, and attach the latter to
1081 rdatalist
->type
= rdtype
;
1082 rdatalist
->covers
= 0;
1083 rdatalist
->rdclass
= rdclass
;
1085 ISC_LIST_INIT(rdatalist
->rdata
);
1087 dns_rdataset_init(rdataset
);
1088 result
= dns_rdatalist_tordataset(rdatalist
, rdataset
);
1089 if (result
!= ISC_R_SUCCESS
)
1092 rdataset
->attributes
|= DNS_RDATASETATTR_QUESTION
;
1094 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1099 return (DNS_R_RECOVERABLE
);
1100 return (ISC_R_SUCCESS
);
1103 if (rdataset
!= NULL
) {
1104 INSIST(!dns_rdataset_isassociated(rdataset
));
1105 isc_mempool_put(msg
->rdspool
, rdataset
);
1108 if (rdatalist
!= NULL
)
1109 isc_mempool_put(msg
->rdlpool
, rdatalist
);
1112 isc_mempool_put(msg
->namepool
, name
);
1117 static isc_boolean_t
1118 update(dns_section_t section
, dns_rdataclass_t rdclass
) {
1119 if (section
== DNS_SECTION_PREREQUISITE
)
1120 return (ISC_TF(rdclass
== dns_rdataclass_any
||
1121 rdclass
== dns_rdataclass_none
));
1122 if (section
== DNS_SECTION_UPDATE
)
1123 return (ISC_TF(rdclass
== dns_rdataclass_any
));
1128 getsection(isc_buffer_t
*source
, dns_message_t
*msg
, dns_decompress_t
*dctx
,
1129 dns_section_t sectionid
, unsigned int options
)
1132 unsigned int count
, rdatalen
;
1135 dns_offsets_t
*offsets
;
1136 dns_rdataset_t
*rdataset
;
1137 dns_rdatalist_t
*rdatalist
;
1138 isc_result_t result
;
1139 dns_rdatatype_t rdtype
, covers
;
1140 dns_rdataclass_t rdclass
;
1143 dns_namelist_t
*section
;
1144 isc_boolean_t free_name
, free_rdataset
;
1145 isc_boolean_t preserve_order
, best_effort
, seen_problem
;
1146 isc_boolean_t issigzero
;
1148 preserve_order
= ISC_TF(options
& DNS_MESSAGEPARSE_PRESERVEORDER
);
1149 best_effort
= ISC_TF(options
& DNS_MESSAGEPARSE_BESTEFFORT
);
1150 seen_problem
= ISC_FALSE
;
1152 for (count
= 0; count
< msg
->counts
[sectionid
]; count
++) {
1153 int recstart
= source
->current
;
1154 isc_boolean_t skip_name_search
, skip_type_search
;
1156 section
= &msg
->sections
[sectionid
];
1158 skip_name_search
= ISC_FALSE
;
1159 skip_type_search
= ISC_FALSE
;
1160 free_name
= ISC_FALSE
;
1161 free_rdataset
= ISC_FALSE
;
1163 name
= isc_mempool_get(msg
->namepool
);
1165 return (ISC_R_NOMEMORY
);
1166 free_name
= ISC_TRUE
;
1168 offsets
= newoffsets(msg
);
1169 if (offsets
== NULL
) {
1170 result
= ISC_R_NOMEMORY
;
1173 dns_name_init(name
, *offsets
);
1176 * Parse the name out of this packet.
1178 isc_buffer_remainingregion(source
, &r
);
1179 isc_buffer_setactive(source
, r
.length
);
1180 result
= getname(name
, source
, msg
, dctx
);
1181 if (result
!= ISC_R_SUCCESS
)
1185 * Get type, class, ttl, and rdatalen. Verify that at least
1186 * rdatalen bytes remain. (Some of this is deferred to
1189 isc_buffer_remainingregion(source
, &r
);
1190 if (r
.length
< 2 + 2 + 4 + 2) {
1191 result
= ISC_R_UNEXPECTEDEND
;
1194 rdtype
= isc_buffer_getuint16(source
);
1195 rdclass
= isc_buffer_getuint16(source
);
1198 * If there was no question section, we may not yet have
1199 * established a class. Do so now.
1201 if (msg
->state
== DNS_SECTION_ANY
&&
1202 rdtype
!= dns_rdatatype_opt
&& /* class is UDP SIZE */
1203 rdtype
!= dns_rdatatype_tsig
&& /* class is ANY */
1204 rdtype
!= dns_rdatatype_tkey
) { /* class is undefined */
1205 msg
->rdclass
= rdclass
;
1206 msg
->state
= DNS_SECTION_QUESTION
;
1210 * If this class is different than the one in the question
1213 if (msg
->opcode
!= dns_opcode_update
1214 && rdtype
!= dns_rdatatype_tsig
1215 && rdtype
!= dns_rdatatype_opt
1216 && rdtype
!= dns_rdatatype_dnskey
/* in a TKEY query */
1217 && rdtype
!= dns_rdatatype_sig
/* SIG(0) */
1218 && rdtype
!= dns_rdatatype_tkey
/* Win2000 TKEY */
1219 && msg
->rdclass
!= dns_rdataclass_any
1220 && msg
->rdclass
!= rdclass
)
1224 * Special type handling for TSIG, OPT, and TKEY.
1226 if (rdtype
== dns_rdatatype_tsig
) {
1228 * If it is a tsig, verify that it is in the
1229 * additional data section.
1231 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1232 rdclass
!= dns_rdataclass_any
||
1233 count
!= msg
->counts
[sectionid
] - 1)
1235 msg
->sigstart
= recstart
;
1236 skip_name_search
= ISC_TRUE
;
1237 skip_type_search
= ISC_TRUE
;
1238 } else if (rdtype
== dns_rdatatype_opt
) {
1240 * The name of an OPT record must be ".", it
1241 * must be in the additional data section, and
1242 * it must be the first OPT we've seen.
1244 if (!dns_name_equal(dns_rootname
, name
) ||
1247 skip_name_search
= ISC_TRUE
;
1248 skip_type_search
= ISC_TRUE
;
1249 } else if (rdtype
== dns_rdatatype_tkey
) {
1251 * A TKEY must be in the additional section if this
1252 * is a query, and the answer section if this is a
1253 * response. Unless it's a Win2000 client.
1255 * Its class is ignored.
1257 dns_section_t tkeysection
;
1259 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0)
1260 tkeysection
= DNS_SECTION_ADDITIONAL
;
1262 tkeysection
= DNS_SECTION_ANSWER
;
1263 if (sectionid
!= tkeysection
&&
1264 sectionid
!= DNS_SECTION_ANSWER
)
1269 * ... now get ttl and rdatalen, and check buffer.
1271 ttl
= isc_buffer_getuint32(source
);
1272 rdatalen
= isc_buffer_getuint16(source
);
1273 r
.length
-= (2 + 2 + 4 + 2);
1274 if (r
.length
< rdatalen
) {
1275 result
= ISC_R_UNEXPECTEDEND
;
1280 * Read the rdata from the wire format. Interpret the
1281 * rdata according to its actual class, even if it had a
1282 * DynDNS meta-class in the packet (unless this is a TSIG).
1283 * Then put the meta-class back into the finished rdata.
1285 rdata
= newrdata(msg
);
1286 if (rdata
== NULL
) {
1287 result
= ISC_R_NOMEMORY
;
1290 if (msg
->opcode
== dns_opcode_update
&&
1291 update(sectionid
, rdclass
)) {
1292 if (rdatalen
!= 0) {
1293 result
= DNS_R_FORMERR
;
1297 * When the rdata is empty, the data pointer is
1298 * never dereferenced, but it must still be non-NULL.
1299 * Casting 1 rather than "" avoids warnings about
1300 * discarding the const attribute of a string,
1301 * for compilers that would warn about such things.
1303 rdata
->data
= (unsigned char *)1;
1305 rdata
->rdclass
= rdclass
;
1306 rdata
->type
= rdtype
;
1307 rdata
->flags
= DNS_RDATA_UPDATE
;
1308 result
= ISC_R_SUCCESS
;
1310 result
= getrdata(source
, msg
, dctx
, rdclass
,
1311 rdtype
, rdatalen
, rdata
);
1312 if (result
!= ISC_R_SUCCESS
)
1314 rdata
->rdclass
= rdclass
;
1315 issigzero
= ISC_FALSE
;
1316 if (rdtype
== dns_rdatatype_rrsig
&&
1317 rdata
->flags
== 0) {
1318 covers
= dns_rdata_covers(rdata
);
1321 } else if (rdtype
== dns_rdatatype_sig
/* SIG(0) */ &&
1322 rdata
->flags
== 0) {
1323 covers
= dns_rdata_covers(rdata
);
1325 if (sectionid
!= DNS_SECTION_ADDITIONAL
||
1326 count
!= msg
->counts
[sectionid
] - 1)
1328 msg
->sigstart
= recstart
;
1329 skip_name_search
= ISC_TRUE
;
1330 skip_type_search
= ISC_TRUE
;
1331 issigzero
= ISC_TRUE
;
1337 * If we are doing a dynamic update or this is a meta-type,
1338 * don't bother searching for a name, just append this one
1339 * to the end of the message.
1341 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1343 if (rdtype
!= dns_rdatatype_opt
&&
1344 rdtype
!= dns_rdatatype_tsig
&&
1347 ISC_LIST_APPEND(*section
, name
, link
);
1348 free_name
= ISC_FALSE
;
1352 * Run through the section, looking to see if this name
1353 * is already there. If it is found, put back the
1354 * allocated name since we no longer need it, and set
1355 * our name pointer to point to the name we found.
1357 result
= findname(&name2
, name
, section
);
1360 * If it is a new name, append to the section.
1362 if (result
== ISC_R_SUCCESS
) {
1363 isc_mempool_put(msg
->namepool
, name
);
1366 ISC_LIST_APPEND(*section
, name
, link
);
1368 free_name
= ISC_FALSE
;
1372 * Search name for the particular type and class.
1373 * Skip this stage if in update mode or this is a meta-type.
1375 if (preserve_order
|| msg
->opcode
== dns_opcode_update
||
1377 result
= ISC_R_NOTFOUND
;
1380 * If this is a type that can only occur in
1381 * the question section, fail.
1383 if (dns_rdatatype_questiononly(rdtype
))
1387 result
= dns_message_find(name
, rdclass
, rdtype
,
1392 * If we found an rdataset that matches, we need to
1393 * append this rdata to that set. If we did not, we need
1394 * to create a new rdatalist, store the important bits there,
1395 * convert it to an rdataset, and link the latter to the name.
1396 * Yuck. When appending, make certain that the type isn't
1397 * a singleton type, such as SOA or CNAME.
1399 * Note that this check will be bypassed when preserving order,
1400 * the opcode is an update, or the type search is skipped.
1402 if (result
== ISC_R_SUCCESS
) {
1403 if (dns_rdatatype_issingleton(rdtype
))
1407 if (result
== ISC_R_NOTFOUND
) {
1408 rdataset
= isc_mempool_get(msg
->rdspool
);
1409 if (rdataset
== NULL
) {
1410 result
= ISC_R_NOMEMORY
;
1413 free_rdataset
= ISC_TRUE
;
1415 rdatalist
= newrdatalist(msg
);
1416 if (rdatalist
== NULL
) {
1417 result
= ISC_R_NOMEMORY
;
1421 rdatalist
->type
= rdtype
;
1422 rdatalist
->covers
= covers
;
1423 rdatalist
->rdclass
= rdclass
;
1424 rdatalist
->ttl
= ttl
;
1425 ISC_LIST_INIT(rdatalist
->rdata
);
1427 dns_rdataset_init(rdataset
);
1428 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
,
1432 if (rdtype
!= dns_rdatatype_opt
&&
1433 rdtype
!= dns_rdatatype_tsig
&&
1436 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1437 free_rdataset
= ISC_FALSE
;
1444 * Section 5.2 of RFC 2181 says we should drop
1445 * nonauthoritative rrsets where the TTLs differ, but we
1446 * currently treat them the as if they were authoritative and
1449 if (ttl
!= rdataset
->ttl
) {
1450 rdataset
->attributes
|= DNS_RDATASETATTR_TTLADJUSTED
;
1451 if (ttl
< rdataset
->ttl
)
1452 rdataset
->ttl
= ttl
;
1456 * XXXMLG Perform a totally ugly hack here to pull
1457 * the rdatalist out of the private field in the rdataset,
1458 * and append this rdata to the rdatalist's linked list
1461 rdatalist
= (dns_rdatalist_t
*)(rdataset
->private1
);
1463 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1466 * If this is an OPT record, remember it. Also, set
1467 * the extended rcode. Note that msg->opt will only be set
1468 * if best-effort parsing is enabled.
1470 if (rdtype
== dns_rdatatype_opt
&& msg
->opt
== NULL
) {
1473 msg
->opt
= rdataset
;
1475 free_rdataset
= ISC_FALSE
;
1476 ercode
= (dns_rcode_t
)
1477 ((msg
->opt
->ttl
& DNS_MESSAGE_EDNSRCODE_MASK
)
1479 msg
->rcode
|= ercode
;
1480 isc_mempool_put(msg
->namepool
, name
);
1481 free_name
= ISC_FALSE
;
1485 * If this is an SIG(0) or TSIG record, remember it. Note
1486 * that msg->sig0 or msg->tsig will only be set if best-effort
1487 * parsing is enabled.
1489 if (issigzero
&& msg
->sig0
== NULL
) {
1490 msg
->sig0
= rdataset
;
1491 msg
->sig0name
= name
;
1493 free_rdataset
= ISC_FALSE
;
1494 free_name
= ISC_FALSE
;
1495 } else if (rdtype
== dns_rdatatype_tsig
&& msg
->tsig
== NULL
) {
1496 msg
->tsig
= rdataset
;
1497 msg
->tsigname
= name
;
1499 free_rdataset
= ISC_FALSE
;
1500 free_name
= ISC_FALSE
;
1505 isc_mempool_put(msg
->namepool
, name
);
1507 isc_mempool_put(msg
->rdspool
, rdataset
);
1508 free_name
= free_rdataset
= ISC_FALSE
;
1510 INSIST(free_name
== ISC_FALSE
);
1511 INSIST(free_rdataset
== ISC_FALSE
);
1515 return (DNS_R_RECOVERABLE
);
1516 return (ISC_R_SUCCESS
);
1520 isc_mempool_put(msg
->namepool
, name
);
1522 isc_mempool_put(msg
->rdspool
, rdataset
);
1528 dns_message_parse(dns_message_t
*msg
, isc_buffer_t
*source
,
1529 unsigned int options
)
1532 dns_decompress_t dctx
;
1534 isc_uint16_t tmpflags
;
1535 isc_buffer_t origsource
;
1536 isc_boolean_t seen_problem
;
1537 isc_boolean_t ignore_tc
;
1539 REQUIRE(DNS_MESSAGE_VALID(msg
));
1540 REQUIRE(source
!= NULL
);
1541 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
1543 seen_problem
= ISC_FALSE
;
1544 ignore_tc
= ISC_TF(options
& DNS_MESSAGEPARSE_IGNORETRUNCATION
);
1546 origsource
= *source
;
1549 msg
->question_ok
= 0;
1551 isc_buffer_remainingregion(source
, &r
);
1552 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1553 return (ISC_R_UNEXPECTEDEND
);
1555 msg
->id
= isc_buffer_getuint16(source
);
1556 tmpflags
= isc_buffer_getuint16(source
);
1557 msg
->opcode
= ((tmpflags
& DNS_MESSAGE_OPCODE_MASK
)
1558 >> DNS_MESSAGE_OPCODE_SHIFT
);
1559 msg
->rcode
= (dns_rcode_t
)(tmpflags
& DNS_MESSAGE_RCODE_MASK
);
1560 msg
->flags
= (tmpflags
& DNS_MESSAGE_FLAG_MASK
);
1561 msg
->counts
[DNS_SECTION_QUESTION
] = isc_buffer_getuint16(source
);
1562 msg
->counts
[DNS_SECTION_ANSWER
] = isc_buffer_getuint16(source
);
1563 msg
->counts
[DNS_SECTION_AUTHORITY
] = isc_buffer_getuint16(source
);
1564 msg
->counts
[DNS_SECTION_ADDITIONAL
] = isc_buffer_getuint16(source
);
1571 dns_decompress_init(&dctx
, -1, DNS_DECOMPRESS_ANY
);
1573 dns_decompress_setmethods(&dctx
, DNS_COMPRESS_GLOBAL14
);
1575 ret
= getquestions(source
, msg
, &dctx
, options
);
1576 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1578 if (ret
== DNS_R_RECOVERABLE
) {
1579 seen_problem
= ISC_TRUE
;
1580 ret
= ISC_R_SUCCESS
;
1582 if (ret
!= ISC_R_SUCCESS
)
1584 msg
->question_ok
= 1;
1586 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ANSWER
, options
);
1587 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1589 if (ret
== DNS_R_RECOVERABLE
) {
1590 seen_problem
= ISC_TRUE
;
1591 ret
= ISC_R_SUCCESS
;
1593 if (ret
!= ISC_R_SUCCESS
)
1596 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_AUTHORITY
, options
);
1597 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1599 if (ret
== DNS_R_RECOVERABLE
) {
1600 seen_problem
= ISC_TRUE
;
1601 ret
= ISC_R_SUCCESS
;
1603 if (ret
!= ISC_R_SUCCESS
)
1606 ret
= getsection(source
, msg
, &dctx
, DNS_SECTION_ADDITIONAL
, options
);
1607 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1609 if (ret
== DNS_R_RECOVERABLE
) {
1610 seen_problem
= ISC_TRUE
;
1611 ret
= ISC_R_SUCCESS
;
1613 if (ret
!= ISC_R_SUCCESS
)
1616 isc_buffer_remainingregion(source
, &r
);
1617 if (r
.length
!= 0) {
1618 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1619 DNS_LOGMODULE_MESSAGE
, ISC_LOG_DEBUG(3),
1620 "message has %u byte(s) of trailing garbage",
1625 if ((options
& DNS_MESSAGEPARSE_CLONEBUFFER
) == 0)
1626 isc_buffer_usedregion(&origsource
, &msg
->saved
);
1628 msg
->saved
.length
= isc_buffer_usedlength(&origsource
);
1629 msg
->saved
.base
= isc_mem_get(msg
->mctx
, msg
->saved
.length
);
1630 if (msg
->saved
.base
== NULL
)
1631 return (ISC_R_NOMEMORY
);
1632 memcpy(msg
->saved
.base
, isc_buffer_base(&origsource
),
1634 msg
->free_saved
= 1;
1637 if (ret
== ISC_R_UNEXPECTEDEND
&& ignore_tc
)
1638 return (DNS_R_RECOVERABLE
);
1639 if (seen_problem
== ISC_TRUE
)
1640 return (DNS_R_RECOVERABLE
);
1641 return (ISC_R_SUCCESS
);
1645 dns_message_renderbegin(dns_message_t
*msg
, dns_compress_t
*cctx
,
1646 isc_buffer_t
*buffer
)
1650 REQUIRE(DNS_MESSAGE_VALID(msg
));
1651 REQUIRE(buffer
!= NULL
);
1652 REQUIRE(msg
->buffer
== NULL
);
1653 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
1658 * Erase the contents of this buffer.
1660 isc_buffer_clear(buffer
);
1663 * Make certain there is enough for at least the header in this
1666 isc_buffer_availableregion(buffer
, &r
);
1667 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
1668 return (ISC_R_NOSPACE
);
1670 if (r
.length
< msg
->reserved
)
1671 return (ISC_R_NOSPACE
);
1674 * Reserve enough space for the header in this buffer.
1676 isc_buffer_add(buffer
, DNS_MESSAGE_HEADERLEN
);
1678 msg
->buffer
= buffer
;
1680 return (ISC_R_SUCCESS
);
1684 dns_message_renderchangebuffer(dns_message_t
*msg
, isc_buffer_t
*buffer
) {
1687 REQUIRE(DNS_MESSAGE_VALID(msg
));
1688 REQUIRE(buffer
!= NULL
);
1689 REQUIRE(msg
->buffer
!= NULL
);
1692 * Ensure that the new buffer is empty, and has enough space to
1693 * hold the current contents.
1695 isc_buffer_clear(buffer
);
1697 isc_buffer_availableregion(buffer
, &rn
);
1698 isc_buffer_usedregion(msg
->buffer
, &r
);
1699 REQUIRE(rn
.length
> r
.length
);
1702 * Copy the contents from the old to the new buffer.
1704 isc_buffer_add(buffer
, r
.length
);
1705 memcpy(rn
.base
, r
.base
, r
.length
);
1707 msg
->buffer
= buffer
;
1709 return (ISC_R_SUCCESS
);
1713 dns_message_renderrelease(dns_message_t
*msg
, unsigned int space
) {
1714 REQUIRE(DNS_MESSAGE_VALID(msg
));
1715 REQUIRE(space
<= msg
->reserved
);
1717 msg
->reserved
-= space
;
1721 dns_message_renderreserve(dns_message_t
*msg
, unsigned int space
) {
1724 REQUIRE(DNS_MESSAGE_VALID(msg
));
1726 if (msg
->buffer
!= NULL
) {
1727 isc_buffer_availableregion(msg
->buffer
, &r
);
1728 if (r
.length
< (space
+ msg
->reserved
))
1729 return (ISC_R_NOSPACE
);
1732 msg
->reserved
+= space
;
1734 return (ISC_R_SUCCESS
);
1737 static inline isc_boolean_t
1738 wrong_priority(dns_rdataset_t
*rds
, int pass
, dns_rdatatype_t preferred_glue
) {
1742 * If we are not rendering class IN, this ordering is bogus.
1744 if (rds
->rdclass
!= dns_rdataclass_in
)
1747 switch (rds
->type
) {
1748 case dns_rdatatype_a
:
1749 case dns_rdatatype_aaaa
:
1750 if (preferred_glue
== rds
->type
)
1755 case dns_rdatatype_rrsig
:
1756 case dns_rdatatype_dnskey
:
1763 if (pass_needed
>= pass
)
1770 dns_message_rendersection(dns_message_t
*msg
, dns_section_t sectionid
,
1771 unsigned int options
)
1773 dns_namelist_t
*section
;
1774 dns_name_t
*name
, *next_name
;
1775 dns_rdataset_t
*rdataset
, *next_rdataset
;
1776 unsigned int count
, total
;
1777 isc_result_t result
;
1778 isc_buffer_t st
; /* for rollbacks */
1780 isc_boolean_t partial
= ISC_FALSE
;
1781 unsigned int rd_options
;
1782 dns_rdatatype_t preferred_glue
= 0;
1784 REQUIRE(DNS_MESSAGE_VALID(msg
));
1785 REQUIRE(msg
->buffer
!= NULL
);
1786 REQUIRE(VALID_NAMED_SECTION(sectionid
));
1788 section
= &msg
->sections
[sectionid
];
1790 if ((sectionid
== DNS_SECTION_ADDITIONAL
)
1791 && (options
& DNS_MESSAGERENDER_ORDERED
) == 0) {
1792 if ((options
& DNS_MESSAGERENDER_PREFER_A
) != 0) {
1793 preferred_glue
= dns_rdatatype_a
;
1795 } else if ((options
& DNS_MESSAGERENDER_PREFER_AAAA
) != 0) {
1796 preferred_glue
= dns_rdatatype_aaaa
;
1803 if ((options
& DNS_MESSAGERENDER_OMITDNSSEC
) == 0)
1806 rd_options
= DNS_RDATASETTOWIRE_OMITDNSSEC
;
1809 * Shrink the space in the buffer by the reserved amount.
1811 msg
->buffer
->length
-= msg
->reserved
;
1814 if (msg
->reserved
== 0 && (options
& DNS_MESSAGERENDER_PARTIAL
) != 0)
1818 * Render required glue first. Set TC if it won't fit.
1820 name
= ISC_LIST_HEAD(*section
);
1822 rdataset
= ISC_LIST_HEAD(name
->list
);
1823 if (rdataset
!= NULL
&&
1824 (rdataset
->attributes
& DNS_RDATASETATTR_REQUIREDGLUE
) != 0 &&
1825 (rdataset
->attributes
& DNS_RDATASETATTR_RENDERED
) == 0) {
1826 const void *order_arg
= msg
->order_arg
;
1827 st
= *(msg
->buffer
);
1830 result
= dns_rdataset_towirepartial(rdataset
,
1840 result
= dns_rdataset_towiresorted(rdataset
,
1849 if (partial
&& result
== ISC_R_NOSPACE
) {
1850 msg
->flags
|= DNS_MESSAGEFLAG_TC
;
1851 msg
->buffer
->length
+= msg
->reserved
;
1852 msg
->counts
[sectionid
] += total
;
1855 if (result
!= ISC_R_SUCCESS
) {
1856 INSIST(st
.used
< 65536);
1857 dns_compress_rollback(msg
->cctx
,
1858 (isc_uint16_t
)st
.used
);
1859 *(msg
->buffer
) = st
; /* rollback */
1860 msg
->buffer
->length
+= msg
->reserved
;
1861 msg
->counts
[sectionid
] += total
;
1864 rdataset
->attributes
|= DNS_RDATASETATTR_RENDERED
;
1869 name
= ISC_LIST_HEAD(*section
);
1871 msg
->buffer
->length
+= msg
->reserved
;
1872 msg
->counts
[sectionid
] += total
;
1873 return (ISC_R_SUCCESS
);
1876 while (name
!= NULL
) {
1877 next_name
= ISC_LIST_NEXT(name
, link
);
1879 rdataset
= ISC_LIST_HEAD(name
->list
);
1880 while (rdataset
!= NULL
) {
1881 next_rdataset
= ISC_LIST_NEXT(rdataset
, link
);
1883 if ((rdataset
->attributes
&
1884 DNS_RDATASETATTR_RENDERED
) != 0)
1887 if (((options
& DNS_MESSAGERENDER_ORDERED
)
1889 && (sectionid
== DNS_SECTION_ADDITIONAL
)
1890 && wrong_priority(rdataset
, pass
,
1894 st
= *(msg
->buffer
);
1898 result
= dns_rdataset_towirepartial(
1909 result
= dns_rdataset_towiresorted(
1922 * If out of space, record stats on what we
1923 * rendered so far, and return that status.
1925 * XXXMLG Need to change this when
1926 * dns_rdataset_towire() can render partial
1927 * sets starting at some arbitary point in the
1928 * set. This will include setting a bit in the
1929 * rdataset to indicate that a partial
1930 * rendering was done, and some state saved
1931 * somewhere (probably in the message struct)
1932 * to indicate where to continue from.
1934 if (partial
&& result
== ISC_R_NOSPACE
) {
1935 msg
->buffer
->length
+= msg
->reserved
;
1936 msg
->counts
[sectionid
] += total
;
1939 if (result
!= ISC_R_SUCCESS
) {
1940 INSIST(st
.used
< 65536);
1941 dns_compress_rollback(msg
->cctx
,
1942 (isc_uint16_t
)st
.used
);
1943 *(msg
->buffer
) = st
; /* rollback */
1944 msg
->buffer
->length
+= msg
->reserved
;
1945 msg
->counts
[sectionid
] += total
;
1950 * If we have rendered non-validated data,
1951 * ensure that the AD bit is not set.
1953 if (rdataset
->trust
!= dns_trust_secure
&&
1954 (sectionid
== DNS_SECTION_ANSWER
||
1955 sectionid
== DNS_SECTION_AUTHORITY
))
1956 msg
->flags
&= ~DNS_MESSAGEFLAG_AD
;
1958 rdataset
->attributes
|=
1959 DNS_RDATASETATTR_RENDERED
;
1962 rdataset
= next_rdataset
;
1967 } while (--pass
!= 0);
1969 msg
->buffer
->length
+= msg
->reserved
;
1970 msg
->counts
[sectionid
] += total
;
1972 return (ISC_R_SUCCESS
);
1976 dns_message_renderheader(dns_message_t
*msg
, isc_buffer_t
*target
) {
1980 REQUIRE(DNS_MESSAGE_VALID(msg
));
1981 REQUIRE(target
!= NULL
);
1983 isc_buffer_availableregion(target
, &r
);
1984 REQUIRE(r
.length
>= DNS_MESSAGE_HEADERLEN
);
1986 isc_buffer_putuint16(target
, msg
->id
);
1988 tmp
= ((msg
->opcode
<< DNS_MESSAGE_OPCODE_SHIFT
)
1989 & DNS_MESSAGE_OPCODE_MASK
);
1990 tmp
|= (msg
->rcode
& DNS_MESSAGE_RCODE_MASK
);
1991 tmp
|= (msg
->flags
& DNS_MESSAGE_FLAG_MASK
);
1993 INSIST(msg
->counts
[DNS_SECTION_QUESTION
] < 65536 &&
1994 msg
->counts
[DNS_SECTION_ANSWER
] < 65536 &&
1995 msg
->counts
[DNS_SECTION_AUTHORITY
] < 65536 &&
1996 msg
->counts
[DNS_SECTION_ADDITIONAL
] < 65536);
1998 isc_buffer_putuint16(target
, tmp
);
1999 isc_buffer_putuint16(target
,
2000 (isc_uint16_t
)msg
->counts
[DNS_SECTION_QUESTION
]);
2001 isc_buffer_putuint16(target
,
2002 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ANSWER
]);
2003 isc_buffer_putuint16(target
,
2004 (isc_uint16_t
)msg
->counts
[DNS_SECTION_AUTHORITY
]);
2005 isc_buffer_putuint16(target
,
2006 (isc_uint16_t
)msg
->counts
[DNS_SECTION_ADDITIONAL
]);
2010 dns_message_renderend(dns_message_t
*msg
) {
2011 isc_buffer_t tmpbuf
;
2016 REQUIRE(DNS_MESSAGE_VALID(msg
));
2017 REQUIRE(msg
->buffer
!= NULL
);
2019 if ((msg
->rcode
& ~DNS_MESSAGE_RCODE_MASK
) != 0 && msg
->opt
== NULL
) {
2021 * We have an extended rcode but are not using EDNS.
2023 return (DNS_R_FORMERR
);
2027 * If we've got an OPT record, render it.
2029 if (msg
->opt
!= NULL
) {
2030 dns_message_renderrelease(msg
, msg
->opt_reserved
);
2031 msg
->opt_reserved
= 0;
2033 * Set the extended rcode.
2035 msg
->opt
->ttl
&= ~DNS_MESSAGE_EDNSRCODE_MASK
;
2036 msg
->opt
->ttl
|= ((msg
->rcode
<< 20) &
2037 DNS_MESSAGE_EDNSRCODE_MASK
);
2042 result
= dns_rdataset_towire(msg
->opt
, dns_rootname
,
2043 msg
->cctx
, msg
->buffer
, 0,
2045 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2046 if (result
!= ISC_R_SUCCESS
)
2051 * If we're adding a TSIG or SIG(0) to a truncated message,
2052 * clear all rdatasets from the message except for the question
2053 * before adding the TSIG or SIG(0). If the question doesn't fit,
2056 if ((msg
->tsigkey
!= NULL
|| msg
->sig0key
!= NULL
) &&
2057 (msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
2061 msgresetnames(msg
, DNS_SECTION_ANSWER
);
2063 dns_message_renderreset(msg
);
2065 isc_buffer_clear(msg
->buffer
);
2066 isc_buffer_add(msg
->buffer
, DNS_MESSAGE_HEADERLEN
);
2067 dns_compress_rollback(msg
->cctx
, 0);
2068 result
= dns_message_rendersection(msg
, DNS_SECTION_QUESTION
,
2070 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOSPACE
)
2075 * If we're adding a TSIG record, generate and render it.
2077 if (msg
->tsigkey
!= NULL
) {
2078 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2079 msg
->sig_reserved
= 0;
2080 result
= dns_tsig_sign(msg
);
2081 if (result
!= ISC_R_SUCCESS
)
2084 result
= dns_rdataset_towire(msg
->tsig
, msg
->tsigname
,
2085 msg
->cctx
, msg
->buffer
, 0,
2087 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2088 if (result
!= ISC_R_SUCCESS
)
2093 * If we're adding a SIG(0) record, generate and render it.
2095 if (msg
->sig0key
!= NULL
) {
2096 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2097 msg
->sig_reserved
= 0;
2098 result
= dns_dnssec_signmessage(msg
, msg
->sig0key
);
2099 if (result
!= ISC_R_SUCCESS
)
2103 * Note: dns_rootname is used here, not msg->sig0name, since
2104 * the owner name of a SIG(0) is irrelevant, and will not
2105 * be set in a message being rendered.
2107 result
= dns_rdataset_towire(msg
->sig0
, dns_rootname
,
2108 msg
->cctx
, msg
->buffer
, 0,
2110 msg
->counts
[DNS_SECTION_ADDITIONAL
] += count
;
2111 if (result
!= ISC_R_SUCCESS
)
2115 isc_buffer_usedregion(msg
->buffer
, &r
);
2116 isc_buffer_init(&tmpbuf
, r
.base
, r
.length
);
2118 dns_message_renderheader(msg
, &tmpbuf
);
2120 msg
->buffer
= NULL
; /* forget about this buffer only on success XXX */
2122 return (ISC_R_SUCCESS
);
2126 dns_message_renderreset(dns_message_t
*msg
) {
2129 dns_rdataset_t
*rds
;
2132 * Reset the message so that it may be rendered again.
2135 REQUIRE(DNS_MESSAGE_VALID(msg
));
2136 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2140 for (i
= 0; i
< DNS_SECTION_MAX
; i
++) {
2141 msg
->cursors
[i
] = NULL
;
2143 for (name
= ISC_LIST_HEAD(msg
->sections
[i
]);
2145 name
= ISC_LIST_NEXT(name
, link
)) {
2146 for (rds
= ISC_LIST_HEAD(name
->list
);
2148 rds
= ISC_LIST_NEXT(rds
, link
)) {
2149 rds
->attributes
&= ~DNS_RDATASETATTR_RENDERED
;
2153 if (msg
->tsigname
!= NULL
)
2154 dns_message_puttempname(msg
, &msg
->tsigname
);
2155 if (msg
->tsig
!= NULL
) {
2156 dns_rdataset_disassociate(msg
->tsig
);
2157 dns_message_puttemprdataset(msg
, &msg
->tsig
);
2159 if (msg
->sig0
!= NULL
) {
2160 dns_rdataset_disassociate(msg
->sig0
);
2161 dns_message_puttemprdataset(msg
, &msg
->sig0
);
2166 dns_message_firstname(dns_message_t
*msg
, dns_section_t section
) {
2167 REQUIRE(DNS_MESSAGE_VALID(msg
));
2168 REQUIRE(VALID_NAMED_SECTION(section
));
2170 msg
->cursors
[section
] = ISC_LIST_HEAD(msg
->sections
[section
]);
2172 if (msg
->cursors
[section
] == NULL
)
2173 return (ISC_R_NOMORE
);
2175 return (ISC_R_SUCCESS
);
2179 dns_message_nextname(dns_message_t
*msg
, dns_section_t section
) {
2180 REQUIRE(DNS_MESSAGE_VALID(msg
));
2181 REQUIRE(VALID_NAMED_SECTION(section
));
2182 REQUIRE(msg
->cursors
[section
] != NULL
);
2184 msg
->cursors
[section
] = ISC_LIST_NEXT(msg
->cursors
[section
], link
);
2186 if (msg
->cursors
[section
] == NULL
)
2187 return (ISC_R_NOMORE
);
2189 return (ISC_R_SUCCESS
);
2193 dns_message_currentname(dns_message_t
*msg
, dns_section_t section
,
2196 REQUIRE(DNS_MESSAGE_VALID(msg
));
2197 REQUIRE(VALID_NAMED_SECTION(section
));
2198 REQUIRE(name
!= NULL
&& *name
== NULL
);
2199 REQUIRE(msg
->cursors
[section
] != NULL
);
2201 *name
= msg
->cursors
[section
];
2205 dns_message_findname(dns_message_t
*msg
, dns_section_t section
,
2206 dns_name_t
*target
, dns_rdatatype_t type
,
2207 dns_rdatatype_t covers
, dns_name_t
**name
,
2208 dns_rdataset_t
**rdataset
)
2210 dns_name_t
*foundname
;
2211 isc_result_t result
;
2214 * XXX These requirements are probably too intensive, especially
2215 * where things can be NULL, but as they are they ensure that if
2216 * something is NON-NULL, indicating that the caller expects it
2217 * to be filled in, that we can in fact fill it in.
2219 REQUIRE(msg
!= NULL
);
2220 REQUIRE(VALID_SECTION(section
));
2221 REQUIRE(target
!= NULL
);
2223 REQUIRE(*name
== NULL
);
2224 if (type
== dns_rdatatype_any
) {
2225 REQUIRE(rdataset
== NULL
);
2227 if (rdataset
!= NULL
)
2228 REQUIRE(*rdataset
== NULL
);
2231 result
= findname(&foundname
, target
,
2232 &msg
->sections
[section
]);
2234 if (result
== ISC_R_NOTFOUND
)
2235 return (DNS_R_NXDOMAIN
);
2236 else if (result
!= ISC_R_SUCCESS
)
2243 * And now look for the type.
2245 if (type
== dns_rdatatype_any
)
2246 return (ISC_R_SUCCESS
);
2248 result
= dns_message_findtype(foundname
, type
, covers
, rdataset
);
2249 if (result
== ISC_R_NOTFOUND
)
2250 return (DNS_R_NXRRSET
);
2256 dns_message_movename(dns_message_t
*msg
, dns_name_t
*name
,
2257 dns_section_t fromsection
,
2258 dns_section_t tosection
)
2260 REQUIRE(msg
!= NULL
);
2261 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2262 REQUIRE(name
!= NULL
);
2263 REQUIRE(VALID_NAMED_SECTION(fromsection
));
2264 REQUIRE(VALID_NAMED_SECTION(tosection
));
2267 * Unlink the name from the old section
2269 ISC_LIST_UNLINK(msg
->sections
[fromsection
], name
, link
);
2270 ISC_LIST_APPEND(msg
->sections
[tosection
], name
, link
);
2274 dns_message_addname(dns_message_t
*msg
, dns_name_t
*name
,
2275 dns_section_t section
)
2277 REQUIRE(msg
!= NULL
);
2278 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2279 REQUIRE(name
!= NULL
);
2280 REQUIRE(VALID_NAMED_SECTION(section
));
2282 ISC_LIST_APPEND(msg
->sections
[section
], name
, link
);
2286 dns_message_gettempname(dns_message_t
*msg
, dns_name_t
**item
) {
2287 REQUIRE(DNS_MESSAGE_VALID(msg
));
2288 REQUIRE(item
!= NULL
&& *item
== NULL
);
2290 *item
= isc_mempool_get(msg
->namepool
);
2292 return (ISC_R_NOMEMORY
);
2293 dns_name_init(*item
, NULL
);
2295 return (ISC_R_SUCCESS
);
2299 dns_message_gettempoffsets(dns_message_t
*msg
, dns_offsets_t
**item
) {
2300 REQUIRE(DNS_MESSAGE_VALID(msg
));
2301 REQUIRE(item
!= NULL
&& *item
== NULL
);
2303 *item
= newoffsets(msg
);
2305 return (ISC_R_NOMEMORY
);
2307 return (ISC_R_SUCCESS
);
2311 dns_message_gettemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2312 REQUIRE(DNS_MESSAGE_VALID(msg
));
2313 REQUIRE(item
!= NULL
&& *item
== NULL
);
2315 *item
= newrdata(msg
);
2317 return (ISC_R_NOMEMORY
);
2319 return (ISC_R_SUCCESS
);
2323 dns_message_gettemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2324 REQUIRE(DNS_MESSAGE_VALID(msg
));
2325 REQUIRE(item
!= NULL
&& *item
== NULL
);
2327 *item
= isc_mempool_get(msg
->rdspool
);
2329 return (ISC_R_NOMEMORY
);
2331 dns_rdataset_init(*item
);
2333 return (ISC_R_SUCCESS
);
2337 dns_message_gettemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2338 REQUIRE(DNS_MESSAGE_VALID(msg
));
2339 REQUIRE(item
!= NULL
&& *item
== NULL
);
2341 *item
= newrdatalist(msg
);
2343 return (ISC_R_NOMEMORY
);
2345 return (ISC_R_SUCCESS
);
2349 dns_message_puttempname(dns_message_t
*msg
, dns_name_t
**item
) {
2350 REQUIRE(DNS_MESSAGE_VALID(msg
));
2351 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2353 if (dns_name_dynamic(*item
))
2354 dns_name_free(*item
, msg
->mctx
);
2355 isc_mempool_put(msg
->namepool
, *item
);
2360 dns_message_puttemprdata(dns_message_t
*msg
, dns_rdata_t
**item
) {
2361 REQUIRE(DNS_MESSAGE_VALID(msg
));
2362 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2364 releaserdata(msg
, *item
);
2369 dns_message_puttemprdataset(dns_message_t
*msg
, dns_rdataset_t
**item
) {
2370 REQUIRE(DNS_MESSAGE_VALID(msg
));
2371 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2373 REQUIRE(!dns_rdataset_isassociated(*item
));
2374 isc_mempool_put(msg
->rdspool
, *item
);
2379 dns_message_puttemprdatalist(dns_message_t
*msg
, dns_rdatalist_t
**item
) {
2380 REQUIRE(DNS_MESSAGE_VALID(msg
));
2381 REQUIRE(item
!= NULL
&& *item
!= NULL
);
2383 releaserdatalist(msg
, *item
);
2388 dns_message_peekheader(isc_buffer_t
*source
, dns_messageid_t
*idp
,
2389 unsigned int *flagsp
)
2392 isc_buffer_t buffer
;
2396 REQUIRE(source
!= NULL
);
2400 isc_buffer_remainingregion(&buffer
, &r
);
2401 if (r
.length
< DNS_MESSAGE_HEADERLEN
)
2402 return (ISC_R_UNEXPECTEDEND
);
2404 id
= isc_buffer_getuint16(&buffer
);
2405 flags
= isc_buffer_getuint16(&buffer
);
2406 flags
&= DNS_MESSAGE_FLAG_MASK
;
2413 return (ISC_R_SUCCESS
);
2417 dns_message_reply(dns_message_t
*msg
, isc_boolean_t want_question_section
) {
2418 unsigned int first_section
;
2419 isc_result_t result
;
2421 REQUIRE(DNS_MESSAGE_VALID(msg
));
2422 REQUIRE((msg
->flags
& DNS_MESSAGEFLAG_QR
) == 0);
2424 if (!msg
->header_ok
)
2425 return (DNS_R_FORMERR
);
2426 if (msg
->opcode
!= dns_opcode_query
&&
2427 msg
->opcode
!= dns_opcode_notify
)
2428 want_question_section
= ISC_FALSE
;
2429 if (want_question_section
) {
2430 if (!msg
->question_ok
)
2431 return (DNS_R_FORMERR
);
2432 first_section
= DNS_SECTION_ANSWER
;
2434 first_section
= DNS_SECTION_QUESTION
;
2435 msg
->from_to_wire
= DNS_MESSAGE_INTENTRENDER
;
2436 msgresetnames(msg
, first_section
);
2438 msgresetsigs(msg
, ISC_TRUE
);
2439 msginitprivate(msg
);
2441 * We now clear most flags and then set QR, ensuring that the
2442 * reply's flags will be in a reasonable state.
2444 msg
->flags
&= DNS_MESSAGE_REPLYPRESERVE
;
2445 msg
->flags
|= DNS_MESSAGEFLAG_QR
;
2448 * This saves the query TSIG status, if the query was signed, and
2449 * reserves space in the reply for the TSIG.
2451 if (msg
->tsigkey
!= NULL
) {
2452 unsigned int otherlen
= 0;
2453 msg
->querytsigstatus
= msg
->tsigstatus
;
2454 msg
->tsigstatus
= dns_rcode_noerror
;
2455 if (msg
->querytsigstatus
== dns_tsigerror_badtime
)
2457 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, otherlen
);
2458 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2459 if (result
!= ISC_R_SUCCESS
) {
2460 msg
->sig_reserved
= 0;
2464 if (msg
->saved
.base
!= NULL
) {
2465 msg
->query
.base
= msg
->saved
.base
;
2466 msg
->query
.length
= msg
->saved
.length
;
2467 msg
->free_query
= msg
->free_saved
;
2468 msg
->saved
.base
= NULL
;
2469 msg
->saved
.length
= 0;
2470 msg
->free_saved
= 0;
2473 return (ISC_R_SUCCESS
);
2477 dns_message_getopt(dns_message_t
*msg
) {
2480 * Get the OPT record for 'msg'.
2483 REQUIRE(DNS_MESSAGE_VALID(msg
));
2489 dns_message_setopt(dns_message_t
*msg
, dns_rdataset_t
*opt
) {
2490 isc_result_t result
;
2491 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2494 * Set the OPT record for 'msg'.
2498 * The space required for an OPT record is:
2500 * 1 byte for the name
2501 * 2 bytes for the type
2502 * 2 bytes for the class
2503 * 4 bytes for the ttl
2504 * 2 bytes for the rdata length
2505 * ---------------------------------
2508 * plus the length of the rdata.
2511 REQUIRE(DNS_MESSAGE_VALID(msg
));
2512 REQUIRE(opt
->type
== dns_rdatatype_opt
);
2513 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2514 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2518 result
= dns_rdataset_first(opt
);
2519 if (result
!= ISC_R_SUCCESS
)
2521 dns_rdataset_current(opt
, &rdata
);
2522 msg
->opt_reserved
= 11 + rdata
.length
;
2523 result
= dns_message_renderreserve(msg
, msg
->opt_reserved
);
2524 if (result
!= ISC_R_SUCCESS
) {
2525 msg
->opt_reserved
= 0;
2531 return (ISC_R_SUCCESS
);
2534 dns_message_puttemprdataset(msg
, &opt
);
2540 dns_message_gettsig(dns_message_t
*msg
, dns_name_t
**owner
) {
2543 * Get the TSIG record and owner for 'msg'.
2546 REQUIRE(DNS_MESSAGE_VALID(msg
));
2547 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2550 *owner
= msg
->tsigname
;
2555 dns_message_settsigkey(dns_message_t
*msg
, dns_tsigkey_t
*key
) {
2556 isc_result_t result
;
2559 * Set the TSIG key for 'msg'
2562 REQUIRE(DNS_MESSAGE_VALID(msg
));
2563 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2565 if (key
== NULL
&& msg
->tsigkey
!= NULL
) {
2566 if (msg
->sig_reserved
!= 0) {
2567 dns_message_renderrelease(msg
, msg
->sig_reserved
);
2568 msg
->sig_reserved
= 0;
2570 dns_tsigkey_detach(&msg
->tsigkey
);
2573 REQUIRE(msg
->tsigkey
== NULL
&& msg
->sig0key
== NULL
);
2574 dns_tsigkey_attach(key
, &msg
->tsigkey
);
2575 if (msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
) {
2576 msg
->sig_reserved
= spacefortsig(msg
->tsigkey
, 0);
2577 result
= dns_message_renderreserve(msg
,
2579 if (result
!= ISC_R_SUCCESS
) {
2580 dns_tsigkey_detach(&msg
->tsigkey
);
2581 msg
->sig_reserved
= 0;
2586 return (ISC_R_SUCCESS
);
2590 dns_message_gettsigkey(dns_message_t
*msg
) {
2593 * Get the TSIG key for 'msg'
2596 REQUIRE(DNS_MESSAGE_VALID(msg
));
2598 return (msg
->tsigkey
);
2602 dns_message_setquerytsig(dns_message_t
*msg
, isc_buffer_t
*querytsig
) {
2603 dns_rdata_t
*rdata
= NULL
;
2604 dns_rdatalist_t
*list
= NULL
;
2605 dns_rdataset_t
*set
= NULL
;
2606 isc_buffer_t
*buf
= NULL
;
2608 isc_result_t result
;
2610 REQUIRE(DNS_MESSAGE_VALID(msg
));
2611 REQUIRE(msg
->querytsig
== NULL
);
2613 if (querytsig
== NULL
)
2614 return (ISC_R_SUCCESS
);
2616 result
= dns_message_gettemprdata(msg
, &rdata
);
2617 if (result
!= ISC_R_SUCCESS
)
2620 result
= dns_message_gettemprdatalist(msg
, &list
);
2621 if (result
!= ISC_R_SUCCESS
)
2623 result
= dns_message_gettemprdataset(msg
, &set
);
2624 if (result
!= ISC_R_SUCCESS
)
2627 isc_buffer_usedregion(querytsig
, &r
);
2628 result
= isc_buffer_allocate(msg
->mctx
, &buf
, r
.length
);
2629 if (result
!= ISC_R_SUCCESS
)
2631 isc_buffer_putmem(buf
, r
.base
, r
.length
);
2632 isc_buffer_usedregion(buf
, &r
);
2633 dns_rdata_init(rdata
);
2634 dns_rdata_fromregion(rdata
, dns_rdataclass_any
, dns_rdatatype_tsig
, &r
);
2635 dns_message_takebuffer(msg
, &buf
);
2636 ISC_LIST_INIT(list
->rdata
);
2637 ISC_LIST_APPEND(list
->rdata
, rdata
, link
);
2638 result
= dns_rdatalist_tordataset(list
, set
);
2639 if (result
!= ISC_R_SUCCESS
)
2642 msg
->querytsig
= set
;
2648 dns_message_puttemprdata(msg
, &rdata
);
2650 dns_message_puttemprdatalist(msg
, &list
);
2652 dns_message_puttemprdataset(msg
, &set
);
2653 return (ISC_R_NOMEMORY
);
2657 dns_message_getquerytsig(dns_message_t
*msg
, isc_mem_t
*mctx
,
2658 isc_buffer_t
**querytsig
) {
2659 isc_result_t result
;
2660 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2663 REQUIRE(DNS_MESSAGE_VALID(msg
));
2664 REQUIRE(mctx
!= NULL
);
2665 REQUIRE(querytsig
!= NULL
&& *querytsig
== NULL
);
2667 if (msg
->tsig
== NULL
)
2668 return (ISC_R_SUCCESS
);
2670 result
= dns_rdataset_first(msg
->tsig
);
2671 if (result
!= ISC_R_SUCCESS
)
2673 dns_rdataset_current(msg
->tsig
, &rdata
);
2674 dns_rdata_toregion(&rdata
, &r
);
2676 result
= isc_buffer_allocate(mctx
, querytsig
, r
.length
);
2677 if (result
!= ISC_R_SUCCESS
)
2679 isc_buffer_putmem(*querytsig
, r
.base
, r
.length
);
2680 return (ISC_R_SUCCESS
);
2684 dns_message_getsig0(dns_message_t
*msg
, dns_name_t
**owner
) {
2687 * Get the SIG(0) record for 'msg'.
2690 REQUIRE(DNS_MESSAGE_VALID(msg
));
2691 REQUIRE(owner
== NULL
|| *owner
== NULL
);
2693 if (msg
->sig0
!= NULL
&& owner
!= NULL
) {
2694 /* If dns_message_getsig0 is called on a rendered message
2695 * after the SIG(0) has been applied, we need to return the
2696 * root name, not NULL.
2698 if (msg
->sig0name
== NULL
)
2699 *owner
= dns_rootname
;
2701 *owner
= msg
->sig0name
;
2707 dns_message_setsig0key(dns_message_t
*msg
, dst_key_t
*key
) {
2710 isc_result_t result
;
2713 * Set the SIG(0) key for 'msg'
2717 * The space required for an SIG(0) record is:
2719 * 1 byte for the name
2720 * 2 bytes for the type
2721 * 2 bytes for the class
2722 * 4 bytes for the ttl
2723 * 2 bytes for the type covered
2724 * 1 byte for the algorithm
2725 * 1 bytes for the labels
2726 * 4 bytes for the original ttl
2727 * 4 bytes for the signature expiration
2728 * 4 bytes for the signature inception
2729 * 2 bytes for the key tag
2730 * n bytes for the signer's name
2731 * x bytes for the signature
2732 * ---------------------------------
2735 REQUIRE(DNS_MESSAGE_VALID(msg
));
2736 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTRENDER
);
2737 REQUIRE(msg
->state
== DNS_SECTION_ANY
);
2740 REQUIRE(msg
->sig0key
== NULL
&& msg
->tsigkey
== NULL
);
2741 dns_name_toregion(dst_key_name(key
), &r
);
2742 result
= dst_key_sigsize(key
, &x
);
2743 if (result
!= ISC_R_SUCCESS
) {
2744 msg
->sig_reserved
= 0;
2747 msg
->sig_reserved
= 27 + r
.length
+ x
;
2748 result
= dns_message_renderreserve(msg
, msg
->sig_reserved
);
2749 if (result
!= ISC_R_SUCCESS
) {
2750 msg
->sig_reserved
= 0;
2755 return (ISC_R_SUCCESS
);
2759 dns_message_getsig0key(dns_message_t
*msg
) {
2762 * Get the SIG(0) key for 'msg'
2765 REQUIRE(DNS_MESSAGE_VALID(msg
));
2767 return (msg
->sig0key
);
2771 dns_message_takebuffer(dns_message_t
*msg
, isc_buffer_t
**buffer
) {
2772 REQUIRE(DNS_MESSAGE_VALID(msg
));
2773 REQUIRE(buffer
!= NULL
);
2774 REQUIRE(ISC_BUFFER_VALID(*buffer
));
2776 ISC_LIST_APPEND(msg
->cleanup
, *buffer
, link
);
2781 dns_message_signer(dns_message_t
*msg
, dns_name_t
*signer
) {
2782 isc_result_t result
= ISC_R_SUCCESS
;
2783 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2785 REQUIRE(DNS_MESSAGE_VALID(msg
));
2786 REQUIRE(signer
!= NULL
);
2787 REQUIRE(msg
->from_to_wire
== DNS_MESSAGE_INTENTPARSE
);
2789 if (msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2790 return (ISC_R_NOTFOUND
);
2792 if (msg
->verify_attempted
== 0)
2793 return (DNS_R_NOTVERIFIEDYET
);
2795 if (!dns_name_hasbuffer(signer
)) {
2796 isc_buffer_t
*dynbuf
= NULL
;
2797 result
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, 512);
2798 if (result
!= ISC_R_SUCCESS
)
2800 dns_name_setbuffer(signer
, dynbuf
);
2801 dns_message_takebuffer(msg
, &dynbuf
);
2804 if (msg
->sig0
!= NULL
) {
2805 dns_rdata_sig_t sig
;
2807 result
= dns_rdataset_first(msg
->sig0
);
2808 INSIST(result
== ISC_R_SUCCESS
);
2809 dns_rdataset_current(msg
->sig0
, &rdata
);
2811 result
= dns_rdata_tostruct(&rdata
, &sig
, NULL
);
2812 if (result
!= ISC_R_SUCCESS
)
2815 if (msg
->verified_sig
&& msg
->sig0status
== dns_rcode_noerror
)
2816 result
= ISC_R_SUCCESS
;
2818 result
= DNS_R_SIGINVALID
;
2819 dns_name_clone(&sig
.signer
, signer
);
2820 dns_rdata_freestruct(&sig
);
2822 dns_name_t
*identity
;
2823 dns_rdata_any_tsig_t tsig
;
2825 result
= dns_rdataset_first(msg
->tsig
);
2826 INSIST(result
== ISC_R_SUCCESS
);
2827 dns_rdataset_current(msg
->tsig
, &rdata
);
2829 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
2830 if (msg
->tsigstatus
!= dns_rcode_noerror
)
2831 result
= DNS_R_TSIGVERIFYFAILURE
;
2832 else if (tsig
.error
!= dns_rcode_noerror
)
2833 result
= DNS_R_TSIGERRORSET
;
2835 result
= ISC_R_SUCCESS
;
2836 dns_rdata_freestruct(&tsig
);
2838 if (msg
->tsigkey
== NULL
) {
2840 * If msg->tsigstatus & tsig.error are both
2841 * dns_rcode_noerror, the message must have been
2842 * verified, which means msg->tsigkey will be
2845 INSIST(result
!= ISC_R_SUCCESS
);
2847 identity
= dns_tsigkey_identity(msg
->tsigkey
);
2848 if (identity
== NULL
) {
2849 if (result
== ISC_R_SUCCESS
)
2850 result
= DNS_R_NOIDENTITY
;
2851 identity
= &msg
->tsigkey
->name
;
2853 dns_name_clone(identity
, signer
);
2861 dns_message_resetsig(dns_message_t
*msg
) {
2862 REQUIRE(DNS_MESSAGE_VALID(msg
));
2863 msg
->verified_sig
= 0;
2864 msg
->verify_attempted
= 0;
2865 msg
->tsigstatus
= dns_rcode_noerror
;
2866 msg
->sig0status
= dns_rcode_noerror
;
2867 msg
->timeadjust
= 0;
2868 if (msg
->tsigkey
!= NULL
) {
2869 dns_tsigkey_detach(&msg
->tsigkey
);
2870 msg
->tsigkey
= NULL
;
2875 dns_message_rechecksig(dns_message_t
*msg
, dns_view_t
*view
) {
2876 dns_message_resetsig(msg
);
2877 return (dns_message_checksig(msg
, view
));
2881 dns_message_checksig(dns_message_t
*msg
, dns_view_t
*view
) {
2882 isc_buffer_t b
, msgb
;
2884 REQUIRE(DNS_MESSAGE_VALID(msg
));
2886 if (msg
->tsigkey
== NULL
&& msg
->tsig
== NULL
&& msg
->sig0
== NULL
)
2887 return (ISC_R_SUCCESS
);
2888 INSIST(msg
->saved
.base
!= NULL
);
2889 isc_buffer_init(&msgb
, msg
->saved
.base
, msg
->saved
.length
);
2890 isc_buffer_add(&msgb
, msg
->saved
.length
);
2891 if (msg
->tsigkey
!= NULL
|| msg
->tsig
!= NULL
) {
2893 return (dns_view_checksig(view
, &msgb
, msg
));
2895 return (dns_tsig_verify(&msgb
, msg
, NULL
, NULL
));
2897 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2898 dns_rdata_sig_t sig
;
2899 dns_rdataset_t keyset
;
2900 isc_result_t result
;
2902 result
= dns_rdataset_first(msg
->sig0
);
2903 INSIST(result
== ISC_R_SUCCESS
);
2904 dns_rdataset_current(msg
->sig0
, &rdata
);
2907 * This can occur when the message is a dynamic update, since
2908 * the rdata length checking is relaxed. This should not
2909 * happen in a well-formed message, since the SIG(0) is only
2910 * looked for in the additional section, and the dynamic update
2911 * meta-records are in the prerequisite and update sections.
2913 if (rdata
.length
== 0)
2914 return (ISC_R_UNEXPECTEDEND
);
2916 result
= dns_rdata_tostruct(&rdata
, &sig
, msg
->mctx
);
2917 if (result
!= ISC_R_SUCCESS
)
2920 dns_rdataset_init(&keyset
);
2922 return (DNS_R_KEYUNAUTHORIZED
);
2923 result
= dns_view_simplefind(view
, &sig
.signer
,
2924 dns_rdatatype_key
/* SIG(0) */,
2925 0, 0, ISC_FALSE
, &keyset
, NULL
);
2927 if (result
!= ISC_R_SUCCESS
) {
2928 /* XXXBEW Should possibly create a fetch here */
2929 result
= DNS_R_KEYUNAUTHORIZED
;
2931 } else if (keyset
.trust
< dns_trust_secure
) {
2932 /* XXXBEW Should call a validator here */
2933 result
= DNS_R_KEYUNAUTHORIZED
;
2936 result
= dns_rdataset_first(&keyset
);
2937 INSIST(result
== ISC_R_SUCCESS
);
2939 result
== ISC_R_SUCCESS
;
2940 result
= dns_rdataset_next(&keyset
))
2942 dst_key_t
*key
= NULL
;
2944 dns_rdataset_current(&keyset
, &rdata
);
2945 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
2946 isc_buffer_add(&b
, rdata
.length
);
2948 result
= dst_key_fromdns(&sig
.signer
, rdata
.rdclass
,
2949 &b
, view
->mctx
, &key
);
2950 if (result
!= ISC_R_SUCCESS
)
2952 if (dst_key_alg(key
) != sig
.algorithm
||
2953 dst_key_id(key
) != sig
.keyid
||
2954 !(dst_key_proto(key
) == DNS_KEYPROTO_DNSSEC
||
2955 dst_key_proto(key
) == DNS_KEYPROTO_ANY
))
2960 result
= dns_dnssec_verifymessage(&msgb
, msg
, key
);
2962 if (result
== ISC_R_SUCCESS
)
2965 if (result
== ISC_R_NOMORE
)
2966 result
= DNS_R_KEYUNAUTHORIZED
;
2969 if (dns_rdataset_isassociated(&keyset
))
2970 dns_rdataset_disassociate(&keyset
);
2971 dns_rdata_freestruct(&sig
);
2977 dns_message_sectiontotext(dns_message_t
*msg
, dns_section_t section
,
2978 const dns_master_style_t
*style
,
2979 dns_messagetextflag_t flags
,
2980 isc_buffer_t
*target
) {
2981 dns_name_t
*name
, empty_name
;
2982 dns_rdataset_t
*rdataset
;
2983 isc_result_t result
;
2985 REQUIRE(DNS_MESSAGE_VALID(msg
));
2986 REQUIRE(target
!= NULL
);
2987 REQUIRE(VALID_SECTION(section
));
2989 if (ISC_LIST_EMPTY(msg
->sections
[section
]))
2990 return (ISC_R_SUCCESS
);
2992 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0) {
2993 ADD_STRING(target
, ";; ");
2994 if (msg
->opcode
!= dns_opcode_update
) {
2995 ADD_STRING(target
, sectiontext
[section
]);
2998 ADD_STRING(target
, updsectiontext
[section
]);
3000 ADD_STRING(target
, " SECTION:\n");
3003 dns_name_init(&empty_name
, NULL
);
3004 result
= dns_message_firstname(msg
, section
);
3005 if (result
!= ISC_R_SUCCESS
) {
3010 dns_message_currentname(msg
, section
, &name
);
3011 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3013 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3014 if (section
== DNS_SECTION_QUESTION
) {
3015 ADD_STRING(target
, ";");
3016 result
= dns_master_questiontotext(name
,
3021 result
= dns_master_rdatasettotext(name
,
3026 if (result
!= ISC_R_SUCCESS
)
3029 result
= dns_message_nextname(msg
, section
);
3030 } while (result
== ISC_R_SUCCESS
);
3031 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3032 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3033 ADD_STRING(target
, "\n");
3034 if (result
== ISC_R_NOMORE
)
3035 result
= ISC_R_SUCCESS
;
3040 dns_message_pseudosectiontotext(dns_message_t
*msg
,
3041 dns_pseudosection_t section
,
3042 const dns_master_style_t
*style
,
3043 dns_messagetextflag_t flags
,
3044 isc_buffer_t
*target
) {
3045 dns_rdataset_t
*ps
= NULL
;
3046 dns_name_t
*name
= NULL
;
3047 isc_result_t result
;
3048 char buf
[sizeof("1234567890")];
3051 REQUIRE(DNS_MESSAGE_VALID(msg
));
3052 REQUIRE(target
!= NULL
);
3053 REQUIRE(VALID_PSEUDOSECTION(section
));
3056 case DNS_PSEUDOSECTION_OPT
:
3057 ps
= dns_message_getopt(msg
);
3059 return (ISC_R_SUCCESS
);
3060 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3061 ADD_STRING(target
, ";; OPT PSEUDOSECTION:\n");
3062 ADD_STRING(target
, "; EDNS: version: ");
3063 snprintf(buf
, sizeof(buf
), "%u",
3064 (unsigned int)((ps
->ttl
& 0x00ff0000) >> 16));
3065 ADD_STRING(target
, buf
);
3066 ADD_STRING(target
, ", flags:");
3067 if ((ps
->ttl
& DNS_MESSAGEEXTFLAG_DO
) != 0)
3068 ADD_STRING(target
, " do");
3069 mbz
= ps
->ttl
& ~DNS_MESSAGEEXTFLAG_DO
& 0xffff;
3071 ADD_STRING(target
, "; MBZ: ");
3072 snprintf(buf
, sizeof(buf
), "%.4x ", mbz
);
3073 ADD_STRING(target
, buf
);
3074 ADD_STRING(target
, ", udp: ");
3076 ADD_STRING(target
, "; udp: ");
3077 snprintf(buf
, sizeof(buf
), "%u\n", (unsigned int)ps
->rdclass
);
3078 ADD_STRING(target
, buf
);
3079 return (ISC_R_SUCCESS
);
3080 case DNS_PSEUDOSECTION_TSIG
:
3081 ps
= dns_message_gettsig(msg
, &name
);
3083 return (ISC_R_SUCCESS
);
3084 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3085 ADD_STRING(target
, ";; TSIG PSEUDOSECTION:\n");
3086 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3087 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3088 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3089 ADD_STRING(target
, "\n");
3091 case DNS_PSEUDOSECTION_SIG0
:
3092 ps
= dns_message_getsig0(msg
, &name
);
3094 return (ISC_R_SUCCESS
);
3095 if ((flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3096 ADD_STRING(target
, ";; SIG0 PSEUDOSECTION:\n");
3097 result
= dns_master_rdatasettotext(name
, ps
, style
, target
);
3098 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0 &&
3099 (flags
& DNS_MESSAGETEXTFLAG_NOCOMMENTS
) == 0)
3100 ADD_STRING(target
, "\n");
3103 return (ISC_R_UNEXPECTED
);
3107 dns_message_totext(dns_message_t
*msg
, const dns_master_style_t
*style
,
3108 dns_messagetextflag_t flags
, isc_buffer_t
*target
) {
3109 char buf
[sizeof("1234567890")];
3110 isc_result_t result
;
3112 REQUIRE(DNS_MESSAGE_VALID(msg
));
3113 REQUIRE(target
!= NULL
);
3115 if ((flags
& DNS_MESSAGETEXTFLAG_NOHEADERS
) == 0) {
3116 ADD_STRING(target
, ";; ->>HEADER<<- opcode: ");
3117 ADD_STRING(target
, opcodetext
[msg
->opcode
]);
3118 ADD_STRING(target
, ", status: ");
3119 ADD_STRING(target
, rcodetext
[msg
->rcode
]);
3120 ADD_STRING(target
, ", id: ");
3121 snprintf(buf
, sizeof(buf
), "%6u", msg
->id
);
3122 ADD_STRING(target
, buf
);
3123 ADD_STRING(target
, "\n;; flags: ");
3124 if ((msg
->flags
& DNS_MESSAGEFLAG_QR
) != 0)
3125 ADD_STRING(target
, "qr ");
3126 if ((msg
->flags
& DNS_MESSAGEFLAG_AA
) != 0)
3127 ADD_STRING(target
, "aa ");
3128 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0)
3129 ADD_STRING(target
, "tc ");
3130 if ((msg
->flags
& DNS_MESSAGEFLAG_RD
) != 0)
3131 ADD_STRING(target
, "rd ");
3132 if ((msg
->flags
& DNS_MESSAGEFLAG_RA
) != 0)
3133 ADD_STRING(target
, "ra ");
3134 if ((msg
->flags
& DNS_MESSAGEFLAG_AD
) != 0)
3135 ADD_STRING(target
, "ad ");
3136 if ((msg
->flags
& DNS_MESSAGEFLAG_CD
) != 0)
3137 ADD_STRING(target
, "cd ");
3138 if (msg
->opcode
!= dns_opcode_update
) {
3139 ADD_STRING(target
, "; QUESTION: ");
3141 ADD_STRING(target
, "; ZONE: ");
3143 snprintf(buf
, sizeof(buf
), "%1u",
3144 msg
->counts
[DNS_SECTION_QUESTION
]);
3145 ADD_STRING(target
, buf
);
3146 if (msg
->opcode
!= dns_opcode_update
) {
3147 ADD_STRING(target
, ", ANSWER: ");
3149 ADD_STRING(target
, ", PREREQ: ");
3151 snprintf(buf
, sizeof(buf
), "%1u",
3152 msg
->counts
[DNS_SECTION_ANSWER
]);
3153 ADD_STRING(target
, buf
);
3154 if (msg
->opcode
!= dns_opcode_update
) {
3155 ADD_STRING(target
, ", AUTHORITY: ");
3157 ADD_STRING(target
, ", UPDATE: ");
3159 snprintf(buf
, sizeof(buf
), "%1u",
3160 msg
->counts
[DNS_SECTION_AUTHORITY
]);
3161 ADD_STRING(target
, buf
);
3162 ADD_STRING(target
, ", ADDITIONAL: ");
3163 snprintf(buf
, sizeof(buf
), "%1u",
3164 msg
->counts
[DNS_SECTION_ADDITIONAL
]);
3165 ADD_STRING(target
, buf
);
3166 ADD_STRING(target
, "\n");
3168 result
= dns_message_pseudosectiontotext(msg
,
3169 DNS_PSEUDOSECTION_OPT
,
3170 style
, flags
, target
);
3171 if (result
!= ISC_R_SUCCESS
)
3174 result
= dns_message_sectiontotext(msg
, DNS_SECTION_QUESTION
,
3175 style
, flags
, target
);
3176 if (result
!= ISC_R_SUCCESS
)
3178 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ANSWER
,
3179 style
, flags
, target
);
3180 if (result
!= ISC_R_SUCCESS
)
3182 result
= dns_message_sectiontotext(msg
, DNS_SECTION_AUTHORITY
,
3183 style
, flags
, target
);
3184 if (result
!= ISC_R_SUCCESS
)
3186 result
= dns_message_sectiontotext(msg
, DNS_SECTION_ADDITIONAL
,
3187 style
, flags
, target
);
3188 if (result
!= ISC_R_SUCCESS
)
3191 result
= dns_message_pseudosectiontotext(msg
,
3192 DNS_PSEUDOSECTION_TSIG
,
3193 style
, flags
, target
);
3194 if (result
!= ISC_R_SUCCESS
)
3197 result
= dns_message_pseudosectiontotext(msg
,
3198 DNS_PSEUDOSECTION_SIG0
,
3199 style
, flags
, target
);
3200 if (result
!= ISC_R_SUCCESS
)
3203 return (ISC_R_SUCCESS
);
3207 dns_message_getrawmessage(dns_message_t
*msg
) {
3208 REQUIRE(DNS_MESSAGE_VALID(msg
));
3209 return (&msg
->saved
);
3213 dns_message_setsortorder(dns_message_t
*msg
, dns_rdatasetorderfunc_t order
,
3214 const void *order_arg
)
3216 REQUIRE(DNS_MESSAGE_VALID(msg
));
3218 msg
->order_arg
= order_arg
;
3222 dns_message_settimeadjust(dns_message_t
*msg
, int timeadjust
) {
3223 REQUIRE(DNS_MESSAGE_VALID(msg
));
3224 msg
->timeadjust
= timeadjust
;
3228 dns_message_gettimeadjust(dns_message_t
*msg
) {
3229 REQUIRE(DNS_MESSAGE_VALID(msg
));
3230 return (msg
->timeadjust
);
3234 dns_opcode_totext(dns_opcode_t opcode
, isc_buffer_t
*target
) {
3236 REQUIRE(opcode
< 16);
3238 if (isc_buffer_availablelength(target
) < strlen(opcodetext
[opcode
]))
3239 return (ISC_R_NOSPACE
);
3240 isc_buffer_putstr(target
, opcodetext
[opcode
]);
3241 return (ISC_R_SUCCESS
);