message.h 6.63 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (C) 1999  Internet Software Consortium.
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

18 19
#ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

/***
 ***	Imports
 ***/

#include <isc/mem.h>

#include <dns/types.h>
#include <dns/result.h>
#include <dns/name.h>
#include <dns/rdataset.h>
#include <dns/callbacks.h>

/*
 * How this beast works:
 *
36
 * When a dns message is received in a buffer, dns_message_fromwire() is called
37 38 39 40 41 42 43 44
 * on the memory region.  Various items are checked including the format
 * of the message (if counts are right, if counts consume the entire sections,
 * and if sections consume the entire message) and known pseudo-RRs in the
 * additional data section are analyzed and removed.
 *
 * TSIG checking is also done at this layer, and any DNSSEC information should
 * also be performed at this time.
 *
45
 * If dns_message_fromwire() returns DNS_R_MOREDATA additional
46 47
 * message packets are required.  This implies an EDNS message.
 *
48
 * When going from structure to wire, dns_message_towire() will return
Michael Graff's avatar
typo  
Michael Graff committed
49
 * DNS_R_MOREDATA if there is more data left in the output buffer that
50 51 52 53 54 55 56 57 58
 * could not be rendered into the exisiting buffer.
 *
 * XXX Needed:  ways to handle TSIG and DNSSEC, supply TSIG and DNSSEC
 * keys, set and retrieve EDNS information, add rdata to a section,
 * move rdata from one section to another, remove rdata, etc.
 */

ISC_LANG_BEGINDECLS

59 60 61 62 63
#define DNS_MESSAGE_QR			0x8000U
#define DNS_MESSAGE_AA			0x0400U
#define DNS_MESSAGE_TC			0x0200U
#define DNS_MESSAGE_RD			0x0100U
#define DNS_MESSAGE_RA			0x0080U
64

65 66 67
#define DNS_MESSAGE_OPCODE_MASK		0x7000U
#define DNS_MESSAGE_OPCODE_SHIFT	    11
#define DNS_MESSAGE_RCODE_MASK		0x000fU
68 69 70 71

typedef struct {
	unsigned int			magic;		/* magic */

Michael Graff's avatar
Michael Graff committed
72 73 74 75 76 77 78 79 80 81 82 83
	unsigned int			id;
	unsigned int			flags;		/* this msg's flags */
	unsigned int			rcode;		/* this msg's rcode */
	unsigned int			opcode;		/* this msg's opcode */
	unsigned int			qcount;		/* this msg's counts */
	unsigned int			ancount;
	unsigned int			aucount;
	unsigned int			adcount;
	dns_namelist_t			question;
	dns_namelist_t			answer;
	dns_namelist_t			authority;
	dns_namelist_t			additional;
84 85 86 87 88

	/* XXX should be an isc_buffer_t? */
	unsigned char		       *data;		/* start of raw data */
	unsigned int			datalen;	/* length of data */

89 90
	ISC_LINK(dns_messageelem_t)	link;		/* next msg */
} dns_messageelem_t;
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121


/*
 * This structure doesn't directly map into a wire format, but is used
 * to keep track of multiple DNS messages which all refer to the same
 * "logical message" (as in edns0)
 *
 * When reading a stream of messages in, the namelists can be "flattened"
 * or "consumed" into the dns_namelist_t fields below as messages arrive.  The
 * message counts will be updated in the appropriate manner in the message.
 *
 * When rendering the "logical message" into multiple wire messages, the
 * various dns_namelist_t fields are removed from these lists and added
 * (in order, of course) to the wire format messages.  Rendering can
 * happen immediately or as time permits.
 */
