]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdistdist/dnsdist-kvs.hh
dnsdist: Wrap pthread_ objects
[thirdparty/pdns.git] / pdns / dnsdistdist / dnsdist-kvs.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
24 #include "dnsdist.hh"
25
26 class KeyValueLookupKey
27 {
28 public:
29 virtual ~KeyValueLookupKey()
30 {
31 }
32 virtual std::vector<std::string> getKeys(const DNSQuestion&) = 0;
33 virtual std::string toString() const = 0;
34 };
35
36 class KeyValueLookupKeySourceIP: public KeyValueLookupKey
37 {
38 public:
39 std::vector<std::string> getKeys(const ComboAddress& addr);
40
41 std::vector<std::string> getKeys(const DNSQuestion& dq) override
42 {
43 return getKeys(*dq.remote);
44 }
45
46 std::string toString() const override
47 {
48 return "source IP";
49 }
50 };
51
52 class KeyValueLookupKeyQName: public KeyValueLookupKey
53 {
54 public:
55
56 KeyValueLookupKeyQName(bool wireFormat): d_wireFormat(wireFormat)
57 {
58 }
59
60 std::vector<std::string> getKeys(const DNSName& qname)
61 {
62 if (d_wireFormat) {
63 return {qname.toDNSStringLC()};
64 }
65 return {qname.makeLowerCase().toStringRootDot()};
66 }
67
68 std::vector<std::string> getKeys(const DNSQuestion& dq) override
69 {
70 return getKeys(*dq.qname);
71 }
72
73 std::string toString() const override
74 {
75 if (d_wireFormat) {
76 return "qname in wire format";
77 }
78 return "qname";
79 }
80
81 private:
82 bool d_wireFormat;
83 };
84
85 class KeyValueLookupKeySuffix: public KeyValueLookupKey
86 {
87 public:
88 KeyValueLookupKeySuffix(size_t minLabels, bool wireFormat): d_minLabels(minLabels), d_wireFormat(wireFormat)
89 {
90 }
91
92 std::vector<std::string> getKeys(const DNSName& qname);
93
94 std::vector<std::string> getKeys(const DNSQuestion& dq) override
95 {
96 return getKeys(*dq.qname);
97 }
98
99 std::string toString() const override
100 {
101 if (d_minLabels > 0) {
102 return "suffix " + std::string(d_wireFormat ? "in wire format " : "") + "with at least " + std::to_string(d_minLabels) + " label(s)";
103 }
104 return "suffix" + std::string(d_wireFormat ? " in wire format" : "");
105 }
106
107 private:
108 size_t d_minLabels;
109 bool d_wireFormat;
110 };
111
112 class KeyValueLookupKeyTag: public KeyValueLookupKey
113 {
114 public:
115 KeyValueLookupKeyTag(const std::string& tag): d_tag(tag)
116 {
117 }
118
119 std::vector<std::string> getKeys(const DNSQuestion& dq) override
120 {
121 if (dq.qTag) {
122 const auto& it = dq.qTag->find(d_tag);
123 if (it != dq.qTag->end()) {
124 return { it->second };
125 }
126 }
127 return {};
128 }
129
130 std::string toString() const override
131 {
132 return "value of the tag named '" + d_tag + "'";
133 }
134
135 private:
136 std::string d_tag;
137 };
138
139 class KeyValueStore
140 {
141 public:
142 virtual ~KeyValueStore()
143 {
144 }
145
146 virtual bool keyExists(const std::string& key) = 0;
147 virtual bool getValue(const std::string& key, std::string& value) = 0;
148 virtual bool reload()
149 {
150 return false;
151 }
152 };
153
154 #ifdef HAVE_LMDB
155
156 #include "ext/lmdb-safe/lmdb-safe.hh"
157
158 class LMDBKVStore: public KeyValueStore
159 {
160 public:
161 LMDBKVStore(const std::string& fname, const std::string& dbName): d_env(fname.c_str(), MDB_NOSUBDIR, 0600), d_fname(fname), d_dbName(dbName)
162 {
163 }
164
165 bool keyExists(const std::string& key) override;
166 bool getValue(const std::string& key, std::string& value) override;
167
168 private:
169 MDBEnv d_env;
170 std::string d_fname;
171 std::string d_dbName;
172 };
173
174 #endif /* HAVE_LMDB */
175
176 #ifdef HAVE_CDB
177
178 #include "cdb.hh"
179
180 class CDBKVStore: public KeyValueStore
181 {
182 public:
183 CDBKVStore(const std::string& fname, time_t refreshDelay);
184 ~CDBKVStore();
185
186 bool keyExists(const std::string& key) override;
187 bool getValue(const std::string& key, std::string& value) override;
188 bool reload() override;
189
190 private:
191 void refreshDBIfNeeded(time_t now);
192 bool reload(const struct stat& st);
193
194 std::unique_ptr<CDB> d_cdb{nullptr};
195 std::string d_fname;
196 ReadWriteLock d_lock;
197 time_t d_mtime{0};
198 time_t d_nextCheck{0};
199 time_t d_refreshDelay{0};
200 std::atomic_flag d_refreshing;
201 };
202
203 #endif /* HAVE_LMDB */