1/*
2 * packet.h -- low-level DNS packet encoding and decoding functions.
3 *
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10#ifndef PACKET_H
11#define PACKET_H
12
13#include <sys/types.h>
14
15#include "dns.h"
16#include "namedb.h"
17
18struct query;
19
20/*
21 * Set of macro's to deal with the dns message header as specified
22 * in RFC1035 in portable way.
23 *
24 */
25
26/*
27 *
28 *                                    1  1  1  1  1  1
29 *      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
30 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
31 *    |                      ID                       |
32 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
33 *    |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
34 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
35 *    |                    QDCOUNT                    |
36 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
37 *    |                    ANCOUNT                    |
38 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
39 *    |                    NSCOUNT                    |
40 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
41 *    |                    ARCOUNT                    |
42 *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43 *
44 */
45
46/* The length of the header */
47#define	QHEADERSZ	12
48
49/* First octet of flags */
50#define	RD_MASK		0x01U
51#define	RD_SHIFT	0
52#define	RD(packet)      (*buffer_at((packet), 2) & RD_MASK)
53#define	RD_SET(packet)	(*buffer_at((packet), 2) |= RD_MASK)
54#define	RD_CLR(packet)	(*buffer_at((packet), 2) &= ~RD_MASK)
55
56#define TC_MASK		0x02U
57#define TC_SHIFT	1
58#define	TC(packet)	(*buffer_at((packet), 2) & TC_MASK)
59#define	TC_SET(packet)	(*buffer_at((packet), 2) |= TC_MASK)
60#define	TC_CLR(packet)	(*buffer_at((packet), 2) &= ~TC_MASK)
61
62#define	AA_MASK		0x04U
63#define	AA_SHIFT	2
64#define	AA(packet)	(*buffer_at((packet), 2) & AA_MASK)
65#define	AA_SET(packet)	(*buffer_at((packet), 2) |= AA_MASK)
66#define	AA_CLR(packet)	(*buffer_at((packet), 2) &= ~AA_MASK)
67
68#define	OPCODE_MASK	0x78U
69#define	OPCODE_SHIFT	3
70#define	OPCODE(packet)	((*buffer_at((packet), 2) & OPCODE_MASK) >> OPCODE_SHIFT)
71#define	OPCODE_SET(packet, opcode) \
72	(*buffer_at((packet), 2) = (*buffer_at((packet), 2) & ~OPCODE_MASK) | ((opcode) << OPCODE_SHIFT))
73
74#define	QR_MASK		0x80U
75#define	QR_SHIFT	7
76#define	QR(packet)	(*buffer_at((packet), 2) & QR_MASK)
77#define	QR_SET(packet)	(*buffer_at((packet), 2) |= QR_MASK)
78#define	QR_CLR(packet)	(*buffer_at((packet), 2) &= ~QR_MASK)
79
80/* Second octet of flags */
81#define	RCODE_MASK	0x0fU
82#define	RCODE_SHIFT	0
83#define	RCODE(packet)	(*buffer_at((packet), 3) & RCODE_MASK)
84#define	RCODE_SET(packet, rcode) \
85	(*buffer_at((packet), 3) = (*buffer_at((packet), 3) & ~RCODE_MASK) | (rcode))
86
87#define	CD_MASK		0x10U
88#define	CD_SHIFT	4
89#define	CD(packet)	(*buffer_at((packet), 3) & CD_MASK)
90#define	CD_SET(packet)	(*buffer_at((packet), 3) |= CD_MASK)
91#define	CD_CLR(packet)	(*buffer_at((packet), 3) &= ~CD_MASK)
92
93#define	AD_MASK		0x20U
94#define	AD_SHIFT	5
95#define	AD(packet)	(*buffer_at((packet), 3) & AD_MASK)
96#define	AD_SET(packet)	(*buffer_at((packet), 3) |= AD_MASK)
97#define	AD_CLR(packet)	(*buffer_at((packet), 3) &= ~AD_MASK)
98
99#define	Z_MASK		0x40U
100#define	Z_SHIFT		6
101#define	Z(packet)	(*buffer_at((packet), 3) & Z_MASK)
102#define	Z_SET(packet)	(*buffer_at((packet), 3) |= Z_MASK)
103#define	Z_CLR(packet)	(*buffer_at((packet), 3) &= ~Z_MASK)
104
105#define	RA_MASK		0x80U
106#define	RA_SHIFT	7
107#define	RA(packet)	(*buffer_at((packet), 3) & RA_MASK)
108#define	RA_SET(packet)	(*buffer_at((packet), 3) |= RA_MASK)
109#define	RA_CLR(packet)	(*buffer_at((packet), 3) &= ~RA_MASK)
110
111/* Query ID */
112#define	ID(packet)		(buffer_read_u16_at((packet), 0))
113#define	ID_SET(packet, id)	(buffer_write_u16_at((packet), 0, (id)))
114
115/* Flags, RCODE, and OPCODE. */
116#define FLAGS(packet)		(buffer_read_u16_at((packet), 2))
117#define FLAGS_SET(packet, f)	(buffer_write_u16_at((packet), 2, (f)))
118
119/* Counter of the question section */
120#define	QDCOUNT(packet)		(buffer_read_u16_at((packet), 4))
121#define QDCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 4, (c)))
122
123/* Counter of the answer section */
124#define	ANCOUNT(packet)		(buffer_read_u16_at((packet), 6))
125#define ANCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 6, (c)))
126
127/* Counter of the authority section */
128#define	NSCOUNT(packet)		(buffer_read_u16_at((packet), 8))
129#define NSCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 8, (c)))
130
131/* Counter of the additional section */
132#define	ARCOUNT(packet)		(buffer_read_u16_at((packet), 10))
133#define ARCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 10, (c)))
134
135/* Miscellaneous limits */
136#define MAX_PACKET_SIZE         65535   /* Maximum supported size of DNS packets.  */
137
138#define	QIOBUFSZ		(MAX_PACKET_SIZE + MAX_RR_SIZE)
139
140#define	MAXRRSPP		10240    /* Maximum number of rr's per packet */
141#define MAX_COMPRESSED_DNAMES	MAXRRSPP /* Maximum number of compressed domains. */
142#define MAX_COMPRESSION_OFFSET  16383	 /* Compression pointers are 14 bit. */
143#define IPV4_MINIMAL_RESPONSE_SIZE 1232	 /* Recommended minimal edns size for IPv4 */
144#define IPV6_MINIMAL_RESPONSE_SIZE 1220	 /* Recommended minimal edns size for IPv6 */
145
146/* use round robin rotation */
147extern int round_robin;
148/* use minimal responses (more minimal, with additional only for referrals) */
149extern int minimal_responses;
150
151/*
152 * Encode RR with OWNER as owner name into QUERY.  Returns the number
153 * of RRs successfully encoded.
154 */
155int packet_encode_rr(struct query *query,
156		     domain_type *owner,
157		     rr_type *rr,
158		     uint32_t ttl);
159
160/*
161 * Encode RRSET with OWNER as the owner name into QUERY.  Returns the
162 * number of RRs successfully encoded.  If TRUNCATE_RRSET the entire
163 * RRset is truncated in case an RR (or the RRsets signature) does not
164 * fit.
165 */
166int packet_encode_rrset(struct query *query,
167			domain_type *owner,
168			rrset_type *rrset,
169			int truncate_rrset,
170			size_t minimal_respsize,
171			int* done);
172
173/*
174 * Skip the RR at the current position in PACKET.
175 */
176int packet_skip_rr(buffer_type *packet, int question_section);
177
178/*
179 * Skip the dname at the current position in PACKET.
180 */
181int packet_skip_dname(buffer_type *packet);
182
183/*
184 * Read the RR at the current position in PACKET.
185 */
186rr_type *packet_read_rr(region_type *region,
187			domain_table_type *owners,
188			buffer_type *packet,
189			int question_section);
190
191/*
192 * read a query entry from network packet given in buffer.
193 * does not follow compression ptrs, checks for errors (returns 0).
194 * Dest must be at least MAXDOMAINLEN long.
195 */
196int packet_read_query_section(buffer_type *packet,
197			uint8_t* dest,
198			uint16_t* qtype,
199			uint16_t* qclass);
200
201/* read notify SOA serial from packet. buffer position is unmodified on return.
202 * returns false on no-serial found or parse failure. */
203int packet_find_notify_serial(buffer_type *packet, uint32_t* serial);
204
205#endif /* PACKET_H */
206