]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add `clearExistingEntries` to `SetExtendedDNSError`
authorEnsar Sarajčić <dev@ensarsarajcic.com>
Mon, 29 Dec 2025 10:36:58 +0000 (11:36 +0100)
committerEnsar Sarajčić <dev@ensarsarajcic.com>
Mon, 29 Dec 2025 10:47:54 +0000 (11:47 +0100)
Signed-off-by: Ensar Sarajčić <dev@ensarsarajcic.com>
pdns/dnsdistdist/dnsdist-actions-definitions.yml
pdns/dnsdistdist/dnsdist-actions-factory.cc
pdns/dnsdistdist/dnsdist-console-completion.cc
pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc
pdns/dnsdistdist/dnsdist-response-actions-definitions.yml
pdns/dnsdistdist/docs/reference/actions.rst

index bb842a73d426c7cb03d0cfe572c011e783d7d51d..2c90a4fc106302b61f1f57dea2766d4ab68fefde 100644 (file)
@@ -1,15 +1,4 @@
 ---
-- name: "AddExtendedDNSError"
-  description: "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action"
-  parameters:
-    - name: "info_code"
-      type: "u16"
-      description: "The EDNS Extended DNS Error code"
-    - name: "extra_text"
-      type: "String"
-      default: ""
-      optional: false
-      description: "The optional EDNS Extended DNS Error extra text"
 - name: "allow"
   description: "Let these packets go through"
 - name: "continue"
@@ -360,7 +349,7 @@ are processed after this action"
       type: "String"
       description: "The EDNS0 option raw content"
 - name: "SetExtendedDNSError"
-  description: "Set an Extended DNS Error status that will be set to the response corresponding to the current query. This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action"
+  description: "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action"
   parameters:
     - name: "info_code"
       type: "u16"
@@ -370,6 +359,11 @@ are processed after this action"
       default: ""
       optional: false
       description: "The optional EDNS Extended DNS Error extra text"
+    - name: "clear_existing_entries"
+      type: "bool"
+      default: "true"
+      optional: false
+      description: "Whether to clear existing EDNS Extended DNS Error codes"
 - name: "SetMacAddr"
   description: "Add the source MAC address to the query as an EDNS0 option. This action is currently only supported on Linux. Subsequent rules are processed after this action"
   parameters:
