From: Otto Moerbeek Date: Tue, 12 Nov 2024 12:25:44 +0000 (+0100) Subject: Add EDNS version and flag info to PB messages X-Git-Tag: rec-5.2.0-beta1~4^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7081cb4d2d6f9a70f6f0fe27fe6dd2b88f02ca9;p=thirdparty%2Fpdns.git Add EDNS version and flag info to PB messages --- diff --git a/pdns/dnswriter.cc b/pdns/dnswriter.cc index 67ed5c57d1..7727a35cc7 100644 --- a/pdns/dnswriter.cc +++ b/pdns/dnswriter.cc @@ -95,7 +95,7 @@ template void GenericDNSPacketWriter::startRecor d_sor=d_content.size(); // this will remind us where to stuff the record size } -template void GenericDNSPacketWriter::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version) +template uint32_t GenericDNSPacketWriter::addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options, const uint8_t version) { uint32_t ttl=0; @@ -127,6 +127,7 @@ template void GenericDNSPacketWriter::addOpt(con xfr16BitInt(option.second.length()); xfrBlob(option.second); } + return ttl; } template void GenericDNSPacketWriter::xfr48BitInt(uint64_t val) diff --git a/pdns/dnswriter.hh b/pdns/dnswriter.hh index 4d6d286182..fa0540faac 100644 --- a/pdns/dnswriter.hh +++ b/pdns/dnswriter.hh @@ -70,7 +70,7 @@ public: /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */ using optvect_t = vector >; - void addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options=optvect_t(), const uint8_t version=0); + uint32_t addOpt(uint16_t udpsize, uint16_t extRCode, uint16_t ednsFlags, const optvect_t& options = {}, uint8_t version = 0); /** needs to be called after the last record is added, but can be called again and again later on. Is called internally by startRecord too. The content of the vector<> passed to the constructor is inconsistent until commit is called. diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index df12afa2c4..087fdfd123 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -1718,8 +1718,9 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi OPT record. This MUST also occur when a truncated response (using the DNS header's TC bit) is returned." */ - packetWriter.addOpt(512, ednsExtRCode, DNSSECOK ? EDNSOpts::DNSSECOK : 0, returnedEdnsOptions); + auto ednsVersion = packetWriter.addOpt(512, ednsExtRCode, DNSSECOK ? EDNSOpts::DNSSECOK : 0, returnedEdnsOptions); packetWriter.commit(); + pbMessage.setMeta("_pdnsREDNS", {}, {ednsVersion}); } t_Counters.at(rec::ResponseStats::responseStats).submitResponse(comboWriter->d_mdp.d_qtype, packet.size(), packetWriter.getHeader()->rcode); @@ -2014,7 +2015,7 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi } void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass, - bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options) + bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options, boost::optional& ednsVersion) { const bool lookForECS = ednssubnet != nullptr; const dnsheader_aligned dnshead(question.data()); @@ -2027,7 +2028,7 @@ void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* const size_t headerSize = /* root */ 1 + sizeof(dnsrecordheader); const uint16_t arcount = ntohs(dhPointer->arcount); - for (uint16_t arpos = 0; arpos < arcount && questionLen > (pos + headerSize) && (lookForECS && !foundECS); arpos++) { + for (uint16_t arpos = 0; arpos < arcount && questionLen >= (pos + headerSize) && (lookForECS && !foundECS); arpos++) { if (question.at(pos) != 0) { /* not an OPT, bye. */ return; @@ -2035,12 +2036,14 @@ void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* pos += 1; const auto* drh = reinterpret_cast(&question.at(pos)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + if (ntohs(drh->d_type) == QType::OPT) { + ednsVersion = htonl(drh->d_ttl); + } pos += sizeof(dnsrecordheader); if (pos >= questionLen) { return; } - /* OPT root label (1) followed by type (2) */ if (lookForECS && ntohs(drh->d_type) == QType::OPT) { if (options == nullptr) { @@ -2228,6 +2231,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr std::string extendedErrorExtra; boost::optional rcode = boost::none; boost::optional extendedErrorCode{boost::none}; + boost::optional ednsVersion{boost::none}; uint32_t ttlCap = std::numeric_limits::max(); bool variable = false; bool followCNAMEs = false; @@ -2248,7 +2252,6 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr g_mtracer->clearAllocators(); */ #endif - // We do not have a SyncRes specific Lua context at this point yet, so ok to use t_pdl if (needECS || (t_pdl && (t_pdl->hasGettagFunc() || t_pdl->hasGettagFFIFunc())) || dnsheader->opcode == static_cast(Opcode::Notify)) { try { @@ -2257,7 +2260,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr ecsFound = false; getQNameAndSubnet(question, &qname, &qtype, &qclass, - ecsFound, &ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr); + ecsFound, &ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr, ednsVersion); qnameParsed = true; ecsParsed = true; @@ -2295,7 +2298,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.source, false, dnsheader->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta); + protobufLogQuery(luaconfsLocal, uniqueId, source, destination, mappedSource, ednssubnet.source, false, dnsheader->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId, deviceName, meta, ednsVersion); } } diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index a9b0e595cd..4c1a69114e 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -525,7 +525,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, uint16_t queryID, 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) +void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, uint16_t queryID, 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) { auto log = g_slog->withName("pblq"); @@ -563,6 +563,9 @@ void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boo msg.setMeta(mit.first, mit.second.stringVal, mit.second.intVal); } + if (ednsVersion) { + msg.setMeta("_pdnsQEDNS", {}, {*ednsVersion}); + } std::string strMsg(msg.finishAndMoveBuf()); for (auto& server : *t_protobufServers.servers) { remoteLoggerQueueData(*server, strMsg); diff --git a/pdns/recursordist/rec-main.hh b/pdns/recursordist/rec-main.hh index 08f60145e4..d5721a1ad7 100644 --- a/pdns/recursordist/rec-main.hh +++ b/pdns/recursordist/rec-main.hh @@ -592,8 +592,8 @@ bool checkOutgoingProtobufExport(LocalStateHolder& luaconfsLocal bool checkFrameStreamExport(LocalStateHolder& luaconfsLocal, const FrameStreamExportConfig& config, FrameStreamServersInfo& serverInfos); #endif void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass, - bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options); -void protobufLogQuery(LocalStateHolder& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const ComboAddress& mappedSource, const Netmask& ednssubnet, bool tcp, uint16_t queryID, 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); + 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, uint16_t queryID, 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); 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 ae0505c6ef..3c658affe5 100644 --- a/pdns/recursordist/rec-tcp.cc +++ b/pdns/recursordist/rec-tcp.cc @@ -273,11 +273,11 @@ static void handleNotify(std::unique_ptr& comboWriter, const DNS } } -static void doProtobufLogQuery(bool logQuery, LocalStateHolder& luaconfsLocal, const std::unique_ptr& comboWriter, const DNSName& qname, QType qtype, QClass qclass, const dnsheader* dnsheader, const shared_ptr& conn) +static void doProtobufLogQuery(bool logQuery, LocalStateHolder& luaconfsLocal, const std::unique_ptr& comboWriter, const DNSName& qname, QType qtype, QClass qclass, const dnsheader* dnsheader, const shared_ptr& conn, const boost::optional& ednsVersion) { 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.source, true, dnsheader->id, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta); + protobufLogQuery(luaconfsLocal, comboWriter->d_uuid, comboWriter->d_source, comboWriter->d_destination, comboWriter->d_mappedSource, comboWriter->d_ednssubnet.source, true, dnsheader->id, conn->qlen, qname, qtype, qclass, comboWriter->d_policyTags, comboWriter->d_requestorId, comboWriter->d_deviceId, comboWriter->d_deviceName, comboWriter->d_meta, ednsVersion); } } catch (const std::exception& e) { @@ -305,6 +305,7 @@ static void doProcessTCPQuestion(std::unique_ptr& comboWriter, s string deviceName; bool logQuery = false; bool qnameParsed = false; + boost::optional ednsVersion; comboWriter->d_eventTrace.setEnabled(SyncRes::s_event_trace_enabled != 0); comboWriter->d_eventTrace.add(RecEventTrace::ReqRecv); @@ -322,7 +323,7 @@ static void doProcessTCPQuestion(std::unique_ptr& comboWriter, s comboWriter->d_ecsParsed = true; comboWriter->d_ecsFound = false; getQNameAndSubnet(conn->data, &qname, &qtype, &qclass, - comboWriter->d_ecsFound, &comboWriter->d_ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr); + comboWriter->d_ecsFound, &comboWriter->d_ednssubnet, g_gettagNeedsEDNSOptions ? &ednsOptions : nullptr, ednsVersion); qnameParsed = true; if (t_pdl) { @@ -376,7 +377,7 @@ static void doProcessTCPQuestion(std::unique_ptr& comboWriter, s } if (t_protobufServers.servers) { - doProtobufLogQuery(logQuery, luaconfsLocal, comboWriter, qname, qtype, qclass, dnsheader, conn); + doProtobufLogQuery(logQuery, luaconfsLocal, comboWriter, qname, qtype, qclass, dnsheader, conn, ednsVersion); } if (t_pdl) {