xref: /openbsd-src/usr.sbin/nsd/packet.h (revision 3efee2e132f9af6db74577d714f3304be2b3af74)
162ac0c33Sjakob /*
262ac0c33Sjakob  * packet.h -- low-level DNS packet encoding and decoding functions.
362ac0c33Sjakob  *
4d3fecca9Ssthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob  *
662ac0c33Sjakob  * See LICENSE for the license.
762ac0c33Sjakob  *
862ac0c33Sjakob  */
962ac0c33Sjakob 
10*3efee2e1Sflorian #ifndef PACKET_H
11*3efee2e1Sflorian #define PACKET_H
1262ac0c33Sjakob 
1362ac0c33Sjakob #include <sys/types.h>
1462ac0c33Sjakob 
1562ac0c33Sjakob #include "dns.h"
1662ac0c33Sjakob #include "namedb.h"
1762ac0c33Sjakob 
1862ac0c33Sjakob struct query;
1962ac0c33Sjakob 
2062ac0c33Sjakob /*
2162ac0c33Sjakob  * Set of macro's to deal with the dns message header as specified
2262ac0c33Sjakob  * in RFC1035 in portable way.
2362ac0c33Sjakob  *
2462ac0c33Sjakob  */
2562ac0c33Sjakob 
2662ac0c33Sjakob /*
2762ac0c33Sjakob  *
2862ac0c33Sjakob  *                                    1  1  1  1  1  1
2962ac0c33Sjakob  *      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
3062ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3162ac0c33Sjakob  *    |                      ID                       |
3262ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3362ac0c33Sjakob  *    |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
3462ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3562ac0c33Sjakob  *    |                    QDCOUNT                    |
3662ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3762ac0c33Sjakob  *    |                    ANCOUNT                    |
3862ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
3962ac0c33Sjakob  *    |                    NSCOUNT                    |
4062ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
4162ac0c33Sjakob  *    |                    ARCOUNT                    |
4262ac0c33Sjakob  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
4362ac0c33Sjakob  *
4462ac0c33Sjakob  */
4562ac0c33Sjakob 
4662ac0c33Sjakob /* The length of the header */
4762ac0c33Sjakob #define	QHEADERSZ	12
4862ac0c33Sjakob 
4962ac0c33Sjakob /* First octet of flags */
5062ac0c33Sjakob #define	RD_MASK		0x01U
5162ac0c33Sjakob #define	RD_SHIFT	0
5262ac0c33Sjakob #define	RD(packet)      (*buffer_at((packet), 2) & RD_MASK)
5362ac0c33Sjakob #define	RD_SET(packet)	(*buffer_at((packet), 2) |= RD_MASK)
5462ac0c33Sjakob #define	RD_CLR(packet)	(*buffer_at((packet), 2) &= ~RD_MASK)
5562ac0c33Sjakob 
5662ac0c33Sjakob #define TC_MASK		0x02U
5762ac0c33Sjakob #define TC_SHIFT	1
5862ac0c33Sjakob #define	TC(packet)	(*buffer_at((packet), 2) & TC_MASK)
5962ac0c33Sjakob #define	TC_SET(packet)	(*buffer_at((packet), 2) |= TC_MASK)
6062ac0c33Sjakob #define	TC_CLR(packet)	(*buffer_at((packet), 2) &= ~TC_MASK)
6162ac0c33Sjakob 
6262ac0c33Sjakob #define	AA_MASK		0x04U
6362ac0c33Sjakob #define	AA_SHIFT	2
6462ac0c33Sjakob #define	AA(packet)	(*buffer_at((packet), 2) & AA_MASK)
6562ac0c33Sjakob #define	AA_SET(packet)	(*buffer_at((packet), 2) |= AA_MASK)
6662ac0c33Sjakob #define	AA_CLR(packet)	(*buffer_at((packet), 2) &= ~AA_MASK)
6762ac0c33Sjakob 
6862ac0c33Sjakob #define	OPCODE_MASK	0x78U
6962ac0c33Sjakob #define	OPCODE_SHIFT	3
7062ac0c33Sjakob #define	OPCODE(packet)	((*buffer_at((packet), 2) & OPCODE_MASK) >> OPCODE_SHIFT)
7162ac0c33Sjakob #define	OPCODE_SET(packet, opcode) \
7262ac0c33Sjakob 	(*buffer_at((packet), 2) = (*buffer_at((packet), 2) & ~OPCODE_MASK) | ((opcode) << OPCODE_SHIFT))
7362ac0c33Sjakob 
7462ac0c33Sjakob #define	QR_MASK		0x80U
7562ac0c33Sjakob #define	QR_SHIFT	7
7662ac0c33Sjakob #define	QR(packet)	(*buffer_at((packet), 2) & QR_MASK)
7762ac0c33Sjakob #define	QR_SET(packet)	(*buffer_at((packet), 2) |= QR_MASK)
7862ac0c33Sjakob #define	QR_CLR(packet)	(*buffer_at((packet), 2) &= ~QR_MASK)
7962ac0c33Sjakob 
8062ac0c33Sjakob /* Second octet of flags */
8162ac0c33Sjakob #define	RCODE_MASK	0x0fU
8262ac0c33Sjakob #define	RCODE_SHIFT	0
8362ac0c33Sjakob #define	RCODE(packet)	(*buffer_at((packet), 3) & RCODE_MASK)
8462ac0c33Sjakob #define	RCODE_SET(packet, rcode) \
8562ac0c33Sjakob 	(*buffer_at((packet), 3) = (*buffer_at((packet), 3) & ~RCODE_MASK) | (rcode))
8662ac0c33Sjakob 
8762ac0c33Sjakob #define	CD_MASK		0x10U
8862ac0c33Sjakob #define	CD_SHIFT	4
8962ac0c33Sjakob #define	CD(packet)	(*buffer_at((packet), 3) & CD_MASK)
9062ac0c33Sjakob #define	CD_SET(packet)	(*buffer_at((packet), 3) |= CD_MASK)
9162ac0c33Sjakob #define	CD_CLR(packet)	(*buffer_at((packet), 3) &= ~CD_MASK)
9262ac0c33Sjakob 
9362ac0c33Sjakob #define	AD_MASK		0x20U
9462ac0c33Sjakob #define	AD_SHIFT	5
9562ac0c33Sjakob #define	AD(packet)	(*buffer_at((packet), 3) & AD_MASK)
9662ac0c33Sjakob #define	AD_SET(packet)	(*buffer_at((packet), 3) |= AD_MASK)
9762ac0c33Sjakob #define	AD_CLR(packet)	(*buffer_at((packet), 3) &= ~AD_MASK)
9862ac0c33Sjakob 
9962ac0c33Sjakob #define	Z_MASK		0x40U
10062ac0c33Sjakob #define	Z_SHIFT		6
10162ac0c33Sjakob #define	Z(packet)	(*buffer_at((packet), 3) & Z_MASK)
10262ac0c33Sjakob #define	Z_SET(packet)	(*buffer_at((packet), 3) |= Z_MASK)
10362ac0c33Sjakob #define	Z_CLR(packet)	(*buffer_at((packet), 3) &= ~Z_MASK)
10462ac0c33Sjakob 
10562ac0c33Sjakob #define	RA_MASK		0x80U
10662ac0c33Sjakob #define	RA_SHIFT	7
10762ac0c33Sjakob #define	RA(packet)	(*buffer_at((packet), 3) & RA_MASK)
10862ac0c33Sjakob #define	RA_SET(packet)	(*buffer_at((packet), 3) |= RA_MASK)
10962ac0c33Sjakob #define	RA_CLR(packet)	(*buffer_at((packet), 3) &= ~RA_MASK)
11062ac0c33Sjakob 
11162ac0c33Sjakob /* Query ID */
11262ac0c33Sjakob #define	ID(packet)		(buffer_read_u16_at((packet), 0))
11362ac0c33Sjakob #define	ID_SET(packet, id)	(buffer_write_u16_at((packet), 0, (id)))
11462ac0c33Sjakob 
11562ac0c33Sjakob /* Flags, RCODE, and OPCODE. */
11662ac0c33Sjakob #define FLAGS(packet)		(buffer_read_u16_at((packet), 2))
11762ac0c33Sjakob #define FLAGS_SET(packet, f)	(buffer_write_u16_at((packet), 2, (f)))
11862ac0c33Sjakob 
11962ac0c33Sjakob /* Counter of the question section */
12062ac0c33Sjakob #define	QDCOUNT(packet)		(buffer_read_u16_at((packet), 4))
12162ac0c33Sjakob #define QDCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 4, (c)))
12262ac0c33Sjakob 
12362ac0c33Sjakob /* Counter of the answer section */
12462ac0c33Sjakob #define	ANCOUNT(packet)		(buffer_read_u16_at((packet), 6))
12562ac0c33Sjakob #define ANCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 6, (c)))
12662ac0c33Sjakob 
12762ac0c33Sjakob /* Counter of the authority section */
12862ac0c33Sjakob #define	NSCOUNT(packet)		(buffer_read_u16_at((packet), 8))
12962ac0c33Sjakob #define NSCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 8, (c)))
13062ac0c33Sjakob 
13162ac0c33Sjakob /* Counter of the additional section */
13262ac0c33Sjakob #define	ARCOUNT(packet)		(buffer_read_u16_at((packet), 10))
13362ac0c33Sjakob #define ARCOUNT_SET(packet, c)	(buffer_write_u16_at((packet), 10, (c)))
13462ac0c33Sjakob 
1352fd875a4Ssthen /* Miscellaneous limits */
13662ac0c33Sjakob #define MAX_PACKET_SIZE         65535   /* Maximum supported size of DNS packets.  */
13762ac0c33Sjakob 
13862ac0c33Sjakob #define	QIOBUFSZ		(MAX_PACKET_SIZE + MAX_RR_SIZE)
13962ac0c33Sjakob 
14062ac0c33Sjakob #define	MAXRRSPP		10240    /* Maximum number of rr's per packet */
14162ac0c33Sjakob #define MAX_COMPRESSED_DNAMES	MAXRRSPP /* Maximum number of compressed domains. */
14262ac0c33Sjakob #define MAX_COMPRESSION_OFFSET  16383	 /* Compression pointers are 14 bit. */
143977db6e5Sflorian #define IPV4_MINIMAL_RESPONSE_SIZE 1232	 /* Recommended minimal edns size for IPv4 */
1440c2b6c02Sjakob #define IPV6_MINIMAL_RESPONSE_SIZE 1220	 /* Recommended minimal edns size for IPv6 */
14562ac0c33Sjakob 
14615ed76cbSbrad /* use round robin rotation */
14715ed76cbSbrad extern int round_robin;
148db7d0d02Sflorian /* use minimal responses (more minimal, with additional only for referrals) */
149db7d0d02Sflorian extern int minimal_responses;
15015ed76cbSbrad 
15162ac0c33Sjakob /*
15262ac0c33Sjakob  * Encode RR with OWNER as owner name into QUERY.  Returns the number
15362ac0c33Sjakob  * of RRs successfully encoded.
15462ac0c33Sjakob  */
155cdb6bbddSbrad int packet_encode_rr(struct query *query,
156cdb6bbddSbrad 		     domain_type *owner,
157cdb6bbddSbrad 		     rr_type *rr,
158cdb6bbddSbrad 		     uint32_t ttl);
15962ac0c33Sjakob 
16062ac0c33Sjakob /*
16162ac0c33Sjakob  * Encode RRSET with OWNER as the owner name into QUERY.  Returns the
16262ac0c33Sjakob  * number of RRs successfully encoded.  If TRUNCATE_RRSET the entire
16362ac0c33Sjakob  * RRset is truncated in case an RR (or the RRsets signature) does not
16462ac0c33Sjakob  * fit.
16562ac0c33Sjakob  */
16662ac0c33Sjakob int packet_encode_rrset(struct query *query,
16762ac0c33Sjakob 			domain_type *owner,
16862ac0c33Sjakob 			rrset_type *rrset,
1690c2b6c02Sjakob 			int truncate_rrset,
1700c2b6c02Sjakob 			size_t minimal_respsize,
1710c2b6c02Sjakob 			int* done);
17262ac0c33Sjakob 
17362ac0c33Sjakob /*
17462ac0c33Sjakob  * Skip the RR at the current position in PACKET.
17562ac0c33Sjakob  */
17662ac0c33Sjakob int packet_skip_rr(buffer_type *packet, int question_section);
17762ac0c33Sjakob 
17862ac0c33Sjakob /*
17962ac0c33Sjakob  * Skip the dname at the current position in PACKET.
18062ac0c33Sjakob  */
18162ac0c33Sjakob int packet_skip_dname(buffer_type *packet);
18262ac0c33Sjakob 
18362ac0c33Sjakob /*
18462ac0c33Sjakob  * Read the RR at the current position in PACKET.
18562ac0c33Sjakob  */
18662ac0c33Sjakob rr_type *packet_read_rr(region_type *region,
18762ac0c33Sjakob 			domain_table_type *owners,
18862ac0c33Sjakob 			buffer_type *packet,
18962ac0c33Sjakob 			int question_section);
19062ac0c33Sjakob 
19162ac0c33Sjakob /*
19262ac0c33Sjakob  * read a query entry from network packet given in buffer.
19362ac0c33Sjakob  * does not follow compression ptrs, checks for errors (returns 0).
19462ac0c33Sjakob  * Dest must be at least MAXDOMAINLEN long.
19562ac0c33Sjakob  */
19662ac0c33Sjakob int packet_read_query_section(buffer_type *packet,
19762ac0c33Sjakob 			uint8_t* dest,
19862ac0c33Sjakob 			uint16_t* qtype,
19962ac0c33Sjakob 			uint16_t* qclass);
20062ac0c33Sjakob 
201c939baa4Ssthen /* read notify SOA serial from packet. buffer position is unmodified on return.
202c939baa4Ssthen  * returns false on no-serial found or parse failure. */
203c939baa4Ssthen int packet_find_notify_serial(buffer_type *packet, uint32_t* serial);
204c939baa4Ssthen 
205*3efee2e1Sflorian #endif /* PACKET_H */
206