]> git.ipfire.org Git - thirdparty/pdns.git/blob - modules/bindbackend/bindbackend2.hh
Standardize license text in all PDNS files
[thirdparty/pdns.git] / modules / bindbackend / bindbackend2.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
23 #ifndef PDNS_BINDBACKEND_HH
24 #define PDNS_BINDBACKEND_HH
25
26 #include <string>
27 #include <map>
28 #include <set>
29 #include <pthread.h>
30 #include <time.h>
31 #include <fstream>
32 #include <boost/utility.hpp>
33
34 #include <boost/tuple/tuple.hpp>
35 #include <boost/tuple/tuple_comparison.hpp>
36 #include <boost/multi_index_container.hpp>
37 #include <boost/multi_index/ordered_index.hpp>
38 #include <boost/multi_index/identity.hpp>
39 #include <boost/multi_index/member.hpp>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include "pdns/lock.hh"
44 #include "pdns/misc.hh"
45 #include "pdns/dnsbackend.hh"
46 #include "pdns/namespaces.hh"
47 #include "pdns/backends/gsql/ssql.hh"
48
49 using namespace ::boost::multi_index;
50
51 /**
52 This struct is used within the Bind2Backend to store DNS information. It is
53 almost identical to a DNSResourceRecord, but then a bit smaller and with
54 different sorting rules, which make sure that the SOA record comes up front.
55 */
56
57 struct Bind2DNSRecord
58 {
59 DNSName qname;
60 string content;
61 string nsec3hash;
62 uint32_t ttl;
63 uint16_t qtype;
64 mutable bool auth;
65 bool operator<(const Bind2DNSRecord& rhs) const
66 {
67 if(qname.canonCompare(rhs.qname))
68 return true;
69 if(rhs.qname.canonCompare(qname))
70 return false;
71 if(qtype==QType::SOA && rhs.qtype!=QType::SOA)
72 return true;
73 return tie(qtype,content, ttl) < tie(rhs.qtype, rhs.content, rhs.ttl);
74 }
75 };
76
77 struct Bind2DNSCompare : std::less<Bind2DNSRecord>
78 {
79 using std::less<Bind2DNSRecord>::operator();
80 // use operator<
81 bool operator() (const DNSName& a, const Bind2DNSRecord& b) const
82 {return a.canonCompare(b.qname);}
83 bool operator() (const Bind2DNSRecord& a, const DNSName& b) const
84 {return a.qname.canonCompare(b);}
85 bool operator() (const Bind2DNSRecord& a, const Bind2DNSRecord& b) const
86 {return a.qname.canonCompare(b.qname);}
87 };
88
89 struct HashedTag{};
90
91 typedef multi_index_container<
92 Bind2DNSRecord,
93 indexed_by <
94 ordered_non_unique<identity<Bind2DNSRecord>, Bind2DNSCompare >,
95 ordered_non_unique<tag<HashedTag>, member<Bind2DNSRecord, std::string, &Bind2DNSRecord::nsec3hash> >
96 >
97 > recordstorage_t;
98
99 template <typename T>
100 class LookButDontTouch // : public boost::noncopyable
101 {
102 public:
103 LookButDontTouch()
104 {
105 pthread_mutex_init(&d_lock, 0);
106 pthread_mutex_init(&d_swaplock, 0);
107 }
108 LookButDontTouch(shared_ptr<T> records) : d_records(records)
109 {
110 pthread_mutex_init(&d_lock, 0);
111 pthread_mutex_init(&d_swaplock, 0);
112 }
113
114 shared_ptr<const T> get()
115 {
116 shared_ptr<const T> ret;
117 {
118 Lock l(&d_lock);
119 ret = d_records;
120 }
121 return ret;
122 }
123
124 shared_ptr<T> getWRITABLE()
125 {
126 shared_ptr<T> ret;
127 {
128 Lock l(&d_lock);
129 ret = d_records;
130 }
131 return ret;
132 }
133
134
135 void swap(shared_ptr<T> records)
136 {
137 Lock l(&d_lock);
138 Lock l2(&d_swaplock);
139 d_records.swap(records);
140 }
141 pthread_mutex_t d_lock;
142 pthread_mutex_t d_swaplock;
143 private:
144 shared_ptr<T> d_records;
145 };
146
147
148 /** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */
149 class BB2DomainInfo
150 {
151 public:
152 BB2DomainInfo();
153 void setCtime();
154 bool current();
155 //! configure how often this domain should be checked for changes (on disk)
156 void setCheckInterval(time_t seconds);
157
158 DNSName d_name; //!< actual name of the domain
159 string d_filename; //!< full absolute filename of the zone on disk
160 string d_status; //!< message describing status of a domain, for human consumption
161 vector<string> d_masters; //!< IP address of the master of this domain
162 set<string> d_also_notify; //!< IP list of hosts to also notify
163 LookButDontTouch<recordstorage_t> d_records; //!< the actual records belonging to this domain
164 time_t d_ctime; //!< last known ctime of the file on disk
165 time_t d_lastcheck; //!< last time domain was checked for freshness
166 uint32_t d_lastnotified; //!< Last serial number we notified our slaves of
167 unsigned int d_id; //!< internal id of the domain
168 mutable bool d_checknow; //!< if this domain has been flagged for a check
169 bool d_loaded; //!< if a domain is loaded
170 bool d_wasRejectedLastReload{false}; //!< if the domain was rejected during Bind2Backend::queueReloadAndStore
171
172 private:
173 time_t getCtime();
174 time_t d_checkinterval;
175 };
176
177 class SSQLite3;
178 class NSEC3PARAMRecordContent;
179
180 struct NameTag
181 {};
182
183 class Bind2Backend : public DNSBackend
184 {
185 public:
186 Bind2Backend(const string &suffix="", bool loadZones=true);
187 ~Bind2Backend();
188 void getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains);
189 void getUpdatedMasters(vector<DomainInfo> *changedDomains);
190 bool getDomainInfo(const DNSName &domain, DomainInfo &di);
191 time_t getCtime(const string &fname);
192 // DNSSEC
193 virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const string& qname, DNSName& unhashed, string& before, string& after);
194 void lookup(const QType &, const DNSName &qdomain, DNSPacket *p=0, int zoneId=-1);
195 bool list(const DNSName &target, int id, bool include_disabled=false);
196 bool get(DNSResourceRecord &);
197 void getAllDomains(vector<DomainInfo> *domains, bool include_disabled=false);
198
199 static DNSBackend *maker();
200 static pthread_mutex_t s_startup_lock;
201
202 void setFresh(uint32_t domain_id);
203 void setNotified(uint32_t id, uint32_t serial);
204 bool startTransaction(const DNSName &qname, int id);
205 bool feedRecord(const DNSResourceRecord &rr, string *ordername=0);
206 bool commitTransaction();
207 bool abortTransaction();
208 void alsoNotifies(const DNSName &domain, set<string> *ips);
209 bool searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result);
210
211 // the DNSSEC related (getDomainMetadata has broader uses too)
212 virtual bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta);
213 virtual bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta);
214 virtual bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta);
215 virtual bool getDomainKeys(const DNSName& name, unsigned int kind, std::vector<KeyData>& keys);
216 virtual bool removeDomainKey(const DNSName& name, unsigned int id);
217 virtual int addDomainKey(const DNSName& name, const KeyData& key);
218 virtual bool activateDomainKey(const DNSName& name, unsigned int id);
219 virtual bool deactivateDomainKey(const DNSName& name, unsigned int id);
220 virtual bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content);
221 virtual bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content);
222 virtual bool deleteTSIGKey(const DNSName& name);
223 virtual bool getTSIGKeys(std::vector< struct TSIGKey > &keys);
224 virtual bool doesDNSSEC();
225 // end of DNSSEC
226
227 typedef multi_index_container < BB2DomainInfo ,
228 indexed_by < ordered_unique<member<BB2DomainInfo, unsigned int, &BB2DomainInfo::d_id> >,
229 ordered_unique<tag<NameTag>, member<BB2DomainInfo, DNSName, &BB2DomainInfo::d_name> >
230 > > state_t;
231 static state_t s_state;
232 static pthread_rwlock_t s_state_lock;
233
234 void parseZoneFile(BB2DomainInfo *bbd);
235 void insertRecord(BB2DomainInfo& bbd, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed=string(), bool *auth=0);
236 void rediscover(string *status=0);
237
238 bool isMaster(const DNSName &name, const string &ip);
239
240 // for supermaster support
241 bool superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db);
242 static pthread_mutex_t s_supermaster_config_lock;
243 bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account);
244
245 private:
246 void setupDNSSEC();
247 void setupStatements();
248 void freeStatements();
249 void release(SSqlStatement**);
250 static bool safeGetBBDomainInfo(int id, BB2DomainInfo* bbd);
251 static void safePutBBDomainInfo(const BB2DomainInfo& bbd);
252 static bool safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd);
253 static bool safeRemoveBBDomainInfo(const DNSName& name);
254 bool GetBBDomainInfo(int id, BB2DomainInfo** bbd);
255 shared_ptr<SSQLite3> d_dnssecdb;
256 bool getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p);
257 class handle
258 {
259 public:
260 bool get(DNSResourceRecord &);
261 void reset();
262
263 handle();
264
265 shared_ptr<const recordstorage_t > d_records;
266 recordstorage_t::const_iterator d_iter, d_end_iter;
267 recordstorage_t::const_iterator d_qname_iter;
268 recordstorage_t::const_iterator d_qname_end;
269 DNSName qname;
270 DNSName domain;
271
272 int id;
273 QType qtype;
274 bool d_list;
275 bool mustlog;
276
277 private:
278 bool get_normal(DNSResourceRecord &);
279 bool get_list(DNSResourceRecord &);
280
281 void operator=(const handle& ); // don't go copying this
282 handle(const handle &);
283 };
284
285 SSqlStatement* d_getAllDomainMetadataQuery_stmt;
286 SSqlStatement* d_getDomainMetadataQuery_stmt;
287 SSqlStatement* d_deleteDomainMetadataQuery_stmt;
288 SSqlStatement* d_insertDomainMetadataQuery_stmt;
289 SSqlStatement* d_getDomainKeysQuery_stmt;
290 SSqlStatement* d_deleteDomainKeyQuery_stmt;
291 SSqlStatement* d_insertDomainKeyQuery_stmt;
292 SSqlStatement* d_activateDomainKeyQuery_stmt;
293 SSqlStatement* d_deactivateDomainKeyQuery_stmt;
294 SSqlStatement* d_getTSIGKeyQuery_stmt;
295 SSqlStatement* d_setTSIGKeyQuery_stmt;
296 SSqlStatement* d_deleteTSIGKeyQuery_stmt;
297 SSqlStatement* d_getTSIGKeysQuery_stmt;
298
299 string d_transaction_tmpname;
300 string d_logprefix;
301 set<string> alsoNotify; //!< this is used to store the also-notify list of interested peers.
302 ofstream *d_of;
303 handle d_handle;
304 static string s_binddirectory; //!< this is used to store the 'directory' setting of the bind configuration
305 static int s_first; //!< this is raised on construction to prevent multiple instances of us being generated
306 int d_transaction_id;
307 static bool s_ignore_broken_records;
308 bool d_hybrid;
309
310 BB2DomainInfo createDomainEntry(const DNSName& domain, const string &filename); //!< does not insert in s_state
311
312 void queueReloadAndStore(unsigned int id);
313 bool findBeforeAndAfterUnhashed(BB2DomainInfo& bbd, const DNSName& qname, DNSName& unhashed, string& before, string& after);
314 void reload();
315 static string DLDomStatusHandler(const vector<string>&parts, Utility::pid_t ppid);
316 static string DLListRejectsHandler(const vector<string>&parts, Utility::pid_t ppid);
317 static string DLReloadNowHandler(const vector<string>&parts, Utility::pid_t ppid);
318 static string DLAddDomainHandler(const vector<string>&parts, Utility::pid_t ppid);
319 static void fixupOrderAndAuth(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr);
320 void doEmptyNonTerminals(BB2DomainInfo& bbd, bool nsec3zone, NSEC3PARAMRecordContent ns3pr);
321 void loadConfig(string *status=0);
322 static void nukeZoneRecords(BB2DomainInfo *bbd);
323
324 };
325
326 #endif /* PDNS_BINDBACKEND_HH */