]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Build active Lua config from data structure that can be supplied by either Lua or...
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 24 Jan 2024 08:46:44 +0000 (09:46 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 25 Apr 2024 09:31:40 +0000 (11:31 +0200)
14 files changed:
pdns/recursordist/Makefile.am
pdns/recursordist/filterpo.hh
pdns/recursordist/rec-lua-conf.cc
pdns/recursordist/rec-lua-conf.hh
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/rpzloader.cc
pdns/recursordist/rpzloader.hh
pdns/recursordist/settings/cxxsettings.hh
pdns/recursordist/settings/cxxsupport.cc
pdns/recursordist/settings/rust-bridge-in.rs
pdns/recursordist/settings/table.py
pdns/recursordist/test-settings.cc

index 6f4d35e56ec647713822fc0926ea7b31eb142550..43ac680342ca40cc689d454a09e339230bbddf1a 100644 (file)
@@ -514,6 +514,7 @@ rec_control_SOURCES = \
        dnsparser.cc dnsparser.hh \
        dnsrecords.cc dnsrecords.hh \
        dnswriter.cc dnswriter.hh \
+       filterpo.cc filterpo.hh \
        logger.cc \
        logging.cc \
        misc.cc \
index d69b799e5d50bd10958b4b93c4744c96ff73ba27..2fec80813b086c110e654cddaeddd16ff12a77d1 100644 (file)
@@ -335,6 +335,10 @@ public:
     {
       d_zoneData->d_tags = std::move(tags);
     }
+    void setTags(const std::unordered_set<std::string>& tags)
+    {
+      d_zoneData->d_tags = tags;
+    }
     void setPolicyOverridesGettag(bool flag)
     {
       d_zoneData->d_policyOverridesGettag = flag;
index b57bec3f2b1cedbb8d318a2eeb12fbf324e855a7..2ac2026a3e3d56c369035b492fac0cd29bef05be 100644 (file)
@@ -99,70 +99,67 @@ typename C::value_type::second_type constGet(const C& c, const std::string& name
 
 typedef std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string, std::vector<std::pair<int, std::string>>>> rpzOptions_t;
 
-static void parseRPZParameters(rpzOptions_t& have, std::shared_ptr<DNSFilterEngine::Zone>& zone, std::string& polName, boost::optional<DNSFilterEngine::Policy>& defpol, bool& defpolOverrideLocal, uint32_t& maxTTL)
+static void parseRPZParameters(rpzOptions_t& have, RPZTrackerParams& params)
 {
   if (have.count("policyName") != 0) {
-    polName = boost::get<std::string>(have["policyName"]);
+    params.polName = boost::get<std::string>(have["policyName"]);
   }
   if (have.count("defpol") != 0) {
-    defpol = DNSFilterEngine::Policy();
-    defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have["defpol"]);
-    defpol->setName(polName);
-    if (defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
-      if (!defpol->d_custom) {
-        defpol->d_custom = make_unique<DNSFilterEngine::Policy::CustomData>();
+    params.defpol = DNSFilterEngine::Policy();
+    params.defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have["defpol"]);
+    params.defpol->setName(params.polName);
+    if (params.defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
+      params.defcontent = boost::get<string>(have["defcontent"]);
+      if (!params.defpol->d_custom) {
+        params.defpol->d_custom = make_unique<DNSFilterEngine::Policy::CustomData>();
       }
-      defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN,
-                                                         boost::get<string>(have["defcontent"])));
+      params.defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN,
+                                                               params.defcontent));
 
       if (have.count("defttl") != 0) {
-        defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have["defttl"]));
+        params.defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have["defttl"]));
       }
       else {
-        defpol->d_ttl = -1; // get it from the zone
+        params.defpol->d_ttl = -1; // get it from the zone
       }
     }
 
     if (have.count("defpolOverrideLocalData") != 0) {
-      defpolOverrideLocal = boost::get<bool>(have["defpolOverrideLocalData"]);
+      params.defpolOverrideLocal = boost::get<bool>(have["defpolOverrideLocalData"]);
     }
   }
   if (have.count("maxTTL") != 0) {
-    maxTTL = boost::get<uint32_t>(have["maxTTL"]);
+    params.maxTTL = boost::get<uint32_t>(have["maxTTL"]);
   }
   if (have.count("zoneSizeHint") != 0) {
-    auto zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have["zoneSizeHint"]));
-    if (zoneSizeHint > 0) {
-      zone->reserve(zoneSizeHint);
-    }
+    params.zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have["zoneSizeHint"]));
   }
   if (have.count("tags") != 0) {
     const auto& tagsTable = boost::get<std::vector<std::pair<int, std::string>>>(have["tags"]);
     std::unordered_set<std::string> tags;
     for (const auto& tag : tagsTable) {
       tags.insert(tag.second);
+      params.tags.insert(tag.second);
     }
-    zone->setTags(std::move(tags));
   }
   if (have.count("overridesGettag") != 0) {
-    zone->setPolicyOverridesGettag(boost::get<bool>(have["overridesGettag"]));
+    params.defpolOverrideLocal = boost::get<bool>(have["overridesGettag"]);
   }
   if (have.count("extendedErrorCode") != 0) {
     auto code = boost::get<uint32_t>(have["extendedErrorCode"]);
     if (code > std::numeric_limits<uint16_t>::max()) {
       throw std::runtime_error("Invalid extendedErrorCode value " + std::to_string(code) + " in RPZ configuration");
     }
-
-    zone->setExtendedErrorCode(static_cast<uint16_t>(code));
+    params.extendedErrorCode = code;
     if (have.count("extendedErrorExtra") != 0) {
-      zone->setExtendedErrorExtra(boost::get<std::string>(have["extendedErrorExtra"]));
+      params.extendedErrorExtra = boost::get<std::string>(have["extendedErrorExtra"]);
     }
   }
   if (have.count("includeSOA") != 0) {
-    zone->setIncludeSOA(boost::get<bool>(have["includeSOA"]));
+    params.includeSOA = boost::get<bool>(have["includeSOA"]);
   }
   if (have.count("ignoreDuplicates") != 0) {
-    zone->setIgnoreDuplicates(boost::get<bool>(have["ignoreDuplicates"]));
+    params.ignoreDuplicates = boost::get<bool>(have["ignoreDuplicates"]);
   }
 }
 
@@ -271,116 +268,72 @@ static void parseFrameStreamOptions(boost::optional<frameStreamOptions_t> vars,
 }
 #endif /* HAVE_FSTRM */
 
