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