*/
#pragma once
+#include "dnsparser.hh"
#include <random>
struct ResponseConfig
DNSName d_cname;
};
+class LimitTTLResponseAction : public DNSResponseAction, public boost::noncopyable
+{
+public:
+ LimitTTLResponseAction() {}
+
+ LimitTTLResponseAction(uint32_t min, uint32_t max = std::numeric_limits<uint32_t>::max()) : d_min(min), d_max(max)
+ {
+ }
+
+ DNSResponseAction::Action operator()(DNSResponse* dr, std::string* ruleresult) const override
+ {
+ auto visitor = [&](uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl) {
+ if (d_min > 0) {
+ if (ttl < d_min) {
+ ttl = d_min;
+ }
+ }
+ if (ttl > d_max) {
+ ttl = d_max;
+ }
+ return ttl;
+ };
+ editDNSPacketTTL(reinterpret_cast<char *>(dr->getMutableData().data()), dr->getData().size(), visitor);
+ return DNSResponseAction::Action::None;
+ }
+
+ std::string toString() const override
+ {
+ return "limit ttl";
+ }
+
+private:
+ uint32_t d_min{0};
+ uint32_t d_max{std::numeric_limits<uint32_t>::max()};
+};
+
typedef boost::variant<string, vector<pair<int, string>>, std::shared_ptr<DNSRule>, DNSName, vector<pair<int, DNSName> > > luadnsrule_t;
std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var);
typedef std::unordered_map<std::string, boost::variant<std::string> > luaruleparams_t;
- :func:`KeyValueStoreLookupAction`
- :func:`DnstapLogAction`
- :func:`DnstapLogResponseAction`
+- :func:`LimitTTLResponseAction`
- :func:`LogAction`
- :func:`NoneAction`
- :func:`RemoteLogAction`
:param KeyValueLookupKey lookupKey: The key to use for the lookup
:param string destinationTag: The name of the tag to store the result into
+.. function:: LimitTTLResponseAction(min[, max])
+
+ .. versionadded:: 1.8.0
+
+ Cap the TTLs of the response to the given boundaries.
+
+ :param int min: The minimum allowed value
+ :param int max: The maximum allowed value
+
.. function:: LogAction([filename[, binary[, append[, buffered[, verboseOnly[, includeTimestamp]]]]]])
.. versionchanged:: 1.4.0
:param int option: The EDNS0 option number
+.. function:: SetMaxTTLResponseAction(max)
+
+ .. versionadded:: 1.8.0
+
+ Cap the TTLs of the response to the given maximum.
+
+ :param int max: The maximum allowed value
+
+.. function:: SetMinTTLResponseAction(min)
+
+ .. versionadded:: 1.8.0
+
+ Cap the TTLs of the response to the given minimum.
+
+ :param int min: The minimum allowed value
+
.. function:: SetNoRecurseAction()
.. versionadded:: 1.6.0
self.assertNotEqual(response.answer[0].ttl, receivedResponse.answer[0].ttl)
self.assertEqual(receivedResponse.answer[0].ttl, self._ttl)
+class TestResponseRuleLimitTTL(DNSDistTest):
+
+ _lowttl = 60
+ _defaulttl = 3600
+ _highttl = 18000
+ _config_params = ['_lowttl', '_highttl', '_testServerPort']
+ _config_template = """
+ local ffi = require("ffi")
+ local lowttl = %d
+ local highttl = %d
+
+ function luaFFISetMinTTL(dr)
+ ffi.C.dnsdist_ffi_dnsresponse_set_min_ttl(dr, highttl)
+ return DNSAction.None, ""
+ end
+ function luaFFISetMaxTTL(dr)
+ ffi.C.dnsdist_ffi_dnsresponse_set_max_ttl(dr, lowttl)
+ return DNSAction.None, ""
+ end
+
+ newServer{address="127.0.0.1:%s"}
+
+ addResponseAction("min.responses.tests.powerdns.com.", SetMinTTLResponseAction(highttl))
+ addResponseAction("max.responses.tests.powerdns.com.", SetMaxTTLResponseAction(lowttl))
+ addResponseAction("ffi.min.limitttl.responses.tests.powerdns.com.", LuaResponseAction(luaFFISetMinTTL))
+ addResponseAction("ffi.max.limitttl.responses.tests.powerdns.com.", LuaResponseAction(luaFFISetMaxTTL))
+ """
+
+ def testLimitTTL(self):
+ """
+ Responses: Alter the TTLs via Limiter
+ """
+ name = 'min.responses.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '192.0.2.1')
+ response.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+ self.assertNotEqual(response.answer[0].ttl, receivedResponse.answer[0].ttl)
+ self.assertEqual(receivedResponse.answer[0].ttl, self._highttl)
+
+ name = 'max.responses.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '192.0.2.1')
+ response.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+ self.assertNotEqual(response.answer[0].ttl, receivedResponse.answer[0].ttl)
+ self.assertEqual(receivedResponse.answer[0].ttl, self._lowttl)
+
+ def testLimitTTLFFI(self):
+ """
+ Responses: Alter the TTLs via Limiter
+ """
+ name = 'ffi.min.responses.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '192.0.2.1')
+ response.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+ self.assertNotEqual(response.answer[0].ttl, receivedResponse.answer[0].ttl)
+ self.assertEqual(receivedResponse.answer[0].ttl, self._highttl)
+
+ name = 'ffi.max.responses.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '192.0.2.1')
+ response.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+ self.assertNotEqual(response.answer[0].ttl, receivedResponse.answer[0].ttl)
+ self.assertEqual(receivedResponse.answer[0].ttl, self._lowttl)
+
class TestResponseLuaActionReturnSyntax(DNSDistTest):
_config_template = """