]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dns.hh
clang-tidy: modernize deprecated header invarious places
[thirdparty/pdns.git] / pdns / dns.hh
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #pragma once
23 #include "qtype.hh"
24 #include "dnsname.hh"
25 #include <ctime>
26 #include <sys/types.h>
27
28 #undef BADSIG // signal.h SIG_ERR
29
30 struct DNSRecord;
31
32 class RCode
33 {
34 public:
35 enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10};
36 static std::string to_s(uint8_t rcode);
37 static std::string to_short_s(uint8_t rcode);
38 const static std::array<std::string, 24> rcodes_s;
39 };
40
41 class ERCode
42 {
43 public:
44 enum rcodes_ { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 };
45 static std::string to_s(uint8_t rcode);
46 };
47
48 class Opcode
49 {
50 public:
51 enum { Query=0, IQuery=1, Status=2, Notify=4, Update=5 };
52 static std::string to_s(uint8_t opcode);
53 };
54
55 //! This class represents a resource record
56 class DNSResourceRecord
57 {
58 public:
59 DNSResourceRecord() : last_modified(0), ttl(0), signttl(0), domain_id(-1), qclass(1), scopeMask(0), auth(1), disabled(0) {};
60 static DNSResourceRecord fromWire(const DNSRecord& d);
61
62 enum Place : uint8_t {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning within, say, a DNSPacket
63
64 void setContent(const string& content);
65 string getZoneRepresentation(bool noDot=false) const;
66
67 // data
68 DNSName qname; //!< the name of this record, for example: www.powerdns.com
69 DNSName ordername;
70 DNSName wildcardname;
71 string content; //!< what this record points to. Example: 10.1.2.3
72
73 // Aligned on 8-byte boundaries on systems where time_t is 8 bytes and int
74 // is 4 bytes, aka modern linux on x86_64
75 time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in
76
77 uint32_t ttl; //!< Time To Live of this record
78 uint32_t signttl; //!< If non-zero, use this TTL as original TTL in the RRSIG
79
80 int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in
81 QType qtype; //!< qtype of this record, ie A, CNAME, MX etc
82 uint16_t qclass; //!< class of this record
83
84 uint8_t scopeMask;
85 bool auth;
86 bool disabled;
87
88 bool operator==(const DNSResourceRecord& rhs);
89
90 bool operator<(const DNSResourceRecord &b) const
91 {
92 if(qname < b.qname)
93 return true;
94 if(qname == b.qname)
95 return(content < b.content);
96 return false;
97 }
98 };
99
100 #define GCCPACKATTRIBUTE __attribute__((packed))
101
102 struct dnsrecordheader
103 {
104 uint16_t d_type;
105 uint16_t d_class;
106 uint32_t d_ttl;
107 uint16_t d_clen;
108 } GCCPACKATTRIBUTE;
109
110 struct EDNS0Record
111 {
112 uint8_t extRCode, version;
113 uint16_t extFlags;
114 } GCCPACKATTRIBUTE;
115
116 static_assert(sizeof(EDNS0Record) == 4, "EDNS0Record size must be 4");
117
118 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
119 #include <machine/endian.h>
120 #elif __linux__ || __GNU__
121 # include <endian.h>
122
123 #else // with thanks to <arpa/nameser.h>
124
125 # define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */
126 # define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
127 # define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */
128
129 #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
130 defined(__i386) || defined(__ia64) || defined(__amd64) || \
131 defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
132 defined(__alpha__) || defined(__alpha) || \
133 (defined(__Lynx__) && defined(__x86__))
134 # define BYTE_ORDER LITTLE_ENDIAN
135 #endif
136
137 #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
138 defined(__sparc) || \
139 defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
140 defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
141 defined(apollo) || defined(__convex__) || defined(_CRAY) || \
142 defined(__hppa) || defined(__hp9000) || \
143 defined(__hp9000s300) || defined(__hp9000s700) || \
144 defined(__hp3000s900) || defined(MPE) || \
145 defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \
146 (defined(__Lynx__) && \
147 (defined(__68k__) || defined(__sparc__) || defined(__powerpc__)))
148 # define BYTE_ORDER BIG_ENDIAN
149 #endif
150
151 #endif
152
153 struct dnsheader {
154 unsigned id :16; /* query identification number */
155 #if BYTE_ORDER == BIG_ENDIAN
156 /* fields in third byte */
157 unsigned qr: 1; /* response flag */
158 unsigned opcode: 4; /* purpose of message */
159 unsigned aa: 1; /* authoritative answer */
160 unsigned tc: 1; /* truncated message */
161 unsigned rd: 1; /* recursion desired */
162 /* fields in fourth byte */
163 unsigned ra: 1; /* recursion available */
164 unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
165 unsigned ad: 1; /* authentic data from named */
166 unsigned cd: 1; /* checking disabled by resolver */
167 unsigned rcode :4; /* response code */
168 #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
169 /* fields in third byte */
170 unsigned rd :1; /* recursion desired */
171 unsigned tc :1; /* truncated message */
172 unsigned aa :1; /* authoritative answer */
173 unsigned opcode :4; /* purpose of message */
174 unsigned qr :1; /* response flag */
175 /* fields in fourth byte */
176 unsigned rcode :4; /* response code */
177 unsigned cd: 1; /* checking disabled by resolver */
178 unsigned ad: 1; /* authentic data from named */
179 unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
180 unsigned ra :1; /* recursion available */
181 #endif
182 /* remaining bytes */
183 unsigned qdcount :16; /* number of question entries */
184 unsigned ancount :16; /* number of answer entries */
185 unsigned nscount :16; /* number of authority entries */
186 unsigned arcount :16; /* number of resource entries */
187 };
188
189 static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");
190
191 class dnsheader_aligned
192 {
193 public:
194 dnsheader_aligned(const void* mem)
195 {
196 if (reinterpret_cast<uintptr_t>(mem) % sizeof(uint32_t) == 0) {
197 d_p = reinterpret_cast<const dnsheader*>(mem);
198 }
199 else {
200 memcpy(&d_h, mem, sizeof(dnsheader));
201 d_p = &d_h;
202 }
203 }
204
205 const dnsheader* get() const
206 {
207 return d_p;
208 }
209
210 private:
211 dnsheader d_h;
212 const dnsheader *d_p;
213 };
214
215 inline uint16_t * getFlagsFromDNSHeader(struct dnsheader * dh)
216 {
217 return (uint16_t*) (((char *) dh) + sizeof(uint16_t));
218 }
219
220 #define DNS_TYPE_SIZE (2)
221 #define DNS_CLASS_SIZE (2)
222 #define DNS_TTL_SIZE (4)
223 #define DNS_RDLENGTH_SIZE (2)
224 #define EDNS_EXTENDED_RCODE_SIZE (1)
225 #define EDNS_VERSION_SIZE (1)
226 #define EDNS_OPTION_CODE_SIZE (2)
227 #define EDNS_OPTION_LENGTH_SIZE (2)
228
229 #if BYTE_ORDER == BIG_ENDIAN
230 #define FLAGS_RD_OFFSET (8)
231 #define FLAGS_CD_OFFSET (12)
232 #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
233 #define FLAGS_RD_OFFSET (0)
234 #define FLAGS_CD_OFFSET (12)
235 #endif
236
237 uint32_t hashQuestion(const uint8_t* packet, uint16_t len, uint32_t init, bool& ok);
238
239 struct TSIGTriplet
240 {
241 DNSName name, algo;
242 string secret;
243 };