]> git.ipfire.org Git - thirdparty/pdns.git/blob - modules/lmdbbackend/lmdbbackend.hh
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / modules / lmdbbackend / lmdbbackend.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 #pragma once
24 #include "pdns/dnsbackend.hh"
25 #include "ext/lmdb-safe/lmdb-typed.hh"
26
27 template <class T, typename std::enable_if<std::is_same<T, DNSName>::value, T>::type* = nullptr>
28 std::string keyConv(const T& t)
29 {
30 /* www.ds9a.nl -> nl0ds9a0www0
31 root -> 0 <- we need this to keep lmdb happy
32 nl -> nl0
33
34 */
35 if (t.empty()) {
36 throw std::out_of_range(std::string(__PRETTY_FUNCTION__) + " Attempt to serialize an unset dnsname");
37 }
38
39 if (t.isRoot()) {
40 return std::string(1, (char)0);
41 }
42
43 std::string in = t.labelReverse().toDNSStringLC(); // www.ds9a.nl is now 2nl4ds9a3www0
44 std::string ret;
45 ret.reserve(in.size());
46
47 for (auto iter = in.begin(); iter != in.end(); ++iter) {
48 uint8_t len = *iter;
49 if (iter != in.begin())
50 ret.append(1, (char)0);
51 if (!len)
52 break;
53
54 ret.append(&*(iter + 1), len);
55 iter += len;
56 }
57 return ret;
58 }
59
60 class LMDBBackend : public DNSBackend
61 {
62 public:
63 explicit LMDBBackend(const string& suffix = "");
64
65 bool list(const DNSName& target, int id, bool include_disabled) override;
66
67 bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getserial = true) override;
68 bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& masters, const string& account) override;
69
70 bool startTransaction(const DNSName& domain, int domain_id = -1) override;
71 bool commitTransaction() override;
72 bool abortTransaction() override;
73 bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override;
74 bool feedEnts(int domain_id, map<DNSName, bool>& nonterm) override;
75 bool feedEnts3(int domain_id, const DNSName& domain, map<DNSName, bool>& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override;
76 bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset) override;
77
78 void getAllDomains(vector<DomainInfo>* domains, bool doSerial, bool include_disabled) override;
79 void lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override;
80 bool get(DNSResourceRecord& rr) override;
81 bool get(DNSZoneRecord& dzr) override;
82
83 void getUnfreshSlaveInfos(vector<DomainInfo>* domains) override;
84
85 bool setMasters(const DNSName& domain, const vector<ComboAddress>& masters) override;
86 bool setKind(const DNSName& domain, const DomainInfo::DomainKind kind) override;
87 bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override;
88 bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override
89 {
90 // std::cout<<"Request for metadata items for zone "<<name<<", kind "<<kind<<endl;
91 meta.clear();
92 std::map<std::string, std::vector<std::string>> metas;
93 if (getAllDomainMetadata(name, metas)) {
94 for (const auto& m : metas) {
95 if (m.first == kind) {
96 meta = m.second;
97 return true;
98 }
99 }
100 return true;
101 }
102 return false;
103 }
104
105 bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override;
106 void setStale(uint32_t domain_id) override;
107 void setFresh(uint32_t domain_id) override;
108 void setNotified(uint32_t id, uint32_t serial) override;
109 bool setAccount(const DNSName& domain, const std::string& account) override;
110 bool deleteDomain(const DNSName& domain) override;
111
112 bool getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) override;
113 bool removeDomainKey(const DNSName& name, unsigned int id) override;
114 bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override;
115 bool activateDomainKey(const DNSName& name, unsigned int id) override;
116 bool deactivateDomainKey(const DNSName& name, unsigned int id) override;
117 bool publishDomainKey(const DNSName& name, unsigned int id) override;
118 bool unpublishDomainKey(const DNSName& name, unsigned int id) override;
119
120 // TSIG
121 bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override;
122 bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override;
123 bool deleteTSIGKey(const DNSName& name) override;
124 bool getTSIGKeys(std::vector<struct TSIGKey>& keys) override;
125
126 // DNSSEC
127
128 bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
129
130 virtual bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) override;
131
132 bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype = QType::ANY) override;
133
134 bool updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove) override;
135
136 bool doesDNSSEC() override
137 {
138 return true;
139 }
140
141 private:
142 struct compoundOrdername
143 {
144 std::string operator()(uint32_t id, const DNSName& t, uint16_t qtype)
145 {
146 std::string ret = operator()(id, t);
147 uint16_t qt = htons(qtype);
148 ret.append((char*)&qt, 2);
149 return ret;
150 }
151 std::string operator()(uint32_t id, const DNSName& t)
152 {
153 std::string ret = operator()(id);
154 ret += keyConv(t);
155 ret.append(1, (char)0); // this means '00' really ends the zone
156 return ret;
157 }
158 std::string operator()(uint32_t id)
159 {
160 std::string ret;
161 id = htonl(id);
162 ret.assign((char*)&id, 4);
163 return ret;
164 }
165
166 std::string operator()(const DNSResourceRecord& rr)
167 {
168 return operator()(rr.domain_id, rr.qname, rr.qtype.getCode());
169 }
170
171 static uint32_t getDomainID(const string_view& key)
172 {
173 uint32_t ret;
174 memcpy(&ret, &key[0], sizeof(ret));
175 return ntohl(ret);
176 }
177
178 static DNSName getQName(const string_view& key)
179 {
180 /* www.ds9a.nl -> nl0ds9a0www0
181 root -> 0 <- we need this to keep lmdb happy
182 nl -> nl0 */
183 DNSName ret;
184 auto iter = key.cbegin() + 4;
185 auto end = key.cend() - 2;
186 while (iter < end) {
187 auto startpos = iter;
188 while (iter != end && *iter)
189 ++iter;
190 if (iter == startpos)
191 break;
192 string part(&*startpos, iter - startpos);
193 ret.prependRawLabel(part);
194 // cout << "Prepending part: "<<part<<endl;
195 if (iter != end)
196 ++iter;
197 }
198 if (ret.empty())
199 return g_rootdnsname;
200 return ret;
201 }
202
203 static QType getQType(const string_view& key)
204 {
205 uint16_t ret;
206 memcpy(&ret, &key[key.size() - 2], sizeof(ret));
207 return QType(ntohs(ret));
208 }
209 };
210
211 public:
212 struct DomainMeta
213 {
214 DNSName domain;
215 string key;
216 string value;
217 };
218 struct KeyDataDB
219 {
220 DNSName domain;
221 std::string content;
222 unsigned int flags{0};
223 bool active{true};
224 bool published{true};
225 };
226 class LMDBResourceRecord : public DNSResourceRecord
227 {
228 public:
229 LMDBResourceRecord() {}
230 LMDBResourceRecord(const DNSResourceRecord& rr) :
231 DNSResourceRecord(rr), ordername(false) {}
232
233 bool ordername{false};
234 };
235
236 private:
237 typedef TypedDBI<DomainInfo,
238 index_on<DomainInfo, DNSName, &DomainInfo::zone>>
239 tdomains_t;
240
241 typedef TypedDBI<DomainMeta,
242 index_on<DomainMeta, DNSName, &DomainMeta::domain>>
243 tmeta_t;
244
245 typedef TypedDBI<KeyDataDB,
246 index_on<KeyDataDB, DNSName, &KeyDataDB::domain>>
247 tkdb_t;
248
249 typedef TypedDBI<TSIGKey,
250 index_on<TSIGKey, DNSName, &TSIGKey::name>>
251 ttsig_t;
252
253 int d_asyncFlag;
254
255 struct RecordsDB
256 {
257 shared_ptr<MDBEnv> env;
258 MDBDbi dbi;
259 };
260
261 struct RecordsROTransaction
262 {
263 RecordsROTransaction(MDBROTransaction&& intxn) :
264 txn(std::move(intxn))
265 {}
266 shared_ptr<RecordsDB> db;
267 MDBROTransaction txn;
268 };
269 struct RecordsRWTransaction
270 {
271 RecordsRWTransaction(MDBRWTransaction&& intxn) :
272 txn(std::move(intxn))
273 {}
274 shared_ptr<RecordsDB> db;
275 MDBRWTransaction txn;
276 };
277
278 vector<RecordsDB> d_trecords;
279 ;
280
281 std::shared_ptr<MDBROCursor> d_getcursor;
282
283 shared_ptr<tdomains_t> d_tdomains;
284 shared_ptr<tmeta_t> d_tmeta;
285 shared_ptr<tkdb_t> d_tkdb;
286 shared_ptr<ttsig_t> d_ttsig;
287
288 shared_ptr<RecordsROTransaction> d_rotxn; // for lookup and list
289 shared_ptr<RecordsRWTransaction> d_rwtxn; // for feedrecord within begin/aborttransaction
290 std::shared_ptr<RecordsRWTransaction> getRecordsRWTransaction(uint32_t id);
291 std::shared_ptr<RecordsROTransaction> getRecordsROTransaction(uint32_t id, std::shared_ptr<LMDBBackend::RecordsRWTransaction> rwtxn = nullptr);
292 int genChangeDomain(const DNSName& domain, std::function<void(DomainInfo&)> func);
293 int genChangeDomain(uint32_t id, std::function<void(DomainInfo&)> func);
294 void deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype = QType::ANY);
295
296 bool getSerial(DomainInfo& di);
297
298 bool upgradeToSchemav3();
299
300 bool get_list(DNSZoneRecord& rr);
301 bool get_lookup(DNSZoneRecord& rr);
302 std::string d_matchkey;
303 DNSName d_lookupdomain;
304
305 vector<LMDBResourceRecord> d_currentrrset;
306 size_t d_currentrrsetpos;
307 MDBOutVal d_currentKey;
308 MDBOutVal d_currentVal;
309 bool d_includedisabled;
310
311 DNSName d_transactiondomain;
312 uint32_t d_transactiondomainid;
313 bool d_dolog;
314 bool d_random_ids;
315 DTime d_dtime; // used only for logging
316 };