From: Otto Moerbeek Date: Thu, 19 Jun 2025 08:28:53 +0000 (+0200) Subject: Encode TraceID and SpanID into a single EDNS option record, as suggested by Habbie X-Git-Tag: rec-5.3.0-alpha1^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5dc14ad7cc58fb9edf4a57b1b6017e19278cdc2;p=thirdparty%2Fpdns.git Encode TraceID and SpanID into a single EDNS option record, as suggested by Habbie Signed-off-by: Otto Moerbeek --- diff --git a/pdns/ednsoptions.hh b/pdns/ednsoptions.hh index 9ec8a5b81f..fee6eb4afd 100644 --- a/pdns/ednsoptions.hh +++ b/pdns/ednsoptions.hh @@ -25,7 +25,7 @@ struct EDNSOptionCode { // Temporary code assigned for OpenTelemetry TraceID and SpanID - enum EDNSOptionCodeEnum : uint16_t {NSID=3, DAU=5, DHU=6, N3U=7, ECS=8, EXPIRE=9, COOKIE=10, TCPKEEPALIVE=11, PADDING=12, CHAIN=13, KEYTAG=14, EXTENDEDERROR=15, OTTRACEID=65500, OTSPANID=65501}; + enum EDNSOptionCodeEnum : uint16_t {NSID=3, DAU=5, DHU=6, N3U=7, ECS=8, EXPIRE=9, COOKIE=10, TCPKEEPALIVE=11, PADDING=12, CHAIN=13, KEYTAG=14, EXTENDEDERROR=15, OTTRACEIDS=65500}; }; /* extract the position (relative to the optRR pointer!) and size of a specific EDNS0 option from a pointer on the beginning rdLen of the OPT RR */ diff --git a/pdns/protozero-trace.cc b/pdns/protozero-trace.cc index c501c4ce1c..059e2a6796 100644 --- a/pdns/protozero-trace.cc +++ b/pdns/protozero-trace.cc @@ -512,25 +512,23 @@ void extractOTraceIDs(const EDNSOptionViewMap& map, pdns::trace::Span& span) // parent_span_id gets set from edns options (if available and well-formed, otherwise it remains cleared (no parent)) // span_id gets inited randomly bool traceidset = false; - if (const auto& option = map.find(EDNSOptionCode::OTTRACEID); option != map.end()) { + const auto traceIDSize = span.trace_id.size(); + + if (const auto& option = map.find(EDNSOptionCode::OTTRACEIDS); option != map.end()) { if (option->second.values.size() > 0) { - if (option->second.values.at(0).size == span.trace_id.size()) { + if (option->second.values.at(0).size >= traceIDSize) { traceidset = true; - pdns::trace::fill(span.trace_id, option->second.values.at(0).content, span.trace_id.size()); + pdns::trace::fill(span.trace_id, option->second.values.at(0).content, traceIDSize); + } + if (option->second.values.at(0).size == traceIDSize + span.parent_span_id.size()) { + pdns::trace::fill(span.parent_span_id, &option->second.values.at(0).content[traceIDSize], span.parent_span_id.size()); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) it's the API } } } if (!traceidset) { random(span.trace_id); } - if (const auto& option = map.find(EDNSOptionCode::OTSPANID); option != map.end()) { - if (option->second.values.size() > 0) { - if (option->second.values.at(0).size == span.parent_span_id.size()) { - pdns::trace::fill(span.parent_span_id, option->second.values.at(0).content, span.parent_span_id.size()); - } - } - // Empty parent span id indicated the client did not set one - } + // Empty parent span id indicated the client did not set one, thats fine random(span.span_id); } diff --git a/pdns/sdig.cc b/pdns/sdig.cc index 41f67128d9..6de3a4a951 100644 --- a/pdns/sdig.cc +++ b/pdns/sdig.cc @@ -95,8 +95,12 @@ static void fillPacket(vector& packet, const string& q, const string& t opts.emplace_back(EDNSOptionCode::COOKIE, cookieOpt.makeOptString()); } if (otids) { - opts.emplace_back(EDNSOptionCode::OTTRACEID, std::string_view(reinterpret_cast(otids->first.data()), otids->first.size())); // NOLINT - opts.emplace_back(EDNSOptionCode::OTSPANID, std::string_view(reinterpret_cast(otids->second.data()), otids->second.size())); // NOLINT + const auto traceid = otids->first; + const auto spanid = otids->second; + std::array data{}; + std::copy(traceid.begin(), traceid.end(), data.begin()); + std::copy(spanid.begin(), spanid.end(), data.begin() + traceid.size()); + opts.emplace_back(EDNSOptionCode::OTTRACEIDS, std::string_view(reinterpret_cast(data.data()), data.size())); // NOLINT } pw.addOpt(bufsize, 0, dnssec ? EDNSOpts::DNSSECOK : 0, opts); pw.commit();