]>
Commit | Line | Data |
---|---|---|
4192ca66 | 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 | */ | |
e8c59f2d | 22 | #pragma once |
8900e2e3 CHB |
23 | #ifdef HAVE_CONFIG_H |
24 | #include "config.h" | |
25 | #endif | |
26 | ||
a0a276c2 BH |
27 | #include "dnsparser.hh" |
28 | #include "dnswriter.hh" | |
18d5647a | 29 | #include "lock.hh" |
cbf0e7f3 | 30 | #include "rcpgenerator.hh" |
8c1c9170 | 31 | #include <set> |
51083cab | 32 | #include <bitset> |
61b26744 | 33 | #include "namespaces.hh" |
f4352636 | 34 | #include "iputils.hh" |
373914dc | 35 | #include "svc-records.hh" |
a0a276c2 | 36 | |
2770fad0 BH |
37 | #define includeboilerplate(RNAME) RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr); \ |
38 | RNAME##RecordContent(const string& zoneData); \ | |
39 | static void report(void); \ | |
ee1ada80 | 40 | static void unreport(void); \ |
32122aab RG |
41 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); \ |
42 | static std::shared_ptr<DNSRecordContent> make(const string& zonedata); \ | |
f21fc0aa | 43 | string getZoneRepresentation(bool noDot=false) const override; \ |
d06dcda4 RG |
44 | void toPacket(DNSPacketWriter& pw) const override; \ |
45 | uint16_t getType() const override { return QType::RNAME; } \ | |
46 | template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false) const; \ | |
f21fc0aa | 47 | template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false); |
a0a276c2 BH |
48 | |
49 | class NAPTRRecordContent : public DNSRecordContent | |
50 | { | |
51 | public: | |
4a51ff72 | 52 | NAPTRRecordContent(uint16_t order, uint16_t preference, string flags, string services, string regexp, DNSName replacement); |
a0a276c2 | 53 | |
1d1d688a | 54 | includeboilerplate(NAPTR) |
cbf0e7f3 | 55 | template<class Convertor> void xfrRecordContent(Convertor& conv); |
1b47f291 | 56 | const string& getFlags() const |
dcc074fb OM |
57 | { |
58 | return d_flags; | |
59 | } | |
1b47f291 | 60 | const DNSName& getReplacement() const |
dcc074fb OM |
61 | { |
62 | return d_replacement; | |
63 | } | |
a0a276c2 BH |
64 | private: |
65 | uint16_t d_order, d_preference; | |
4a51ff72 PD |
66 | string d_flags, d_services, d_regexp; |
67 | DNSName d_replacement; | |
a0a276c2 BH |
68 | }; |
69 | ||
2770fad0 | 70 | |
a0a276c2 BH |
71 | class ARecordContent : public DNSRecordContent |
72 | { | |
73 | public: | |
447e0cff | 74 | explicit ARecordContent(const ComboAddress& ca); |
efb265e3 | 75 | explicit ARecordContent(uint32_t ip); |
1d1d688a | 76 | includeboilerplate(A) |
2770fad0 | 77 | void doRecordCheck(const DNSRecord& dr); |
447e0cff | 78 | ComboAddress getCA(int port=0) const; |
f18e430f | 79 | bool operator==(const DNSRecordContent& rhs) const override |
80 | { | |
81 | if(typeid(*this) != typeid(rhs)) | |
82 | return false; | |
83 | return d_ip == dynamic_cast<const ARecordContent&>(rhs).d_ip; | |
84 | } | |
2770fad0 BH |
85 | private: |
86 | uint32_t d_ip; | |
87 | }; | |
a0a276c2 | 88 | |
fc465b41 AT |
89 | class AAAARecordContent : public DNSRecordContent |
90 | { | |
91 | public: | |
92 | AAAARecordContent(std::string &val); | |
447e0cff | 93 | explicit AAAARecordContent(const ComboAddress& ca); |
1d1d688a | 94 | includeboilerplate(AAAA) |
447e0cff | 95 | ComboAddress getCA(int port=0) const; |
f18e430f | 96 | bool operator==(const DNSRecordContent& rhs) const override |
97 | { | |
98 | if(typeid(*this) != typeid(rhs)) | |
99 | return false; | |
100 | return d_ip6 == dynamic_cast<const decltype(this)>(&rhs)->d_ip6; | |
101 | } | |
fc465b41 | 102 | private: |
447e0cff | 103 | string d_ip6; // why?? |
fc465b41 AT |
104 | }; |
105 | ||
2770fad0 BH |
106 | class MXRecordContent : public DNSRecordContent |
107 | { | |
108 | public: | |
1290c1d2 | 109 | MXRecordContent(uint16_t preference, DNSName mxname); |
a0a276c2 | 110 | |
2770fad0 | 111 | includeboilerplate(MX) |
a0a276c2 | 112 | |
2770fad0 | 113 | uint16_t d_preference; |
89735451 | 114 | DNSName d_mxname; |
f18e430f | 115 | |
116 | bool operator==(const DNSRecordContent& rhs) const override | |
117 | { | |
118 | if(typeid(*this) != typeid(rhs)) | |
119 | return false; | |
120 | auto rrhs =dynamic_cast<const decltype(this)>(&rhs); | |
121 | return std::tie(d_preference, d_mxname) == std::tie(rrhs->d_preference, rrhs->d_mxname); | |
122 | } | |
123 | ||
2770fad0 BH |
124 | }; |
125 | ||
9fd71f2e BH |
126 | class KXRecordContent : public DNSRecordContent |
127 | { | |
128 | public: | |
89735451 | 129 | KXRecordContent(uint16_t preference, const DNSName& exchanger); |
9fd71f2e BH |
130 | |
131 | includeboilerplate(KX) | |
132 | ||
133 | private: | |
134 | uint16_t d_preference; | |
89735451 | 135 | DNSName d_exchanger; |
9fd71f2e BH |
136 | }; |
137 | ||
138 | class IPSECKEYRecordContent : public DNSRecordContent | |
139 | { | |
140 | public: | |
c2f3be9d | 141 | IPSECKEYRecordContent(uint16_t preference, uint8_t gatewaytype, uint8_t algo, const DNSName& gateway, const string& publickey); |
9fd71f2e BH |
142 | |
143 | includeboilerplate(IPSECKEY) | |
144 | ||
145 | private: | |
d0793109 | 146 | uint32_t d_ip4; |
c2f3be9d PD |
147 | DNSName d_gateway; |
148 | string d_publickey; | |
1cafb958 | 149 | string d_ip6; |
adc18742 | 150 | uint8_t d_preference, d_gatewaytype, d_algorithm; |
9fd71f2e BH |
151 | }; |
152 | ||
153 | class DHCIDRecordContent : public DNSRecordContent | |
154 | { | |
155 | public: | |
156 | includeboilerplate(DHCID) | |
157 | ||
158 | private: | |
159 | string d_content; | |
160 | }; | |
161 | ||
162 | ||
2770fad0 BH |
163 | class SRVRecordContent : public DNSRecordContent |
164 | { | |
165 | public: | |
1290c1d2 | 166 | SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, DNSName target); |
2770fad0 BH |
167 | |
168 | includeboilerplate(SRV) | |
169 | ||
a2d7c36a | 170 | uint16_t d_weight, d_port; |
89735451 | 171 | DNSName d_target; |
a2d7c36a | 172 | uint16_t d_preference; |
2770fad0 BH |
173 | }; |
174 | ||
06ffdc52 BH |
175 | class TSIGRecordContent : public DNSRecordContent |
176 | { | |
177 | public: | |
178 | includeboilerplate(TSIG) | |
abb11ca4 | 179 | TSIGRecordContent() = default; |
06ffdc52 | 180 | |
34c513f9 RG |
181 | uint16_t d_origID{0}; |
182 | uint16_t d_fudge{0}; | |
c3a81a30 | 183 | |
0b6fa0eb | 184 | DNSName d_algoName; |
483d2f10 PL |
185 | string d_mac; |
186 | string d_otherData; | |
34c513f9 | 187 | uint64_t d_time{0}; |
06ffdc52 | 188 | // uint16_t d_macSize; |
34c513f9 | 189 | uint16_t d_eRcode{0}; |
06ffdc52 | 190 | // uint16_t d_otherLen |
06ffdc52 BH |
191 | }; |
192 | ||
2770fad0 BH |
193 | |
194 | class TXTRecordContent : public DNSRecordContent | |
195 | { | |
196 | public: | |
197 | includeboilerplate(TXT) | |
198 | ||
2770fad0 | 199 | string d_text; |
a0a276c2 BH |
200 | }; |
201 | ||
8900e2e3 | 202 | #ifdef HAVE_LUA_RECORDS |
6b547a53 | 203 | class LUARecordContent : public DNSRecordContent |
204 | { | |
205 | public: | |
206 | includeboilerplate(LUA) | |
98fa3598 | 207 | string getCode() const; |
5dbd408c | 208 | uint16_t d_type; |
6b547a53 | 209 | string d_code; |
210 | }; | |
8900e2e3 | 211 | #endif |
6b547a53 | 212 | |
acedb99e | 213 | class ENTRecordContent : public DNSRecordContent |
214 | { | |
215 | public: | |
216 | includeboilerplate(ENT) | |
217 | }; | |
218 | ||
8c1c9170 BH |
219 | class SPFRecordContent : public DNSRecordContent |
220 | { | |
221 | public: | |
222 | includeboilerplate(SPF) | |
0bd2e252 RG |
223 | const std::string& getText() const |
224 | { | |
225 | return d_text; | |
226 | } | |
8c1c9170 BH |
227 | |
228 | private: | |
229 | string d_text; | |
230 | }; | |
231 | ||
232 | ||
cbf0e7f3 BH |
233 | class NSRecordContent : public DNSRecordContent |
234 | { | |
235 | public: | |
236 | includeboilerplate(NS) | |
5a1f298f | 237 | explicit NSRecordContent(const DNSName& content) : d_content(content){} |
f18e430f | 238 | const DNSName& getNS() const { return d_content; } |
239 | bool operator==(const DNSRecordContent& rhs) const override | |
240 | { | |
241 | if(typeid(*this) != typeid(rhs)) | |
242 | return false; | |
243 | auto rrhs =dynamic_cast<const decltype(this)>(&rhs); | |
244 | return d_content == rrhs->d_content; | |
245 | } | |
246 | ||
cbf0e7f3 | 247 | private: |
89735451 | 248 | DNSName d_content; |
cbf0e7f3 BH |
249 | }; |
250 | ||
251 | class PTRRecordContent : public DNSRecordContent | |
252 | { | |
253 | public: | |
254 | includeboilerplate(PTR) | |
98cda0a9 | 255 | explicit PTRRecordContent(const DNSName& content) : d_content(content){} |
0bd2e252 | 256 | const DNSName& getContent() const { return d_content; } |
cbf0e7f3 | 257 | private: |
89735451 | 258 | DNSName d_content; |
cbf0e7f3 BH |
259 | }; |
260 | ||
261 | class CNAMERecordContent : public DNSRecordContent | |
262 | { | |
263 | public: | |
264 | includeboilerplate(CNAME) | |
90ba52e0 | 265 | CNAMERecordContent(const DNSName& content) : d_content(content){} |
447e0cff | 266 | DNSName getTarget() const { return d_content; } |
cbf0e7f3 | 267 | private: |
89735451 | 268 | DNSName d_content; |
cbf0e7f3 BH |
269 | }; |
270 | ||
0abfc310 | 271 | #if !defined(RECURSOR) |
d59b894d | 272 | class ALIASRecordContent : public DNSRecordContent |
273 | { | |
274 | public: | |
275 | includeboilerplate(ALIAS) | |
276 | ||
d06dcda4 RG |
277 | [[nodiscard]] const DNSName& getContent() const |
278 | { | |
279 | return d_content; | |
280 | } | |
281 | private: | |
89735451 | 282 | DNSName d_content; |
d59b894d | 283 | }; |
0abfc310 | 284 | #endif |
d59b894d | 285 | |
8dee0750 | 286 | class DNAMERecordContent : public DNSRecordContent |
287 | { | |
288 | public: | |
289 | includeboilerplate(DNAME) | |
c3491dd6 | 290 | DNAMERecordContent(const DNSName& content) : d_content(content){} |
dc0d34db | 291 | const DNSName& getTarget() const { return d_content; } |
c3491dd6 | 292 | private: |
89735451 | 293 | DNSName d_content; |
8dee0750 | 294 | }; |
295 | ||
296 | ||
fa552262 CHB |
297 | class MBRecordContent : public DNSRecordContent |
298 | { | |
299 | public: | |
300 | includeboilerplate(MB) | |
301 | ||
302 | private: | |
303 | DNSName d_madname; | |
304 | }; | |
305 | ||
306 | class MGRecordContent : public DNSRecordContent | |
307 | { | |
308 | public: | |
309 | includeboilerplate(MG) | |
310 | ||
311 | private: | |
312 | DNSName d_mgmname; | |
313 | }; | |
314 | ||
4e0805a6 BH |
315 | class MRRecordContent : public DNSRecordContent |
316 | { | |
317 | public: | |
318 | includeboilerplate(MR) | |
319 | ||
320 | private: | |
89735451 | 321 | DNSName d_alias; |
4e0805a6 BH |
322 | }; |
323 | ||
7c0b8593 | 324 | class MINFORecordContent : public DNSRecordContent |
325 | { | |
326 | public: | |
327 | includeboilerplate(MINFO) | |
328 | ||
329 | private: | |
89735451 PD |
330 | DNSName d_rmailbx; |
331 | DNSName d_emailbx; | |
7c0b8593 | 332 | }; |
cbf0e7f3 | 333 | |
878435ce BH |
334 | class OPTRecordContent : public DNSRecordContent |
335 | { | |
336 | public: | |
abb11ca4 | 337 | OPTRecordContent() = default; |
878435ce | 338 | includeboilerplate(OPT) |
d06dcda4 | 339 | void getData(vector<pair<uint16_t, string> > &opts) const; |
878435ce BH |
340 | private: |
341 | string d_data; | |
342 | }; | |
343 | ||
344 | ||
cbf0e7f3 BH |
345 | class HINFORecordContent : public DNSRecordContent |
346 | { | |
347 | public: | |
348 | includeboilerplate(HINFO) | |
349 | ||
350 | private: | |
351 | string d_cpu, d_host; | |
352 | }; | |
353 | ||
354 | class RPRecordContent : public DNSRecordContent | |
355 | { | |
356 | public: | |
357 | includeboilerplate(RP) | |
358 | ||
359 | private: | |
89735451 | 360 | DNSName d_mbox, d_info; |
cbf0e7f3 BH |
361 | }; |
362 | ||
363 | ||
8c1c9170 BH |
364 | class DNSKEYRecordContent : public DNSRecordContent |
365 | { | |
366 | public: | |
1c4d88c5 | 367 | DNSKEYRecordContent(); |
8c1c9170 | 368 | includeboilerplate(DNSKEY) |
523c312b | 369 | uint16_t getTag() const; |
8c1c9170 | 370 | |
34c513f9 RG |
371 | uint16_t d_flags{0}; |
372 | uint8_t d_protocol{0}; | |
373 | uint8_t d_algorithm{0}; | |
8c1c9170 | 374 | string d_key; |
523c312b | 375 | bool operator<(const DNSKEYRecordContent& rhs) const |
376 | { | |
b35fe860 | 377 | return std::tie(d_flags, d_protocol, d_algorithm, d_key) < |
1a09e47b | 378 | std::tie(rhs.d_flags, rhs.d_protocol, rhs.d_algorithm, rhs.d_key); |
523c312b | 379 | } |
8c1c9170 BH |
380 | }; |
381 | ||
882de365 PL |
382 | class CDNSKEYRecordContent : public DNSRecordContent |
383 | { | |
384 | public: | |
385 | CDNSKEYRecordContent(); | |
386 | includeboilerplate(CDNSKEY) | |
387 | uint16_t getTag(); | |
388 | ||
34c513f9 RG |
389 | uint16_t d_flags{0}; |
390 | uint8_t d_protocol{0}; | |
391 | uint8_t d_algorithm{0}; | |
882de365 PL |
392 | string d_key; |
393 | }; | |
394 | ||
8c1c9170 BH |
395 | class DSRecordContent : public DNSRecordContent |
396 | { | |
397 | public: | |
1c4d88c5 | 398 | DSRecordContent(); |
0b062478 | 399 | bool operator==(const DNSRecordContent& rhs) const override |
a820bc34 | 400 | { |
0b062478 RG |
401 | if(typeid(*this) != typeid(rhs)) |
402 | return false; | |
403 | auto rrhs =dynamic_cast<const decltype(this)>(&rhs); | |
1a09e47b RG |
404 | return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) == |
405 | std::tie(rrhs->d_tag, rrhs->d_algorithm, rrhs->d_digesttype, rrhs->d_digest); | |
a820bc34 | 406 | } |
407 | bool operator<(const DSRecordContent& rhs) const | |
408 | { | |
1a09e47b RG |
409 | return std::tie(d_tag, d_algorithm, d_digesttype, d_digest) < |
410 | std::tie(rhs.d_tag, rhs.d_algorithm, rhs.d_digesttype, rhs.d_digest); | |
a820bc34 | 411 | } |
412 | ||
8c1c9170 BH |
413 | includeboilerplate(DS) |
414 | ||
34c513f9 RG |
415 | uint16_t d_tag{0}; |
416 | uint8_t d_algorithm{0}, d_digesttype{0}; | |
8c1c9170 BH |
417 | string d_digest; |
418 | }; | |
419 | ||
882de365 PL |
420 | class CDSRecordContent : public DNSRecordContent |
421 | { | |
422 | public: | |
423 | CDSRecordContent(); | |
424 | includeboilerplate(CDS) | |
425 | ||
34c513f9 RG |
426 | uint16_t d_tag{0}; |
427 | uint8_t d_algorithm{0}, d_digesttype{0}; | |
882de365 PL |
428 | string d_digest; |
429 | }; | |
430 | ||
0b55f2f5 BH |
431 | class DLVRecordContent : public DNSRecordContent |
432 | { | |
433 | public: | |
434 | DLVRecordContent(); | |
435 | includeboilerplate(DLV) | |
436 | ||
34c513f9 RG |
437 | uint16_t d_tag{0}; |
438 | uint8_t d_algorithm{0}, d_digesttype{0}; | |
0b55f2f5 BH |
439 | string d_digest; |
440 | }; | |
441 | ||
442 | ||
a40a693b BH |
443 | class SSHFPRecordContent : public DNSRecordContent |
444 | { | |
445 | public: | |
446 | includeboilerplate(SSHFP) | |
447 | ||
448 | private: | |
449 | uint8_t d_algorithm, d_fptype; | |
450 | string d_fingerprint; | |
451 | }; | |
8c1c9170 | 452 | |
4b5762f1 BH |
453 | class KEYRecordContent : public DNSRecordContent |
454 | { | |
455 | public: | |
456 | includeboilerplate(KEY) | |
457 | ||
458 | private: | |
459 | uint16_t d_flags; | |
460 | uint8_t d_protocol, d_algorithm; | |
461 | string d_certificate; | |
462 | }; | |
463 | ||
37f47031 BH |
464 | class AFSDBRecordContent : public DNSRecordContent |
465 | { | |
466 | public: | |
467 | includeboilerplate(AFSDB) | |
468 | ||
469 | private: | |
470 | uint16_t d_subtype; | |
89735451 | 471 | DNSName d_hostname; |
37f47031 BH |
472 | }; |
473 | ||
474 | ||
4d6fa3eb O |
475 | #ifdef CERT |
476 | #error likely openssl/ssl2.h is included, defining CERT, avoid that or undef CERT before including dnsrecords.hh | |
477 | #endif | |
478 | ||
2475a4fc BH |
479 | class CERTRecordContent : public DNSRecordContent |
480 | { | |
481 | public: | |
482 | includeboilerplate(CERT) | |
483 | ||
484 | private: | |
485 | uint16_t d_type, d_tag; | |
2475a4fc | 486 | string d_certificate; |
1e56bb82 | 487 | uint8_t d_algorithm; |
2475a4fc BH |
488 | }; |
489 | ||
07dbe87e BH |
490 | class TLSARecordContent : public DNSRecordContent |
491 | { | |
492 | public: | |
493 | includeboilerplate(TLSA) | |
494 | ||
495 | private: | |
f5a09796 | 496 | uint8_t d_certusage, d_selector, d_matchtype; |
07dbe87e BH |
497 | string d_cert; |
498 | }; | |
499 | ||
291935bb PL |
500 | class SMIMEARecordContent : public DNSRecordContent |
501 | { | |
502 | public: | |
503 | includeboilerplate(SMIMEA) | |
504 | ||
505 | private: | |
506 | uint8_t d_certusage, d_selector, d_matchtype; | |
507 | string d_cert; | |
508 | }; | |
509 | ||
68066337 JC |
510 | class OPENPGPKEYRecordContent : public DNSRecordContent |
511 | { | |
512 | public: | |
513 | includeboilerplate(OPENPGPKEY) | |
514 | ||
515 | private: | |
3fd06ce5 | 516 | string d_keyring; |
68066337 JC |
517 | }; |
518 | ||
e5acc81c PL |
519 | class SVCBBaseRecordContent : public DNSRecordContent |
520 | { | |
521 | public: | |
522 | const DNSName& getTarget() const {return d_target;} | |
523 | uint16_t getPriority() const {return d_priority;} | |
ec999800 | 524 | // Returns true if a value for |key| was set to 'auto' |
467ad1f0 | 525 | bool autoHint(const SvcParam::SvcParamKey &key) const; |
ec999800 PL |
526 | // Sets the |addresses| to the existing hints for |key| |
527 | void setHints(const SvcParam::SvcParamKey &key, const std::vector<ComboAddress> &addresses); | |
bdbee377 PL |
528 | // Removes the parameter for |key| from d_params |
529 | void removeParam(const SvcParam::SvcParamKey &key); | |
a563ced8 | 530 | // Whether or not there are any parameter |
467ad1f0 | 531 | bool hasParams() const; |
d499f521 | 532 | // Whether or not the param of |key| exists |
467ad1f0 | 533 | bool hasParam(const SvcParam::SvcParamKey &key) const; |
d499f521 | 534 | // Get the parameter with |key|, will throw out_of_range if param isn't there |
467ad1f0 RG |
535 | SvcParam getParam(const SvcParam::SvcParamKey &key) const; |
536 | virtual std::shared_ptr<SVCBBaseRecordContent> clone() const = 0; | |
e5acc81c PL |
537 | |
538 | protected: | |
467ad1f0 | 539 | std::set<SvcParam> d_params; |
e5acc81c | 540 | DNSName d_target; |
18d5647a | 541 | uint16_t d_priority; |
a563ced8 PL |
542 | |
543 | // Get the iterator to parameter with |key|, return value can be d_params::end | |
467ad1f0 | 544 | std::set<SvcParam>::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const; |
e5acc81c PL |
545 | }; |
546 | ||
547 | class SVCBRecordContent : public SVCBBaseRecordContent | |
373914dc PL |
548 | { |
549 | public: | |
550 | includeboilerplate(SVCB) | |
467ad1f0 | 551 | std::shared_ptr<SVCBBaseRecordContent> clone() const override; |
373914dc PL |
552 | }; |
553 | ||
e5acc81c | 554 | class HTTPSRecordContent : public SVCBBaseRecordContent |
373914dc PL |
555 | { |
556 | public: | |
557 | includeboilerplate(HTTPS) | |
467ad1f0 | 558 | std::shared_ptr<SVCBBaseRecordContent> clone() const override; |
373914dc | 559 | }; |
07dbe87e | 560 | |
8c1c9170 BH |
561 | class RRSIGRecordContent : public DNSRecordContent |
562 | { | |
563 | public: | |
b35fe860 | 564 | RRSIGRecordContent(); |
8c1c9170 BH |
565 | includeboilerplate(RRSIG) |
566 | ||
34c513f9 RG |
567 | uint16_t d_type{0}; |
568 | uint16_t d_tag{0}; | |
89735451 PD |
569 | DNSName d_signer; |
570 | string d_signature; | |
34c513f9 RG |
571 | uint32_t d_originalttl{0}, d_sigexpire{0}, d_siginception{0}; |
572 | uint8_t d_algorithm{0}, d_labels{0}; | |
8c1c9170 BH |
573 | }; |
574 | ||
5ac6a3a3 | 575 | //namespace { |
b35fe860 | 576 | struct soatimes |
2770fad0 BH |
577 | { |
578 | uint32_t serial; | |
579 | uint32_t refresh; | |
580 | uint32_t retry; | |
581 | uint32_t expire; | |
582 | uint32_t minimum; | |
583 | }; | |
5ac6a3a3 | 584 | //} |
2770fad0 | 585 | |
3150a49c | 586 | class RKEYRecordContent : public DNSRecordContent |
587 | { | |
588 | public: | |
589 | RKEYRecordContent(); | |
590 | includeboilerplate(RKEY) | |
34c513f9 RG |
591 | uint16_t d_flags{0}; |
592 | uint8_t d_protocol{0}, d_algorithm{0}; | |
3150a49c | 593 | string d_key; |
594 | }; | |
2770fad0 BH |
595 | |
596 | class SOARecordContent : public DNSRecordContent | |
597 | { | |
598 | public: | |
599 | includeboilerplate(SOA) | |
1290c1d2 | 600 | SOARecordContent(DNSName mname, DNSName rname, const struct soatimes& st); |
2770fad0 | 601 | |
89735451 PD |
602 | DNSName d_mname; |
603 | DNSName d_rname; | |
1c21ab45 | 604 | struct soatimes d_st; |
2770fad0 | 605 | }; |
a0a276c2 | 606 | |
f01f7fa4 O |
607 | class ZONEMDRecordContent : public DNSRecordContent |
608 | { | |
609 | public: | |
610 | includeboilerplate(ZONEMD) | |
611 | //ZONEMDRecordContent(uint32_t serial, uint8_t scheme, uint8_t hashalgo, string digest); | |
612 | ||
f01f7fa4 O |
613 | uint32_t d_serial; |
614 | uint8_t d_scheme; | |
615 | uint8_t d_hashalgo; | |
616 | string d_digest; | |
617 | }; | |
618 | ||
27d4a65b RG |
619 | class NSECBitmap |
620 | { | |
621 | public: | |
22a0ef16 RG |
622 | NSECBitmap(): d_bitset(nullptr) |
623 | { | |
624 | } | |
625 | NSECBitmap(const NSECBitmap& rhs): d_set(rhs.d_set) | |
626 | { | |
627 | if (rhs.d_bitset) { | |
2bbc9eb0 | 628 | d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset)); |
22a0ef16 RG |
629 | } |
630 | } | |
631 | NSECBitmap& operator=(const NSECBitmap& rhs) | |
632 | { | |
633 | d_set = rhs.d_set; | |
634 | ||
635 | if (rhs.d_bitset) { | |
2bbc9eb0 | 636 | d_bitset = std::make_unique<std::bitset<nbTypes>>(*(rhs.d_bitset)); |
22a0ef16 RG |
637 | } |
638 | ||
639 | return *this; | |
640 | } | |
641 | NSECBitmap(NSECBitmap&& rhs): d_bitset(std::move(rhs.d_bitset)), d_set(std::move(rhs.d_set)) | |
642 | { | |
643 | } | |
27d4a65b RG |
644 | bool isSet(uint16_t type) const |
645 | { | |
646 | if (d_bitset) { | |
647 | return d_bitset->test(type); | |
648 | } | |
649 | return d_set.count(type); | |
650 | } | |
651 | void set(uint16_t type) | |
652 | { | |
653 | if (!d_bitset) { | |
654 | if (d_set.size() >= 200) { | |
655 | migrateToBitSet(); | |
656 | } | |
657 | } | |
658 | if (d_bitset) { | |
659 | d_bitset->set(type); | |
660 | } | |
661 | else { | |
662 | d_set.insert(type); | |
663 | } | |
664 | } | |
665 | size_t count() const | |
666 | { | |
667 | if (d_bitset) { | |
668 | return d_bitset->count(); | |
669 | } | |
670 | else { | |
671 | return d_set.size(); | |
672 | } | |
673 | } | |
674 | ||
675 | void fromPacket(PacketReader& pr); | |
d06dcda4 | 676 | void toPacket(DNSPacketWriter& pw) const; |
27d4a65b RG |
677 | std::string getZoneRepresentation() const; |
678 | ||
9f607f21 RG |
679 | static constexpr size_t const nbTypes = 65536; |
680 | ||
27d4a65b | 681 | private: |
9f607f21 | 682 | |
27d4a65b RG |
683 | void migrateToBitSet() |
684 | { | |
2bbc9eb0 | 685 | d_bitset = std::make_unique<std::bitset<nbTypes>>(); |
27d4a65b RG |
686 | for (const auto& type : d_set) { |
687 | d_bitset->set(type); | |
688 | } | |
689 | d_set.clear(); | |
690 | } | |
691 | /* using a dynamic set is very efficient for a small number of | |
692 | types covered (~200), but uses a lot of memory (up to 3MB) | |
693 | when there are a lot of them. | |
694 | So we start with the set, but allocate and switch to a bitset | |
695 | if the number of covered types increases a lot */ | |
9f607f21 | 696 | std::unique_ptr<std::bitset<nbTypes>> d_bitset; |
27d4a65b RG |
697 | std::set<uint16_t> d_set; |
698 | }; | |
699 | ||
20133c59 BH |
700 | class NSECRecordContent : public DNSRecordContent |
701 | { | |
702 | public: | |
df8248ca | 703 | static void report(); |
abb11ca4 | 704 | NSECRecordContent() = default; |
a2a77b28 | 705 | NSECRecordContent(const string& content, const DNSName& zone=DNSName()); |
20133c59 | 706 | |
32122aab RG |
707 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
708 | static std::shared_ptr<DNSRecordContent> make(const string& content); | |
f21fc0aa | 709 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 710 | void toPacket(DNSPacketWriter& pw) const override; |
5a1f298f | 711 | uint16_t getType() const override |
712 | { | |
713 | return QType::NSEC; | |
714 | } | |
27d4a65b RG |
715 | bool isSet(uint16_t type) const |
716 | { | |
717 | return d_bitmap.isSet(type); | |
718 | } | |
719 | void set(uint16_t type) | |
720 | { | |
721 | d_bitmap.set(type); | |
722 | } | |
22a0ef16 RG |
723 | void set(const NSECBitmap& bitmap) |
724 | { | |
725 | d_bitmap = bitmap; | |
726 | } | |
27d4a65b RG |
727 | size_t numberOfTypesSet() const |
728 | { | |
729 | return d_bitmap.count(); | |
730 | } | |
731 | ||
89735451 | 732 | DNSName d_next; |
20133c59 | 733 | private: |
27d4a65b | 734 | NSECBitmap d_bitmap; |
20133c59 BH |
735 | }; |
736 | ||
1c4d88c5 BH |
737 | class NSEC3RecordContent : public DNSRecordContent |
738 | { | |
739 | public: | |
df8248ca | 740 | static void report(); |
abb11ca4 | 741 | NSEC3RecordContent() = default; |
a2a77b28 | 742 | NSEC3RecordContent(const string& content, const DNSName& zone=DNSName()); |
1c4d88c5 | 743 | |
32122aab RG |
744 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
745 | static std::shared_ptr<DNSRecordContent> make(const string& content); | |
f21fc0aa | 746 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 747 | void toPacket(DNSPacketWriter& pw) const override; |
1c4d88c5 | 748 | |
34c513f9 RG |
749 | uint8_t d_algorithm{0}, d_flags{0}; |
750 | uint16_t d_iterations{0}; | |
1c4d88c5 | 751 | string d_salt; |
1c4d88c5 | 752 | string d_nexthash; |
1c4d88c5 | 753 | |
5a1f298f | 754 | uint16_t getType() const override |
755 | { | |
756 | return QType::NSEC3; | |
757 | } | |
27d4a65b RG |
758 | bool isSet(uint16_t type) const |
759 | { | |
760 | return d_bitmap.isSet(type); | |
761 | } | |
762 | void set(uint16_t type) | |
763 | { | |
764 | d_bitmap.set(type); | |
765 | } | |
22a0ef16 RG |
766 | void set(const NSECBitmap& bitmap) |
767 | { | |
768 | d_bitmap = bitmap; | |
769 | } | |
27d4a65b RG |
770 | size_t numberOfTypesSet() const |
771 | { | |
772 | return d_bitmap.count(); | |
773 | } | |
0cbcfeda RG |
774 | bool isOptOut() const |
775 | { | |
776 | return d_flags & 1; | |
777 | } | |
5a1f298f | 778 | |
1c4d88c5 | 779 | private: |
27d4a65b | 780 | NSECBitmap d_bitmap; |
1c4d88c5 BH |
781 | }; |
782 | ||
3a63bb5f PD |
783 | class CSYNCRecordContent : public DNSRecordContent |
784 | { | |
785 | public: | |
df8248ca | 786 | static void report(); |
abb11ca4 | 787 | CSYNCRecordContent() = default; |
3a63bb5f PD |
788 | CSYNCRecordContent(const string& content, const DNSName& zone=DNSName()); |
789 | ||
790 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); | |
791 | static std::shared_ptr<DNSRecordContent> make(const string& content); | |
792 | string getZoneRepresentation(bool noDot=false) const override; | |
d06dcda4 | 793 | void toPacket(DNSPacketWriter& pw) const override; |
3a63bb5f PD |
794 | |
795 | uint16_t getType() const override | |
796 | { | |
797 | return QType::CSYNC; | |
798 | } | |
799 | ||
800 | void set(uint16_t type) | |
801 | { | |
802 | d_bitmap.set(type); | |
803 | } | |
804 | ||
805 | private: | |
98c7dd26 PD |
806 | uint32_t d_serial{0}; |
807 | uint16_t d_flags{0}; | |
3a63bb5f PD |
808 | NSECBitmap d_bitmap; |
809 | }; | |
1c4d88c5 BH |
810 | |
811 | class NSEC3PARAMRecordContent : public DNSRecordContent | |
812 | { | |
813 | public: | |
df8248ca | 814 | static void report(); |
abb11ca4 | 815 | NSEC3PARAMRecordContent() = default; |
a2a77b28 | 816 | NSEC3PARAMRecordContent(const string& content, const DNSName& zone=DNSName()); |
827634f0 | 817 | |
32122aab RG |
818 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
819 | static std::shared_ptr<DNSRecordContent> make(const string& content); | |
f21fc0aa | 820 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 821 | void toPacket(DNSPacketWriter& pw) const override; |
827634f0 | 822 | |
5a1f298f | 823 | uint16_t getType() const override |
824 | { | |
825 | return QType::NSEC3PARAM; | |
826 | } | |
827 | ||
1c4d88c5 | 828 | |
34c513f9 RG |
829 | uint8_t d_algorithm{0}, d_flags{0}; |
830 | uint16_t d_iterations{0}; | |
1c4d88c5 BH |
831 | string d_salt; |
832 | }; | |
833 | ||
834 | ||
c6a60874 BH |
835 | class LOCRecordContent : public DNSRecordContent |
836 | { | |
837 | public: | |
df8248ca | 838 | static void report(); |
abb11ca4 | 839 | LOCRecordContent() = default; |
c6a60874 | 840 | LOCRecordContent(const string& content, const string& zone=""); |
20133c59 | 841 | |
32122aab RG |
842 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
843 | static std::shared_ptr<DNSRecordContent> make(const string& content); | |
f21fc0aa | 844 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 845 | void toPacket(DNSPacketWriter& pw) const override; |
c6a60874 | 846 | |
34c513f9 RG |
847 | uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0}; |
848 | uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0}; | |
5a1f298f | 849 | uint16_t getType() const override |
850 | { | |
851 | return QType::LOC; | |
852 | } | |
853 | ||
c6a60874 BH |
854 | private: |
855 | }; | |
8c1c9170 | 856 | |
786ed0ff PL |
857 | |
858 | class NIDRecordContent : public DNSRecordContent | |
859 | { | |
860 | public: | |
861 | includeboilerplate(NID); | |
862 | ||
863 | private: | |
864 | uint16_t d_preference; | |
865 | NodeOrLocatorID d_node_id; | |
866 | }; | |
867 | ||
868 | class L32RecordContent : public DNSRecordContent | |
869 | { | |
870 | public: | |
871 | includeboilerplate(L32); | |
872 | ||
873 | private: | |
874 | uint16_t d_preference; | |
875 | uint32_t d_locator; | |
876 | }; | |
877 | ||
878 | class L64RecordContent : public DNSRecordContent | |
879 | { | |
880 | public: | |
881 | includeboilerplate(L64); | |
882 | ||
883 | private: | |
884 | uint16_t d_preference; | |
885 | NodeOrLocatorID d_locator; | |
886 | }; | |
887 | ||
888 | class LPRecordContent : public DNSRecordContent | |
889 | { | |
890 | public: | |
891 | includeboilerplate(LP); | |
892 | ||
893 | private: | |
894 | uint16_t d_preference; | |
895 | DNSName d_fqdn; | |
896 | }; | |
897 | ||
b35fe860 | 898 | class EUI48RecordContent : public DNSRecordContent |
66a07c55 AT |
899 | { |
900 | public: | |
abb11ca4 | 901 | EUI48RecordContent() = default; |
df8248ca | 902 | static void report(); |
32122aab RG |
903 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
904 | static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone? | |
f21fc0aa | 905 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 906 | void toPacket(DNSPacketWriter& pw) const override; |
5a1f298f | 907 | uint16_t getType() const override { return QType::EUI48; } |
66a07c55 AT |
908 | private: |
909 | // storage for the bytes | |
b35fe860 | 910 | uint8_t d_eui48[6]; |
66a07c55 AT |
911 | }; |
912 | ||
913 | class EUI64RecordContent : public DNSRecordContent | |
914 | { | |
915 | public: | |
abb11ca4 | 916 | EUI64RecordContent() = default; |
df8248ca | 917 | static void report(); |
32122aab RG |
918 | static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); |
919 | static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone? | |
f21fc0aa | 920 | string getZoneRepresentation(bool noDot=false) const override; |
d06dcda4 | 921 | void toPacket(DNSPacketWriter& pw) const override; |
5a1f298f | 922 | uint16_t getType() const override { return QType::EUI64; } |
66a07c55 AT |
923 | private: |
924 | // storage for the bytes | |
925 | uint8_t d_eui64[8]; | |
926 | }; | |
d34d3e01 | 927 | |
66eb5eb7 ND |
928 | #define APL_FAMILY_IPV4 1 |
929 | #define APL_FAMILY_IPV6 2 | |
343ef20b ND |
930 | typedef struct s_APLRDataElement { |
931 | uint16_t d_family; | |
932 | uint8_t d_prefix; | |
933 | bool d_n : 1; | |
934 | unsigned int d_afdlength : 7; | |
a7bc63dd ND |
935 | union u_d_ip { |
936 | uint8_t d_ip4[4]; | |
937 | uint8_t d_ip6[16]; | |
938 | } d_ip; | |
343ef20b | 939 | } APLRDataElement; |
66eb5eb7 ND |
940 | class APLRecordContent : public DNSRecordContent |
941 | { | |
942 | public: | |
abb11ca4 | 943 | APLRecordContent() = default; |
16d54fe8 | 944 | includeboilerplate(APL) |
66eb5eb7 | 945 | private: |
343ef20b ND |
946 | std::vector<APLRDataElement> aplrdata; |
947 | APLRDataElement parseAPLElement(const string &element); | |
66eb5eb7 ND |
948 | }; |
949 | ||
950 | ||
b3ac6324 AT |
951 | class TKEYRecordContent : public DNSRecordContent |
952 | { | |
953 | public: | |
954 | TKEYRecordContent(); | |
955 | includeboilerplate(TKEY) | |
956 | ||
957 | // storage for the bytes | |
34c513f9 RG |
958 | uint16_t d_othersize{0}; |
959 | uint16_t d_mode{0}; | |
960 | uint32_t d_inception{0}; | |
961 | uint32_t d_expiration{0}; | |
adc18742 | 962 | |
0b6fa0eb | 963 | DNSName d_algo; |
b3ac6324 | 964 | string d_key; |
b3ac6324 | 965 | string d_other; |
adc18742 | 966 | |
34c513f9 RG |
967 | uint16_t d_error{0}; |
968 | uint16_t d_keysize{0}; | |
b3ac6324 AT |
969 | private: |
970 | }; | |
971 | ||
20966479 PL |
972 | class URIRecordContent : public DNSRecordContent { |
973 | public: | |
974 | includeboilerplate(URI) | |
975 | private: | |
fa38400f | 976 | uint16_t d_priority, d_weight; |
20966479 PL |
977 | string d_target; |
978 | }; | |
979 | ||
f75f6821 PL |
980 | class CAARecordContent : public DNSRecordContent { |
981 | public: | |
982 | includeboilerplate(CAA) | |
983 | private: | |
984 | uint8_t d_flags; | |
985 | string d_tag, d_value; | |
986 | }; | |
987 | ||
46fd1cbb | 988 | #define boilerplate(RNAME) \ |
32122aab | 989 | std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \ |
8c1c9170 | 990 | { \ |
32122aab | 991 | return std::make_shared<RNAME##RecordContent>(dr, pr); \ |
8c1c9170 BH |
992 | } \ |
993 | \ | |
5a1f298f | 994 | RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \ |
8c1c9170 BH |
995 | { \ |
996 | doRecordCheck(dr); \ | |
997 | xfrPacket(pr); \ | |
998 | } \ | |
999 | \ | |
32122aab | 1000 | std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata) \ |
8c1c9170 | 1001 | { \ |
32122aab | 1002 | return std::make_shared<RNAME##RecordContent>(zonedata); \ |
8c1c9170 BH |
1003 | } \ |
1004 | \ | |
d06dcda4 | 1005 | void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const \ |
8c1c9170 BH |
1006 | { \ |
1007 | this->xfrPacket(pw); \ | |
1008 | } \ | |
1009 | \ | |
1010 | void RNAME##RecordContent::report(void) \ | |
1011 | { \ | |
46fd1cbb OM |
1012 | regist(1, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \ |
1013 | regist(254, QType::RNAME, &RNAME##RecordContent::make, &RNAME##RecordContent::make, #RNAME); \ | |
ee1ada80 BH |
1014 | } \ |
1015 | void RNAME##RecordContent::unreport(void) \ | |
1016 | { \ | |
46fd1cbb OM |
1017 | unregist(1, QType::RNAME); \ |
1018 | unregist(254, QType::RNAME); \ | |
8c1c9170 BH |
1019 | } \ |
1020 | \ | |
5a1f298f | 1021 | RNAME##RecordContent::RNAME##RecordContent(const string& zoneData) \ |
8c1c9170 | 1022 | { \ |
aab4adb0 BH |
1023 | try { \ |
1024 | RecordTextReader rtr(zoneData); \ | |
1025 | xfrPacket(rtr); \ | |
1026 | } \ | |
81bb680e JS |
1027 | catch(RecordTextException& rte) { \ |
1028 | throw MOADNSException("Parsing record content (try 'pdnsutil check-zone'): "+string(rte.what())); \ | |
1649b6ef | 1029 | } \ |
8c1c9170 BH |
1030 | } \ |
1031 | \ | |
f21fc0aa | 1032 | string RNAME##RecordContent::getZoneRepresentation(bool noDot) const \ |
8c1c9170 BH |
1033 | { \ |
1034 | string ret; \ | |
f21fc0aa | 1035 | RecordTextWriter rtw(ret, noDot); \ |
8c1c9170 BH |
1036 | const_cast<RNAME##RecordContent*>(this)->xfrPacket(rtw); \ |
1037 | return ret; \ | |
b35fe860 FM |
1038 | } |
1039 | ||
8c1c9170 | 1040 | |
d73de874 FM |
1041 | #define boilerplate_conv(RNAME, CONV) \ |
1042 | boilerplate(RNAME) \ | |
1043 | template<class Convertor> \ | |
1044 | void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) \ | |
1045 | { \ | |
1046 | CONV; \ | |
ddb79bca | 1047 | if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \ |
d73de874 | 1048 | } \ |
d06dcda4 RG |
1049 | template<class Convertor> \ |
1050 | void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) const \ | |
1051 | { \ | |
1052 | CONV; \ | |
1053 | if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \ | |
1054 | } \ | |
8c1c9170 | 1055 | |
7f7b8d55 BH |
1056 | struct EDNSOpts |
1057 | { | |
5ca95d47 PL |
1058 | enum zFlags { DNSSECOK=32768 }; |
1059 | vector<pair<uint16_t, string> > d_options; | |
447e0cff | 1060 | uint16_t d_packetsize{0}; |
d6c335ab | 1061 | uint16_t d_extFlags{0}; |
5ca95d47 | 1062 | uint8_t d_extRCode, d_version; |
7f7b8d55 BH |
1063 | }; |
1064 | //! Convenience function that fills out EDNS0 options, and returns true if there are any | |
1065 | ||
1066 | class MOADNSParser; | |
1067 | bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo); | |
ea634573 BH |
1068 | void reportBasicTypes(); |
1069 | void reportOtherTypes(); | |
1070 | void reportAllTypes(); | |
f1ae49f7 | 1071 | ComboAddress getAddr(const DNSRecord& dr, uint16_t defport=0); |
97c8ea81 | 1072 | void checkHostnameCorrectness(const DNSResourceRecord& rr); |