From f441962aa3cdd9e1c2d6bab36d4274c6ac22dab7 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 4 Jul 2019 18:12:13 +0200 Subject: [PATCH] dnsdist: Add a KeyValueStoreLookup action based on LMDB --- configure.ac | 13 ++ m4/pdns_check_lmdb.m4 | 13 +- modules/lmdbbackend/Makefile.am | 5 +- modules/lmdbbackend/lmdb-typed.hh | 2 +- pdns/Makefile.am | 8 ++ pdns/dnsdist-lua-actions.cc | 38 +++++- pdns/dnsdist-lua-bindings.cc | 22 ++++ pdns/dnsdist.cc | 3 + pdns/dnsdistdist/Makefile.am | 132 ++++++++++++--------- pdns/dnsdistdist/configure.ac | 7 ++ pdns/dnsdistdist/dnsdist-kvs.cc | 50 ++++++++ pdns/dnsdistdist/dnsdist-kvs.hh | 128 ++++++++++++++++++++ pdns/dnsdistdist/lmdb-safe.cc | 1 + pdns/dnsdistdist/lmdb-safe.hh | 1 + pdns/dnsdistdist/m4/pdns_check_lmdb.m4 | 1 + pdns/dnsdistdist/test-dnsdistkvs_cc.cc | 45 +++++++ {modules/lmdbbackend => pdns}/lmdb-safe.cc | 0 {modules/lmdbbackend => pdns}/lmdb-safe.hh | 0 18 files changed, 401 insertions(+), 68 deletions(-) create mode 100644 pdns/dnsdistdist/dnsdist-kvs.cc create mode 100644 pdns/dnsdistdist/dnsdist-kvs.hh create mode 120000 pdns/dnsdistdist/lmdb-safe.cc create mode 120000 pdns/dnsdistdist/lmdb-safe.hh create mode 120000 pdns/dnsdistdist/m4/pdns_check_lmdb.m4 create mode 100644 pdns/dnsdistdist/test-dnsdistkvs_cc.cc rename {modules/lmdbbackend => pdns}/lmdb-safe.cc (100%) rename {modules/lmdbbackend => pdns}/lmdb-safe.hh (100%) diff --git a/configure.ac b/configure.ac index 22fdd6a32..c2f7c6d7e 100644 --- a/configure.ac +++ b/configure.ac @@ -217,6 +217,7 @@ for a in $modules $dynmodules; do ) ;; lmdb) + needlmdb=yes PDNS_CHECK_LMDB BOOST_SERIALIZATION ;; @@ -239,6 +240,18 @@ AM_CONDITIONAL([LDAP], [test "x$needldap" = "xyes"]) PDNS_CHECK_SQLITE3 AM_CONDITIONAL([SQLITE3], [test "x$needsqlite3" = "xyes"]) +AM_CONDITIONAL([LMDB], [test "x$needlmdb" != "x"]) +AM_CONDITIONAL([HAVE_LMDB], [test "x$LMDB_LIBS" != "x"]) + +AS_IF([test "x$needlmdb" = "xyes"], [ + AS_IF([test "$with_lmdb" = "no"], [ + AC_MSG_ERROR([--with-lmdb is set to 'no', but lmdb support is required]) + ]) + AS_IF([test "x$HAVE_LMDB" != "x1"], [ + AC_MSG_ERROR([lmdb not found via pkg-config, please install lmdb or set --with-lmdb to your lmdb installation directory]) + ]) +]) + for a in $modules; do AC_MSG_CHECKING([whether we can build module "${a}"]) if [[ -d "$srcdir/modules/${a}backend" ]]; then diff --git a/m4/pdns_check_lmdb.m4 b/m4/pdns_check_lmdb.m4 index 611f66823..f1921bde9 100644 --- a/m4/pdns_check_lmdb.m4 +++ b/m4/pdns_check_lmdb.m4 @@ -11,9 +11,11 @@ AC_DEFUN([PDNS_CHECK_LMDB], [ AS_IF([test "$with_lmdb" != "no"], [ AS_IF([test "x$with_lmdb" = "xyes" -o "x$with_lmdb" = "xauto"], [ - PKG_CHECK_MODULES([LMDB], [lmdb], [ : ], [ - AC_MSG_ERROR([lmdb not found via pkg-config, please install lmdb or set --with-lmdb to your lmdb installation directory]) - ]) + PKG_CHECK_MODULES([LMDB], [lmdb], [ + AC_DEFINE([HAVE_LMDB], [1], [Define to 1 if you have LMDB]) + [HAVE_LMDB=1] + ], [ : ] + ) ], [ save_CPPFLAGS=$CPPFLAGS save_LIBS=$LIBS @@ -31,6 +33,8 @@ AC_DEFUN([PDNS_CHECK_LMDB], [ AC_CHECK_HEADERS([lmdb.h], [ dnl ac_cv_search_mdb_env_open contains '-llmdb' LMDB_LIBS="$LMDB_LIBS $ac_cv_search_mdb_env_open" + AC_DEFINE([HAVE_LMDB], [1], [Define to 1 if you have LMDB]) + [HAVE_LMDB=1] ], [ AC_MSG_ERROR([lmdb headers not found in $with_lmdb]) ]) @@ -40,7 +44,6 @@ AC_DEFUN([PDNS_CHECK_LMDB], [ AC_SUBST([LMDB_LIBS]) ]) ]) - ], [ - AC_MSG_ERROR([--with-lmdb is set to 'no', but lmdb support is required]) ]) + AM_CONDITIONAL([HAVE_LMDB], [test "x$LMDB_LIBS" != "x"]) ]) diff --git a/modules/lmdbbackend/Makefile.am b/modules/lmdbbackend/Makefile.am index 6ac36e9c3..0ad0eb2cf 100644 --- a/modules/lmdbbackend/Makefile.am +++ b/modules/lmdbbackend/Makefile.am @@ -4,6 +4,7 @@ pkglib_LTLIBRARIES = liblmdbbackend.la EXTRA_DIST = OBJECTFILES OBJECTLIBS -liblmdbbackend_la_SOURCES = lmdbbackend.cc lmdbbackend.hh lmdb-safe.hh lmdb-safe.cc lmdb-typed.hh lmdb-typed.cc +liblmdbbackend_la_SOURCES = lmdbbackend.cc lmdbbackend.hh lmdb-typed.hh lmdb-typed.cc \ + ../../pdns/lmdb-safe.hh ../../pdns/lmdb-safe.cc liblmdbbackend_la_LDFLAGS = -module -avoid-version -liblmdbbackend_la_LIBADD = $(LMDB_LIBS) $(BOOST_SERIALIZATION_LIBS) \ No newline at end of file +liblmdbbackend_la_LIBADD = $(LMDB_LIBS) $(BOOST_SERIALIZATION_LIBS) diff --git a/modules/lmdbbackend/lmdb-typed.hh b/modules/lmdbbackend/lmdb-typed.hh index e6da3dd7d..d9d6f17fb 100644 --- a/modules/lmdbbackend/lmdb-typed.hh +++ b/modules/lmdbbackend/lmdb-typed.hh @@ -1,6 +1,6 @@ #pragma once #include -#include "lmdb-safe.hh" +#include "pdns/lmdb-safe.hh" #include #include #include diff --git a/pdns/Makefile.am b/pdns/Makefile.am index c1bbed005..238bc0c8e 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -40,6 +40,10 @@ if LIBSODIUM AM_CPPFLAGS +=$(LIBSODIUM_CFLAGS) endif +if LMDB +AM_CPPFLAGS +=$(LMDB_CFLAGS) +endif + EXTRA_DIST = \ dnslabeltext.rl \ dnslabeltext.cc \ @@ -263,6 +267,10 @@ pdns_server_SOURCES += decafsigners.cc pdns_server_LDADD += $(LIBDECAF_LIBS) endif +if LMDB +pdns_server_LDADD += $(LMDB_LIBS) +endif + if SQLITE3 pdns_server_SOURCES += ssqlite3.cc ssqlite3.hh pdns_server_LDADD += $(SQLITE3_LIBS) diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index be4a8785d..b6526088c 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -25,6 +25,7 @@ #include "dnsdist-ecs.hh" #include "dnsdist-lua.hh" #include "dnsdist-protobuf.hh" +#include "dnsdist-kvs.hh" #include "dolog.hh" #include "dnstap.hh" @@ -1076,7 +1077,6 @@ private: std::shared_ptr d_action; }; - #ifdef HAVE_DNS_OVER_HTTPS class HTTPStatusAction: public DNSAction { @@ -1107,6 +1107,38 @@ private: }; #endif /* HAVE_DNS_OVER_HTTPS */ +class KeyValueStoreLookupAction : public DNSAction +{ +public: + KeyValueStoreLookupAction(std::shared_ptr& kvs, std::shared_ptr& lookupKey, const std::string& destinationTag): d_kvs(kvs), d_key(lookupKey), d_tag(destinationTag) + { + } + + DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override + { + std::string key = d_key->getKey(*dq); + std::string result = d_kvs->getValue(key); + + if (!dq->qTag) { + dq->qTag = std::make_shared(); + } + + dq->qTag->insert({d_tag, std::move(result)}); + + return Action::None; + } + + std::string toString() const override + { + return "lookup key-value store based on '" + d_key->toString() + "' and set the result in tag '" + d_tag + "'"; + } + +private: + std::shared_ptr d_kvs; + std::shared_ptr d_key; + std::string d_tag; +}; + template static void addAction(GlobalStateHolder > *someRulActions, luadnsrule_t var, std::shared_ptr action, boost::optional params) { setLuaSideEffect(); @@ -1416,4 +1448,8 @@ void setupLuaActions() return std::shared_ptr(new HTTPStatusAction(status, body, contentType ? *contentType : "")); }); #endif /* HAVE_DNS_OVER_HTTPS */ + + g_lua.writeFunction("KeyValueStoreLookupAction", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey, const std::string& destinationTag) { + return std::shared_ptr(new KeyValueStoreLookupAction(kvs, lookupKey, destinationTag)); + }); } diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index e642f929a..4dad8fbe4 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -25,6 +25,7 @@ #include "config.h" #include "dnsdist.hh" +#include "dnsdist-kvs.hh" #include "dnsdist-lua.hh" #include "dnsdist-protobuf.hh" @@ -713,4 +714,25 @@ void setupLuaBindings(bool client) } return values; }); + + /* Key Value Store objects */ + g_lua.writeFunction("KeyValueLookupKeySourceIP", []() { + return std::shared_ptr(new KeyValueLookupKeySourceIP()); + }); + g_lua.writeFunction("KeyValueLookupKeyQName", []() { + return std::shared_ptr(new KeyValueLookupKeyQName()); + }); + g_lua.writeFunction("KeyValueLookupKeyTag", [](const std::string& tag) { + return std::shared_ptr(new KeyValueLookupKeyTag(tag)); + }); + +#ifdef HAVE_LMDB + g_lua.writeFunction("newLMDBKVStore", [client](const std::string& fname, const std::string& dbName) { + if (client) { + return std::shared_ptr(nullptr); + } + return std::shared_ptr(new LMDBKVStore(fname, dbName)); + }); +#endif /* HAVE_LMDB */ + } diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 46ad4dfa3..6089b854e 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -2541,6 +2541,9 @@ try #ifdef HAVE_LIBSODIUM cout<<"libsodium "; #endif +#ifdef HAVE_LMDB + cout<<"lmdb "; +#endif #ifdef HAVE_PROTOBUF cout<<"protobuf "; #endif diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 97ce69463..98c662965 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -49,6 +49,10 @@ if HAVE_LIBCRYPTO AM_CPPFLAGS += $(LIBCRYPTO_INCLUDES) endif +if HAVE_LMDB +AM_CPPFLAGS += $(LMDB_CFLAGS) +endif + if HAVE_DNS_OVER_HTTPS if HAVE_LIBSSL AM_CPPFLAGS += $(LIBSSL_CFLAGS) @@ -115,6 +119,7 @@ dnsdist_SOURCES = \ dnsdist-dynblocks.hh \ dnsdist-ecs.cc dnsdist-ecs.hh \ dnsdist-idstate.cc \ + dnsdist-kvs.hh dnsdist-kvs.cc \ dnsdist-lua.hh dnsdist-lua.cc \ dnsdist-lua-actions.cc \ dnsdist-lua-bindings.cc \ @@ -170,6 +175,53 @@ dnsdist_SOURCES = \ ext/incbin/incbin.h \ ext/libbpf/libbpf.h +testrunner_SOURCES = \ + base64.hh \ + dns.hh \ + test-base64_cc.cc \ + test-delaypipe_hh.cc \ + test-dnscrypt_cc.cc \ + test-dnsdist_cc.cc \ + test-dnsdistdynblocks_hh.cc \ + test-dnsdistkvs_cc.cc \ + test-dnsdistpacketcache_cc.cc \ + test-dnsdistrings_cc.cc \ + test-dnsdistrules_cc.cc \ + test-dnsparser_cc.cc \ + test-iputils_hh.cc \ + test-mplexer.cc \ + cachecleaner.hh \ + circular_buffer.hh \ + dnsdist.hh \ + dnsdist-cache.cc dnsdist-cache.hh \ + dnsdist-ecs.cc dnsdist-ecs.hh \ + dnsdist-kvs.cc dnsdist-kvs.hh \ + dnsdist-rings.hh \ + dnsdist-xpf.cc dnsdist-xpf.hh \ + dnscrypt.cc dnscrypt.hh \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.hh dnsparser.cc \ + dnswriter.cc dnswriter.hh \ + dolog.hh \ + ednsoptions.cc ednsoptions.hh \ + ednscookies.cc ednscookies.hh \ + ednssubnet.cc ednssubnet.hh \ + gettime.cc gettime.hh \ + iputils.cc iputils.hh \ + misc.cc misc.hh \ + namespaces.hh \ + pdnsexception.hh \ + pollmplexer.cc \ + qtype.cc qtype.hh \ + sholder.hh \ + sodcrypto.cc \ + sstuff.hh \ + statnode.cc statnode.hh \ + threadname.hh threadname.cc \ + testrunner.cc \ + xpf.cc xpf.hh + dnsdist_LDFLAGS = \ $(AM_LDFLAGS) \ $(PROGRAM_LDFLAGS) \ @@ -188,6 +240,20 @@ dnsdist_LDADD = \ $(LIBCAP_LIBS) \ $(IPCRYPT_LIBS) +testrunner_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(PROGRAM_LDFLAGS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) \ + -pthread + +testrunner_LDADD = \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ + $(LIBSODIUM_LIBS) \ + $(FSTRM_LIBS) \ + $(RT_LIBS) \ + $(SANITIZER_FLAGS) \ + $(LIBCAP_LIBS) + if HAVE_RE2 dnsdist_LDADD += $(RE2_LIBS) endif @@ -201,6 +267,13 @@ dnsdist_LDADD += $(LIBCRYPTO_LDFLAGS) $(LIBCRYPTO_LIBS) dnsdist_SOURCES += ipcipher.cc ipcipher.hh endif +if HAVE_LMDB +dnsdist_LDADD += $(LMDB_LDFLAGS) $(LMDB_LIBS) +testrunner_LDADD += $(LMDB_LDFLAGS) $(LMDB_LIBS) +dnsdist_SOURCES += lmdb-safe.cc lmdb-safe.hh +testrunner_SOURCES += lmdb-safe.cc lmdb-safe.hh +endif + if HAVE_DNS_OVER_TLS if HAVE_GNUTLS dnsdist_LDADD += -lgnutls @@ -238,51 +311,6 @@ dnsdist.$(OBJEXT): dnsmessage.pb.cc dnstap.pb.cc endif endif -testrunner_SOURCES = \ - base64.hh \ - dns.hh \ - test-base64_cc.cc \ - test-delaypipe_hh.cc \ - test-dnscrypt_cc.cc \ - test-dnsdist_cc.cc \ - test-dnsdistdynblocks_hh.cc \ - test-dnsdistpacketcache_cc.cc \ - test-dnsdistrings_cc.cc \ - test-dnsdistrules_cc.cc \ - test-dnsparser_cc.cc \ - test-iputils_hh.cc \ - test-mplexer.cc \ - cachecleaner.hh \ - circular_buffer.hh \ - dnsdist.hh \ - dnsdist-cache.cc dnsdist-cache.hh \ - dnsdist-ecs.cc dnsdist-ecs.hh \ - dnsdist-rings.hh \ - dnsdist-xpf.cc dnsdist-xpf.hh \ - dnscrypt.cc dnscrypt.hh \ - dnslabeltext.cc \ - dnsname.cc dnsname.hh \ - dnsparser.hh dnsparser.cc \ - dnswriter.cc dnswriter.hh \ - dolog.hh \ - ednsoptions.cc ednsoptions.hh \ - ednscookies.cc ednscookies.hh \ - ednssubnet.cc ednssubnet.hh \ - gettime.cc gettime.hh \ - iputils.cc iputils.hh \ - misc.cc misc.hh \ - namespaces.hh \ - pdnsexception.hh \ - pollmplexer.cc \ - qtype.cc qtype.hh \ - sholder.hh \ - sodcrypto.cc \ - sstuff.hh \ - statnode.cc statnode.hh \ - threadname.hh threadname.cc \ - testrunner.cc \ - xpf.cc xpf.hh - if HAVE_FREEBSD dnsdist_SOURCES += kqueuemplexer.cc testrunner_SOURCES += kqueuemplexer.cc @@ -302,20 +330,6 @@ testrunner_SOURCES += \ portsmplexer.cc endif -testrunner_LDFLAGS = \ - $(AM_LDFLAGS) \ - $(PROGRAM_LDFLAGS) \ - $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) \ - -pthread - -testrunner_LDADD = \ - $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \ - $(LIBSODIUM_LIBS) \ - $(FSTRM_LIBS) \ - $(RT_LIBS) \ - $(SANITIZER_FLAGS) \ - $(LIBCAP_LIBS) - MANPAGES=dnsdist.1 dist_man_MANS=$(MANPAGES) diff --git a/pdns/dnsdistdist/configure.ac b/pdns/dnsdistdist/configure.ac index 83563abad..34b484fdd 100644 --- a/pdns/dnsdistdist/configure.ac +++ b/pdns/dnsdistdist/configure.ac @@ -63,6 +63,7 @@ PDNS_CHECK_LUA_HPP AM_CONDITIONAL([HAVE_GNUTLS], [false]) AM_CONDITIONAL([HAVE_LIBSSL], [false]) +AM_CONDITIONAL([HAVE_LMDB], [false]) PDNS_CHECK_LIBCRYPTO @@ -92,6 +93,8 @@ AS_IF([test "x$enable_dns_over_https" != "xno"], [ ]) ]) +PDNS_CHECK_LMDB + AX_CXX_COMPILE_STDCXX_11([ext], [mandatory]) AC_MSG_CHECKING([whether we will enable compiler security checks]) @@ -213,5 +216,9 @@ AS_IF([test "x$enable_dns_over_tls" != "xno" -o "x$enable_dns_over_https" != "xn [AC_MSG_NOTICE([OpenSSL: no])] )] ) +AS_IF([test "x$LMDB_LIBS" != "x"], + [AC_MSG_NOTICE([lmdb: yes])], + [AC_MSG_NOTICE([lmdb: no])] +) AC_MSG_NOTICE([]) diff --git a/pdns/dnsdistdist/dnsdist-kvs.cc b/pdns/dnsdistdist/dnsdist-kvs.cc new file mode 100644 index 000000000..f29e3d644 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-kvs.cc @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#include "dnsdist-kvs.hh" +#include "dolog.hh" + +#ifdef HAVE_LMDB + +#include "lmdb-safe.hh" + +std::string LMDBKVStore::getValue(const std::string& key) +{ + string_view result; + try { + auto transaction = d_env.getROTransaction(); + auto dbi = transaction.openDB(d_dbName, 0); + int rc = transaction.get(dbi, MDBInVal(key), result); + if (rc == 0) { + return result.to_string(); + } + else if (rc == MDB_NOTFOUND) { + return std::string(); + } + } + catch(const std::exception& e) { + warnlog("Error while looking up key '%s' from LMDB file '%s', database '%s': %s", key, d_fname, d_dbName); + } + return std::string(); +} + +#endif /* HAVE_LMDB */ diff --git a/pdns/dnsdistdist/dnsdist-kvs.hh b/pdns/dnsdistdist/dnsdist-kvs.hh new file mode 100644 index 000000000..aa5654536 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-kvs.hh @@ -0,0 +1,128 @@ +/* + * 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::string getKey(const DNSQuestion&) = 0; + virtual std::string toString() const = 0; +}; + +class KeyValueLookupKeySourceIP: public KeyValueLookupKey +{ +public: + std::string getKey(const DNSQuestion& dq) override + { + std::string key; + if (dq.remote->sin4.sin_family == AF_INET) { + key = std::string(reinterpret_cast(&dq.remote->sin4.sin_addr.s_addr), sizeof(dq.remote->sin4.sin_addr.s_addr)); + } + else if (dq.remote->sin4.sin_family == AF_INET6) { + key = std::string(reinterpret_cast(&dq.remote->sin6.sin6_addr.s6_addr), sizeof(dq.remote->sin6.sin6_addr.s6_addr)); + } + return key; + } + + std::string toString() const override + { + return "source IP"; + } +}; + +class KeyValueLookupKeyQName: public KeyValueLookupKey +{ +public: + std::string getKey(const DNSQuestion& dq) override + { + return dq.qname->toDNSStringLC(); + } + + std::string toString() const override + { + return "qname"; + } +}; + +class KeyValueLookupKeyTag: public KeyValueLookupKey +{ +public: + KeyValueLookupKeyTag(const std::string& tag): d_tag(tag) + { + } + + std::string getKey(const DNSQuestion& dq) override + { + std::string key; + if (dq.qTag) { + const auto& it = dq.qTag->find(d_tag); + if (it != dq.qTag->end()) { + key = it->second; + } + } + return key; + } + + std::string toString() const override + { + return " value of the tag named '" + d_tag + '"'; + } + +private: + std::string d_tag; +}; + +class KeyValueStore +{ +public: + virtual ~KeyValueStore() + { + } + + virtual std::string getValue(const std::string& key) = 0; +}; + +#ifdef HAVE_LMDB + +#include "lmdb-safe.hh" + +class LMDBKVStore: public KeyValueStore +{ +public: + LMDBKVStore(const std::string& fname, const std::string& dbName): d_env(fname.c_str(), MDB_NOSUBDIR, 0600), d_fname(fname), d_dbName(dbName) + { + } + + std::string getValue(const std::string& key) override; + +private: + MDBEnv d_env; + std::string d_fname; + std::string d_dbName; +}; + +#endif /* HAVE_LMDB */ diff --git a/pdns/dnsdistdist/lmdb-safe.cc b/pdns/dnsdistdist/lmdb-safe.cc new file mode 120000 index 000000000..bdc1219c1 --- /dev/null +++ b/pdns/dnsdistdist/lmdb-safe.cc @@ -0,0 +1 @@ +../lmdb-safe.cc \ No newline at end of file diff --git a/pdns/dnsdistdist/lmdb-safe.hh b/pdns/dnsdistdist/lmdb-safe.hh new file mode 120000 index 000000000..4e3d388f5 --- /dev/null +++ b/pdns/dnsdistdist/lmdb-safe.hh @@ -0,0 +1 @@ +../lmdb-safe.hh \ No newline at end of file diff --git a/pdns/dnsdistdist/m4/pdns_check_lmdb.m4 b/pdns/dnsdistdist/m4/pdns_check_lmdb.m4 new file mode 120000 index 000000000..2b4a9ee5c --- /dev/null +++ b/pdns/dnsdistdist/m4/pdns_check_lmdb.m4 @@ -0,0 +1 @@ +../../../m4/pdns_check_lmdb.m4 \ No newline at end of file diff --git a/pdns/dnsdistdist/test-dnsdistkvs_cc.cc b/pdns/dnsdistdist/test-dnsdistkvs_cc.cc new file mode 100644 index 000000000..00e530013 --- /dev/null +++ b/pdns/dnsdistdist/test-dnsdistkvs_cc.cc @@ -0,0 +1,45 @@ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#include + +#include "dnsdist-kvs.hh" + +BOOST_AUTO_TEST_SUITE(dnsdistkvs_cc) + +#ifdef HAVE_LMDB +BOOST_AUTO_TEST_CASE(test_LMDB) { + + auto lmdb = make_unique("/data/Dumps/lmdb", "db-name"); + auto key = make_unique(); + + DNSName qname("powerdns.com."); + uint16_t qtype = QType::A; + uint16_t qclass = QClass::IN; + ComboAddress lc("127.0.0.1:53"); + ComboAddress rem("127.0.0.1:42"); + struct dnsheader dh; + memset(&dh, 0, sizeof(dh)); + size_t bufferSize = 0; + size_t queryLen = 0; + bool isTcp = false; + struct timespec queryRealTime; + gettime(&queryRealTime, true); + struct timespec expiredTime; + /* the internal QPS limiter does not use the real time */ + gettime(&expiredTime); + + DNSQuestion dq(&qname, qtype, qclass, qname.wirelength(), &lc, &rem, &dh, bufferSize, queryLen, isTcp, &queryRealTime); + + DTime dt; + dt.set(); + for (size_t idx = 0; idx < 10000000; idx++) { + std::string value = lmdb->getValue(key->getKey(dq)); + BOOST_CHECK_EQUAL(value, "this is the value of the tag"); + } + cerr<