]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsbackend.hh
Avoid throwing an exception in Logger::log().
[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
973ad2b5
BH
24class DNSPacket;
25
12c86877
BH
26#include "utility.hh"
27#include <string>
28#include <vector>
29#include <map>
30#include <sys/types.h>
5c409fa2 31#include "pdnsexception.hh"
973ad2b5 32#include <set>
702b226d 33#include <iostream>
76473b92
KM
34#include <sys/socket.h>
35#include <dirent.h>
76979e74 36#include "misc.hh"
12c86877
BH
37#include "qtype.hh"
38#include "dns.hh"
e5b11b2f 39#include <vector>
10f4eea8 40#include "namespaces.hh"
6cc98ddf 41#include "comment.hh"
675fa24c 42#include "dnsname.hh"
28e2e78e 43#include "dnsrecords.hh"
a2dfc9ea 44#include "iputils.hh"
76979e74 45
12c86877
BH
46class DNSBackend;
47struct DomainInfo
48{
f82ed9fc 49 DomainInfo() : last_check(0), backend(NULL), id(0), notified_serial(0), serial(0), kind(DomainInfo::Native) {}
52ff1db1 50
675fa24c 51 DNSName zone;
12c86877 52 time_t last_check;
8ffb7a9b 53 string account;
d622042f 54 vector<ComboAddress> masters;
12c86877 55 DNSBackend *backend;
52ff1db1
PL
56
57 uint32_t id;
58 uint32_t notified_serial;
59
60 uint32_t serial;
61 enum DomainKind : uint8_t { Master, Slave, Native } kind;
7f3d870e
BH
62
63 bool operator<(const DomainInfo& rhs) const
64 {
65 return zone < rhs.zone;
66 }
ec10217f
CH
67
68 const char *getKindString() const
76979e74
CH
69 {
70 return DomainInfo::getKindString(kind);
71 }
72
73 static const char *getKindString(enum DomainKind kind)
ec10217f
CH
74 {
75 const char *kinds[]={"Master", "Slave", "Native"};
76 return kinds[kind];
77 }
76979e74
CH
78
79 static DomainKind stringToKind(const string& kind)
80 {
81 if(pdns_iequals(kind,"SLAVE"))
82 return DomainInfo::Slave;
83 else if(pdns_iequals(kind,"MASTER"))
84 return DomainInfo::Master;
85 else
86 return DomainInfo::Native;
87 }
88
2f538e82 89 bool isMaster(const ComboAddress& ip) const
a2dfc9ea
KM
90 {
91 for( const auto& master: masters) {
f43e6a40 92 if(ComboAddress::addressOnlyEqual()(ip, master))
a2dfc9ea
KM
93 return true;
94 }
95 return false;
96 }
97
12c86877
BH
98};
99
6f872b78 100struct TSIGKey {
675fa24c
PD
101 DNSName name;
102 DNSName algorithm;
6f872b78
AT
103 std::string key;
104};
105
12c86877 106class DNSPacket;
bdc9f8d2 107
35520716 108//! This virtual base class defines the interface for backends for PowerDNS.
bdc9f8d2
BH
109/** To create a backend, inherit from this class and implement functions for all virtual methods.
110 Methods should not throw an exception if they are sure they did not find the requested data. However,
111 if an error occurred which prevented them temporarily from performing a lockup, they should throw a DBException,
112 which will cause the nameserver to send out a ServFail or take other evasive action. Probably only locking
113 issues should lead to DBExceptions.
114
115 More serious errors, which may indicate that the database connection is hosed, or a configuration error occurred, should
3f81d239 116 lead to the throwing of an PDNSException. This exception will fall straight through the UeberBackend and the PacketHandler
bdc9f8d2
BH
117 and be caught by the Distributor, which will delete your DNSBackend instance and spawn a new one.
118*/
12c86877
BH
119class DNSBackend
120{
121public:
bdc9f8d2 122 //! lookup() initiates a lookup. A lookup without results should not throw!
acb61e0a 123 virtual void lookup(const QType &qtype, const DNSName &qdomain, int zoneId=-1, DNSPacket *pkt_p=nullptr)=0;
bdc9f8d2 124 virtual bool get(DNSResourceRecord &)=0; //!< retrieves one DNSResource record, returns false if no more were available
90ba52e0 125 virtual bool get(DNSZoneRecord &r);
702b226d 126
bdc9f8d2
BH
127 //! Initiates a list of the specified domain
128 /** Once initiated, DNSResourceRecord objects can be retrieved using get(). Should return false
129 if the backend does not consider itself responsible for the id passed.
130 \param domain_id ID of which a list is requested
131 */
675fa24c 132 virtual bool list(const DNSName &target, int domain_id, bool include_disabled=false)=0;
12c86877
BH
133
134 virtual ~DNSBackend(){};
135
bdc9f8d2 136 //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
76e1255a 137 virtual bool getSOA(const DNSName &name, SOAData &soadata);
d07fc616 138
675fa24c 139 virtual bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset)
8bbb6f36
BH
140 {
141 return false;
142 }
143
675fa24c 144 virtual bool listSubZone(const DNSName &zone, int domain_id)
6a323f63
RA
145 {
146 return false;
147 }
148
4aafcb39 149 // the DNSSEC related (getDomainMetadata has broader uses too)
ad34750d
KM
150 bool isDnssecDomainMetadata (const string& name) {
151 return (name == "PRESIGNED" || name == "NSEC3PARAM" || name == "NSEC3NARROW");
152 }
675fa24c
PD
153 virtual bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta) { return false; };
154 virtual bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) { return false; }
155 virtual bool getDomainMetadataOne(const DNSName& name, const std::string& kind, std::string& value)
d29d5db7
CH
156 {
157 std::vector<std::string> meta;
158 if (getDomainMetadata(name, kind, meta)) {
159 if(!meta.empty()) {
160 value = *meta.begin();
161 return true;
162 }
163 }
164 return false;
165 }
166
675fa24c
PD
167 virtual bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) {return false;}
168 virtual bool setDomainMetadataOne(const DNSName& name, const std::string& kind, const std::string& value)
d29d5db7
CH
169 {
170 const std::vector<std::string> meta(1, value);
171 return setDomainMetadata(name, kind, meta);
172 }
173
4aafcb39 174
cea26350 175 virtual void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false) { }
1325e8a2 176
c14bc34a 177 /** Determines if we are authoritative for a zone, and at what level */
cec52de6 178 virtual bool getAuth(const DNSName &target, SOAData *sd);
c14bc34a 179
4aafcb39 180 struct KeyData {
eda140fa 181 std::string content;
4aafcb39
BH
182 unsigned int id;
183 unsigned int flags;
184 bool active;
33918299 185 bool published;
4aafcb39
BH
186 };
187
9c1c5d49 188 virtual bool getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) { return false;}
675fa24c 189 virtual bool removeDomainKey(const DNSName& name, unsigned int id) { return false; }
82cc0761 190 virtual bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id){ return false; }
675fa24c
PD
191 virtual bool activateDomainKey(const DNSName& name, unsigned int id) { return false; }
192 virtual bool deactivateDomainKey(const DNSName& name, unsigned int id) { return false; }
33918299
RG
193 virtual bool publishDomainKey(const DNSName& name, unsigned int id) { return false; }
194 virtual bool unpublishDomainKey(const DNSName& name, unsigned int id) { return false; }
8ab63616 195
675fa24c
PD
196 virtual bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) { return false; }
197 virtual bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) { return false; }
198 virtual bool deleteTSIGKey(const DNSName& name) { return false; }
6f872b78 199 virtual bool getTSIGKeys(std::vector< struct TSIGKey > &keys) { return false; }
78bcb858 200
29e0008a 201 virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after)
4aafcb39
BH
202 {
203 std::cerr<<"Default beforeAndAfterAbsolute called!"<<std::endl;
204 abort();
205 return false;
206 }
207
675fa24c 208 virtual bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after);
4aafcb39 209
96e63d77 210 virtual bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype=QType::ANY)
4aafcb39
BH
211 {
212 return false;
213 }
214
96e63d77 215 virtual bool updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove)
c2df797e
PD
216 {
217 return false;
218 }
219
ece45ffb
PD
220 virtual bool doesDNSSEC()
221 {
222 return false;
223 }
224
4aafcb39
BH
225 // end DNSSEC
226
6cc98ddf
CH
227 // comments support
228 virtual bool listComments(uint32_t domain_id)
229 {
230 return false; // unsupported by this backend
231 }
232
233 virtual bool getComment(Comment& comment)
234 {
235 return false;
236 }
237
238 virtual void feedComment(const Comment& comment)
239 {
240 }
241
675fa24c 242 virtual bool replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<Comment>& comments)
6cc98ddf
CH
243 {
244 return false;
245 }
246
bdc9f8d2 247 //! returns true if master ip is master for domain name.
bdc9f8d2 248 //! starts the transaction for updating domain qname (FIXME: what is id?)
675fa24c 249 virtual bool startTransaction(const DNSName &qname, int id=-1)
12c86877
BH
250 {
251 return false;
252 }
253
bdc9f8d2 254 //! commits the transaction started by startTransaction
12c86877
BH
255 virtual bool commitTransaction()
256 {
257 return false;
258 }
259
bdc9f8d2 260 //! aborts the transaction started by strartTransaction, should leave state unaltered
12c86877
BH
261 virtual bool abortTransaction()
262 {
263 return false;
264 }
265
266 virtual void reload()
267 {
268 }
269
973ad2b5 270 virtual void rediscover(string* status=0)
12c86877
BH
271 {
272 }
273
bdc9f8d2 274 //! feeds a record to a zone, needs a call to startTransaction first
3bb3f561 275 virtual bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false)
12c86877
BH
276 {
277 return false; // no problem!
278 }
675fa24c 279 virtual bool feedEnts(int domain_id, map<DNSName,bool> &nonterm)
f9cf6d92
KM
280 {
281 return false;
282 }
28e2e78e 283 virtual bool feedEnts3(int domain_id, const DNSName &domain, map<DNSName,bool> &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow)
f9cf6d92
KM
284 {
285 return false;
286 }
287
bdc9f8d2 288 //! if this returns true, DomainInfo di contains information about the domain
47bddbb7 289 virtual bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true)
12c86877
BH
290 {
291 return false;
292 }
bdc9f8d2 293 //! slave capable backends should return a list of slaves that should be rechecked for staleness
12c86877
BH
294 virtual void getUnfreshSlaveInfos(vector<DomainInfo>* domains)
295 {
296 }
297
bdc9f8d2 298 //! get a list of IP addresses that should also be notified for a domain
675fa24c 299 virtual void alsoNotifies(const DNSName &domain, set<string> *ips)
12c86877
BH
300 {
301 }
bdc9f8d2
BH
302
303 //! get list of domains that have been changed since their last notification to slaves
12c86877
BH
304 virtual void getUpdatedMasters(vector<DomainInfo>* domains)
305 {
306 }
bdc9f8d2
BH
307
308 //! Called by PowerDNS to inform a backend that a domain has been checked for freshness
092f210a 309 virtual void setFresh(uint32_t domain_id)
12c86877
BH
310 {
311
312 }
bdc9f8d2 313 //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to slaves
092f210a 314 virtual void setNotified(uint32_t id, uint32_t serial)
12c86877
BH
315 {
316 }
317
6d58359c 318 //! Called when the Master of a domain should be changed
675fa24c 319 virtual bool setMaster(const DNSName &domain, const string &ip)
6d58359c
CH
320 {
321 return false;
322 }
323
324 //! Called when the Kind of a domain should be changed (master -> native and similar)
675fa24c 325 virtual bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind)
6d58359c
CH
326 {
327 return false;
328 }
329
79532aa7 330 //! Called when the Account of a domain should be changed
675fa24c 331 virtual bool setAccount(const DNSName &domain, const string &account)
79532aa7
CH
332 {
333 return false;
334 }
335
bdc9f8d2 336 //! Can be called to seed the getArg() function with a prefix
12c86877 337 void setArgPrefix(const string &prefix);
bdc9f8d2
BH
338
339 //! determine if ip is a supermaster or a domain
675fa24c 340 virtual bool superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db)
12c86877
BH
341 {
342 return false;
343 }
bdc9f8d2 344
487cf033 345 //! called by PowerDNS to create a new domain
675fa24c 346 virtual bool createDomain(const DNSName &domain)
487cf033
CH
347 {
348 return false;
349 }
350
bdc9f8d2 351 //! called by PowerDNS to create a slave record for a superMaster
675fa24c 352 virtual bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account)
12c86877
BH
353 {
354 return false;
355 }
356
44e62984 357 //! called to delete a domain, incl. all metadata, zone contents, etc.
675fa24c 358 virtual bool deleteDomain(const DNSName &domain)
44e62984
CH
359 {
360 return false;
361 }
362
f641c3b7
PD
363 virtual string directBackendCmd(const string &query)
364 {
365 return "directBackendCmd not supported for this backend\n";
366 }
367
9f8e226e
AT
368 //! Search for records, returns true if search was done successfully.
369 virtual bool searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result)
370 {
371 return false;
372 }
373
374 //! Search for comments, returns true if search was done successfully.
375 virtual bool searchComments(const string &pattern, int maxResults, vector<Comment>& result)
376 {
377 return false;
378 }
379
ece1aa0b 380 const string& getPrefix() { return d_prefix; };
12c86877
BH
381protected:
382 bool mustDo(const string &key);
383 const string &getArg(const string &key);
384 int getArgAsNum(const string &key);
12c86877
BH
385
386private:
387 string d_prefix;
388};
389
390class BackendFactory
391{
392public:
393 BackendFactory(const string &name) : d_name(name) {}
394 virtual ~BackendFactory(){}
395 virtual DNSBackend *make(const string &suffix)=0;
2717b8b3
BH
396 virtual DNSBackend *makeMetadataOnly(const string &suffix)
397 {
398 return this->make(suffix);
399 }
12c86877
BH
400 virtual void declareArguments(const string &suffix=""){}
401 const string &getName() const;
402
403protected:
404 void declare(const string &suffix, const string &param, const string &explanation, const string &value);
405
406private:
407 const string d_name;
408};
409
410class BackendMakerClass
411{
412public:
413 void report(BackendFactory *bf);
414 void launch(const string &instr);
e0d84497 415 vector<DNSBackend *>all(bool skipBIND=false);
12c86877
BH
416 void load(const string &module);
417 int numLauncheable();
418 vector<string> getModules();
419
420private:
421 void load_all();
422 typedef map<string,BackendFactory *>d_repository_t;
423 d_repository_t d_repository;
424 vector<pair<string,string> >d_instances;
425};
426
427extern BackendMakerClass &BackendMakers();
428
bdc9f8d2 429//! Exception that can be thrown by a DNSBackend to indicate a failure
3f81d239 430class DBException : public PDNSException
cc3afe25
BH
431{
432public:
dd079764 433 DBException(const string &reason_) : PDNSException(reason_){}
cc3afe25
BH
434};
435
ceea1ba6 436/** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
437void fillSOAData(const string &content, SOAData &data);
90ba52e0 438// same but more karmic
439void fillSOAData(const DNSZoneRecord& in, SOAData& data);
440// the reverse
441std::shared_ptr<DNSRecordContent> makeSOAContent(const SOAData& sd);