]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add mmdb to YAML configuration
authorEnsar Sarajčić <dev@ensarsarajcic.com>
Tue, 19 May 2026 08:53:21 +0000 (10:53 +0200)
committerEnsar Sarajčić <dev@ensarsarajcic.com>
Tue, 9 Jun 2026 07:54:57 +0000 (09:54 +0200)
Signed-off-by: Ensar Sarajčić <dev@ensarsarajcic.com>
pdns/dnsdistdist/dnsdist-configuration-yaml.cc
pdns/dnsdistdist/dnsdist-rust-bridge.hh
pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs
pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs
pdns/dnsdistdist/dnsdist-settings-definitions.yml

index 19b164ec2795895a527af6d6bf09831cf2badefc..cf0ec18125a17257ac071610a14b6347423f2356 100644 (file)
@@ -28,6 +28,7 @@
 #include "dnsdist-configuration.hh"
 #include "logging.hh"
 #include "logr.hh"
+#include "mmdb.hh"
 
 #if defined(HAVE_YAML_CONFIGURATION)
 #include "base64.hh"
@@ -71,7 +72,12 @@ struct Context
 
 using XSKMap = std::vector<std::shared_ptr<XskSocket>>;
 
-using RegisteredTypes = std::variant<std::shared_ptr<DNSDistPacketCache>, std::shared_ptr<dnsdist::rust::settings::DNSSelector>, std::shared_ptr<dnsdist::rust::settings::DNSActionWrapper>, std::shared_ptr<dnsdist::rust::settings::DNSResponseActionWrapper>, std::shared_ptr<NetmaskGroup>, std::shared_ptr<KeyValueStore>, std::shared_ptr<KeyValueLookupKey>, std::shared_ptr<RemoteLoggerInterface>, std::shared_ptr<ServerPolicy>, std::shared_ptr<TimedIPSetRule>, std::shared_ptr<XSKMap>>;
+using RegisteredTypes = std::variant<std::shared_ptr<DNSDistPacketCache>, std::shared_ptr<dnsdist::rust::settings::DNSSelector>, std::shared_ptr<dnsdist::rust::settings::DNSActionWrapper>, std::shared_ptr<dnsdist::rust::settings::DNSResponseActionWrapper>, std::shared_ptr<NetmaskGroup>, std::shared_ptr<KeyValueStore>, std::shared_ptr<KeyValueLookupKey>, std::shared_ptr<RemoteLoggerInterface>, std::shared_ptr<ServerPolicy>, std::shared_ptr<TimedIPSetRule>, std::shared_ptr<XSKMap>
+#ifdef HAVE_MMDB
+                                     ,
+                                     std::shared_ptr<MMDB>
+#endif
+                                     >;
 static LockGuarded<std::unordered_map<std::string, RegisteredTypes>> s_registeredTypesMap;
 static std::atomic<bool> s_inConfigCheckMode;
 static std::atomic<bool> s_inClientMode;
