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