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