]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Start of protobuf handling
authorOtto <otto.moerbeek@open-xchange.com>
Tue, 6 Jul 2021 09:20:53 +0000 (11:20 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Wed, 13 Oct 2021 12:31:29 +0000 (14:31 +0200)
contrib/ProtobufLogger.py
pdns/dnsmessage.proto
pdns/pdns_recursor.cc
pdns/protozero.hh
pdns/recursordist/rec-eventtrace.cc
pdns/recursordist/rec-eventtrace.hh
pdns/recursordist/rec-protozero.cc
pdns/recursordist/rec-protozero.hh

index 812863376e6f91888bf3f63dedeb933d0f3397a6..0b6a1a52b528ca3c519857cae9b7a37a1aa865d0 100644 (file)
@@ -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
 
index 972bd8de38f23d307c757f3e8b77022a26e10fc3..48eb0af96bcb8d2c84f79b7b57d3cf737a0344ac 100644 (file)
@@ -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 {
index 50e9c82162f9f2a137f3e2a90232c76f9430e27f..6ef4764241de39c195951043c928ef143724cc51 100644 (file)
@@ -1066,7 +1066,8 @@ static void protobufLogResponse(const struct dnsheader* dh, LocalStateHolder<Lua
                                 bool tcp, const ComboAddress& source, const ComboAddress& destination,
                                 const EDNSSubnetOpts& ednssubnet,
                                 const boost::uuids::uuid& uniqueId, const string& requestorId, const string& deviceId,
-                                const string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta)
+                                const string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& 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, LocalStateHolder<Lua
     pbMessage.setNewlyObservedDomain(false);
   }
 #endif
+  if (eventTrace.enabled()) {
+    pbMessage.addEvents(eventTrace);
+  }
   protobufLogResponse(pbMessage);
 }
 
@@ -2293,6 +2297,9 @@ static void startDoResolve(void *p)
         }
       }
 #endif /* NOD_ENABLED */
+      if (sr.d_eventTrace.enabled()) {
+        pbMessage.addEvents(sr.d_eventTrace);
+      }
       if (dc->d_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;
       }
index a7a65e238835449ee088772fe0a9dbb2d4a60db5..665565322f1860140f279926ffd72cb06c75eaeb 100644 (file)
@@ -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 };
index c5ceca4efd3ccacdf89dc4889d0e10e3fcefff0a..31ad2299f2ae1c4817062f3a036ba9e7ce534920 100644 (file)
@@ -26,8 +26,7 @@
     M, #M            \
   }
 
-const std::map<RecEventTrace::EventType, std::string> RecEventTrace::s_eventNames = {
-  NameEntry(Processing),
+const std::unordered_map<RecEventTrace::EventType, std::string> RecEventTrace::s_eventNames = {
   NameEntry(RecRecv),
   NameEntry(DistPipe),
   NameEntry(PCacheCheck),
@@ -41,4 +40,6 @@ const std::map<RecEventTrace::EventType, std::string> RecEventTrace::s_eventName
   NameEntry(LuaPreOutQuery),
   NameEntry(LuaPostResolve),
   NameEntry(LuaNoData),
-  NameEntry(LuaNXDomain)};
+  NameEntry(LuaNXDomain)
+};
+
index 569a5739dbc1a3f748088676ec9ff7f0a1228099..73a1cb4b7c33fc992205b15914052ed6b8b8483c 100644 (file)
 #pragma once
 
 #include "namespaces.hh"
+#include "misc.hh"
+#include "noinitvector.hh"
+
+#include <protozero/pbf_writer.hpp>
 #include <optional>
 #include <time.h>
+#include <unordered_map>
 #include <variant>
 
 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<EventType, std::string> s_eventNames;
+  static const std::unordered_map<EventType, std::string> 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<std::nullopt_t, bool, int32_t, uint32_t, std::string> Value_t;
+  // We distinguisg beteen string and byres. Does not amtter in C++, but in Go, .Java etc it does
+  typedef std::variant<std::nullopt_t, bool, int64_t, std::string, PacketBuffer> Value_t;
 
   static std::string toString(const EventType v)
   {
@@ -95,21 +102,22 @@ public:
     else if (std::holds_alternative<bool>(v)) {
       return std::to_string(std::get<bool>(v));
     }
-    else if (std::holds_alternative<int32_t>(v)) {
-      return std::to_string(std::get<int32_t>(v));
-    }
-    else if (std::holds_alternative<uint32_t>(v)) {
-      return std::to_string(std::get<uint32_t>(v));
+    else if (std::holds_alternative<int64_t>(v)) {
+      return std::to_string(std::get<int64_t>(v));
     }
     else if (std::holds_alternative<std::string>(v)) {
       return std::get<std::string>(v);
     }
+    else if (std::holds_alternative<PacketBuffer>(v)) {
+      const PacketBuffer& p = std::get<PacketBuffer>(v);
+      return makeHexDump(std::string(reinterpret_cast<const char*>(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<Entry>& getEvents() const
+  {
+    return d_events;
+  }
+  
 private:
   std::vector<Entry> d_events;
   uint64_t d_base;
index 86f3666885853d8fa497cebe6aadba5f00a8619d..7ade38f9acd19a9d1299de83bcc3a09b6da1ad43 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "dnsrecords.hh"
 #include "rec-protozero.hh"
+#include <variant>
 
 void pdns::ProtoZero::RecMessage::addRR(const DNSRecord& record, const std::set<uint16_t>& 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<protozero::pbf_tag_type>(Field::trace)};
+    pbf_trace.add_uint64(static_cast<protozero::pbf_tag_type>(Event::ts), t.d_ts);
+    pbf_trace.add_uint32(static_cast<protozero::pbf_tag_type>(Event::event), t.d_event);
+    pbf_trace.add_bool(static_cast<protozero::pbf_tag_type>(Event::start), t.d_start);
+
+    const auto& v = t.d_value;
+    if (std::holds_alternative<std::nullopt_t>(v)) {
+    }
+    else if (std::holds_alternative<bool>(v)) {
+      pbf_trace.add_bool(static_cast<protozero::pbf_tag_type>(Event::boolVal), std::get<bool>(v));
+    }
+    else if (std::holds_alternative<int64_t>(v)) {
+      pbf_trace.add_int64(static_cast<protozero::pbf_tag_type>(Event::intVal), std::get<int64_t>(v));
+    }
+    else if (std::holds_alternative<std::string>(v)) {
+      pbf_trace.add_string(static_cast<protozero::pbf_tag_type>(Event::stringVal), std::get<std::string>(v));
+    }
+    else if (std::holds_alternative<PacketBuffer>(v)) {
+      const PacketBuffer& p = std::get<PacketBuffer>(v);
+      pbf_trace.add_bytes(static_cast<protozero::pbf_tag_type>(Event::bytesVal), reinterpret_cast<const char*>(p.data()), p.size());
+    }
+  }
+}
+
index 20f511168381c27ddeb523668e0639cc5a7e069e..6502fd71a7ab1303242c3a61cf6474b967a590b0 100644 (file)
@@ -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<uint16_t>& exportTypes, bool udr);