-static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThreads, const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options)
+static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options)
 {
-  boost::optional<DNSFilterEngine::Policy> defpol;
-  bool defpolOverrideLocal = true;
+  RPZTrackerParams params;
+  params.name = zoneName;
+  params.polName = zoneName;
+
   std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
-  TSIGTriplet tt;
-  uint32_t refresh = 0;
-  size_t maxReceivedXFRMBytes = 0;
-  uint16_t axfrTimeout = 20;
-  uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
-  ComboAddress localAddress;
-  std::vector<ComboAddress> primaries;
   if (primaries_.type() == typeid(string)) {
-    primaries.push_back(ComboAddress(boost::get<std::string>(primaries_), 53));
+    params.primaries.emplace_back(boost::get<std::string>(primaries_), 53);
   }
   else {
     for (const auto& primary : boost::get<std::vector<std::pair<int, std::string>>>(primaries_)) {
-      primaries.push_back(ComboAddress(primary.second, 53));
+      params.primaries.emplace_back(primary.second, 53);
     }
   }
 
-  size_t zoneIdx;
-  std::string dumpFile;
-  std::shared_ptr<const SOARecordContent> sr = nullptr;
-
   try {
-    std::string seedFile;
-    std::string polName(zoneName);
-
     if (options) {
       auto& have = *options;
-      parseRPZParameters(have, zone, polName, defpol, defpolOverrideLocal, maxTTL);
+      parseRPZParameters(have, params);
 
-      if (have.count("tsigname")) {
-        tt.name = DNSName(toLower(boost::get<string>(have["tsigname"])));
-        tt.algo = DNSName(toLower(boost::get<string>(have["tsigalgo"])));
-        if (B64Decode(boost::get<string>(have["tsigsecret"]), tt.secret))
+      if (have.count("tsigname") != 0) {
+        params.tsigtriplet.name = DNSName(toLower(boost::get<string>(have["tsigname"])));
+        params.tsigtriplet.algo = DNSName(toLower(boost::get<string>(have["tsigalgo"])));
+        if (B64Decode(boost::get<string>(have["tsigsecret"]), params.tsigtriplet.secret)) {
           throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
+        }
       }
-
-      if (have.count("refresh")) {
-        refresh = boost::get<uint32_t>(have["refresh"]);
-        if (refresh == 0) {
+      if (have.count("refresh") != 0) {
+        params.refreshFromConf = boost::get<uint32_t>(have["refresh"]);
+        if (params.refreshFromConf == 0) {
           SLOG(g_log << Logger::Warning << "rpzPrimary refresh value of 0 ignored" << endl,
                lci.d_slog->info(Logr::Warning, "rpzPrimary refresh value of 0 ignored"));
         }
       }
 
-      if (have.count("maxReceivedMBytes")) {
-        maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
+      if (have.count("maxReceivedMBytes") != 0) {
+        params.maxReceivedMBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
       }
 
-      if (have.count("localAddress")) {
-        localAddress = ComboAddress(boost::get<string>(have["localAddress"]));
+      if (have.count("localAddress") != 0) {
+        params.localAddress = ComboAddress(boost::get<string>(have["localAddress"]));
       }
 
-      if (have.count("axfrTimeout")) {
-        axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have["axfrTimeout"]));
+      if (have.count("axfrTimeout") != 0) {
+        params.xfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have["axfrTimeout"]));
       }
 
-      if (have.count("seedFile")) {
-        seedFile = boost::get<std::string>(have["seedFile"]);
+      if (have.count("seedFile") != 0) {
+        params.seedFileName = boost::get<std::string>(have["seedFile"]);
       }
 
-      if (have.count("dumpFile")) {
-        dumpFile = boost::get<std::string>(have["dumpFile"]);
+      if (have.count("dumpFile") != 0) {
+        params.dumpZoneFileName = boost::get<std::string>(have["dumpFile"]);
       }
     }
 
-    if (localAddress != ComboAddress()) {
+    if (params.localAddress != ComboAddress()) {
       // We were passed a localAddress, check if its AF matches the primaries'
-      for (const auto& primary : primaries) {
-        if (localAddress.sin4.sin_family != primary.sin4.sin_family) {
-          throw PDNSException("Primary address(" + primary.toString() + ") is not of the same Address Family as the local address (" + localAddress.toString() + ").");
+      for (const auto& primary : params.primaries) {
+        if (params.localAddress.sin4.sin_family != primary.sin4.sin_family) {
+          throw PDNSException("Primary address(" + primary.toString() + ") is not of the same Address Family as the local address (" + params.localAddress.toString() + ").");
         }
       }
     }
-
-    DNSName domain(zoneName);
-    zone->setDomain(domain);
-    zone->setName(polName);
-    zoneIdx = lci.dfe.addZone(zone);
-
-    auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(seedFile), "zone", Logging::Loggable(zoneName));
-    if (!seedFile.empty()) {
-      SLOG(g_log << Logger::Info << "Pre-loading RPZ zone " << zoneName << " from seed file '" << seedFile << "'" << endl,
-           log->info(Logr::Info, "Pre-loading RPZ zone from seed file"));
-      try {
-        sr = loadRPZFromFile(seedFile, zone, defpol, defpolOverrideLocal, maxTTL);
-
-        if (zone->getDomain() != domain) {
-          throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
-        }
-
-        if (sr == nullptr) {
-          throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
-        }
-      }
-      catch (const PDNSException& e) {
-        SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << zoneName << " from seed file '" << seedFile << "': " << e.reason << endl,
-             log->error(Logr::Warning, e.reason, "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("PDNSException")));
-        zone->clear();
-      }
-      catch (const std::exception& e) {
-        SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << zoneName << " from seed file '" << seedFile << "': " << e.what() << endl,
-             log->error(Logr::Warning, e.what(), "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("std::exception")));
-        zone->clear();
-      }
-    }
-    lci.rpzRaw.emplace_back(RPZRaw{primaries, zoneName, options});
+    lci.rpzs.emplace_back(params);
   }
   catch (const std::exception& e) {
     SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.what() << endl,
@@ -390,8 +343,6 @@ static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThre
     SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.reason << endl,
          lci.d_slog->error(Logr::Error, e.reason, "Exception configuring 'rpzPrimary'", Logging::Loggable("PDNSException")));
   }
-
-  delayedThreads.rpzPrimaryThreads.emplace_back(RPZTrackerParams{std::move(primaries), std::move(defpol), defpolOverrideLocal, maxTTL, zoneIdx, std::move(tt), maxReceivedXFRMBytes, localAddress, axfrTimeout, refresh, std::move(sr), std::move(dumpFile)});
 }
 
 // A wrapper class that loads the standard Lua defintions into the context, so that we can use things like pdns.A
@@ -422,7 +373,7 @@ public:
   }
 };
 
-void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping& proxyMapping)
+void loadRecursorLuaConfig(const std::string& fname, ProxyMapping& proxyMapping, LuaConfigItems& newLuaConfig)
 {
   LuaConfigItems lci;
   lci.d_slog = g_slog->withName("luaconfig");
@@ -455,39 +406,22 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
   Lua->writeVariable("Policy", pmap);
 
   Lua->writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
-    auto log = lci.d_slog->withValues("file", Logging::Loggable(filename));
-    try {
-      boost::optional<DNSFilterEngine::Policy> defpol;
-      bool defpolOverrideLocal = true;
-      std::string polName("rpzFile");
-      std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
-      uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
-      if (options) {
-        auto& have = *options;
-        parseRPZParameters(have, zone, polName, defpol, defpolOverrideLocal, maxTTL);
-      }
-      SLOG(g_log << Logger::Warning << "Loading RPZ from file '" << filename << "'" << endl,
-           log->info(Logr::Info, "Loading RPZ from file"));
-      zone->setName(polName);
-      loadRPZFromFile(filename, zone, defpol, defpolOverrideLocal, maxTTL);
-      lci.dfe.addZone(std::move(zone));
-      SLOG(g_log << Logger::Warning << "Done loading RPZ from file '" << filename << "'" << endl,
-           log->info(Logr::Info,  "Done loading RPZ from file"));
-      lci.rpzRaw.emplace_back(RPZRaw{{}, filename, options});
-    }
-    catch (const std::exception& e) {
-      SLOG(g_log << Logger::Error << "Unable to load RPZ zone from '" << filename << "': " << e.what() << endl,
-           log->error(Logr::Error, e.what(), "Exception while loading RPZ zone from file"));
+    RPZTrackerParams params;
+    params.name = filename;
+    params.polName = "rpzFile";
+    if (options) {
+      parseRPZParameters(*options, params);
     }
+    lci.rpzs.emplace_back(params);
   });
 
-  Lua->writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options) {
+  Lua->writeFunction("rpzMaster", [&lci](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options) {
     SLOG(g_log << Logger::Warning << "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead" << endl,
          lci.d_slog->info(Logr::Warning, "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead"));
-    rpzPrimary(lci, delayedThreads, primaries_, zoneName, options);
+    rpzPrimary(lci, primaries_, zoneName, options);
   });
-  Lua->writeFunction("rpzPrimary", [&lci, &delayedThreads](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options) {
-    rpzPrimary(lci, delayedThreads, primaries_, zoneName, options);
+  Lua->writeFunction("rpzPrimary", [&lci](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, boost::optional<rpzOptions_t> options) {
+    rpzPrimary(lci, primaries_, zoneName, options);
   });
 
   typedef std::unordered_map<std::string, boost::variant<uint32_t, std::string>> zoneToCacheOptions_t;
@@ -607,14 +541,12 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
                      });
 
   Lua->writeFunction("addTA", [&lci](const std::string& who, const std::string& what) {
-    warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addTA), but dnssec is set to 'off'!");
     DNSName zone(who);
     auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
     lci.dsAnchors[zone].insert(*ds);
   });
 
   Lua->writeFunction("clearTA", [&lci](boost::optional<string> who) {
-    warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearTA), but dnssec is set to 'off'!");
     if (who)
       lci.dsAnchors.erase(DNSName(*who));
     else
@@ -623,7 +555,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
 
   /* Remove in 4.3 */
   Lua->writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
-    warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!");
     SLOG(g_log << Logger::Warning << "addDS is deprecated and will be removed in the future, switch to addTA" << endl,
          lci.d_slog->info(Logr::Warning, "addDS is deprecated and will be removed in the future, switch to addTA"));
     DNSName zone(who);
@@ -635,7 +566,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
   Lua->writeFunction("clearDS", [&lci](boost::optional<string> who) {
     SLOG(g_log << Logger::Warning << "clearDS is deprecated and will be removed in the future, switch to clearTA" << endl,
          lci.d_slog->info(Logr::Warning, "clearDS is deprecated and will be removed in the future, switch to clearTA"));
-    warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!");
     if (who)
       lci.dsAnchors.erase(DNSName(*who));
     else
@@ -643,7 +573,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
   });
 
   Lua->writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) {
-    warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!");
     if (why)
       lci.negAnchors[DNSName(who)] = static_cast<string>(*why);
     else
@@ -651,7 +580,6 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
   });
 
   Lua->writeFunction("clearNTA", [&lci](boost::optional<string> who) {
-    warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!");
     if (who)
       lci.negAnchors.erase(DNSName(*who));
     else
@@ -663,10 +591,8 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
     if (interval) {
       realInterval = static_cast<uint32_t>(*interval);
     }
-    warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!");
     lci.trustAnchorFileInfo.fname = fnamearg;
     lci.trustAnchorFileInfo.interval = realInterval;
-    updateTrustAnchorsFromFile(fnamearg, lci.dsAnchors, lci.d_slog);
   });
 
   Lua->writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
@@ -876,7 +802,7 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
 
   try {
     Lua->executeCode(ifs);
-    g_luaconfs.setState(std::move(lci));
+    newLuaConfig = lci;
   }
   catch (const LuaContext::ExecutionErrorException& e) {
     SLOG(g_log << Logger::Error << "Unable to load Lua script from '" + fname + "': ",
@@ -902,25 +828,3 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
     throw;
   }
 }
-
-void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation)
-{
-  for (const auto& rpzPrimary : delayedThreads.rpzPrimaryThreads) {
-    try {
-      // The get calls all return a value object here. That is essential, since we want copies so that RPZIXFRTracker gets values
-      // with the proper lifetime.
-      std::thread theThread(RPZIXFRTracker, rpzPrimary, generation);
-      theThread.detach();
-    }
-    catch (const std::exception& e) {
-      SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.what() << endl,
-           g_slog->withName("rpz")->error(Logr::Error, e.what(), "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("std::exception")));
-      exit(1);
-    }
-    catch (const PDNSException& e) {
-      SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.reason << endl,
-           g_slog->withName("rpz")->error(Logr::Error, e.reason, "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("PDNSException")));
-      exit(1);
-    }
-  }
-}
index abed5c4196d26a43e61a38e7ed20553449f58c83..7e595715b00c09f4cf7d1f0b2329325af124c307 100644 (file)
@@ -101,20 +101,13 @@ using ProxyMapping = NetmaskTree<ProxyByTableValue, Netmask>;
 
 using rpzOptions_t = std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string, std::vector<std::pair<int, std::string>>>>;
 
-struct RPZRaw
-{
-  std::vector<ComboAddress> addresses;
-  std::string name;
-  boost::optional<rpzOptions_t> options;
-};
-
 class LuaConfigItems
 {
 public:
   LuaConfigItems();
   SortList sortlist;
   DNSFilterEngine dfe;
-  vector<RPZRaw> rpzRaw;
+  vector<RPZTrackerParams> rpzs;
   TrustAnchorFileInfo trustAnchorFileInfo; // Used to update the Trust Anchors from file periodically
   map<DNSName, dsset_t> dsAnchors;
   map<DNSName, std::string> negAnchors;
@@ -135,10 +128,4 @@ public:
 
 extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
 
-struct luaConfigDelayedThreads
-{
-  std::vector<RPZTrackerParams> rpzPrimaryThreads;
-};
-
-void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping&);
-void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation);
+void loadRecursorLuaConfig(const std::string& fname, ProxyMapping&, LuaConfigItems& newConfig);
index 2bfc587aa81490b89d25458d80d1bca6bef0b5ec..5ff54beb9bf21c6a30019e7d6649f9dc79476e63 100644 (file)
@@ -42,6 +42,8 @@
 #include "settings/cxxsettings.hh"
 #include "json.hh"
 #include "rec-system-resolve.hh"
+#include "root-dnssec.hh"
+
 #ifdef NOD_ENABLED
 #include "nod.hh"
 #endif /* NOD_ENABLED */
@@ -2079,12 +2081,13 @@ static int serviceMain(Logr::log_t log)
   }
   g_maxCacheEntries = ::arg().asNum("max-cache-entries");
 
-  luaConfigDelayedThreads delayedLuaThreads;
   try {
     ProxyMapping proxyMapping;
-    loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping);
+    LuaConfigItems lci;
+    loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci);
     // Initial proxy mapping
     g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique<ProxyMapping>(proxyMapping);
