]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsbackend.hh
dnsdist: Fix DNS over plain HTTP broken by `reloadAllCertificates()`
[thirdparty/pdns.git] / pdns / dnsbackend.hh
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
e8c59f2d 22#pragma once
12c86877 23
ed1038f5 24#include <algorithm>
fd9af6ec 25#include <cstddef>
973ad2b5
BH
26class DNSPacket;
27
12c86877
BH
28#include "utility.hh"
29#include <string>
68ba155d 30#include <utility>
12c86877
BH
31#include <vector>
32#include <map>
33#include <sys/types.h>
5c409fa2 34#include "pdnsexception.hh"
973ad2b5 35#include <set>
702b226d 36#include <iostream>
76473b92
KM
37#include <sys/socket.h>
38#include <dirent.h>
76979e74 39#include "misc.hh"
12c86877
BH
40#include "qtype.hh"
41#include "dns.hh"
10f4eea8 42#include "namespaces.hh"
6cc98ddf 43#include "comment.hh"
675fa24c 44#include "dnsname.hh"
28e2e78e 45#include "dnsrecords.hh"
a2dfc9ea 46#include "iputils.hh"
ddeea7a6 47#include "sha.hh"
8a66a927 48#include "auth-catalogzone.hh"
76979e74 49
ef20739c
CH
50class DNSBackend;
51struct SOAData;
52
12c86877
BH
53struct DomainInfo
54{
68ba155d 55 DomainInfo() = default;
52ff1db1 56
675fa24c 57 DNSName zone;
4bc3a9e0 58 DNSName catalog;
ed1038f5 59 time_t last_check{};
9da0c596 60 string options;
8ffb7a9b 61 string account;
d525b58b 62 vector<ComboAddress> primaries;
02789fe0 63 DNSBackend* backend{};
52ff1db1 64
ed1038f5
FM
65 uint32_t id{};
66 uint32_t notified_serial{};
52ff1db1 67
ed1038f5 68 bool receivedNotify{};
472429fb 69
ed1038f5 70 uint32_t serial{};
ddeea7a6 71
7f3d870e
BH
72 bool operator<(const DomainInfo& rhs) const
73 {
74 return zone < rhs.zone;
75 }
ec10217f 76
ddeea7a6
KM
77 // Do not reorder (lmdbbackend)!!! One exception 'All' is always last.
78 enum DomainKind : uint8_t
79 {
d525b58b 80 Primary,
c02c999b 81 Secondary,
ddeea7a6
KM
82 Native,
83 Producer,
84 Consumer,
85 All
68ba155d 86 } kind{DomainInfo::Native};
ddeea7a6 87
02789fe0 88 [[nodiscard]] const char* getKindString() const
76979e74
CH
89 {
90 return DomainInfo::getKindString(kind);
91 }
92
02789fe0 93 static const char* getKindString(enum DomainKind kind)
ec10217f 94 {
68ba155d
FM
95 std::array<const char*, 6> kinds{"Master", "Slave", "Native", "Producer", "Consumer", "All"};
96 return kinds.at(kind);
ec10217f 97 }
76979e74
CH
98
99 static DomainKind stringToKind(const string& kind)
100 {
ed1038f5 101 if (pdns_iequals(kind, "SECONDARY") || pdns_iequals(kind, "SLAVE")) {
c02c999b 102 return DomainInfo::Secondary;
ed1038f5
FM
103 }
104 if (pdns_iequals(kind, "PRIMARY") || pdns_iequals(kind, "MASTER")) {
d525b58b 105 return DomainInfo::Primary;
ed1038f5
FM
106 }
107 if (pdns_iequals(kind, "PRODUCER")) {
ddeea7a6 108 return DomainInfo::Producer;
ed1038f5
FM
109 }
110 if (pdns_iequals(kind, "CONSUMER")) {
ddeea7a6 111 return DomainInfo::Consumer;
ed1038f5 112 }
ddeea7a6
KM
113 // No "ALL" here please. Yes, I really mean it...
114 return DomainInfo::Native;
76979e74
CH
115 }
116
d525b58b 117 [[nodiscard]] bool isPrimaryType() const { return (kind == DomainInfo::Primary || kind == DomainInfo::Producer); }
c02c999b 118 [[nodiscard]] bool isSecondaryType() const { return (kind == DomainInfo::Secondary || kind == DomainInfo::Consumer); }
ed1038f5 119 [[nodiscard]] bool isCatalogType() const { return (kind == DomainInfo::Producer || kind == DomainInfo::Consumer); }
ddeea7a6 120
d525b58b 121 [[nodiscard]] bool isPrimary(const ComboAddress& ipAddress) const
a2dfc9ea 122 {
d525b58b 123 return std::any_of(primaries.begin(), primaries.end(), [ipAddress](auto primary) { return ComboAddress::addressOnlyEqual()(ipAddress, primary); });
a2dfc9ea 124 }
12c86877
BH
125};
126
02789fe0
FM
127struct TSIGKey
128{
129 DNSName name;
130 DNSName algorithm;
131 std::string key;
6f872b78
AT
132};
133
02789fe0
FM
134struct AutoPrimary
135{
68ba155d
FM
136 AutoPrimary(string new_ip, string new_nameserver, string new_account) :
137 ip(std::move(new_ip)), nameserver(std::move(new_nameserver)), account(std::move(new_account)){};
02789fe0
FM
138 std::string ip;
139 std::string nameserver;
140 std::string account;
782e9b24
AT
141};
142
12c86877 143class DNSPacket;
bdc9f8d2 144
35520716 145//! This virtual base class defines the interface for backends for PowerDNS.
bdc9f8d2
BH
146/** To create a backend, inherit from this class and implement functions for all virtual methods.
147 Methods should not throw an exception if they are sure they did not find the requested data. However,
148 if an error occurred which prevented them temporarily from performing a lockup, they should throw a DBException,
149 which will cause the nameserver to send out a ServFail or take other evasive action. Probably only locking
150 issues should lead to DBExceptions.
151
152 More serious errors, which may indicate that the database connection is hosed, or a configuration error occurred, should
3f81d239 153 lead to the throwing of an PDNSException. This exception will fall straight through the UeberBackend and the PacketHandler
bdc9f8d2
BH
154 and be caught by the Distributor, which will delete your DNSBackend instance and spawn a new one.
155*/
12c86877
BH
156class DNSBackend
157{
158public:
bdc9f8d2 159 //! lookup() initiates a lookup. A lookup without results should not throw!
02789fe0
FM
160 virtual void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket* pkt_p = nullptr) = 0;
161 virtual bool get(DNSResourceRecord&) = 0; //!< retrieves one DNSResource record, returns false if no more were available
68ba155d 162 virtual bool get(DNSZoneRecord& zoneRecord);
702b226d 163
bdc9f8d2
BH
164 //! Initiates a list of the specified domain
165 /** Once initiated, DNSResourceRecord objects can be retrieved using get(). Should return false
166 if the backend does not consider itself responsible for the id passed.
167 \param domain_id ID of which a list is requested
168 */
02789fe0 169 virtual bool list(const DNSName& target, int domain_id, bool include_disabled = false) = 0;
12c86877 170
abb11ca4 171 virtual ~DNSBackend() = default;
12c86877 172
bdc9f8d2 173 //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
68ba155d 174 virtual bool getSOA(const DNSName& domain, SOAData& soaData);
d07fc616 175
d73de874 176 virtual bool replaceRRSet(uint32_t /* domain_id */, const DNSName& /* qname */, const QType& /* qt */, const vector<DNSResourceRecord>& /* rrset */)
8bbb6f36
BH
177 {
178 return false;
179 }
180
d73de874 181 virtual bool listSubZone(const DNSName& /* zone */, int /* domain_id */)
6a323f63
RA
182 {
183 return false;
184 }
185
4aafcb39 186 // the DNSSEC related (getDomainMetadata has broader uses too)
ed1038f5
FM
187 static bool isDnssecDomainMetadata(const string& name)
188 {
ad34750d
KM
189 return (name == "PRESIGNED" || name == "NSEC3PARAM" || name == "NSEC3NARROW");
190 }
d73de874
FM
191 virtual bool getAllDomainMetadata(const DNSName& /* name */, std::map<std::string, std::vector<std::string>>& /* meta */) { return false; };
192 virtual bool getDomainMetadata(const DNSName& /* name */, const std::string& /* kind */, std::vector<std::string>& /* meta */) { return false; }
675fa24c 193 virtual bool getDomainMetadataOne(const DNSName& name, const std::string& kind, std::string& value)
d29d5db7
CH
194 {
195 std::vector<std::string> meta;
196 if (getDomainMetadata(name, kind, meta)) {
ed1038f5 197 if (!meta.empty()) {
d29d5db7
CH
198 value = *meta.begin();
199 return true;
200 }
201 }
202 return false;
203 }
204
d73de874 205 virtual bool setDomainMetadata(const DNSName& /* name */, const std::string& /* kind */, const std::vector<std::string>& /* meta */) { return false; }
675fa24c 206 virtual bool setDomainMetadataOne(const DNSName& name, const std::string& kind, const std::string& value)
d29d5db7
CH
207 {
208 const std::vector<std::string> meta(1, value);
209 return setDomainMetadata(name, kind, meta);
210 }
211
39dafc3b 212 virtual void getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled);
1325e8a2 213
c14bc34a 214 /** Determines if we are authoritative for a zone, and at what level */
d73de874 215 virtual bool getAuth(const DNSName& target, SOAData* /* sd */);
c14bc34a 216
02789fe0
FM
217 struct KeyData
218 {
eda140fa 219 std::string content;
ed5dfdee
RG
220 unsigned int id{0};
221 unsigned int flags{0};
222 bool active{false};
223 bool published{false};
4aafcb39
BH
224 };
225
d73de874
FM
226 virtual bool getDomainKeys(const DNSName& /* name */, std::vector<KeyData>& /* keys */) { return false; }
227 virtual bool removeDomainKey(const DNSName& /* name */, unsigned int /* id */) { return false; }
228 virtual bool addDomainKey(const DNSName& /* name */, const KeyData& /* key */, int64_t& /* id */) { return false; }
229 virtual bool activateDomainKey(const DNSName& /* name */, unsigned int /* id */) { return false; }
230 virtual bool deactivateDomainKey(const DNSName& /* name */, unsigned int /* id */) { return false; }
231 virtual bool publishDomainKey(const DNSName& /* name */, unsigned int /* id */) { return false; }
232 virtual bool unpublishDomainKey(const DNSName& /* name */, unsigned int /* id */) { return false; }
8ab63616 233
d73de874
FM
234 virtual bool setTSIGKey(const DNSName& /* name */, const DNSName& /* algorithm */, const string& /* content */) { return false; }
235 virtual bool getTSIGKey(const DNSName& /* name */, DNSName& /* algorithm */, string& /* content */) { return false; }
236 virtual bool getTSIGKeys(std::vector<struct TSIGKey>& /* keys */) { return false; }
237 virtual bool deleteTSIGKey(const DNSName& /* name */) { return false; }
78bcb858 238
d73de874 239 virtual bool getBeforeAndAfterNamesAbsolute(uint32_t /* id */, const DNSName& /* qname */, DNSName& /* unhashed */, DNSName& /* before */, DNSName& /* after */)
4aafcb39 240 {
d73de874 241 std::cerr << "Default beforeAndAfterAbsolute called!" << std::endl;
4aafcb39
BH
242 abort();
243 return false;
244 }
245
d73de874 246 virtual bool getBeforeAndAfterNames(uint32_t /* id */, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after);
4aafcb39 247
d73de874 248 virtual bool updateDNSSECOrderNameAndAuth(uint32_t /* domain_id */, const DNSName& /* qname */, const DNSName& /* ordername */, bool /* auth */, const uint16_t /* qtype */ = QType::ANY)
4aafcb39
BH
249 {
250 return false;
251 }
252
d73de874 253 virtual bool updateEmptyNonTerminals(uint32_t /* domain_id */, set<DNSName>& /* insert */, set<DNSName>& /* erase */, bool /* remove */)
c2df797e
PD
254 {
255 return false;
256 }
257
ece45ffb
PD
258 virtual bool doesDNSSEC()
259 {
260 return false;
261 }
262
4aafcb39
BH
263 // end DNSSEC
264
6cc98ddf 265 // comments support
d73de874 266 virtual bool listComments(uint32_t /* domain_id */)
6cc98ddf
CH
267 {
268 return false; // unsupported by this backend
269 }
270
d73de874 271 virtual bool getComment(Comment& /* comment */)
6cc98ddf
CH
272 {
273 return false;
274 }
275
f79eef05 276 virtual bool feedComment(const Comment& /* comment */)
6cc98ddf 277 {
f79eef05 278 return false;
6cc98ddf
CH
279 }
280
d73de874 281 virtual bool replaceComments(const uint32_t /* domain_id */, const DNSName& /* qname */, const QType& /* qt */, const vector<Comment>& /* comments */)
6cc98ddf
CH
282 {
283 return false;
284 }
285
d525b58b 286 //! returns true if primary ip is primary for domain name.
bdc9f8d2 287 //! starts the transaction for updating domain qname (FIXME: what is id?)
d73de874 288 virtual bool startTransaction(const DNSName& /* qname */, int /* id */ = -1)
12c86877
BH
289 {
290 return false;
291 }
292
bdc9f8d2 293 //! commits the transaction started by startTransaction
12c86877
BH
294 virtual bool commitTransaction()
295 {
296 return false;
297 }
298
d07ed91e 299 //! aborts the transaction started by startTransaction, should leave state unaltered
12c86877
BH
300 virtual bool abortTransaction()
301 {
302 return false;
303 }
304
9c56d755
KM
305 virtual bool inTransaction()
306 {
307 return false;
308 }
309
12c86877
BH
310 virtual void reload()
311 {
312 }
313
d73de874 314 virtual void rediscover(string* /* status */ = nullptr)
12c86877
BH
315 {
316 }
317
bdc9f8d2 318 //! feeds a record to a zone, needs a call to startTransaction first
d73de874 319 virtual bool feedRecord(const DNSResourceRecord& /* rr */, const DNSName& /* ordername */, bool /* ordernameIsNSEC3 */ = false)
12c86877
BH
320 {
321 return false; // no problem!
322 }
d73de874 323 virtual bool feedEnts(int /* domain_id */, map<DNSName, bool>& /* nonterm */)
f9cf6d92
KM
324 {
325 return false;
326 }
d73de874 327 virtual bool feedEnts3(int /* domain_id */, const DNSName& /* domain */, map<DNSName, bool>& /* nonterm */, const NSEC3PARAMRecordContent& /* ns3prc */, bool /* narrow */)
f9cf6d92
KM
328 {
329 return false;
330 }
331
bdc9f8d2 332 //! if this returns true, DomainInfo di contains information about the domain
d73de874 333 virtual bool getDomainInfo(const DNSName& /* domain */, DomainInfo& /* di */, bool /* getSerial */ = true)
12c86877
BH
334 {
335 return false;
336 }
c02c999b
KM
337 //! secondary capable backends should return a list of secondaries that should be rechecked for staleness
338 virtual void getUnfreshSecondaryInfos(vector<DomainInfo>* /* domains */)
12c86877
BH
339 {
340 }
341
bdc9f8d2 342 //! get a list of IP addresses that should also be notified for a domain
d73de874 343 virtual void alsoNotifies(const DNSName& domain, set<string>* ips)
12c86877 344 {
338041a8
PD
345 std::vector<std::string> meta;
346 getDomainMetadata(domain, "ALSO-NOTIFY", meta);
347 ips->insert(meta.begin(), meta.end());
12c86877 348 }
bdc9f8d2 349
c02c999b 350 //! get list of domains that have been changed since their last notification to secondaries
d525b58b 351 virtual void getUpdatedPrimaries(vector<DomainInfo>& /* domains */, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
12c86877
BH
352 {
353 }
ce8c5899 354
8a66a927 355 //! get list of all members in a catalog
d73de874 356 virtual bool getCatalogMembers(const DNSName& /* catalog */, vector<CatalogInfo>& /* members */, CatalogInfo::CatalogType /* type */)
8a66a927
KM
357 {
358 return false;
359 }
360
ce8c5899 361 //! Called by PowerDNS to inform a backend that a domain need to be checked for freshness
d73de874 362 virtual void setStale(uint32_t /* domain_id */)
ce8c5899
KM
363 {
364 }
365
bdc9f8d2 366 //! Called by PowerDNS to inform a backend that a domain has been checked for freshness
d73de874 367 virtual void setFresh(uint32_t /* domain_id */)
12c86877 368 {
12c86877 369 }
ce8c5899 370
c02c999b 371 //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to secondaries
d73de874 372 virtual void setNotified(uint32_t /* id */, uint32_t /* serial */)
12c86877
BH
373 {
374 }
375
d525b58b
KM
376 //! Called when the Primary list of a domain should be changed
377 virtual bool setPrimaries(const DNSName& /* domain */, const vector<ComboAddress>& /* primaries */)
6d58359c
CH
378 {
379 return false;
380 }
381
d525b58b 382 //! Called when the Kind of a domain should be changed (primary -> native and similar)
d73de874 383 virtual bool setKind(const DNSName& /* domain */, const DomainInfo::DomainKind /* kind */)
6d58359c
CH
384 {
385 return false;
386 }
387
9da0c596 388 //! Called when the options of a domain should be changed
d73de874 389 virtual bool setOptions(const DNSName& /* domain */, const string& /* options */)
9da0c596
KM
390 {
391 return false;
392 }
393
4bc3a9e0 394 //! Called when the catalog of a domain should be changed
d73de874 395 virtual bool setCatalog(const DNSName& /* domain */, const DNSName& /* catalog */)
4bc3a9e0
KM
396 {
397 return false;
398 }
399
79532aa7 400 //! Called when the Account of a domain should be changed
d73de874 401 virtual bool setAccount(const DNSName& /* domain */, const string& /* account */)
79532aa7
CH
402 {
403 return false;
404 }
405
bdc9f8d2 406 //! Can be called to seed the getArg() function with a prefix
02789fe0 407 void setArgPrefix(const string& prefix);
bdc9f8d2 408
d525b58b
KM
409 //! Add an entry for a super primary
410 virtual bool autoPrimaryAdd(const struct AutoPrimary& /* primary */)
3d26f6dc 411 {
d73de874 412 return false;
3d26f6dc
E
413 }
414
d525b58b 415 //! Remove an entry for a super primary
d73de874 416 virtual bool autoPrimaryRemove(const struct AutoPrimary& /* primary */)
782e9b24
AT
417 {
418 return false;
419 }
420
d525b58b 421 //! List all AutoPrimaries, returns false if feature not supported.
d73de874 422 virtual bool autoPrimariesList(std::vector<AutoPrimary>& /* primaries */)
782e9b24
AT
423 {
424 return false;
425 }
426
d525b58b
KM
427 //! determine if ip is a autoprimary or a domain
428 virtual bool autoPrimaryBackend(const string& /* ip */, const DNSName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* /* account */, DNSBackend** /* db */)
12c86877
BH
429 {
430 return false;
431 }
bdc9f8d2 432
487cf033 433 //! called by PowerDNS to create a new domain
d525b58b 434 virtual bool createDomain(const DNSName& /* domain */, const DomainInfo::DomainKind /* kind */, const vector<ComboAddress>& /* primaries */, const string& /* account */)
487cf033
CH
435 {
436 return false;
437 }
438
c02c999b
KM
439 //! called by PowerDNS to create a secondary record for a autoPrimary
440 virtual bool createSecondaryDomain(const string& /* ip */, const DNSName& /* domain */, const string& /* nameserver */, const string& /* account */)
12c86877
BH
441 {
442 return false;
443 }
444
44e62984 445 //! called to delete a domain, incl. all metadata, zone contents, etc.
d73de874 446 virtual bool deleteDomain(const DNSName& /* domain */)
44e62984
CH
447 {
448 return false;
449 }
450
d73de874 451 virtual string directBackendCmd(const string& /* query */)
f641c3b7
PD
452 {
453 return "directBackendCmd not supported for this backend\n";
454 }
455
9f8e226e 456 //! Search for records, returns true if search was done successfully.
fd9af6ec 457 virtual bool searchRecords(const string& /* pattern */, size_t /* maxResults */, vector<DNSResourceRecord>& /* result */)
9f8e226e
AT
458 {
459 return false;
460 }
461
462 //! Search for comments, returns true if search was done successfully.
fd9af6ec 463 virtual bool searchComments(const string& /* pattern */, size_t /* maxResults */, vector<Comment>& /* result */)
9f8e226e
AT
464 {
465 return false;
466 }
467
ece1aa0b 468 const string& getPrefix() { return d_prefix; };
02789fe0 469
12c86877 470protected:
02789fe0
FM
471 bool mustDo(const string& key);
472 const string& getArg(const string& key);
473 int getArgAsNum(const string& key);
12c86877
BH
474
475private:
476 string d_prefix;
477};
478
479class BackendFactory
480{
481public:
02789fe0
FM
482 BackendFactory(const string& name) :
483 d_name(name) {}
abb11ca4 484 virtual ~BackendFactory() = default;
02789fe0
FM
485 virtual DNSBackend* make(const string& suffix) = 0;
486 virtual DNSBackend* makeMetadataOnly(const string& suffix)
2717b8b3
BH
487 {
488 return this->make(suffix);
489 }
d73de874
FM
490 virtual void declareArguments(const string& /* suffix */ = "") {}
491 [[nodiscard]] const string& getName() const;
492
12c86877 493protected:
02789fe0 494 void declare(const string& suffix, const string& param, const string& explanation, const string& value);
12c86877
BH
495
496private:
68ba155d 497 string d_name;
12c86877
BH
498};
499
500class BackendMakerClass
501{
502public:
5144dfa8 503 void report(std::unique_ptr<BackendFactory>&& backendFactory);
02789fe0
FM
504 void launch(const string& instr);
505 vector<std::unique_ptr<DNSBackend>> all(bool metadataOnly = false);
68ba155d 506 static void load(const string& module);
ed1038f5 507 [[nodiscard]] size_t numLauncheable() const;
12c86877 508 vector<string> getModules();
b51bb9a2 509 void clear();
12c86877
BH
510
511private:
68ba155d 512 static void load_all();
5144dfa8 513 using d_repository_t = map<string, std::unique_ptr<BackendFactory>>;
12c86877 514 d_repository_t d_repository;
02789fe0 515 vector<pair<string, string>> d_instances;
12c86877
BH
516};
517
02789fe0 518extern BackendMakerClass& BackendMakers();
12c86877 519
bdc9f8d2 520//! Exception that can be thrown by a DNSBackend to indicate a failure
3f81d239 521class DBException : public PDNSException
cc3afe25
BH
522{
523public:
02789fe0
FM
524 DBException(const string& reason_) :
525 PDNSException(reason_) {}
cc3afe25
BH
526};
527
ef20739c
CH
528struct SOAData
529{
02789fe0
FM
530 SOAData() :
531 domain_id(-1){};
ef20739c
CH
532
533 DNSName qname;
534 DNSName nameserver;
d525b58b 535 DNSName rname;
ed1038f5
FM
536 uint32_t ttl{};
537 uint32_t serial{};
538 uint32_t refresh{};
539 uint32_t retry{};
540 uint32_t expire{};
541 uint32_t minimum{};
02789fe0 542 DNSBackend* db{};
ed1038f5
FM
543 int domain_id{};
544
545 [[nodiscard]] uint32_t getNegativeTTL() const { return min(ttl, minimum); }
ef20739c
CH
546};
547
ceea1ba6 548/** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
68ba155d 549void fillSOAData(const string& content, SOAData& soaData);
90ba52e0 550// same but more karmic
68ba155d 551void fillSOAData(const DNSZoneRecord& inZoneRecord, SOAData& soaData);
90ba52e0 552// the reverse
68ba155d 553std::shared_ptr<DNSRecordContent> makeSOAContent(const SOAData& soaData);