]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add ffi interface to clear given record types in a response
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Fri, 3 Dec 2021 17:54:05 +0000 (18:54 +0100)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 16 Dec 2021 13:27:05 +0000 (14:27 +0100)
pdns/dnsdistdist/dnsdist-lua-ffi-interface.h
pdns/dnsdistdist/dnsdist-lua-ffi.cc
pdns/dnsparser.cc
pdns/dnsparser.hh
regression-tests.dnsdist/test_Responses.py

index f9e635fed63ac05fd808dad839eea4af3bdaa44c..bdf45ed29b8e072f78747e9d9bd2d0a288a682c1 100644 (file)
@@ -130,6 +130,7 @@ double dnsdist_ffi_server_get_latency(const dnsdist_ffi_server_t* server) __attr
 void dnsdist_ffi_dnsresponse_set_min_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t min) __attribute__ ((visibility ("default")));
 void dnsdist_ffi_dnsresponse_set_max_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t max) __attribute__ ((visibility ("default")));
 void dnsdist_ffi_dnsresponse_limit_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t min, uint32_t max) __attribute__ ((visibility ("default")));
+void dnsdist_ffi_dnsresponse_clear_records_type(dnsdist_ffi_dnsresponse_t* dr, uint16_t qtype) __attribute__ ((visibility ("default")));
 
 typedef struct dnsdist_ffi_proxy_protocol_value {
   char* value;
index 1707ef2d34cb860f53fe1237f6c00c68f21c7188..0dfefb1ffdc3f947f1d61ec14c153daafbd1aa05 100644 (file)
@@ -564,9 +564,18 @@ void dnsdist_ffi_dnsresponse_set_max_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t
 
 void dnsdist_ffi_dnsresponse_limit_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t min, uint32_t max)
 {
-  std::string result;
-  LimitTTLResponseAction ac(min, max);
-  ac(dr->dr, &result);
+  if (dr->dr != nullptr) {
+    std::string result;
+    LimitTTLResponseAction ac(min, max);
+    ac(dr->dr, &result);
+  }
+}
+
+void dnsdist_ffi_dnsresponse_clear_records_type(dnsdist_ffi_dnsresponse_t* dr, uint16_t qtype)
+{
+  if (dr->dr != nullptr) {
+    clearDNSPacketRecordTypes(dr->dr->getMutableData(), std::set<QType>{qtype});
+  }
 }
 
 const std::string& getLuaFFIWrappers()
index 008aca8af65b60e5df718cf63a1f4cecfc33e1b2..a2a6634dbfd313408dd7ada81bdfc760b5fc3942 100644 (file)
@@ -752,6 +752,13 @@ void clearDNSPacketRecordTypes(vector<uint8_t>& packet, const std::set<QType>& q
   packet.resize(finalsize);
 }
 
+void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::set<QType>& qtypes)
+{
+  size_t finalsize = packet.size();
+  clearDNSPacketRecordTypes(reinterpret_cast<char*>(packet.data()), finalsize, qtypes);
+  packet.resize(finalsize);
+}
+
 // method of operation: silently fail if it doesn't work - we're only trying to be nice, don't fall over on it
 void clearDNSPacketRecordTypes(char* packet, size_t& length, const std::set<QType>& qtypes)
 {
index 250e1223ba7e18c52b2f5938dfb489662d4c3f92..631636bae27c8db4bc7a4e7b2381d3f0f478bc80 100644 (file)
@@ -34,6 +34,7 @@
 #include "dns.hh"
 #include "dnswriter.hh"
 #include "dnsname.hh"
+#include "noinitvector.hh"
 #include "pdnsexception.hh"
 #include "iputils.hh"
 #include "svc-records.hh"
@@ -435,6 +436,7 @@ void ageDNSPacket(char* packet, size_t length, uint32_t seconds);
 void ageDNSPacket(std::string& packet, uint32_t seconds);
 void editDNSPacketTTL(char* packet, size_t length, const std::function<uint32_t(uint8_t, uint16_t, uint16_t, uint32_t)>& visitor);
 void clearDNSPacketRecordTypes(vector<uint8_t>& packet, const std::set<QType>& qtypes);
+void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::set<QType>& qtypes);
 void clearDNSPacketRecordTypes(char* packet, size_t& length, const std::set<QType>& qtypes);
 uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA=nullptr);
 uint32_t getDNSPacketLength(const char* packet, size_t length);
index 02aafae0085caa63a7aaf706ebaa0f45991ff1e5..cd76fbe815613ef749afffc7ac2c957466159db2 100644 (file)
@@ -398,3 +398,49 @@ class TestResponseLuaActionReturnSyntax(DNSDistTest):
             receivedQuery.id = query.id
             self.assertEqual(query, receivedQuery)
             self.assertEqual(receivedResponse, None)
+
+from pprint import pprint
+
+class TestResponseClearRecordsType(DNSDistTest):
+
+    _config_params = ['_testServerPort']
+    _config_template = """
+    local ffi = require("ffi")
+
+    function luafct(dr)
+      ffi.C.dnsdist_ffi_dnsresponse_clear_records_type(dr, DNSQType.AAAA)
+      return DNSResponseAction.HeaderModify, ""
+    end
+
+    newServer{address="127.0.0.1:%s"}
+
+    addResponseAction("ffi.clear-records-type.responses.tests.powerdns.com.", LuaResponseAction(luafct))
+    """
+
+    def testClearedFFI(self):
+        """
+        Responses: Removes records of a given type (FFI API)
+        """
+        name = 'ffi.clear-records-type.responses.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        expectedResponse = 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)
+        expectedResponse.answer.append(rrset)
+        rrset = dns.rrset.from_text(name,
+                                    3660,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.AAAA,
+                                    '2001:DB8::1', '2001:DB8::2')
+        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(expectedResponse, receivedResponse)