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