+    activateLuaConfig(lci);
   }
   catch (PDNSException& e) {
     SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl,
@@ -2257,8 +2260,8 @@ static int serviceMain(Logr::log_t log)
     return ret;
   }
 
-  startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
-  delayedLuaThreads.rpzPrimaryThreads.clear(); // no longer needed
+  auto lci = g_luaconfs.getCopy();
+  activateLuaConfig(lci);
 
   RecThreadInfo::makeThreadPipes(log);
 
@@ -2904,17 +2907,16 @@ static pair<int, bool> doYamlConfig(Logr::log_t startupLog, int argc, char* argv
     ::arg().parse(argc, argv);
     pdns::rust::settings::rec::Recursorsettings settings;
     pdns::settings::rec::oldStyleSettingsToBridgeStruct(settings);
-    luaConfigDelayedThreads delayedLuaThreads;
     ProxyMapping proxyMapping;
+    LuaConfigItems lci;
     try {
-      loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping);
+      loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci);
     }
     catch (PDNSException& e) {
       SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl,
            startupLog->error(Logr::Error, e.reason, "Cannot load Lua configuration"));
     }
-    auto luaConfig = g_luaconfs.getLocal();
-    pdns::settings::rec::fromLuaConfigToBridgeStruct(luaConfig, proxyMapping, settings);
+    pdns::settings::rec::fromLuaConfigToBridgeStruct(lci, proxyMapping, settings);
     auto yaml = settings.to_yaml_string();
     cout << yaml << endl;
   }
