From: Charles-Henri Bruyand Date: Wed, 19 Jun 2019 09:48:42 +0000 (+0200) Subject: recursor: add new deviceName field to the dnsmessage protobuf export X-Git-Tag: dnsdist-1.4.0-rc1~73^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a6a45c8545f86a668003f453b38177308f5aff5;p=thirdparty%2Fpdns.git recursor: add new deviceName field to the dnsmessage protobuf export --- diff --git a/pdns/dnsmessage.proto b/pdns/dnsmessage.proto index a460b51f3c..fa8970d7d0 100644 --- a/pdns/dnsmessage.proto +++ b/pdns/dnsmessage.proto @@ -87,4 +87,5 @@ message PBDNSMessage { optional bytes initialRequestId = 16; // UUID of the incoming query that initiated this outgoing query or incoming response optional bytes deviceId = 17; // Device ID of the requestor (could be mac address IP address or e.g. IMEI) optional bool newlyObservedDomain = 18; // True if the domain has not been seen before + optional string deviceName = 19; // Device name of the requestor } diff --git a/pdns/lua-recursor4.cc b/pdns/lua-recursor4.cc index 4ad23d2246..98b38c8bfb 100644 --- a/pdns/lua-recursor4.cc +++ b/pdns/lua-recursor4.cc @@ -533,7 +533,7 @@ bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& loca return false; // don't block } -unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId) const +unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName) const { if(d_gettag) { auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp); @@ -558,6 +558,11 @@ unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& edn if (deviceIdret) { deviceId = *deviceIdret; } + + const auto deviceNameret = std::get<5>(ret); + if (deviceNameret) { + deviceName = *deviceNameret; + } return std::get<0>(ret); } return 0; @@ -566,7 +571,7 @@ unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& edn struct pdns_ffi_param { public: - pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::vector& policyTags_, const EDNSOptionViewMap& ednsOptions_, std::string& requestorId_, std::string& deviceId_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), ednsOptions(ednsOptions_), requestorId(requestorId_), deviceId(deviceId_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), qtype(qtype_), tcp(tcp_) + pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::vector& policyTags_, const EDNSOptionViewMap& ednsOptions_, std::string& requestorId_, std::string& deviceId_, std::string& deviceName_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), ednsOptions(ednsOptions_), requestorId(requestorId_), deviceId(deviceId_), deviceName(deviceName_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), qtype(qtype_), tcp(tcp_) { } @@ -584,6 +589,7 @@ public: const EDNSOptionViewMap& ednsOptions; std::string& requestorId; std::string& deviceId; + std::string& deviceName; uint32_t& ttlCap; bool& variable; bool& logQuery; @@ -593,10 +599,10 @@ public: bool tcp; }; -unsigned int RecursorLua4::gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, uint32_t& ttlCap, bool& variable, bool& logQuery) const +unsigned int RecursorLua4::gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, uint32_t& ttlCap, bool& variable, bool& logQuery) const { if (d_gettag_ffi) { - pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, ednsOptions, requestorId, deviceId, ttlCap, variable, tcp, logQuery); + pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, ednsOptions, requestorId, deviceId, deviceName, ttlCap, variable, tcp, logQuery); auto ret = d_gettag_ffi(¶m); if (ret) { @@ -843,7 +849,7 @@ void pdns_ffi_param_set_requestorid(pdns_ffi_param_t* ref, const char* name) void pdns_ffi_param_set_devicename(pdns_ffi_param_t* ref, const char* name) { - ref->deviceId = std::string(name); + ref->deviceName = std::string(name); } void pdns_ffi_param_set_deviceid(pdns_ffi_param_t* ref, size_t len, const void* name) diff --git a/pdns/lua-recursor4.hh b/pdns/lua-recursor4.hh index 20e7f2bc53..7a8a2539b9 100644 --- a/pdns/lua-recursor4.hh +++ b/pdns/lua-recursor4.hh @@ -77,6 +77,7 @@ public: std::unordered_map* discardedPolicies{nullptr}; std::string requestorId; std::string deviceId; + std::string deviceName; vState validationState{Indeterminate}; bool& variable; bool& wantsRPZ; @@ -110,8 +111,8 @@ public: DNSName followupName; }; - unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId) const; - unsigned int gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId, uint32_t& ttlCap, bool& variable, bool& logQuery) const; + unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName) const; + unsigned int gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, uint32_t& ttlCap, bool& variable, bool& logQuery) const; void maintenance() const; bool prerpz(DNSQuestion& dq, int& ret) const; @@ -132,7 +133,7 @@ public: d_postresolve); } - typedef std::function >,boost::optional,boost::optional,boost::optional >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const EDNSOptionViewMap&, bool)> gettag_t; + typedef std::function >,boost::optional,boost::optional,boost::optional,boost::optional >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const EDNSOptionViewMap&, bool)> gettag_t; gettag_t d_gettag; // public so you can query if we have this hooked typedef std::function(pdns_ffi_param_t*)> gettag_ffi_t; gettag_ffi_t d_gettag_ffi; diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 491ae26bd9..24f6c77b73 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -321,6 +321,7 @@ struct DNSComboWriter { boost::uuids::uuid d_uuid; string d_requestorId; string d_deviceId; + string d_deviceName; struct timeval d_kernelTimestamp{0,0}; #endif std::string d_query; @@ -795,7 +796,7 @@ catch(...) } #ifdef HAVE_PROTOBUF -static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector& policyTags, const std::string& requestorId, const std::string& deviceId) +static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName) { if (!t_protobufServers) { return; @@ -808,6 +809,7 @@ static void protobufLogQuery(uint8_t maskV4, uint8_t maskV6, const boost::uuids: message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6); message.setRequestorId(requestorId); message.setDeviceId(deviceId); + message.setDeviceName(deviceName); if (!policyTags.empty()) { message.setPolicyTags(policyTags); @@ -1246,6 +1248,7 @@ static void startDoResolve(void *p) #ifdef HAVE_PROTOBUF dq.requestorId = dc->d_requestorId; dq.deviceId = dc->d_deviceId; + dq.deviceName = dc->d_deviceName; #endif if(ednsExtRCode != 0) { @@ -1627,6 +1630,7 @@ static void startDoResolve(void *p) } pbMessage->setRequestorId(dq.requestorId); pbMessage->setDeviceId(dq.deviceId); + pbMessage->setDeviceName(dq.deviceName); #ifdef NOD_ENABLED if (g_nodEnabled) { if (nod) { @@ -1987,6 +1991,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) bool needXPF = g_XPFAcl.match(conn->d_remote); string requestorId; string deviceId; + string deviceName; bool logQuery = false; #ifdef HAVE_PROTOBUF auto luaconfsLocal = g_luaconfs.getLocal(); @@ -2014,10 +2019,10 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) if(t_pdl) { try { if (t_pdl->d_gettag_ffi) { - dc->d_tag = t_pdl->gettag_ffi(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, dc->d_ttlCap, dc->d_variable, logQuery); + dc->d_tag = t_pdl->gettag_ffi(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, deviceName, dc->d_ttlCap, dc->d_variable, logQuery); } else if (t_pdl->d_gettag) { - dc->d_tag = t_pdl->gettag(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId); + dc->d_tag = t_pdl->gettag(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, deviceName); } } catch(const std::exception& e) { @@ -2039,6 +2044,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) if(t_protobufServers || t_outgoingProtobufServers) { dc->d_requestorId = requestorId; dc->d_deviceId = deviceId; + dc->d_deviceName = deviceName; dc->d_uuid = getUniqueID(); } @@ -2046,7 +2052,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) try { if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && dc->d_policyTags.empty())) { - protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, dc->d_source, dc->d_destination, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId); + protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, dc->d_source, dc->d_destination, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId, dc->d_deviceName); } } catch(std::exception& e) { @@ -2180,6 +2186,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr ComboAddress destination = destaddr; string requestorId; string deviceId; + string deviceName; bool logQuery = false; #ifdef HAVE_PROTOBUF boost::uuids::uuid uniqueId; @@ -2238,10 +2245,10 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr if(t_pdl) { try { if (t_pdl->d_gettag_ffi) { - ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, ttlCap, variable, logQuery); + ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, deviceName, ttlCap, variable, logQuery); } else if (t_pdl->d_gettag) { - ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId); + ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, deviceName); } } catch(const std::exception& e) { @@ -2264,7 +2271,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr pbMessage = RecProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType::Response); pbMessage->setServerIdentity(SyncRes::s_serverID); if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) { - protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, source, destination, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId); + protobufLogQuery(luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, source, destination, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName); } } #endif /* HAVE_PROTOBUF */ @@ -2302,6 +2309,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr } pbMessage->setRequestorId(requestorId); pbMessage->setDeviceId(deviceId); + pbMessage->setDeviceName(deviceName); protobufLogResponse(*pbMessage); } #endif /* HAVE_PROTOBUF */ @@ -2377,6 +2385,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr } dc->d_requestorId = requestorId; dc->d_deviceId = deviceId; + dc->d_deviceName = deviceName; dc->d_kernelTimestamp = tv; #endif diff --git a/pdns/protobuf.cc b/pdns/protobuf.cc index fd491ac669..46f625fa70 100644 --- a/pdns/protobuf.cc +++ b/pdns/protobuf.cc @@ -242,6 +242,13 @@ void DNSProtoBufMessage::setDeviceId(const std::string& deviceId) #endif /* HAVE_PROTOBUF */ } +void DNSProtoBufMessage::setDeviceName(const std::string& deviceName) +{ +#ifdef HAVE_PROTOBUF + d_message.set_devicename(deviceName); +#endif /* HAVE_PROTOBUF */ +} + void DNSProtoBufMessage::setServerIdentity(const std::string& serverId) { #ifdef HAVE_PROTOBUF diff --git a/pdns/protobuf.hh b/pdns/protobuf.hh index f87dd5f08c..0f1f74a157 100644 --- a/pdns/protobuf.hh +++ b/pdns/protobuf.hh @@ -70,6 +70,7 @@ public: void setResponder(const ComboAddress& responder); void setRequestorId(const std::string& requestorId); void setDeviceId(const std::string& deviceId); + void setDeviceName(const std::string& deviceName); void setServerIdentity(const std::string& serverId); std::string toDebugString() const; void addTag(const std::string& strValue); diff --git a/pdns/recursordist/docs/lua-scripting/dq.rst b/pdns/recursordist/docs/lua-scripting/dq.rst index dc9a1fcdef..591bc7f521 100644 --- a/pdns/recursordist/docs/lua-scripting/dq.rst +++ b/pdns/recursordist/docs/lua-scripting/dq.rst @@ -108,6 +108,12 @@ The DNSQuestion object contains at least the following fields: A string that will be used to set the ``deviceId`` field in :doc:`protobuf <../lua-config/protobuf>` messages. + .. attribute:: DNSQuestion.deviceName + + .. versionadded:: 4.1.15 + + A string that will be used to set the ``deviceName`` field in :doc:`protobuf <../lua-config/protobuf>` messages. + .. attribute:: DNSQuestion.udpAnswer Answer to the :attr:`udpQuery ` when when using the ``udpQueryResponse`` :attr:`followupFunction `. diff --git a/pdns/recursordist/docs/lua-scripting/hooks.rst b/pdns/recursordist/docs/lua-scripting/hooks.rst index 887d8d1de1..ea04d7b8d8 100644 --- a/pdns/recursordist/docs/lua-scripting/hooks.rst +++ b/pdns/recursordist/docs/lua-scripting/hooks.rst @@ -69,6 +69,9 @@ Interception Functions .. versionadded:: 4.1.0 It can also return a table whose keys and values are strings to fill the :attr:`DNSQuestion.data` table, as well as a ``requestorId`` value to fill the :attr:`DNSQuestion.requestorId` field and a ``deviceId`` value to fill the :attr:`DNSQuestion.deviceId` field. + .. versionadded:: 4.1.15 + + Along the ``deviceId`` value that can be returned, it was addded a ``deviceName`` field to fill the :attr:`DNSQuestion.deviceName` field. The tagged packetcache can e.g. be used to answer queries from cache that have e.g. been filtered for certain IPs (this logic should be implemented in :func:`gettag`). This ensure that queries are answered quickly compared to setting :attr:`dq.variable ` to true. diff --git a/regression-tests.recursor-dnssec/test_Protobuf.py b/regression-tests.recursor-dnssec/test_Protobuf.py index 50a6449d4b..c1ff6a4bc9 100644 --- a/regression-tests.recursor-dnssec/test_Protobuf.py +++ b/regression-tests.recursor-dnssec/test_Protobuf.py @@ -221,6 +221,14 @@ class TestRecursorProtobuf(RecursorTest): self.assertTrue(msg.HasField('response')) self.assertTrue(msg.response.HasField('queryTimeSec')) + def checkProtobufIdentity(self, msg, requestorId, deviceId, deviceName): + self.assertTrue(msg.HasField('requestorId')) + self.assertTrue(msg.HasField('deviceId')) + self.assertTrue(msg.HasField('deviceName')) + self.assertEquals(msg.requestorId, requestorId) + self.assertEquals(msg.deviceId, deviceId) + self.assertEquals(msg.deviceName, deviceName) + @classmethod def setUpClass(cls): @@ -652,3 +660,112 @@ auth-zones=example=configs/%s/example.zone""" % _confdir self.assertEquals(rr.rdata, 'a.example.') self.checkNoRemainingMessage() + +class ProtobufTaggedExtraFieldsTest(TestRecursorProtobuf): + """ + This test makes sure that we correctly export extra fields that may have been set while being tagged. + """ + + _confdir = 'ProtobufTaggedExtraFields' + _config_template = """ +auth-zones=example=configs/%s/example.zone""" % _confdir + _lua_config_file = """ + protobufServer({"127.0.0.1:%d", "127.0.0.1:%d"}, { logQueries=true, logResponses=true } ) + """ % (protobufServersParameters[0].port, protobufServersParameters[1].port) + _requestorId = 'S-000001727' + _deviceId = 'd1:0a:91:dc:cc:82' + _deviceName = 'Joe' + _lua_dns_script_file = """ + function gettag(remote, ednssubnet, localip, qname, qtype, ednsoptions, tcp) + if qname:equal('tagged.example.') then + -- tag number, policy tags, data, requestorId, deviceId, deviceName + return 0, {}, {}, '%s', '%s', '%s' + end + return 0 + end + """ % (_requestorId, _deviceId, _deviceName) + + def testA(self): + name = 'a.example.' + expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.42') + query = dns.message.make_query(name, 'A', want_dnssec=True) + query.flags |= dns.flags.CD + res = self.sendUDPQuery(query) + self.assertRRsetInAnswer(res, expected) + + # check the protobuf message corresponding to the UDP response + # the first query and answer are not tagged, so there is nothing in the queue + # check the protobuf messages corresponding to the UDP query and answer + msg = self.getFirstProtobufMessage() + self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name) + self.checkProtobufIdentity(msg, '', '', '') + + # then the response + msg = self.getFirstProtobufMessage() + self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res, '127.0.0.1') + self.assertEquals(len(msg.response.rrs), 1) + rr = msg.response.rrs[0] + # we have max-cache-ttl set to 15 + self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, name, 15) + self.assertEquals(socket.inet_ntop(socket.AF_INET, rr.rdata), '192.0.2.42') + self.checkProtobufIdentity(msg, '', '', '') + self.checkNoRemainingMessage() + + def testTagged(self): + name = 'tagged.example.' + expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.84') + query = dns.message.make_query(name, 'A', want_dnssec=True) + query.flags |= dns.flags.CD + res = self.sendUDPQuery(query) + self.assertRRsetInAnswer(res, expected) + + # check the protobuf messages corresponding to the UDP query and answer + msg = self.getFirstProtobufMessage() + self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name) + self.checkProtobufIdentity(msg, self._requestorId, self._deviceId, self._deviceName) + + # then the response + msg = self.getFirstProtobufMessage() + self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res) + self.assertEquals(len(msg.response.rrs), 1) + rr = msg.response.rrs[0] + # we have max-cache-ttl set to 15 + self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, name, 15) + self.assertEquals(socket.inet_ntop(socket.AF_INET, rr.rdata), '192.0.2.84') + self.checkProtobufIdentity(msg, self._requestorId, self._deviceId, self._deviceName) + self.checkNoRemainingMessage() + +class ProtobufTaggedExtraFieldsFFITest(ProtobufTaggedExtraFieldsTest): + """ + This test makes sure that we correctly export extra fields that may have been set while being tagged (FFI version). + """ + _confdir = 'ProtobufTaggedExtraFieldsFFI' + _config_template = """ +auth-zones=example=configs/%s/example.zone""" % _confdir + _lua_config_file = """ + protobufServer({"127.0.0.1:%d", "127.0.0.1:%d"}, { logQueries=true, logResponses=true } ) + """ % (protobufServersParameters[0].port, protobufServersParameters[1].port) + _lua_dns_script_file = """ + local ffi = require("ffi") + + ffi.cdef[[ + typedef struct pdns_ffi_param pdns_ffi_param_t; + + const char* pdns_ffi_param_get_qname(pdns_ffi_param_t* ref); + void pdns_ffi_param_set_tag(pdns_ffi_param_t* ref, unsigned int tag); + void pdns_ffi_param_set_requestorid(pdns_ffi_param_t* ref, const char* name); + void pdns_ffi_param_set_devicename(pdns_ffi_param_t* ref, const char* name); + void pdns_ffi_param_set_deviceid(pdns_ffi_param_t* ref, size_t len, const void* name); + ]] + + function gettag_ffi(obj) + qname = ffi.string(ffi.C.pdns_ffi_param_get_qname(obj)) + if qname == 'tagged.example' then + ffi.C.pdns_ffi_param_set_requestorid(obj, "%s") + deviceid = "%s" + ffi.C.pdns_ffi_param_set_deviceid(obj, string.len(deviceid), deviceid) + ffi.C.pdns_ffi_param_set_devicename(obj, "%s") + end + return 0 + end + """ % (ProtobufTaggedExtraFieldsTest._requestorId, ProtobufTaggedExtraFieldsTest._deviceId, ProtobufTaggedExtraFieldsTest._deviceName)