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