From: Otto Date: Tue, 6 Jul 2021 09:20:53 +0000 (+0200) Subject: Start of protobuf handling X-Git-Tag: dnsdist-1.7.0-alpha2~9^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4cdc62f5691cff68c61e284f5b9b410c3ea2bb65;p=thirdparty%2Fpdns.git Start of protobuf handling --- diff --git a/contrib/ProtobufLogger.py b/contrib/ProtobufLogger.py index 812863376e..0b6a1a52b5 100644 --- a/contrib/ProtobufLogger.py +++ b/contrib/ProtobufLogger.py @@ -98,7 +98,33 @@ class PDNSPBConnHandler(object): elif polType == dnsmessage_pb2.PBDNSMessage.NSIP: return 'NS IP' + @staticmethod + def getEventAsString(event): + descr = dnsmessage_pb2.PBDNSMessage.DESCRIPTOR + return descr.EnumValueName('EventType', event); + def printResponse(self, message): + if message.trace: + print("- Event Trace:") + for event in message.trace: + ev = self.getEventAsString(event.event) + '(' + str(event.ts) + valstr = '' + if event.HasField('boolVal'): + valstr = str(event.boolVal) + elif event.HasField('intVal'): + valstr = str(event.intVal) + elif event.HasField('stringVal'): + valstr = event.stringVal + elif event.HasField('bytesVal'): + valstr = binascii.hexlify(event.bytesVal) + if len(valstr) > 0: + valstr = ',' + valstr + if not event.start: + startstr = ',done' + else: + startstr = '' + print("\t- %s%s%s)" % (ev, valstr, startstr)) + if message.HasField('response'): response = message.response diff --git a/pdns/dnsmessage.proto b/pdns/dnsmessage.proto index 972bd8de38..48eb0af96b 100644 --- a/pdns/dnsmessage.proto +++ b/pdns/dnsmessage.proto @@ -126,6 +126,34 @@ message PBDNSMessage { required MetaValue value = 2; } repeated Meta meta = 22; // Arbitrary meta-data - to be used in future rather than adding new fields all the time + + enum EventType { + RecRecv = 1; + DistPipe = 2; + PCacheCheck = 3; + SyncRes = 4; + AnswerSent = 5; + LuaGetTag = 100; + LuaGetTagFFI = 101; + LuaIPFilter = 102; + LuaPreRPZ = 103; + LuaPreResolve = 104; + LuaPreOutQuery = 105; + LuaPostResolve = 106; + LuaNoData = 107; + LuaNXDomain = 108; + } + + message Event { + required uint64 ts = 1; + required EventType event = 2; + required bool start = 3; + optional bool boolVal = 4; + optional int64 intVal = 5; + optional string stringVal = 6; + optional bytes bytesVal = 7; + } + repeated Event trace = 23; } message PBDNSMessageList { diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 50e9c82162..6ef4764241 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -1066,7 +1066,8 @@ static void protobufLogResponse(const struct dnsheader* dh, LocalStateHolder& meta) + const string& deviceName, const std::map& meta, + const RecEventTrace& eventTrace) { pdns::ProtoZero::RecMessage pbMessage(pbData ? pbData->d_message : "", pbData ? pbData->d_response : "", 64, 10); // The extra bytes we are going to add // Normally we take the immutable string from the cache and append a few values, but if it's not there (can this happen?) @@ -1108,6 +1109,9 @@ static void protobufLogResponse(const struct dnsheader* dh, LocalStateHolderd_logResponse) { protobufLogResponse(pbMessage); } @@ -2880,7 +2887,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) if (cacheHit) { if (t_protobufServers && dc->d_logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbData && !pbData->d_tagged)) { struct timeval tv{0, 0}; - protobufLogResponse(dh, luaconfsLocal, pbData, tv, true, dc->d_source, dc->d_destination, dc->d_ednssubnet, dc->d_uuid, dc->d_requestorId, dc->d_deviceId, dc->d_deviceName, dc->d_meta); + protobufLogResponse(dh, luaconfsLocal, pbData, tv, true, dc->d_source, dc->d_destination, dc->d_ednssubnet, dc->d_uuid, dc->d_requestorId, dc->d_deviceId, dc->d_deviceName, dc->d_meta, dc->d_eventTrace); } if (!g_quiet) { @@ -2894,6 +2901,9 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) uint64_t spentUsec = uSec(now - start); g_stats.cumulativeAnswers(spentUsec); dc->d_eventTrace.add(RecEventTrace::AnswerSent); + + // Protobuf sending shoudl be here... + if (dc->d_eventTrace.enabled()) { g_log << Logger::Info << dc->d_eventTrace.toString() << endl; } @@ -3126,7 +3136,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr eventTrace.add(RecEventTrace::PCacheCheck, cacheHit, false); if (cacheHit) { if (t_protobufServers && logResponse && !(luaconfsLocal->protobufExportConfig.taggedOnly && pbData && !pbData->d_tagged)) { - protobufLogResponse(dh, luaconfsLocal, pbData, tv, false, source, destination, ednssubnet, uniqueId, requestorId, deviceId, deviceName, meta); + protobufLogResponse(dh, luaconfsLocal, pbData, tv, false, source, destination, ednssubnet, uniqueId, requestorId, deviceId, deviceName, meta, eventTrace); } if (!g_quiet) { @@ -3143,6 +3153,9 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr } int sendErr = sendOnNBSocket(fd, &msgh); eventTrace.add(RecEventTrace::AnswerSent); + + // Protobuf sending should be here... + if (eventTrace.enabled()) { g_log << Logger::Info << eventTrace.toString() << endl; } diff --git a/pdns/protozero.hh b/pdns/protozero.hh index a7a65e2388..665565322f 100644 --- a/pdns/protozero.hh +++ b/pdns/protozero.hh @@ -35,8 +35,9 @@ namespace pdns { enum class MetaValueField : protozero::pbf_tag_type { stringVal = 1, intVal = 2 }; enum class MetaField : protozero::pbf_tag_type { key = 1, value = 2 }; + enum class Event : protozero::pbf_tag_type { ts = 1, event = 2, start = 3, boolVal = 4, intVal = 5, stringVal = 6, bytesVal = 7 }; enum class MessageType : int32_t { DNSQueryType = 1, DNSResponseType = 2, DNSOutgoingQueryType = 3, DNSIncomingResponseType = 4 }; - enum class Field : protozero::pbf_tag_type { type = 1, messageId = 2, serverIdentity = 3, socketFamily = 4, socketProtocol = 5, from = 6, to = 7, inBytes = 8, timeSec = 9, timeUsec = 10, id = 11, question = 12, response = 13, originalRequestorSubnet = 14, requestorId = 15, initialRequestId = 16, deviceId = 17, newlyObservedDomain = 18, deviceName = 19, fromPort = 20, toPort = 21, meta = 22 }; + enum class Field : protozero::pbf_tag_type { type = 1, messageId = 2, serverIdentity = 3, socketFamily = 4, socketProtocol = 5, from = 6, to = 7, inBytes = 8, timeSec = 9, timeUsec = 10, id = 11, question = 12, response = 13, originalRequestorSubnet = 14, requestorId = 15, initialRequestId = 16, deviceId = 17, newlyObservedDomain = 18, deviceName = 19, fromPort = 20, toPort = 21, meta = 22, trace = 23 }; enum class QuestionField : protozero::pbf_tag_type { qName = 1, qType = 2, qClass = 3 }; enum class ResponseField : protozero::pbf_tag_type { rcode = 1, rrs = 2, appliedPolicy = 3, tags = 4, queryTimeSec = 5, queryTimeUsec = 6, appliedPolicyType = 7, appliedPolicyTrigger = 8, appliedPolicyHit = 9, appliedPolicyKind = 10, validationState = 11 }; enum class RRField : protozero::pbf_tag_type { name = 1, type = 2, class_ = 3, ttl = 4, rdata = 5, udr = 6 }; diff --git a/pdns/recursordist/rec-eventtrace.cc b/pdns/recursordist/rec-eventtrace.cc index c5ceca4efd..31ad2299f2 100644 --- a/pdns/recursordist/rec-eventtrace.cc +++ b/pdns/recursordist/rec-eventtrace.cc @@ -26,8 +26,7 @@ M, #M \ } -const std::map RecEventTrace::s_eventNames = { - NameEntry(Processing), +const std::unordered_map RecEventTrace::s_eventNames = { NameEntry(RecRecv), NameEntry(DistPipe), NameEntry(PCacheCheck), @@ -41,4 +40,6 @@ const std::map RecEventTrace::s_eventName NameEntry(LuaPreOutQuery), NameEntry(LuaPostResolve), NameEntry(LuaNoData), - NameEntry(LuaNXDomain)}; + NameEntry(LuaNXDomain) +}; + diff --git a/pdns/recursordist/rec-eventtrace.hh b/pdns/recursordist/rec-eventtrace.hh index 569a5739db..73a1cb4b7c 100644 --- a/pdns/recursordist/rec-eventtrace.hh +++ b/pdns/recursordist/rec-eventtrace.hh @@ -22,8 +22,13 @@ #pragma once #include "namespaces.hh" +#include "misc.hh" +#include "noinitvector.hh" + +#include #include #include +#include #include class RecEventTrace @@ -32,24 +37,23 @@ public: enum EventType : uint8_t { // Don't forget to add a new entry to the table in the .cc file! - Processing = 1, - RecRecv = 2, - DistPipe = 3, - PCacheCheck = 4, - SyncRes = 5, - AnswerSent = 6, - LuaGetTag = 50, - LuaGetTagFFI = 51, - LuaIPFilter = 52, - LuaPreRPZ = 53, - LuaPreResolve = 54, - LuaPreOutQuery = 55, - LuaPostResolve = 56, - LuaNoData = 57, - LuaNXDomain = 58 + RecRecv = 1, + DistPipe = 2, + PCacheCheck = 3 , + SyncRes = 4, + AnswerSent = 5, + LuaGetTag = 100, + LuaGetTagFFI = 101, + LuaIPFilter = 102, + LuaPreRPZ = 103, + LuaPreResolve = 104, + LuaPreOutQuery = 105, + LuaPostResolve = 106, + LuaNoData = 107, + LuaNXDomain = 108, }; - static const std::map s_eventNames; + static const std::unordered_map s_eventNames; RecEventTrace() { @@ -63,6 +67,7 @@ public: { old.d_status = Invalid; } + RecEventTrace(RecEventTrace&& old) : d_events(std::move(old.d_events)), d_base(old.d_base), @@ -70,6 +75,7 @@ public: { old.d_status = Invalid; } + RecEventTrace& operator=(const RecEventTrace& old) = delete; RecEventTrace& operator=(RecEventTrace&& old) { @@ -80,7 +86,8 @@ public: return *this; } - typedef std::variant Value_t; + // We distinguisg beteen string and byres. Does not amtter in C++, but in Go, .Java etc it does + typedef std::variant Value_t; static std::string toString(const EventType v) { @@ -95,21 +102,22 @@ public: else if (std::holds_alternative(v)) { return std::to_string(std::get(v)); } - else if (std::holds_alternative(v)) { - return std::to_string(std::get(v)); - } - else if (std::holds_alternative(v)) { - return std::to_string(std::get(v)); + else if (std::holds_alternative(v)) { + return std::to_string(std::get(v)); } else if (std::holds_alternative(v)) { return std::get(v); } + else if (std::holds_alternative(v)) { + const PacketBuffer& p = std::get(v); + return makeHexDump(std::string(reinterpret_cast(p.data()), p.size())); + } return "?"; } struct Entry { - Entry(Value_t& v, EventType e, bool start, uint32_t ts) : + Entry(Value_t& v, EventType e, bool start, uint64_t ts) : d_value(v), d_ts(ts), d_event(e), d_start(start) { } @@ -197,6 +205,11 @@ public: return ret; } + const std::vector& getEvents() const + { + return d_events; + } + private: std::vector d_events; uint64_t d_base; diff --git a/pdns/recursordist/rec-protozero.cc b/pdns/recursordist/rec-protozero.cc index 86f3666885..7ade38f9ac 100644 --- a/pdns/recursordist/rec-protozero.cc +++ b/pdns/recursordist/rec-protozero.cc @@ -22,6 +22,7 @@ #include "dnsrecords.hh" #include "rec-protozero.hh" +#include void pdns::ProtoZero::RecMessage::addRR(const DNSRecord& record, const std::set& exportTypes, bool udr) { @@ -109,3 +110,31 @@ void pdns::ProtoZero::RecMessage::clearUDR(std::string& str) } } #endif + +void pdns::ProtoZero::RecMessage::addEvents(const RecEventTrace& trace) +{ + for (const auto& t : trace.getEvents()) { + protozero::pbf_writer pbf_trace{d_message, static_cast(Field::trace)}; + pbf_trace.add_uint64(static_cast(Event::ts), t.d_ts); + pbf_trace.add_uint32(static_cast(Event::event), t.d_event); + pbf_trace.add_bool(static_cast(Event::start), t.d_start); + + const auto& v = t.d_value; + if (std::holds_alternative(v)) { + } + else if (std::holds_alternative(v)) { + pbf_trace.add_bool(static_cast(Event::boolVal), std::get(v)); + } + else if (std::holds_alternative(v)) { + pbf_trace.add_int64(static_cast(Event::intVal), std::get(v)); + } + else if (std::holds_alternative(v)) { + pbf_trace.add_string(static_cast(Event::stringVal), std::get(v)); + } + else if (std::holds_alternative(v)) { + const PacketBuffer& p = std::get(v); + pbf_trace.add_bytes(static_cast(Event::bytesVal), reinterpret_cast(p.data()), p.size()); + } + } +} + diff --git a/pdns/recursordist/rec-protozero.hh b/pdns/recursordist/rec-protozero.hh index 20f5111683..6502fd71a7 100644 --- a/pdns/recursordist/rec-protozero.hh +++ b/pdns/recursordist/rec-protozero.hh @@ -24,6 +24,7 @@ #include "protozero.hh" #include "filterpo.hh" +#include "rec-eventtrace.hh" #include "validate.hh" namespace pdns @@ -99,6 +100,8 @@ namespace ProtoZero return std::move(d_msgbuf); } + void addEvents(const RecEventTrace& trace); + // DNSResponse related fields below void addRR(const DNSRecord& record, const std::set& exportTypes, bool udr);