]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Convert YAML to Lua config, including full test
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Fri, 19 Jan 2024 13:37:50 +0000 (14:37 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 25 Apr 2024 09:31:40 +0000 (11:31 +0200)
pdns/recursordist/Makefile.am
pdns/recursordist/rec-lua-conf.cc
pdns/recursordist/settings/cxxsettings.hh
pdns/recursordist/settings/cxxsupport.cc
pdns/recursordist/settings/rust-bridge-in.rs
pdns/recursordist/test-settings.cc

index 762f7a37622665c45e9428b71f859a4cd6c8a435..6f4d35e56ec647713822fc0926ea7b31eb142550 100644 (file)
@@ -323,6 +323,7 @@ testrunner_SOURCES = \
        settings/cxxsupport.cc \
        sholder.hh \
        sillyrecords.cc \
+       sortlist.cc sortlist.hh \
        sstuff.hh \
        stable-bloom.hh \
        svc-records.cc svc-records.hh \
@@ -505,17 +506,26 @@ endif
 
 rec_control_SOURCES = \
        arguments.cc arguments.hh \
+       base32.cc base32.hh \
        base64.cc base64.hh \
        credentials.cc credentials.hh \
        dnslabeltext.cc \
        dnsname.hh dnsname.cc \
+       dnsparser.cc dnsparser.hh \
+       dnsrecords.cc dnsrecords.hh \
+       dnswriter.cc dnswriter.hh \
        logger.cc \
        logging.cc \
        misc.cc \
+       nsecrecords.cc \
        qtype.cc \
+       rcpgenerator.cc rcpgenerator.hh \
        rec_channel.cc rec_channel.hh \
        rec_control.cc \
        settings/cxxsupport.cc \
+       sillyrecords.cc \
+       sortlist.cc sortlist.hh \
+       svc-records.cc svc-records.hh \
        unix_utility.cc
 
 nodist_rec_control_SOURCES = \
index ff204c3cab8da8db35303c498a14a136584d3f7e..b57bec3f2b1cedbb8d318a2eeb12fbf324e855a7 100644 (file)
@@ -36,8 +36,8 @@ LuaConfigItems::LuaConfigItems()
 {
   DNSName root("."); // don't use g_rootdnsname here, it might not exist yet
   for (const auto& dsRecord : rootDSs) {
-    auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
-    dsAnchors[root].insert(*ds);
+    auto dsRecContent = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
+    dsAnchors[root].emplace(*dsRecContent);
   }
 }
 
index 8b4993bf378fe68c331d25c3cc0dd75ec2d35135..cb0f9a086bbab999e040c0874de9b5c8bd89403b 100644 (file)
@@ -53,4 +53,5 @@ void readYamlAllowNotifyForFile(const std::string& filename, ::rust::Vec<::rust:
 void setArgsForZoneRelatedSettings(pdns::rust::settings::rec::Recursorsettings& settings);
 void setArgsForACLRelatedSettings(pdns::rust::settings::rec::Recursorsettings& settings);
 void fromLuaConfigToBridgeStruct(LocalStateHolder<LuaConfigItems>& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings);
+  void fromBridgeStructToLuaConfig(const pdns::rust::settings::rec::Recursorsettings& settings, LuaConfigItems& luaConfig, ProxyMapping& proxyMapping);
 }
index 348cddd128a03571de88660b08347904810e50d1..e2b49b992b4c21a6d33587f5e0dcc8a6eb89a26f 100644 (file)
@@ -34,6 +34,9 @@
 #include "logger.hh"
 #include "logging.hh"
 #include "rec-lua-conf.hh"
+#include "root-dnssec.hh"
+#include "dnsrecords.hh"
+#include "base64.hh"
 
 ::rust::Vec<::rust::String> pdns::settings::rec::getStrings(const std::string& name)
 {
@@ -707,7 +710,28 @@ std::string pdns::settings::rec::defaultsToYaml()
 
 namespace
 {
-void fromLuaToProtobufServerStruct(const ProtobufExportConfig& pbConfig, pdns::rust::settings::rec::ProtobufServer& pbServer)
+void fromLuaToRust(LocalStateHolder<LuaConfigItems>& luaConfig, pdns::rust::settings::rec::Dnssec& dnssec)
+{
+  dnssec.trustanchorfile = luaConfig->trustAnchorFileInfo.fname;
+  dnssec.trustanchorfile_interval = luaConfig->trustAnchorFileInfo.interval;
+  for (const auto& anchors : luaConfig->dsAnchors) {
+    ::rust::Vec<::rust::String> dsRecords;
+    for (const auto& dsRecord : anchors.second) {
+      const auto dsString = dsRecord.getZoneRepresentation();
+      if (std::find(rootDSs.begin(), rootDSs.end(), dsString) == rootDSs.end()) {
+        dsRecords.emplace_back(dsRecord.getZoneRepresentation());
+      }
+    }
+    pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords};
+    dnssec.trustanchors.emplace_back(trustAnchor);
+  }
+  for (const auto& anchors : luaConfig->negAnchors) {
+    pdns::rust::settings::rec::NegativeTrustAnchor negtrustAnchor{anchors.first.toString(), anchors.second};
+    dnssec.negative_trustanchors.emplace_back(negtrustAnchor);
+  }
+}
+
+void fromLuaToRust(const ProtobufExportConfig& pbConfig, pdns::rust::settings::rec::ProtobufServer& pbServer)
 {
   for (const auto& server : pbConfig.servers) {
     pbServer.servers.emplace_back(server.toStringWithPort());
@@ -725,24 +749,37 @@ void fromLuaToProtobufServerStruct(const ProtobufExportConfig& pbConfig, pdns::r
   pbServer.logMappedFrom = pbConfig.logMappedFrom;
 }
 
-void fromLuaConfigToTAInfo(LocalStateHolder<LuaConfigItems>& luaConfig, pdns::rust::settings::rec::Dnssec& dnssec)
+void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec::DNSTapFrameStreamServer& dnstap)
 {
-  dnssec.trustanchorfile = luaConfig->trustAnchorFileInfo.fname;
-  dnssec.trustanchorfile_interval = luaConfig->trustAnchorFileInfo.interval;
-  for (const auto& anchors : luaConfig->dsAnchors) {
-    ::rust::Vec<::rust::String> dsRecords;
-    for (const auto& dsRecord : anchors.second) {
-      dsRecords.emplace_back(dsRecord.getZoneRepresentation());
-    }
-    pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords};
-    dnssec.trustanchors.emplace_back(trustAnchor);
-  }
-  for (const auto& anchors : luaConfig->negAnchors) {
-    pdns::rust::settings::rec::NegativeTrustAnchor negtrustAnchor{anchors.first.toString(), anchors.second};
-    dnssec.negative_trustanchors.emplace_back(negtrustAnchor);
-  }
+  for (const auto& server : fsc.servers) {
+    dnstap.servers.emplace_back(server);
+  }
+  dnstap.logQueries = fsc.logQueries;
+  dnstap.logResponses = fsc.logQueries;
+  dnstap.bufferHint= fsc.bufferHint;
+  dnstap.flushTimeout = fsc.flushTimeout;
+  dnstap.inputQueueSize = fsc.inputQueueSize;
+  dnstap.outputQueueSize = fsc.outputQueueSize;
+  dnstap.queueNotifyThreshold = fsc.queueNotifyThreshold;
+  dnstap.reopenInterval = fsc.reopenInterval;
 }
 
+void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec::DNSTapNODFrameStreamServer& dnstap)
+{
+  for (const auto& server : fsc.servers) {
+    dnstap.servers.emplace_back(server);
+  }
+  dnstap.logNODs = fsc.logNODs;
+  dnstap.logUDRs = fsc.logUDRs;
+  dnstap.bufferHint= fsc.bufferHint;
+  dnstap.flushTimeout = fsc.flushTimeout;
+  dnstap.inputQueueSize = fsc.inputQueueSize;
+  dnstap.outputQueueSize = fsc.outputQueueSize;
+  dnstap.queueNotifyThreshold = fsc.queueNotifyThreshold;
+  dnstap.reopenInterval = fsc.reopenInterval;
+}
+
+
 template <typename T>
 void setIfAvailable(const rpzOptions_t& table, T& var, const std::string& name)
 {
@@ -766,7 +803,7 @@ void setIfAvailable(const rpzOptions_t& table, pdns::rust::settings::rec::TSIGTr
     var.secret = boost::get<std::string>(table.at("tsigsecret"));
   }
 }
-void fromLuaConfigToRPZ(const vector<RPZRaw>& rpzs, pdns::rust::settings::rec::Recursor& rec)
+void fromLuaToRust(const vector<RPZRaw>& rpzs, pdns::rust::settings::rec::Recursor& rec)
 {
   for (const auto& rpz : rpzs) {
     pdns::rust::settings::rec::RPZ rustrpz{
@@ -798,7 +835,7 @@ void fromLuaConfigToRPZ(const vector<RPZRaw>& rpzs, pdns::rust::settings::rec::R
       setIfAvailable(*rpz.options, rustrpz.maxTTL, "maxTTL");
       setIfAvailable(*rpz.options, rustrpz.policyName, "policyName");
       if (rpz.options->count("tags") != 0) {
-        const auto& tags = boost::get<vector<std::pair<int, std::string>>>(rpz.options->at("have"));
+        const auto& tags = boost::get<vector<std::pair<int, std::string>>>(rpz.options->at("tags"));
         for (const auto& tag : tags) {
           rustrpz.tags.emplace_back(tag.second);
         }
@@ -829,7 +866,7 @@ string cvt(pdns::ZoneMD::Config cfg)
   }
 }
 
-void fromLuaConfigToZoneToCache(const map<DNSName, RecZoneToCache::Config>& ztcConfigs, pdns::rust::settings::rec::Recordcache& recordcache)
+void fromLuaToRust(const map<DNSName, RecZoneToCache::Config>& ztcConfigs, pdns::rust::settings::rec::Recordcache& recordcache)
 {
   for (const auto& [_, iter] : ztcConfigs) {
     pdns::rust::settings::rec::ZoneToCache ztc;
@@ -842,18 +879,21 @@ void fromLuaConfigToZoneToCache(const map<DNSName, RecZoneToCache::Config>& ztcC
     if (!iter.d_tt.name.empty()) {
       ztc.tsig.name = iter.d_tt.name.toString();
       ztc.tsig.algo = iter.d_tt.algo.toString();
-      ztc.tsig.secret = iter.d_tt.secret;
+      ztc.tsig.secret = Base64Encode(iter.d_tt.secret);
     }
     ztc.refreshPeriod = iter.d_refreshPeriod;
     ztc.retryOnErrorPeriod = iter.d_retryOnError;
     ztc.maxReceivedMBytes = iter.d_maxReceivedBytes;
-    ztc.localAddress = iter.d_local.toStringWithPort();
+    if (iter.d_local != ComboAddress()) {
+      ztc.localAddress = iter.d_local.toString();
+    }
     ztc.zonemd = cvt(iter.d_zonemd);
     ztc.dnssec = cvt(iter.d_dnssec);
     recordcache.zonetocaches.emplace_back(ztc);
   }
 }
-string cvt(AdditionalMode mode)
+
+std::string cvt(AdditionalMode mode)
 {
   switch (mode) {
   case AdditionalMode::Ignore:
@@ -869,7 +909,35 @@ string cvt(AdditionalMode mode)
   }
 }
 
-void fromLuaConfigToAllowAddtionalQTypes(const std::map<QType, std::pair<std::set<QType>, AdditionalMode>>& allowAdditionalQTypes, pdns::rust::settings::rec::Recursor& rec)
+AdditionalMode cvtAdditional(const std::string& mode)
+{
+  static const std::map<std::string, AdditionalMode> map = {
+    { "Ignore", AdditionalMode::Ignore },
+    { "CacheOnly", AdditionalMode::CacheOnly },
+    { "CacheOnlyRequireAuth", AdditionalMode::CacheOnlyRequireAuth },
+    { "ResolveImmediately", AdditionalMode::ResolveImmediately },
+    { "ResolveDeferred", AdditionalMode::ResolveDeferred}
+  };
+  if (auto iter = map.find(mode); iter != map.end()) {
+    return iter->second;
+  }
+  throw runtime_error("AdditionalMode '" + mode + "' unknown");
+}
+
+pdns::ZoneMD::Config cvtZoneMDConfig(const std::string& mode)
+{
+  static const std::map<std::string, pdns::ZoneMD::Config> map = {
+    { "ignore", pdns::ZoneMD::Config::Ignore },
+    { "validate", pdns::ZoneMD::Config::Validate },
+    { "require", pdns::ZoneMD::Config::Require },
+  };
+  if (auto iter = map.find(mode); iter != map.end()) {
+    return iter->second;
+  }
+  throw runtime_error("ZoneMD config '" + mode + "' unknown");
+}
+
+void fromLuaToRust(const std::map<QType, std::pair<std::set<QType>, AdditionalMode>>& allowAdditionalQTypes, pdns::rust::settings::rec::Recursor& rec)
 {
   for (const auto& [qtype, data] : allowAdditionalQTypes) {
     const auto& [qtypeset, mode] = data;
@@ -883,7 +951,7 @@ void fromLuaConfigToAllowAddtionalQTypes(const std::map<QType, std::pair<std::se
   }
 }
 
-void fromLuaConfigToProxyMappings(const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Incoming& incoming)
+void fromLuaToRust(const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Incoming& incoming)
 {
   for (const auto& mapping : proxyMapping) {
     pdns::rust::settings::rec::ProxyMapping pmap;
@@ -898,7 +966,7 @@ void fromLuaConfigToProxyMappings(const ProxyMapping& proxyMapping, pdns::rust::
   }
 }
 
-void fromLuaConfigToSortList(const SortList& arg, pdns::rust::settings::rec::Recursor& rec)
+void fromLuaToRust(const SortList& arg, pdns::rust::settings::rec::Recursor& rec)
 {
   const auto& sortlist = arg.getTree();
   for (const auto& iter : sortlist) {
@@ -929,21 +997,275 @@ void fromLuaConfigToSortList(const SortList& arg, pdns::rust::settings::rec::Rec
 void pdns::settings::rec::fromLuaConfigToBridgeStruct(LocalStateHolder<LuaConfigItems>& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings)
 {
 
-  fromLuaConfigToTAInfo(luaConfig, settings.dnssec);
+  fromLuaToRust(luaConfig, settings.dnssec);
   if (luaConfig->protobufExportConfig.enabled) {
     pdns::rust::settings::rec::ProtobufServer pbServer;
-    fromLuaToProtobufServerStruct(luaConfig->protobufExportConfig, pbServer);
+    fromLuaToRust(luaConfig->protobufExportConfig, pbServer);
     settings.logging.protobuf_servers.emplace_back(pbServer);
   }
   if (luaConfig->outgoingProtobufExportConfig.enabled) {
     pdns::rust::settings::rec::ProtobufServer pbServer;
-    fromLuaToProtobufServerStruct(luaConfig->outgoingProtobufExportConfig, pbServer);
+    fromLuaToRust(luaConfig->outgoingProtobufExportConfig, pbServer);
     settings.logging.outgoing_protobuf_servers.emplace_back(pbServer);
   }
+  if (luaConfig->frameStreamExportConfig.enabled) {
+    pdns::rust::settings::rec::DNSTapFrameStreamServer dnstap;
+    fromLuaToRust(luaConfig->frameStreamExportConfig, dnstap);
+    settings.logging.dnstap_framestream_servers.emplace_back(dnstap);
+  }
+  if (luaConfig->nodFrameStreamExportConfig.enabled) {
+    pdns::rust::settings::rec::DNSTapNODFrameStreamServer dnstap;
+    fromLuaToRust(luaConfig->nodFrameStreamExportConfig, dnstap);
+    settings.logging.dnstap_nod_framestream_servers.emplace_back(dnstap);
+  }
+  fromLuaToRust(luaConfig->rpzRaw, settings.recursor);
+  fromLuaToRust(luaConfig->sortlist, settings.recursor);
+  fromLuaToRust(luaConfig->ztcConfigs, settings.recordcache);
+  fromLuaToRust(luaConfig->allowAdditionalQTypes, settings.recursor);
+  fromLuaToRust(proxyMapping, settings.incoming);
+}
 
-  fromLuaConfigToRPZ(luaConfig->rpzRaw, settings.recursor);
-  fromLuaConfigToSortList(luaConfig->sortlist, settings.recursor);
-  fromLuaConfigToZoneToCache(luaConfig->ztcConfigs, settings.recordcache);
-  fromLuaConfigToAllowAddtionalQTypes(luaConfig->allowAdditionalQTypes, settings.recursor);
-  fromLuaConfigToProxyMappings(proxyMapping, settings.incoming);
+namespace {
+void fromRustToLuaConfig(const pdns::rust::settings::rec::Dnssec& dnssec, LuaConfigItems& luaConfig)
+{
+  for (const auto& trustAnchor : dnssec.trustanchors) {
+    // Do not inser the default root DS records
+    if (trustAnchor.name == ".") {
+      for (const auto &dsRecord : trustAnchor.dsrecords) {
+        const std::string dsString = std::string(dsRecord);
+        if (std::find(rootDSs.begin(), rootDSs.end(), dsString) == rootDSs.end()) {
+          auto dsRecContent = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsString));
+          luaConfig.dsAnchors[DNSName(std::string(trustAnchor.name))].emplace(*dsRecContent);
+        }
+      }
+    }
+    else {
+      for (const auto &dsRecord : trustAnchor.dsrecords) {
+        auto dsRecContent = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(std::string(dsRecord)));
+        luaConfig.dsAnchors[DNSName(std::string(trustAnchor.name))].emplace(*dsRecContent);
+      }
+    }
+  }
+  for (const auto& nta : dnssec.negative_trustanchors) {
+    luaConfig.negAnchors[DNSName(std::string(nta.name))] = std::string(nta.reason);
+  }
+  luaConfig.trustAnchorFileInfo.fname = std::string(dnssec.trustanchorfile);
+  luaConfig.trustAnchorFileInfo.interval = dnssec.trustanchorfile_interval;
+}
+
+void fromRustToLuaConfig(const pdns::rust::settings::rec::ProtobufServer& pbServer, ProtobufExportConfig& exp)
+{
+  exp.enabled = true;
+  exp.exportTypes.clear();
+  for (const auto& type : pbServer.exportTypes) {
+    exp.exportTypes.emplace(QType::chartocode(std::string(type).c_str()));
+  }
+  for (const auto& server : pbServer.servers) {
+    exp.servers.emplace_back(std::string(server));
+  }
+  exp.maxQueuedEntries = pbServer.maxQueuedEntries;
+  exp.timeout = pbServer.timeout;
+  exp.reconnectWaitTime = pbServer.reconnectWaitTime;
+  exp.asyncConnect = pbServer.asyncConnect;
+  exp.logQueries = pbServer.logQueries;
+  exp.logResponses = pbServer.logResponses;
+  exp.taggedOnly = pbServer.taggedOnly;
+  exp.logMappedFrom = pbServer.logMappedFrom;
+}
+
+void fromRustToLuaConfig(const pdns::rust::settings::rec::DNSTapFrameStreamServer& dnstap, FrameStreamExportConfig& exp)
+{
+  exp.enabled = true;
+  for (const auto& server : dnstap.servers) {
+    exp.servers.emplace_back(std::string(server));
+  }
+  exp.logQueries = dnstap.logQueries;
+  exp.logResponses = dnstap.logResponses;
+  exp.bufferHint = dnstap.bufferHint;
+  exp.flushTimeout = dnstap.flushTimeout;
+  exp.inputQueueSize = dnstap.inputQueueSize;
+  exp.outputQueueSize = dnstap.outputQueueSize;
+  exp.queueNotifyThreshold = dnstap.queueNotifyThreshold;
+  exp.reopenInterval = dnstap.reopenInterval;
+}
+
+void fromRustToLuaConfig(const pdns::rust::settings::rec::DNSTapNODFrameStreamServer& dnstap, FrameStreamExportConfig& exp)
+{
+  exp.enabled = true;
+  for (const auto& server : dnstap.servers) {
+    exp.servers.emplace_back(std::string(server));
+  }
+  exp.logNODs = dnstap.logNODs;
+  exp.logUDRs = dnstap.logUDRs;
+  exp.bufferHint = dnstap.bufferHint;
+  exp.flushTimeout = dnstap.flushTimeout;
+  exp.inputQueueSize = dnstap.inputQueueSize;
+  exp.outputQueueSize = dnstap.outputQueueSize;
+  exp.queueNotifyThreshold = dnstap.queueNotifyThreshold;
+  exp.reopenInterval = dnstap.reopenInterval;
+}
+
+
+void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::RPZ>& rpzs, LuaConfigItems& luaConfig)
+{
+  for (const auto& rpz : rpzs) {
+    RPZRaw rpzRaw;
+    for (const auto& address : rpz.addresses) {
+      rpzRaw.addresses.emplace_back(std::string(address));
+    }
+    rpzRaw.name = std::string(rpz.name);
+    rpzOptions_t options;
+
+    auto setIfNonDefault = [&options](const rust::String& value, const string& name)
+    {
+      if (!value.empty()) {
+        options[name] = std::string(value);
+      }
+    };
+    setIfNonDefault(rpz.defcontent, "defcontent");
+    setIfNonDefault(rpz.defpol, "defpol");
+    if (!rpz.defpolOverrideLocalData) {
+        options["defpolOverrideLocalData"] = false;
+    }
+    if (rpz.defttl != -1U) {
+        options["defttl"] = rpz.defttl;
+    }
+    if (rpz.extendedErrorCode != 0) {
+        options["extendedErrorCode"] = rpz.extendedErrorCode;
+    }
+    setIfNonDefault(rpz.extendedErrorExtra, "extendedErrorExtra");
+    if (rpz.includeSOA) {
+        options["includeSOA"] = true;
+    }
+    if (rpz.ignoreDuplicates) {
+        options["ignoreDuplicates"] = true;
+    }
+    if (rpz.maxTTL != -1U) {
+        options["maxTTL"] = rpz.maxTTL;
+    }
+    setIfNonDefault(rpz.policyName, "policyName");
+    std::vector<std::pair<int, std::string>> tags;
+    int count = 0;
+    for (const auto& tag : rpz.tags) {
+      tags.emplace_back(++count, tag);
+    }
+    if (!tags.empty()) {
+      options["tags"] = tags;
+    }
+    if (!rpz.overridesGettag) {
+        options["overridesGettag"] = false;
+    }
+    if (rpz.zoneSizeHint != 0) {
+        options["zoneSizeHint"] = rpz.zoneSizeHint;
+    }
+    setIfNonDefault(rpz.tsig.name, "tsigname");
+    setIfNonDefault(rpz.tsig.algo, "tsigalgo");
+    setIfNonDefault(rpz.tsig.secret, "tsigsecret");
+    if (rpz.refresh != 0) {
+        options["refresh"] = rpz.refresh;
+    }
+    if (rpz.maxReceivedMBytes != 0) {
+        options["maxReceivedMBytes"] = rpz.maxReceivedMBytes;
+    }
+    setIfNonDefault(rpz.localAddress, "localAddress");
+    if (rpz.axfrTimeout != 0) {
+      options["axfrTimeout"] = rpz.axfrTimeout;
+    }
+    setIfNonDefault(rpz.dumpFile, "dumpFile");
+    setIfNonDefault(rpz.seedFile, "seedFile");
+    if (!options.empty()) {
+      rpzRaw.options = options;
+    }
+    luaConfig.rpzRaw.emplace_back(rpzRaw);
+  }
+}
+
+  void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::ZoneToCache>& ztcs, map<DNSName, RecZoneToCache::Config>& lua)
+{
+  for (const auto& ztc : ztcs) {
+    DNSName zone = DNSName(std::string(ztc.zone));
+    RecZoneToCache::Config lztc;
+    for (const auto& source : ztc.sources) {
+      lztc.d_sources.emplace_back(std::string(source));
+     }
+    lztc.d_zone = std::string(ztc.zone);
+    lztc.d_method = std::string(ztc.method);
+    if (!ztc.localAddress.empty()) {
+      lztc.d_local = ComboAddress(std::string(ztc.localAddress));
+    }
+    if (!ztc.tsig.name.empty()) {
+      lztc.d_tt.name = DNSName(std::string(ztc.tsig.name));
+      lztc.d_tt.algo = DNSName(std::string(ztc.tsig.algo));
+      B64Decode(std::string(ztc.tsig.secret), lztc.d_tt.secret);
+    }
+    lztc.d_maxReceivedBytes = ztc.maxReceivedMBytes;
+    lztc.d_retryOnError = static_cast<time_t>(ztc.retryOnErrorPeriod);
+    lztc.d_refreshPeriod = static_cast<time_t>(ztc.refreshPeriod);
+    lztc.d_timeout = ztc.timeout;
+    lztc.d_zonemd = cvtZoneMDConfig(std::string(ztc.zonemd));
+    lztc.d_dnssec = cvtZoneMDConfig(std::string(ztc.dnssec));
+    lua.emplace(zone, lztc);
+  }
+}
+
+void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::SortList>& sortlists, SortList& lua)
+{
+  for (const auto& sortlist : sortlists) {
+    for (const auto& entry : sortlist.subnets) {
+      lua.addEntry(Netmask(std::string(sortlist.key)), Netmask(std::string(entry.subnet)), static_cast<int>(entry.order));
+    }
+  }
+}
+
+void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::AllowedAdditionalQType>& alloweds, std::map<QType, std::pair<std::set<QType>, AdditionalMode>>& lua)
+{
+  for (const auto& allowed : alloweds) {
+    QType qtype(QType::chartocode(std::string(allowed.qtype).c_str()));
+    std::set<QType> set;
+    for (const auto& target : allowed.targets) {
+      set.emplace(QType::chartocode(std::string(target).c_str()));
+    }
+    AdditionalMode mode = AdditionalMode::CacheOnlyRequireAuth;
+    mode = cvtAdditional(std::string(allowed.mode));
+    lua.emplace(qtype, std::pair{set, mode});
+  }
+}
+
+void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::ProxyMapping>& pmaps, ProxyMapping& proxyMapping)
+{
+  for (const auto& pmap : pmaps) {
+    Netmask subnet = Netmask(std::string(pmap.subnet));
+    ComboAddress address(std::string(pmap.address));
+    boost::optional<SuffixMatchNode> smn;
+    if (!pmap.domains.empty()) {
+      smn = boost::make_optional(SuffixMatchNode{});
+      for (const auto& dom : pmap.domains) {
+        smn->add(DNSName(std::string(dom)));
+      }
+    }
+    proxyMapping.insert_or_assign(subnet, {address, smn});
+  }
+}
+}
+
+void pdns::settings::rec::fromBridgeStructToLuaConfig(const pdns::rust::settings::rec::Recursorsettings& settings, LuaConfigItems& luaConfig, ProxyMapping& proxyMapping)
+{
+  fromRustToLuaConfig(settings.dnssec, luaConfig);
+  if (!settings.logging.protobuf_servers.empty()) {
+    fromRustToLuaConfig(settings.logging.protobuf_servers.at(0), luaConfig.protobufExportConfig);
+  }
+  if (!settings.logging.outgoing_protobuf_servers.empty()) {
+    fromRustToLuaConfig(settings.logging.outgoing_protobuf_servers.at(0), luaConfig.outgoingProtobufExportConfig);
+  }
+  if (!settings.logging.dnstap_framestream_servers.empty()) {
+    fromRustToLuaConfig(settings.logging.dnstap_framestream_servers.at(0), luaConfig.frameStreamExportConfig);
+  }
+  if (!settings.logging.dnstap_nod_framestream_servers.empty()) {
+    fromRustToLuaConfig(settings.logging.dnstap_nod_framestream_servers.at(0), luaConfig.nodFrameStreamExportConfig);
+  }
+  fromRustToLuaConfig(settings.recursor.rpzs, luaConfig);
+  fromRustToLuaConfig(settings.recursor.sortlists, luaConfig.sortlist);
+  fromRustToLuaConfig(settings.recordcache.zonetocaches, luaConfig.ztcConfigs);
+  fromRustToLuaConfig(settings.recursor.allowed_additional_qtypes, luaConfig.allowAdditionalQTypes);
+  fromRustToLuaConfig(settings.incoming.proxymappings, proxyMapping);
 }
index f18c0a4aca4c75d22af04346c254bd12a880ee38..53052e40b5170957050d88ab2139f30e98b67600 100644 (file)
@@ -135,11 +135,11 @@ pub struct TSIGTriplet {
 #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
 #[serde(deny_unknown_fields)]
 pub struct RPZ {
-    #[serde(default, skip_serializing_if = "crate::is_default")]
-    addresses: Vec<String>,
     #[serde(default, skip_serializing_if = "crate::is_default")]
     name: String,
     #[serde(default, skip_serializing_if = "crate::is_default")]
+    addresses: Vec<String>,
+    #[serde(default, skip_serializing_if = "crate::is_default")]
     defcontent: String,
     #[serde(default, skip_serializing_if = "crate::is_default")]
     defpol: String,
index 7335c6021e47e38cfe0562d9eca701e3fb85532c..462b2a61cfd32a541b1a44c7712ae5f08f775c0d 100644 (file)
@@ -7,6 +7,7 @@
 #include <memory>
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/format.hpp>
+#include <fstream>
 
 #include "settings/cxxsettings.hh"
 
@@ -679,6 +680,8 @@ BOOST_AUTO_TEST_CASE(test_yaml_defaults_rpz)
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].ignoreDuplicates, true);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].maxTTL, 101U);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].tags.size(), 2U);
+  BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].tags[0], "d");
+  BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].tags[1], "e");
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].overridesGettag, false);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[2].zoneSizeHint, 102U);
 
