From: Otto Moerbeek Date: Wed, 17 Sep 2025 13:32:06 +0000 (+0200) Subject: rec: add EDE and OT TraceID to protobuf X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=78c972fd88e70eabc1af0470a02d89a07d5d3178;p=thirdparty%2Fpdns.git rec: add EDE and OT TraceID to protobuf Signed-off-by: Otto Moerbeek --- diff --git a/contrib/ProtobufLogger.py b/contrib/ProtobufLogger.py index c056150c1..1b035e0e9 100644 --- a/contrib/ProtobufLogger.py +++ b/contrib/ProtobufLogger.py @@ -304,12 +304,23 @@ class PDNSPBConnHandler(object): if msg.HasField('ednsVersion'): ednsVersion = "0x%08X" % socket.ntohl(msg.ednsVersion) + ede = "N/A" + if msg.HasField('ede'): + ede = str(msg.ede) + edeText = "N/A" + if msg.HasField('edeText'): + edeText = msg.edeText + openTelemetryData = "N/A" if opentelemetryAvailable and msg.HasField('openTelemetryData'): openTelemetryData = str(len(msg.openTelemetryData)) + openTelemetryTraceID = "N/A" + if msg.HasField('openTelemetryTraceID'): + openTelemetryTraceID = binascii.hexlify(msg.openTelemetryTraceID) + print('[%s] %s of size %d: %s%s%s -> %s%s(%s) id: %d uuid: %s%s ' - 'requestorid: %s deviceid: %s devicename: %s serverid: %s nod: %s workerId: %s pcCacheHit: %s outgoingQueries: %s headerFlags: %s ednsVersion: %s openTelemetryData: len %s' % + 'requestorid: %s deviceid: %s devicename: %s serverid: %s nod: %s workerId: %s pcCacheHit: %s outgoingQueries: %s headerFlags: %s ednsVersion: %s ede: %s edeText: %s openTelemetryData: len %s otTraceID: %s' % (datestr, typestr, msg.inBytes, @@ -332,7 +343,10 @@ class PDNSPBConnHandler(object): outgoingQs, headerFlags, ednsVersion, - openTelemetryData)) + ede, + edeText, + openTelemetryData, + openTelemetryTraceID)) for mt in msg.meta: values = '' diff --git a/pdns/dnsmessage.proto b/pdns/dnsmessage.proto index cfc721f2f..f459e993d 100644 --- a/pdns/dnsmessage.proto +++ b/pdns/dnsmessage.proto @@ -193,6 +193,9 @@ message PBDNSMessage { optional uint32 headerFlags = 28; // Flags field in wire format, 16 bits used optional uint32 ednsVersion = 29; // EDNS version and flags in wire format, see https://www.rfc-editor.org/rfc/rfc6891.html#section-6.1.3 optional bytes openTelemetryData = 30; // Protobuf encoded Open Telemetry Data, see https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto + optional uint32 ede = 31; // EDNS error code, actually 16 bits + optional string edeText = 32; // EDNS error text + optional bytes openTelemetryTraceID = 33; // OpenTelemetry TraceID } message PBDNSMessageList { diff --git a/pdns/protozero-trace.hh b/pdns/protozero-trace.hh index a915dc331..9bcbb5ec0 100644 --- a/pdns/protozero-trace.hh +++ b/pdns/protozero-trace.hh @@ -226,6 +226,8 @@ struct InstrumentationScope using TraceID = std::array; using SpanID = std::array; +constexpr TraceID s_emptyTraceID = {}; + inline void random(TraceID& trace) { dns_random(trace.data(), trace.size()); diff --git a/pdns/protozero.hh b/pdns/protozero.hh index 3b42e5fc7..744e3bcb9 100644 --- a/pdns/protozero.hh +++ b/pdns/protozero.hh @@ -104,6 +104,9 @@ namespace ProtoZero headerFlags = 28, ednsVersion = 29, openTelemetryData = 30, + ede = 31, + edeText = 32, + openTelemetryTraceID = 33, }; enum class QuestionField : protozero::pbf_tag_type { @@ -322,6 +325,23 @@ namespace ProtoZero } } + void setEDE(const uint16_t ede) + { + add_uint32(d_message, Field::ede, ede); + } + + void setEDEText(const std::string edeText) + { + if (!edeText.empty()) { + add_string(d_message, Field::edeText, edeText); + } + } + + void setOpenTelemtryTraceID(const std::array& traceID) + { + add_bytes(d_message, Field::openTelemetryTraceID, reinterpret_cast(traceID.data()), traceID.size()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast): it's the API + } + void startResponse() { d_response = protozero::pbf_writer{d_message, static_cast(Field::response)}; diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index 4ac18ec19..fd3ceb01c 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -1618,6 +1618,7 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi } } + std::optional eee; if (haveEDNS) { auto state = resolver.getValidationState(); if (comboWriter->d_extendedErrorCode || resolver.d_extendedError || (SyncRes::s_addExtendedResolutionDNSErrors && vStateIsBogus(state))) { @@ -1681,13 +1682,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi throw std::runtime_error("Bogus validation state not handled: " + vStateToString(state)); } } + eee.emplace(EDNSExtendedError{static_cast(code), std::move(extra)}); - EDNSExtendedError eee; - eee.infoCode = static_cast(code); - eee.extraText = std::move(extra); - - if (packetWriter.size() < maxanswersize && (maxanswersize - packetWriter.size()) >= (EDNSOptionCodeSize + EDNSOptionLengthSize + sizeof(eee.infoCode) + eee.extraText.size())) { - returnedEdnsOptions.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(eee)); + if (packetWriter.size() < maxanswersize && (maxanswersize - packetWriter.size()) >= (EDNSOptionCodeSize + EDNSOptionLengthSize + sizeof(eee->infoCode) + eee->extraText.size())) { + returnedEdnsOptions.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(*eee)); } } @@ -1750,6 +1748,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi pbMessage.setValidationState(resolver.getValidationState()); // See if we want to store the policyTags into the PC addPolicyTagsToPBMessageIfNeeded(*comboWriter, pbMessage); + if (eee) { + pbMessage.setEDE(eee->infoCode); + pbMessage.setEDEText(eee->extraText); + } // Take s snap of the current protobuf buffer state to store in the PC pbDataForCache = boost::make_optional(RecursorPacketCache::PBData{ @@ -1863,6 +1865,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi string otData = otTrace.encode(); pbMessage.setOpenTelemetryData(otData); } + // Currently only set if an OT trace is generated + if (resolver.d_otTrace.trace_id != pdns::trace::s_emptyTraceID) { + pbMessage.setOpenTelemtryTraceID(resolver.d_otTrace.trace_id); + } if (comboWriter->d_logResponse) { protobufLogResponse(pbMessage); } @@ -2268,7 +2274,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr RecursorPacketCache::OptPBData pbData{boost::none}; if (t_protobufServers.servers) { if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && policyTags.empty())) { - protobufLogQuery(luaconfsLocal, uniqueId, source, destination, mappedSource, ednssubnet.getSource(), false, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta, ednsVersion, *dnsheader); + protobufLogQuery(luaconfsLocal, uniqueId, source, destination, mappedSource, ednssubnet.getSource(), false, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta, ednsVersion, *dnsheader, otTrace.trace_id); } } diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 11773172c..55149fa15 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -502,7 +502,7 @@ bool checkOutgoingProtobufExport(LocalStateHolder& luaconfsLocal return true; } -void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map& meta, const boost::optional& ednsVersion, const dnsheader& header) +void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map& meta, const boost::optional& ednsVersion, const dnsheader& header, const pdns::trace::TraceID& traceID) { auto log = g_slog->withName("pblq"); @@ -543,6 +543,9 @@ void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boo if (ednsVersion) { msg.setEDNSVersion(*ednsVersion); } + if (traceID != pdns::trace::s_emptyTraceID) { + msg.setOpenTelemtryTraceID(traceID); + } std::string strMsg(msg.finishAndMoveBuf()); for (auto& server : *t_protobufServers.servers) { @@ -636,6 +639,9 @@ void protobufLogResponse(const DNSName& qname, QType qtype, auto trace = pdns::trace::TracesData::boilerPlate("rec", qname.toLogString() + '/' + qtype.toString(), eventTrace.convertToOT(otTrace)); pbMessage.setOpenTelemetryData(trace.encode()); } + if (otTrace.trace_id != pdns::trace::s_emptyTraceID) { + pbMessage.setOpenTelemtryTraceID(otTrace.trace_id); + } pbMessage.addPolicyTags(policyTags); protobufLogResponse(pbMessage); diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index 928800203..d378e14a0 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -625,7 +625,7 @@ bool checkFrameStreamExport(LocalStateHolder& luaconfsLocal, con #endif void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass, bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options, boost::optional& ednsVersion); -void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map& meta, const boost::optional& ednsVersion, const dnsheader& header); +void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map& meta, const boost::optional& ednsVersion, const dnsheader& header, const pdns::trace::TraceID& traceID); bool isAllowNotifyForZone(DNSName qname); bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data, DNSName& qname, uint16_t& qtype, uint16_t& qclass, diff --git a/pdns/recursordist/rec-tcp.cc b/pdns/recursordist/rec-tcp.cc index 6d26f2b41..b5e23140d 100644 --- a/pdns/recursordist/rec-tcp.cc +++ b/pdns/recursordist/rec-tcp.cc @@ -274,7 +274,7 @@ static void doProtobufLogQuery(bool logQuery, LocalStateHolder& { try { if (logQuery && !(luaconfsLocal->protobufExportConfig.taggedOnly && comboWriter->d_policyTags.empty())) { - protobufLogQuery(luaconfsLocal, comboWriter->d_uuid, comboWriter->d_source, comboWriter->d_destination, comboWriter->d_mappedSource, comboWriter->d_ednssubnet.getSource(), true, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta, ednsVersion, *dnsheader); + protobufLogQuery(luaconfsLocal, comboWriter->d_uuid, comboWriter->d_source, comboWriter->d_destination, comboWriter->d_mappedSource, comboWriter->d_ednssubnet.getSource(), true, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta, ednsVersion, *dnsheader, comboWriter->d_otTrace.trace_id); } } catch (const std::exception& e) {