]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: allow forcing TCP from preoutquery()
authorAnton Khirnov <anton@khirnov.net>
Mon, 7 Jul 2025 09:37:19 +0000 (11:37 +0200)
committerAnton Khirnov <anton@khirnov.net>
Tue, 8 Jul 2025 09:18:02 +0000 (11:18 +0200)
pdns/recursordist/docs/lua-scripting/hooks.rst
pdns/recursordist/lua-recursor4.cc
pdns/recursordist/lua-recursor4.hh
pdns/recursordist/test-syncres_cc.cc

index 7a041e711ef819d9f244846759ac0f288ab83833..aee61f23849dad626f9829e50503a657b3aa1d35 100644 (file)
@@ -183,13 +183,17 @@ Interception Functions
 
 .. function:: preoutquery(dq) -> bool
 
+  .. versionchanged:: 5.3.0
+
+    `isTcp` can be set to force TCP or UDP
+
   This hook is not called in response to a client packet, but fires when the Recursor wants to talk to an authoritative server.
 
   When this hook sets the special result code ``-3``, the whole DNS client query causing this outgoing query gets a ``ServFail``.
 
   However, this function can also return records like :func:`preresolve`.
 
-  :param DNSQuestion dq: The DNS question to handle.
+  :param DNSQuestion dq: Attributes of a DNS question to be sent out to an authoritative server
 
   In the case of :func:`preoutquery`, only a few attributes if the :class:`dq <DNSQuestion>` object are filled in:
 
@@ -197,7 +201,10 @@ Interception Functions
   - :attr:`dq.localaddr <DNSQuestion.localaddr>`
   - :attr:`dq.qname <DNSQuestion.qname>`
   - :attr:`dq.qtype <DNSQuestion.qtype>`
-  - :attr:`dq.isTcp <DNSQuestion.isTcp>`
+  - :attr:`dq.isTcp <DNSQuestion.isTcp>` since version 5.3.0 this attribute may be changed by the hook to force the use of UDP or TCP
+
+  Note that except for `dq.localaddr`, which identifies the client that triggered this outgoing query, all other attributes apply to
+  the *outgoing* query that will be sent by the Recursor.
 
   Do not rely on other attributes having a value and do not call any method of the :class:`dq <DNSQuestion>` object apart from the record set manipulation methods.
 
index 66bdf9b20f370d795b271cc69c05425e18d8d7b2..906d5f2c7138064161fd4a5acbd7f945be8fcbe1 100644 (file)
@@ -163,7 +163,7 @@ void RecursorLua4::postPrepareContext() // NOLINT(readability-function-cognitive
 {
   d_lw->registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dnsQuestion) -> const DNSName& { return dnsQuestion.qname; }, [](DNSQuestion& /* dnsQuestion */, const DNSName& newName) { (void) newName; });
   d_lw->registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.qtype; }, [](DNSQuestion& /* dnsQuestion */, uint16_t newType) { (void) newType; });
-  d_lw->registerMember<bool (DNSQuestion::*)>("isTcp", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.isTcp; }, [](DNSQuestion& /* dnsQuestion */, bool newTcp) { (void) newTcp; });
+  d_lw->registerMember<bool (DNSQuestion::*)>("isTcp", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.isTcp; }, [](DNSQuestion& dnsQuestion, bool newTcp) { dnsQuestion.isTcp = newTcp; });
   d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("localaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.local; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newLocal) { (void) newLocal; });
   d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.remote; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newRemote) { (void) newRemote; });
   d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("interface_localaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.interface_local; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newLocal) { (void) newLocal; });
@@ -652,7 +652,7 @@ bool RecursorLua4::postresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace
   return isOK;
 }
 
-bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const
+bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool& isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const
 {
   if (!d_preoutquery) {
     return false;
@@ -667,6 +667,9 @@ bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddres
   bool isOK = genhook(d_preoutquery, dnsQuestion, ret);
   eventTrace.add(RecEventTrace::LuaPreOutQuery, isOK, false, match);
   warnDrop(dnsQuestion);
+
+  isTcp = dnsQuestion.isTcp;
+
   return isOK;
 }
 
index 375a3b9fe02226555b4f9a20cbd8ed90a05704b0..0d3874f07d012fc07df67cf161eefc6bcf42c5b2 100644 (file)
@@ -137,7 +137,7 @@ public:
     unsigned int tag{0};
     int rcode{0};
     const uint16_t qtype;
-    const bool isTcp;
+    bool isTcp;
     vState validationState{vState::Indeterminate};
 
     void addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl, boost::optional<string> name);
@@ -219,7 +219,7 @@ public:
   bool nodata(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
   bool postresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const;
 
-  bool preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const;
+  bool preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool& isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const;
   bool ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader&, RecEventTrace&) const;
 
   bool policyHitEventFilter(const ComboAddress& remote, const DNSName& qname, const QType& qtype, bool tcp, DNSFilterEngine::Policy& policy, std::unordered_set<std::string>& tags, std::unordered_map<std::string, bool>& discardedPolicies) const;
index a38c1569439b8201fe94fb21c2513750146213fc..344f7cc51aee9334f89e7cf933f60ca5d05e6ece 100644 (file)
@@ -38,7 +38,7 @@ void BaseLua4::getFeatures(Features& /* features */)
 {
 }
 
-bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool /* isTcp */, vector<DNSRecord>& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const
+bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool& /* isTcp */, vector<DNSRecord>& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const
 {
   return false;
 }