index 13de4258bcb31143930711296eb716afbc057c2c..47f5d1729f11a57e616bb32c344173f8c0b3b9ca 100644 (file)
@@ -2393,7 +2393,8 @@ class SetExtendedDNSErrorAction : public DNSAction
 {
 public:
   // this action does not stop the processing
-  SetExtendedDNSErrorAction(uint16_t infoCode, const std::string& extraText)
+  SetExtendedDNSErrorAction(uint16_t infoCode, const std::string& extraText, bool clearExistingEntries) :
+    d_clearExistingEntries(clearExistingEntries)
   {
     d_ede.infoCode = infoCode;
     d_ede.extraText = extraText;
@@ -2402,65 +2403,16 @@ public:
   DNSAction::Action operator()(DNSQuestion* dnsQuestion, std::string* ruleresult) const override
   {
     (void)ruleresult;
-    dnsQuestion->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
-
-    return DNSAction::Action::None;
-  }
-
-  [[nodiscard]] std::string toString() const override
-  {
-    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
-  }
-
-private:
-  EDNSExtendedError d_ede;
-};
-
-class SetExtendedDNSErrorResponseAction : public DNSResponseAction
-{
-public:
-  // this action does not stop the processing
-  SetExtendedDNSErrorResponseAction(uint16_t infoCode, const std::string& extraText)
-  {
-    d_ede.infoCode = infoCode;
-    d_ede.extraText = extraText;
-  }
-
-  DNSResponseAction::Action operator()(DNSResponse* dnsResponse, std::string* ruleresult) const override
-  {
-    (void)ruleresult;
-    dnsResponse->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
-
-    return DNSResponseAction::Action::None;
-  }
-
-  [[nodiscard]] std::string toString() const override
-  {
-    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
-  }
-
-private:
-  EDNSExtendedError d_ede;
-};
-
-class AddExtendedDNSErrorAction : public DNSAction
-{
-public:
-  // this action does not stop the processing
-  AddExtendedDNSErrorAction(uint16_t infoCode, const std::string& extraText)
-  {
-    d_ede.infoCode = infoCode;
-    d_ede.extraText = extraText;
-  }
-
-  DNSAction::Action operator()(DNSQuestion* dnsQuestion, std::string* ruleresult) const override
-  {
-    (void)ruleresult;
-    if (!dnsQuestion->ids.d_extendedErrors) {
+    if (d_clearExistingEntries) {
       dnsQuestion->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
     }
     else {
-      dnsQuestion->ids.d_extendedErrors->emplace_back(d_ede);
+      if (!dnsQuestion->ids.d_extendedErrors) {
+        dnsQuestion->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
+      }
+      else {
+        dnsQuestion->ids.d_extendedErrors->emplace_back(d_ede);
+      }
     }
 
     return DNSAction::Action::None;
@@ -2468,18 +2420,20 @@ public:
 
   [[nodiscard]] std::string toString() const override
   {
-    return "add EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
+    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
   }
 
 private:
   EDNSExtendedError d_ede;
+  bool d_clearExistingEntries;
 };
 
-class AddExtendedDNSErrorResponseAction : public DNSResponseAction
+class SetExtendedDNSErrorResponseAction : public DNSResponseAction
 {
 public:
   // this action does not stop the processing
-  AddExtendedDNSErrorResponseAction(uint16_t infoCode, const std::string& extraText)
+  SetExtendedDNSErrorResponseAction(uint16_t infoCode, const std::string& extraText, bool clearExistingEntries) :
+    d_clearExistingEntries(clearExistingEntries)
   {
     d_ede.infoCode = infoCode;
     d_ede.extraText = extraText;
@@ -2488,11 +2442,16 @@ public:
   DNSResponseAction::Action operator()(DNSResponse* dnsResponse, std::string* ruleresult) const override
   {
     (void)ruleresult;
-    if (!dnsResponse->ids.d_extendedErrors) {
+    if (d_clearExistingEntries) {
       dnsResponse->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
     }
     else {
-      dnsResponse->ids.d_extendedErrors->emplace_back(d_ede);
+      if (!dnsResponse->ids.d_extendedErrors) {
+        dnsResponse->ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({d_ede}));
+      }
+      else {
+        dnsResponse->ids.d_extendedErrors->emplace_back(d_ede);
+      }
     }
 
     return DNSResponseAction::Action::None;
@@ -2500,11 +2459,12 @@ public:
 
   [[nodiscard]] std::string toString() const override
   {
-    return "add EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
+    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
   }
 
 private:
   EDNSExtendedError d_ede;
+  bool d_clearExistingEntries;
 };
 
 class LimitTTLResponseAction : public DNSResponseAction, public boost::noncopyable
index 69915e4a2b34d20e1dbfaaea1600589559180666..64a4f84df109c2e2950e4a7ebe59914c5fcd5261 100644 (file)
@@ -54,8 +54,6 @@ static std::vector<dnsdist::console::completion::ConsoleKeyword> s_consoleKeywor
   {"addDynamicBlock", true, "address, message[, action [, seconds [, clientIPMask [, clientIPPortMask]]]]", "block the supplied address with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"},
   {"addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"},
   {"addDynBlockSMT", true, "names, message[, seconds [, action]]", "block the set of names with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"},
-  {"AddExtendedDNSErrorAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action"},
-  {"AddExtendedDNSErrorResponseAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to this response. Subsequent rules are processed after this action"},
   {"addLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "add `addr` to the list of addresses we listen on"},
   {"addMaintenanceCallback", true, "callback", "register a function to be called as part of the maintenance hook, every second"},
   {"addExitCallback", true, "callback", "register a function to be called when DNSdist exits"},
@@ -346,8 +344,8 @@ static std::vector<dnsdist::console::completion::ConsoleKeyword> s_consoleKeywor
   {"SetMacAddrAction", true, "option", "Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this action"},
   {"SetEDNSOptionAction", true, "option, data", "Add arbitrary EDNS option and data to the query. Subsequent rules are processed after this action"},
   {"SetEDNSOptionResponseAction", true, "option, data", "Add arbitrary EDNS option and data to the response. Subsequent rules are processed after this action"},
-  {"SetExtendedDNSErrorAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be set to the response corresponding to the current query. This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action"},
-  {"SetExtendedDNSErrorResponseAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be set to this response. This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action"},
+  {"SetExtendedDNSErrorAction", true, "infoCode [, extraText [, clearExistingEntries]]", "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action"},
+  {"SetExtendedDNSErrorResponseAction", true, "infoCode [, extraText [, clearExistingEntries]]", "Set an Extended DNS Error status that will be added to this response. Subsequent rules are processed after this action"},
   {"SetNoRecurseAction", true, "", "strip RD bit from the question, let it go through"},
   {"setOutgoingDoHWorkerThreads", true, "n", "Number of outgoing DoH worker threads"},
   {"SetProxyProtocolValuesAction", true, "values", "Set the Proxy-Protocol values for this queries to 'values'"},
index 145abc489d2f6f3ec0592fb6459073bf3dd5fad8..7835b3e5089f123dd5e568bf9d40c393035e096e 100644 (file)
@@ -318,27 +318,24 @@ void setupLuaBindingsDNSQuestion([[maybe_unused]] LuaContext& luaCtx)
     setEDNSOption(dnsQuestion, code, data);
   });
 
-  luaCtx.registerFunction<void (DNSQuestion::*)(uint16_t infoCode, const std::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const std::optional<std::string>& extraText) {
+  luaCtx.registerFunction<void (DNSQuestion::*)(uint16_t infoCode, const std::optional<std::string>& extraText, const std::optional<bool> clearExistingEntries)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const std::optional<std::string>& extraText, const std::optional<bool> clearExistingEntries) {
     EDNSExtendedError ede;
     ede.infoCode = infoCode;
     if (extraText) {
       ede.extraText = *extraText;
     }
-    dnsQuestion.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
-  });
-
-  luaCtx.registerFunction<void (DNSQuestion::*)(uint16_t infoCode, const std::optional<std::string>& extraText)>("addExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const std::optional<std::string>& extraText) {
-    EDNSExtendedError ede;
-    ede.infoCode = infoCode;
-    if (extraText) {
-      ede.extraText = *extraText;
-    }
-    if (!dnsQuestion.ids.d_extendedErrors) {
+    if (clearExistingEntries.value_or(true)) {
       dnsQuestion.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
     }
     else {
-      dnsQuestion.ids.d_extendedErrors->emplace_back(ede);
+      if (!dnsQuestion.ids.d_extendedErrors) {
+        dnsQuestion.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
+      }
+      else {
+        dnsQuestion.ids.d_extendedErrors->emplace_back(ede);
+      }
     }
+    dnsQuestion.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
   });
 
   luaCtx.registerFunction<bool (DNSQuestion::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSQuestion& dnsQuestion, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
@@ -696,13 +693,23 @@ void setupLuaBindingsDNSQuestion([[maybe_unused]] LuaContext& luaCtx)
     return setNegativeAndAdditionalSOA(dnsQuestion, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false);
   });
 
-  luaCtx.registerFunction<void (DNSResponse::*)(uint16_t infoCode, const std::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const std::optional<std::string>& extraText) {
+  luaCtx.registerFunction<void (DNSResponse::*)(uint16_t infoCode, const std::optional<std::string>& extraText, const std::optional<bool> clearExistingEntries)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const std::optional<std::string>& extraText, const std::optional<bool> clearExistingEntries) {
     EDNSExtendedError ede;
     ede.infoCode = infoCode;
     if (extraText) {
       ede.extraText = *extraText;
     }
-    dnsResponse.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
+    if (clearExistingEntries.value_or(true)) {
+      dnsResponse.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
+    }
+    else {
+      if (!dnsResponse.ids.d_extendedErrors) {
+        dnsResponse.ids.d_extendedErrors = std::make_unique<std::vector<EDNSExtendedError>>(std::initializer_list<EDNSExtendedError>({ede}));
+      }
+      else {
+        dnsResponse.ids.d_extendedErrors->emplace_back(ede);
+      }
+    }
   });
 
   luaCtx.registerFunction<bool (DNSResponse::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSResponse& dnsResponse, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
index 9ae5dcc7444daada43ef84e98d236e2c3146b1cf..b2de068dafa3027a163d2532cf105c61f82b1582 100644 (file)
@@ -1,15 +1,4 @@
 ---
-- name: "AddExtendedDNSError"
-  description: "Set an Extended DNS Error status that will be added to the response. Subsequent rules are processed after this action"
-  parameters:
-    - name: "info_code"
-      type: "u16"
-      description: "The EDNS Extended DNS Error code"
-    - name: "extra_text"
-      type: "String"
-      default: ""
-      optional: false
-      description: "The optional EDNS Extended DNS Error extra text"
 - name: "allow"
   description: "Let these packets go through."
 - name: "ClearRecordTypes"
@@ -204,7 +193,7 @@ The function will be invoked in a per-thread Lua state, without access to the gl
       type: "String"
       description: "The EDNS0 option raw content"
 - name: "SetExtendedDNSError"
-  description: "Set an Extended DNS Error status that will be set to the response. This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action"
+  description: "Set an Extended DNS Error status that will be added to the response. Subsequent rules are processed after this action"
   parameters:
     - name: "info_code"
       type: "u16"
@@ -214,6 +203,11 @@ The function will be invoked in a per-thread Lua state, without access to the gl
       default: ""
       optional: false
       description: "The optional EDNS Extended DNS Error extra text"
+    - name: "clear_existing_entries"
+      type: "bool"
+      default: "true"
+      optional: false
+      description: "Whether to clear existing EDNS Extended DNS Error codes"
 - name: "SetMaxReturnedTTL"
   description: "Cap the TTLs of the response to the given maximum, but only after inserting the response into the packet cache with the initial TTL values"
   skip-cpp: true
index 2db58835424dfa8ff2b065523674e60f5f9af02b..556d6edff70537badb63707131dc9e354f0aef4d 100644 (file)
@@ -22,26 +22,6 @@ Some actions allow further processing of rules, this is noted in their descripti
 
 The following actions exist.
 
-.. function:: AddExtendedDNSErrorAction(infoCode [, extraText])
-
-  .. versionadded:: 2.1.0
-
-  Set an Extended DNS Error status that will be added to the response corresponding to the current query.
-  Subsequent rules are processed after this action.
-
-  :param int infoCode: The EDNS Extended DNS Error code
-  :param string extraText: The optional EDNS Extended DNS Error extra text
-
-.. function:: AddExtendedDNSErrorResponseAction(infoCode [, extraText])
-
-  .. versionadded:: 2.1.0
-
-  Set an Extended DNS Error status that will be added to this response.
-  Subsequent rules are processed after this action.
-
-  :param int infoCode: The EDNS Extended DNS Error code
-  :param string extraText: The optional EDNS Extended DNS Error extra text
-
 .. function:: AllowAction()
 
   Let these packets go through.
@@ -627,25 +607,33 @@ The following actions exist.
   :param int option: The EDNS option number
   :param string data: The EDNS0 option raw content
 
-.. function:: SetExtendedDNSErrorAction(infoCode [, extraText])
+.. function:: SetExtendedDNSErrorAction(infoCode [, extraText [, clearExistingEntries]])
 
   .. versionadded:: 1.9.0
 
-  Set an Extended DNS Error status that will be set to the response corresponding to the current query.
-  This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action.
+  .. versionchanged:: 2.1.0
+    ``clearExistingEntries`` optional parameter added.
+
+  Set an Extended DNS Error status that will be added to the response corresponding to the current query.
+  Subsequent rules are processed after this action.
 
   :param int infoCode: The EDNS Extended DNS Error code
   :param string extraText: The optional EDNS Extended DNS Error extra text
+  :param bool clearExistingEntries: Whether to clear existing EDNS Extended DNS Error codes, default true
 
-.. function:: SetExtendedDNSErrorResponseAction(infoCode [, extraText])
+.. function:: SetExtendedDNSErrorResponseAction(infoCode [, extraText [, clearExistingEntries]])
 
   .. versionadded:: 1.9.0
 
-  Set an Extended DNS Error status that will be set to this response.
-  This will clear any previously set Extended DNS Errors. Subsequent rules are processed after this action.
+  .. versionchanged:: 2.1.0
+    ``clearExistingEntries`` optional parameter added.
+
+  Set an Extended DNS Error status that will be added to this response.
+  Subsequent rules are processed after this action.
 
   :param int infoCode: The EDNS Extended DNS Error code
   :param string extraText: The optional EDNS Extended DNS Error extra text
+  :param bool clearExistingEntries: Whether to clear existing EDNS Extended DNS Error codes, default true
 
 .. function:: SetMacAddrAction(option)