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