@@ -1394,7 +1400,12 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo
 void addLuaBindingsForYAMLObjects([[maybe_unused]] LuaContext& luaCtx)
 {
 #if defined(HAVE_YAML_CONFIGURATION)
-  using ReturnValue = std::optional<boost::variant<std::shared_ptr<DNSDistPacketCache>, std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction>, std::shared_ptr<NetmaskGroup>, std::shared_ptr<KeyValueStore>, std::shared_ptr<KeyValueLookupKey>, std::shared_ptr<RemoteLoggerInterface>, std::shared_ptr<ServerPolicy>, std::shared_ptr<TimedIPSetRule>, std::shared_ptr<XSKMap>>>;
+  using ReturnValue = std::optional<boost::variant<std::shared_ptr<DNSDistPacketCache>, std::shared_ptr<DNSRule>, std::shared_ptr<DNSAction>, std::shared_ptr<DNSResponseAction>, std::shared_ptr<NetmaskGroup>, std::shared_ptr<KeyValueStore>, std::shared_ptr<KeyValueLookupKey>, std::shared_ptr<RemoteLoggerInterface>, std::shared_ptr<ServerPolicy>, std::shared_ptr<TimedIPSetRule>, std::shared_ptr<XSKMap>
+#ifdef HAVE_MMDB
+                                                   ,
+                                                   std::shared_ptr<MMDB>
+#endif
+                                                   >>;
 
   luaCtx.writeFunction("getObjectFromYAMLConfiguration", [](const std::string& name) -> ReturnValue {
     auto map = s_registeredTypesMap.lock();
@@ -1435,6 +1446,11 @@ void addLuaBindingsForYAMLObjects([[maybe_unused]] LuaContext& luaCtx)
     if (auto* ptr = std::get_if<std::shared_ptr<XSKMap>>(&item->second)) {
       return ReturnValue(*ptr);
     }
+#ifdef HAVE_MMDB
+    if (auto* ptr = std::get_if<std::shared_ptr<MMDB>>(&item->second)) {
+      return ReturnValue(*ptr);
+    }
+#endif
 
     return std::nullopt;
   });
@@ -1698,7 +1714,7 @@ std::shared_ptr<DNSSelector> getNetmaskGroupSelector(const NetmaskGroupSelectorC
 
 std::shared_ptr<DNSActionWrapper> getKeyValueStoreLookupAction([[maybe_unused]] const KeyValueStoreLookupActionConfiguration& config)
 {
-#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+#if defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB)
   auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
   if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
     throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
@@ -1716,7 +1732,7 @@ std::shared_ptr<DNSActionWrapper> getKeyValueStoreLookupAction([[maybe_unused]]
 
 std::shared_ptr<DNSActionWrapper> getKeyValueStoreRangeLookupAction([[maybe_unused]] const KeyValueStoreRangeLookupActionConfiguration& config)
 {
-#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+#if defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB)
   auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
   if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
     throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
@@ -1734,7 +1750,7 @@ std::shared_ptr<DNSActionWrapper> getKeyValueStoreRangeLookupAction([[maybe_unus
 
 std::shared_ptr<DNSSelector> getKeyValueStoreLookupSelector([[maybe_unused]] const KeyValueStoreLookupSelectorConfiguration& config)
 {
-#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+#if defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB)
   auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
   if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
     throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
@@ -1752,7 +1768,7 @@ std::shared_ptr<DNSSelector> getKeyValueStoreLookupSelector([[maybe_unused]] con
 
 std::shared_ptr<DNSSelector> getKeyValueStoreRangeLookupSelector([[maybe_unused]] const KeyValueStoreRangeLookupSelectorConfiguration& config)
 {
-#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+#if defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB)
   auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
   if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
     throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
@@ -2005,7 +2021,7 @@ void registerDnstapLogger([[maybe_unused]] const DnstapLoggerConfiguration& conf
 
 void registerKVSObjects([[maybe_unused]] const KeyValueStoresConfiguration& config)
 {
-#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+#if defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB)
   bool createObjects = !dnsdist::configuration::yaml::s_inClientMode && !dnsdist::configuration::yaml::s_inConfigCheckMode;
 #if defined(HAVE_LMDB)
   for (const auto& lmdb : config.lmdb) {
@@ -2019,6 +2035,29 @@ void registerKVSObjects([[maybe_unused]] const KeyValueStoresConfiguration& conf
     dnsdist::configuration::yaml::registerType<KeyValueStore>(store, cdb.name);
   }
 #endif /* defined(HAVE_CDB) */
+#if defined(HAVE_MMDB)
+  for (const auto& mmdb : config.mmdb) {
+    auto definedMmdb = dnsdist::configuration::yaml::getRegisteredTypeByName<MMDB>(mmdb.mmdb);
+    if (!definedMmdb) {
+      throw std::runtime_error("Unable to find a MMDB named " + std::string(mmdb.mmdb));
+    }
+    LuaTypeOrArrayOf<std::string> queryParams;
+    if (!mmdb.query_param.empty()) {
+      queryParams = std::string(mmdb.query_param);
+    }
+    else {
+      std::vector<std::pair<int, std::string>> params;
+      params.reserve(mmdb.query_params.size());
+      int i = 1;
+      for (const auto& param : mmdb.query_params) {
+        params.emplace_back(i++, param);
+      }
+      queryParams = params;
+    }
+    auto store = createObjects ? std::shared_ptr<KeyValueStore>(std::make_shared<MMDBKVStore>(definedMmdb, queryParams)) : std::shared_ptr<KeyValueStore>();
+    dnsdist::configuration::yaml::registerType<KeyValueStore>(store, mmdb.name);
+  }
+#endif /* defined(HAVE_MMDB) */
   for (const auto& key : config.lookup_keys.source_ip_keys) {
     auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySourceIP>(key.v4_mask, key.v6_mask, key.include_port)) : std::shared_ptr<KeyValueLookupKey>();
     dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
@@ -2035,7 +2074,16 @@ void registerKVSObjects([[maybe_unused]] const KeyValueStoresConfiguration& conf
     auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyTag>(std::string(key.tag))) : std::shared_ptr<KeyValueLookupKey>();
     dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
   }
-#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
+#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) || defined(HAVE_MMDB) */
+}
+
+void registerMMDBObjects([[maybe_unused]] const ::rust::Vec<MmdbConfiguration>& config)
+{
+#ifdef HAVE_MMDB
+  for (const auto& mmdb : config) {
+    dnsdist::configuration::yaml::registerType<MMDB>(std::make_shared<MMDB>(std::string(mmdb.file_name), mmdb.mmap ? "mmap" : ""), mmdb.name);
+  }
+#endif
 }
 
 void registerNMGObjects(const ::rust::Vec<NetmaskGroupConfiguration>& nmgs)
index be86c01e1446d94ec3618874e7b5b6208b5cf543..a03f8391e0918d035b334b5e414c498946eb2df2 100644 (file)
@@ -33,12 +33,14 @@ struct DNSResponseActionWrapper
 struct ProtobufLoggerConfiguration;
 struct DnstapLoggerConfiguration;
 struct KeyValueStoresConfiguration;
+struct MmdbConfiguration;
 struct NetmaskGroupConfiguration;
 struct TimedIpSetConfiguration;
 
 void registerProtobufLogger(const ProtobufLoggerConfiguration& config);
 void registerDnstapLogger(const DnstapLoggerConfiguration& config);
 void registerKVSObjects(const KeyValueStoresConfiguration& config);
+void registerMMDBObjects(const ::rust::Vec<MmdbConfiguration>& config);
 void registerNMGObjects(const ::rust::Vec<NetmaskGroupConfiguration>& nmgs);
 void registerTimedIPSetObjects(const ::rust::Vec<TimedIpSetConfiguration>& sets);
 
index 8bfac01e27df3240ef0c9c014c9389874aae7c1b..7da6bc1290e9ecbbde5902cdc396d244b90747b2 100644 (file)
@@ -15,6 +15,7 @@
         fn registerProtobufLogger(config: &ProtobufLoggerConfiguration);
         fn registerDnstapLogger(config: &DnstapLoggerConfiguration);
         fn registerKVSObjects(config: &KeyValueStoresConfiguration);
+        fn registerMMDBObjects(config: &Vec<MmdbConfiguration>);
         fn registerNMGObjects(nmgs: &Vec<NetmaskGroupConfiguration>);
         fn registerTimedIPSetObjects(sets: &Vec<TimedIpSetConfiguration>);
     }
index 091441c408e8f0aed78cfbdf20d255a1fb63d2e0..5ab74482201ed854fe176222592946d33ce24805 100644 (file)
@@ -70,6 +70,7 @@ fn get_global_configuration_from_serde(
         ebpf: serde.ebpf,
         edns_client_subnet: serde.edns_client_subnet,
         general: serde.general,
+        mmdbs: serde.mmdbs,
         key_value_stores: serde.key_value_stores,
         load_balancing_policies: serde.load_balancing_policies,
         logging: serde.logging,
@@ -91,6 +92,8 @@ fn get_global_configuration_from_serde(
     };
     // this needs to be done before the rules so that they can refer to the loggers
     register_remote_loggers(&config.remote_logging);
+    // this needs to be done before the KVS so they can refer to the DBs
+    dnsdistsettings::registerMMDBObjects(&config.mmdbs);
     // this needs to be done before the rules so that they can refer to the KVS objects
     dnsdistsettings::registerKVSObjects(&config.key_value_stores);
     // this needs to be done before the rules so that they can refer to the NMG objects
index f703630122d9c7564620417c62a9b4fb64047b7b..d1540c9c472f958bb0e4f50b1cedde82eb9e722b 100644 (file)
@@ -73,6 +73,10 @@ global:
       type: "MetricsConfiguration"
       default: true
       description: "Metrics-related settings"
+    - name: "mmdbs"
+      type: "Vec<MmdbConfiguration>"
+      default: true
+      description: "List of MMDB databases"
     - name: "netmask_groups"
       type: "Vec<NetmaskGroupConfiguration>"
       default: true
@@ -310,6 +314,38 @@ cdb_kv_store:
       type: "u32"
       description: "The delay in seconds between two checks of the database modification time. 0 means disabled"
 
+mmdb_kv_store:
+  description: "MMDB-based key-value store"
+  parameters:
+    - name: "name"
+      type: "String"
+      description: "The name of this object"
+    - name: "mmdb"
+      type: "String"
+      description: "Name of an existing MMDB database"
+    - name: "query_param"
+      type: "String"
+      default: ""
+      description: "Key to look up in the MMDB database associated with an IP - top level only."
+    - name: "query_params"
+      type: "Vec<String>"
+      default: true
+      description: "List of nested keys to look up in the MMDB database associated with an IP"
+
+mmdb:
+  description: "MMDB database"
+  parameters:
+    - name: "name"
+      type: "String"
+      description: "The name of this object"
+    - name: "file_name"
+      type: "String"
+      description: "The path to the MMDB file"
+    - name: "mmap"
+      type: "bool"
+      default: "false"
+      description: "Whether to open the MMDB in mmap mode"
+
 kvs_lookup_key_source_ip:
   description: "Lookup key that can be used with :ref:`yaml-settings-KeyValueStoreLookupAction` or :ref:`yaml-settings-KeyValueStoreLookupSelector`, will return the source IP of the client in network byte-order"
   parameters:
@@ -404,6 +440,10 @@ key_value_stores:
       type: "Vec<CdbKvStoreConfiguration>"
       default: true
       description: "List of CDB-based key-value stores"
+    - name: "mmdb"
+      type: "Vec<MmdbKvStoreConfiguration>"
+      default: true
+      description: "List of MMDB-based key-value stores"
     - name: "lookup_keys"
       type: "KvsLookupKeysConfiguration"
       default: true