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