]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
12471842 PL |
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 | */ | |
ea76bac0 | 22 | #pragma once |
12c86877 | 23 | #include "qtype.hh" |
675fa24c | 24 | #include "dnsname.hh" |
dc6aa7f5 | 25 | #include <ctime> |
12c86877 | 26 | #include <sys/types.h> |
d83feb68 CH |
27 | |
28 | #undef BADSIG // signal.h SIG_ERR | |
29 | ||
4950b140 | 30 | struct DNSRecord; |
12c86877 | 31 | |
12c86877 BH |
32 | class RCode |
33 | { | |
34 | public: | |
4f9f2fd5 | 35 | enum rcodes_ : uint8_t { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10}; |
f6007449 | 36 | static std::string to_s(uint8_t rcode); |
ccdac0ad | 37 | static std::string to_short_s(uint8_t rcode); |
251aedda | 38 | const static std::array<std::string, 24> rcodes_s; |
12c86877 BH |
39 | }; |
40 | ||
d83feb68 CH |
41 | class ERCode |
42 | { | |
43 | public: | |
4f9f2fd5 OM |
44 | enum rcodes_ : uint16_t { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 }; |
45 | static std::string to_s(uint16_t rcode); | |
d83feb68 CH |
46 | }; |
47 | ||
12c86877 BH |
48 | class Opcode |
49 | { | |
50 | public: | |
7a863d5e | 51 | enum opcodes_ : uint8_t { Query=0, IQuery=1, Status=2, Notify=4, Update=5 }; |
f3c9f421 | 52 | static std::string to_s(uint8_t opcode); |
12c86877 BH |
53 | }; |
54 | ||
12c86877 BH |
55 | //! This class represents a resource record |
56 | class DNSResourceRecord | |
57 | { | |
58 | public: | |
ae2dcdd3 | 59 | static DNSResourceRecord fromWire(const DNSRecord& wire); |
12c86877 | 60 | |
fb0b67ee FM |
61 | enum Place : uint8_t |
62 | { | |
63 | QUESTION = 0, | |
64 | ANSWER = 1, | |
65 | AUTHORITY = 2, | |
66 | ADDITIONAL = 3 | |
67 | }; //!< Type describing the positioning within, say, a DNSPacket | |
e693ff5a | 68 | |
f7a69a4c | 69 | void setContent(const string& content); |
ae2dcdd3 | 70 | [[nodiscard]] string getZoneRepresentation(bool noDot = false) const; |
f7a69a4c | 71 | |
12c86877 | 72 | // data |
675fa24c | 73 | DNSName qname; //!< the name of this record, for example: www.powerdns.com |
fc5245c3 | 74 | DNSName ordername; |
675fa24c | 75 | DNSName wildcardname; |
12c86877 | 76 | string content; //!< what this record points to. Example: 10.1.2.3 |
7c2faec9 | 77 | |
ef2ea4bf | 78 | // Aligned on 8-byte boundaries on systems where time_t is 8 bytes and int |
7c2faec9 | 79 | // is 4 bytes, aka modern linux on x86_64 |
ae2dcdd3 | 80 | time_t last_modified{}; //!< For autocalculating SOA serial numbers - the backend needs to fill this in |
7c2faec9 | 81 | |
ae2dcdd3 FM |
82 | uint32_t ttl{}; //!< Time To Live of this record |
83 | uint32_t signttl{}; //!< If non-zero, use this TTL as original TTL in the RRSIG | |
7c2faec9 | 84 | |
ae2dcdd3 | 85 | int domain_id{-1}; //!< If a backend implements this, the domain_id of the zone this record is in |
7c2faec9 | 86 | QType qtype; //!< qtype of this record, ie A, CNAME, MX etc |
ae2dcdd3 | 87 | uint16_t qclass{1}; //!< class of this record |
12c86877 | 88 | |
ae2dcdd3 FM |
89 | uint8_t scopeMask{}; |
90 | bool auth{true}; | |
91 | bool disabled{}; | |
702b226d | 92 | |
f7a69a4c | 93 | bool operator==(const DNSResourceRecord& rhs); |
cb433f9c | 94 | |
ae2dcdd3 | 95 | bool operator<(const DNSResourceRecord& other) const |
728485ca | 96 | { |
ae2dcdd3 | 97 | if (qname < other.qname) { |
728485ca | 98 | return true; |
ae2dcdd3 FM |
99 | } |
100 | if (qname == other.qname) { | |
101 | return (content < other.content); | |
102 | } | |
728485ca BH |
103 | return false; |
104 | } | |
12c86877 BH |
105 | }; |
106 | ||
76473b92 KM |
107 | #define GCCPACKATTRIBUTE __attribute__((packed)) |
108 | ||
5a57d2ea BH |
109 | struct dnsrecordheader |
110 | { | |
111 | uint16_t d_type; | |
112 | uint16_t d_class; | |
113 | uint32_t d_ttl; | |
114 | uint16_t d_clen; | |
009f9f55 BH |
115 | } GCCPACKATTRIBUTE; |
116 | ||
d6c335ab PL |
117 | struct EDNS0Record |
118 | { | |
0e55cc96 RG |
119 | uint8_t extRCode, version; |
120 | uint16_t extFlags; | |
009f9f55 | 121 | } GCCPACKATTRIBUTE; |
009f9f55 | 122 | |
a683e8bd RG |
123 | static_assert(sizeof(EDNS0Record) == 4, "EDNS0Record size must be 4"); |
124 | ||
4d39d7f3 | 125 | #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) |
009f9f55 | 126 | #include <machine/endian.h> |
8348048f | 127 | #elif __linux__ || __GNU__ |
a1a344bf BH |
128 | # include <endian.h> |
129 | ||
f95da229 | 130 | #else // with thanks to <arpa/nameser.h> |
a1a344bf BH |
131 | |
132 | # define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ | |
133 | # define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ | |
134 | # define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ | |
135 | ||
136 | #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ | |
137 | defined(__i386) || defined(__ia64) || defined(__amd64) || \ | |
138 | defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ | |
139 | defined(__alpha__) || defined(__alpha) || \ | |
140 | (defined(__Lynx__) && defined(__x86__)) | |
141 | # define BYTE_ORDER LITTLE_ENDIAN | |
142 | #endif | |
143 | ||
144 | #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ | |
145 | defined(__sparc) || \ | |
146 | defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ | |
147 | defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ | |
148 | defined(apollo) || defined(__convex__) || defined(_CRAY) || \ | |
149 | defined(__hppa) || defined(__hp9000) || \ | |
150 | defined(__hp9000s300) || defined(__hp9000s700) || \ | |
151 | defined(__hp3000s900) || defined(MPE) || \ | |
152 | defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \ | |
153 | (defined(__Lynx__) && \ | |
154 | (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) | |
155 | # define BYTE_ORDER BIG_ENDIAN | |
156 | #endif | |
157 | ||
5a57d2ea BH |
158 | #endif |
159 | ||
160 | struct dnsheader { | |
da3af217 | 161 | uint16_t id; /* query identification number */ |
5a57d2ea BH |
162 | #if BYTE_ORDER == BIG_ENDIAN |
163 | /* fields in third byte */ | |
164 | unsigned qr: 1; /* response flag */ | |
165 | unsigned opcode: 4; /* purpose of message */ | |
7c696097 | 166 | unsigned aa: 1; /* authoritative answer */ |
5a57d2ea BH |
167 | unsigned tc: 1; /* truncated message */ |
168 | unsigned rd: 1; /* recursion desired */ | |
169 | /* fields in fourth byte */ | |
170 | unsigned ra: 1; /* recursion available */ | |
171 | unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ | |
172 | unsigned ad: 1; /* authentic data from named */ | |
173 | unsigned cd: 1; /* checking disabled by resolver */ | |
174 | unsigned rcode :4; /* response code */ | |
9cf8d46a | 175 | #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN |
5a57d2ea BH |
176 | /* fields in third byte */ |
177 | unsigned rd :1; /* recursion desired */ | |
178 | unsigned tc :1; /* truncated message */ | |
7c696097 | 179 | unsigned aa :1; /* authoritative answer */ |
5a57d2ea BH |
180 | unsigned opcode :4; /* purpose of message */ |
181 | unsigned qr :1; /* response flag */ | |
182 | /* fields in fourth byte */ | |
183 | unsigned rcode :4; /* response code */ | |
184 | unsigned cd: 1; /* checking disabled by resolver */ | |
185 | unsigned ad: 1; /* authentic data from named */ | |
186 | unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ | |
187 | unsigned ra :1; /* recursion available */ | |
188 | #endif | |
189 | /* remaining bytes */ | |
da3af217 RG |
190 | uint16_t qdcount; /* number of question entries */ |
191 | uint16_t ancount; /* number of answer entries */ | |
192 | uint16_t nscount; /* number of authority entries */ | |
193 | uint16_t arcount; /* number of resource entries */ | |
5a57d2ea BH |
194 | }; |
195 | ||
ca404e94 RG |
196 | static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12"); |
197 | ||
325a18bf OM |
198 | class dnsheader_aligned |
199 | { | |
200 | public: | |
d5d9573c RG |
201 | static bool isMemoryAligned(const void* mem) |
202 | { | |
203 | return reinterpret_cast<uintptr_t>(mem) % sizeof(uint32_t) == 0; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) | |
204 | } | |
205 | ||
325a18bf OM |
206 | dnsheader_aligned(const void* mem) |
207 | { | |
d5d9573c | 208 | if (isMemoryAligned(mem)) { |
e8e12e8c | 209 | d_p = reinterpret_cast<const dnsheader*>(mem); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) |
325a18bf OM |
210 | } |
211 | else { | |
212 | memcpy(&d_h, mem, sizeof(dnsheader)); | |
213 | d_p = &d_h; | |
214 | } | |
215 | } | |
216 | ||
e8e12e8c | 217 | [[nodiscard]] const dnsheader* get() const |
325a18bf OM |
218 | { |
219 | return d_p; | |
220 | } | |
221 | ||
d5d9573c RG |
222 | [[nodiscard]] const dnsheader& operator*() const |
223 | { | |
224 | return *d_p; | |
225 | } | |
226 | ||
227 | [[nodiscard]] const dnsheader* operator->() const | |
228 | { | |
229 | return d_p; | |
230 | } | |
231 | ||
325a18bf | 232 | private: |
e8e12e8c | 233 | dnsheader d_h{}; |
d5d9573c | 234 | const dnsheader* d_p{}; |
325a18bf OM |
235 | }; |
236 | ||
d5d9573c RG |
237 | inline uint16_t* getFlagsFromDNSHeader(dnsheader* dh) |
238 | { | |
239 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) | |
240 | return reinterpret_cast<uint16_t*>(reinterpret_cast<char*>(dh) + sizeof(uint16_t)); | |
241 | } | |
242 | ||
243 | inline const uint16_t * getFlagsFromDNSHeader(const dnsheader* dh) | |
aeb36780 | 244 | { |
d5d9573c RG |
245 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) |
246 | return reinterpret_cast<const uint16_t*>(reinterpret_cast<const char*>(dh) + sizeof(uint16_t)); | |
aeb36780 RG |
247 | } |
248 | ||
ca404e94 RG |
249 | #define DNS_TYPE_SIZE (2) |
250 | #define DNS_CLASS_SIZE (2) | |
251 | #define DNS_TTL_SIZE (4) | |
252 | #define DNS_RDLENGTH_SIZE (2) | |
253 | #define EDNS_EXTENDED_RCODE_SIZE (1) | |
254 | #define EDNS_VERSION_SIZE (1) | |
255 | #define EDNS_OPTION_CODE_SIZE (2) | |
256 | #define EDNS_OPTION_LENGTH_SIZE (2) | |
257 | ||
aeb36780 RG |
258 | #if BYTE_ORDER == BIG_ENDIAN |
259 | #define FLAGS_RD_OFFSET (8) | |
260 | #define FLAGS_CD_OFFSET (12) | |
261 | #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN | |
262 | #define FLAGS_RD_OFFSET (0) | |
263 | #define FLAGS_CD_OFFSET (12) | |
264 | #endif | |
5a57d2ea | 265 | |
538c11f9 | 266 | uint32_t hashQuestion(const uint8_t* packet, uint16_t len, uint32_t init, bool& ok); |
65a60c2c | 267 | |
98c9ec39 | 268 | struct TSIGTriplet |
269 | { | |
270 | DNSName name, algo; | |
271 | string secret; | |
272 | }; |