if(luaconfsLocal->protobufServer) {
try {
- if (!luaconfsLocal->protobufTaggedOnly) {
+ if (!luaconfsLocal->protobufResponsesOnly && !luaconfsLocal->protobufTaggedOnly) {
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, conn->d_remote, dest, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId);
}
}
#ifdef HAVE_PROTOBUF
pbMessage.setServerIdentity(SyncRes::s_serverID);
if(luaconfsLocal->protobufServer) {
- if (!luaconfsLocal->protobufTaggedOnly || !policyTags.empty()) {
+ if (!luaconfsLocal->protobufResponsesOnly && (!luaconfsLocal->protobufTaggedOnly || !policyTags.empty())) {
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, fromaddr, destaddr, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId);
}
}
});
#if HAVE_PROTOBUF
- Lua.writeFunction("protobufServer", [&lci](const string& server_, const boost::optional<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, const boost::optional<uint8_t> maskV4, boost::optional<uint8_t> maskV6, boost::optional<bool> asyncConnect, boost::optional<bool> taggedOnly) {
+ Lua.writeFunction("protobufServer", [&lci](const string& server_, const boost::optional<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, const boost::optional<uint8_t> maskV4, boost::optional<uint8_t> maskV6, boost::optional<bool> asyncConnect, boost::optional<bool> taggedOnly, boost::optional<bool> responsesOnly) {
try {
ComboAddress server(server_);
if (!lci.protobufServer) {
if (taggedOnly) {
lci.protobufTaggedOnly = *taggedOnly;
}
+ if (responsesOnly) {
+ lci.protobufResponsesOnly = *responsesOnly;
+ }
}
else {
theL()<<Logger::Error<<"Only one protobuf server can be configured, we already have "<<lci.protobufServer->toString()<<endl;
uint8_t protobufMaskV4{32};
uint8_t protobufMaskV6{128};
bool protobufTaggedOnly{false};
+ bool protobufResponsesOnly{false};
};
extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
--------------------------------
Protobuf export to a server is enabled using the ``protobufServer()`` directive:
-.. function:: protobufServer(server [[[[[[[, timeout=2], maxQueuedEntries=100], reconnectWaitTime=1], maskV4=32], maskV6=128], asyncConnect=false], taggedOnly=false])
+.. function:: protobufServer(server [[[[[[[[, timeout=2], maxQueuedEntries=100], reconnectWaitTime=1], maskV4=32], maskV6=128], asyncConnect=false], taggedOnly=false], responsesOnly=false])
+
+ .. versionchanged:: 4.1.11
+
+ The optional ``responsesOnly`` parameter was added.
:param string server: The IP and port to connect to
:param int timeout: Time in seconds to wait when sending a message
:param int maskV6: Same as maskV4, but for IPv6. Defaults to 128.
:param bool taggedOnly: Only entries with a policy or a policy tag set will be sent.
:param bool asyncConnect: When set to false (default) the first connection to the server during startup will block up to ``timeout`` seconds, otherwise the connection is done in a separate thread.
+ :param bool responsesOnly: When set to true, protobuf messages will only be generated for responses, instead of being generated for queries and responses.
Logging outgoing queries and responses
--------------------------------------
self.assertEquals(socket.inet_ntop(socket.AF_INET, rr.rdata), '192.0.2.42')
self.checkNoRemainingMessage()
+class ProtobufResponsesOnlyTest(TestRecursorProtobuf):
+ """
+ This test makes sure that we correctly export responses but not queries over protobuf.
+ """
+
+ _confdir = 'ProtobufResponsesOnly'
+ _config_template = """
+auth-zones=example=configs/%s/example.zone""" % _confdir
+ _lua_config_file = """
+ protobufServer("127.0.0.1:%d", 2, 100, 1, 32, 128, false, false, true)
+ """ % (protobufServersParameters[0].port)
+
+ 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
+ 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.42')
+ # nothing else in the queue
+ self.checkNoRemainingMessage()
+
class ProtobufTaggedOnlyTest(TestRecursorProtobuf):
"""
This test makes sure that we correctly export queries and responses but only if they have been tagged.