2 #include "pdns/dnsbackend.hh"
3 #include "ext/lmdb-safe/lmdb-typed.hh"
5 template<class T, typename std::enable_if<std::is_same<T, DNSName>::value,T>::type* = nullptr>
6 std::string keyConv(const T& t)
8 /* www.ds9a.nl -> nl0ds9a0www0
9 root -> 0 <- we need this to keep lmdb happy
14 return std::string(1, (char)0);
15 std::string in = t.labelReverse().toDNSStringLC(); // www.ds9a.nl is now 2nl4ds9a3www0
17 ret.reserve(in.size());
19 for(auto iter = in.begin(); iter != in.end(); ++iter) {
21 if(iter != in.begin())
22 ret.append(1, (char)0);
26 ret.append(&*(iter+1), len);
33 class LMDBBackend : public DNSBackend
36 explicit LMDBBackend(const string &suffix="");
38 bool list(const DNSName &target, int id, bool include_disabled) override;
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);
43 bool createDomain(const DNSName &domain) override;
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;
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;
58 bool getSOA(const DNSName &domain, SOAData &sd) override;
59 void getUnfreshSlaveInfos(vector<DomainInfo>* domains) override;
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
66 // std::cout<<"Request for metadata items for zone "<<name<<", kind "<<kind<<endl;
68 std::map<std::string, std::vector<std::string> > metas;
69 if(getAllDomainMetadata(name, metas)) {
70 for(const auto& m : metas) {
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;
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;
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;
102 bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
104 virtual bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) override;
106 bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype=QType::ANY) override;
108 bool updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove) override;
110 bool doesDNSSEC() override
116 struct compoundOrdername
118 std::string operator()(uint32_t id, const DNSName& t, uint16_t qtype)
120 std::string ret = operator()(id, t);
121 uint16_t qt = htons(qtype);
122 ret.append((char*)&qt, 2);
125 std::string operator()(uint32_t id, const DNSName& t)
127 std::string ret = operator()(id);
129 ret.append(1, (char)0); // this means '00' really ends the zone
132 std::string operator()(uint32_t id)
136 ret.assign((char*)&id, 4);
140 std::string operator()(const DNSResourceRecord& rr)
142 return operator()(rr.domain_id, rr.qname, rr.qtype.getCode());
145 static uint32_t getDomainID(const string_view& key)
148 memcpy(&ret, &key[0], sizeof(ret));
152 static DNSName getQName(const string_view& key)
154 /* www.ds9a.nl -> nl0ds9a0www0
155 root -> 0 <- we need this to keep lmdb happy
158 auto iter = key.cbegin() + 4;
159 auto end = key.cend() - 2;
161 auto startpos = iter;
162 while(iter != end && *iter)
166 string part(&*startpos, iter-startpos);
167 ret.prependRawLabel(part);
168 // cout << "Prepending part: "<<part<<endl;
173 return g_rootdnsname;
177 static QType getQType(const string_view& key)
180 memcpy(&ret, &key[key.size()-2], sizeof(ret));
181 return QType(ntohs(ret));
202 typedef TypedDBI<DomainInfo,
203 index_on<DomainInfo, DNSName, &DomainInfo::zone>
207 typedef TypedDBI<DomainMeta,
208 index_on<DomainMeta, DNSName, &DomainMeta::domain>
211 typedef TypedDBI<KeyDataDB,
212 index_on<KeyDataDB, DNSName, &KeyDataDB::domain>
215 typedef TypedDBI<TSIGKey,
216 index_on<TSIGKey, DNSName, &TSIGKey::name>
224 shared_ptr<MDBEnv> env;
228 struct RecordsROTransaction
230 RecordsROTransaction(MDBROTransaction&& intxn) : txn(std::move(intxn))
232 shared_ptr<RecordsDB> db;
233 MDBROTransaction txn;
235 struct RecordsRWTransaction
237 RecordsRWTransaction(MDBRWTransaction&& intxn) : txn(std::move(intxn))
239 shared_ptr<RecordsDB> db;
240 MDBRWTransaction txn;
243 vector<RecordsDB> d_trecords;;
245 std::shared_ptr<MDBROCursor> d_getcursor;
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;
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);
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;
269 DNSName d_transactiondomain;
270 uint32_t d_transactiondomainid;
272 DTime d_dtime; // used only for logging