summaryrefslogtreecommitdiffstats
path: root/dnsdist-kvs.hh
diff options
context:
space:
mode:
Diffstat (limited to 'dnsdist-kvs.hh')
-rw-r--r--dnsdist-kvs.hh221
1 files changed, 221 insertions, 0 deletions
diff --git a/dnsdist-kvs.hh b/dnsdist-kvs.hh
new file mode 100644
index 0000000..14d0bed
--- /dev/null
+++ b/dnsdist-kvs.hh
@@ -0,0 +1,221 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include "dnsdist.hh"
+
+class KeyValueLookupKey
+{
+public:
+ virtual ~KeyValueLookupKey()
+ {
+ }
+ virtual std::vector<std::string> getKeys(const DNSQuestion&) = 0;
+ virtual std::string toString() const = 0;
+};
+
+class KeyValueLookupKeySourceIP: public KeyValueLookupKey
+{
+public:
+ KeyValueLookupKeySourceIP(uint8_t v4Mask, uint8_t v6Mask, bool includePort): d_v4Mask(v4Mask), d_v6Mask(v6Mask), d_includePort(includePort)
+ {
+ }
+
+ std::vector<std::string> getKeys(const ComboAddress& addr);
+
+ std::vector<std::string> getKeys(const DNSQuestion& dq) override
+ {
+ return getKeys(*dq.remote);
+ }
+
+ std::string toString() const override
+ {
+ return "source IP (masked to " + std::to_string(d_v4Mask) + " (v4) / " + std::to_string(d_v6Mask) + " (v6) bits)" + (d_includePort ? " including the port" : "");
+ }
+private:
+ uint8_t d_v4Mask;
+ uint8_t d_v6Mask;
+ bool d_includePort;
+};
+
+class KeyValueLookupKeyQName: public KeyValueLookupKey
+{
+public:
+
+ KeyValueLookupKeyQName(bool wireFormat): d_wireFormat(wireFormat)
+ {
+ }
+
+ std::vector<std::string> getKeys(const DNSName& qname)
+ {
+ if (d_wireFormat) {
+ return {qname.toDNSStringLC()};
+ }
+ return {qname.makeLowerCase().toStringRootDot()};
+ }
+
+ std::vector<std::string> getKeys(const DNSQuestion& dq) override
+ {
+ return getKeys(*dq.qname);
+ }
+
+ std::string toString() const override
+ {
+ if (d_wireFormat) {
+ return "qname in wire format";
+ }
+ return "qname";
+ }
+
+private:
+ bool d_wireFormat;
+};
+
+class KeyValueLookupKeySuffix: public KeyValueLookupKey
+{
+public:
+ KeyValueLookupKeySuffix(size_t minLabels, bool wireFormat): d_minLabels(minLabels), d_wireFormat(wireFormat)
+ {
+ }
+
+ std::vector<std::string> getKeys(const DNSName& qname);
+
+ std::vector<std::string> getKeys(const DNSQuestion& dq) override
+ {
+ return getKeys(*dq.qname);
+ }
+
+ std::string toString() const override
+ {
+ if (d_minLabels > 0) {
+ return "suffix " + std::string(d_wireFormat ? "in wire format " : "") + "with at least " + std::to_string(d_minLabels) + " label(s)";
+ }
+ return "suffix" + std::string(d_wireFormat ? " in wire format" : "");
+ }
+
+private:
+ size_t d_minLabels;
+ bool d_wireFormat;
+};
+
+class KeyValueLookupKeyTag: public KeyValueLookupKey
+{
+public:
+ KeyValueLookupKeyTag(const std::string& tag): d_tag(tag)
+ {
+ }
+
+ std::vector<std::string> getKeys(const DNSQuestion& dq) override
+ {
+ if (dq.qTag) {
+ const auto& it = dq.qTag->find(d_tag);
+ if (it != dq.qTag->end()) {
+ return { it->second };
+ }
+ }
+ return {};
+ }
+
+ std::string toString() const override
+ {
+ return "value of the tag named '" + d_tag + "'";
+ }
+
+private:
+ std::string d_tag;
+};
+
+class KeyValueStore
+{
+public:
+ virtual ~KeyValueStore()
+ {
+ }
+
+ virtual bool keyExists(const std::string& key) = 0;
+ virtual bool getValue(const std::string& key, std::string& value) = 0;
+ // do a range-based lookup (mostly useful for IP addresses), assuming that:
+ // 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)
+ // 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
+ // AND there is no overlapping ranges in the database !!
+ // This requires that the underlying store supports ordered keys, which is true for LMDB but not for CDB, for example.
+ virtual bool getRangeValue(const std::string& key, std::string& value)
+ {
+ throw std::runtime_error("range-based lookups are not implemented for this Key-Value Store");
+ }
+ virtual bool reload()
+ {
+ return false;
+ }
+};
+
+#ifdef HAVE_LMDB
+
+#include "ext/lmdb-safe/lmdb-safe.hh"
+
+class LMDBKVStore: public KeyValueStore
+{
+public:
+ 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), d_dbi(d_env.openDB(dbName, 0)), d_fname(fname), d_dbName(dbName)
+ {
+ }
+
+ bool keyExists(const std::string& key) override;
+ bool getValue(const std::string& key, std::string& value) override;
+ bool getRangeValue(const std::string& key, std::string& value) override;
+
+private:
+ MDBEnv d_env;
+ MDBDbi d_dbi;
+ std::string d_fname;
+ std::string d_dbName;
+};
+
+#endif /* HAVE_LMDB */
+
+#ifdef HAVE_CDB
+
+#include "cdb.hh"
+
+class CDBKVStore: public KeyValueStore
+{
+public:
+ CDBKVStore(const std::string& fname, time_t refreshDelay);
+ ~CDBKVStore();
+
+ bool keyExists(const std::string& key) override;
+ bool getValue(const std::string& key, std::string& value) override;
+ bool reload() override;
+
+private:
+ void refreshDBIfNeeded(time_t now);
+ bool reload(const struct stat& st);
+
+ SharedLockGuarded<std::unique_ptr<CDB>> d_cdb{nullptr};
+ std::string d_fname;
+ time_t d_mtime{0};
+ time_t d_nextCheck{0};
+ time_t d_refreshDelay{0};
+ std::atomic_flag d_refreshing;
+};
+
+#endif /* HAVE_LMDB */