]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dns.hh
Merge pull request #14032 from rgacogne/ddist-192-changelog-secpoll
[thirdparty/pdns.git] / pdns / dns.hh
CommitLineData
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 30struct DNSRecord;
12c86877 31
12c86877
BH
32class RCode
33{
34public:
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
41class ERCode
42{
43public:
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
48class Opcode
49{
50public:
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
56class DNSResourceRecord
57{
58public:
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
109struct 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
117struct EDNS0Record
118{
0e55cc96
RG
119 uint8_t extRCode, version;
120 uint16_t extFlags;
009f9f55 121} GCCPACKATTRIBUTE;
009f9f55 122
a683e8bd
RG
123static_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
160struct 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
196static_assert(sizeof(dnsheader) == 12, "dnsheader size must be 12");
197
325a18bf
OM
198class dnsheader_aligned
199{
200public:
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 232private:
e8e12e8c 233 dnsheader d_h{};
d5d9573c 234 const dnsheader* d_p{};
325a18bf
OM
235};
236
d5d9573c
RG
237inline 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
243inline 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 266uint32_t hashQuestion(const uint8_t* packet, uint16_t len, uint32_t init, bool& ok);
65a60c2c 267
98c9ec39 268struct TSIGTriplet
269{
270 DNSName name, algo;
271 string secret;
272};