@@ -3335,3 +3337,128 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q
 
   return res;
 }
+
+static void startLuaConfigDelayedThreads(const vector<RPZTrackerParams>& rpzs, uint64_t generation)
+{
+  for (const auto& rpzPrimary : rpzs) {
+    if (rpzPrimary.primaries.empty()) {
+      continue;
+    }
+    try {
+      // The get calls all return a value object here. That is essential, since we want copies so that RPZIXFRTracker gets values
+      // with the proper lifetime.
+      std::thread theThread(RPZIXFRTracker, rpzPrimary, generation);
+      theThread.detach();
+    }
+    catch (const std::exception& e) {
+      SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.what() << endl,
+           g_slog->withName("rpz")->error(Logr::Error, e.what(), "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("std::exception")));
+      exit(1);
+    }
+    catch (const PDNSException& e) {
+      SLOG(g_log << Logger::Error << "Problem starting RPZIXFRTracker thread: " << e.reason << endl,
+           g_slog->withName("rpz")->error(Logr::Error, e.reason, "Exception starting RPZIXFRTracker thread", "exception", Logging::Loggable("PDNSException")));
+      exit(1);
+    }
+  }
+}
+
+static void activateRPZFile(const RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr<DNSFilterEngine::Zone>& zone)
+{
+  auto log = lci.d_slog->withValues("file", Logging::Loggable(params.name));
+
+  zone->setName(params.polName);
+  try {
+    SLOG(g_log << Logger::Warning << "Loading RPZ from file '" << params.name << "'" << endl,
+         log->info(Logr::Info, "Loading RPZ from file"));
+    loadRPZFromFile(params.name, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
+    SLOG(g_log << Logger::Warning << "Done loading RPZ from file '" << params.name << "'" << endl,
+         log->info(Logr::Info,  "Done loading RPZ from file"));
+  }
+  catch (const std::exception& e) {
+    SLOG(g_log << Logger::Error << "Unable to load RPZ zone from '" << params.name << "': " << e.what() << endl,
+         log->error(Logr::Error, e.what(), "Exception while loading RPZ zone from file"));
+  }
+}
+
+static void activateRPZPrimary(RPZTrackerParams& params, LuaConfigItems& lci, shared_ptr<DNSFilterEngine::Zone>& zone, const DNSName& domain)
+{
+  auto log = lci.d_slog->withValues("seedfile", Logging::Loggable(params.seedFileName), "zone", Logging::Loggable(params.name));
+
+  if (!params.seedFileName.empty()) {
+    SLOG(g_log << Logger::Info << "Pre-loading RPZ zone " << params.name << " from seed file '" << params.seedFileName << "'" << endl,
+         log->info(Logr::Info, "Pre-loading RPZ zone from seed file"));
+    try {
+      params.soaRecordContent = loadRPZFromFile(params.seedFileName, zone, params.defpol, params.defpolOverrideLocal, params.maxTTL);
+
+      if (zone->getDomain() != domain) {
+        throw PDNSException("The RPZ zone " + params.name + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
+      }
+
+      if (params.soaRecordContent == nullptr) {
+        throw PDNSException("The RPZ zone " + params.name + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
+        }
+      }
+      catch (const PDNSException& e) {
+        SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << params.name << " from seed file '" << params.seedFileName << "': " << e.reason << endl,
+             log->error(Logr::Warning, e.reason, "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("PDNSException")));
+        zone->clear();
+      }
+      catch (const std::exception& e) {
+        SLOG(g_log << Logger::Warning << "Unable to pre-load RPZ zone " << params.name << " from seed file '" << params.seedFileName << "': " << e.what() << endl,
+             log->error(Logr::Warning, e.what(), "Exception while pre-loading RPZ zone", "exception", Logging::Loggable("std::exception")));
+        zone->clear();
+      }
+    }
+}
+
+static void activateRPZs(LuaConfigItems& lci)
+{
+  for (auto& params : lci.rpzs) {
+    auto zone = std::make_shared<DNSFilterEngine::Zone>();
+    if (params.zoneSizeHint != 0) {
+      zone->reserve(params.zoneSizeHint);
+    }
+    if (!params.tags.empty()) {
+      zone->setTags(params.tags);
+    }
+    zone->setPolicyOverridesGettag(params.defpolOverrideLocal);
+    if (params.extendedErrorCode != std::numeric_limits<uint32_t>::max()) {
+      zone->setExtendedErrorCode(params.extendedErrorCode);
+      if (!params.extendedErrorExtra.empty()) {
+        zone->setExtendedErrorExtra(params.extendedErrorExtra);
+      }
+    }
+    zone->setIncludeSOA(params.includeSOA);
+    zone->setIgnoreDuplicates(params.ignoreDuplicates);
+
+    if (params.primaries.empty()) {
+      activateRPZFile(params, lci, zone);
+      lci.dfe.addZone(std::move(zone));
+   }
+    else {
+      DNSName domain(params.name);
+      zone->setDomain(domain);
+      zone->setName(params.polName);
+      params.zoneIdx = lci.dfe.addZone(zone);
+      activateRPZPrimary(params, lci, zone, domain);
+    }
+  }
+  startLuaConfigDelayedThreads(lci.rpzs, lci.generation);
+}
+
+void activateLuaConfig(LuaConfigItems& lci)
+{
+  if (!lci.trustAnchorFileInfo.fname.empty()) {
+    warnIfDNSSECDisabled("Warning: reading Trust Anchors from file, but dnssec is set to 'off'!");
+    updateTrustAnchorsFromFile(lci.trustAnchorFileInfo.fname, lci.dsAnchors, lci.d_slog);
+  }
+  if (lci.dsAnchors.size() > rootDSs.size()) {
+     warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC, but dnssec is set to 'off'!");
+  }
+  if (!lci.negAnchors.empty()) {
+     warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC, but dnssec is set to 'off'!");
+  }
+  activateRPZs(lci);
+  g_luaconfs.setState(std::move(lci));
+}
index 98c6898696f2841c73ed9bf0a2771421fef9654a..fd51919d412f48e700b4204169b86c006d88cc08 100644 (file)
@@ -620,6 +620,7 @@ void handleNewTCPQuestion(int fileDesc, FDMultiplexer::funcparam_t&);
 
 void makeUDPServerSockets(deferredAdd_t& deferredAdds, Logr::log_t);
 string doTraceRegex(FDWrapper file, vector<string>::const_iterator begin, vector<string>::const_iterator end);
+void activateLuaConfig(LuaConfigItems& lci);
 
 #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
 #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10"
index 8a3af52076cfa16fc7554af273bbc511bdfa1bb1..fe95ee0558c11c63abaad3f9676912725f9a9615 100644 (file)
@@ -2138,10 +2138,10 @@ static RecursorControlChannel::Answer luaconfig(T begin, T end)
     ::arg().set("lua-config-file") = *begin;
   }
   try {
-    luaConfigDelayedThreads delayedLuaThreads;
     ProxyMapping proxyMapping;
-    loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping);
-    startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
+    LuaConfigItems lci;
+    loadRecursorLuaConfig(::arg()["lua-config-file"], proxyMapping, lci);
+    activateLuaConfig(lci);
     broadcastFunction([=] { return pleaseSupplantProxyMapping(proxyMapping); });
     g_log << Logger::Warning << "Reloaded Lua configuration file '" << ::arg()["lua-config-file"] << "', requested via control channel" << endl;
     return {0, "Reloaded Lua configuration file '" + ::arg()["lua-config-file"] + "'\n"};
index 4b28464edb355068f9a845021b797db23f1e0292..1870a4f494c63db348247c6717185daf6d2cb6cb 100644 (file)
@@ -454,7 +454,7 @@ static void preloadRPZFIle(RPZTrackerParams& params, const DNSName& zoneName, st
     std::shared_ptr<DNSFilterEngine::Zone> newZone = std::make_shared<DNSFilterEngine::Zone>(*oldZone);
     for (const auto& primary : params.primaries) {
       try {
-        params.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.tsigtriplet, params.maxReceivedBytes, params.localAddress, params.xfrTimeout);
+        params.soaRecordContent = loadRPZFromServer(logger, primary, zoneName, newZone, params.defpol, params.defpolOverrideLocal, params.maxTTL, params.tsigtriplet, params.maxReceivedMBytes, params.localAddress, params.xfrTimeout);
         newZone->setSerial(params.soaRecordContent->d_st.serial);
         newZone->setRefresh(params.soaRecordContent->d_st.refresh);
         refresh = std::max(params.refreshFromConf != 0 ? params.refreshFromConf : newZone->getRefresh(), 1U);
@@ -543,7 +543,7 @@ static bool RPZTrackerIteration(RPZTrackerParams& params, const DNSName& zoneNam
     }
 
     try {
-      deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedBytes);
+      deltas = getIXFRDeltas(primary, zoneName, dnsRecord, params.xfrTimeout, true, params.tsigtriplet, &local, params.maxReceivedMBytes);
 
       /* no need to try another primary */
       break;
index 57fddce8af4c8c0f126ccbfdd7fb257c26425897..3e94acde492b0522d5436667875922c5abb23299 100644 (file)
@@ -29,18 +29,28 @@ extern bool g_logRPZChanges;
 // Please make sure that the struct below only contains value types since they are used as parameters in a thread ct
 struct RPZTrackerParams
 {
+  std::string name;
   std::vector<ComboAddress> primaries;
   boost::optional<DNSFilterEngine::Policy> defpol;
-  bool defpolOverrideLocal;
-  uint32_t maxTTL;
-  size_t zoneIdx;
+  std::string defcontent;
+  bool defpolOverrideLocal{true};
+  uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
+  size_t zoneIdx{0};
   TSIGTriplet tsigtriplet;
-  size_t maxReceivedBytes;
+  size_t maxReceivedMBytes{0};
   ComboAddress localAddress;
-  uint16_t xfrTimeout;
-  uint32_t refreshFromConf;
+  uint16_t xfrTimeout{20};
+  uint32_t refreshFromConf{0};
   std::shared_ptr<const SOARecordContent> soaRecordContent;
+  std::string seedFileName;
   std::string dumpZoneFileName;
+  std::string polName;
+  size_t zoneSizeHint{0};
+  std::unordered_set<std::string> tags;
+  uint32_t extendedErrorCode{std::numeric_limits<uint32_t>::max()};
+  std::string extendedErrorExtra;
+  bool includeSOA{false};
+  bool ignoreDuplicates{false};
 };
 
 std::shared_ptr<const SOARecordContent> loadRPZFromFile(const std::string& fname, const std::shared_ptr<DNSFilterEngine::Zone>& zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL);
index cb0f9a086bbab999e040c0874de9b5c8bd89403b..d327820f5b43575f2591a0259ba496c3f7a404e5 100644 (file)
@@ -52,6 +52,6 @@ void readYamlAllowFromFile(const std::string& filename, ::rust::Vec<::rust::Stri
 void readYamlAllowNotifyForFile(const std::string& filename, ::rust::Vec<::rust::String>& vec, Logr::log_t log);
 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);
+void fromLuaConfigToBridgeStruct(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 e2b49b992b4c21a6d33587f5e0dcc8a6eb89a26f..8a12eeffd3ab2cd3421fc27dde60436244ed1069 100644 (file)
@@ -37,6 +37,7 @@
 #include "root-dnssec.hh"
 #include "dnsrecords.hh"
 #include "base64.hh"
+#include "validate-recursor.hh"
 
 ::rust::Vec<::rust::String> pdns::settings::rec::getStrings(const std::string& name)
 {
@@ -710,11 +711,11 @@ std::string pdns::settings::rec::defaultsToYaml()
 
 namespace
 {
-void fromLuaToRust(LocalStateHolder<LuaConfigItems>& luaConfig, pdns::rust::settings::rec::Dnssec& dnssec)
+void fromLuaToRust(const 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) {
+  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();
@@ -725,7 +726,7 @@ void fromLuaToRust(LocalStateHolder<LuaConfigItems>& luaConfig, pdns::rust::sett
     pdns::rust::settings::rec::TrustAnchor trustAnchor{anchors.first.toString(), dsRecords};
     dnssec.trustanchors.emplace_back(trustAnchor);
   }
-  for (const auto& anchors : luaConfig->negAnchors) {
+  for (const auto& anchors : luaConfig.negAnchors) {
     pdns::rust::settings::rec::NegativeTrustAnchor negtrustAnchor{anchors.first.toString(), anchors.second};
     dnssec.negative_trustanchors.emplace_back(negtrustAnchor);
   }
@@ -779,37 +780,45 @@ void fromLuaToRust(const FrameStreamExportConfig& fsc, pdns::rust::settings::rec
   dnstap.reopenInterval = fsc.reopenInterval;
 }
 
-
-template <typename T>
-void setIfAvailable(const rpzOptions_t& table, T& var, const std::string& name)
+void assign(pdns::rust::settings::rec::TSIGTriplet& var, const TSIGTriplet& tsig)
 {
-  if (table.count(name) != 0) {
-    var = boost::get<T>(table.at(name));
-  }
+  var.name = tsig.name.empty() ? "" : tsig.name.toStringNoDot();
+  var.algo = tsig.algo.empty() ? "" : tsig.algo.toStringNoDot();
+  var.secret = Base64Encode(tsig.secret);
 }
 
-void setIfAvailable(const rpzOptions_t& table, rust::string& var, const std::string& name)
+void assign(TSIGTriplet& var, const pdns::rust::settings::rec::TSIGTriplet& tsig)
 {
-  if (table.count(name) != 0) {
-    var = boost::get<std::string>(table.at(name));
-  }
+  var.name = DNSName(std::string(tsig.name));
+  var.algo = DNSName(std::string(tsig.algo));
+  B64Decode(std::string(tsig.secret), var.secret);
 }
 
-void setIfAvailable(const rpzOptions_t& table, pdns::rust::settings::rec::TSIGTriplet& var, const std::string& name)
+std::string cvt(DNSFilterEngine::PolicyKind kind)
 {
-  if (table.count(name) != 0) {
-    var.name = boost::get<std::string>(table.at("tsigname"));
-    var.algo = boost::get<std::string>(table.at("tsigalgo"));
-    var.secret = boost::get<std::string>(table.at("tsigsecret"));
+  switch (kind) {
+  case DNSFilterEngine::PolicyKind::NoAction:
+    return "NoAction";
+  case DNSFilterEngine::PolicyKind::Drop:
+    return "Drop";
+  case DNSFilterEngine::PolicyKind::NXDOMAIN:
+    return "NXDOMAIN";
+  case DNSFilterEngine::PolicyKind::NODATA:
+    return "NODATA";
+  case DNSFilterEngine::PolicyKind::Truncate:
+    return "Truncate";
+  case DNSFilterEngine::PolicyKind::Custom:
+    return "Custom";
   }
 }
-void fromLuaToRust(const vector<RPZRaw>& rpzs, pdns::rust::settings::rec::Recursor& rec)
+
+void fromLuaToRust(const vector<RPZTrackerParams>& rpzs, pdns::rust::settings::rec::Recursor& rec)
 {
   for (const auto& rpz : rpzs) {
     pdns::rust::settings::rec::RPZ rustrpz{
       .defpolOverrideLocalData = true,
       .defttl = std::numeric_limits<uint32_t>::max(),
-      .extendedErrorCode = 0,
+      .extendedErrorCode = std::numeric_limits<uint32_t>::max(),
       .includeSOA = false,
       .ignoreDuplicates = false,
       .maxTTL = std::numeric_limits<uint32_t>::max(),
@@ -819,37 +828,37 @@ void fromLuaToRust(const vector<RPZRaw>& rpzs, pdns::rust::settings::rec::Recurs
       .maxReceivedMBytes = 0,
       .axfrTimeout = 20};
 
-    for (const auto& address : rpz.addresses) {
+    for (const auto& address : rpz.primaries) {
       rustrpz.addresses.emplace_back(address.toStringWithPort());
     }
     rustrpz.name = rpz.name;
-    if (rpz.options) {
-      setIfAvailable(*rpz.options, rustrpz.defcontent, "defcontent");
-      setIfAvailable(*rpz.options, rustrpz.defpol, "defpol");
-      setIfAvailable(*rpz.options, rustrpz.defpolOverrideLocalData, "defpolOverrideLocalData");
-      setIfAvailable(*rpz.options, rustrpz.defttl, "defttl");
-      setIfAvailable(*rpz.options, rustrpz.extendedErrorCode, "extendedErrorCode");
-      setIfAvailable(*rpz.options, rustrpz.extendedErrorExtra, "extendedErrorExtra");
-      setIfAvailable(*rpz.options, rustrpz.includeSOA, "includeSOA");
-      setIfAvailable(*rpz.options, rustrpz.ignoreDuplicates, "ignoreDuplicates");
-      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("tags"));
-        for (const auto& tag : tags) {
-          rustrpz.tags.emplace_back(tag.second);
-        }
-      }
-      setIfAvailable(*rpz.options, rustrpz.overridesGettag, "overridesGettag");
-      setIfAvailable(*rpz.options, rustrpz.zoneSizeHint, "zoneSizeHint");
-      setIfAvailable(*rpz.options, rustrpz.tsig, "tsig");
-      setIfAvailable(*rpz.options, rustrpz.refresh, "refresh");
-      setIfAvailable(*rpz.options, rustrpz.maxReceivedMBytes, "maxReceivedMBytes");
-      setIfAvailable(*rpz.options, rustrpz.localAddress, "localAddress");
-      setIfAvailable(*rpz.options, rustrpz.axfrTimeout, "axfrTimeout");
-      setIfAvailable(*rpz.options, rustrpz.dumpFile, "dumpFile");
-      setIfAvailable(*rpz.options, rustrpz.seedFile, "seedFile");
+    rustrpz.defcontent = rpz.defcontent;
+    if (rpz.defpol) {
+      rustrpz.defpol = cvt(rpz.defpol->d_kind);
+      rustrpz.defttl = rpz.defpol->d_ttl;
+    }
+    rustrpz.defpolOverrideLocalData = rpz.defpolOverrideLocal;
+    rustrpz.extendedErrorCode = rpz.extendedErrorCode;
+    rustrpz.extendedErrorExtra = rpz.extendedErrorExtra;
+    rustrpz.includeSOA = rpz.includeSOA;
+    rustrpz.ignoreDuplicates = rpz.ignoreDuplicates;
+    rustrpz.maxTTL = rpz.maxTTL;
+    rustrpz.policyName = rpz.polName;
+    for (const auto& tag : rpz.tags) {
+      rustrpz.tags.emplace_back(tag);
     }
+    rustrpz.overridesGettag = rpz.defpolOverrideLocal;
+    rustrpz.zoneSizeHint = rpz.zoneSizeHint;
+    assign(rustrpz.tsig, rpz.tsigtriplet);
+    rustrpz.refresh = rpz.refreshFromConf;
+    rustrpz.maxReceivedMBytes = rpz.maxReceivedMBytes;
+    if (rpz.localAddress != ComboAddress()) {
+      rustrpz.localAddress = rpz.localAddress.toString();
+    }
+    rustrpz.axfrTimeout = rpz.xfrTimeout;
+    rustrpz.dumpFile = rpz.dumpZoneFileName;
+    rustrpz.seedFile = rpz.seedFileName;
+
     rec.rpzs.emplace_back(rustrpz);
   }
 }
@@ -994,34 +1003,36 @@ void fromLuaToRust(const SortList& arg, pdns::rust::settings::rec::Recursor& rec
 }
 } // namespace
 
-void pdns::settings::rec::fromLuaConfigToBridgeStruct(LocalStateHolder<LuaConfigItems>& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings)
+void pdns::settings::rec::fromLuaConfigToBridgeStruct(LuaConfigItems& luaConfig, const ProxyMapping& proxyMapping, pdns::rust::settings::rec::Recursorsettings& settings)
 {
 
   fromLuaToRust(luaConfig, settings.dnssec);
-  if (luaConfig->protobufExportConfig.enabled) {
+  settings.logging.protobuf_mask_v4 = luaConfig.protobufMaskV4;
+  settings.logging.protobuf_mask_v6 = luaConfig.protobufMaskV6;
+  if (luaConfig.protobufExportConfig.enabled) {
     pdns::rust::settings::rec::ProtobufServer pbServer;
-    fromLuaToRust(luaConfig->protobufExportConfig, pbServer);
+    fromLuaToRust(luaConfig.protobufExportConfig, pbServer);
     settings.logging.protobuf_servers.emplace_back(pbServer);
   }
-  if (luaConfig->outgoingProtobufExportConfig.enabled) {
+  if (luaConfig.outgoingProtobufExportConfig.enabled) {
     pdns::rust::settings::rec::ProtobufServer pbServer;
-    fromLuaToRust(luaConfig->outgoingProtobufExportConfig, pbServer);
+    fromLuaToRust(luaConfig.outgoingProtobufExportConfig, pbServer);
     settings.logging.outgoing_protobuf_servers.emplace_back(pbServer);
   }
-  if (luaConfig->frameStreamExportConfig.enabled) {
+  if (luaConfig.frameStreamExportConfig.enabled) {
     pdns::rust::settings::rec::DNSTapFrameStreamServer dnstap;
-    fromLuaToRust(luaConfig->frameStreamExportConfig, dnstap);
+    fromLuaToRust(luaConfig.frameStreamExportConfig, dnstap);
     settings.logging.dnstap_framestream_servers.emplace_back(dnstap);
   }
-  if (luaConfig->nodFrameStreamExportConfig.enabled) {
+  if (luaConfig.nodFrameStreamExportConfig.enabled) {
     pdns::rust::settings::rec::DNSTapNODFrameStreamServer dnstap;
-    fromLuaToRust(luaConfig->nodFrameStreamExportConfig, 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(luaConfig.rpzs, settings.recursor);
+  fromLuaToRust(luaConfig.sortlist, settings.recursor);
+  fromLuaToRust(luaConfig.ztcConfigs, settings.recordcache);
+  fromLuaToRust(luaConfig.allowAdditionalQTypes, settings.recursor);
   fromLuaToRust(proxyMapping, settings.incoming);
 }
 
@@ -1105,78 +1116,75 @@ void fromRustToLuaConfig(const pdns::rust::settings::rec::DNSTapNODFrameStreamSe
   exp.reopenInterval = dnstap.reopenInterval;
 }
 
+DNSFilterEngine::PolicyKind cvtKind(const std::string& kind)
+{
+  static const std::map<std::string, DNSFilterEngine::PolicyKind> map = {
+    { "Custom", DNSFilterEngine::PolicyKind::Custom },
+    { "Drop", DNSFilterEngine::PolicyKind::Drop },
+    { "NoAction", DNSFilterEngine::PolicyKind::NoAction },
+    { "NODATA", DNSFilterEngine::PolicyKind::NODATA },
+    { "NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN },
+    { "Truncate", DNSFilterEngine::PolicyKind::Truncate }
+  };
+  if (auto iter = map.find(kind); iter != map.end()) {
+    return iter->second;
+  }
+  throw runtime_error("PolicyKind '" + kind + "' unknown");
+}
+
 
 void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::RPZ>& rpzs, LuaConfigItems& luaConfig)
 {
   for (const auto& rpz : rpzs) {
-    RPZRaw rpzRaw;
+    RPZTrackerParams params;
     for (const auto& address : rpz.addresses) {
-      rpzRaw.addresses.emplace_back(std::string(address));
+      params.primaries.emplace_back(std::string(address));
     }
-    rpzRaw.name = std::string(rpz.name);
-    rpzOptions_t options;
+    params.name = std::string(rpz.name);
+    params.polName = std::string(rpz.policyName);
+
+    if (!rpz.defpol.empty()) {
+      params.defpol = DNSFilterEngine::Policy();
+      params.defcontent = std::string(rpz.defcontent);
+      params.defpol->d_kind = cvtKind(std::string(rpz.defpol));
+      params.defpol->setName(params.polName);
+      if (params.defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
+        if (!params.defpol->d_custom) {
+          params.defpol->d_custom = make_unique<DNSFilterEngine::Policy::CustomData>();
+        }
+        params.defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN,
+                                                                 std::string(params.defcontent)));
 
-    auto setIfNonDefault = [&options](const rust::String& value, const string& name)
-    {
-      if (!value.empty()) {
-        options[name] = std::string(value);
+        if (rpz.defttl != std::numeric_limits<uint32_t>::max()) {
+          params.defpol->d_ttl = static_cast<int>(rpz.defttl);
+        }
+        else {
+          params.defpol->d_ttl = -1; // get it from the zone
+        }
       }
-    };
-    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;
+    params.defpolOverrideLocal = rpz.defpolOverrideLocalData;
+    params.extendedErrorCode = rpz.extendedErrorCode;
+    params.extendedErrorExtra = std::string(rpz.extendedErrorExtra);
+    params.includeSOA = rpz.includeSOA;
+    params.ignoreDuplicates = rpz.ignoreDuplicates;
+    params.maxTTL = rpz.maxTTL;
+
     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;
+      params.tags.emplace(std::string(tag));
     }
-    setIfNonDefault(rpz.tsig.name, "tsigname");
-    setIfNonDefault(rpz.tsig.algo, "tsigalgo");
-    setIfNonDefault(rpz.tsig.secret, "tsigsecret");
-    if (rpz.refresh != 0) {
-        options["refresh"] = rpz.refresh;
+    params.defpolOverrideLocal = rpz.overridesGettag;
+    params.zoneSizeHint = rpz.zoneSizeHint;
+    assign(params.tsigtriplet, rpz.tsig);
+    params.refreshFromConf = rpz.refresh;
+    params.maxReceivedMBytes = rpz.maxReceivedMBytes;
+    if (!rpz.localAddress.empty()) {
+      params.localAddress = ComboAddress(std::string(rpz.localAddress));
     }
-    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);
+    params.xfrTimeout = rpz.axfrTimeout;
+    params.dumpZoneFileName = std::string(rpz.dumpFile);
+    params.seedFileName = std::string(rpz.seedFile);
+    luaConfig.rpzs.emplace_back(params);
   }
 }
 
@@ -1251,6 +1259,8 @@ void fromRustToLuaConfig(const rust::Vec<pdns::rust::settings::rec::ProxyMapping
 void pdns::settings::rec::fromBridgeStructToLuaConfig(const pdns::rust::settings::rec::Recursorsettings& settings, LuaConfigItems& luaConfig, ProxyMapping& proxyMapping)
 {
   fromRustToLuaConfig(settings.dnssec, luaConfig);
+  luaConfig.protobufMaskV4 = settings.logging.protobuf_mask_v4;
+  luaConfig.protobufMaskV6 = settings.logging.protobuf_mask_v6;
   if (!settings.logging.protobuf_servers.empty()) {
     fromRustToLuaConfig(settings.logging.protobuf_servers.at(0), luaConfig.protobufExportConfig);
   }
@@ -1269,3 +1279,4 @@ void pdns::settings::rec::fromBridgeStructToLuaConfig(const pdns::rust::settings
   fromRustToLuaConfig(settings.recursor.allowed_additional_qtypes, luaConfig.allowAdditionalQTypes);
   fromRustToLuaConfig(settings.incoming.proxymappings, proxyMapping);
 }
+
index 53052e40b5170957050d88ab2139f30e98b67600..5807bd6de705b5bac047e4d559f0002c1c289138 100644 (file)
@@ -147,7 +147,7 @@ pub struct RPZ {
     defpolOverrideLocalData: bool,
     #[serde(default = "crate::U32::<{u32::MAX}>::value", skip_serializing_if = "crate::U32::<{u32::MAX}>::is_equal")]
     defttl: u32,
-    #[serde(default, skip_serializing_if = "crate::is_default")]
+    #[serde(default = "crate::U32::<{u32::MAX}>::value", skip_serializing_if = "crate::U32::<{u32::MAX}>::is_equal")]
     extendedErrorCode: u32,
     #[serde(default, skip_serializing_if = "crate::is_default")]
     extendedErrorExtra: String,
index 5e91bd3770a07fd37d086e78c842eba456dad59a..63d59ca00fc09913d0cf8e89daeffe0e2ae5ce69 100644 (file)
@@ -3256,6 +3256,30 @@ XXX
         'default' : '',
         'help' : 'XXX',
         'doc' : ''',
+XXX
+        ''',
+        'skip-old' : True,
+        'versionadded': '5.1.0',
+    },
+    {
+        'name' : 'protobuf_mask_v4',
+        'section' : 'logging',
+        'type' : LType.Uint64,
+        'default' : '32',
+        'help' : 'XXX',
+        'doc' : ''',
+XXX
+        ''',
+        'skip-old' : True,
+        'versionadded': '5.1.0',
+    },
+    {
+        'name' : 'protobuf_mask_v6',
+        'section' : 'logging',
+        'type' : LType.Uint64,
+        'default' : '128',
+        'help' : 'XXX',
+        'doc' : ''',
 XXX
         ''',
         'skip-old' : True,
index 462b2a61cfd32a541b1a44c7712ae5f08f775c0d..2470fae8fb7022632cb74446a66a7715213660e6 100644 (file)
@@ -647,7 +647,7 @@ BOOST_AUTO_TEST_CASE(test_yaml_defaults_rpz)
   BOOST_CHECK_EQUAL(std::string(settings.recursor.rpzs[0].defpol), "");
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].defpolOverrideLocalData, true);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].defttl, -1U);
-  BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].extendedErrorCode, 0U);
+  BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].extendedErrorCode, -1U);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].extendedErrorExtra, "");
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].includeSOA, false);
   BOOST_CHECK_EQUAL(settings.recursor.rpzs[0].ignoreDuplicates, false);
@@ -965,11 +965,11 @@ recordcache:
 
   // 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();
+  //GlobalStateHolder<LuaConfigItems> gsluaConfig;
+  //gsluaConfig.setState(luaConfig);
+  //LuaConfigItems local; // = gsluaConfig.getCopy();
   try {
-    pdns::settings::rec::fromLuaConfigToBridgeStruct(local, proxyMapping, newsettings);
+    pdns::settings::rec::fromLuaConfigToBridgeStruct(luaConfig, proxyMapping, newsettings);
   }
   catch (std::exception& e) {
     cerr << e.what() << endl;