]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdistdist/dnsdist-kvs.hh
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[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 KeyValueLookupKeySourceIP(uint8_t v4Mask, uint8_t v6Mask, bool includePort): d_v4Mask(v4Mask), d_v6Mask(v6Mask), d_includePort(includePort)
40 {
41 }
42
43 std::vector<std::string> getKeys(const ComboAddress& addr);
44
45 std::vector<std::string> getKeys(const DNSQuestion& dq) override
46 {
47 return getKeys(dq.ids.origRemote);
48 }
49
50 std::string toString() const override
51 {
52 return "source IP (masked to " + std::to_string(d_v4Mask) + " (v4) / " + std::to_string(d_v6Mask) + " (v6) bits)" + (d_includePort ? " including the port" : "");
53 }
54 private:
55 uint8_t d_v4Mask;
56 uint8_t d_v6Mask;
57 bool d_includePort;
58 };
59
60 class KeyValueLookupKeyQName: public KeyValueLookupKey
61 {
62 public:
63
64 KeyValueLookupKeyQName(bool wireFormat): d_wireFormat(wireFormat)
65 {
66 }
67
68 std::vector<std::string> getKeys(const DNSName& qname)
69 {
70 if (d_wireFormat) {
71 return {qname.toDNSStringLC()};
72 }
73 return {qname.makeLowerCase().toStringRootDot()};
74 }
75
76 std::vector<std::string> getKeys(const DNSQuestion& dq) override
77 {
78 return getKeys(dq.ids.qname);
79 }
80
81 std::string toString() const override
82 {
83 if (d_wireFormat) {
84 return "qname in wire format";
85 }
86 return "qname";
87 }
88
89 private:
90 bool d_wireFormat;
91 };
92
93 class KeyValueLookupKeySuffix: public KeyValueLookupKey
94 {
95 public:
96 KeyValueLookupKeySuffix(size_t minLabels, bool wireFormat): d_minLabels(minLabels), d_wireFormat(wireFormat)
97 {
98 }
99
100 std::vector<std::string> getKeys(const DNSName& qname);
101
102 std::vector<std::string> getKeys(const DNSQuestion& dq) override
103 {
104 return getKeys(dq.ids.qname);
105 }
106
107 std::string toString() const override
108 {
109 if (d_minLabels > 0) {
110 return "suffix " + std::string(d_wireFormat ? "in wire format " : "") + "with at least " + std::to_string(d_minLabels) + " label(s)";
111 }
112 return "suffix" + std::string(d_wireFormat ? " in wire format" : "");
113 }
114
115 private:
116 size_t d_minLabels;
117 bool d_wireFormat;
118 };
119
120 class KeyValueLookupKeyTag: public KeyValueLookupKey
121 {
122 public:
123 KeyValueLookupKeyTag(const std::string& tag): d_tag(tag)
124 {
125 }
126
127 std::vector<std::string> getKeys(const DNSQuestion& dq) override
128 {
129 if (dq.ids.qTag) {
130 const auto& it = dq.ids.qTag->find(d_tag);
131 if (it != dq.ids.qTag->end()) {
132 return { it->second };
133 }
134 }
135 return {};
136 }
137
138 std::string toString() const override
139 {
140 return "value of the tag named '" + d_tag + "'";
141 }
142
143 private:
144 std::string d_tag;
145 };
146
147 class KeyValueStore
148 {
149 public:
150 virtual ~KeyValueStore()
151 {
152 }
153
154 virtual bool keyExists(const std::string& key) = 0;
155 virtual bool getValue(const std::string& key, std::string& value) = 0;
156 // do a range-based lookup (mostly useful for IP addresses), assuming that:
157 // there is a key for the last element of the range (2001:0db8:ffff:ffff:ffff:ffff:ffff:ffff, in network byte order, for 2001:db8::/32)
158 // which contains the first element of the range (2001:0db8:0000:0000:0000:0000:0000:0000, in network bytes order) followed by any data in the value
159 // AND there is no overlapping ranges in the database !!
160 // This requires that the underlying store supports ordered keys, which is true for LMDB but not for CDB, for example.
161 virtual bool getRangeValue(const std::string& key, std::string& value)
162 {
163 throw std::runtime_error("range-based lookups are not implemented for this Key-Value Store");
164 }
165 virtual bool reload()
166 {
167 return false;
168 }
169 };
170
171 #ifdef HAVE_LMDB
172
173 #include "ext/lmdb-safe/lmdb-safe.hh"
174
175 class LMDBKVStore: public KeyValueStore
176 {
177 public:
178 LMDBKVStore(const std::string& fname, const std::string& dbName, bool noLock=false): d_env(fname.c_str(), noLock ? MDB_NOSUBDIR|MDB_RDONLY|MDB_NOLOCK : MDB_NOSUBDIR|MDB_RDONLY, 0600, 0), d_dbi(d_env.openDB(dbName, 0)), d_fname(fname), d_dbName(dbName)
179 {
180 }
181
182 bool keyExists(const std::string& key) override;
183 bool getValue(const std::string& key, std::string& value) override;
184 bool getRangeValue(const std::string& key, std::string& value) override;
185
186 private:
187 MDBEnv d_env;
188 MDBDbi d_dbi;
189 std::string d_fname;
190 std::string d_dbName;
191 };
192
193 #endif /* HAVE_LMDB */
194
195 #ifdef HAVE_CDB
196
197 #include "cdb.hh"
198
199 class CDBKVStore: public KeyValueStore
200 {
201 public:
202 CDBKVStore(const std::string& fname, time_t refreshDelay);
203 ~CDBKVStore();
204
205 bool keyExists(const std::string& key) override;
206 bool getValue(const std::string& key, std::string& value) override;
207 bool reload() override;
208
209 private:
210 void refreshDBIfNeeded(time_t now);
211 bool reload(const struct stat& st);
212
213 SharedLockGuarded<std::unique_ptr<CDB>> d_cdb{nullptr};
214 std::string d_fname;
215 time_t d_mtime{0};
216 time_t d_nextCheck{0};
217 time_t d_refreshDelay{0};
218 std::atomic_flag d_refreshing;
219 };
220
221 #endif /* HAVE_LMDB */