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
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 {
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?)
pbMessage.setNewlyObservedDomain(false);
}
#endif
+ if (eventTrace.enabled()) {
+ pbMessage.addEvents(eventTrace);
+ }
protobufLogResponse(pbMessage);
}
}
}
#endif /* NOD_ENABLED */
+ if (sr.d_eventTrace.enabled()) {
+ pbMessage.addEvents(sr.d_eventTrace);
+ }
if (dc->d_logResponse) {
protobufLogResponse(pbMessage);
}
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) {
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;
}
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) {
}
int sendErr = sendOnNBSocket(fd, &msgh);
eventTrace.add(RecEventTrace::AnswerSent);
+
+ // Protobuf sending should be here...
+
if (eventTrace.enabled()) {
g_log << Logger::Info << eventTrace.toString() << endl;
}
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 };
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),
NameEntry(LuaPreOutQuery),
NameEntry(LuaPostResolve),
NameEntry(LuaNoData),
- NameEntry(LuaNXDomain)};
+ NameEntry(LuaNXDomain)
+};
+
#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
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()
{
{
old.d_status = Invalid;
}
+
RecEventTrace(RecEventTrace&& old) :
d_events(std::move(old.d_events)),
d_base(old.d_base),
{
old.d_status = Invalid;
}
+
RecEventTrace& operator=(const RecEventTrace& old) = delete;
RecEventTrace& operator=(RecEventTrace&& old)
{
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)
{
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)
{
}
return ret;
}
+ const std::vector<Entry>& getEvents() const
+ {
+ return d_events;
+ }
+
private:
std::vector<Entry> d_events;
uint64_t d_base;
#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)
{
}
}
#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());
+ }
+ }
+}
+
#include "protozero.hh"
#include "filterpo.hh"
+#include "rec-eventtrace.hh"
#include "validate.hh"
namespace pdns
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);