Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: message.h,v 1.18 2026/04/08 00:16:14 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #pragma once
     17 
     18 /***
     19  ***	Imports
     20  ***/
     21 
     22 #include <inttypes.h>
     23 #include <stdbool.h>
     24 
     25 #include <isc/lang.h>
     26 #include <isc/magic.h>
     27 #include <isc/refcount.h>
     28 
     29 #include <dns/compress.h>
     30 #include <dns/ede.h>
     31 #include <dns/masterdump.h>
     32 #include <dns/types.h>
     33 
     34 #include <dst/dst.h>
     35 
     36 /* Add -DDNS_MESSAGE_TRACE=1 to CFLAGS for detailed reference tracing */
     37 
     38 /*! \file dns/message.h
     39  * \brief Message Handling Module
     40  *
     41  * How this beast works:
     42  *
     43  * When a dns message is received in a buffer, dns_message_parse() is called
     44  * on the memory region.  Various items are checked including the format
     45  * of the message (if counts are right, if counts consume the entire sections,
     46  * and if sections consume the entire message) and known pseudo-RRs in the
     47  * additional data section are analyzed and removed.
     48  *
     49  * TSIG checking is also done at this layer, and any DNSSEC transaction
     50  * signatures should also be checked here.
     51  *
     52  * Notes on using the gettemp*() and puttemp*() functions:
     53  *
     54  * These functions return items (names, rdatasets, etc) allocated from some
     55  * internal state of the dns_message_t.
     56  *
     57  * Names and rdatasets must be put back into the dns_message_t in
     58  * one of two ways.  Assume a name was allocated via
     59  * dns_message_gettempname():
     60  *
     61  *\li	(1) insert it into a section, using dns_message_addname().
     62  *
     63  *\li	(2) return it to the message using dns_message_puttempname().
     64  *
     65  * The same applies to rdatasets.
     66  *
     67  * On the other hand, offsets, rdatalists and rdatas allocated using
     68  * dns_message_gettemp*() will always be freed automatically
     69  * when the message is reset or destroyed; calling dns_message_puttemp*()
     70  * on rdatalists and rdatas is optional and serves only to enable the item
     71  * to be reused multiple times during the lifetime of the message; offsets
     72  * cannot be reused.
     73  *
     74  * Buffers allocated using isc_buffer_allocate() can be automatically freed
     75  * as well by giving the buffer to the message using dns_message_takebuffer().
     76  * Doing this will cause the buffer to be freed using isc_buffer_free()
     77  * when the section lists are cleared, such as in a reset or in a destroy.
     78  * Since the buffer itself exists until the message is destroyed, this sort
     79  * of code can be written:
     80  *
     81  * \code
     82  *	buffer = isc_buffer_allocate(mctx, 512);
     83  *	name = NULL;
     84  *	result = dns_message_gettempname(message, &name);
     85  *	result = dns_name_fromtext(name, &source, dns_rootname, 0, buffer);
     86  *	dns_message_takebuffer(message, &buffer);
     87  * \endcode
     88  *
     89  *
     90  * TODO:
     91  *
     92  * XXX Needed:  ways to set and retrieve EDNS information, add rdata to a
     93  * section, move rdata from one section to another, remove rdata, etc.
     94  */
     95 
     96 #define DNS_MESSAGEFLAG_QR 0x8000U
     97 #define DNS_MESSAGEFLAG_AA 0x0400U
     98 #define DNS_MESSAGEFLAG_TC 0x0200U
     99 #define DNS_MESSAGEFLAG_RD 0x0100U
    100 #define DNS_MESSAGEFLAG_RA 0x0080U
    101 #define DNS_MESSAGEFLAG_AD 0x0020U
    102 #define DNS_MESSAGEFLAG_CD 0x0010U
    103 
    104 /*%< EDNS0 extended message flags */
    105 #define DNS_MESSAGEEXTFLAG_DO 0x8000U /* DNSSEC OK */
    106 #define DNS_MESSAGEEXTFLAG_CO 0x4000U /* Compact denial of existence OK */
    107 
    108 /*%< EDNS0 extended OPT codes */
    109 
    110 #define DNS_OPT_LLQ	       1  /*%< LLQ opt code */
    111 #define DNS_OPT_UL	       2  /*%< UL opt code */
    112 #define DNS_OPT_NSID	       3  /*%< NSID opt code */
    113 #define DNS_OPT_DAU	       5  /*%< DNSSEC algorithm understood */
    114 #define DNS_OPT_DHU	       6  /*%< DNSSEC hash understood */
    115 #define DNS_OPT_N3U	       7  /*%< NSEC3 hash understood */
    116 #define DNS_OPT_CLIENT_SUBNET  8  /*%< client subnet opt code */
    117 #define DNS_OPT_EXPIRE	       9  /*%< EXPIRE opt code */
    118 #define DNS_OPT_COOKIE	       10 /*%< COOKIE opt code */
    119 #define DNS_OPT_TCP_KEEPALIVE  11 /*%< TCP keepalive opt code */
    120 #define DNS_OPT_PAD	       12 /*%< PAD opt code */
    121 #define DNS_OPT_CHAIN	       13 /*%< CHAIN opt code */
    122 #define DNS_OPT_KEY_TAG	       14 /*%< Key tag opt code */
    123 #define DNS_OPT_EDE	       15 /*%< Extended DNS Error opt code */
    124 #define DNS_OPT_CLIENT_TAG     16 /*%< Client tag opt code */
    125 #define DNS_OPT_SERVER_TAG     17 /*%< Server tag opt code */
    126 #define DNS_OPT_REPORT_CHANNEL 18 /*%< DNS Reporting Channel */
    127 #define DNS_OPT_ZONEVERSION    19 /*%< Zoneversion opt code */
    128 
    129 /*%< Experimental options [65001...65534] as per RFC6891 */
    130 
    131 /*%<
    132  * The maximum number of EDNS options we allow to set. Reserve space for the
    133  * options we know about. Extended DNS Errors may occur multiple times, see
    134  * DNS_EDE_MAX_ERRORS.
    135  */
    136 #define DNS_EDNSOPTIONS 7 + DNS_EDE_MAX_ERRORS
    137 
    138 #define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_CD)
    139 #define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
    140 
    141 #define DNS_MESSAGE_HEADERLEN 12 /*%< 6 uint16_t's */
    142 
    143 #define DNS_MESSAGE_MAGIC      ISC_MAGIC('M', 'S', 'G', '@')
    144 #define DNS_MESSAGE_VALID(msg) ISC_MAGIC_VALID(msg, DNS_MESSAGE_MAGIC)
    145 
    146 /*
    147  * Ordering here matters.  DNS_SECTION_ANY must be the lowest and negative,
    148  * and DNS_SECTION_MAX must be one greater than the last used section.
    149  */
    150 typedef int dns_section_t;
    151 #define DNS_SECTION_ANY	       (-1)
    152 #define DNS_SECTION_QUESTION   0
    153 #define DNS_SECTION_ANSWER     1
    154 #define DNS_SECTION_AUTHORITY  2
    155 #define DNS_SECTION_ADDITIONAL 3
    156 #define DNS_SECTION_MAX	       4
    157 
    158 typedef int dns_pseudosection_t;
    159 #define DNS_PSEUDOSECTION_ANY  (-1)
    160 #define DNS_PSEUDOSECTION_OPT  0
    161 #define DNS_PSEUDOSECTION_TSIG 1
    162 #define DNS_PSEUDOSECTION_SIG0 2
    163 #define DNS_PSEUDOSECTION_MAX  3
    164 
    165 typedef int dns_messagetextflag_t;
    166 #define DNS_MESSAGETEXTFLAG_NOCOMMENTS 0x0001
    167 #define DNS_MESSAGETEXTFLAG_NOHEADERS  0x0002
    168 #define DNS_MESSAGETEXTFLAG_ONESOA     0x0004
    169 #define DNS_MESSAGETEXTFLAG_OMITSOA    0x0008
    170 
    171 /*
    172  * Dynamic update names for these sections.
    173  */
    174 #define DNS_SECTION_ZONE	 DNS_SECTION_QUESTION
    175 #define DNS_SECTION_PREREQUISITE DNS_SECTION_ANSWER
    176 #define DNS_SECTION_UPDATE	 DNS_SECTION_AUTHORITY
    177 
    178 /*
    179  * These tell the message library how the created dns_message_t will be used.
    180  */
    181 typedef enum dns_message_intent {
    182 	DNS_MESSAGE_INTENTUNKNOWN = 0, /*%< internal use only */
    183 	DNS_MESSAGE_INTENTPARSE = 1,   /*%< parsing messages */
    184 	DNS_MESSAGE_INTENTRENDER = 2,  /*%< rendering */
    185 } dns_message_intent_t;
    186 
    187 /*
    188  * Control behavior of parsing
    189  */
    190 #define DNS_MESSAGEPARSE_PRESERVEORDER 0x0001 /*%< preserve rdata order */
    191 #define DNS_MESSAGEPARSE_BESTEFFORT       \
    192 	0x0002 /*%< return a message if a \
    193 		* recoverable parse error \
    194 		* occurs */
    195 #define DNS_MESSAGEPARSE_CLONEBUFFER   \
    196 	0x0004 /*%< save a copy of the \
    197 		* source buffer */
    198 #define DNS_MESSAGEPARSE_IGNORETRUNCATION \
    199 	0x0008 /*%< truncation errors are \
    200 		* not fatal. */
    201 
    202 /*
    203  * Control behavior of rendering
    204  */
    205 #define DNS_MESSAGERENDER_ORDERED    0x0001 /*%< don't change order */
    206 #define DNS_MESSAGERENDER_PARTIAL    0x0002 /*%< allow a partial rdataset */
    207 #define DNS_MESSAGERENDER_OMITDNSSEC 0x0004 /*%< omit DNSSEC records */
    208 #define DNS_MESSAGERENDER_PREFER_A      \
    209 	0x0008 /*%< prefer A records in \
    210 		*   additional section. */
    211 #define DNS_MESSAGERENDER_PREFER_AAAA      \
    212 	0x0010 /*%< prefer AAAA records in \
    213 		*   additional section. */
    214 /* Obsolete: DNS_MESSAGERENDER_FILTER_AAAA	0x0020	*/
    215 
    216 typedef struct dns_msgblock dns_msgblock_t;
    217 
    218 struct dns_sortlist_arg {
    219 	dns_aclenv_t	       *env;
    220 	dns_acl_t	       *acl;
    221 	const dns_aclelement_t *element;
    222 };
    223 
    224 typedef struct dns_minttl {
    225 	bool	  is_set;
    226 	dns_ttl_t ttl;
    227 } dns_minttl_t;
    228 
    229 struct dns_message {
    230 	/* public from here down */
    231 	unsigned int   magic;
    232 	isc_refcount_t references;
    233 
    234 	dns_messageid_t	 id;
    235 	unsigned int	 flags;
    236 	dns_rcode_t	 rcode;
    237 	dns_opcode_t	 opcode;
    238 	dns_rdataclass_t rdclass;
    239 
    240 	/* 4 real, 1 pseudo */
    241 	unsigned int counts[DNS_SECTION_MAX];
    242 
    243 	/* private from here down */
    244 	dns_namelist_t	sections[DNS_SECTION_MAX];
    245 	dns_name_t     *cursors[DNS_SECTION_MAX];
    246 	dns_rdataset_t *opt;
    247 	dns_rdataset_t *sig0;
    248 	dns_rdataset_t *tsig;
    249 
    250 	int state;
    251 	unsigned int			      : 0; /* bits */
    252 	dns_message_intent_t from_to_wire     : 2; /* 2 */
    253 	unsigned int	     header_ok	      : 1; /* 3 */
    254 	unsigned int	     question_ok      : 1; /* 4 */
    255 	unsigned int	     tcp_continuation : 1; /* 5 */
    256 	unsigned int	     verified_sig     : 1; /* 6 */
    257 	unsigned int	     verify_attempted : 1; /* 7 */
    258 	unsigned int	     free_query	      : 1; /* 8 */
    259 	unsigned int	     free_saved	      : 1; /* 9 */
    260 	unsigned int	     cc_ok	      : 1; /* 10 */
    261 	unsigned int	     cc_bad	      : 1; /* 11 */
    262 	unsigned int	     cc_echoed	      : 1; /* 12 */
    263 	unsigned int	     tkey	      : 1; /* 13 */
    264 	unsigned int	     rdclass_set      : 1; /* 14 */
    265 	unsigned int	     fuzzing	      : 1; /* 15 */
    266 	unsigned int	     free_pools	      : 1; /* 16 */
    267 	unsigned int	     has_dname	      : 1; /* 17 */
    268 	unsigned int			      : 0;
    269 
    270 	unsigned int opt_reserved;
    271 	unsigned int sig_reserved;
    272 	unsigned int reserved; /* reserved space (render) */
    273 
    274 	uint16_t     padding;
    275 	unsigned int padding_off;
    276 
    277 	isc_buffer_t   *buffer;
    278 	dns_compress_t *cctx;
    279 
    280 	isc_mem_t     *mctx;
    281 	isc_mempool_t *namepool;
    282 	isc_mempool_t *rdspool;
    283 
    284 	isc_bufferlist_t scratchpad;
    285 	isc_bufferlist_t cleanup;
    286 
    287 	ISC_LIST(dns_msgblock_t) rdatas;
    288 	ISC_LIST(dns_msgblock_t) rdatalists;
    289 	ISC_LIST(dns_msgblock_t) offsets;
    290 
    291 	ISC_LIST(dns_rdata_t) freerdata;
    292 	ISC_LIST(dns_rdatalist_t) freerdatalist;
    293 
    294 	dns_rcode_t	tsigstatus;
    295 	dns_rcode_t	querytsigstatus;
    296 	dns_name_t     *tsigname; /* Owner name of TSIG, if any */
    297 	dns_rdataset_t *querytsig;
    298 	dns_tsigkey_t  *tsigkey;
    299 	dst_context_t  *tsigctx;
    300 	int		sigstart;
    301 	int		timeadjust;
    302 
    303 	dns_name_t  *sig0name; /* Owner name of SIG0, if any */
    304 	dst_key_t   *sig0key;
    305 	dns_rcode_t  sig0status;
    306 	isc_region_t query;
    307 	isc_region_t saved;
    308 
    309 	/*
    310 	 * Time to be used when fuzzing.
    311 	 */
    312 	isc_stdtime_t fuzztime;
    313 
    314 	dns_rdatasetorderfunc_t order;
    315 	dns_sortlist_arg_t	order_arg;
    316 
    317 	dns_indent_t indent;
    318 
    319 	dns_minttl_t minttl[DNS_SECTION_MAX];
    320 };
    321 
    322 struct dns_ednsopt {
    323 	uint16_t code;
    324 	uint16_t length;
    325 	uint8_t *value;
    326 };
    327 
    328 typedef void (*dns_message_cb_t)(void *arg, isc_result_t result);
    329 
    330 /***
    331  *** Functions
    332  ***/
    333 
    334 ISC_LANG_BEGINDECLS
    335 
    336 void
    337 dns_message_create(isc_mem_t *mctx, isc_mempool_t *namepool,
    338 		   isc_mempool_t *rdspool, dns_message_intent_t intent,
    339 		   dns_message_t **msgp);
    340 /*%<
    341  * Create msg structure.
    342  *
    343  * This function will allocate some internal blocks of memory that are
    344  * expected to be needed for parsing or rendering nearly any type of message.
    345  *
    346  * Requires:
    347  *\li	'mctx' be a valid memory context.
    348  *
    349  *\li	'msgp' be non-null and '*msg' be NULL.
    350  *
    351  *\li	'namepool' and 'rdspool' must be either both NULL or both valid
    352  *	isc_mempool_t
    353  *
    354  *\li	'intent' must be one of DNS_MESSAGE_INTENTPARSE or
    355  *	#DNS_MESSAGE_INTENTRENDER.
    356  *
    357  * Ensures:
    358  *\li	The data in "*msg" is set to indicate an unused and empty msg
    359  *	structure.
    360  */
    361 
    362 void
    363 dns_message_reset(dns_message_t *msg, dns_message_intent_t intent);
    364 /*%<
    365  * Reset a message structure to default state.  All internal lists are freed
    366  * or reset to a default state as well.  This is simply a more efficient
    367  * way to call dns_message_detach() (assuming last reference is hold),
    368  * followed by dns_message_create(), since it avoid many memory allocations.
    369  *
    370  * If any data loanouts (buffers, names, rdatas, etc) were requested,
    371  * the caller must no longer use them after this call.
    372  *
    373  * The intended next use of the message will be 'intent'.
    374  *
    375  * Requires:
    376  *
    377  *\li	'msg' be valid.
    378  *
    379  *\li	'intent' is DNS_MESSAGE_INTENTPARSE or DNS_MESSAGE_INTENTRENDER
    380  */
    381 
    382 #if DNS_MESSAGE_TRACE
    383 #define dns_message_ref(ptr) dns_message__ref(ptr, __func__, __FILE__, __LINE__)
    384 #define dns_message_unref(ptr) \
    385 	dns_message__unref(ptr, __func__, __FILE__, __LINE__)
    386 #define dns_message_attach(ptr, ptrp) \
    387 	dns_message__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    388 #define dns_message_detach(ptrp) \
    389 	dns_message__detach(ptrp, __func__, __FILE__, __LINE__)
    390 ISC_REFCOUNT_TRACE_DECL(dns_message);
    391 #else
    392 ISC_REFCOUNT_DECL(dns_message);
    393 #endif
    394 /*
    395  * Reference counting for dns_message
    396  */
    397 
    398 isc_result_t
    399 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
    400 			  const dns_master_style_t *style,
    401 			  dns_messagetextflag_t flags, isc_buffer_t *target);
    402 
    403 isc_result_t
    404 dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
    405 				const dns_master_style_t *style,
    406 				dns_messagetextflag_t	  flags,
    407 				isc_buffer_t		 *target);
    408 /*%<
    409  * Convert section 'section' or 'pseudosection' of message 'msg' to
    410  * a cleartext representation
    411  *
    412  * Notes:
    413  *     \li See dns_message_totext for meanings of flags.
    414  *
    415  * Requires:
    416  *
    417  *\li	'msg' is a valid message.
    418  *
    419  *\li	'style' is a valid master dump style.
    420  *
    421  *\li	'target' is a valid buffer.
    422  *
    423  *\li	'section' is a named section label.
    424  *
    425  * Ensures:
    426  *
    427  *\li	If the result is success:
    428  *		The used space in 'target' is updated.
    429  *
    430  * Returns:
    431  *
    432  *\li	#ISC_R_SUCCESS
    433  *\li	#ISC_R_NOSPACE
    434  *\li	#ISC_R_NOMORE
    435  *
    436  *\li	Note: On error return, *target may be partially filled with data.
    437  */
    438 
    439 isc_result_t
    440 dns_message_headertotext(dns_message_t *msg, const dns_master_style_t *style,
    441 			 dns_messagetextflag_t flags, isc_buffer_t *target);
    442 /*%<
    443  * Convert the header section of message 'msg' to a cleartext
    444  * representation. This is called from dns_message_totext().
    445  *
    446  * Notes on flags:
    447  *\li	If #DNS_MESSAGETEXTFLAG_NOHEADERS is set, header lines will be
    448  * 	suppressed and this function is a no-op.
    449  *
    450  * Requires:
    451  *
    452  *\li	'msg' is a valid message.
    453  *
    454  *\li	'target' is a valid buffer.
    455  *
    456  * Ensures:
    457  *
    458  *\li	If the result is success:
    459  *		The used space in 'target' is updated.
    460  *
    461  * Returns:
    462  *
    463  *\li	#ISC_R_SUCCESS
    464  *\li	#ISC_R_NOSPACE
    465  *\li	#ISC_R_NOMORE
    466  *
    467  *\li	Note: On error return, *target may be partially filled with data.
    468  */
    469 
    470 isc_result_t
    471 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
    472 		   dns_messagetextflag_t flags, isc_buffer_t *target);
    473 /*%<
    474  * Convert all sections of message 'msg' to a cleartext representation
    475  *
    476  * Notes on flags:
    477  *\li	If #DNS_MESSAGETEXTFLAG_NOCOMMENTS is cleared, lines beginning with
    478  * 	";;" will be emitted indicating section name.
    479  *\li	If #DNS_MESSAGETEXTFLAG_NOHEADERS is cleared, header lines will be
    480  * 	emitted.
    481  *\li	If #DNS_MESSAGETEXTFLAG_ONESOA is set then only print the first
    482  *	SOA record in the answer section.
    483  *\li	If *#DNS_MESSAGETEXTFLAG_OMITSOA is set don't print any SOA records
    484  *	in the answer section.
    485  *
    486  * The SOA flags are useful for suppressing the display of the second
    487  * SOA record in an AXFR by setting #DNS_MESSAGETEXTFLAG_ONESOA on the
    488  * first message in an AXFR stream and #DNS_MESSAGETEXTFLAG_OMITSOA on
    489  * subsequent messages.
    490  *
    491  * Requires:
    492  *
    493  *\li	'msg' is a valid message.
    494  *
    495  *\li	'style' is a valid master dump style.
    496  *
    497  *\li	'target' is a valid buffer.
    498  *
    499  * Ensures:
    500  *
    501  *\li	If the result is success:
    502  *		The used space in 'target' is updated.
    503  *
    504  * Returns:
    505  *
    506  *\li	#ISC_R_SUCCESS
    507  *\li	#ISC_R_NOSPACE
    508  *\li	#ISC_R_NOMORE
    509  *
    510  *\li	Note: On error return, *target may be partially filled with data.
    511  */
    512 
    513 isc_result_t
    514 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
    515 		  unsigned int options);
    516 /*%<
    517  * Parse raw wire data in 'source' as a DNS message.
    518  *
    519  * OPT records are detected and stored in the pseudo-section "opt".
    520  * TSIGs are detected and stored in the pseudo-section "tsig".
    521  *
    522  * If #DNS_MESSAGEPARSE_PRESERVEORDER is set, or if the opcode of the message
    523  * is UPDATE, a separate dns_name_t object will be created for each RR in the
    524  * message.  Each such dns_name_t will have a single rdataset containing the
    525  * single RR, and the order of the RRs in the message is preserved.
    526  * Otherwise, only one dns_name_t object will be created for each unique
    527  * owner name in the section, and each such dns_name_t will have a list
    528  * of rdatasets.  To access the names and their data, use
    529  * dns_message_firstname() and dns_message_nextname().
    530  *
    531  * If #DNS_MESSAGEPARSE_BESTEFFORT is set, errors in message content will
    532  * not be considered FORMERRs.  If the entire message can be parsed, it
    533  * will be returned and DNS_R_RECOVERABLE will be returned.
    534  *
    535  * If #DNS_MESSAGEPARSE_IGNORETRUNCATION is set then return as many complete
    536  * RR's as possible, DNS_R_RECOVERABLE will be returned.
    537  *
    538  * OPT and TSIG records are always handled specially, regardless of the
    539  * 'preserve_order' setting.
    540  *
    541  * Requires:
    542  *\li	"msg" be a valid message with parsing intent.
    543  *
    544  *\li	"source" be a wire format buffer.
    545  *
    546  * Ensures:
    547  *\li	The buffer's data format is correct.
    548  *
    549  *\li	The buffer's contents verify as correct regarding header bits, buffer
    550  * 	and rdata sizes, etc.
    551  *
    552  * Returns:
    553  *\li	#ISC_R_SUCCESS		-- all is well
    554  *\li	#ISC_R_NOMEMORY		-- no memory
    555  *\li	#DNS_R_RECOVERABLE	-- the message parsed properly, but contained
    556  *				   errors.
    557  *\li	Many other errors possible XXXMLG
    558  */
    559 
    560 isc_result_t
    561 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
    562 			isc_buffer_t *buffer);
    563 /*%<
    564  * Begin rendering on a message.  Only one call can be made to this function
    565  * per message.
    566  *
    567  * The compression context is "owned" by the message library until
    568  * dns_message_renderend() is called.  It must be invalidated by the caller.
    569  *
    570  * The buffer is "owned" by the message library until dns_message_renderend()
    571  * is called.
    572  *
    573  * Requires:
    574  *
    575  *\li	'msg' be a valid message with rendering intent.
    576  *
    577  *\li	dns_message_renderbegin() has not previously been called.
    578  *
    579  *\li	'cctx' be valid.
    580  *
    581  *\li	'buffer' is a valid buffer with length less than 65536.
    582  *
    583  * Side Effects:
    584  *
    585  *\li	The buffer is cleared before it is used.
    586  *
    587  * Returns:
    588  *\li	#ISC_R_SUCCESS		-- all is well
    589  *\li	#ISC_R_NOSPACE		-- output buffer is too small
    590  */
    591 
    592 isc_result_t
    593 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer);
    594 /*%<
    595  * Reset the buffer.  This can be used after growing the old buffer
    596  * on a ISC_R_NOSPACE return from most of the render functions.
    597  *
    598  * On successful completion, the old buffer is no longer used by the
    599  * library.  The new buffer is owned by the library until
    600  * dns_message_renderend() is called.
    601  *
    602  * Requires:
    603  *
    604  *\li	'msg' be valid.
    605  *
    606  *\li	dns_message_renderbegin() was called.
    607  *
    608  *\li	buffer != NULL.
    609  *
    610  * Returns:
    611  *\li	#ISC_R_NOSPACE		-- new buffer is too small
    612  *\li	#ISC_R_SUCCESS		-- all is well.
    613  */
    614 
    615 isc_result_t
    616 dns_message_renderreserve(dns_message_t *msg, unsigned int space);
    617 /*%<
    618  * XXXMLG should use size_t rather than unsigned int once the buffer
    619  * API is cleaned up
    620  *
    621  * Reserve "space" bytes in the given buffer.
    622  *
    623  * Requires:
    624  *
    625  *\li	'msg' be valid.
    626  *
    627  * Returns:
    628  *\li	#ISC_R_SUCCESS		-- all is well.
    629  *\li	#ISC_R_NOSPACE		-- not enough free space in the buffer.
    630  */
    631 
    632 void
    633 dns_message_renderrelease(dns_message_t *msg, unsigned int space);
    634 /*%<
    635  * XXXMLG should use size_t rather than unsigned int once the buffer
    636  * API is cleaned up
    637  *
    638  * Release "space" bytes in the given buffer that was previously reserved.
    639  *
    640  * Requires:
    641  *
    642  *\li	'msg' be valid.
    643  *
    644  *\li	'space' is less than or equal to the total amount of space reserved
    645  *	via prior calls to dns_message_renderreserve().
    646  */
    647 
    648 isc_result_t
    649 dns_message_rendersection(dns_message_t *msg, dns_section_t section,
    650 			  unsigned int options);
    651 /*%<
    652  * Render all names, rdatalists, etc from the given section at the
    653  * specified priority or higher.
    654  *
    655  * Requires:
    656  *\li	'msg' be valid.
    657  *
    658  *\li	'section' be a valid section.
    659  *
    660  *\li	dns_message_renderbegin() was called.
    661  *
    662  * Returns:
    663  *\li	#ISC_R_SUCCESS		-- all records were written, and there are
    664  *				   no more records for this section.
    665  *\li	#ISC_R_NOSPACE		-- Not enough room in the buffer to write
    666  *				   all records requested.
    667  *\li	#DNS_R_MOREDATA		-- All requested records written, and there
    668  *				   are records remaining for this section.
    669  */
    670 
    671 void
    672 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target);
    673 /*%<
    674  * Render the message header.  This is implicitly called by
    675  * dns_message_renderend().
    676  *
    677  * Requires:
    678  *
    679  *\li	'msg' be a valid message.
    680  *
    681  *\li	dns_message_renderbegin() was called.
    682  *
    683  *\li	'target' is a valid buffer with enough space to hold a message header
    684  */
    685 
    686 isc_result_t
    687 dns_message_renderend(dns_message_t *msg);
    688 /*%<
    689  * Finish rendering to the buffer.  Note that more data can be in the
    690  * 'msg' structure.  Destroying the structure will free this, or in a multi-
    691  * part EDNS1 message this data can be rendered to another buffer later.
    692  *
    693  * Requires:
    694  *
    695  *\li	'msg' be a valid message.
    696  *
    697  *\li	dns_message_renderbegin() was called.
    698  *
    699  * Returns:
    700  *\li	#ISC_R_SUCCESS		-- all is well.
    701  */
    702 
    703 void
    704 dns_message_renderreset(dns_message_t *msg);
    705 /*%<
    706  * Reset the message so that it may be rendered again.
    707  *
    708  * Notes:
    709  *
    710  *\li	If dns_message_renderbegin() has been called, dns_message_renderend()
    711  *	must be called before calling this function.
    712  *
    713  * Requires:
    714  *
    715  *\li	'msg' be a valid message with rendering intent.
    716  */
    717 
    718 isc_result_t
    719 dns_message_firstname(dns_message_t *msg, dns_section_t section);
    720 /*%<
    721  * Set internal per-section name pointer to the beginning of the section.
    722  *
    723  * The functions dns_message_firstname() and dns_message_nextname() may
    724  * be used for iterating over the owner names in a section.
    725  *
    726  * Requires:
    727  *
    728  *\li	'msg' be valid.
    729  *
    730  *\li	'section' be a valid section.
    731  *
    732  * Returns:
    733  *\li	#ISC_R_SUCCESS		-- All is well.
    734  *\li	#ISC_R_NOMORE		-- No names on given section.
    735  */
    736 
    737 isc_result_t
    738 dns_message_nextname(dns_message_t *msg, dns_section_t section);
    739 /*%<
    740  * Sets the internal per-section name pointer to point to the next name
    741  * in that section.
    742  *
    743  * Requires:
    744  *
    745  *\li	'msg' be valid.
    746  *
    747  *\li	'section' be a valid section.
    748  *
    749  *\li	dns_message_firstname() must have been called on this section,
    750  *	and the result was ISC_R_SUCCESS.
    751  *
    752  * Returns:
    753  *\li	#ISC_R_SUCCESS		-- All is well.
    754  *\li	#ISC_R_NOMORE		-- No more names in given section.
    755  */
    756 
    757 void
    758 dns_message_currentname(dns_message_t *msg, dns_section_t section,
    759 			dns_name_t **name);
    760 /*%<
    761  * Sets 'name' to point to the name where the per-section internal name
    762  * pointer is currently set.
    763  *
    764  * This function returns the name in the database, so any data associated
    765  * with it (via the name's "list" member) contains the actual rdatasets.
    766  *
    767  * Requires:
    768  *
    769  *\li	'msg' be valid.
    770  *
    771  *\li	'name' be non-NULL, and *name be NULL.
    772  *
    773  *\li	'section' be a valid section.
    774  *
    775  *\li	dns_message_firstname() must have been called on this section,
    776  *	and the result of it and any dns_message_nextname() calls was
    777  *	#ISC_R_SUCCESS.
    778  */
    779 
    780 isc_result_t
    781 dns_message_findname(dns_message_t *msg, dns_section_t section,
    782 		     const dns_name_t *target, dns_rdatatype_t type,
    783 		     dns_rdatatype_t covers, dns_name_t **foundname,
    784 		     dns_rdataset_t **rdataset);
    785 /*%<
    786  * Search for a name in the specified section.  If it is found, *name is
    787  * set to point to the name, and *rdataset is set to point to the found
    788  * rdataset (if type is specified as other than dns_rdatatype_any).
    789  *
    790  * Requires:
    791  *\li	'msg' be valid.
    792  *
    793  *\li	'section' be a named section.
    794  *
    795  *\li	If a pointer to the name is desired, 'foundname' should be non-NULL.
    796  *	If it is non-NULL, '*foundname' MUST be NULL.
    797  *
    798  *\li	If a type other than dns_datatype_any is searched for, 'rdataset'
    799  *	may be non-NULL, '*rdataset' be NULL, and will point at the found
    800  *	rdataset.  If the type is dns_datatype_any, 'rdataset' must be NULL.
    801  *
    802  *\li	'target' be a valid name.
    803  *
    804  *\li	'type' be a valid type.
    805  *
    806  *\li	If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
    807  *	Otherwise it should be 0.
    808  *
    809  * Returns:
    810  *\li	#ISC_R_SUCCESS		-- all is well.
    811  *\li	#DNS_R_NXDOMAIN		-- name does not exist in that section.
    812  *\li	#DNS_R_NXRRSET		-- The name does exist, but the desired
    813  *				   type does not.
    814  */
    815 
    816 isc_result_t
    817 dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type,
    818 		     dns_rdatatype_t covers, dns_rdataset_t **rdataset);
    819 /*%<
    820  * Search the name for the specified type.  If it is found, *rdataset is
    821  * filled in with a pointer to that rdataset.
    822  *
    823  * Requires:
    824  *\li	if '**rdataset' is non-NULL, *rdataset needs to be NULL.
    825  *
    826  *\li	'type' be a valid type, and NOT dns_rdatatype_any.
    827  *
    828  *\li	If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
    829  *	Otherwise it should be 0.
    830  *
    831  * Returns:
    832  *\li	#ISC_R_SUCCESS		-- all is well.
    833  *\li	#ISC_R_NOTFOUND		-- the desired type does not exist.
    834  */
    835 
    836 void
    837 dns_message_addname(dns_message_t *msg, dns_name_t *name,
    838 		    dns_section_t section);
    839 /*%<
    840  * Adds the name to the given section.
    841  *
    842  * It is the caller's responsibility to enforce any unique name requirements
    843  * in a section.
    844  *
    845  * Requires:
    846  *
    847  *\li	'msg' be valid, and be a renderable message.
    848  *
    849  *\li	'name' be a valid absolute name.
    850  *
    851  *\li	'section' be a named section.
    852  */
    853 
    854 void
    855 dns_message_removename(dns_message_t *msg, dns_name_t *name,
    856 		       dns_section_t section);
    857 /*%<
    858  * Remove a existing name from a given section.
    859  *
    860  * It is the caller's responsibility to ensure the name is part of the
    861  * given section.
    862  *
    863  * Requires:
    864  *
    865  *\li	'msg' be a valid message with rendering intent.
    866  *
    867  *\li	'name' be a valid absolute name.
    868  *
    869  *\li	'section' be a named section.
    870  */
    871 
    872 /*
    873  * LOANOUT FUNCTIONS
    874  *
    875  * Each of these functions loan a particular type of data to the caller.
    876  * The storage for these will vanish when the message is destroyed or
    877  * reset, and must NOT be used after these operations.
    878  */
    879 
    880 void
    881 dns_message_gettempname(dns_message_t *msg, dns_name_t **item);
    882 /*%<
    883  * Return a name that can be used for any temporary purpose, including
    884  * inserting into the message's linked lists.  The name must be returned
    885  * to the message code using dns_message_puttempname() or inserted into
    886  * one of the message's sections before the message is destroyed.
    887  *
    888  * The name will be associated with a dns_fixedname object, and will
    889  * be initialized.
    890  *
    891  * Requires:
    892  *\li	msg be a valid message
    893  *
    894  *\li	item != NULL && *item == NULL
    895  */
    896 
    897 void
    898 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item);
    899 /*%<
    900  * Return a rdata that can be used for any temporary purpose, including
    901  * inserting into the message's linked lists.  The rdata will be freed
    902  * when the message is destroyed or reset.
    903  *
    904  * Requires:
    905  *\li	msg be a valid message
    906  *
    907  *\li	item != NULL && *item == NULL
    908  */
    909 
    910 void
    911 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item);
    912 /*%<
    913  * Return a rdataset that can be used for any temporary purpose, including
    914  * inserting into the message's linked lists. The name must be returned
    915  * to the message code using dns_message_puttempname() or inserted into
    916  * one of the message's sections before the message is destroyed.
    917  *
    918  * Requires:
    919  *\li	msg be a valid message
    920  *
    921  *\li	item != NULL && *item == NULL
    922  */
    923 
    924 void
    925 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
    926 /*%<
    927  * Return a rdatalist that can be used for any temporary purpose, including
    928  * inserting into the message's linked lists.  The rdatalist will be
    929  * destroyed when the message is destroyed or reset.
    930  *
    931  * Requires:
    932  *\li	msg be a valid message
    933  *
    934  *\li	item != NULL && *item == NULL
    935  */
    936 
    937 void
    938 dns_message_puttempname(dns_message_t *msg, dns_name_t **item);
    939 /*%<
    940  * Return a borrowed name to the message's name free list.
    941  *
    942  * Requires:
    943  *\li	msg be a valid message
    944  *
    945  *\li	item != NULL && *item point to a name returned by
    946  *	dns_message_gettempname()
    947  *
    948  * Ensures:
    949  *\li	*item == NULL
    950  */
    951 
    952 void
    953 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item);
    954 /*%<
    955  * Return a borrowed rdata to the message's rdata free list.
    956  *
    957  * Requires:
    958  *\li	msg be a valid message
    959  *
    960  *\li	item != NULL && *item point to a rdata returned by
    961  *	dns_message_gettemprdata()
    962  *
    963  * Ensures:
    964  *\li	*item == NULL
    965  */
    966 
    967 void
    968 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item);
    969 /*%<
    970  * Return a borrowed rdataset to the message's rdataset free list.
    971  *
    972  * Requires:
    973  *\li	msg be a valid message
    974  *
    975  *\li	item != NULL && *item point to a rdataset returned by
    976  *	dns_message_gettemprdataset()
    977  *
    978  * Ensures:
    979  *\li	*item == NULL
    980  */
    981 
    982 void
    983 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
    984 /*%<
    985  * Return a borrowed rdatalist to the message's rdatalist free list.
    986  *
    987  * Requires:
    988  *\li	msg be a valid message
    989  *
    990  *\li	item != NULL && *item point to a rdatalist returned by
    991  *	dns_message_gettemprdatalist()
    992  *
    993  * Ensures:
    994  *\li	*item == NULL
    995  */
    996 
    997 isc_result_t
    998 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
    999 		       unsigned int *flagsp);
   1000 /*%<
   1001  * Assume the remaining region of "source" is a DNS message.  Peek into
   1002  * it and fill in "*idp" with the message id, and "*flagsp" with the flags.
   1003  *
   1004  * Requires:
   1005  *
   1006  *\li	source != NULL
   1007  *
   1008  * Ensures:
   1009  *
   1010  *\li	if (idp != NULL) *idp == message id.
   1011  *
   1012  *\li	if (flagsp != NULL) *flagsp == message flags.
   1013  *
   1014  * Returns:
   1015  *
   1016  *\li	#ISC_R_SUCCESS		-- all is well.
   1017  *
   1018  *\li	#ISC_R_UNEXPECTEDEND	-- buffer doesn't contain enough for a header.
   1019  */
   1020 
   1021 isc_result_t
   1022 dns_message_reply(dns_message_t *msg, bool want_question_section);
   1023 /*%<
   1024  * Start formatting a reply to the query in 'msg'.
   1025  *
   1026  * Requires:
   1027  *
   1028  *\li	'msg' is a valid message which contains a query.
   1029  *
   1030  * Ensures:
   1031  *
   1032  *\li	The message will have a rendering intent.  If 'want_question_section'
   1033  *	is true, the message opcode is query or notify, and the question
   1034  *	section is present and properly formatted, then the question section
   1035  *	will be included in the reply.  All other sections will be cleared.
   1036  *	The QR flag will be set, the RD flag will be preserved, and all other
   1037  *	flags will be cleared.
   1038  *
   1039  * Returns:
   1040  *
   1041  *\li	#ISC_R_SUCCESS		-- all is well.
   1042  *
   1043  *\li	#DNS_R_FORMERR		-- the header or question section of the
   1044  *				   message is invalid, replying is impossible.
   1045  *				   If DNS_R_FORMERR is returned when
   1046  *				   want_question_section is false, then
   1047  *				   it's the header section that's bad;
   1048  *				   otherwise either of the header or question
   1049  *				   sections may be bad.
   1050  */
   1051 
   1052 dns_rdataset_t *
   1053 dns_message_getopt(dns_message_t *msg);
   1054 /*%<
   1055  * Get the OPT record for 'msg'.
   1056  *
   1057  * Requires:
   1058  *
   1059  *\li	'msg' is a valid message.
   1060  *
   1061  * Returns:
   1062  *
   1063  *\li	The OPT rdataset of 'msg', or NULL if there isn't one.
   1064  */
   1065 
   1066 isc_result_t
   1067 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt);
   1068 /*%<
   1069  * Set/clear the OPT record for 'msg'.
   1070  *
   1071  * Requires:
   1072  *
   1073  *\li	'msg' is a valid message with rendering intent
   1074  *	and no sections have been rendered.
   1075  *
   1076  *\li	'opt' is a valid OPT rdataset or NULL.
   1077  *
   1078  * Ensures:
   1079  *
   1080  *\li	The OPT record has either been freed or ownership of it has
   1081  *	been transferred to the message.
   1082  *
   1083  *\li	If ISC_R_SUCCESS was returned, the OPT record will be rendered
   1084  *	when dns_message_renderend() is called.
   1085  *
   1086  * Returns:
   1087  *
   1088  *\li	#ISC_R_SUCCESS		-- all is well.
   1089  *
   1090  *\li	#ISC_R_NOSPACE		-- there is no space for the OPT record.
   1091  */
   1092 
   1093 dns_rdataset_t *
   1094 dns_message_gettsig(dns_message_t *msg, const dns_name_t **owner);
   1095 /*%<
   1096  * Get the TSIG record and owner for 'msg'.
   1097  *
   1098  * Requires:
   1099  *
   1100  *\li	'msg' is a valid message.
   1101  *\li	'owner' is NULL or *owner is NULL.
   1102  *
   1103  * Returns:
   1104  *
   1105  *\li	The TSIG rdataset of 'msg', or NULL if there isn't one.
   1106  *
   1107  * Ensures:
   1108  *
   1109  *\li	If 'owner' is not NULL, it will point to the owner name.
   1110  */
   1111 
   1112 isc_result_t
   1113 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key);
   1114 /*%<
   1115  * Set the tsig key for 'msg'.  This is only necessary for when rendering a
   1116  * query or parsing a response.  The key (if non-NULL) is attached to
   1117  * to the message, and will be detached when the message is destroyed.
   1118  *
   1119  * Requires:
   1120  *
   1121  *\li	'msg' is a valid message.
   1122  *
   1123  *\li	'key' is a valid tsig key or NULL.
   1124  *
   1125  * Returns:
   1126  *
   1127  *\li	#ISC_R_SUCCESS		-- all is well.
   1128  *
   1129  *\li	#ISC_R_NOSPACE		-- there is no space for the TSIG record.
   1130  */
   1131 
   1132 dns_tsigkey_t *
   1133 dns_message_gettsigkey(dns_message_t *msg);
   1134 /*%<
   1135  * Gets the tsig key for 'msg'.
   1136  *
   1137  * Requires:
   1138  *
   1139  *\li	'msg' is a valid message, and dns_message_settsigkey() has been
   1140  *	run previously.
   1141  */
   1142 
   1143 void
   1144 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig);
   1145 /*%<
   1146  * Indicates that 'querytsig' is the TSIG from the signed query for which
   1147  * 'msg' is the response.  This is also used for chained TSIGs in TCP
   1148  * responses.
   1149  *
   1150  * Requires:
   1151  *
   1152  *\li	'querytsig' is a valid buffer as returned by dns_message_getquerytsig(),
   1153  *	or NULL
   1154  *
   1155  *\li	'msg' is a valid message on which dns_message_setquerytsig() has
   1156  *	not previously been run.
   1157  */
   1158 
   1159 isc_result_t
   1160 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
   1161 			 isc_buffer_t **querytsig);
   1162 /*%<
   1163  * Gets the tsig from the TSIG from the signed query 'msg'.  This is also used
   1164  * for chained TSIGs in TCP responses.  Unlike dns_message_gettsig, this makes
   1165  * a copy of the data, so can be used if the message is destroyed.
   1166  *
   1167  * Requires:
   1168  *
   1169  *\li	'msg' is a valid signed message
   1170  *\li	'mctx' is a valid memory context
   1171  *\li	querytsig != NULL && *querytsig == NULL
   1172  *
   1173  * Returns:
   1174  *
   1175  *\li	#ISC_R_SUCCESS
   1176  *\li	#ISC_R_NOMEMORY
   1177  *
   1178  * Ensures:
   1179  *\li 	'tsig' points to NULL or an allocated buffer which must be freed
   1180  * 	by the caller.
   1181  */
   1182 
   1183 dns_rdataset_t *
   1184 dns_message_getsig0(dns_message_t *msg, const dns_name_t **owner);
   1185 /*%<
   1186  * Get the SIG(0) record and owner for 'msg'.
   1187  *
   1188  * Requires:
   1189  *
   1190  *\li	'msg' is a valid message.
   1191  *\li	'owner' is NULL or *owner is NULL.
   1192  *
   1193  * Returns:
   1194  *
   1195  *\li	The SIG(0) rdataset of 'msg', or NULL if there isn't one.
   1196  *
   1197  * Ensures:
   1198  *
   1199  *\li	If 'owner' is not NULL, it will point to the owner name.
   1200  */
   1201 
   1202 isc_result_t
   1203 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key);
   1204 /*%<
   1205  * Set the SIG(0) key for 'msg'.
   1206  *
   1207  * Requires:
   1208  *
   1209  *\li	'msg' is a valid message with rendering intent,
   1210  *	dns_message_renderbegin() has been called, and no sections have been
   1211  *	rendered.
   1212  *\li	'key' is a valid sig key or NULL.
   1213  *
   1214  * Returns:
   1215  *
   1216  *\li	#ISC_R_SUCCESS		-- all is well.
   1217  *
   1218  *\li	#ISC_R_NOSPACE		-- there is no space for the SIG(0) record.
   1219  */
   1220 
   1221 dst_key_t *
   1222 dns_message_getsig0key(dns_message_t *msg);
   1223 /*%<
   1224  * Gets the SIG(0) key for 'msg'.
   1225  *
   1226  * Requires:
   1227  *
   1228  *\li	'msg' is a valid message
   1229  */
   1230 
   1231 void
   1232 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer);
   1233 /*%<
   1234  * Give the *buffer to the message code to clean up when it is no
   1235  * longer needed.  This is usually when the message is reset or
   1236  * destroyed.
   1237  *
   1238  * Requires:
   1239  *
   1240  *\li	msg be a valid message.
   1241  *
   1242  *\li	buffer != NULL && *buffer is a valid isc_buffer_t, which was
   1243  *	dynamically allocated via isc_buffer_allocate().
   1244  */
   1245 
   1246 isc_result_t
   1247 dns_message_signer(dns_message_t *msg, dns_name_t *signer);
   1248 /*%<
   1249  * If this message was signed, return the identity of the signer.
   1250  * Unless ISC_R_NOTFOUND is returned, signer will reflect the name of the
   1251  * key that signed the message.
   1252  *
   1253  * Requires:
   1254  *
   1255  *\li	msg is a valid message with parsing intent.
   1256  *\li	signer is a valid name
   1257  *
   1258  * Returns:
   1259  *
   1260  *\li	#ISC_R_SUCCESS		- the message was signed, and *signer
   1261  *				  contains the signing identity
   1262  *
   1263  *\li	#ISC_R_NOTFOUND		- no TSIG or SIG(0) record is present in the
   1264  *				  message
   1265  *
   1266  *\li	#DNS_R_TSIGVERIFYFAILURE	- the message was signed by a TSIG, but
   1267  * the signature failed to verify
   1268  *
   1269  *\li	#DNS_R_TSIGERRORSET	- the message was signed by a TSIG and
   1270  *				  verified, but the query was rejected by
   1271  *				  the server
   1272  *
   1273  *\li	#DNS_R_NOIDENTITY	- the message was signed by a TSIG and
   1274  *				  verified, but the key has no identity since
   1275  *				  it was generated by an unsigned TKEY process
   1276  *
   1277  *\li	#DNS_R_SIGINVALID	- the message was signed by a SIG(0), but
   1278  *				  the signature failed to verify
   1279  *
   1280  *\li	#DNS_R_NOTVERIFIEDYET	- the message was signed by a TSIG or SIG(0),
   1281  *				  but the signature has not been verified yet
   1282  */
   1283 
   1284 isc_result_t
   1285 dns_message_checksig(dns_message_t *msg, dns_view_t *view);
   1286 /*%<
   1287  * If this message was signed, verify the signature.
   1288  *
   1289  * Requires:
   1290  *
   1291  *\li	msg is a valid parsed message.
   1292  *\li	view is a valid view or NULL
   1293  *
   1294  * Returns:
   1295  *
   1296  *\li	#ISC_R_SUCCESS		- the message was unsigned, or the message
   1297  *				  was signed correctly.
   1298  *
   1299  *\li	#DNS_R_EXPECTEDTSIG	- A TSIG was expected, but not seen
   1300  *\li	#DNS_R_UNEXPECTEDTSIG	- A TSIG was seen but not expected
   1301  *\li	#DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
   1302  */
   1303 
   1304 isc_result_t
   1305 dns_message_checksig_async(dns_message_t *msg, dns_view_t *view,
   1306 			   isc_loop_t *loop, dns_message_cb_t cb, void *cbarg);
   1307 /*%<
   1308  * Run dns_message_checksig() in an offloaded thread and return its result
   1309  * using the 'cb' callback function, running on the 'loop'.
   1310  *
   1311  * Requires:
   1312  *
   1313  *\li	msg is a valid parsed message.
   1314  *\li	view is a valid view or NULL.
   1315  *\li	loop is a valid loop.
   1316  *\li	cb is a valid callback function.
   1317  *
   1318  * Returns:
   1319  *
   1320  *\li	#DNS_R_WAIT
   1321  *
   1322  */
   1323 
   1324 void
   1325 dns_message_resetsig(dns_message_t *msg);
   1326 /*%<
   1327  * Reset the signature state.
   1328  *
   1329  * Requires:
   1330  *\li	'msg' is a valid parsed message.
   1331  */
   1332 
   1333 isc_region_t *
   1334 dns_message_getrawmessage(dns_message_t *msg);
   1335 /*%<
   1336  * Retrieve the raw message in compressed wire format.  The message must
   1337  * have been successfully parsed for it to have been saved.
   1338  *
   1339  * Requires:
   1340  *\li	msg is a valid parsed message.
   1341  *
   1342  * Returns:
   1343  *\li	NULL	if there is no saved message.
   1344  *	a pointer to a region which refers the dns message.
   1345  */
   1346 
   1347 void
   1348 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
   1349 			 dns_aclenv_t *env, dns_acl_t *acl,
   1350 			 const dns_aclelement_t *element);
   1351 /*%<
   1352  * Define the order in which RR sets get rendered by
   1353  * dns_message_rendersection() to be the ascending order
   1354  * defined by the integer value returned by 'order' when
   1355  * given each RR and a ns_sortlist_arg_t constructed from 'env',
   1356  * 'acl', and 'element' as arguments.
   1357  *
   1358  * If 'order' is NULL, a default order is used.
   1359  *
   1360  * Requires:
   1361  *\li	msg be a valid message.
   1362  *\li	If 'env' is NULL, 'order' must be NULL.
   1363  *\li	If 'env' is not NULL, 'order' must not be NULL and at least one of
   1364  *	'acl' and 'element' must also not be NULL.
   1365  */
   1366 
   1367 void
   1368 dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
   1369 /*%<
   1370  * Adjust the time used to sign/verify a message by timeadjust.
   1371  * Currently only TSIG.
   1372  *
   1373  * Requires:
   1374  *\li	msg be a valid message.
   1375  */
   1376 
   1377 int
   1378 dns_message_gettimeadjust(dns_message_t *msg);
   1379 /*%<
   1380  * Return the current time adjustment.
   1381  *
   1382  * Requires:
   1383  *\li	msg be a valid message.
   1384  */
   1385 
   1386 void
   1387 dns_message_logpacket(dns_message_t *message, const char *description,
   1388 		      const isc_sockaddr_t *address,
   1389 		      isc_logcategory_t *category, isc_logmodule_t *module,
   1390 		      int level, isc_mem_t *mctx);
   1391 
   1392 void
   1393 dns_message_logfmtpacket(dns_message_t *message, const char *description,
   1394 			 const isc_sockaddr_t *address,
   1395 			 isc_logcategory_t *category, isc_logmodule_t *module,
   1396 			 const dns_master_style_t *style, int level,
   1397 			 isc_mem_t *mctx);
   1398 /*%<
   1399  * Log 'message' at the specified logging parameters.
   1400  *
   1401  * For dns_message_logpacket and dns_message_logfmtpacket expect the
   1402  * 'description' to end in a newline.
   1403  *
   1404  * Requires:
   1405  *\li	'message' be a valid DNS message.
   1406  *\li	'description' to be non-NULL.
   1407  *\li	'address' to be non-NULL.
   1408  *\li	'category' to be a valid logging category.
   1409  *\li	'module' to be a valid logging module.
   1410  *\li	'mctx' to be a valid memory context.
   1411  */
   1412 
   1413 isc_result_t
   1414 dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt,
   1415 		     unsigned int version, uint16_t udpsize, unsigned int flags,
   1416 		     dns_ednsopt_t *ednsopts, size_t count);
   1417 /*%<
   1418  * Built a opt record.
   1419  *
   1420  * Requires:
   1421  *\li	msg be a valid message.
   1422  *\li	opt to be a non NULL and *opt to be NULL.
   1423  *
   1424  * Returns:
   1425  *\li	 ISC_R_SUCCESS
   1426  *\li	 ISC_R_NOSPACE
   1427  */
   1428 
   1429 void
   1430 dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass);
   1431 /*%<
   1432  * Set the expected class of records in the response.
   1433  *
   1434  * Requires:
   1435  *\li	msg be a valid message with parsing intent.
   1436  */
   1437 
   1438 void
   1439 dns_message_setpadding(dns_message_t *msg, uint16_t padding);
   1440 /*%<
   1441  * Set the padding block size in the response.
   1442  * 0 means no padding (default).
   1443  *
   1444  * Requires:
   1445  *\li	msg be a valid message.
   1446  */
   1447 
   1448 void
   1449 dns_message_clonebuffer(dns_message_t *msg);
   1450 /*%<
   1451  * Clone the query or saved buffers if they where not cloned
   1452  * when parsing.
   1453  *
   1454  * Requires:
   1455  *\li	msg be a valid message.
   1456  */
   1457 
   1458 isc_result_t
   1459 dns_message_minttl(dns_message_t *msg, const dns_section_t sectionid,
   1460 		   dns_ttl_t *pttl);
   1461 /*%<
   1462  * Get the smallest TTL from the 'sectionid' section of a rendered
   1463  * message.
   1464  *
   1465  * Requires:
   1466  *\li	msg be a valid rendered message;
   1467  *\li	'pttl != NULL'.
   1468  */
   1469 
   1470 isc_result_t
   1471 dns_message_response_minttl(dns_message_t *msg, dns_ttl_t *pttl);
   1472 /*%<
   1473  * Get the smalled TTL from the Answer section of 'msg', or if empty, try
   1474  * the MIN(SOA TTL, SOA MINIMUM) value from an SOA record in the Authority
   1475  * section. If neither of these are set, return ISC_R_NOTFOUND.
   1476  *
   1477  * Requires:
   1478  *\li	msg be a valid rendered message;
   1479  *\li	'pttl != NULL'.
   1480  */
   1481 
   1482 void
   1483 dns_message_createpools(isc_mem_t *mctx, isc_mempool_t **namepoolp,
   1484 			isc_mempool_t **rdspoolp);
   1485 void
   1486 dns_message_destroypools(isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp);
   1487 
   1488 bool
   1489 dns_message_hasdname(dns_message_t *msg);
   1490 /*%<
   1491  * Return whether a DNAME was detected in the ANSWER section of a QUERY
   1492  * message when it was parsed.
   1493  */
   1494 
   1495 ISC_LANG_ENDDECLS
   1496