]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsbackend.hh
3a71ef7ba10473581a393818a8b1091c2ba679d3
[thirdparty/pdns.git] / pdns / dnsbackend.hh
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2010 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
8
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 #ifndef DNSBACKEND_HH
20 #define DNSBACKEND_HH
21
22 class DNSPacket;
23
24 #include "utility.hh"
25 #include <string>
26 #include <vector>
27 #include <map>
28 #include <sys/types.h>
29 #include "pdnsexception.hh"
30 #include <set>
31 #include <iostream>
32 #include <sys/socket.h>
33 #include <dirent.h>
34 #include "misc.hh"
35 #include "qtype.hh"
36 #include "dns.hh"
37 #include <vector>
38 #include "namespaces.hh"
39
40 class DNSBackend;
41 struct DomainInfo
42 {
43 DomainInfo() : backend(0) {}
44 uint32_t id;
45 string zone;
46 vector<string> masters;
47 uint32_t notified_serial;
48 uint32_t serial;
49 time_t last_check;
50 enum DomainKind { Master, Slave, Native } kind;
51 DNSBackend *backend;
52
53 bool operator<(const DomainInfo& rhs) const
54 {
55 return zone < rhs.zone;
56 }
57
58 const char *getKindString() const
59 {
60 return DomainInfo::getKindString(kind);
61 }
62
63 static const char *getKindString(enum DomainKind kind)
64 {
65 const char *kinds[]={"Master", "Slave", "Native"};
66 return kinds[kind];
67 }
68
69 static DomainKind stringToKind(const string& kind)
70 {
71 if(pdns_iequals(kind,"SLAVE"))
72 return DomainInfo::Slave;
73 else if(pdns_iequals(kind,"MASTER"))
74 return DomainInfo::Master;
75 else
76 return DomainInfo::Native;
77 }
78
79 };
80
81 struct TSIGKey {
82 std::string name;
83 std::string algorithm;
84 std::string key;
85 };
86
87 class DNSPacket;
88
89
90 //! This virtual base class defines the interface for backends for the ahudns.
91 /** To create a backend, inherit from this class and implement functions for all virtual methods.
92 Methods should not throw an exception if they are sure they did not find the requested data. However,
93 if an error occurred which prevented them temporarily from performing a lockup, they should throw a DBException,
94 which will cause the nameserver to send out a ServFail or take other evasive action. Probably only locking
95 issues should lead to DBExceptions.
96
97 More serious errors, which may indicate that the database connection is hosed, or a configuration error occurred, should
98 lead to the throwing of an PDNSException. This exception will fall straight through the UeberBackend and the PacketHandler
99 and be caught by the Distributor, which will delete your DNSBackend instance and spawn a new one.
100 */
101 class DNSBackend
102 {
103 public:
104 //! lookup() initiates a lookup. A lookup without results should not throw!
105 virtual void lookup(const QType &qtype, const string &qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0;
106 virtual bool get(DNSResourceRecord &)=0; //!< retrieves one DNSResource record, returns false if no more were available
107
108
109 //! Initiates a list of the specified domain
110 /** Once initiated, DNSResourceRecord objects can be retrieved using get(). Should return false
111 if the backend does not consider itself responsible for the id passed.
112 \param domain_id ID of which a list is requested
113 */
114 virtual bool list(const string &target, int domain_id)=0;
115
116 virtual ~DNSBackend(){};
117
118 //! fills the soadata struct with the SOA details. Returns false if there is no SOA.
119 virtual bool getSOA(const string &name, SOAData &soadata, DNSPacket *p=0);
120
121 //! Calculates a SOA serial for the zone and stores it in the third argument.
122 virtual bool calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial);
123
124 virtual bool replaceRRSet(uint32_t domain_id, const string& qname, const QType& qt, const vector<DNSResourceRecord>& rrset)
125 {
126 return false;
127 }
128
129 virtual bool listSubZone(const string &zone, int domain_id)
130 {
131 return false;
132 }
133
134 // the DNSSEC related (getDomainMetadata has broader uses too)
135 virtual bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta) { return false; }
136 virtual bool setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta) {return false;}
137
138 virtual void getAllDomains(vector<DomainInfo> *domains) { }
139
140 struct KeyData {
141 unsigned int id;
142 unsigned int flags;
143 bool active;
144 std::string content;
145 };
146
147 virtual bool getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys) { return false;}
148 virtual bool removeDomainKey(const string& name, unsigned int id) { return false; }
149 virtual int addDomainKey(const string& name, const KeyData& key){ return -1; }
150 virtual bool activateDomainKey(const string& name, unsigned int id) { return false; }
151 virtual bool deactivateDomainKey(const string& name, unsigned int id) { return false; }
152
153 virtual bool getTSIGKey(const string& name, string* algorithm, string* content) { return false; }
154 virtual bool setTSIGKey(const string& name, const string& algorithm, const string& content) { return false; }
155 virtual bool deleteTSIGKey(const string& name) { return false; }
156 virtual bool getTSIGKeys(std::vector< struct TSIGKey > &keys) { return false; }
157
158 virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after)
159 {
160 std::cerr<<"Default beforeAndAfterAbsolute called!"<<std::endl;
161 abort();
162 return false;
163 }
164
165 bool getBeforeAndAfterNames(uint32_t id, const std::string& zonename, const std::string& qname, std::string& before, std::string& after);
166
167 virtual bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth)
168 {
169 return false;
170 }
171
172 virtual bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth)
173 {
174 return false;
175 }
176
177 virtual bool updateEmptyNonTerminals(uint32_t domain_id, const std::string& zonename, set<string>& insert, set<string>& erase, bool remove)
178 {
179 return false;
180 }
181
182 virtual bool nullifyDNSSECOrderNameAndUpdateAuth(uint32_t domain_id, const std::string& qname, bool auth)
183 {
184 return false;
185 }
186
187 virtual bool nullifyDNSSECOrderNameAndAuth(uint32_t domain_id, const std::string& qname, const std::string& type)
188 {
189 return false;
190 }
191
192 virtual bool setDNSSECAuthOnDsRecord(uint32_t domain_id, const std::string& qname)
193 {
194 return false;
195 }
196
197 virtual bool doesDNSSEC()
198 {
199 return false;
200 }
201
202 // end DNSSEC
203
204 //! returns true if master ip is master for domain name.
205 virtual bool isMaster(const string &name, const string &ip)
206 {
207 return false;
208 }
209
210 //! starts the transaction for updating domain qname (FIXME: what is id?)
211 virtual bool startTransaction(const string &qname, int id=-1)
212 {
213 return false;
214 }
215
216 //! commits the transaction started by startTransaction
217 virtual bool commitTransaction()
218 {
219 return false;
220 }
221
222 //! aborts the transaction started by strartTransaction, should leave state unaltered
223 virtual bool abortTransaction()
224 {
225 return false;
226 }
227
228 virtual void reload()
229 {
230 }
231
232 virtual void rediscover(string* status=0)
233 {
234 }
235
236 //! feeds a record to a zone, needs a call to startTransaction first
237 virtual bool feedRecord(const DNSResourceRecord &rr, string *ordername=0)
238 {
239 return false; // no problem!
240 }
241 virtual bool feedEnts(int domain_id, set<string> &nonterm)
242 {
243 return false;
244 }
245 virtual bool feedEnts3(int domain_id, const string &domain, set<string> &nonterm, unsigned int times, const string &salt, bool narrow)
246 {
247 return false;
248 }
249
250 //! if this returns true, DomainInfo di contains information about the domain
251 virtual bool getDomainInfo(const string &domain, DomainInfo &di)
252 {
253 return false;
254 }
255 //! slave capable backends should return a list of slaves that should be rechecked for staleness
256 virtual void getUnfreshSlaveInfos(vector<DomainInfo>* domains)
257 {
258 }
259
260 //! get a list of IP addresses that should also be notified for a domain
261 virtual void alsoNotifies(const string &domain, set<string> *ips)
262 {
263 }
264
265 //! get list of domains that have been changed since their last notification to slaves
266 virtual void getUpdatedMasters(vector<DomainInfo>* domains)
267 {
268 }
269
270 //! Called by PowerDNS to inform a backend that a domain has been checked for freshness
271 virtual void setFresh(uint32_t domain_id)
272 {
273
274 }
275 //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to slaves
276 virtual void setNotified(uint32_t id, uint32_t serial)
277 {
278 }
279
280 //! Called when the Master of a domain should be changed
281 virtual bool setMaster(const string &domain, const string &ip)
282 {
283 return false;
284 }
285
286 //! Called when the Kind of a domain should be changed (master -> native and similar)
287 virtual bool setKind(const string &domain, const DomainInfo::DomainKind kind)
288 {
289 return false;
290 }
291
292 //! Can be called to seed the getArg() function with a prefix
293 void setArgPrefix(const string &prefix);
294
295 //! determine if ip is a supermaster or a domain
296 virtual bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
297 {
298 return false;
299 }
300
301 //! called by PowerDNS to create a new domain
302 virtual bool createDomain(const string &domain)
303 {
304 return false;
305 }
306
307 //! called by PowerDNS to create a slave record for a superMaster
308 virtual bool createSlaveDomain(const string &ip, const string &domain, const string &account)
309 {
310 return false;
311 }
312
313 //! called to delete a domain, incl. all metadata, zone contents, etc.
314 virtual bool deleteDomain(const string &domain)
315 {
316 return false;
317 }
318
319 protected:
320 bool mustDo(const string &key);
321 const string &getArg(const string &key);
322 int getArgAsNum(const string &key);
323 string getRemote(DNSPacket *p);
324 bool getRemote(DNSPacket *p, struct sockaddr *in, Utility::socklen_t *len);
325
326 private:
327 string d_prefix;
328 };
329
330 class BackendFactory
331 {
332 public:
333 BackendFactory(const string &name) : d_name(name) {}
334 virtual ~BackendFactory(){}
335 virtual DNSBackend *make(const string &suffix)=0;
336 virtual DNSBackend *makeMetadataOnly(const string &suffix)
337 {
338 return this->make(suffix);
339 }
340 virtual void declareArguments(const string &suffix=""){}
341 const string &getName() const;
342
343 protected:
344 void declare(const string &suffix, const string &param, const string &explanation, const string &value);
345
346 private:
347 const string d_name;
348 };
349
350 class BackendMakerClass
351 {
352 public:
353 void report(BackendFactory *bf);
354 void launch(const string &instr);
355 vector<DNSBackend *>all(bool skipBIND=false);
356 void load(const string &module);
357 int numLauncheable();
358 vector<string> getModules();
359
360 private:
361 void load_all();
362 typedef map<string,BackendFactory *>d_repository_t;
363 d_repository_t d_repository;
364 vector<pair<string,string> >d_instances;
365 };
366
367 extern BackendMakerClass &BackendMakers();
368
369 //! Exception that can be thrown by a DNSBackend to indicate a failure
370 class DBException : public PDNSException
371 {
372 public:
373 DBException(const string &reason) : PDNSException(reason){}
374 };
375
376
377 #endif