typedef struct {
	unsigned int			magic;

	unsigned int			id;		/* overall ID */
	unsigned int			flags;		/* overall flags */
	unsigned int			qcount;		/* total qcount */
	unsigned int			ancount;
	unsigned int			aucount;
	unsigned int			adcount;
	dns_namelist_t			question;	/* see above */
	dns_namelist_t			answer;
	dns_namelist_t			authority;
	dns_namelist_t			additional;

	unsigned int			nmsgs;
122 123
	ISC_LIST(dns_messageelem_t)	msgs;
} dns_message_t;
Michael Graff's avatar
Michael Graff committed
124

125
void dns_message_init(dns_message_t *msg);
Michael Graff's avatar
Michael Graff committed
126 127 128 129 130 131 132 133
/*
 * initialize msg structure.  Must be called on a new (or reused) structure.
 *
 * Ensures:
 *	The data in "msg" is set to indicate an unused and empty msg
 *	structure.
 */

134 135
dns_result_t dns_message_associate(dns_message_t *msg,
				   void *buffer, size_t buflen);
Michael Graff's avatar
Michael Graff committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
/*
 * Associate a buffer with a message structure.  This function will
 * validate the buffer, allocate an internal message element to hold
 * the buffer's information, and update various counters.  Also, any
 * DNSSEC or TSIG signatures are verified at this time.
 *
 * If this is a multi-packet message (edns) and more data is required to
 * build the full message state, DNS_R_MOREDATA is returned.  In this case,
 * this function should be repeated with all input buffers until DNS_R_SUCCESS
 * (or an error) is returned.
 *
 * Requires:
 *	"msg" be valid.
 *
 *	"buffer" have "sane" contents.
 *
 * Ensures:
 *	The buffer's data format is correct.
 *
 *	The buffer's contents verify as correct regarding signatures,
 *	bits set, etc.
 *
 * Returns:
 *	DNS_R_SUCCESS		-- all is well
 *	DNS_R_NOMEM		-- no memory
 *	DNS_R_MOREDATA		-- more packets needed for complete message
 *	DNS_R_???		-- bad signature (XXX need more of these)
 */

165
dns_messageelem_t *dns_messageelem_first(dns_message_t *msg);
Michael Graff's avatar
Michael Graff committed
166 167 168 169 170 171 172 173 174 175 176
/*
 * Return the first message element's pointer.
 *
 * Requires:
 *	"msg" be valid.
 *
 * Returns:
 *	The first element on the message buffer list, or NULL if no buffers
 *	are associated.
 */

177 178
dns_messageelem_t *dns_messageelem_next(dns_message_t *msg,
					dns_messageelem_t *elem);
Michael Graff's avatar
Michael Graff committed
179 180 181 182 183 184 185 186 187 188 189 190 191
/*
 * Return the next message element pointer.
 *
 * Requires:
 *	"msg" be valid.
 *
 *	"msgelem" be valid, and part of the chain of elements for "msg".
 *
 * Returns:
 *	The next element on the message buffer list, or NULL if no more
 *	exist.
 */

192
dns_name_t *dns_message_firstname(dns_message_t *msg, dns_namelist_t *section);
Michael Graff's avatar
Michael Graff committed
193 194 195 196
/*
 * Returns a pointer to the first name in the specified section.
 */

197 198
dns_name_t *dns_message_nextname(dns_message_t *msg, dns_namelist_t *section,
				 dns_name_t *name);
Michael Graff's avatar
Michael Graff committed
199 200 201 202
/*
 * Returns a pointer to the next name in the specified section.
 */

203 204
void dns_message_movename(dns_message_t *msg, dns_namelist_t *fromsection,
			  dns_namelist_t *tosection);
Michael Graff's avatar
Michael Graff committed
205 206 207 208
/*
 * Move a name from one section to another.
 */

209 210
dns_result_t dns_message_addname(dns_message_t *msg, dns_namelist_t *section,
				 dns_name_t *name);
Michael Graff's avatar
Michael Graff committed
211 212 213 214 215
/*
 * Adds the name to the given section.
 *
 * Caller must ensure that the name does not already exist.
 */
216 217 218 219

ISC_LANG_ENDDECLS

#endif	/* DNS_DNS_H */