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