/* * packet.h -- low-level DNS packet encoding and decoding functions. * * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * * See LICENSE for the license. * */ #ifndef _PACKET_H_ #define _PACKET_H_ #include #include "dns.h" #include "namedb.h" struct query; /* * Set of macro's to deal with the dns message header as specified * in RFC1035 in portable way. * */ /* * * 1 1 1 1 1 1 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ID | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | QDCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ANCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | NSCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * | ARCOUNT | * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * */ /* The length of the header */ #define QHEADERSZ 12 /* First octet of flags */ #define RD_MASK 0x01U #define RD_SHIFT 0 #define RD(packet) (*buffer_at((packet), 2) & RD_MASK) #define RD_SET(packet) (*buffer_at((packet), 2) |= RD_MASK) #define RD_CLR(packet) (*buffer_at((packet), 2) &= ~RD_MASK) #define TC_MASK 0x02U #define TC_SHIFT 1 #define TC(packet) (*buffer_at((packet), 2) & TC_MASK) #define TC_SET(packet) (*buffer_at((packet), 2) |= TC_MASK) #define TC_CLR(packet) (*buffer_at((packet), 2) &= ~TC_MASK) #define AA_MASK 0x04U #define AA_SHIFT 2 #define AA(packet) (*buffer_at((packet), 2) & AA_MASK) #define AA_SET(packet) (*buffer_at((packet), 2) |= AA_MASK) #define AA_CLR(packet) (*buffer_at((packet), 2) &= ~AA_MASK) #define OPCODE_MASK 0x78U #define OPCODE_SHIFT 3 #define OPCODE(packet) ((*buffer_at((packet), 2) & OPCODE_MASK) >> OPCODE_SHIFT) #define OPCODE_SET(packet, opcode) \ (*buffer_at((packet), 2) = (*buffer_at((packet), 2) & ~OPCODE_MASK) | ((opcode) << OPCODE_SHIFT)) #define QR_MASK 0x80U #define QR_SHIFT 7 #define QR(packet) (*buffer_at((packet), 2) & QR_MASK) #define QR_SET(packet) (*buffer_at((packet), 2) |= QR_MASK) #define QR_CLR(packet) (*buffer_at((packet), 2) &= ~QR_MASK) /* Second octet of flags */ #define RCODE_MASK 0x0fU #define RCODE_SHIFT 0 #define RCODE(packet) (*buffer_at((packet), 3) & RCODE_MASK) #define RCODE_SET(packet, rcode) \ (*buffer_at((packet), 3) = (*buffer_at((packet), 3) & ~RCODE_MASK) | (rcode)) #define CD_MASK 0x10U #define CD_SHIFT 4 #define CD(packet) (*buffer_at((packet), 3) & CD_MASK) #define CD_SET(packet) (*buffer_at((packet), 3) |= CD_MASK) #define CD_CLR(packet) (*buffer_at((packet), 3) &= ~CD_MASK) #define AD_MASK 0x20U #define AD_SHIFT 5 #define AD(packet) (*buffer_at((packet), 3) & AD_MASK) #define AD_SET(packet) (*buffer_at((packet), 3) |= AD_MASK) #define AD_CLR(packet) (*buffer_at((packet), 3) &= ~AD_MASK) #define Z_MASK 0x40U #define Z_SHIFT 6 #define Z(packet) (*buffer_at((packet), 3) & Z_MASK) #define Z_SET(packet) (*buffer_at((packet), 3) |= Z_MASK) #define Z_CLR(packet) (*buffer_at((packet), 3) &= ~Z_MASK) #define RA_MASK 0x80U #define RA_SHIFT 7 #define RA(packet) (*buffer_at((packet), 3) & RA_MASK) #define RA_SET(packet) (*buffer_at((packet), 3) |= RA_MASK) #define RA_CLR(packet) (*buffer_at((packet), 3) &= ~RA_MASK) /* Query ID */ #define ID(packet) (buffer_read_u16_at((packet), 0)) #define ID_SET(packet, id) (buffer_write_u16_at((packet), 0, (id))) /* Flags, RCODE, and OPCODE. */ #define FLAGS(packet) (buffer_read_u16_at((packet), 2)) #define FLAGS_SET(packet, f) (buffer_write_u16_at((packet), 2, (f))) /* Counter of the question section */ #define QDCOUNT(packet) (buffer_read_u16_at((packet), 4)) #define QDCOUNT_SET(packet, c) (buffer_write_u16_at((packet), 4, (c))) /* Counter of the answer section */ #define ANCOUNT(packet) (buffer_read_u16_at((packet), 6)) #define ANCOUNT_SET(packet, c) (buffer_write_u16_at((packet), 6, (c))) /* Counter of the authority section */ #define NSCOUNT(packet) (buffer_read_u16_at((packet), 8)) #define NSCOUNT_SET(packet, c) (buffer_write_u16_at((packet), 8, (c))) /* Counter of the additional section */ #define ARCOUNT(packet) (buffer_read_u16_at((packet), 10)) #define ARCOUNT_SET(packet, c) (buffer_write_u16_at((packet), 10, (c))) /* Miscellaneous limits */ #define MAX_PACKET_SIZE 65535 /* Maximum supported size of DNS packets. */ #define QIOBUFSZ (MAX_PACKET_SIZE + MAX_RR_SIZE) #define MAXRRSPP 10240 /* Maximum number of rr's per packet */ #define MAX_COMPRESSED_DNAMES MAXRRSPP /* Maximum number of compressed domains. */ #define MAX_COMPRESSION_OFFSET 16383 /* Compression pointers are 14 bit. */ #define IPV4_MINIMAL_RESPONSE_SIZE 1480 /* Recommended minimal edns size for IPv4 */ #define IPV6_MINIMAL_RESPONSE_SIZE 1220 /* Recommended minimal edns size for IPv6 */ /* use round robin rotation */ extern int round_robin; /* * Encode RR with OWNER as owner name into QUERY. Returns the number * of RRs successfully encoded. */ int packet_encode_rr(struct query *query, domain_type *owner, rr_type *rr, uint32_t ttl); /* * Encode RRSET with OWNER as the owner name into QUERY. Returns the * number of RRs successfully encoded. If TRUNCATE_RRSET the entire * RRset is truncated in case an RR (or the RRsets signature) does not * fit. */ int packet_encode_rrset(struct query *query, domain_type *owner, rrset_type *rrset, int truncate_rrset, size_t minimal_respsize, int* done); /* * Skip the RR at the current position in PACKET. */ int packet_skip_rr(buffer_type *packet, int question_section); /* * Skip the dname at the current position in PACKET. */ int packet_skip_dname(buffer_type *packet); /* * Read the RR at the current position in PACKET. */ rr_type *packet_read_rr(region_type *region, domain_table_type *owners, buffer_type *packet, int question_section); /* * read a query entry from network packet given in buffer. * does not follow compression ptrs, checks for errors (returns 0). * Dest must be at least MAXDOMAINLEN long. */ int packet_read_query_section(buffer_type *packet, uint8_t* dest, uint16_t* qtype, uint16_t* qclass); /* read notify SOA serial from packet. buffer position is unmodified on return. * returns false on no-serial found or parse failure. */ int packet_find_notify_serial(buffer_type *packet, uint32_t* serial); #endif /* _PACKET_H_ */