From: Charles-Henri Bruyand Date: Fri, 3 Dec 2021 17:54:05 +0000 (+0100) Subject: dnsdist: add ffi interface to clear given record types in a response X-Git-Tag: auth-4.7.0-alpha1~108^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb8d953f15faf99259c1a1ca510631ae202dec7d;p=thirdparty%2Fpdns.git dnsdist: add ffi interface to clear given record types in a response --- diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h index f9e635fed6..bdf45ed29b 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h +++ b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h @@ -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; diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 1707ef2d34..0dfefb1ffd 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -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}); + } } const std::string& getLuaFFIWrappers() diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index 008aca8af6..a2a6634dbf 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -752,6 +752,13 @@ void clearDNSPacketRecordTypes(vector& packet, const std::set& q packet.resize(finalsize); } +void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::set& qtypes) +{ + size_t finalsize = packet.size(); + clearDNSPacketRecordTypes(reinterpret_cast(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& qtypes) { diff --git a/pdns/dnsparser.hh b/pdns/dnsparser.hh index 250e1223ba..631636bae2 100644 --- a/pdns/dnsparser.hh +++ b/pdns/dnsparser.hh @@ -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& visitor); void clearDNSPacketRecordTypes(vector& packet, const std::set& qtypes); +void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::set& qtypes); void clearDNSPacketRecordTypes(char* packet, size_t& length, const std::set& qtypes); uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA=nullptr); uint32_t getDNSPacketLength(const char* packet, size_t length); diff --git a/regression-tests.dnsdist/test_Responses.py b/regression-tests.dnsdist/test_Responses.py index 02aafae008..cd76fbe815 100644 --- a/regression-tests.dnsdist/test_Responses.py +++ b/regression-tests.dnsdist/test_Responses.py @@ -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)