@@ -808,4 +811,179 @@ BOOST_AUTO_TEST_CASE(test_yaml_proxymapping)
   BOOST_CHECK_EQUAL(settings.incoming.proxymappings[1].domains.size(), 3U);
 }
 
+BOOST_AUTO_TEST_CASE(test_yaml_to_luaconfigand_back)
+{
+  const std::string yaml = R"EOT(dnssec:
+  trustanchors:
+  - name: .
+    dsrecords:
+    - 10000 8 2 a06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
+  - name: aa.
+    dsrecords:
+    - 1234 8 2 a06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
+    - 4567 8 2 b06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
+  negative_trustanchors:
+  - name: aa.
+    reason: aaa
+  - name: kwh.
+    reason: why
+  trustanchorfile: tmp/tas
+  trustanchorfile_interval: 99
+incoming:
+  proxymappings:
+  - subnet: 1.0.0.0/8
+    address: 4.5.6.7
+  - subnet: 3.4.5.6/32
+    address: 6.7.8.9
+    domains:
+    - a.
+    - b.
+    - c.
+recursor:
+  sortlists:
+  - key: 1.0.0.0/8
+    subnets:
+    - subnet: 5.6.7.8/32
+      order: 99
+  rpzs:
+  - name: rpz.local
+    addresses:
+    - 192.168.178.3:53
+    refresh: 10
+    dumpFile: tmp/rpz.dump
+    seedFile: tmp/rpz.dump
+  - name: zzzz
+    addresses:
+    - '[::1]:99'
+    defcontent: a
+    defpol: Custom
+    defpolOverrideLocalData: false
+    defttl: 10
+    extendedErrorCode: 11
+    extendedErrorExtra: b
+    includeSOA: true
+    ignoreDuplicates: true
+    maxTTL: 12
+    policyName: c
+    tags:
+    - d
+    - e
+    overridesGettag: false
+    zoneSizeHint: 13
+  - name: tmp/file2.rpz
+    ignoreDuplicates: true
+  allowed_additional_qtypes:
+  - qtype: A
+    targets:
+    - A
+    - MX
+    - AAAA
+  - qtype: MX
+    targets:
+    - SRV
+    - HTTPS
+    mode: CacheOnly
+logging:
+  protobuf_servers:
+  - servers:
+    - 1.2.3.4:99
+    timeout: 100
+    maxQueuedEntries: 101
+    reconnectWaitTime: 102
+    taggedOnly: true
+    asyncConnect: true
+    logQueries: false
+    logResponses: false
+    exportTypes:
+    - A
+    - MX
+    logMappedFrom: true
+  outgoing_protobuf_servers:
+  - servers:
+    - 1.2.3.6:101
+    timeout: 100
+    maxQueuedEntries: 101
+    reconnectWaitTime: 102
+    taggedOnly: true
+    asyncConnect: true
+    logQueries: false
+    exportTypes:
+    - A
+    - MX
+    logMappedFrom: true
+  dnstap_framestream_servers:
+  - servers:
+    - b
+    logQueries: false
+    logResponses: false
+    bufferHint: 1
+    flushTimeout: 2
+    inputQueueSize: 3
+    outputQueueSize: 4
+    queueNotifyThreshold: 5
+    reopenInterval: 6
+  dnstap_nod_framestream_servers:
+  - servers:
+    - c
+    logNODs: false
+    logUDRs: true
+    bufferHint: 1
+    flushTimeout: 2
+    inputQueueSize: 3
+    outputQueueSize: 4
+    queueNotifyThreshold: 5
+    reopenInterval: 6
+recordcache:
+  zonetocaches:
+  - zone: zone
+    method: url
+    sources:
+    - https://www.example.com
+  - zone: anotherzone
+    method: axfr
+    sources:
+    - 4.5.6.7
+    timeout: 1
+    tsig:
+      name: a.
+      algo: b.
+      secret: aGVsbG8hCg==
+    refreshPeriod: 2
+    retryOnErrorPeriod: 3
+    maxReceivedMBytes: 4
+    localAddress: 'ffff::'
+    zonemd: ignore
+    dnssec: require
+)EOT";
+  auto settings = pdns::rust::settings::rec::parse_yaml_string(yaml);
+  settings.validate();
+
+  // create a Lua config based on YAML
+  LuaConfigItems luaConfig;
+  ProxyMapping proxyMapping;
+  pdns::settings::rec::fromBridgeStructToLuaConfig(settings, luaConfig, proxyMapping);
+
+  // Create YAML, given a Lua config
+  auto newsettings = pdns::rust::settings::rec::parse_yaml_string("");
+  GlobalStateHolder<LuaConfigItems> gsluaConfig;
+  gsluaConfig.setState(luaConfig);
+  LocalStateHolder<LuaConfigItems> local = gsluaConfig.getLocal();
+  try {
+    pdns::settings::rec::fromLuaConfigToBridgeStruct(local, proxyMapping, newsettings);
+  }
+  catch (std::exception& e) {
+    cerr << e.what() << endl;
+    BOOST_CHECK(false);
+  }
+  // They should be the same
+  auto newyaml = newsettings.to_yaml_string();
+
+  std::ofstream aaa("a");
+  std::ofstream bbb("b");
+  aaa << "===" << endl << yaml << endl << "===" << endl;
+  bbb << "===" << endl << newyaml << endl << "===" << endl;
+
+  BOOST_CHECK_EQUAL(yaml, std::string(newyaml));
+}
+
 BOOST_AUTO_TEST_SUITE_END()